diff options
| -rw-r--r-- | NEWS | 8 | ||||
| -rw-r--r-- | README | 73 | ||||
| -rw-r--r-- | filegraph.dot | 7 | ||||
| -rw-r--r-- | luaotfload-auxiliary.lua | 66 | ||||
| -rw-r--r-- | luaotfload-colors.lua | 348 | ||||
| -rw-r--r-- | luaotfload-database.lua | 65 | ||||
| -rw-r--r-- | luaotfload-features.lua | 287 | ||||
| -rw-r--r-- | luaotfload-loaders.lua | 8 | ||||
| -rw-r--r-- | luaotfload-override.lua | 14 | ||||
| -rwxr-xr-x | luaotfload-tool.lua | 31 | ||||
| -rw-r--r-- | luaotfload.dtx | 107 | ||||
| -rwxr-xr-x | mkglyphlist | 10 | ||||
| -rw-r--r-- | tests/systemfonts.tex | 2 | 
13 files changed, 570 insertions, 456 deletions
| @@ -2,6 +2,8 @@ Change History  --------------  2013/04/xx, luaotfload v2.2: +    * There is now a central, non-personal dev repo on github: +      https://github.com/lualatex/luaotfload      * Synchronisation with ConTeXt from TeXLive 2013, inducing        backward-incompatible changes in the font structure (fontspec and         unicode-math must be updated) @@ -10,7 +12,7 @@ Change History        the LuaTeX-Plain format)      * Improved and extended documentation      * Font filenames are stored in the database (file: lookups more efficient) -    * Optional caching of name: lookups +    * Optional caching of name: lookups (uses separate cache file)      * Increased fidelity of XeTeX emulation      * Renaming mkluatexfontdb into luaotfload-tool (the old behavior is kept if        the script is symlinked/ renamed mkluatexfontdb) @@ -21,8 +23,8 @@ Change History      * The Adobe Glyph List (font-age.lua) is now built via script (mkglyphlist)      * Hans adapted the font loader to several of our requests (attribute        allocation, custom merged package name etc.) -    * There is now a central, non-personal dev repo on github: -      https://github.com/lualatex/luaotfload +    * Auxiliary functions for package authors +    * Fallbacks for older versions of dependent packages  2013/04/27, luaotfload v1.3:      *  blacklisting lingoes.ttf (segfaults) @@ -1,42 +1,46 @@ -                         The luaotfload package - -Luaotfload is an adaptation of the ConTeXt font loading system for Plain and -LaTeX. It allows OpenType fonts to be loaded with OpenType features accessible -through the XeTeX font syntax. - -It 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 +******************************************************************************* +                            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 on <http://github.com/khaledhosny/luaotfload>. -Please report bugs at the Github address above. +This package is developed by the LuaLaTeX dev team on +<http://github.com/lualatex/luaotfload>. Please report bugs to the issue +tracker there. -Discussion of development for LuaLaTeX is held in the lualatex-dev mailing -list. See <http://www.tug.org/mailman/listinfo/lualatex-dev> to join or to -view the archives. +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@eglug.org>  Elie Roux                <elie.roux@telecom-bretagne.eu>  Will Robertson           <will.robertson@latex-project.org> - +Philipp Gesang           <philipp.gesang@alumni.uni-heidelberg.de>  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. +   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. @@ -50,22 +54,27 @@ Alternatively, try your (TeX or Linux) distribution's package management system.  4. Try to figure it out by looking at the Makefile and comments in the sources.  License -------- +------------------------------------------------------------------------------- + +The luaotfload bundle, as a derived work of ConTeXt, is distributed under the +GNU GPLv2 license: -The luaotfload bundle 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. -It may be located within the documentation luaotfload.pdf. -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; either version 2 -of the License, or (at your option) any later version. +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. +        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. +        See headers of each source file for copyright details. diff --git a/filegraph.dot b/filegraph.dot index d69937b..36e5764 100644 --- a/filegraph.dot +++ b/filegraph.dot @@ -139,9 +139,10 @@ strict digraph luaotfload_files { //looks weird with circo ...          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-lib-dir.lua</td>  <td>luaotfload-features.lua</td> </tr> -                <tr> <td>luaotfload-override.lua</td> <td>luaotfload-loaders.lua</td>  </tr> -                <tr> <td>luaotfload-database.lua</td> <td>luaotfload-color.lua</td>    </tr> +                <tr> <td>luaotfload-lib-dir.lua</td>   <td>luaotfload-features.lua</td> </tr> +                <tr> <td>luaotfload-override.lua</td>  <td>luaotfload-loaders.lua</td>  </tr> +                <tr> <td>luaotfload-database.lua</td>  <td>luaotfload-color.lua</td>    </tr> +                <tr> <td>luaotfload-auxiliary.lua</td>                                  </tr>              </table>          >,      ] diff --git a/luaotfload-auxiliary.lua b/luaotfload-auxiliary.lua index 844c170..5de964d 100644 --- a/luaotfload-auxiliary.lua +++ b/luaotfload-auxiliary.lua @@ -4,7 +4,7 @@  --  DESCRIPTION:  part of luaotfload  -- REQUIREMENTS:  luaotfload 2.2  --       AUTHOR:  Khaled Hosny, Élie Roux, Philipp Gesang ---      VERSION:  1.0 +--      VERSION:  2.2  --      CREATED:  2013-05-01 14:40:50+0200  -----------------------------------------------------------------------  -- @@ -36,6 +36,69 @@ local stringbyte    = string.byte  -----------------------------------------------------------------------  --[[doc-- + +The font object (tfmdata) structure has changed since version 1.x, so +in case other packages haven’t been updated we put fallbacks in place +where they’d expect them. Specifically we have in mind: + +  · fontspec +  · unicode-math +  · microtype (most likely fixed till TL2013) + +--doc]]-- + +--- fontobj -> fontobj +local add_fontdata_fallbacks = function (fontdata) +  if type(fontdata) == "table" then +    local fontparameters = fontdata.parameters +    local metadata +    if not fontdata.shared then --- that would be a tfm +      --- we can’t really catch everything that +      --- goes wrong; for some reason, fontspec.lua +      --- just assumes it always gets an otf object, +      --- so its capheight callback, which does not +      --- bother to do any checks, will access +      --- fontdata.shared no matter what ... +      fontdata.units = fontdata.units_per_em +    else --- otf +      metadata = fontdata.shared.rawdata.metadata +      fontdata.units   = fontparameters.units +      local resources  = fontdata.resources +      fontdata.size    = fontparameters.size +      --- for legacy fontspec.lua and unicode-math.lua +      fontdata.shared.otfdata          = metadata +      fontdata.shared.otfdata.metadata = metadata --- brr, that’s meta indeed +      --- for microtype.lua +      fontdata.shared.otfdata.luatex = { +        unicodes = resources.unicodes, +        features = resources.features, +      } +    end +  end +  return fontdata +end + +luatexbase.add_to_callback( +  "luaotfload.patch_font", +  add_fontdata_fallbacks, +  "luaotfload.fontdata_fallbacks") + +--[[doc-- + +Additionally, the font registry is expected at fonts.identifiers +(fontspec) or fonts.ids (microtype), but in the meantime it has been +migrated to fonts.hashes.identifiers.  We’ll make luaotfload satisfy +those assumptions. (Maybe it’d be more appropriate to use +font.getfont() since Hans made it a harmless wrapper [1].) + +[1] http://www.ntg.nl/pipermail/ntg-context/2013/072166.html + +--doc]]-- + +fonts.identifiers = fonts.hashes.identifiers +fonts.ids         = fonts.hashes.identifiers + +--[[doc--  This sets two dimensions apparently relied upon by the unicode-math  package.  --doc]]-- @@ -71,6 +134,7 @@ end  --[[doc--  This callback corrects some values of the Cambria font.  --doc]]-- +--- fontobj -> unit  local patch_cambria_domh = function (fontdata)    local mathconstants = fontdata.MathConstants    if mathconstants and fontdata.psname == "CambriaMath" then diff --git a/luaotfload-colors.lua b/luaotfload-colors.lua index 3d8bfab..ec076c2 100644 --- a/luaotfload-colors.lua +++ b/luaotfload-colors.lua @@ -1,44 +1,110 @@  if not modules then modules = { } end modules ['luaotfload-colors'] = { -    version   = 1.001, +    version   = 2.200,      comment   = "companion to luaotfload.lua (font color)", -    author    = "Khaled Hosny and Elie Roux", +    author    = "Khaled Hosny, Elie Roux, Philipp Gesang",      copyright = "Luaotfload Development Team", -    license   = "GPL" +    license   = "GNU GPL v2"  } -local newnode            = node.new -local nodetype           = node.id -local traverse_nodes     = node.traverse -local insert_node_before = node.insert_before -local insert_node_after  = node.insert_after +--[[doc-- +buggy coloring with the pre_output_filter when expansion is enabled +    · tfmdata for different expansion values is split over different objects +    · in ``initializeexpansion()``, chr.expansion_factor is set, and only +      those characters that have it are affected +    · in constructors.scale: chr.expansion_factor = ve*1000 if commented out +      makes the bug vanish +--doc]]-- -local stringformat = string.format -local stringgsub   = string.gsub -local stringfind   = string.find -local otffeatures        = fonts.constructors.newfeatures("otf") -local ids                = fonts.hashes.identifiers -local registerotffeature = otffeatures.register +local color_callback = config.luaotfload.color_callback +if not color_callback then +    --- maybe this would be better as a method: "early" | "late" +    color_callback = "pre_linebreak_filter" +--  color_callback = "pre_output_filter" --- old behavior, breaks expansion +end -local function setcolor(tfmdata,value) -    local sanitized -    local properties = tfmdata.properties -    if value then -        value = tostring(value) -        if #value == 6 or #value == 8 then -            sanitized = value -        elseif #value == 7 then -            _, _, sanitized = stringfind(value, "(......)") -        elseif #value > 8 then -            _, _, sanitized = stringfind(value, "(........)") -        else -            -- broken color code ignored, issue a warning? -        end +local newnode               = node.new +local nodetype              = node.id +local traverse_nodes        = node.traverse +local insert_node_before    = node.insert_before +local insert_node_after     = node.insert_after + +local stringformat          = string.format +local stringgsub            = string.gsub +local stringfind            = string.find +local stringsub             = string.sub + +local otffeatures           = fonts.constructors.newfeatures("otf") +local identifiers           = fonts.hashes.identifiers +local registerotffeature    = otffeatures.register + +local add_color_callback --[[ this used to be a global‽ ]] + +--[[doc-- +This converts a single octet into a decimal with three digits of +precision. The optional second argument limits precision to a single +digit. +--doc]]-- + +--- string -> bool? -> string +local hex_to_dec = function (hex,one) --- one isn’t actually used anywhere ... +    if one then +        return stringformat("%.1g", tonumber(hex, 16)/255) +    else +        return stringformat("%.3g", tonumber(hex, 16)/255)      end +end + +--[[doc-- +Color string validator / parser. +--doc]]-- + +local lpeg           = require"lpeg" +local lpegmatch      = lpeg.match +local C, Cg, Ct, P, R, S = lpeg.C, lpeg.Cg, lpeg.Ct, lpeg.P, lpeg.R, lpeg.S + +local digit16        = R("09", "af", "AF") +local octet          = C(digit16 * digit16) + +local p_rgb          = octet * octet * octet +local p_rgba         = p_rgb * octet +local valid_digits   = C(p_rgba + p_rgb) -- matches eight or six hex digits + +local p_Crgb         = Cg(octet/hex_to_dec, "red") --- for captures +                     * Cg(octet/hex_to_dec, "green") +                     * Cg(octet/hex_to_dec, "blue") +local p_Crgba        = p_Crgb * Cg(octet/hex_to_dec, "alpha") +local extract_color  = Ct(p_Crgba + p_Crgb) + +--- string -> (string | nil) +local sanitize_color_expression = function (digits) +    digits = tostring(digits) +    local sanitized = lpegmatch(valid_digits, digits) +    if not sanitized then +        luaotfload.warning( +            "“%s” is not a valid rgb[a] color expression", digits) +        return nil +    end +    return sanitized +end + +--[[doc-- +``setcolor`` modifies tfmdata.properties.color in place +--doc]]-- + +--- fontobj -> string -> unit +--- +---         (where “string” is a rgb value as three octet +---         hexadecimal, with an optional fourth transparency +---         value) +--- +local setcolor = function (tfmdata, value) +    local sanitized  = sanitize_color_expression(value) +    local properties = tfmdata.properties      if sanitized then -        tfmdata.properties.color = sanitized +        properties.color = sanitized          add_color_callback()      end  end @@ -52,133 +118,187 @@ registerotffeature {      }  } -local function hex2dec(hex,one) -    if one then -        return stringformat("%.1g", tonumber(hex, 16)/255) -    else -        return stringformat("%.3g", tonumber(hex, 16)/255) -    end -end -local res +--- something is carried around in ``res`` +--- for later use by color_handler() --- but what? + +local res --- <- state of what? -local function pageresources(a) +--- float -> unit +local function pageresources(alpha)      local res2      if not res then         res = "/TransGs1<</ca 1/CA 1>>"      end -    res2 = stringformat("/TransGs%s<</ca %s/CA %s>>", a, a, a) -    res  = stringformat("%s%s", res, stringfind(res, res2) and "" or res2) +    res2 = stringformat("/TransGs%s<</ca %s/CA %s>>", +                        alpha, alpha, alpha) +    res  = stringformat("%s%s", +                        res, +                        stringfind(res, res2) and "" or res2)  end -local function hex_to_rgba(hex) -    local r, g, b, a, push, pop, res3 -    if hex then -        if #hex == 6 then -            _, _, r, g, b    = stringfind(hex, '(..)(..)(..)') -        elseif #hex == 8 then -            _, _, r, g, b, a = stringfind(hex, '(..)(..)(..)(..)') -            a                = hex2dec(a,true) -            pageresources(a) -        end -    else -        return nil +--- we store results of below color handler as tuples of +--- push/pop strings +local color_cache = { } --- (string, (string * string)) hash_t + +--- string -> (string * string) +local hex_to_rgba = function (digits) +    if not digits then +        return      end -    r = hex2dec(r) -    g = hex2dec(g) -    b = hex2dec(b) -    if a then -        push = stringformat('/TransGs%g gs %s %s %s rg', a, r, g, b) -        pop  = '0 g /TransGs1 gs' -    else -        push = stringformat('%s %s %s rg', r, g, b) -        pop  = '0 g' + +    --- this is called like a thousand times, so some +    --- memoizing is in order. +    local cached = color_cache[digits] +    if not cached then +        local push, pop +        local rgb = lpegmatch(extract_color, digits) +        if rgb.alpha then +            pageresources(rgb.alpha) +            push = stringformat( +                        "/TransGs%g gs %s %s %s rg", +                        rgb.alpha, +                        rgb.red, +                        rgb.green, +                        rgb.blue) +            pop  = "0 g /TransGs1 gs" +        else +            push = stringformat( +                        "%s %s %s rg", +                        rgb.red, +                        rgb.green, +                        rgb.blue) +            pop  = "0 g" +        end +        color_cache[digits] = { push, pop } +        return push, pop      end -    return push, pop + +    return cached[1], cached[2]  end -local glyph   = nodetype('glyph') -local hlist   = nodetype('hlist') -local vlist   = nodetype('vlist') -local whatsit = nodetype('whatsit') -local pgi     = nodetype('page_insert') -local sbox    = nodetype('sub_box') +--- Luatex internal types + +local glyph_t           = nodetype("glyph") +local hlist_t           = nodetype("hlist") +local vlist_t           = nodetype("vlist") +local whatsit_t         = nodetype("whatsit") +local page_insert_t     = nodetype("page_insert") +local sub_box_t         = nodetype("sub_box") -local function lookup_next_color(head) +--- node -> nil | -1 | color‽ +local lookup_next_color +lookup_next_color = function (head) --- paragraph material      for n in traverse_nodes(head) do -        if n.id == glyph then -            if ids[n.font] and ids[n.font].properties and ids[n.font].properties.color then -                return ids[n.font].properties.color +        local n_id = n.id + +        if n_id == glyph_t then +            local n_font +            if  identifiers[n_font] +            and identifiers[n_font].properties +            and identifiers[n_font].properties.color +            then +                return identifiers[n.font].properties.color              else                  return -1              end -        elseif n.id == vlist or n.id == hlist or n.id == sbox then + +        elseif n_id == vlist_t or n_id == hlist_t or n_id == sub_box_t then              local r = lookup_next_color(n.list) -            if r == -1 then -                return -1 -            elseif r then +            if r then                  return r              end -        elseif n.id == whatsit or n.id == pgi then + +        elseif n_id == whatsit_t or n_id == page_insert_t then              return -1          end      end      return nil  end -local function node_colorize(head, current_color, next_color) +--[[doc-- +While the second argument and second returned value are apparently +always nil when the function is called, they temporarily take string +values during the node list traversal. +--doc]]-- + +local cnt = 0 +--- node -> string -> int -> (node * string) +local node_colorize +node_colorize = function (head, current_color, next_color)      for n in traverse_nodes(head) do -        if n.id == hlist or n.id == vlist or n.id == sbox then -            local next_color_in = lookup_next_color(n.next) or next_color +        local n_id      = n.id +        local nextnode  = n.next + +        if n_id == hlist_t or n_id == vlist_t or n_id == sub_box_t then +            local next_color_in = lookup_next_color(nextnode) or next_color              n.list, current_color = node_colorize(n.list, current_color, next_color_in) -        elseif n.id == glyph then -            local tfmdata = ids[n.font] + +        elseif n_id == glyph_t then +            cnt = cnt + 1 +            local tfmdata = identifiers[n.font] + +            --- colorization is restricted to those fonts +            --- that received the “color” property upon +            --- loading (see ``setcolor()`` above)              if tfmdata and tfmdata.properties  and tfmdata.properties.color then -                if tfmdata.properties.color ~= current_color then -                    local pushcolor = hex_to_rgba(tfmdata.properties.color) -                    local push = newnode(whatsit, 8) -                    push.mode  = 1 -                    push.data  = pushcolor -                    head       = insert_node_before(head, n, push) -                    current_color = tfmdata.properties.color +                local font_color = tfmdata.properties.color +--                luaotfload.info( +--                    "n: %d; %s; %d %s, %s", +--                    cnt, utf.char(n.char), n.font, "<TRUE>", font_color) +                if font_color ~= current_color then +                    local pushcolor = hex_to_rgba(font_color) +                    local push      = newnode(whatsit_t, 8) +                    push.mode       = 1 +                    push.data       = pushcolor +                    head            = insert_node_before(head, n, push) +                    current_color   = font_color                  end -                local next_color_in = lookup_next_color (n.next) or next_color -                if next_color_in ~= tfmdata.properties.color then -                    local _, popcolor = hex_to_rgba(tfmdata.properties.color) -                    local pop  = newnode(whatsit, 8) -                    pop.mode   = 1 -                    pop.data   = popcolor -                    head       = insert_node_after(head, n, pop) -                    current_color = nil +                local next_color_in = lookup_next_color (nextnode) or next_color +                if next_color_in ~= font_color then +                    local _, popcolor = hex_to_rgba(font_color) +                    local pop         = newnode(whatsit_t, 8) +                    pop.mode          = 1 +                    pop.data          = popcolor +                    head              = insert_node_after(head, n, pop) +                    current_color     = nil                  end + +--            else +--                luaotfload.info( +--                    "n: %d; %s; %d %s", +--                    cnt, utf.char(n.char), n.font, "<FALSE>")              end          end      end      return head, current_color  end -local function font_colorize(head) -   -- check if our page resources existed in the previous run -   -- and remove it to avoid duplicating it later -   if res then -      local r = "/ExtGState<<"..res..">>" -      tex.pdfpageresources = stringgsub(tex.pdfpageresources, r, "") -   end -   local h = node_colorize(head, nil, nil) -   -- now append our page resources -   if res and stringfind(res, "%S") then -- test for non-empty string -      local r = "/ExtGState<<"..res..">>" -      tex.pdfpageresources = tex.pdfpageresources..r -   end -   return h +--- node -> node +local color_handler = function (head) +    -- check if our page resources existed in the previous run +    -- and remove it to avoid duplicating it later +    if res then +        local r = "/ExtGState<<" .. res .. ">>" +        tex.pdfpageresources = stringgsub(tex.pdfpageresources, r, "") +    end +    local new_head = node_colorize(head, nil, nil) +    -- now append our page resources +    if res and stringfind(res, "%S") then -- test for non-empty string +        local r = "/ExtGState<<" .. res .. ">>" +        tex.pdfpageresources = tex.pdfpageresources..r +    end +    return new_head  end  local color_callback_activated = 0 -function add_color_callback() +--- unit -> unit +add_color_callback = function ( )      if color_callback_activated == 0 then -        luatexbase.add_to_callback( -          "pre_output_filter", font_colorize, "luaotfload.colorize") +        luatexbase.add_to_callback(color_callback, +                                   color_handler, +                                   "luaotfload.color_handler")          color_callback_activated = 1      end  end diff --git a/luaotfload-database.lua b/luaotfload-database.lua index aaba55a..576341f 100644 --- a/luaotfload-database.lua +++ b/luaotfload-database.lua @@ -1,7 +1,7 @@  if not modules then modules = { } end modules ['luaotfload-database'] = {      version   = 2.2,      comment   = "companion to luaotfload.lua", -    author    = "Khaled Hosny and Elie Roux", +    author    = "Khaled Hosny, Elie Roux, Philipp Gesang",      copyright = "Luaotfload Development Team",      license   = "GNU GPL v2"  } @@ -98,7 +98,7 @@ local writable_path  if caches then      writable_path = caches.getwritablepath("names","")      if not writable_path then -        error("Impossible to find a suitable writeable cache...") +        luaotfload.error("Impossible to find a suitable writeable cache...")      end      names.path.dir          = writable_path      names.path.path         = filejoin(writable_path, names.path.basename) @@ -116,6 +116,7 @@ Auxiliary functions  local report = logs.names_report +--- string -> string  local sanitize_string = function (str)      if str ~= nil then          return utf8gsub(utf8lower(str), "[^%a%d]", "") @@ -133,11 +134,10 @@ This is a sketch of the luaotfload db:          // preliminary additions of v2.2:          basenames       : (string, int) hash;    // where int is the index in mappings          barenames       : (string, int) hash;    // where int is the index in mappings -        request_cache   : lookup_cache;          // see below      }      and fontentry = {          familyname  : string; -        filename    : (string * bool); +        filename    : (string * int);            // int: subfont          fontname    : string;          fullname    : string;          names       : { @@ -188,21 +188,15 @@ mtx-fonts has in names.tma:          width         : string;      } -  --doc]]--  local fontnames_init = function (keep_cache) --- returns dbobj      return {          mappings        = { },          status          = { }, -        --- adding filename mapping increases the -        --- size of the serialized db on my system -        --- (5840 font files) by a factor of 1.09 -        --- if we store only the indices in the -        --- mappings table          barenames       = { },          basenames       = { }, ---      fullnames       = { }, +--      fullnames       = { }, // -> status          version         = names.version,      }  end @@ -261,18 +255,21 @@ local update_names  local fonts_loaded   = false  local fonts_reloaded = false +--- limit output when approximate font matching (luaotfload-tool -F) +local fuzzy_limit = 1 --- display closest only +  --- unit -> dbobj  load_names = function ( )      local starttime = os.gettimeofday()      local foundname, data = load_lua_file(names.path.path)      if data then -        report("info", 1, "db", +        report("both", 2, "db",              "Font names database loaded", "%s", foundname)          report("info", 3, "db", "Loading took %0.f ms",                                  1000*(os.gettimeofday()-starttime))      else -        report("info", 1, "db", +        report("both", 0, "db",              [[Font names database not found, generating new one.               This can take several minutes; please be patient.]])          data = update_names(fontnames_init(false)) @@ -286,7 +283,7 @@ end  load_lookups = function ( )      local foundname, data = load_lua_file(names.path.lookup_path)      if data then -        report("both", 1, "cache", +        report("both", 3, "cache",                 "Lookup cache loaded (%s)", foundname)      else          report("both", 1, "cache", @@ -296,8 +293,6 @@ load_lookups = function ( )      return data  end -local fuzzy_limit = 1 --- display closest only -  local style_synonyms = { set = { } }  do      style_synonyms.list = { @@ -382,25 +377,20 @@ Even if we find a matching font eventually, the next time the  user compiles Eir document E will have to stand through the delay  again.  Thus, some caching of results -- even between runs -- is in order. -We’ll just store successful lookups in the database in a record of -the respective lookup type. +We’ll just store successful name: lookups in a separate cache file.  type lookup_cache = (string, (string * num)) dict -TODO: +Complete, needs testing:   ×  1) add cache to dbobj   ×  2) wrap lookups in cached versions   ×  3) make caching optional (via the config table) for debugging   ×  4) make names_update() cache aware (nil if “force”)   ×  5) add logging   ×  6) add cache control to luaotfload-tool - ×  7) incr db version -    8) wishlist: save cache only at the end of a run -    9) ??? -    n) PROFIT!!! + ×  7) incr db version (now 2.203) + ×  8) save cache only at the end of a run -The name lookup requires both the “name” and some other -keys, so we’ll concatenate them.  The spec is modified in place (ugh), so we’ll have to catalogue what  fields actually influence its behavior. @@ -415,20 +405,11 @@ Idk what the “spec” resolver is for.  * name: contains both the name resolver from luatex-fonts and resolve()    below -The following fields of a resolved spec need to be cached: ---doc]]-- -local cache_fields = { -    "forced", "hash", "lookup", "name", "resolved", "sub", -} - ---[[doc--  From my reading of font-def.lua, what a resolver does is  basically rewrite the “name” field of the specification record  with the resolution.  Also, the fields “resolved”, “sub”, “force” etc. influence the outcome. -We’ll just cache a deep copy of the entire spec as it leaves the -resolver, lest we want to worry if we caught all the details.  --doc]]--  --- 'a -> 'a -> table -> (string * int|boolean * boolean) @@ -458,12 +439,8 @@ resolve_cached = function (_, _, specification)      names.lookups[request] = entry      --- obviously, the updated cache needs to be stored. -    --- for the moment, we write the entire db to disk -    --- whenever the cache is updated.      --- TODO this should trigger a save only once the      ---      document is compiled (finish_pdffile callback?) -    --- TODO we should speed up writing by separating -    ---      the cache from the db      report("both", 5, "cache", "saving updated cache")      save_lookups()      return filename, subfont, true @@ -681,15 +658,12 @@ resolve = function (_,_,specification) -- the 1st two parameters are used by Con      if not fonts_reloaded then          --- last straw: try reloading the database          return reload_db( -            "unresolved font name: “" .. name .. "”", +            "unresolved font name: ‘" .. name .. "’",              resolve, nil, nil, specification          )      end      --- else, fallback to requested name -    --- specification.name is empty with absolute paths, looks -    --- like a bug in the specification parser <TODO< is it still -    --- relevant? looks not...      return specification.name, false, false  end --- resolve() @@ -1491,7 +1465,7 @@ save_lookups = function ( )              if lucname and type(caches.compile) == "function" then                  os.remove(lucname)                  caches.compile(lookups, luaname, lucname) -                report("info", 1, "cache", "Lookup cache saved") +                report("both", 3, "cache", "Lookup cache saved")                  return names.path.lookup_path              end          end @@ -1518,7 +1492,7 @@ save_names = function (fontnames)              end          end      end -    report("info", 0, "db", "Failed to save names database") +    report("both", 0, "db", "Failed to save names database")      return nil  end @@ -1537,6 +1511,7 @@ end  --- export functionality to the namespace “fonts.names”  names.flush_cache                 = flush_cache +names.save_lookups                = save_lookups  names.load                        = load_names  names.save                        = save_names  names.scan                        = scan_external_dir @@ -1546,7 +1521,7 @@ names.crude_file_lookup_verbose   = crude_file_lookup_verbose  --- replace the resolver from luatex-fonts  if config.luaotfload.resolver == "cached" then -    report("info", 0, "cache", "caching of name: lookups active") +    report("both", 2, "cache", "caching of name: lookups active")      names.resolve     = resolve_cached      names.resolvespec = resolve_cached  else diff --git a/luaotfload-features.lua b/luaotfload-features.lua index 494d02d..f91aee7 100644 --- a/luaotfload-features.lua +++ b/luaotfload-features.lua @@ -1,26 +1,28 @@  if not modules then modules = { } end modules ["features"] = { -    version   = 1.000, +    version   = 2.200,      comment   = "companion to luaotfload.lua", -    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL", +    author    = "Hans Hagen, Khaled Hosny, Elie Roux, Philipp Gesang",      copyright = "PRAGMA ADE / ConTeXt Development Team",      license   = "see context related readme files"  } -local format, insert = string.format, table.insert -local type, next = type, next -local lpegmatch = lpeg.match +local format, insert    = string.format, table.insert +local type, next        = type, next +local lpegmatch         = lpeg.match  ---[[ begin included font-ltx.lua ]]  --- this appears to be based in part on luatex-fonts-def.lua  local fonts = fonts --- A bit of tuning for definitions. +--HH A bit of tuning for definitions.  fonts.constructors.namemode = "specification" -- somehow latex needs this (changed name!) => will change into an overload --- tricky: we sort of bypass the parser and directly feed all into --- the sub parser +--[[HH-- +    tricky: we sort of bypass the parser and directly feed all into +    the sub parser +--HH]]--  function fonts.definers.getspecification(str)      return "", str, "", ":", str @@ -31,53 +33,9 @@ local old_feature_list = { }  local report = logs.names_report  local stringlower      = string.lower -local stringsub        = string.sub  local stringgsub       = string.gsub -local stringfind       = string.find -local stringexplode    = string.explode  local stringis_empty   = string.is_empty ---[[doc-- -Apparently, these “modifiers” are another measure of emulating \XETEX, -cf. “About \XETEX”, by Jonathan Kew, 2005; and -    “The \XETEX Reference Guide”, by Will Robertson, 2011. ---doc]]-- - -local supported = { -    b    = "bold", -    i    = "italic", -    bi   = "bolditalic", -    aat  = false, -    icu  = false, -    gr   = false, -} - ---- this parses the optional flags after the slash ---- the original behavior is that multiple slashes ---- are valid but they might cancel prior settings ---- example: {name:Antykwa Torunska/I/B} -> bold - -local isstyle = function (request) -    request = stringlower(request) -    request = stringexplode(request, "/") - -    for _,v in next, request do -        local stylename = supported[v] -        if stylename then -            old_feature_list.style = stylename -        elseif stringfind(v, "^s=") then -            --- after all, we want everything after the second byte ... -            local val = stringsub(v, 3) -            old_feature_list.optsize = val -        elseif stylename == false then -            report("log", 0, -                "load", "unsupported font option: %s", v) -        elseif not stringis_empty(v) then -            old_feature_list.style = stringgsub(v, "[^%a%d]", "") -        end -    end -end -  --- TODO an option to dump the default features for a script would make  ---      a nice addition to luaotfload-tool @@ -135,13 +93,36 @@ defaults.tibt = defaults.khmr  defaults.lao  = defaults.thai  --[[doc-- -Which features are active by default depends on the script requested. + +    As discussed, we will issue a warning because of incomplete support +    when one of the scripts below is requested. + +    Reference: https://github.com/lualatex/luaotfload/issues/31 + +--doc]]-- + +local support_incomplete = table.tohash({ +    "deva", "beng", "guru", "gujr", +    "orya", "taml", "telu", "knda", +    "mlym", "sinh", +}, true) + +--[[doc-- + +    Which features are active by default depends on the script +    requested. +  --doc]]--  --- (string, string) dict -> (string, string) dict  local set_default_features = function (speclist)      speclist = speclist or { }      local script = speclist.script or "dflt" +    if support_incomplete[script] then +        report("log", 0, "load", +            "support for the requested script: “%s” may be incomplete", +            script) +    end      report("log", 0, "load",          "auto-selecting default features for script: %s", @@ -169,84 +150,6 @@ local set_default_features = function (speclist)      return speclist  end --- --[==[obsolete-- -local function issome ()    old_feature_list.lookup = 'name' end -local function isfile ()    old_feature_list.lookup = 'file' end -local function isname ()    old_feature_list.lookup = 'name' end -local function thename(s)   old_feature_list.name   = s end -local function issub  (v)   old_feature_list.sub    = v end -local function istrue (s)   old_feature_list[s]     = true end -local function isfalse(s)   old_feature_list[s]     = false end -local function iskey  (k,v) old_feature_list[k]     = v end - -local P, S, R, C = lpeg.P, lpeg.S, lpeg.R, lpeg.C - -local spaces     = P(" ")^0 ---local namespec   = (1-S("/:("))^0 -- was: (1-S("/: ("))^0 ---[[phg-- this prevents matching of absolute paths as file names --]]-- -local namespec   = (1-S("/:("))^1 -local filespec   = (R("az", "AZ") * P(":"))^-1 * (1-S(":("))^1 -local stylespec  = spaces * P("/") * (((1-P(":"))^0)/isstyle) * spaces -local filename   = (P("file:")/isfile * (filespec/thename)) -                 + (P("[") * P(true)/isname * (((1-P("]"))^0)/thename) * P("]")) -local fontname   = (P("name:")/isname * (namespec/thename)) + P(true)/issome * (namespec/thename) -local sometext   = (R("az","AZ","09") + S("+-.,"))^1 -local truevalue  = P("+") * spaces * (sometext/istrue) -local falsevalue = P("-") * spaces * (sometext/isfalse) -local keyvalue   = P("+") + (C(sometext) * spaces * P("=") * spaces * C(sometext))/iskey -local somevalue  = sometext/istrue -local subvalue   = P("(") * (C(P(1-S("()"))^1)/issub) * P(")") -- for Kim -local option     = spaces * (keyvalue + falsevalue + truevalue + somevalue) * spaces -local options    = P(":") * spaces * (P(";")^0  * option)^0 -local oldsyntax  = (filename + fontname) * subvalue^0 * stylespec^0 * options^0 - ---- to be annihilated -local function old_behavior (specification) -- xetex mode -    old_feature_list = { } -    lpeg.match(oldsyntax,specification.specification) -    old_feature_list = set_default_features(old_feature_list) -    if old_feature_list.style then -        specification.style = old_feature_list.style -        old_feature_list.style = nil -    end -    if old_feature_list.optsize then -        specification.optsize = old_feature_list.optsize -        old_feature_list.optsize = nil -    end -    if old_feature_list.name then -        if resolvers.findfile(old_feature_list.name, "tfm") then -            old_feature_list.lookup = "file" -            old_feature_list.name   = file.addsuffix(old_feature_list.name, "tfm") -        elseif resolvers.findfile(old_feature_list.name, "ofm") then -            old_feature_list.lookup = "file" -            old_feature_list.name   = file.addsuffix(old_feature_list.name, "ofm") -        end - -        specification.name = old_feature_list.name -        old_feature_list.name = nil -    end -    --- this test overwrites valid file: requests for xetex bracket -    --- syntax -    if old_feature_list.lookup then -        specification.lookup = old_feature_list.lookup -        old_feature_list.lookup = nil -    end -    if old_feature_list.sub then -        specification.sub = old_feature_list.sub -        old_feature_list.sub = nil -    end -    if not old_feature_list.mode then -        -- if no mode is set, use our default -        old_feature_list.mode = fonts.mode -    end -    specification.features.normal = fonts.handlers.otf.features.normalize(old_feature_list) -    return specification -end - ---fonts.definers.registersplit(":",old_behavior,"cryptic") ---fonts.definers.registersplit("", old_behavior,"more cryptic") -- catches \font\text=[names] ---obsolete]==]-- -  -----------------------------------------------------------------------  ---                    request syntax parser 2.2  ----------------------------------------------------------------------- @@ -282,37 +185,28 @@ end  ---     according to my reconstruction, the correct chaining  ---     of the lookups for each category is as follows:  --- ----     | File -> ( db/filename lookup; ----                 db/basename lookup; ----                 kpse.find_file() ) ----     | Name -> ( names.resolve() ) ----     | Path -> ( db/filename lookup; ----                 db/basename lookup; ----                 kpse.find_file(); ----                 fullpath lookup ) ----     | Anon -> ( names.resolve();      (* most general *) ----                 db/filename lookup; ----                 db/basename lookup; ----                 kpse.find_file(); ----                 fullpath lookup ) +---     | File -> ( db/filename lookup )  --- ----     the database should be generated only if the chain has ----     been completed, and then only once. +---     | Name -> ( db/name lookup, +---                 db/filename lookup )  --- ----     caching of successful lookups is essential. we need ----     an additional subtable "cached" in the database. it ----     should be nil’able by issuing luaotfload-tool --flush or ----     something. if a cache miss is followed by a successful ----     lookup, then it will be counted as new addition to the ----     cache. we also need a config option to ignore caching. +---     | Path -> ( db/filename lookup, +---                 fullpath lookup )  --- ----     also everything has to be finished by tomorrow at noon. +---     | Anon -> ( kpse.find_file(),     // <- for tfm, ofm +---                 db/name lookup, +---                 db/filename lookup, +---                 fullpath lookup ) +--- +---     caching of successful lookups is essential. we now +---     as of v2.2 have an experimental lookup cache that is +---     stored in a separate file. it pertains only to name: +---     lookups, and is described in more detail in +---     luaotfload-database.lua.  ---  ----------------------------------------------------------------------- -local stringlower = string.lower -  local toboolean = function (s)    if s == "true"  then return true  end    if s == "false" then return false end @@ -348,17 +242,19 @@ local decimal     = digit^1 * (dot * digit^0)^-1      The slash notation: called “modifiers” (Kew) or “font options”      (Robertson, Goosens)      we only support the shorthands for italic / bold / bold italic -    shapes, the rest is ignored. +    shapes, as well as setting optical size, the rest is ignored.  --doc]]--  local style_modifier    = (P"BI" + P"IB" + P"bi" + P"ib" + S"biBI")                          / stringlower -local other_modifier    = P"S=" * decimal --- optical size; unsupported -                        + P"AAT" + P"aat" --- apple stuff;  unsupported +local size_modifier     = S"Ss" * P"="    --- optical size +                        * Cc"optsize" * C(decimal) +local other_modifier    = P"AAT" + P"aat" --- apple stuff;  unsupported                          + P"ICU" + P"icu" --- not applicable                          + P"GR"  + P"gr"  --- sil stuff;    unsupported  local garbage_modifier  = ((1 - colon - slash)^0 * Cc(false))  local modifier          = slash * (other_modifier      --> ignore                                   + Cs(style_modifier)  --> collect +                                 + Ct(size_modifier)   --> collect                                   + garbage_modifier)   --> warn  local modifier_list     = Cg(Ct(modifier^0), "modifiers") @@ -409,15 +305,15 @@ local specification     = (prefixed + unprefixed)  local font_request      = Ct(path_lookup   * (colon^-1 * features)^-1                             + specification * (colon    * features)^-1) --- lpeg.print(font_request) ---- new parser: 632 rules +--  lpeg.print(font_request) +--- new parser: 657 rules  --- old parser: 230 rules  local import_values = {      --- That’s what the 1.x parser did, not quite as graciously,      --- with an array of branch expressions.      -- "style", "optsize",--> from slashed notation; handled otherwise -    "lookup", "sub" --[[‽]], "mode", +    "lookup", "sub", "mode",  }  local lookup_types = { "anon", "file", "name", "path" } @@ -441,21 +337,21 @@ local supported = {      gr   = false,  } +--- (string | (string * string) | bool) list -> (string * number)  local handle_slashed = function (modifiers)      local style, optsize      for i=1, #modifiers do          local mod  = modifiers[i] -        if supported[mod] then -            style = supported[mod] -        --elseif stringfind(v, "^s=") then -        elseif stringsub(v, 1, 2) == "s=" then -            local val = stringsub(v, 3) -            optsize = val -        elseif stylename == false then +        if type(mod) == "table" and mod[1] == "optsize" then --> optical size +            optsize = tonumber(mod[2]) +        elseif mod == false then +            --- ignore              report("log", 0,                  "load", "unsupported font option: %s", v) -        elseif not stringis_empty(v) then -            style = stringgsub(v, "[^%a%d]", "") +        elseif supported[mod] then +            style = supported[mod] +        elseif not stringis_empty(mod) then +            style = stringgsub(mod, "[^%a%d]", "")          end      end      return style, optsize @@ -465,6 +361,18 @@ end  local handle_request = function (specification)      local request = lpegmatch(font_request,                                specification.specification) +    if not request then +        --- happens when called with an absolute path +        --- in an anonymous lookup; +        --- we try to behave as friendly as possible +        --- just go with it ... +        report("log", 0, "load", "invalid request “%s” of type anon", +            specification.specification) +        report("log", 0, "load", "use square bracket syntax or consult the documentation.") +        specification.name      = specification.specification +        specification.lookup    = "file" +        return specification +    end      local lookup, name = select_lookup(request)      request.features  = set_default_features(request.features) @@ -501,15 +409,9 @@ local compare_requests = function (spec)      return new  end ---fonts.definers.registersplit(":", compare_requests, "cryptic") ---fonts.definers.registersplit("",  compare_requests, "more cryptic") -- catches \font\text=[names] -  fonts.definers.registersplit(":", handle_request, "cryptic")  fonts.definers.registersplit("",  handle_request, "more cryptic") -- catches \font\text=[names] ---fonts.definers.registersplit(":",old_behavior,"cryptic") ---fonts.definers.registersplit("", old_behavior,"more cryptic") -- catches \font\text=[names] -  ---[[ end included font-ltx.lua ]]  --[[doc-- @@ -531,11 +433,15 @@ local otf                 = fonts.handlers.otf  local registerotffeature  = otf.features.register  local setmetatableindex   = table.setmetatableindex --- In the userdata interface we can not longer tweak the loaded font as --- conveniently as before. For instance, instead of pushing extra data in --- in the table using the original structure, we now have to operate on --- the mkiv representation. And as the fontloader interface is modelled --- after fontforge we cannot change that one too much either. +--[[HH-- + +   In the userdata interface we can not longer tweak the loaded font as +   conveniently as before. For instance, instead of pushing extra data in +   in the table using the original structure, we now have to operate on +   the mkiv representation. And as the fontloader interface is modelled +   after fontforge we cannot change that one too much either. + +--HH]]--  local types = {      substitution = "gsub_single", @@ -799,24 +705,7 @@ local anum_specification = {  --- below the specifications as given in the removed font-otc.lua  --- the rest was identical to what this file had from the beginning  --- both make the “anum.tex” test pass anyways --- ---local anum_specification = { ---    { ---        type     = "substitution", ---        features = { arab = { urd = true, dflt = true } }, ---        data     = anum_arabic, ---        flags    = noflags, -- { }, ---        valid    = valid, ---    }, ---    { ---        type     = "substitution", ---        features = { arab = { urd = true } }, ---        data     = anum_persian, ---        flags    = noflags, -- { }, ---        valid    = valid, ---    }, ---} --- +  otf.addfeature("anum",anum_specification)  registerotffeature { diff --git a/luaotfload-loaders.lua b/luaotfload-loaders.lua index 8ab6b29..c9c30de 100644 --- a/luaotfload-loaders.lua +++ b/luaotfload-loaders.lua @@ -1,3 +1,11 @@ +if not modules then modules = { } end modules ["loaders"] = { +    version   = 2.200, +    comment   = "companion to luaotfload.lua", +    author    = "Hans Hagen, Khaled Hosny, Elie Roux, Philipp Gesang", +    copyright = "PRAGMA ADE / ConTeXt Development Team", +    license   = "see context related readme files" +} +  local fonts = fonts  --- diff --git a/luaotfload-override.lua b/luaotfload-override.lua index 2b9ef8b..863187f 100644 --- a/luaotfload-override.lua +++ b/luaotfload-override.lua @@ -1,12 +1,11 @@  if not modules then modules = { } end modules ['luat-ovr'] = { -    version   = 1.001, +    version   = 2.2,      comment   = "companion to luatex-*.tex", -    author    = "Khaled Hosny and Elie Roux", +    author    = "Khaled Hosny, Elie Roux, Philipp Gesang",      copyright = "Luaotfload Development Team",      license   = "GNU GPL v2"  } -  local module_name = "luaotfload"  local texiowrite_nl = texio.write_nl @@ -27,6 +26,7 @@ We recreate the verbosity levels previously implemented in font-nms:      ==========================================================  --doc]]-- +  local loglevel = 1 --- default  local logout   = "log" @@ -81,12 +81,4 @@ logs.names_report = function (mode, lvl, ...)      end  end -if containers then -    --- This will vanish as soon as Hans fixes it in data-con -    --- https://github.com/lualatex/luaotfload/issues/17 - -    containers.cleanname = function (name) -        return (string.gsub(string.lower(name),"[^%w%d\128\255]+","-")) -    end -end  -- vim:tw=71:sw=4:ts=4:expandtab diff --git a/luaotfload-tool.lua b/luaotfload-tool.lua index bb935cf..0cd19b1 100755 --- a/luaotfload-tool.lua +++ b/luaotfload-tool.lua @@ -1,13 +1,28 @@  #!/usr/bin/env texlua +----------------------------------------------------------------------- +--         FILE:  luaotfload-tool.lua +--  DESCRIPTION:  database functionality +-- REQUIREMENTS:  luaotfload 2.2 +--       AUTHOR:  Khaled Hosny, Élie Roux, Philipp Gesang +--      VERSION:  2.2 +--      LICENSE:  GPL v2 +--      CREATED:  2013-05-06 13:37:12+0200 +-----------------------------------------------------------------------  --[[doc-- -This file was originally written by Elie Roux and Khaled Hosny and is under CC0 -license (see http://creativecommons.org/publicdomain/zero/1.0/legalcode). + +This file was originally written (as \fileent{mkluatexfontdb.lua}) by +Elie Roux and Khaled Hosny and, as a derived work of ConTeXt, is +provided under the terms of the GPL v2.0 license as printed in full +text in the manual (luaotfload.pdf). + +    \url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html}.  This file is a wrapper for the luaotfload font names module  (luaotfload-database.lua). It is part of the luaotfload bundle, please  see the luaotfload documentation for more info. Report bugs to -\url{https://github.com/lualatex/luaotfload/issues}. + +    \url{https://github.com/lualatex/luaotfload/issues}.  --doc]]-- @@ -15,7 +30,6 @@ kpse.set_program_name"luatex"  local stringformat    = string.format  local texiowrite_nl   = texio.write_nl -local stringfind      = string.find  local stringlower     = string.lower @@ -93,7 +107,7 @@ require"luaotfload-override.lua"  --- this populates the logs.* namespace  require"luaotfload-database"  require"alt_getopt" -local version = "2.2" -- same version number as luaotfload +local version  = "2.2" -- same version number as luaotfload  local names    = fonts.names  local db_src_out = names.path.dir.."/"..names.path.basename @@ -253,11 +267,10 @@ actions.generate = function (job)  end  actions.flush = function (job) -    local success, fontnames = names.flush_cache() +    local success, lookups = names.flush_cache()      if success then -        local savedname = names.save(fontnames) -        logs.names_report("info", 2, "cache", -            "Cache emptied", #fontnames.mappings) +        local savedname = names.save_lookups() +        logs.names_report("info", 2, "cache", "Cache emptied")          if savedname then              return true, true          end diff --git a/luaotfload.dtx b/luaotfload.dtx index fd71485..ddd0116 100644 --- a/luaotfload.dtx +++ b/luaotfload.dtx @@ -1,10 +1,14 @@  % \iffalse meta-comment  % -% Copyright (C) 2009-2013 by Elie Roux    <elie.roux@telecom-bretagne.eu> -%                        and Khaled Hosny <khaledhosny@eglug.org> -%                             (Support: <lualatex-dev@tug.org>.) +% Copyright (C) 2009-2013 +%      by  Elie Roux      <elie.roux@telecom-bretagne.eu> +%      and Khaled Hosny   <khaledhosny@eglug.org> +%      and Philipp Gesang <philipp.gesang@alumni.uni-heidelberg.de>  % -% This work is under the CC0 license. +%      Home:      https://github.com/lualatex/luaotfload +%      Support:   <lualatex-dev@tug.org>. +% +% This work is under the GPL v2.0 license.  %  % This work consists of the main source file luaotfload.dtx  % and the derived files @@ -47,11 +51,15 @@  \preamble  This is a generated file. -Copyright (C) 2009-2013 by by Elie Roux    <elie.roux@telecom-bretagne.eu> -                          and Khaled Hosny <khaledhosny@eglug.org> -                               (Support: <lualatex-dev@tug.org>.) +Copyright (C) 2009-2013 +     by  Elie Roux      <elie.roux@telecom-bretagne.eu> +     and Khaled Hosny   <khaledhosny@eglug.org> +     and Philipp Gesang <philipp.gesang@alumni.uni-heidelberg.de> + +     Home:      https://github.com/lualatex/luaotfload +     Support:   <lualatex-dev@tug.org>. -This work is under the CC0 license. +This work is under the GPL v2.0 license.  This work consists of the main source file luaotfload.dtx  and the derived files @@ -119,12 +127,18 @@ and the derived files      citecolor=\primarycolor,       pdftitle={The luaotfload package},     pdfsubject={OpenType layout system for Plain TeX and LaTeX}, -    pdfauthor={Elie Roux & Khaled Hosny}, +    pdfauthor={Elie Roux & Khaled Hosny & Philipp Gesang},    pdfkeywords={luatex, lualatex, unicode, opentype}  ]{hyperref}  \usepackage{fontspec} -%usepackage{unicode-math}%% broken -\setmainfont[Numbers=OldStyle,Ligatures=TeX]{Linux Libertine O} +\usepackage{unicode-math} +\setmainfont[ +  Numbers     = OldStyle, +  Ligatures   = TeX, +  BoldFont    = {Linux Libertine Bold}, +  ItalicFont  = {Linux Libertine Italic}, +  SlantedFont = {Linux Libertine Italic}, +]{Linux Libertine O}  \setmonofont[Ligatures=TeX,Scale=MatchLowercase]{Liberation Mono}  %setsansfont[Ligatures=TeX]{Linux Biolinum O}  \setsansfont[Ligatures=TeX,Scale=MatchLowercase]{Iwona Medium} @@ -164,6 +178,27 @@ and the derived files  \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}%% no \word; life is full of disappointments +             {\movecountertomargin\thesection} \zeropoint {} +\titleformat \subsection +             {\small\rmfamily\itshape} +             {\movecountertomargin\thesubsection} \zeropoint {} + +\usepackage{tocloft} +\renewcommand \cftpartfont   {\rmfamily\upshape} +\renewcommand \cftsecfont    {\rmfamily\upshape} +\renewcommand \cftsubsecfont {\rmfamily\upshape} +\setlength \cftbeforepartskip {1ex} +\setlength \cftbeforesecskip  {1ex} +  \VerbatimFootnotes  \begin{document}    \DocInput{luaotfload.dtx}% @@ -192,9 +227,10 @@ and the derived files  % \GetFileInfo{luaotfload.drv}  %  % \title{The \identifier{luaotfload} package} -% \date{2013/04/16 v2.2} -% \author{Elie Roux and Khaled Hosny\\ -%         Support: \email{lualatex-dev@tug.org}} +% \date{2013/05/05 v2.2} +% \author{Elie Roux · Khaled Hosny · Philipp Gesang\\ +%         Home:      \url{https://github.com/lualatex/luaotfload}\\ +%         Support:   \email{lualatex-dev@tug.org}}  %  % \maketitle  % @@ -296,7 +332,7 @@ and the derived files  %  %       <path lookup>      ::= \{ {\sc all_characters} - `]' \} ;  % -%       <modifier>         ::= `/', (`I' | `B' | `BI' | `IB') ; +%       <modifier>         ::= `/', (`I' | `B' | `BI' | `IB' | `S=', \{ {\sc digit} \} ) ;  %  %       <subfont no>       ::= `(', \{ {\sc digit} \}, `)' ;  % @@ -1104,6 +1140,9 @@ and the derived files  %                                          (\abbrev{pfa}, \abbrev{pfb}).  %     \ouritem {luaotfload-database.lua}   font names database.  %     \ouritem {luaotfload-colors.lua}     color handling. +%     \ouritem {luaotfload-auxiliary.lua}  access to internal functionality +%                                          for package authors +%                                          (proposals for additions welcome).  % \end{itemize}  %  % \begin{figure}[b] @@ -1178,10 +1217,13 @@ and the derived files  luaotfload                  = luaotfload or {}  local luaotfload            = luaotfload -config                      = config or { } -config.luaotfload           = config.luaotfload or { } -config.luaotfload.resolver  = config.luaotfload.resolver or "normal" -config.luaotfload.definer   = config.luaotfload.definer  or "patch" +config                            = config or { } +config.luaotfload                 = config.luaotfload or { } +------.luaotfload.resolver        = config.luaotfload.resolver  or "normal" +config.luaotfload.resolver        = config.luaotfload.resolver  or "cached" +config.luaotfload.definer         = config.luaotfload.definer   or "patch" +config.luaotfload.loglevel        = config.luaotfload.loglevel  or 1 +config.luaotfload.color_callback  = config.luaotfload.color_callback  or "pre_linebreak_filter"  --luaotfload.prefer_merge     = config.luaotfload.prefer_merge or true  luaotfload.module = { @@ -1191,7 +1233,7 @@ luaotfload.module = {      description   = "OpenType layout system.",      author        = "Elie Roux & Hans Hagen",      copyright     = "Elie Roux", -    license       = "CC0" +    license       = "GPL v2.0"  }  local luatexbase = luatexbase @@ -1378,7 +1420,7 @@ local pop_namespaces = function (normalglobal, isolate)          local _G = _G          local mode = "non-destructive"          if isolate then mode = "destructive" end -        log("pop namespace from font loader -- "..mode) +        log("pop namespace from font loader -- " .. mode)          for k, v in next, _G do              if not normalglobal[k] then                  context_environment[k] = v @@ -1419,6 +1461,7 @@ tex.attribute[0] = 0  %    \begin{macrocode}  loadmodule"merged.lua" +---loadmodule"font-odv.lua" --- <= Devanagari support from Context  if fonts then @@ -1518,20 +1561,9 @@ add_to_callback("find_vf_file",  loadmodule"lib-dir.lua"   --- required by luaofload-database.lua  loadmodule"override.lua"  --- “luat-ovr” -logs.set_loglevel(config.luaotfload.loglevel or 2) +logs.set_loglevel(config.luaotfload.loglevel)  %    \end{macrocode} -% \CONTEXT does not support ofm, these lines were added in order to make it -% work. However they do not seem necessary so they are commented for now. -% -%    \begin{macrocode} --- if fonts and fonts.readers.tfm then ---  fonts.readers.ofm  = fonts.readers.tfm ---  fonts.handlers.ofm = fonts.handlers.tfm --- empty anyways ---  fonts.formats.ofm  = fonts.formats.tfm  --- “type1” ---  --- fonts.readers.sequence[#fonts.readers.sequence+1] = "ofm" ---end -%    \end{macrocode}  % Now we load the modules written for \identifier{luaotfload}.  %  %    \begin{macrocode} @@ -1575,8 +1607,8 @@ formats.ofm               = "type1"  %  %    \begin{macrocode}  request_resolvers.file = function (specification) -    --local found = fonts.names.crude_file_lookup(specification.name) -    local found = fonts.names.crude_file_lookup_verbose(specification.name) +    local found = fonts.names.crude_file_lookup(specification.name) +    --local found = fonts.names.crude_file_lookup_verbose(specification.name)      specification.name = found[1]      --if format then specification.forced = format end  end @@ -1658,7 +1690,10 @@ local read_font_file = fonts.definers.read  --- spec -> size -> id -> tmfdata  local patch_defined_font = function (specification, size, id)      local tfmdata = read_font_file(specification, size, id) -    if type(tfmdata) == "table" then +    if type(tfmdata) == "table" and tfmdata.shared then +        --- We need to test for the “shared” field here +        --- or else the fontspec capheight callback will +        --- operate on tfm fonts.          call_callback("luaotfload.patch_font", tfmdata)      end      return tfmdata diff --git a/mkglyphlist b/mkglyphlist index d73a608..281c736 100755 --- a/mkglyphlist +++ b/mkglyphlist @@ -27,9 +27,13 @@ require"lpeg"  require"socket"  kpse.set_program_name"luatex" -dofile(kpse.find_file("lualibs-lua.lua",   "lua")) -dofile(kpse.find_file("lualibs-lpeg.lua",  "lua")) -dofile(kpse.find_file("lualibs-table.lua", "lua")) --- for serialization +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 diff --git a/tests/systemfonts.tex b/tests/systemfonts.tex index 0e842db..af08509 100644 --- a/tests/systemfonts.tex +++ b/tests/systemfonts.tex @@ -21,6 +21,8 @@  \font\lmbi     ={Latin Modern Roman/BI:+liga} at 10pt  \font\lms      ={Latin Modern Roman Slanted:+liga} at 10pt  \font\lmltn    ={Latin Modern Roman:script=latn} at 10pt +%% get this font here: +%% http://sourceforge.net/projects/arabeyes/files/kacst_fonts/kacst_one_5.0.tar.bz2/download  \font\arab     ={KacstOne:mode=node;script=arab} at 10pt  \termesr   fi fl ffi ffl ff\par | 
