diff options
| -rw-r--r-- | luaotfload-legacy-attributes.lua | 27 | ||||
| -rw-r--r-- | luaotfload-legacy-database.lua | 724 | ||||
| -rw-r--r-- | luaotfload-legacy-merged.lua | 8157 | ||||
| -rwxr-xr-x | luaotfload-legacy-tool.lua | 105 | ||||
| -rw-r--r-- | luaotfload-legacy.lua | 402 | 
5 files changed, 0 insertions, 9415 deletions
| diff --git a/luaotfload-legacy-attributes.lua b/luaotfload-legacy-attributes.lua deleted file mode 100644 index c6130b4..0000000 --- a/luaotfload-legacy-attributes.lua +++ /dev/null @@ -1,27 +0,0 @@ ------------------------------------------------------------------------ ---         FILE:  otfl-luat-att.lua ---        USAGE:  with old luaotfload ---  DESCRIPTION:  setting attributes abide luatexbase rules --- REQUIREMENTS:  some old luatex ---       AUTHOR:  Philipp Gesang (Phg), <phg42.2a@gmail.com> ---      CREATED:  2013-05-10 20:37:19+0200 ------------------------------------------------------------------------ --- - -if not modules then modules = { } end modules ['otfl-luat-att'] = { -    version   = math.pi/42, -    comment   = "companion to luaotfload.lua", -    author    = "Philipp Gesang", -    copyright = "Luaotfload Development Team", -    license   = "GNU GPL v2" -} - -function attributes.private(name) -    local attr   = "otfl@" .. name -    local number = luatexbase.attributes[attr] -    if not number then -        number = luatexbase.new_attribute(attr) -    end -    return number -end - diff --git a/luaotfload-legacy-database.lua b/luaotfload-legacy-database.lua deleted file mode 100644 index b31fe88..0000000 --- a/luaotfload-legacy-database.lua +++ /dev/null @@ -1,724 +0,0 @@ -if not modules then modules = { } end modules ['font-nms'] = { -    version   = "old", -    comment   = "companion to luaotfload.lua", -    author    = "Khaled Hosny and Elie Roux", -    copyright = "Luaotfload Development Team", -    license   = "GNU GPL v2" -} - -fonts                = fonts       or { } -fonts.names          = fonts.names or { } - -local names          = fonts.names -local names_dir      = "luatex-cache/generic/names" -names.version        = "old" -- not the same as in context -names.data           = nil -names.path           = { -    basename  = "otfl-names.lua", --- different from current -    localdir  = file.join(kpse.expand_var("$TEXMFVAR"),    names_dir), -    systemdir = file.join(kpse.expand_var("$TEXMFSYSVAR"), names_dir), -} - - -local splitpath, expandpath = file.split_path, kpse.expand_path -local glob, basename        = dir.glob, file.basename -local upper, lower, format  = string.upper, string.lower, string.format -local gsub, match, rpadd    = string.gsub, string.match, string.rpadd -local gmatch, sub, find     = string.gmatch, string.sub, string.find -local utfgsub               = unicode.utf8.gsub - -local trace_short    = false --tracing adapted to rebuilding of the database inside a document -local trace_search   = false --trackers.register("names.search",   function(v) trace_search   = v end) -local trace_loading  = false --trackers.register("names.loading",  function(v) trace_loading  = v end) - -local function sanitize(str) -    if str then -        return utfgsub(lower(str), "[^%a%d]", "") -    else -        return str -- nil -    end -end - -local function fontnames_init() -    return { -        mappings  = { }, -        status    = { }, -        version   = names.version, -    } -end - -local function load_names() -    local localpath  = file.join(names.path.localdir, names.path.basename) -    local systempath = file.join(names.path.systemdir, names.path.basename) -    local kpsefound  = kpse.find_file(names.path.basename) -    local foundname -    local data -    if kpsefound and file.isreadable(kpsefound) then -        data = dofile(kpsefound) -	foundname = kpsefound -    elseif file.isreadable(localpath)  then -        data = dofile(localpath) -	foundname = localpath -    elseif file.isreadable(systempath) then -        data = dofile(systempath) -	foundname = systempath -    end -    if data then -        logs.info("Font names database loaded: " .. foundname) -    else -        logs.info([[Font names database not found, generating new one. -             This can take several minutes; please be patient.]]) -        data = names.update(fontnames_init()) -        names.save(data) -    end -    return data -end - -local synonyms = { -    regular    = { "normal", "roman", "plain", "book", "medium" }, -    -- boldregular was for old versions of Linux Libertine, is it still useful? -    -- semibold is in new versions of Linux Libertine, but there is also a bold, -    -- not sure it's useful here... -    bold       = { "demi", "demibold", "semibold", "boldregular" }, -    italic     = { "regularitalic", "normalitalic", "oblique", "slanted" }, -    bolditalic = { "boldoblique", "boldslanted", "demiitalic", "demioblique", "demislanted", "demibolditalic", "semibolditalic" }, -} - -local loaded   = false -local reloaded = false - -function names.resolve(specification) -    local name  = sanitize(specification.name) -    local style = sanitize(specification.style) or "regular" - -    local size -    if specification.optsize then -        size = tonumber(specification.optsize) -    elseif specification.size then -        size = specification.size / 65536 -    end - - -    if not loaded then -        names.data = names.load() -        loaded     = true -    end - -    local data = names.data -    if type(data) == "table" and data.version == names.version then -        if data.mappings then -            local found = { } -            for _,face in next, data.mappings do -                local family, subfamily, fullname, psname -                local optsize, dsnsize, maxsize, minsize - -                if face.names then -                    family    = sanitize(face.names.family) -                    subfamily = sanitize(face.names.subfamily) -                    fullname  = sanitize(face.names.fullname) -                    psname    = sanitize(face.names.psname) -                end -                local fontname  = sanitize(face.fontname) -                local pfullname = sanitize(face.fullname) -                if #face.size > 0 then -                    optsize = face.size -                    dsnsize = optsize[1] and optsize[1] / 10 -                    -- can be nil -                    maxsize = optsize[2] and optsize[2] / 10 or dsnsize -                    minsize = optsize[3] and optsize[3] / 10 or dsnsize -                end -                if name == family then -                    if subfamily == style then -                        if optsize then -                            if dsnsize == size -                            or (size > minsize and size <= maxsize) then -                                found[1] = face -                                break -                            else -                                found[#found+1] = face -                            end -                        else -                            found[1] = face -                            break -                        end -                    elseif synonyms[style] and -                           table.contains(synonyms[style], subfamily) then -                        if optsize then -                            if dsnsize == size -                            or (size > minsize and size <= maxsize) then -                                found[1] = face -                                break -                            else -                                found[#found+1] = face -                            end -                        else -                            found[1] = face -                            break -                        end -                    elseif subfamily == "regular" or -                           table.contains(synonyms.regular, subfamily) then -                        found.fallback = face -                    elseif name == fullname -                    or name == pfullname -                    or name == fontname -                    or name == psname then -                        if optsize then -                            if dsnsize == size -                            or (size > minsize and size <= maxsize) then -                                found[1] = face -                                break -                            else -                                found[#found+1] = face -                            end -                        else -                            found[1] = face -                            break -                        end -                    end -                else -                    if name == fullname -                    or name == pfullname -                    or name == fontname -                    or name == psname then -                        if optsize then -                            if dsnsize == size -                            or (size > minsize and size <= maxsize) then -                                found[1] = face -                                break -                            else -                                found[#found+1] = face -                            end -                        else -                            found[1] = face -                            break -                        end -                    end -                end -            end -            if #found == 1 then -                if kpse.lookup(found[1].filename[1]) then -                    logs.report("load font", -                                "font family='%s', subfamily='%s' found: %s", -                                name, style, found[1].filename[1]) -                    return found[1].filename[1], found[1].filename[2] -                elseif lfs.isfile(found[1].found_at) then -                    logs.report("load font", -                                "font family='%s', subfamily='%s' found: %s", -                                name, style, found[1].found_at) -                    return found[1].found_at, found[1].filename[2] -                end -            elseif #found > 1 then -                -- we found matching font(s) but not in the requested optical -                -- sizes, so we loop through the matches to find the one with -                -- least difference from the requested size. -                local closest -                local least = math.huge -- initial value is infinity -                for i,face in next, found do -                    local dsnsize    = face.size[1]/10 -                    local difference = math.abs(dsnsize-size) -                    if difference < least then -                        closest = face -                        least   = difference -                    end -                end -                if kpse.lookup(closest.filename[1]) then -                    logs.report("load font", -                                "font family='%s', subfamily='%s' found: %s", -                                name, style, closest.filename[1]) -                    return closest.filename[1], closest.filename[2] -                elseif lfs.isfile(closest.found_at) then -                    logs.report("load font", -                                "font family='%s', subfamily='%s' found: %s", -                                name, style, closest.found_at) -                    return closest.found_at, closest.filename[2] -                end -            elseif found.fallback then -                return found.fallback.filename[1], found.fallback.filename[2] -            end -            -- no font found so far -            if not reloaded then -                -- try reloading the database -                names.data = names.update(names.data) -                names.save(names.data) -                reloaded   = true -                return names.resolve(specification) -            else -                -- else, fallback to filename -                return specification.name, false -            end -        end -    else -        if not reloaded then -            names.data = names.update() -            names.save(names.data) -            reloaded   = true -            return names.resolve(specification) -        else -            return specification.name, false -        end -    end -end - -names.resolvespec = names.resolve - -function names.set_log_level(level) -    if level == 2 then -        trace_loading = true -    elseif level >= 3 then -        trace_loading = true -        trace_search = true -    end -end - -local lastislog = 0 - -local function log(fmt, ...) -    lastislog = 1 -    texio.write_nl(format("luaotfload | %s", format(fmt,...))) -    io.flush() -end - -logs        = logs or { } -logs.report = logs.report or log -logs.info   = logs.info or log - -local function font_fullinfo(filename, subfont, texmf) -    local found_at = filename -    local t = { } -    local f = fontloader.open(filename, subfont) -    if not f then -	    if trace_loading then -        	logs.report("error: failed to open %s", filename) -	    end -        return -    end -    local m = fontloader.to_table(f) -    fontloader.close(f) -    collectgarbage('collect') -    -- see http://www.microsoft.com/typography/OTSPEC/features_pt.htm#size -    if m.fontstyle_name then -        for _,v in next, m.fontstyle_name do -            if v.lang == 1033 then -                t.fontstyle_name = v.name -            end -        end -    end -    if m.names then -        for _,v in next, m.names do -            if v.lang == "English (US)" then -                t.names = { -                    -- see -                    -- http://developer.apple.com/textfonts/ -                    -- TTRefMan/RM06/Chap6name.html -                    fullname = v.names.compatfull     or v.names.fullname, -                    family   = v.names.preffamilyname or v.names.family, -                    subfamily= t.fontstyle_name       or v.names.prefmodifiers  or v.names.subfamily, -                    psname   = v.names.postscriptname -                } -            end -        end -    else -        -- no names table, propably a broken font -        if trace_loading then -            logs.report("broken font rejected: %s", basefile) -        end -        return -    end -    t.fontname    = m.fontname -    t.fullname    = m.fullname -    t.familyname  = m.familyname -    t.filename    = { texmf and basename(filename) or filename, subfont } -    t.weight      = m.pfminfo.weight -    t.width       = m.pfminfo.width -    t.slant       = m.italicangle -    -- don't waste the space with zero values -    t.size = { -        m.design_size         ~= 0 and m.design_size         or nil, -        m.design_range_top    ~= 0 and m.design_range_top    or nil, -        m.design_range_bottom ~= 0 and m.design_range_bottom or nil, -    } -    -- rather, waste space on paths -    t.found_at = found_at -    return t -end - -local function load_font(filename, fontnames, newfontnames, texmf) -    local newmappings = newfontnames.mappings -    local newstatus   = newfontnames.status -    local mappings    = fontnames.mappings -    local status      = fontnames.status -    local basefile    = texmf and basename(filename) or filename -    if filename then -        if table.contains(names.blacklist, filename) or -           table.contains(names.blacklist, basename(filename)) then -            if trace_search then -                logs.report("ignoring font '%s'", filename) -            end -            return -        end -        local timestamp, db_timestamp -        db_timestamp        = status[basefile] and status[basefile].timestamp -        timestamp           = lfs.attributes(filename, "modification") - -        local index_status = newstatus[basefile] or (not texmf and newstatus[basename(filename)]) -        if index_status and index_status.timestamp == timestamp then -            -- already indexed this run -            return -        end - -        newstatus[basefile] = newstatus[basefile] or { } -        newstatus[basefile].timestamp = timestamp -        newstatus[basefile].index     = newstatus[basefile].index or { } - -        if db_timestamp == timestamp and not newstatus[basefile].index[1] then -            for _,v in next, status[basefile].index do -                local index = #newstatus[basefile].index -                newmappings[#newmappings+1]        = mappings[v] -                newstatus[basefile].index[index+1] = #newmappings -            end -            if trace_loading then -                logs.report("font already indexed: %s", basefile) -            end -            return -        end -        local info = fontloader.info(filename) -        if info then -            if type(info) == "table" and #info > 1 then -                for i in next, info do -                    local fullinfo = font_fullinfo(filename, i-1, texmf) -                    if not fullinfo then -                        return -                    end -                    local index = newstatus[basefile].index[i] -                    if not index then -                        index = #newmappings+1 -                    end -                    newmappings[index]           = fullinfo -                    newstatus[basefile].index[i] = index -                end -            else -                local fullinfo = font_fullinfo(filename, false, texmf) -                if not fullinfo then -                    return -                end -                local index = newstatus[basefile].index[1] -                if not index then -                    index = #newmappings+1 -                end -                newmappings[index]           = fullinfo -                newstatus[basefile].index[1] = index -            end -        else -            if trace_loading then -               logs.report("failed to load %s", basefile) -            end -        end -    end -end - -local function path_normalize(path) -    --[[ -        path normalization: -        - a\b\c  -> a/b/c -        - a/../b -> b -        - /cygdrive/a/b -> a:/b -        - reading symlinks under non-Win32 -        - using kpse.readable_file on Win32 -    ]] -    if os.type == "windows" or os.type == "msdos" then -        path = path:gsub('\\', '/') -        path = path:lower() -        path = path:gsub('^/cygdrive/(%a)/', '%1:/') -    end -    if os.type ~= "windows" and os.type ~= "msdos" then -        local dest = lfs.readlink(path) -        if dest then -            if kpse.readable_file(dest) then -                path = dest -            elseif kpse.readable_file(file.join(file.dirname(path), dest)) then -                path = file.join(file.dirname(path), dest) -            else -                -- broken symlink? -            end -        end -    end -    path = file.collapse_path(path) -    return path -end - -fonts.path_normalize = path_normalize - -names.blacklist = { } - -local function read_blacklist() -    local files = { -        kpse.lookup("otfl-blacklist.cnf", {all=true, format="tex"}) -    } -    local blacklist = names.blacklist - -    if files and type(files) == "table" then -        for _,v in next, files do -            for line in io.lines(v) do -                line = line:strip() -- to get rid of lines like " % foo" -                if line:find("^%%") or line:is_empty() then -                    -- comment or empty line -                else -                    line = line:split("%")[1] -                    line = line:strip() -                    if trace_search then -                        logs.report("blacklisted file: %s", line) -                    end -                    blacklist[#blacklist+1] = line -                end -            end -        end -    end -end - -local font_extensions = { "otf", "ttf", "ttc", "dfont" } - -local function scan_dir(dirname, fontnames, newfontnames, texmf) -    --[[ -    This function scans a directory and populates the list of fonts -    with all the fonts it finds. -    - dirname is the name of the directory to scan -    - names is the font database to fill -    - texmf is a boolean saying if we are scanning a texmf directory -    ]] -    local list, found = { }, { } -    local nbfound = 0 -    if trace_search then -        logs.report("scanning '%s'", dirname) -    end -    for _,i in next, font_extensions do -        for _,ext in next, { i, upper(i) } do -            found = glob(format("%s/**.%s$", dirname, ext)) -            -- note that glob fails silently on broken symlinks, which happens -            -- sometimes in TeX Live. -            if trace_search then -                logs.report("%s '%s' fonts found", #found, ext) -            end -            nbfound = nbfound + #found -            table.append(list, found) -        end -    end -    if trace_search then -        logs.report("%d fonts found in '%s'", nbfound, dirname) -    end - -    for _,file in next, list do -        file = path_normalize(file) -        if trace_loading then -            logs.report("loading font: %s", file) -        end -        load_font(file, fontnames, newfontnames, texmf) -    end -end - -local function scan_texmf_fonts(fontnames, newfontnames) -    --[[ -    This function scans all fonts in the texmf tree, through kpathsea -    variables OPENTYPEFONTS and TTFONTS of texmf.cnf -    ]] -    if expandpath("$OSFONTDIR"):is_empty() then -        logs.info("Scanning TEXMF fonts...") -    else -        logs.info("Scanning TEXMF and OS fonts...") -    end -    local fontdirs = expandpath("$OPENTYPEFONTS"):gsub("^%.", "") -    fontdirs = fontdirs .. expandpath("$TTFONTS"):gsub("^%.", "") -    if not fontdirs:is_empty() then -        for _,d in next, splitpath(fontdirs) do -            scan_dir(d, fontnames, newfontnames, true) -        end -    end -end - ---[[ -  For the OS fonts, there are several options: -   - if OSFONTDIR is set (which is the case under windows by default but -     not on the other OSs), it scans it at the same time as the texmf tree, -     in the scan_texmf_fonts. -   - in addition: -     - under Windows and Mac OSX, we take a look at some hardcoded directories -     - under Unix, we read /etc/fonts/fonts.conf and read the directories in it - -  This means that if you have fonts in fancy directories, you need to set them -  in OSFONTDIR if they cannot be found by fontconfig. -]] - -local function read_fonts_conf(path, results, passed_paths) -    --[[ -    This function parses /etc/fonts/fonts.conf and returns all the dir it finds. -    The code is minimal, please report any error it may generate. -    ]] -    local f = io.open(path) -    table.insert(passed_paths, path) -    if not f then -        logs.info("Warning: unable to read "..path.. ", skipping...") -        return results -    end -    local incomments = false -    for line in f:lines() do -        while line and line ~= "" do -            -- spaghetti code... hmmm... -            if incomments then -                local tmp = find(line, '-->') -                if tmp then -                    incomments = false -                    line = sub(line, tmp+3) -                else -                    line = nil -                end -            else -                local tmp = find(line, '<!--') -                local newline = line -                if tmp then -                    -- for the analysis, we take everything that is before the -                    -- comment sign -                    newline = sub(line, 1, tmp-1) -                    -- and we loop again with the comment -                    incomments = true -                    line = sub(line, tmp+4) -                else -                    -- if there is no comment start, the block after that will -                    -- end the analysis, we exit the while loop -                    line = nil -                end -                for dir in gmatch(newline, '<dir>([^<]+)</dir>') do -                    -- now we need to replace ~ by kpse.expand_path('~') -                    if sub(dir, 1, 1) == '~' then -                        dir = file.join(kpse.expand_path('~'), sub(dir, 2)) -                    end -                    -- we exclude paths with texmf in them, as they should be -                    -- found anyway -                    if not find(dir, 'texmf') then -                        results[#results+1] = dir -                    end -                end -                for include in gmatch(newline, '<include[^<]*>([^<]+)</include>') do -                    -- include here can be four things: a directory or a file, -                    -- in absolute or relative path. -                    if sub(include, 1, 1) == '~' then -                        include = file.join(kpse.expand_path('~'),sub(include, 2)) -                        -- First if the path is relative, we make it absolute: -                    elseif not lfs.isfile(include) and not lfs.isdir(include) then -                        include = file.join(file.dirname(path), include) -                    end -                    if lfs.isfile(include) and kpse.readable_file(include) and not table.contains(passed_paths, include) then -                        -- we exclude path with texmf in them, as they should -                        -- be found otherwise -                        read_fonts_conf(include, results, passed_paths) -                    elseif lfs.isdir(include) then -                        for _,f in next, glob(file.join(include, "*.conf")) do -                            if not table.contains(passed_paths, f) then -                                read_fonts_conf(f, results, passed_paths) -                            end -                        end -                    end -                end -            end -        end -    end -    f:close() -    return results -end - --- for testing purpose -names.read_fonts_conf = read_fonts_conf - -local function get_os_dirs() -    if os.name == 'macosx' then -        return { -            file.join(kpse.expand_path('~'), "Library/Fonts"), -            "/Library/Fonts", -            "/System/Library/Fonts", -            "/Network/Library/Fonts", -        } -    elseif os.type == "windows" or os.type == "msdos" then -        local windir = os.getenv("WINDIR") -        return { file.join(windir, 'Fonts') } -    else -        return read_fonts_conf("/etc/fonts/fonts.conf", {}, {}) -    end -end - -local function scan_os_fonts(fontnames, newfontnames) -    --[[ -    This function scans the OS fonts through -      - fontcache for Unix (reads the fonts.conf file and scans the directories) -      - a static set of directories for Windows and MacOSX -    ]] -    logs.info("Scanning OS fonts...") -    if trace_search then -        logs.info("Searching in static system directories...") -    end -    for _,d in next, get_os_dirs() do -        scan_dir(d, fontnames, newfontnames, false) -    end -end - -local function update_names(fontnames, force) -    --[[ -    The main function, scans everything -    - fontnames is the final table to return -    - force is whether we rebuild it from scratch or not -    ]] -    logs.info("Updating the font names database:") - -    if force then -        fontnames = fontnames_init() -    else -        if not fontnames then -            fontnames = names.load() -        end -        if fontnames.version ~= names.version then -            fontnames = fontnames_init() -            if trace_search then -                logs.report("No font names database or old one found; " -                          .."generating new one") -            end -        end -    end -    local newfontnames = fontnames_init() -    read_blacklist() -    scan_texmf_fonts(fontnames, newfontnames) -    scan_os_fonts(fontnames, newfontnames) -    return newfontnames -end - -local function save_names(fontnames) -    local savepath  = names.path.localdir -    if not lfs.isdir(savepath) then -        dir.mkdirs(savepath) -    end -    savepath = file.join(savepath, names.path.basename) -    if file.iswritable(savepath) then -        table.tofile(savepath, fontnames, true) -        logs.info("Font names database saved: %s \n", savepath) -        return savepath -    else -        logs.info("Failed to save names database\n") -        return nil -    end -end - -local function scan_external_dir(dir) -    local old_names, new_names -    if loaded then -        old_names = names.data -    else -        old_names = names.load() -        loaded    = true -    end -    new_names = table.copy(old_names) -    scan_dir(dir, old_names, new_names) -    names.data = new_names -end - -names.scan   = scan_external_dir -names.load   = load_names -names.update = update_names -names.save   = save_names - --- vim:ft=lua:sw=4:ts=4:expandtab diff --git a/luaotfload-legacy-merged.lua b/luaotfload-legacy-merged.lua deleted file mode 100644 index 9bec298..0000000 --- a/luaotfload-legacy-merged.lua +++ /dev/null @@ -1,8157 +0,0 @@ --- merged file : luaotfload-legacy-merged.lua --- parent file : luaotfload-legacy.lua --- merge date  : Fri May 10 20:57:35 2013 - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['luat-dum']={ -  version=1.100, -  comment="companion to luatex-*.tex", -  author="Hans Hagen, PRAGMA-ADE, Hasselt NL", -  copyright="PRAGMA ADE / ConTeXt Development Team", -  license="see context related readme files" -} -local dummyfunction=function() end -statistics={ -  register=dummyfunction, -  starttiming=dummyfunction, -  stoptiming=dummyfunction, -} -directives={ -  register=dummyfunction, -  enable=dummyfunction, -  disable=dummyfunction, -} -trackers={ -  register=dummyfunction, -  enable=dummyfunction, -  disable=dummyfunction, -} -experiments={ -  register=dummyfunction, -  enable=dummyfunction, -  disable=dummyfunction, -} -storage={ -  register=dummyfunction, -  shared={}, -} -logs={ -  report=dummyfunction, -  simple=dummyfunction, -} -tasks={ -  new=dummyfunction, -  actions=dummyfunction, -  appendaction=dummyfunction, -  prependaction=dummyfunction, -} -callbacks={ -  register=function(n,f) return callback.register(n,f) end, -} -texconfig.kpse_init=true -resolvers=resolvers or {}  -local remapper={ -  otf="opentype fonts", -  ttf="truetype fonts", -  ttc="truetype fonts", -  dfont="truetype fonts", -  cid="cid maps", -  fea="font feature files", -} -function resolvers.find_file(name,kind) -  name=string.gsub(name,"\\","/") -  kind=string.lower(kind) -  return kpse.find_file(name,(kind and kind~="" and (remapper[kind] or kind)) or file.extname(name,"tex")) -end -function resolvers.findbinfile(name,kind) -  if not kind or kind=="" then -    kind=file.extname(name)  -  end -  return resolvers.find_file(name,(kind and remapper[kind]) or kind) -end -caches={} -local writable,readables=nil,{} -if not caches.namespace or caches.namespace=="" or caches.namespace=="context" then -  caches.namespace='generic' -end -do -  local cachepaths -  if kpse.expand_var('$TEXMFCACHE')~='$TEXMFCACHE' then -    cachepaths=kpse.expand_var('$TEXMFCACHE') -  elseif kpse.expand_var('$TEXMFVAR')~='$TEXMFVAR' then -    cachepaths=kpse.expand_var('$TEXMFVAR') -  end -  if not cachepaths then -    cachepaths="." -  end -  cachepaths=string.split(cachepaths,os.type=="windows" and ";" or ":") -  for i=1,#cachepaths do -    local done -    writable=file.join(cachepaths[i],"luatex-cache") -    writable=file.join(writable,caches.namespace) -    writable,done=dir.mkdirs(writable) -    if done then -      break -    end -  end -  for i=1,#cachepaths do -    if file.isreadable(cachepaths[i]) then -      readables[#readables+1]=file.join(cachepaths[i],"luatex-cache",caches.namespace) -    end -  end -  if not writable then -    texio.write_nl("quiting: fix your writable cache path\n") -    os.exit() -  elseif #readables==0 then -    texio.write_nl("quiting: fix your readable cache path\n") -    os.exit() -  elseif #readables==1 and readables[1]==writable then -    texio.write(string.format("(using cache: %s)",writable)) -  else -    texio.write(string.format("(using write cache: %s)",writable)) -    texio.write(string.format("(using read cache: %s)",table.concat(readables," "))) -  end -end -function caches.getwritablepath(category,subcategory) -  local path=file.join(writable,category) -  lfs.mkdir(path) -  path=file.join(path,subcategory) -  lfs.mkdir(path) -  return path -end -function caches.getreadablepaths(category,subcategory) -  local t={} -  for i=1,#readables do -    t[i]=file.join(readables[i],category,subcategory) -  end -  return t -end -local function makefullname(path,name) -  if path and path~="" then -    name="temp-"..name  -    return file.addsuffix(file.join(path,name),"lua") -  end -end -function caches.iswritable(path,name) -  local fullname=makefullname(path,name) -  return fullname and file.iswritable(fullname) -end -function caches.loaddata(paths,name) -  for i=1,#paths do -    local fullname=makefullname(paths[i],name) -    if fullname then -      texio.write(string.format("(load: %s)",fullname)) -      local data=loadfile(fullname) -      return data and data() -    end -  end -end -function caches.savedata(path,name,data) -  local fullname=makefullname(path,name) -  if fullname then -    texio.write(string.format("(save: %s)",fullname)) -    table.tofile(fullname,data,'return',false,true,false) -  end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['luat-ovr']={ -  version=1.001, -  comment="companion to luatex-*.tex", -  author="Khaled Hosny and Elie Roux", -  copyright="Luaotfload Development Team", -  license="GNU GPL v2" -} -local write_nl,format,name=texio.write_nl,string.format,"luaotfload" -local dummyfunction=function() end -callbacks={ -  register=dummyfunction, -} -function logs.report(category,fmt,...) -  if fmt then -    write_nl('log',format("%s | %s: %s",name,category,format(fmt,...))) -  elseif category then -    write_nl('log',format("%s | %s",name,category)) -  else -    write_nl('log',format("%s |",name)) -  end -end -function logs.info(category,fmt,...) -  if fmt then -    write_nl(format("%s | %s: %s",name,category,format(fmt,...))) -  elseif category then -    write_nl(format("%s | %s",name,category)) -  else -    write_nl(format("%s |",name)) -  end -  io.flush() -end -function logs.simple(fmt,...) -  if fmt then -    write_nl('log',format("%s | %s",name,format(fmt,...))) -  else -    write_nl('log',format("%s |",name)) -  end -end -tex.attribute[0]=0 -tex.ctxcatcodes=luatexbase.catcodetables.latex - -end -- closure - -do -- begin closure to overcome local limits and interference - -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 {} -containers.usecache=true -local function report(container,tag,name) -  if trace_cache or trace_containers then -    logs.report(format("%s cache",container.subcategory),"%s: %s",tag,name or 'invalid') -  end -end -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 -} -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.iswritable(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) -    if stored and stored.cache_version==container.version then -      report(container,"loaded",name) -    else -      stored=nil -    end -    storage[name]=stored -  elseif stored then -    report(container,"reusing",name) -  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) -      report(container,"saved",name) -      data.unique,data.shared=unique,shared -    end -    report(container,"stored",name) -    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%d]+","-")) -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -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 utf=unicode.utf8 -local format,serialize=string.format,table.serialize -local write_nl=texio.write_nl -local lower=string.lower -if not fontloader then fontloader=fontforge end -fontloader.totable=fontloader.to_table -fonts=fonts   or {} -fonts.ids=fonts.ids or {} fonts.identifiers=fonts.ids  -fonts.chr=fonts.chr or {} fonts.characters=fonts.chr  -fonts.qua=fonts.qua or {} fonts.quads=fonts.qua  -fonts.tfm=fonts.tfm or {} -fonts.mode='base' -fonts.private=0xF0000  -fonts.verbose=false  -fonts.ids[0]={  -  characters={}, -  descriptions={}, -  name="nullfont", -} -fonts.chr[0]={} -fonts.methods=fonts.methods or { -  base={ tfm={},afm={},otf={},vtf={},fix={} }, -  node={ tfm={},afm={},otf={},vtf={},fix={} }, -} -fonts.initializers=fonts.initializers or { -  base={ tfm={},afm={},otf={},vtf={},fix={} }, -  node={ tfm={},afm={},otf={},vtf={},fix={} } -} -fonts.triggers=fonts.triggers or { -  'mode', -  'language', -  'script', -  'strategy', -} -fonts.processors=fonts.processors or {} -fonts.manipulators=fonts.manipulators or {} -fonts.define=fonts.define         or {} -fonts.define.specify=fonts.define.specify     or {} -fonts.define.specify.synonyms=fonts.define.specify.synonyms or {} -if not fonts.color then -  fonts.color={ -    set=function() end, -    reset=function() end, -  } -end -fonts.formats={} -function fonts.fontformat(filename,default) -  local extname=lower(file.extname(filename)) -  local format=fonts.formats[extname] -  if format then -    return format -  else -    logs.report("fonts define","unable to determine font format for '%s'",filename) -    return default -  end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['node-dum']={ -  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" -} -nodes=nodes   or {} -fonts=fonts   or {} -attributes=attributes or {} -local traverse_id=node.traverse_id -local free_node=node.free -local remove_node=node.remove -local new_node=node.new -local glyph=node.id('glyph') -local fontdata=fonts.ids or {} -function nodes.simple_font_handler(head) -  head=nodes.process_characters(head) -  nodes.inject_kerns(head) -  nodes.protect_glyphs(head) -  head=node.ligaturing(head) -  head=node.kerning(head) -  return head -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","! purposed so setting them at the TeX end might break the font handler.") -  texio.write_nl("log","!") -  tex.attribute[0]=0  -end -nodes.protect_glyphs=node.protect_glyphs -nodes.unprotect_glyphs=node.unprotect_glyphs -function nodes.process_characters(head) -  local usedfonts,done,prevfont={},false,nil -  for n in traverse_id(glyph,head) do -    local font=n.font -    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 -              done=true -            end -          end -        end -      end -    end -  end -  if done then -    for font,processors in next,usedfonts do -      for i=1,#processors do -        local h,d=processors[i](head,font,0) -        head,done=h or head,done or d -      end -    end -  end -  return head,true -end -function nodes.kern(k) -  local n=new_node("kern",1) -  n.kern=k -  return n -end -function nodes.remove(head,current,free_too) -  local t=current -  head,current=remove_node(head,current) -  if t then -    if free_too then -      free_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 -nodes.before=node.insert_before -nodes.after=node.insert_after -attributes.unsetvalue=-0x7FFFFFFF -local numbers,last={},127 -function attributes.private(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 - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['node-inj']={ -  version=1.001, -  comment="companion to node-ini.mkiv", -  author="Hans Hagen, PRAGMA-ADE, Hasselt NL", -  copyright="PRAGMA ADE / ConTeXt Development Team", -  license="see context related readme files" -} -local next=next -local trace_injections=false trackers.register("nodes.injections",function(v) trace_injections=v end) -fonts=fonts   or {} -fonts.tfm=fonts.tfm or {} -fonts.ids=fonts.ids or {} -local fontdata=fonts.ids -local glyph=node.id('glyph') -local kern=node.id('kern') -local traverse_id=node.traverse_id -local unset_attribute=node.unset_attribute -local has_attribute=node.has_attribute -local set_attribute=node.set_attribute -local insert_node_before=node.insert_before -local insert_node_after=node.insert_after -local newkern=nodes.kern -local markbase=attributes.private('markbase') -local markmark=attributes.private('markmark') -local markdone=attributes.private('markdone') -local cursbase=attributes.private('cursbase') -local curscurs=attributes.private('curscurs') -local cursdone=attributes.private('cursdone') -local kernpair=attributes.private('kernpair') -local cursives={} -local marks={} -local kerns={} -function nodes.set_cursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext) -  local dx,dy=factor*(exit[1]-entry[1]),factor*(exit[2]-entry[2]) -  local ws,wn=tfmstart.width,tfmnext.width -  local bound=#cursives+1 -  set_attribute(start,cursbase,bound) -  set_attribute(nxt,curscurs,bound) -  cursives[bound]={ rlmode,dx,dy,ws,wn } -  return dx,dy,bound -end -function nodes.set_pair(current,factor,rlmode,r2lflag,spec,tfmchr) -  local x,y,w,h=factor*spec[1],factor*spec[2],factor*spec[3],factor*spec[4] -  if x~=0 or w~=0 or y~=0 or h~=0 then -    local bound=has_attribute(current,kernpair) -    if bound then -      local kb=kerns[bound] -      kb[2],kb[3],kb[4],kb[5]=(kb[2] or 0)+x,(kb[3] or 0)+y,(kb[4] or 0)+w,(kb[5] or 0)+h -    else -      bound=#kerns+1 -      set_attribute(current,kernpair,bound) -      kerns[bound]={ rlmode,x,y,w,h,r2lflag,tfmchr.width } -    end -    return x,y,w,h,bound -  end -  return x,y,w,h  -end -function nodes.set_kern(current,factor,rlmode,x,tfmchr) -  local dx=factor*x -  if dx~=0 then -    local bound=#kerns+1 -    set_attribute(current,kernpair,bound) -    kerns[bound]={ rlmode,dx } -    return dx,bound -  else -    return 0,0 -  end -end -function nodes.set_mark(start,base,factor,rlmode,ba,ma,index)  -  local dx,dy=factor*(ba[1]-ma[1]),factor*(ba[2]-ma[2]) -  local bound=has_attribute(base,markbase) -  if bound then -    local mb=marks[bound] -    if mb then -      if not index then index=#mb+1 end -      mb[index]={ dx,dy } -      set_attribute(start,markmark,bound) -      set_attribute(start,markdone,index) -      return dx,dy,bound -    else -      logs.report("nodes mark","possible problem, U+%04X is base without data (id: %s)",base.char,bound) -    end -  end -  index=index or 1 -  bound=#marks+1 -  set_attribute(base,markbase,bound) -  set_attribute(start,markmark,bound) -  set_attribute(start,markdone,index) -  marks[bound]={ [index]={ dx,dy,rlmode } } -  return dx,dy,bound -end -function nodes.trace_injection(head) -  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 report(...) -    logs.report("nodes finisher",...) -  end -  report("begin run") -  for n in traverse_id(glyph,head) do -    if n.subtype<256 then -      local kp=has_attribute(n,kernpair) -      local mb=has_attribute(n,markbase) -      local mm=has_attribute(n,markmark) -      local md=has_attribute(n,markdone) -      local cb=has_attribute(n,cursbase) -      local cc=has_attribute(n,curscurs) -      report("char U+%05X, font=%s",n.char,n.font) -      if kp then -        local k=kerns[kp] -        if k[3] then -          report("  pairkern: dir=%s, x=%s, y=%s, w=%s, h=%s",dir(k[1]),k[2] or "?",k[3] or "?",k[4] or "?",k[5] or "?") -        else -          report("  kern: dir=%s, dx=%s",dir(k[1]),k[2] or "?") -        end -      end -      if mb then -        report("  markbase: bound=%s",mb) -      end -      if mm then -        local m=marks[mm] -        if mb then -          local m=m[mb] -          if m then -            report("  markmark: bound=%s, index=%s, dx=%s, dy=%s",mm,md or "?",m[1] or "?",m[2] or "?") -          else -            report("  markmark: bound=%s, missing index",mm) -          end -        else -          m=m[1] -          report("  markmark: bound=%s, dx=%s, dy=%s",mm,m[1] or "?",m[2] or "?") -        end -      end -      if cb then -        report("  cursbase: bound=%s",cb) -      end -      if cc then -        local c=cursives[cc] -        report("  curscurs: bound=%s, dir=%s, dx=%s, dy=%s",cc,dir(c[1]),c[2] or "?",c[3] or "?") -      end -    end -  end -  report("end run") -end -function nodes.inject_kerns(head,where,keep) -  local has_marks,has_cursives,has_kerns=next(marks),next(cursives),next(kerns) -  if has_marks or has_cursives then -    if trace_injections then -      nodes.trace_injection(head) -    end -    local done,ky,rl,valid,cx,wx,mk=false,{},{},{},{},{},{} -    if has_kerns then  -      local nf,tm=nil,nil -      for n in traverse_id(glyph,head) do -        if n.subtype<256 then -          valid[#valid+1]=n -          if n.font~=nf then -            nf=n.font -            tm=fontdata[nf].marks -          end -          mk[n]=tm[n.char] -          local k=has_attribute(n,kernpair) -          if k then -            local kk=kerns[k] -            if kk then -              local x,y,w,h=kk[2] or 0,kk[3] or 0,kk[4] or 0,kk[5] or 0 -              local dy=y-h -              if dy~=0 then -                ky[n]=dy -              end -              if w~=0 or x~=0 then -                wx[n]=kk -              end -              rl[n]=kk[1]  -            end -          end -        end -      end -    else -      local nf,tm=nil,nil -      for n in traverse_id(glyph,head) do -        if n.subtype<256 then -          valid[#valid+1]=n -          if n.font~=nf then -            nf=n.font -            tm=fontdata[nf].marks -          end -          mk[n]=tm[n.char] -        end -      end -    end -    if #valid>0 then -      local cx={} -      if has_kerns and next(ky) then -        for n,k in next,ky do -          n.yoffset=k -        end -      end -      if has_cursives then -        local p_cursbase,p=nil,nil -        local t,d,maxt={},{},0 -        for i=1,#valid do  -          local n=valid[i] -          if not mk[n] then -            local n_cursbase=has_attribute(n,cursbase) -            if p_cursbase then -              local n_curscurs=has_attribute(n,curscurs) -              if p_cursbase==n_curscurs then -                local c=cursives[n_curscurs] -                if c then -                  local rlmode,dx,dy,ws,wn=c[1],c[2],c[3],c[4],c[5] -                  if rlmode>=0 then -                    dx=dx-ws -                  else -                    dx=dx+wn -                  end -                  if dx~=0 then -                    cx[n]=dx -                    rl[n]=rlmode -                  end -                    dy=-dy -                  maxt=maxt+1 -                  t[maxt]=p -                  d[maxt]=dy -                else -                  maxt=0 -                end -              end -            elseif maxt>0 then -              local ny=n.yoffset -              for i=maxt,1,-1 do -                ny=ny+d[i] -                local ti=t[i] -                ti.yoffset=ti.yoffset+ny -              end -              maxt=0 -            end -            if not n_cursbase and maxt>0 then -              local ny=n.yoffset -              for i=maxt,1,-1 do -                ny=ny+d[i] -                local ti=t[i] -                ti.yoffset=ny -              end -              maxt=0 -            end -            p_cursbase,p=n_cursbase,n -          end -        end -        if maxt>0 then -          local ny=n.yoffset -          for i=maxt,1,-1 do -            ny=ny+d[i] -            local ti=t[i] -            ti.yoffset=ny -          end -          maxt=0 -        end -        if not keep then -          cursives={} -        end -      end -      if has_marks then -        for i=1,#valid do -          local p=valid[i] -          local p_markbase=has_attribute(p,markbase) -          if p_markbase then -            local mrks=marks[p_markbase] -            for n in traverse_id(glyph,p.next) do -              local n_markmark=has_attribute(n,markmark) -              if p_markbase==n_markmark then -                local index=has_attribute(n,markdone) or 1 -                local d=mrks[index] -                if d then -                  local rlmode=d[3] -                  if rlmode and rlmode>0 then -                    local k=wx[p] -                    if k then  -                      n.xoffset=p.xoffset-(p.width-d[1])-k[2] -                    else -                      n.xoffset=p.xoffset-(p.width-d[1]) -                    end -                  else -                    local k=wx[p] -                    if k then -                      n.xoffset=p.xoffset-d[1]-k[2] -                    else -                      n.xoffset=p.xoffset-d[1] -                    end -                  end -                  if mk[p] then -                    n.yoffset=p.yoffset+d[2] -                  else -                    n.yoffset=n.yoffset+p.yoffset+d[2] -                  end -                end -              else -                break -              end -            end -          end -        end -        if not keep then -          marks={} -        end -      end -      if next(wx) then -        for n,k in next,wx do -          local rl,x,w,r2l=k[1],k[2] or 0,k[4] or 0,k[6] -          local wx=w-x -          if r2l then -            if wx~=0 then -              insert_node_before(head,n,newkern(wx)) -            end -            if x~=0 then -              insert_node_after (head,n,newkern(x)) -            end -          else -            if x~=0 then -              insert_node_before(head,n,newkern(x)) -            end -            if wx~=0 then -              insert_node_after(head,n,newkern(wx)) -            end -          end -        end -      end -      if next(cx) then -        for n,k in next,cx do -          if k~=0 then -            local rln=rl[n] -            if rln and rln<0 then -              insert_node_before(head,n,newkern(-k)) -            else -              insert_node_before(head,n,newkern(k)) -            end -          end -        end -      end -      if not keep then -        kerns={} -      end -      return head,true -    elseif not keep then -      kerns,cursives,marks={},{},{} -    end -  elseif has_kerns then -    if trace_injections then -      nodes.trace_injection(head) -    end -    for n in traverse_id(glyph,head) do -      if n.subtype<256 then -        local k=has_attribute(n,kernpair) -        if k then -          local kk=kerns[k] -          if kk then -            local rl,x,y,w=kk[1],kk[2] or 0,kk[3],kk[4] -            if y and y~=0 then -              n.yoffset=y  -            end -            if w then -              local r2l=kk[6] -              local wx=w-x -              if r2l then -                if wx~=0 then -                  insert_node_before(head,n,newkern(wx)) -                end -                if x~=0 then -                  insert_node_after (head,n,newkern(x)) -                end -              else -                if x~=0 then -                  insert_node_before(head,n,newkern(x)) -                end -                if wx~=0 then -                  insert_node_after(head,n,newkern(wx)) -                end -              end -            else -              if x~=0 then -                insert_node_before(head,n,newkern(x)) -              end -            end -          end -        end -      end -    end -    if not keep then -      kerns={} -    end -    return head,true -  else -  end -  return head,false -end - -end -- closure - -do -- begin closure to overcome local limits and interference - - -if not modules then modules={} end modules ['otfl-luat-att']={ -  version=math.pi/42, -  comment="companion to luaotfload.lua", -  author="Philipp Gesang", -  copyright="Luaotfload Development Team", -  license="GNU GPL v2" -} -function attributes.private(name) -  local attr="otfl@"..name -  local number=luatexbase.attributes[attr] -  if not number then -    number=luatexbase.new_attribute(attr) -  end -  return number -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -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 utf=unicode.utf8 -local next,format,match,lower,gsub=next,string.format,string.match,string.lower,string.gsub -local concat,sortedkeys,utfbyte,serialize=table.concat,table.sortedkeys,utf.byte,table.serialize -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) -fonts=fonts   or {} -fonts.tfm=fonts.tfm or {} -fonts.ids=fonts.ids or {} -local tfm=fonts.tfm -fonts.loaded=fonts.loaded  or {} -fonts.dontembed=fonts.dontembed or {} -fonts.triggers=fonts.triggers or {}  -fonts.initializers=fonts.initializers    or {} -fonts.initializers.common=fonts.initializers.common or {} -local fontdata=fonts.ids -local disc=node.id('disc') -local glyph=node.id('glyph') -local set_attribute=node.set_attribute -tfm.resolve_vf=true  -tfm.share_base_kerns=false  -tfm.mathactions={} -tfm.fontname_mode="fullpath" -tfm.enhance=tfm.enhance or function() end -fonts.formats.tfm="type1"  -function tfm.read_from_tfm(specification) -  local fname,tfmdata=specification.filename or "",nil -  if fname~="" then -    if trace_defining then -      logs.report("define font","loading tfm file %s at size %s",fname,specification.size) -    end -    tfmdata=font.read_tfm(fname,specification.size)  -    if tfmdata then -      tfmdata.descriptions=tfmdata.descriptions or {} -      if tfm.resolve_vf then -        fonts.logger.save(tfmdata,file.extname(fname),specification)  -        fname=resolvers.findbinfile(specification.name,'ovf') -        if fname and fname~="" then -          local vfdata=font.read_vf(fname,specification.size)  -          if vfdata then -            local chars=tfmdata.characters -            for k,v in next,vfdata.characters do -              chars[k].commands=v.commands -            end -            tfmdata.type='virtual' -            tfmdata.fonts=vfdata.fonts -          end -        end -      end -      tfm.enhance(tfmdata,specification) -    end -  elseif trace_defining then -    logs.report("define font","loading tfm with name %s fails",specification.name) -  end -  return tfmdata -end -local factors={ -  pt=65536.0, -  bp=65781.8, -} -function tfm.setfactor(f) -  tfm.factor=factors[f or 'pt'] or factors.pt -end -tfm.setfactor() -function tfm.scaled(scaledpoints,designsize)  -  if scaledpoints<0 then -    if designsize then -      if designsize>tfm.factor then  -        return (- scaledpoints/1000)*designsize  -      else -        return (- scaledpoints/1000)*designsize*tfm.factor -      end -    else -      return (- scaledpoints/1000)*10*tfm.factor -    end -  else -    return scaledpoints -  end -end -function tfm.get_virtual_id(tfmdata) -  if not tfmdata.fonts then -    tfmdata.type="virtual" -    tfmdata.fonts={ { id=0 } } -    return 1 -  else -    tfmdata.fonts[#tfmdata.fonts+1]={ id=0 } -    return #tfmdata.fonts -  end -end -function tfm.check_virtual_id(tfmdata,id) -  if tfmdata and tfmdata.type=="virtual" then -    if not tfmdata.fonts or #tfmdata.fonts==0 then -      tfmdata.type,tfmdata.fonts="real",nil -    else -      local vfonts=tfmdata.fonts -      for f=1,#vfonts do -        local fnt=vfonts[f] -        if fnt.id and fnt.id==0 then -          fnt.id=id -        end -      end -    end -  end -end -fonts.trace_scaling=false -local charactercache={} -function tfm.calculate_scale(tfmtable,scaledpoints,relativeid) -  if scaledpoints<0 then -    scaledpoints=(- scaledpoints/1000)*tfmtable.designsize  -  end -  local units=tfmtable.units or 1000 -  local delta=scaledpoints/units  -  return scaledpoints,delta,units -end -function tfm.do_scale(tfmtable,scaledpoints,relativeid) -  local t={}  -  local scaledpoints,delta,units=tfm.calculate_scale(tfmtable,scaledpoints,relativeid) -  t.units_per_em=units or 1000 -  local hdelta,vdelta=delta,delta -  for k,v in next,tfmtable do -    if type(v)=="table" then -    else -      t[k]=v -    end -  end -  local extend_factor=tfmtable.extend_factor or 0 -  if extend_factor~=0 and extend_factor~=1 then -    hdelta=hdelta*extend_factor -    t.extend=extend_factor*1000 -  else -    t.extend=1000 -  end -  local slant_factor=tfmtable.slant_factor or 0 -  if slant_factor~=0 then -    t.slant=slant_factor*1000 -  else -    t.slant=0 -  end -  local isvirtual=tfmtable.type=="virtual" or tfmtable.virtualized -  local hasmath=(tfmtable.math_parameters~=nil and next(tfmtable.math_parameters)~=nil) or (tfmtable.MathConstants~=nil and next(tfmtable.MathConstants)~=nil) -  local nodemode=tfmtable.mode=="node" -  local hasquality=tfmtable.auto_expand or tfmtable.auto_protrude -  local hasitalic=tfmtable.has_italic -  t.parameters={} -  t.characters={} -  t.MathConstants={} -  local descriptions=tfmtable.descriptions or {} -  t.unicodes=tfmtable.unicodes -  t.indices=tfmtable.indices -  t.marks=tfmtable.marks -t.goodies=tfmtable.goodies -t.colorscheme=tfmtable.colorscheme -  t.descriptions=descriptions -  if tfmtable.fonts then -    t.fonts=table.fastcopy(tfmtable.fonts)  -  end -  local tp=t.parameters -  local mp=t.math_parameters -  local tfmp=tfmtable.parameters -  tp.slant=(tfmp.slant     or tfmp[1] or 0) -  tp.space=(tfmp.space     or tfmp[2] or 0)*hdelta -  tp.space_stretch=(tfmp.space_stretch or tfmp[3] or 0)*hdelta -  tp.space_shrink=(tfmp.space_shrink or tfmp[4] or 0)*hdelta -  tp.x_height=(tfmp.x_height   or tfmp[5] or 0)*vdelta -  tp.quad=(tfmp.quad     or tfmp[6] or 0)*hdelta -  tp.extra_space=(tfmp.extra_space  or tfmp[7] or 0)*hdelta -  local protrusionfactor=(tp.quad~=0 and 1000/tp.quad) or 0 -  local tc=t.characters -  local characters=tfmtable.characters -  local nameneeded=not tfmtable.shared.otfdata  -  local changed=tfmtable.changed or {}  -  local ischanged=changed and next(changed) -  local indices=tfmtable.indices -  local luatex=tfmtable.luatex -  local tounicode=luatex and luatex.tounicode -  local defaultwidth=luatex and luatex.defaultwidth or 0 -  local defaultheight=luatex and luatex.defaultheight or 0 -  local defaultdepth=luatex and luatex.defaultdepth or 0 -  local scaledwidth=defaultwidth*hdelta -  local scaledheight=defaultheight*vdelta -  local scaleddepth=defaultdepth*vdelta -  local stackmath=tfmtable.ignore_stack_math~=true -  local private=fonts.private -  local sharedkerns={} -  for k,v in next,characters do -    local chr,description,index -    if ischanged then -      local c=changed[k] -      if c then -        description=descriptions[c] or v -        v=characters[c] or v -        index=(indices and indices[c]) or c -      else -        description=descriptions[k] or v -        index=(indices and indices[k]) or k -      end -    else -      description=descriptions[k] or v -      index=(indices and indices[k]) or k -    end -    local width=description.width -    local height=description.height -    local depth=description.depth -    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 nameneeded then -        chr={ -          name=description.name, -          index=index, -          height=height, -          depth=depth, -          width=width, -        } -      else -        chr={ -          index=index, -          height=height, -          depth=depth, -          width=width, -        } -      end -    else -      if nameneeded then -        chr={ -          name=description.name, -          index=index, -          height=height, -          width=width, -        } -      else -        chr={ -          index=index, -          height=height, -          width=width, -        } -      end -    end -    if tounicode then -      local tu=tounicode[index]  -      if tu then -        chr.tounicode=tu -      end -    end -    if hasquality then -      local ve=v.expansion_factor -      if ve then -        chr.expansion_factor=ve*1000  -      end -      local vl=v.left_protruding -      if vl then -        chr.left_protruding=protrusionfactor*width*vl -      end -      local vr=v.right_protruding -      if vr then -        chr.right_protruding=protrusionfactor*width*vr -      end -    end -    if hasitalic then -      local vi=description.italic or v.italic -      if vi and vi~=0 then -        chr.italic=vi*hdelta -      end -    end -    if hasmath then -      local vn=v.next -      if vn then -        chr.next=vn -      else -        local vv=v.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=v.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 vt=description.top_accent -      if vt then -        chr.top_accent=vdelta*vt -      end -      if stackmath then -        local mk=v.mathkerns -        if mk then -          local kerns={} -          local v=mk.top_right  if v then local k={} for i=1,#v do local vi=v[i] -            k[i]={ height=vdelta*vi.height,kern=vdelta*vi.kern } -          end   kerns.top_right=k end -          local v=mk.top_left   if v then local k={} for i=1,#v do local vi=v[i] -            k[i]={ height=vdelta*vi.height,kern=vdelta*vi.kern } -          end   kerns.top_left=k end -          local v=mk.bottom_left if v then local k={} for i=1,#v do local vi=v[i] -            k[i]={ height=vdelta*vi.height,kern=vdelta*vi.kern } -          end   kerns.bottom_left=k end -          local v=mk.bottom_right if v then local k={} for i=1,#v do local vi=v[i] -            k[i]={ height=vdelta*vi.height,kern=vdelta*vi.kern } -          end   kerns.bottom_right=k end -          chr.mathkern=kerns  -        end -      end -    end -    if not nodemode then -      local vk=v.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 -      local vl=v.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=v.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[#tt+1]={ key,ivc[2]*hdelta } -            elseif key=="down" then -              tt[#tt+1]={ key,ivc[2]*vdelta } -            elseif key=="rule" then -              tt[#tt+1]={ key,ivc[2]*vdelta,ivc[3]*hdelta } -            else  -              tt[#tt+1]=ivc  -            end -          end -          chr.commands=tt -        else -          chr.commands=vc -        end -      end -    end -    tc[k]=chr -  end -  t.size=scaledpoints -  t.factor=delta -  t.hfactor=hdelta -  t.vfactor=vdelta -  if t.fonts then -    t.fonts=table.fastcopy(t.fonts)  -  end -  if hasmath then -    local ma=tfm.mathactions -    for i=1,#ma do -      ma[i](t,tfmtable,delta,hdelta,vdelta)  -    end -  end -  local tpx=tp.x_height -  if hasmath then -    if not tp[13] then tp[13]=.86*tpx end  -    if not tp[14] then tp[14]=.86*tpx end  -    if not tp[15] then tp[15]=.86*tpx end  -    if not tp[16] then tp[16]=.48*tpx end  -    if not tp[17] then tp[17]=.48*tpx end  -    if not tp[22] then tp[22]=0   end  -    if t.MathConstants then t.MathConstants.AccentBaseHeight=nil end  -  end -  t.tounicode=1 -  t.cidinfo=tfmtable.cidinfo -  if hasmath then -    if trace_defining then -      logs.report("define font","math enabled for: name '%s', fullname: '%s', filename: '%s'",t.name or "noname",t.fullname or "nofullname",t.filename or "nofilename") -    end -  else -    if trace_defining then -      logs.report("define font","math disabled for: name '%s', fullname: '%s', filename: '%s'",t.name or "noname",t.fullname or "nofullname",t.filename or "nofilename") -    end -    t.nomath,t.MathConstants=true,nil -  end -  if not t.psname then -    t.psname=t.fontname or (t.fullname and fonts.names.cleanname(t.fullname)) -  end -  if trace_defining then -    logs.report("define font","used for accesing subfont: '%s'",t.psname or "nopsname") -    logs.report("define font","used for subsetting: '%s'",t.fontname or "nofontname") -  end -  return t,delta -end -tfm.auto_cleanup=true -local lastfont=nil -function tfm.cleanup_table(tfmdata)  -  if tfm.auto_cleanup then  -    if tfmdata.type=='virtual' or tfmdata.virtualized then -      for k,v in next,tfmdata.characters do -        if v.commands then v.commands=nil end -      end -    else -    end -  end -end -function tfm.cleanup(tfmdata)  -end -function tfm.scale(tfmtable,scaledpoints,relativeid) -  local t,factor=tfm.do_scale(tfmtable,scaledpoints,relativeid) -  t.factor=factor -  t.ascender=factor*(tfmtable.ascender or 0) -  t.descender=factor*(tfmtable.descender or 0) -  t.shared=tfmtable.shared or {} -  t.unique=table.fastcopy(tfmtable.unique or {}) -  tfm.cleanup(t) -  return t -end -fonts.analyzers=fonts.analyzers       or {} -fonts.analyzers.aux=fonts.analyzers.aux     or {} -fonts.analyzers.methods=fonts.analyzers.methods   or {} -fonts.analyzers.initializers=fonts.analyzers.initializers or {} -local state=attributes.private('state') -function fonts.analyzers.aux.setstate(head,font) -  local tfmdata=fontdata[font] -  local characters=tfmdata.characters -  local descriptions=tfmdata.descriptions -  local first,last,current,n,done=nil,nil,head,0,false  -  while current do -    local id=current.id -    if id==glyph and current.font==font then -      local d=descriptions[current.char] -      if d then -        if d.class=="mark" then -          done=true -          set_attribute(current,state,5)  -        elseif n==0 then -          first,last,n=current,current,1 -          set_attribute(current,state,1)  -        else -          last,n=current,n+1 -          set_attribute(current,state,2)  -        end -      else  -        if first and first==last then -          set_attribute(last,state,4)  -        elseif last then -          set_attribute(last,state,3)  -        end -        first,last,n=nil,nil,0 -      end -    elseif id==disc then -      set_attribute(current,state,2)  -      last=current -    else  -      if first and first==last then -        set_attribute(last,state,4)  -      elseif last then -        set_attribute(last,state,3)  -      end -      first,last,n=nil,nil,0 -    end -    current=current.next -  end -  if first and first==last then -    set_attribute(last,state,4)  -  elseif last then -    set_attribute(last,state,3)  -  end -  return head,done -end -function tfm.replacements(tfm,value) -  tfm.characters[0x0027]=tfm.characters[0x2019] -end -function tfm.checked_filename(metadata,whatever) -  local foundfilename=metadata.foundfilename -  if not foundfilename then -    local askedfilename=metadata.filename or "" -    if askedfilename~="" then -      foundfilename=resolvers.findbinfile(askedfilename,"") or "" -      if foundfilename=="" then -        logs.report("fonts","source file '%s' is not found",askedfilename) -        foundfilename=resolvers.findbinfile(file.basename(askedfilename),"") or "" -        if foundfilename~="" then -          logs.report("fonts","using source file '%s' (cache mismatch)",foundfilename) -        end -      end -    elseif whatever then -      logs.report("fonts","no source file for '%s'",whatever) -      foundfilename="" -    end -    metadata.foundfilename=foundfilename -  end -  return foundfilename -end -statistics.register("fonts load time",function() -  return statistics.elapsedseconds(fonts) -end) - -end -- closure - -do -- begin closure to overcome local limits and interference - -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 lpegmatch=lpeg.match -local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end) -fonts=fonts     or {} -fonts.cid=fonts.cid   or {} -fonts.cid.map=fonts.cid.map or {} -fonts.cid.max=fonts.cid.max or 10 -local number=lpeg.C(lpeg.R("09","af","AF")^1) -local space=lpeg.S(" \n\r\t") -local spaces=space^0 -local period=lpeg.P(".") -local periods=period*period -local name=lpeg.P("/")*lpeg.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=lpeg.P { "start", -  start=number*spaces*number*lpeg.V("series"), -  series=(spaces*(lpeg.V("one")+lpeg.V("range")+lpeg.V("named")) )^1, -  one=(number*spaces*number)/do_one, -  range=(number*periods*number*spaces*number)/do_range, -  named=(number*spaces*name)/do_name -} -function fonts.cid.load(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 -    } -  else -    return nil -  end -end -local template="%s-%s-%s.cidmap" -local function locate(registry,ordering,supplement) -  local filename=format(template,registry,ordering,supplement) -  local hashname=lower(filename) -  local cidmap=fonts.cid.map[hashname] -  if not cidmap then -    if trace_loading then -      logs.report("load otf","checking cidmap, registry: %s, ordering: %s, supplement: %s, filename: %s",registry,ordering,supplement,filename) -    end -    local fullname=resolvers.find_file(filename,'cid') or "" -    if fullname~="" then -      cidmap=fonts.cid.load(fullname) -      if cidmap then -        if trace_loading then -          logs.report("load otf","using cidmap file %s",filename) -        end -        fonts.cid.map[hashname]=cidmap -        cidmap.usedname=file.basename(filename) -        return cidmap -      end -    end -  end -  return cidmap -end -function fonts.cid.getmap(registry,ordering,supplement) -  local supplement=tonumber(supplement) -  if trace_loading then -    logs.report("load otf","needed cidmap, registry: %s, ordering: %s, supplement: %s",registry,ordering,supplement) -  end -  local cidmap=locate(registry,ordering,supplement) -  if not cidmap then -    local cidnum=nil -    if supplement<fonts.cid.max then -      for supplement=supplement+1,fonts.cid.max do -        local c=locate(registry,ordering,supplement) -        if c then -          cidmap,cidnum=c,supplement -          break -        end -      end -    end -    if not cidmap and supplement>0 then -      for supplement=supplement-1,0,-1 do -        local c=locate(registry,ordering,supplement) -        if c then -          cidmap,cidnum=c,supplement -          break -        end -      end -    end -    if cidmap and cidnum>0 then -      for s=0,cidnum-1 do -        filename=format(template,registry,ordering,s) -        if not fonts.cid.map[filename] then -          fonts.cid.map[filename]=cidmap  -        end -      end -    end -  end -  return cidmap -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-otf']={ -  version=1.001, -  comment="companion to font-otf.lua (tables)", -  author="Hans Hagen, PRAGMA-ADE, Hasselt NL", -  copyright="PRAGMA ADE / ConTeXt Development Team", -  license="see context related readme files" -} -local type,next,tonumber,tostring=type,next,tonumber,tostring -local gsub,lower=string.gsub,string.lower -fonts=fonts   or {} -fonts.otf=fonts.otf or {} -local otf=fonts.otf -otf.tables=otf.tables  or {} -otf.meanings=otf.meanings or {} -otf.tables.scripts={ -  ['dflt']='Default', -  ['arab']='Arabic', -  ['armn']='Armenian', -  ['bali']='Balinese', -  ['beng']='Bengali', -  ['bopo']='Bopomofo', -  ['brai']='Braille', -  ['bugi']='Buginese', -  ['buhd']='Buhid', -  ['byzm']='Byzantine Music', -  ['cans']='Canadian Syllabics', -  ['cher']='Cherokee', -  ['copt']='Coptic', -  ['cprt']='Cypriot Syllabary', -  ['cyrl']='Cyrillic', -  ['deva']='Devanagari', -  ['dsrt']='Deseret', -  ['ethi']='Ethiopic', -  ['geor']='Georgian', -  ['glag']='Glagolitic', -  ['goth']='Gothic', -  ['grek']='Greek', -  ['gujr']='Gujarati', -  ['guru']='Gurmukhi', -  ['hang']='Hangul', -  ['hani']='CJK Ideographic', -  ['hano']='Hanunoo', -  ['hebr']='Hebrew', -  ['ital']='Old Italic', -  ['jamo']='Hangul Jamo', -  ['java']='Javanese', -  ['kana']='Hiragana and Katakana', -  ['khar']='Kharosthi', -  ['khmr']='Khmer', -  ['knda']='Kannada', -  ['lao' ]='Lao', -  ['latn']='Latin', -  ['limb']='Limbu', -  ['linb']='Linear B', -  ['math']='Mathematical Alphanumeric Symbols', -  ['mlym']='Malayalam', -  ['mong']='Mongolian', -  ['musc']='Musical Symbols', -  ['mymr']='Myanmar', -  ['nko' ]="N'ko", -  ['ogam']='Ogham', -  ['orya']='Oriya', -  ['osma']='Osmanya', -  ['phag']='Phags-pa', -  ['phnx']='Phoenician', -  ['runr']='Runic', -  ['shaw']='Shavian', -  ['sinh']='Sinhala', -  ['sylo']='Syloti Nagri', -  ['syrc']='Syriac', -  ['tagb']='Tagbanwa', -  ['tale']='Tai Le', -  ['talu']='Tai Lu', -  ['taml']='Tamil', -  ['telu']='Telugu', -  ['tfng']='Tifinagh', -  ['tglg']='Tagalog', -  ['thaa']='Thaana', -  ['thai']='Thai', -  ['tibt']='Tibetan', -  ['ugar']='Ugaritic Cuneiform', -  ['xpeo']='Old Persian Cuneiform', -  ['xsux']='Sumero-Akkadian Cuneiform', -  ['yi' ]='Yi', -} -otf.tables.languages={ -  ['dflt']='Default', -  ['aba']='Abaza', -  ['abk']='Abkhazian', -  ['ady']='Adyghe', -  ['afk']='Afrikaans', -  ['afr']='Afar', -  ['agw']='Agaw', -  ['als']='Alsatian', -  ['alt']='Altai', -  ['amh']='Amharic', -  ['ara']='Arabic', -  ['ari']='Aari', -  ['ark']='Arakanese', -  ['asm']='Assamese', -  ['ath']='Athapaskan', -  ['avr']='Avar', -  ['awa']='Awadhi', -  ['aym']='Aymara', -  ['aze']='Azeri', -  ['bad']='Badaga', -  ['bag']='Baghelkhandi', -  ['bal']='Balkar', -  ['bau']='Baule', -  ['bbr']='Berber', -  ['bch']='Bench', -  ['bcr']='Bible Cree', -  ['bel']='Belarussian', -  ['bem']='Bemba', -  ['ben']='Bengali', -  ['bgr']='Bulgarian', -  ['bhi']='Bhili', -  ['bho']='Bhojpuri', -  ['bik']='Bikol', -  ['bil']='Bilen', -  ['bkf']='Blackfoot', -  ['bli']='Balochi', -  ['bln']='Balante', -  ['blt']='Balti', -  ['bmb']='Bambara', -  ['bml']='Bamileke', -  ['bos']='Bosnian', -  ['bre']='Breton', -  ['brh']='Brahui', -  ['bri']='Braj Bhasha', -  ['brm']='Burmese', -  ['bsh']='Bashkir', -  ['bti']='Beti', -  ['cat']='Catalan', -  ['ceb']='Cebuano', -  ['che']='Chechen', -  ['chg']='Chaha Gurage', -  ['chh']='Chattisgarhi', -  ['chi']='Chichewa', -  ['chk']='Chukchi', -  ['chp']='Chipewyan', -  ['chr']='Cherokee', -  ['chu']='Chuvash', -  ['cmr']='Comorian', -  ['cop']='Coptic', -  ['cos']='Corsican', -  ['cre']='Cree', -  ['crr']='Carrier', -  ['crt']='Crimean Tatar', -  ['csl']='Church Slavonic', -  ['csy']='Czech', -  ['dan']='Danish', -  ['dar']='Dargwa', -  ['dcr']='Woods Cree', -  ['deu']='German', -  ['dgr']='Dogri', -  ['div']='Divehi', -  ['djr']='Djerma', -  ['dng']='Dangme', -  ['dnk']='Dinka', -  ['dri']='Dari', -  ['dun']='Dungan', -  ['dzn']='Dzongkha', -  ['ebi']='Ebira', -  ['ecr']='Eastern Cree', -  ['edo']='Edo', -  ['efi']='Efik', -  ['ell']='Greek', -  ['eng']='English', -  ['erz']='Erzya', -  ['esp']='Spanish', -  ['eti']='Estonian', -  ['euq']='Basque', -  ['evk']='Evenki', -  ['evn']='Even', -  ['ewe']='Ewe', -  ['fan']='French Antillean', -  ['far']='Farsi', -  ['fin']='Finnish', -  ['fji']='Fijian', -  ['fle']='Flemish', -  ['fne']='Forest Nenets', -  ['fon']='Fon', -  ['fos']='Faroese', -  ['fra']='French', -  ['fri']='Frisian', -  ['frl']='Friulian', -  ['fta']='Futa', -  ['ful']='Fulani', -  ['gad']='Ga', -  ['gae']='Gaelic', -  ['gag']='Gagauz', -  ['gal']='Galician', -  ['gar']='Garshuni', -  ['gaw']='Garhwali', -  ['gez']="Ge'ez", -  ['gil']='Gilyak', -  ['gmz']='Gumuz', -  ['gon']='Gondi', -  ['grn']='Greenlandic', -  ['gro']='Garo', -  ['gua']='Guarani', -  ['guj']='Gujarati', -  ['hai']='Haitian', -  ['hal']='Halam', -  ['har']='Harauti', -  ['hau']='Hausa', -  ['haw']='Hawaiin', -  ['hbn']='Hammer-Banna', -  ['hil']='Hiligaynon', -  ['hin']='Hindi', -  ['hma']='High Mari', -  ['hnd']='Hindko', -  ['ho']='Ho', -  ['hri']='Harari', -  ['hrv']='Croatian', -  ['hun']='Hungarian', -  ['hye']='Armenian', -  ['ibo']='Igbo', -  ['ijo']='Ijo', -  ['ilo']='Ilokano', -  ['ind']='Indonesian', -  ['ing']='Ingush', -  ['inu']='Inuktitut', -  ['iri']='Irish', -  ['irt']='Irish Traditional', -  ['isl']='Icelandic', -  ['ism']='Inari Sami', -  ['ita']='Italian', -  ['iwr']='Hebrew', -  ['jan']='Japanese', -  ['jav']='Javanese', -  ['jii']='Yiddish', -  ['jud']='Judezmo', -  ['jul']='Jula', -  ['kab']='Kabardian', -  ['kac']='Kachchi', -  ['kal']='Kalenjin', -  ['kan']='Kannada', -  ['kar']='Karachay', -  ['kat']='Georgian', -  ['kaz']='Kazakh', -  ['keb']='Kebena', -  ['kge']='Khutsuri Georgian', -  ['kha']='Khakass', -  ['khk']='Khanty-Kazim', -  ['khm']='Khmer', -  ['khs']='Khanty-Shurishkar', -  ['khv']='Khanty-Vakhi', -  ['khw']='Khowar', -  ['kik']='Kikuyu', -  ['kir']='Kirghiz', -  ['kis']='Kisii', -  ['kkn']='Kokni', -  ['klm']='Kalmyk', -  ['kmb']='Kamba', -  ['kmn']='Kumaoni', -  ['kmo']='Komo', -  ['kms']='Komso', -  ['knr']='Kanuri', -  ['kod']='Kodagu', -  ['koh']='Korean Old Hangul', -  ['kok']='Konkani', -  ['kon']='Kikongo', -  ['kop']='Komi-Permyak', -  ['kor']='Korean', -  ['koz']='Komi-Zyrian', -  ['kpl']='Kpelle', -  ['kri']='Krio', -  ['krk']='Karakalpak', -  ['krl']='Karelian', -  ['krm']='Karaim', -  ['krn']='Karen', -  ['krt']='Koorete', -  ['ksh']='Kashmiri', -  ['ksi']='Khasi', -  ['ksm']='Kildin Sami', -  ['kui']='Kui', -  ['kul']='Kulvi', -  ['kum']='Kumyk', -  ['kur']='Kurdish', -  ['kuu']='Kurukh', -  ['kuy']='Kuy', -  ['kyk']='Koryak', -  ['lad']='Ladin', -  ['lah']='Lahuli', -  ['lak']='Lak', -  ['lam']='Lambani', -  ['lao']='Lao', -  ['lat']='Latin', -  ['laz']='Laz', -  ['lcr']='L-Cree', -  ['ldk']='Ladakhi', -  ['lez']='Lezgi', -  ['lin']='Lingala', -  ['lma']='Low Mari', -  ['lmb']='Limbu', -  ['lmw']='Lomwe', -  ['lsb']='Lower Sorbian', -  ['lsm']='Lule Sami', -  ['lth']='Lithuanian', -  ['ltz']='Luxembourgish', -  ['lub']='Luba', -  ['lug']='Luganda', -  ['luh']='Luhya', -  ['luo']='Luo', -  ['lvi']='Latvian', -  ['maj']='Majang', -  ['mak']='Makua', -  ['mal']='Malayalam Traditional', -  ['man']='Mansi', -  ['map']='Mapudungun', -  ['mar']='Marathi', -  ['maw']='Marwari', -  ['mbn']='Mbundu', -  ['mch']='Manchu', -  ['mcr']='Moose Cree', -  ['mde']='Mende', -  ['men']="Me'en", -  ['miz']='Mizo', -  ['mkd']='Macedonian', -  ['mle']='Male', -  ['mlg']='Malagasy', -  ['mln']='Malinke', -  ['mlr']='Malayalam Reformed', -  ['mly']='Malay', -  ['mnd']='Mandinka', -  ['mng']='Mongolian', -  ['mni']='Manipuri', -  ['mnk']='Maninka', -  ['mnx']='Manx Gaelic', -  ['moh']='Mohawk', -  ['mok']='Moksha', -  ['mol']='Moldavian', -  ['mon']='Mon', -  ['mor']='Moroccan', -  ['mri']='Maori', -  ['mth']='Maithili', -  ['mts']='Maltese', -  ['mun']='Mundari', -  ['nag']='Naga-Assamese', -  ['nan']='Nanai', -  ['nas']='Naskapi', -  ['ncr']='N-Cree', -  ['ndb']='Ndebele', -  ['ndg']='Ndonga', -  ['nep']='Nepali', -  ['new']='Newari', -  ['ngr']='Nagari', -  ['nhc']='Norway House Cree', -  ['nis']='Nisi', -  ['niu']='Niuean', -  ['nkl']='Nkole', -  ['nko']="N'ko", -  ['nld']='Dutch', -  ['nog']='Nogai', -  ['nor']='Norwegian', -  ['nsm']='Northern Sami', -  ['nta']='Northern Tai', -  ['nto']='Esperanto', -  ['nyn']='Nynorsk', -  ['oci']='Occitan', -  ['ocr']='Oji-Cree', -  ['ojb']='Ojibway', -  ['ori']='Oriya', -  ['oro']='Oromo', -  ['oss']='Ossetian', -  ['paa']='Palestinian Aramaic', -  ['pal']='Pali', -  ['pan']='Punjabi', -  ['pap']='Palpa', -  ['pas']='Pashto', -  ['pgr']='Polytonic Greek', -  ['pil']='Pilipino', -  ['plg']='Palaung', -  ['plk']='Polish', -  ['pro']='Provencal', -  ['ptg']='Portuguese', -  ['qin']='Chin', -  ['raj']='Rajasthani', -  ['rbu']='Russian Buriat', -  ['rcr']='R-Cree', -  ['ria']='Riang', -  ['rms']='Rhaeto-Romanic', -  ['rom']='Romanian', -  ['roy']='Romany', -  ['rsy']='Rusyn', -  ['rua']='Ruanda', -  ['rus']='Russian', -  ['sad']='Sadri', -  ['san']='Sanskrit', -  ['sat']='Santali', -  ['say']='Sayisi', -  ['sek']='Sekota', -  ['sel']='Selkup', -  ['sgo']='Sango', -  ['shn']='Shan', -  ['sib']='Sibe', -  ['sid']='Sidamo', -  ['sig']='Silte Gurage', -  ['sks']='Skolt Sami', -  ['sky']='Slovak', -  ['sla']='Slavey', -  ['slv']='Slovenian', -  ['sml']='Somali', -  ['smo']='Samoan', -  ['sna']='Sena', -  ['snd']='Sindhi', -  ['snh']='Sinhalese', -  ['snk']='Soninke', -  ['sog']='Sodo Gurage', -  ['sot']='Sotho', -  ['sqi']='Albanian', -  ['srb']='Serbian', -  ['srk']='Saraiki', -  ['srr']='Serer', -  ['ssl']='South Slavey', -  ['ssm']='Southern Sami', -  ['sur']='Suri', -  ['sva']='Svan', -  ['sve']='Swedish', -  ['swa']='Swadaya Aramaic', -  ['swk']='Swahili', -  ['swz']='Swazi', -  ['sxt']='Sutu', -  ['syr']='Syriac', -  ['tab']='Tabasaran', -  ['taj']='Tajiki', -  ['tam']='Tamil', -  ['tat']='Tatar', -  ['tcr']='TH-Cree', -  ['tel']='Telugu', -  ['tgn']='Tongan', -  ['tgr']='Tigre', -  ['tgy']='Tigrinya', -  ['tha']='Thai', -  ['tht']='Tahitian', -  ['tib']='Tibetan', -  ['tkm']='Turkmen', -  ['tmn']='Temne', -  ['tna']='Tswana', -  ['tne']='Tundra Nenets', -  ['tng']='Tonga', -  ['tod']='Todo', -  ['trk']='Turkish', -  ['tsg']='Tsonga', -  ['tua']='Turoyo Aramaic', -  ['tul']='Tulu', -  ['tuv']='Tuvin', -  ['twi']='Twi', -  ['udm']='Udmurt', -  ['ukr']='Ukrainian', -  ['urd']='Urdu', -  ['usb']='Upper Sorbian', -  ['uyg']='Uyghur', -  ['uzb']='Uzbek', -  ['ven']='Venda', -  ['vit']='Vietnamese', -  ['wa' ]='Wa', -  ['wag']='Wagdi', -  ['wcr']='West-Cree', -  ['wel']='Welsh', -  ['wlf']='Wolof', -  ['xbd']='Tai Lue', -  ['xhs']='Xhosa', -  ['yak']='Yakut', -  ['yba']='Yoruba', -  ['ycr']='Y-Cree', -  ['yic']='Yi Classic', -  ['yim']='Yi Modern', -  ['zhh']='Chinese Hong Kong', -  ['zhp']='Chinese Phonetic', -  ['zhs']='Chinese Simplified', -  ['zht']='Chinese Traditional', -  ['znd']='Zande', -  ['zul']='Zulu' -} -otf.tables.features={ -  ['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', -  ['cjct']='Conjunct Forms', -  ['clig']='Contextual Ligatures', -  ['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', -  ['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', -  ['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', -  ['rkrf']='Rakar Forms', -  ['rlig']='Required Ligatures', -  ['rphf']='Reph Form', -  ['rtbd']='Right Bounds', -  ['rtla']='Right-To-Left Alternates', -  ['rtlm']='Right To Left Math', -  ['ruby']='Ruby Notation Forms', -  ['salt']='Stylistic Alternates', -  ['sinf']='Scientific Inferiors', -  ['size']='Optical Size', -  ['smcp']='Small Capitals', -  ['smpl']='Simplified Forms', -  ['ss01']='Stylistic Set 1', -  ['ss02']='Stylistic Set 2', -  ['ss03']='Stylistic Set 3', -  ['ss04']='Stylistic Set 4', -  ['ss05']='Stylistic Set 5', -  ['ss06']='Stylistic Set 6', -  ['ss07']='Stylistic Set 7', -  ['ss08']='Stylistic Set 8', -  ['ss09']='Stylistic Set 9', -  ['ss10']='Stylistic Set 10', -  ['ss11']='Stylistic Set 11', -  ['ss12']='Stylistic Set 12', -  ['ss13']='Stylistic Set 13', -  ['ss14']='Stylistic Set 14', -  ['ss15']='Stylistic Set 15', -  ['ss16']='Stylistic Set 16', -  ['ss17']='Stylistic Set 17', -  ['ss18']='Stylistic Set 18', -  ['ss19']='Stylistic Set 19', -  ['ss20']='Stylistic Set 20', -  ['ssty']='Script Style', -  ['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', -} -otf.tables.baselines={ -  ['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']='Mathmatical centered baseline', -  ['romn']='Roman baseline' -} -function otf.tables.to_tag(id) -  return stringformat("%4s",lower(id)) -end -local function resolve(tab,id) -  if tab and id then -    id=lower(id) -    return tab[id] or tab[gsub(id," ","")] or tab['dflt'] or '' -  else -    return "unknown" -  end -end -function otf.meanings.script(id) -  return resolve(otf.tables.scripts,id) -end -function otf.meanings.language(id) -  return resolve(otf.tables.languages,id) -end -function otf.meanings.feature(id) -  return resolve(otf.tables.features,id) -end -function otf.meanings.baseline(id) -  return resolve(otf.tables.baselines,id) -end -otf.tables.to_scripts=table.reverse_hash(otf.tables.scripts ) -otf.tables.to_languages=table.reverse_hash(otf.tables.languages) -otf.tables.to_features=table.reverse_hash(otf.tables.features ) -local scripts=otf.tables.scripts -local languages=otf.tables.languages -local features=otf.tables.features -local to_scripts=otf.tables.to_scripts -local to_languages=otf.tables.to_languages -local to_features=otf.tables.to_features -for k,v in next,to_features do -  local stripped=gsub(k,"%-"," ") -  to_features[stripped]=v -  local stripped=gsub(k,"[^a-zA-Z0-9]","") -  to_features[stripped]=v -end -for k,v in next,to_features do -  to_features[lower(k)]=v -end -otf.meanings.checkers={ -  rand=function(v) -    return v and "random" -  end -} -local checkers=otf.meanings.checkers -function otf.meanings.normalize(features) -  local h={} -  for k,v in next,features do -    k=lower(k) -    if k=="language" or k=="lang" then -      v=gsub(lower(v),"[^a-z0-9%-]","") -      if not languages[v] then -        h.language=to_languages[v] or "dflt" -      else -        h.language=v -      end -    elseif k=="script" then -      v=gsub(lower(v),"[^a-z0-9%-]","") -      if not scripts[v] then -        h.script=to_scripts[v] or "dflt" -      else -        h.script=v -      end -    else -      if type(v)=="string" then -        local b=v:is_boolean() -        if type(b)=="nil" then -          v=tonumber(v) or lower(v) -        else -          v=b -        end -      end -      k=to_features[k] or k -      local c=checkers[k] -      h[k]=c and c(v) or v -    end -  end -  return h -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -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 utf=unicode.utf8 -local match,format,find,concat,gsub,lower=string.match,string.format,string.find,table.concat,string.gsub,string.lower -local lpegmatch=lpeg.match -local utfbyte=utf.byte -local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end) -local trace_unimapping=false trackers.register("otf.unimapping",function(v) trace_unimapping=v end) -local ctxcatcodes=tex and tex.ctxcatcodes -fonts=fonts   or {} -fonts.map=fonts.map or {} -local function load_lum_table(filename)  -  local lumname=file.replacesuffix(file.basename(filename),"lum") -  local lumfile=resolvers.find_file(lumname,"map") or "" -  if lumfile~="" and lfs.isfile(lumfile) then -    if trace_loading or trace_unimapping then -      logs.report("load otf","enhance: loading %s ",lumfile) -    end -    lumunic=dofile(lumfile) -    return lumunic,lumfile -  end -end -local hex=lpeg.R("AF","09") -local hexfour=(hex*hex*hex*hex)/function(s) return tonumber(s,16) end -local hexsix=(hex^1)/function(s) return tonumber(s,16) end -local dec=(lpeg.R("09")^1)/tonumber -local period=lpeg.P(".") -local unicode=lpeg.P("uni")*(hexfour*(period+lpeg.P(-1))*lpeg.Cc(false)+lpeg.Ct(hexfour^1)*lpeg.Cc(true)) -local ucode=lpeg.P("u")*(hexsix*(period+lpeg.P(-1))*lpeg.Cc(false)+lpeg.Ct(hexsix^1)*lpeg.Cc(true)) -local index=lpeg.P("index")*dec*lpeg.Cc(false) -local parser=unicode+ucode+index -local parsers={} -local function make_name_parser(str) -  if not str or str=="" then -    return parser -  else -    local p=parsers[str] -    if not p then -      p=lpeg.P(str)*period*dec*lpeg.Cc(false) -      parsers[str]=p -    end -    return p -  end -end -local function tounicode16(unicode) -  if unicode<0x10000 then -    return format("%04X",unicode) -  else -    return format("%04X%04X",unicode/1024+0xD800,unicode%1024+0xDC00) -  end -end -local function tounicode16sequence(unicodes) -  local t={} -  for l=1,#unicodes do -    local unicode=unicodes[l] -    if unicode<0x10000 then -      t[l]=format("%04X",unicode) -    else -      t[l]=format("%04X%04X",unicode/1024+0xD800,unicode%1024+0xDC00) -    end -  end -  return concat(t) -end -fonts.map.load_lum_table=load_lum_table -fonts.map.make_name_parser=make_name_parser -fonts.map.tounicode16=tounicode16 -fonts.map.tounicode16sequence=tounicode16sequence -local separator=lpeg.S("_.") -local other=lpeg.C((1-separator)^1) -local ligsplitter=lpeg.Ct(other*(separator*other)^0) -fonts.map.add_to_unicode=function(data,filename) -  local unicodes=data.luatex and data.luatex.unicodes -  if not unicodes then -    return -  end -  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 tounicode,originals,ns,nl,private,unknown={},{},0,0,fonts.private,format("%04X",utfbyte("?")) -  data.luatex.tounicode,data.luatex.originals=tounicode,originals -  local lumunic,uparser,oparser -  if false then  -    lumunic=load_lum_table(filename) -    lumunic=lumunic and lumunic.tounicode -  end -  local cidinfo,cidnames,cidcodes=data.cidinfo -  local usedmap=cidinfo and cidinfo.usedname -  usedmap=usedmap and lower(usedmap) -  usedmap=usedmap and fonts.cid.map[usedmap] -  if usedmap then -    oparser=usedmap and make_name_parser(cidinfo.ordering) -    cidnames=usedmap.names -    cidcodes=usedmap.unicodes -  end -  uparser=make_name_parser() -  local aglmap=fonts.map and fonts.map.agl_to_unicode -  for index,glyph in next,data.glyphs do -    local name,unic=glyph.name,glyph.unicode or -1  -    if unic==-1 or unic>=private or (unic>=0xE000 and unic<=0xF8FF) or unic==0xFFFE or unic==0xFFFF then -      local unicode=(lumunic and lumunic[name]) or (aglmap and aglmap[name]) -      if unicode then -        originals[index],tounicode[index],ns=unicode,tounicode16(unicode),ns+1 -      end -      if (not unicode) and usedmap then -        local foundindex=lpegmatch(oparser,name) -        if foundindex then -          unicode=cidcodes[foundindex]  -          if unicode then -            originals[index],tounicode[index],ns=unicode,tounicode16(unicode),ns+1 -          else -            local reference=cidnames[foundindex]  -            if reference then -              local foundindex=lpegmatch(oparser,reference) -              if foundindex then -                unicode=cidcodes[foundindex] -                if unicode then -                  originals[index],tounicode[index],ns=unicode,tounicode16(unicode),ns+1 -                end -              end -              if not unicode then -                local foundcodes,multiple=lpegmatch(uparser,reference) -                if foundcodes then -                  if multiple then -                    originals[index],tounicode[index],nl,unicode=foundcodes,tounicode16sequence(foundcodes),nl+1,true -                  else -                    originals[index],tounicode[index],ns,unicode=foundcodes,tounicode16(foundcodes),ns+1,foundcodes -                  end -                end -              end -            end -          end -        end -      end -      if not unicode then -        local split=lpegmatch(ligsplitter,name) -        local nplit=(split and #split) or 0 -        if nplit==0 then -        elseif nplit==1 then -          local base=split[1] -          unicode=unicodes[base] or (aglmap and aglmap[base]) -          if unicode then -            if type(unicode)=="table" then -              unicode=unicode[1] -            end -            originals[index],tounicode[index],ns=unicode,tounicode16(unicode),ns+1 -          end -        else -          local t={} -          for l=1,nplit do -            local base=split[l] -            local u=unicodes[base] or (aglmap and aglmap[base]) -            if not u then -              break -            elseif type(u)=="table" then -              t[#t+1]=u[1] -            else -              t[#t+1]=u -            end -          end -          if #t>0 then  -            originals[index],tounicode[index],nl,unicode=t,tounicode16sequence(t),nl+1,true -          end -        end -      end -      if not unicode then -        local foundcodes,multiple=lpegmatch(uparser,name) -        if foundcodes then -          if multiple then -            originals[index],tounicode[index],nl,unicode=foundcodes,tounicode16sequence(foundcodes),nl+1,true -          else -            originals[index],tounicode[index],ns,unicode=foundcodes,tounicode16(foundcodes),ns+1,foundcodes -          end -        end -      end -      if not unicode then -        originals[index],tounicode[index]=0xFFFD,"FFFD" -      end -    end -  end -  if trace_unimapping then -    for index,glyph in table.sortedhash(data.glyphs) do -      local toun,name,unic=tounicode[index],glyph.name,glyph.unicode or -1  -      if toun then -        logs.report("load otf","internal: 0x%05X, name: %s, unicode: 0x%05X, tounicode: %s",index,name,unic,toun) -      else -        logs.report("load otf","internal: 0x%05X, name: %s, unicode: 0x%05X",index,name,unic) -      end -    end -  end -  if trace_loading and (ns>0 or nl>0) then -    logs.report("load otf","enhance: %s tounicode entries added (%s ligatures)",nl+ns,ns) -  end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-otf']={ -  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 utf=unicode.utf8 -local concat,utfbyte=table.concat,utf.byte -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=type,next,tonumber,tostring -local abs=math.abs -local getn=table.getn -local lpegmatch=lpeg.match -local trace_private=false trackers.register("otf.private",function(v) trace_private=v end) -local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end) -local trace_features=false trackers.register("otf.features",function(v) trace_features=v end) -local trace_dynamics=false trackers.register("otf.dynamics",function(v) trace_dynamics=v end) -local trace_sequences=false trackers.register("otf.sequences",function(v) trace_sequences=v end) -local trace_math=false trackers.register("otf.math",function(v) trace_math=v end) -local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end) -fonts=fonts   or {} -fonts.otf=fonts.otf or {} -fonts.tfm=fonts.tfm or {} -local otf=fonts.otf -local tfm=fonts.tfm -local fontdata=fonts.ids -otf.tables=otf.tables      or {}  -otf.meanings=otf.meanings     or {}  -otf.tables.features=otf.tables.features or {}  -otf.tables.languages=otf.tables.languages or {}  -otf.tables.scripts=otf.tables.scripts  or {}  -otf.features=otf.features     or {} -otf.features.list=otf.features.list  or {} -otf.features.default=otf.features.default or {} -otf.enhancers=otf.enhancers    or {} -otf.glists={ "gsub","gpos" } -otf.version=2.653  -otf.pack=true  -otf.syncspace=true -otf.notdef=false -otf.cache=containers.define("fonts","otf",otf.version,true) -otf.cleanup_aat=false  -local wildcard="*" -local default="dflt" -otf.tables.global_fields=table.tohash { -  "lookups", -  "glyphs", -  "subfonts", -  "luatex", -  "pfminfo", -  "cidinfo", -  "tables", -  "names", -  "unicodes", -  "names", -  "anchor_classes", -  "kern_classes", -  "gpos", -  "gsub" -} -otf.tables.valid_fields={ -  "anchor_classes", -  "ascent", -  "cache_version", -  "cidinfo", -  "copyright", -  "creationtime", -  "descent", -  "design_range_bottom", -  "design_range_top", -  "design_size", -  "encodingchanged", -  "extrema_bound", -  "familyname", -  "fontname", -  "fontstyle_id", -  "fontstyle_name", -  "fullname", -  "glyphs", -  "hasvmetrics", -  "head_optimized_for_cleartype", -  "horiz_base", -  "issans", -  "isserif", -  "italicangle", -  "kerns", -  "lookups", -  "macstyle", -  "modificationtime", -  "onlybitmaps", -  "origname", -  "os2_version", -  "pfminfo", -  "private", -  "serifcheck", -  "sfd_version", -  "strokedfont", -  "strokewidth", -  "subfonts", -  "table_version", -  "ttf_tables", -  "uni_interp", -  "uniqueid", -  "units_per_em", -  "upos", -  "use_typo_metrics", -  "uwidth", -  "validation_state", -  "verbose", -  "version", -  "vert_base", -  "weight", -  "weight_width_slope_only", -  "xuid", -} -local function load_featurefile(ff,featurefile) -  if featurefile then -    featurefile=resolvers.find_file(file.addsuffix(featurefile,'fea'),'fea') -    if featurefile and featurefile~="" then -      if trace_loading then -        logs.report("load otf","featurefile: %s",featurefile) -      end -      fontloader.apply_featurefile(ff,featurefile) -    end -  end -end -function otf.enhance(name,data,filename,verbose) -  local enhancer=otf.enhancers[name] -  if enhancer then -    if (verbose~=nil and verbose) or trace_loading then -      logs.report("load otf","enhance: %s (%s)",name,filename) -    end -    enhancer(data,filename) -  end -end -local enhancers={ -  "patch bugs", -  "merge cid fonts","prepare unicode","cleanup ttf tables","compact glyphs","reverse coverage", -  "cleanup aat","enrich with features","add some missing characters", -  "reorganize mark classes", -  "reorganize kerns", -  "flatten glyph lookups","flatten anchor tables","flatten feature tables", -  "simplify glyph lookups", -  "prepare luatex tables", -  "analyse features","rehash features", -  "analyse anchors","analyse marks","analyse unicodes","analyse subtables", -  "check italic correction","check math", -  "share widths", -  "strip not needed data", -  "migrate metadata", -  "check math parameters", -} -function otf.load(filename,format,sub,featurefile) -  local name=file.basename(file.removesuffix(filename)) -  local attr=lfs.attributes(filename) -  local size,time=attr.size or 0,attr.modification or 0 -  if featurefile then -    local fattr=lfs.attributes(featurefile) -    local fsize,ftime=fattr and fattr.size or 0,fattr and fattr.modification or 0 -    name=name.."@"..file.removesuffix(file.basename(featurefile))..ftime..fsize -  end -  if sub=="" then sub=false end -  local hash=name -  if sub then -    hash=hash.."-"..sub -  end -  hash=containers.cleanname(hash) -  local data=containers.read(otf.cache,hash) -  if not data or data.verbose~=fonts.verbose or data.size~=size or data.time~=time then -    logs.report("load otf","loading: %s (hash: %s)",filename,hash) -    local ff,messages -    if sub then -      ff,messages=fontloader.open(filename,sub) -    else -      ff,messages=fontloader.open(filename) -    end -    if trace_loading and messages and #messages>0 then -      if type(messages)=="string" then -        logs.report("load otf","warning: %s",messages) -      else -        for m=1,#messages do -          logs.report("load otf","warning: %s",tostring(messages[m])) -        end -      end -    else -      logs.report("load otf","font loaded okay") -    end -    if ff then -      load_featurefile(ff,featurefile) -      data=fontloader.to_table(ff) -      fontloader.close(ff) -      if data then -        logs.report("load otf","file size: %s",size) -        logs.report("load otf","enhancing ...") -        for e=1,#enhancers do -          otf.enhance(enhancers[e],data,filename) -          io.flush()  -        end -        if otf.pack and not fonts.verbose then -          otf.enhance("pack",data,filename) -        end -        data.size=size -        data.time=time -        data.verbose=fonts.verbose -        logs.report("load otf","saving in cache: %s",filename) -        data=containers.write(otf.cache,hash,data) -        collectgarbage("collect") -        data=containers.read(otf.cache,hash)  -        collectgarbage("collect") -      else -        logs.report("load otf","loading failed (table conversion error)") -      end -    else -      logs.report("load otf","loading failed (file read error)") -    end -  end -  if data then -    if trace_defining then -      logs.report("define font","loading from cache: %s",hash) -    end -    otf.enhance("unpack",data,filename,false)  -    otf.add_dimensions(data) -    if trace_sequences then -      otf.show_feature_order(data,filename) -    end -  end -  return data -end -function otf.add_dimensions(data) -  if data then -    local force=otf.notdef -    local luatex=data.luatex -    local defaultwidth=luatex.defaultwidth or 0 -    local defaultheight=luatex.defaultheight or 0 -    local defaultdepth=luatex.defaultdepth or 0 -    for _,d in next,data.glyphs do -      local bb,wd=d.boundingbox,d.width -      if not wd then -        d.width=defaultwidth -      elseif wd~=0 and d.class=="mark" then -        d.width=-wd -      end -      if force and not d.name then -        d.name=".notdef" -      end -      if bb then -        local ht,dp=bb[4],-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 -end -function otf.show_feature_order(otfdata,filename) -  local sequences=otfdata.luatex.sequences -  if sequences and #sequences>0 then -    if trace_loading then -      logs.report("otf check","font %s has %s sequences",filename,#sequences) -      logs.report("otf check"," ") -    end -    for nos=1,#sequences do -      local sequence=sequences[nos] -      local typ=sequence.type or "no-type" -      local name=sequence.name or "no-name" -      local subtables=sequence.subtables or { "no-subtables" } -      local features=sequence.features -      if trace_loading then -        logs.report("otf check","%3i  %-15s  %-20s  [%s]",nos,name,typ,concat(subtables,",")) -      end -      if features then -        for feature,scripts in next,features do -          local tt={} -          for script,languages in next,scripts do -            local ttt={} -            for language,_ in next,languages do -              ttt[#ttt+1]=language -            end -            tt[#tt+1]=format("[%s: %s]",script,concat(ttt," ")) -          end -          if trace_loading then -            logs.report("otf check","       %s: %s",feature,concat(tt," ")) -          end -        end -      end -    end -    if trace_loading then -      logs.report("otf check","\n") -    end -  elseif trace_loading then -    logs.report("otf check","font %s has no sequences",filename) -  end -end -otf.enhancers["reorganize mark classes"]=function(data,filename) -  if data.mark_classes then -    local unicodes=data.luatex.unicodes -    local reverse={} -    for name,class in next,data.mark_classes do -      local t={} -      for s in gmatch(class,"[^ ]+") do -        local us=unicodes[s] -        if type(us)=="table" then -          for u=1,#us do -            t[us[u]]=true -          end -        else -          t[us]=true -        end -      end -      reverse[name]=t -    end -    data.luatex.markclasses=reverse -    data.mark_classes=nil -  end -end -otf.enhancers["prepare luatex tables"]=function(data,filename) -  data.luatex=data.luatex or {} -  local luatex=data.luatex -  luatex.filename=filename -  luatex.version=otf.version -  luatex.creator="context mkiv" -end -otf.enhancers["cleanup aat"]=function(data,filename) -  if otf.cleanup_aat then -  end -end -local function analyze_features(g,features) -  if g then -    local t,done={},{} -    for k=1,#g do -      local f=features or g[k].features -      if f then -        for k=1,#f do -          local tag=f[k].tag -          if not done[tag] then -            t[#t+1]=tag -            done[tag]=true -          end -        end -      end -    end -    if #t>0 then -      return t -    end -  end -  return nil -end -otf.enhancers["analyse features"]=function(data,filename) -end -otf.enhancers["rehash features"]=function(data,filename) -  local features={} -  data.luatex.features=features -  for k,what in next,otf.glists do -    local dw=data[what] -    if dw then -      local f={} -      features[what]=f -      for i=1,#dw do -        local d=dw[i] -        local dfeatures=d.features -        if dfeatures then -          for i=1,#dfeatures do -            local df=dfeatures[i] -            local tag=strip(lower(df.tag)) -            local ft=f[tag] if not ft then ft={} f[tag]=ft end -            local dscripts=df.scripts -            for script,languages in next,dscripts do -              script=strip(lower(script)) -              local fts=ft[script] if not fts then fts={} ft[script]=fts end -              for i=1,#languages do -                fts[strip(lower(languages[i]))]=true -              end -            end -          end -        end -      end -    end -  end -end -otf.enhancers["analyse anchors"]=function(data,filename) -  local classes=data.anchor_classes -  local luatex=data.luatex -  local anchor_to_lookup,lookup_to_anchor={},{} -  luatex.anchor_to_lookup,luatex.lookup_to_anchor=anchor_to_lookup,lookup_to_anchor -  if classes then -    for c=1,#classes do -      local class=classes[c] -      local anchor=class.name -      local lookups=class.lookup -      if type(lookups)~="table" then -        lookups={ lookups } -      end -      local a=anchor_to_lookup[anchor] -      if not a then a={} anchor_to_lookup[anchor]=a end -      for l=1,#lookups do -        local lookup=lookups[l] -        local l=lookup_to_anchor[lookup] -        if not l then l={} lookup_to_anchor[lookup]=l end -        l[anchor]=true -        a[lookup]=true -      end -    end -  end -end -otf.enhancers["analyse marks"]=function(data,filename) -  local glyphs=data.glyphs -  local marks={} -  data.luatex.marks=marks -  for unicode,index in next,data.luatex.indices do -    local glyph=glyphs[index] -    if glyph.class=="mark" then -      marks[unicode]=true -    end -  end -end -otf.enhancers["analyse unicodes"]=fonts.map.add_to_unicode -otf.enhancers["analyse subtables"]=function(data,filename) -  data.luatex=data.luatex or {} -  local luatex=data.luatex -  local sequences={} -  local lookups={} -  luatex.sequences=sequences -  luatex.lookups=lookups -  for _,g in next,{ data.gsub,data.gpos } do -    for k=1,#g do -      local gk=g[k] -      local typ=gk.type -      if typ=="gsub_contextchain" or typ=="gpos_contextchain" then -        gk.chain=1 -      elseif typ=="gsub_reversecontextchain" or typ=="gpos_reversecontextchain" then -        gk.chain=-1 -      else -        gk.chain=0 -      end -      local features=gk.features -      if features then -        sequences[#sequences+1]=gk -        local t={} -        for f=1,#features do -          local feature=features[f] -          local hash={} -          for s,languages in next,feature.scripts do -            s=lower(s) -            local h=hash[s] -            if not h then h={} hash[s]=h end -            for l=1,#languages do -              h[strip(lower(languages[l]))]=true -            end -          end -          t[feature.tag]=hash -        end -        gk.features=t -      else -        lookups[gk.name]=gk -        gk.name=nil -      end -      local subtables=gk.subtables -      if subtables then -        local t={} -        for s=1,#subtables do -          local subtable=subtables[s] -          local name=subtable.name -          t[#t+1]=name -        end -        gk.subtables=t -      end -      local flags=gk.flags -      if flags then -        gk.flags={  -          (flags.ignorecombiningmarks and "mark")   or false, -          (flags.ignoreligatures   and "ligature") or false, -          (flags.ignorebaseglyphs   and "base")   or false, -           flags.r2l                 or false, -        } -        if flags.mark_class then -          gk.markclass=luatex.markclasses[flags.mark_class] -        end -      end -    end -  end -end -otf.enhancers["merge cid fonts"]=function(data,filename) -  if data.subfonts then -    if data.glyphs and next(data.glyphs) then -      logs.report("load otf","replacing existing glyph table due to subfonts") -    end -    local cidinfo=data.cidinfo -    local verbose=fonts.verbose -    if cidinfo.registry then -      local cidmap,cidname=fonts.cid.getmap(cidinfo.registry,cidinfo.ordering,cidinfo.supplement) -      if cidmap then -        cidinfo.usedname=cidmap.usedname -        local glyphs,uni_to_int,int_to_uni,nofnames,nofunicodes={},{},{},0,0 -        local unicodes,names=cidmap.unicodes,cidmap.names -        for n,subfont in next,data.subfonts do -          for index,g in next,subfont.glyphs do -            if not next(g) then -            else -              local unicode,name=unicodes[index],names[index] -              g.cidindex=n -              g.boundingbox=g.boundingbox  -              g.name=g.name or name or "unknown" -              if unicode then -                uni_to_int[unicode]=index -                int_to_uni[index]=unicode -                nofunicodes=nofunicodes+1 -                g.unicode=unicode -              elseif name then -                nofnames=nofnames+1 -                g.unicode=-1 -              end -              glyphs[index]=g -            end -          end -          subfont.glyphs=nil -        end -        if trace_loading then -          logs.report("load otf","cid font remapped, %s unicode points, %s symbolic names, %s glyphs",nofunicodes,nofnames,nofunicodes+nofnames) -        end -        data.glyphs=glyphs -        data.map=data.map or {} -        data.map.map=uni_to_int -        data.map.backmap=int_to_uni -      elseif trace_loading then -        logs.report("load otf","unable to remap cid font, missing cid file for %s",filename) -      end -    elseif trace_loading then -      logs.report("load otf","font %s has no glyphs",filename) -    end -  end -end -otf.enhancers["prepare unicode"]=function(data,filename) -  local luatex=data.luatex -  if not luatex then luatex={} data.luatex=luatex end -  local indices,unicodes,multiples,internals={},{},{},{} -  local glyphs=data.glyphs -  local mapmap=data.map -  if not mapmap then -    logs.report("load otf","no map in %s",filename) -    mapmap={} -    data.map={ map=mapmap } -  elseif not mapmap.map then -    logs.report("load otf","no unicode map in %s",filename) -    mapmap={} -    data.map.map=mapmap -  else -    mapmap=mapmap.map -  end -  local criterium=fonts.private -  local private=fonts.private -  for index,glyph in next,glyphs do -    if index>0 then -      local name=glyph.name -      if name then -        local unicode=glyph.unicode -        if unicode==-1 or unicode>=criterium then -          glyph.unicode=private -          indices[private]=index -          unicodes[name]=private -          internals[index]=true -          if trace_private then -            logs.report("load otf","enhance: glyph %s at index U+%04X is moved to private unicode slot U+%04X",name,index,private) -          end -          private=private+1 -        else -          indices[unicode]=index -          unicodes[name]=unicode -        end -      end -    end -  end -  for unicode,index in next,mapmap do -    if not internals[index] then -      local name=glyphs[index].name -      if name then -        local un=unicodes[name] -        if not un then -          unicodes[name]=unicode  -        elseif type(un)=="number" then -          if un~=unicode then -            multiples[#multiples+1]=name -            unicodes[name]={ un,unicode } -            indices[unicode]=index -          end -        else -          local ok=false -          for u=1,#un do -            if un[u]==unicode then -              ok=true -              break -            end -          end -          if not ok then -            multiples[#multiples+1]=name -            un[#un+1]=unicode -            indices[unicode]=index -          end -        end -      end -    end -  end -  if trace_loading then -    if #multiples>0 then -      logs.report("load otf","%s glyph are reused: %s",#multiples,concat(multiples," ")) -    else -      logs.report("load otf","no glyph are reused") -    end -  end -  luatex.indices=indices -  luatex.unicodes=unicodes -  luatex.private=private -end -otf.enhancers["cleanup ttf tables"]=function(data,filename) -  local ttf_tables=data.ttf_tables -  if ttf_tables then -    for k=1,#ttf_tables do -      if ttf_tables[k].data then ttf_tables[k].data="deleted" end -    end -  end -  data.ttf_tab_saved=nil -end -otf.enhancers["compact glyphs"]=function(data,filename) -  table.compact(data.glyphs)  -  if data.subfonts then -    for _,subfont in next,data.subfonts do -      table.compact(subfont.glyphs)  -    end -  end -end -otf.enhancers["reverse coverage"]=function(data,filename) -  if data.lookups then -    for _,v in next,data.lookups do -      if v.rules then -        for _,vv in next,v.rules do -          local c=vv.coverage -          if c and c.before then -            c.before=table.reverse(c.before) -          end -        end -      end -    end -  end -end -otf.enhancers["check italic correction"]=function(data,filename) -  local glyphs=data.glyphs -  local ok=false -  for index,glyph in next,glyphs do -    local ic=glyph.italic_correction -    if ic then -      if ic~=0 then -        glyph.italic=ic -      end -      glyph.italic_correction=nil -      ok=true -    end -  end -  otf.tables.valid_fields[#otf.tables.valid_fields+1]="has_italic" -  data.has_italic=true -end -otf.enhancers["check math"]=function(data,filename) -  if data.math then -    local glyphs=data.glyphs -    local unicodes=data.luatex.unicodes -    for index,glyph in next,glyphs do -      local mk=glyph.mathkern -      local hv=glyph.horiz_variants -      local vv=glyph.vert_variants -      if mk or hv or vv then -        local math={} -        glyph.math=math -        if mk then -          for k,v in next,mk do -            if not next(v) then -              mk[k]=nil -            end -          end -          math.kerns=mk -          glyph.mathkern=nil -        end -        if hv then -          math.horiz_variants=hv.variants -          local p=hv.parts -          if p and #p>0 then -            for i=1,#p do -              local pi=p[i] -              pi.glyph=unicodes[pi.component] or 0 -            end -            math.horiz_parts=p -          end -          local ic=hv.italic_correction -          if ic and ic~=0 then -            math.horiz_italic_correction=ic -          end -          glyph.horiz_variants=nil -        end -        if vv then -          local uc=unicodes[index] -          math.vert_variants=vv.variants -          local p=vv.parts -          if p and #p>0 then -            for i=1,#p do -              local pi=p[i] -              pi.glyph=unicodes[pi.component] or 0 -            end -            math.vert_parts=p -          end -          local ic=vv.italic_correction -          if ic and ic~=0 then -            math.vert_italic_correction=ic -          end -          glyph.vert_variants=nil -        end -        local ic=glyph.italic_correction -        if ic then -          if ic~=0 then -            math.italic_correction=ic -          end -          glyph.italic_correction=nil -        end -      end -    end -  end -end -otf.enhancers["share widths"]=function(data,filename) -  local glyphs=data.glyphs -  local widths={} -  for index,glyph in next,glyphs do -    local width=glyph.width -    widths[width]=(widths[width] or 0)+1 -  end -  local wd,most=0,1 -  for k,v in next,widths do -    if v>most then -      wd,most=k,v -    end -  end -  if most>1000 then -    if trace_loading then -      logs.report("load otf","most common width: %s (%s times), sharing (cjk font)",wd,most) -    end -    for k,v in next,glyphs do -      if v.width==wd then -        v.width=nil -      end -    end -    data.luatex.defaultwidth=wd -  end -end -otf.enhancers["reorganize kerns"]=function(data,filename) -  local glyphs,mapmap,unicodes=data.glyphs,data.luatex.indices,data.luatex.unicodes -  local mkdone=false -  local function do_it(lookup,first_unicode,kerns) -    local glyph=glyphs[mapmap[first_unicode]] -    if glyph then -      local mykerns=glyph.mykerns -      if not mykerns then -        mykerns={}  -        glyph.mykerns=mykerns -      end -      local lookupkerns=mykerns[lookup] -      if not lookupkerns then -        lookupkerns={} -        mykerns[lookup]=lookupkerns -      end -      for second_unicode,kern in next,kerns do -        lookupkerns[second_unicode]=kern -      end -    elseif trace_loading then -      logs.report("load otf","no glyph data for U+%04X",first_unicode) -    end -  end -  for index,glyph in next,glyphs do -    if glyph.kerns then -      local mykerns={} -      for k,v in next,glyph.kerns do -        local vc,vo,vl=v.char,v.off,v.lookup -        if vc and vo and vl then  -          local uvc=unicodes[vc] -          if not uvc then -            if trace_loading then -              logs.report("load otf","problems with unicode %s of kern %s at glyph %s",vc,k,index) -            end -          else -            if type(vl)~="table" then -              vl={ vl } -            end -            for l=1,#vl do -              local vll=vl[l] -              local mkl=mykerns[vll] -              if not mkl then -                mkl={} -                mykerns[vll]=mkl -              end -              if type(uvc)=="table" then -                for u=1,#uvc do -                  mkl[uvc[u]]=vo -                end -              else -                mkl[uvc]=vo -              end -            end -          end -        end -      end -      glyph.mykerns=mykerns -      glyph.kerns=nil  -      mkdone=true -    end -  end -  if trace_loading and mkdone then -    logs.report("load otf","replacing 'kerns' tables by 'mykerns' tables") -  end -  if data.kerns then -    if trace_loading then -      logs.report("load otf","removing global 'kern' table") -    end -    data.kerns=nil -  end -  local dgpos=data.gpos -  if dgpos then -    local separator=lpeg.P(" ") -    local other=((1-separator)^0)/unicodes -    local splitter=lpeg.Ct(other*(separator*other)^0) -    for gp=1,#dgpos do -      local gpos=dgpos[gp] -      local subtables=gpos.subtables -      if subtables then -        for s=1,#subtables do -          local subtable=subtables[s] -          local kernclass=subtable.kernclass  -          if kernclass then  -            local split={}  -            for k=1,#kernclass do -              local kcl=kernclass[k] -              local firsts,seconds,offsets,lookups=kcl.firsts,kcl.seconds,kcl.offsets,kcl.lookup  -              if type(lookups)~="table" then -                lookups={ lookups } -              end -              local maxfirsts,maxseconds=#firsts,#seconds -              for _,s in next,firsts do -                split[s]=split[s] or lpegmatch(splitter,s) -              end -              for _,s in next,seconds do -                split[s]=split[s] or lpegmatch(splitter,s) -              end -              for l=1,#lookups do -                local lookup=lookups[l] -                for fk=1,#firsts do -                  local fv=firsts[fk] -                  local splt=split[fv] -                  if splt then -                    local kerns,baseoffset={},(fk-1)*maxseconds -                    for sk=2,maxseconds do -                      local sv=seconds[sk] -                      local splt=split[sv] -                      if splt then -                        local offset=offsets[baseoffset+sk] -                        if offset then -                          for i=1,#splt do -                            local second_unicode=splt[i] -                            if tonumber(second_unicode) then -                              kerns[second_unicode]=offset -                            else for s=1,#second_unicode do -                              kerns[second_unicode[s]]=offset -                            end end -                          end -                        end -                      end -                    end -                    for i=1,#splt do -                      local first_unicode=splt[i] -                      if tonumber(first_unicode) then -                        do_it(lookup,first_unicode,kerns) -                      else for f=1,#first_unicode do -                        do_it(lookup,first_unicode[f],kerns) -                      end end -                    end -                  end -                end -              end -            end -            subtable.comment="The kernclass table is merged into mykerns in the indexed glyph tables." -            subtable.kernclass={} -          end -        end -      end -    end -  end -end -otf.enhancers["strip not needed data"]=function(data,filename) -  local verbose=fonts.verbose -  local int_to_uni=data.luatex.unicodes -  for k,v in next,data.glyphs do -    local d=v.dependents -    if d then v.dependents=nil end -    local a=v.altuni -    if a then v.altuni=nil end -    if verbose then -      local code=int_to_uni[k] -      if code then -        local vu=v.unicode -        if not vu then -          v.unicode=code -        elseif type(vu)=="table" then -          if vu[#vu]==code then -          else -            vu[#vu+1]=code -          end -        elseif vu~=code then -          v.unicode={ vu,code } -        end -      end -    else -      v.unicode=nil -      v.index=nil -    end -  end -  data.luatex.comment="Glyph tables have their original index. When present, mykern tables are indexed by unicode." -  data.map=nil -  data.names=nil  -  data.glyphcnt=nil -  data.glyphmax=nil -  if true then -    data.gpos=nil -    data.gsub=nil -    data.anchor_classes=nil -  end -end -otf.enhancers["migrate metadata"]=function(data,filename) -  local global_fields=otf.tables.global_fields -  local metadata={} -  for k,v in next,data do -    if not global_fields[k] then -      metadata[k]=v -      data[k]=nil -    end -  end -  data.metadata=metadata -  local pfminfo=data.pfminfo -  metadata.isfixedpitch=metadata.isfixedpitch or (pfminfo.panose and pfminfo.panose["proportion"]=="Monospaced") -  metadata.charwidth=pfminfo and pfminfo.avgwidth -end -local private_math_parameters={ -  "FractionDelimiterSize", -  "FractionDelimiterDisplayStyleSize", -} -otf.enhancers["check math parameters"]=function(data,filename) -  local mathdata=data.metadata.math -  if mathdata then -    for m=1,#private_math_parameters do -      local pmp=private_math_parameters[m] -      if not mathdata[pmp] then -        if trace_loading then -          logs.report("load otf","setting math parameter '%s' to 0",pmp) -        end -        mathdata[pmp]=0 -      end -    end -  end -end -otf.enhancers["flatten glyph lookups"]=function(data,filename) -  for k,v in next,data.glyphs do -    local lookups=v.lookups -    if lookups then -      for kk,vv in next,lookups do -        for kkk=1,#vv do -          local vvv=vv[kkk] -          local s=vvv.specification -          if s then -            local t=vvv.type -            if t=="ligature" then -              vv[kkk]={ "ligature",s.components,s.char } -            elseif t=="alternate" then -              vv[kkk]={ "alternate",s.components } -            elseif t=="substitution" then -              vv[kkk]={ "substitution",s.variant } -            elseif t=="multiple" then -              vv[kkk]={ "multiple",s.components } -            elseif t=="position" then -              vv[kkk]={ "position",{ s.x or 0,s.y or 0,s.h or 0,s.v or 0 } } -            elseif t=="pair" then -              local one,two,paired=s.offsets[1],s.offsets[2],s.paired or "" -              if one then -                if two then -                  vv[kkk]={ "pair",paired,{ one.x or 0,one.y or 0,one.h or 0,one.v or 0 },{ two.x or 0,two.y or 0,two.h or 0,two.v or 0 } } -                else -                  vv[kkk]={ "pair",paired,{ one.x or 0,one.y or 0,one.h or 0,one.v or 0 } } -                end -              else -                if two then -                  vv[kkk]={ "pair",paired,{},{ two.x or 0,two.y or 0,two.h or 0,two.v or 0} }  -                else -                  vv[kkk]={ "pair",paired } -                end -              end -            else -              if trace_loading then -                logs.report("load otf","flattening needed, report to context list") -              end -              for a,b in next,s do -                if trace_loading and vvv[a] then -                  logs.report("load otf","flattening conflict, report to context list") -                end -                vvv[a]=b -              end -              vvv.specification=nil -            end -          end -        end -      end -    end -  end -end -otf.enhancers["simplify glyph lookups"]=function(data,filename) -  for k,v in next,data.glyphs do -    local lookups=v.lookups -    if lookups then -      local slookups,mlookups -      for kk,vv in next,lookups do -        if #vv==1 then -          if not slookups then -            slookups={} -            v.slookups=slookups -          end -          slookups[kk]=vv[1] -        else -          if not mlookups then -            mlookups={} -            v.mlookups=mlookups -          end -          mlookups[kk]=vv -        end -      end -      v.lookups=nil -    end -  end -end -otf.enhancers["flatten anchor tables"]=function(data,filename) -  for k,v in next,data.glyphs do -    if v.anchors then -      for kk,vv in next,v.anchors do -        for kkk,vvv in next,vv do -          if vvv.x or vvv.y then -            vv[kkk]={ vvv.x or 0,vvv.y or 0 } -          else -            for kkkk=1,#vvv do -              local vvvv=vvv[kkkk] -              vvv[kkkk]={ vvvv.x or 0,vvvv.y or 0 } -            end -          end -        end -      end -    end -  end -end -otf.enhancers["flatten feature tables"]=function(data,filename) -  for _,tag in next,otf.glists do -    if data[tag] then -      if trace_loading then -        logs.report("load otf","flattening %s table",tag) -      end -      for k,v in next,data[tag] do -        local features=v.features -        if features then -          for kk=1,#features do -            local vv=features[kk] -            local t={} -            local scripts=vv.scripts -            for kkk=1,#scripts do -              local vvv=scripts[kkk] -              t[vvv.script]=vvv.langs -            end -            vv.scripts=t -          end -        end -      end -    end -  end -end -otf.enhancers.patches=otf.enhancers.patches or {} -otf.enhancers["patch bugs"]=function(data,filename) -  local basename=file.basename(lower(filename)) -  for pattern,action in next,otf.enhancers.patches do -    if find(basename,pattern) then -      action(data,filename) -    end -  end -end -fonts.otf.enhancers["enrich with features"]=function(data,filename) -end -function otf.features.register(name,default) -  otf.features.list[#otf.features.list+1]=name -  otf.features.default[name]=default -end -function otf.set_features(tfmdata,features) -  local processes={} -  if features and next(features) then -    local lists={  -      fonts.triggers, -      fonts.processors, -      fonts.manipulators, -    } -    local mode=tfmdata.mode or fonts.mode  -    local initializers=fonts.initializers -    local fi=initializers[mode] -    if fi then -      local fiotf=fi.otf -      if fiotf then -        local done={} -        for l=1,4 do -          local list=lists[l] -          if list then -            for i=1,#list do -              local f=list[i] -              local value=features[f] -              if value and fiotf[f] then  -                if not done[f] then  -                  if trace_features then -                    logs.report("define otf","initializing feature %s to %s for mode %s for font %s",f,tostring(value),mode or 'unknown',tfmdata.fullname or 'unknown') -                  end -                  fiotf[f](tfmdata,value)  -                  mode=tfmdata.mode or fonts.mode  -                  local im=initializers[mode] -                  if im then -                    fiotf=initializers[mode].otf -                  end -                  done[f]=true -                end -              end -            end -          end -        end -      end -    end -    local fm=fonts.methods[mode]  -    if fm then -      local fmotf=fm.otf -      if fmotf then -        for l=1,4 do -          local list=lists[l] -          if list then -            for i=1,#list do -              local f=list[i] -              if fmotf[f] then  -                if trace_features then -                  logs.report("define otf","installing feature handler %s for mode %s for font %s",f,mode or 'unknown',tfmdata.fullname or 'unknown') -                end -                processes[#processes+1]=fmotf[f] -              end -            end -          end -        end -      end -    else -    end -  end -  return processes,features -end -function otf.otf_to_tfm(specification) -  local name=specification.name -  local sub=specification.sub -  local filename=specification.filename -  local format=specification.format -  local features=specification.features.normal -  local cache_id=specification.hash -  local tfmdata=containers.read(tfm.cache,cache_id) -  if not tfmdata then -    local otfdata=otf.load(filename,format,sub,features and features.featurefile) -    if otfdata and next(otfdata) then -      otfdata.shared=otfdata.shared or { -        featuredata={}, -        anchorhash={}, -        initialized=false, -      } -      tfmdata=otf.copy_to_tfm(otfdata,cache_id) -      if tfmdata and next(tfmdata) then -        tfmdata.unique=tfmdata.unique or {} -        tfmdata.shared=tfmdata.shared or {}  -        local shared=tfmdata.shared -        shared.otfdata=otfdata -        shared.features=features  -        shared.dynamics={} -        shared.processes={} -        shared.set_dynamics=otf.set_dynamics -        tfmdata.luatex=otfdata.luatex -        tfmdata.indices=otfdata.luatex.indices -        tfmdata.unicodes=otfdata.luatex.unicodes -        tfmdata.marks=otfdata.luatex.marks -        tfmdata.originals=otfdata.luatex.originals -        tfmdata.changed={} -        tfmdata.has_italic=otfdata.metadata.has_italic -        if not tfmdata.language then tfmdata.language='dflt' end -        if not tfmdata.script  then tfmdata.script='dflt' end -        shared.processes,shared.features=otf.set_features(tfmdata,fonts.define.check(features,otf.features.default)) -      end -    end -    containers.write(tfm.cache,cache_id,tfmdata) -  end -  return tfmdata -end -fonts.formats.dfont="truetype" -fonts.formats.ttc="truetype" -fonts.formats.ttf="truetype" -fonts.formats.otf="opentype" -function otf.copy_to_tfm(data,cache_id)  -  if data then -    local glyphs,pfminfo,metadata=data.glyphs or {},data.pfminfo or {},data.metadata or {} -    local luatex=data.luatex -    local unicodes=luatex.unicodes  -    local indices=luatex.indices -    local characters,parameters,math_parameters,descriptions={},{},{},{} -    local designsize=metadata.designsize or metadata.design_size or 100 -    if designsize==0 then -      designsize=100 -    end -    local spaceunits,spacer=500,"space" -    for u,i in next,indices do -      characters[u]={}  -      descriptions[u]=glyphs[i] -    end -    if metadata.math then -      for name,value in next,metadata.math do -        math_parameters[name]=value -      end -      for u,char in next,characters do -        local d=descriptions[u] -        local m=d.math -        if m then -          local variants,parts,c,uc=m.horiz_variants,m.horiz_parts,char,u -          if variants then -            for n in gmatch(variants,"[^ ]+") do -              local un=unicodes[n] -              if un and uc~=un then -                c.next=un -                c=characters[un] -				uc=un -              end -            end -            c.horiz_variants=parts -          elseif parts then -            c.horiz_variants=parts -          end -          local variants,parts,c,uc=m.vert_variants,m.vert_parts,char,u -          if variants then -            for n in gmatch(variants,"[^ ]+") do -              local un=unicodes[n] -              if un and uc~=un then -                c.next=un -                c=characters[un] -				uc=un -              end -            end  -            c.vert_variants=parts -          elseif parts then -            c.vert_variants=parts -          end -          local italic_correction=m.vert_italic_correction -          if italic_correction then -            c.vert_italic_correction=italic_correction -          end -          local kerns=m.kerns -          if kerns then -            char.mathkerns=kerns -          end -        end -      end -    end -    local endash,emdash,space=0x20,0x2014,"space"  -    if metadata.isfixedpitch 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 metadata.charwidth then -        spaceunits,spacer=metadata.charwidth,"charwidth" -      end -    else -      if descriptions[endash] then -        spaceunits,spacer=descriptions[endash].width,"space" -      end -      if not spaceunits and descriptions[emdash] then -        spaceunits,spacer=descriptions[emdash].width/2,"emdash/2" -      end -      if not spaceunits and metadata.charwidth then -        spaceunits,spacer=metadata.charwidth,"charwidth" -      end -    end -    spaceunits=tonumber(spaceunits) or tfm.units/2 -    local filename=fonts.tfm.checked_filename(luatex) -    local fontname=metadata.fontname -    local fullname=metadata.fullname or fontname -    local cidinfo=data.cidinfo -    local units=metadata.units_per_em or 1000 -    cidinfo.registry=cidinfo and cidinfo.registry or "" -    parameters.slant=0 -    parameters.space=spaceunits      -    parameters.space_stretch=units/2   -    parameters.space_shrink=1*units/3  -    parameters.x_height=2*units/5  -    parameters.quad=units    -    if spaceunits<2*units/5 then -    end -    local italicangle=metadata.italicangle -    if italicangle then  -      parameters.slant=parameters.slant-math.round(math.tan(italicangle*math.pi/180)) -    end -    if metadata.isfixedpitch then -      parameters.space_stretch=0 -      parameters.space_shrink=0 -    elseif otf.syncspace then  -      parameters.space_stretch=spaceunits/2 -      parameters.space_shrink=spaceunits/3 -    end -    parameters.extra_space=parameters.space_shrink  -    if pfminfo.os2_xheight and pfminfo.os2_xheight>0 then -      parameters.x_height=pfminfo.os2_xheight -    else -      local x=0x78  -      if x then -        local x=descriptions[x] -        if x then -          parameters.x_height=x.height -        end -      end -    end -    return { -      characters=characters, -      parameters=parameters, -      math_parameters=math_parameters, -      descriptions=descriptions, -      indices=indices, -      unicodes=unicodes, -      type="real", -      direction=0, -      boundarychar_label=0, -      boundarychar=65536, -      designsize=(designsize/10)*65536, -      spacer="500 units", -      encodingbytes=2, -      filename=filename, -      fontname=fontname, -      fullname=fullname, -      psname=fontname or fullname, -      name=filename or fullname, -      units=units, -      format=fonts.fontformat(filename,"opentype"), -      cidinfo=cidinfo, -      ascender=abs(metadata.ascent or 0), -      descender=abs(metadata.descent or 0), -      spacer=spacer, -      italicangle=italicangle, -    } -  else -    return nil -  end -end -otf.features.register('mathsize') -function tfm.read_from_open_type(specification) -  local tfmtable=otf.otf_to_tfm(specification) -  if tfmtable then -    local otfdata=tfmtable.shared.otfdata -    tfmtable.name=specification.name -    tfmtable.sub=specification.sub -    local s=specification.size -    local m=otfdata.metadata.math -    if m then -      local f=specification.features -      if f then -        local f=f.normal -        if f and f.mathsize then -          local mathsize=specification.mathsize or 0 -          if mathsize==2 then -            local p=m.ScriptPercentScaleDown -            if p then -              local ps=p*specification.textsize/100 -              if trace_math then -                logs.report("define font","asked script size: %s, used: %s (%2.2f %%)",s,ps,(ps/s)*100) -              end -              s=ps -            end -          elseif mathsize==3 then -            local p=m.ScriptScriptPercentScaleDown -            if p then -              local ps=p*specification.textsize/100 -              if trace_math then -                logs.report("define font","asked scriptscript size: %s, used: %s (%2.2f %%)",s,ps,(ps/s)*100) -              end -              s=ps -            end -          end -        end -      end -    end -    tfmtable=tfm.scale(tfmtable,s,specification.relativeid) -    if tfm.fontname_mode=="specification" then -      local specname=specification.specification -      if specname then -        tfmtable.name=specname -        if trace_defining then -          logs.report("define font","overloaded fontname: '%s'",specname) -        end -      end -    end -    fonts.logger.save(tfmtable,file.extname(specification.filename),specification) -  end -  return tfmtable -end -function otf.collect_lookups(otfdata,kind,script,language) -  local sequences=otfdata.luatex.sequences -  if sequences then -    local featuremap,featurelist={},{} -    for s=1,#sequences do -      local sequence=sequences[s] -      local features=sequence.features -      features=features and features[kind] -      features=features and (features[script]  or features[default] or features[wildcard]) -      features=features and (features[language] or features[default] or features[wildcard]) -      if features then -        local subtables=sequence.subtables -        if subtables then -          for s=1,#subtables do -            local ss=subtables[s] -            if not featuremap[s] then -              featuremap[ss]=true -              featurelist[#featurelist+1]=ss -            end -          end -        end -      end -    end -    if #featurelist>0 then -      return featuremap,featurelist -    end -  end -  return nil,nil -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-otd']={ -  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_dynamics=false trackers.register("otf.dynamics",function(v) trace_dynamics=v end) -fonts=fonts   or {} -fonts.otf=fonts.otf or {} -local otf=fonts.otf -local fontdata=fonts.ids -otf.features=otf.features     or {} -otf.features.default=otf.features.default or {} -local context_setups=fonts.define.specify.context_setups -local context_numbers=fonts.define.specify.context_numbers -local a_to_script={} otf.a_to_script=a_to_script -local a_to_language={} otf.a_to_language=a_to_language -function otf.set_dynamics(font,dynamics,attribute) -  local features=context_setups[context_numbers[attribute]]  -  if features then -    local script=features.script  or 'dflt' -    local language=features.language or 'dflt' -    local ds=dynamics[script] -    if not ds then -      ds={} -      dynamics[script]=ds -    end -    local dsl=ds[language] -    if not dsl then -      dsl={} -      ds[language]=dsl -    end -    local dsla=dsl[attribute] -    if dsla then -      return dsla -    else -      local tfmdata=fontdata[font] -      a_to_script [attribute]=script -      a_to_language[attribute]=language -      local saved={ -        script=tfmdata.script, -        language=tfmdata.language, -        mode=tfmdata.mode, -        features=tfmdata.shared.features -      } -      tfmdata.mode="node" -      tfmdata.language=language -      tfmdata.script=script -      tfmdata.shared.features={} -      local set=fonts.define.check(features,otf.features.default) -      dsla=otf.set_features(tfmdata,set) -      if trace_dynamics then -        logs.report("otf define","setting dynamics %s: attribute %s, script %s, language %s, set: %s",context_numbers[attribute],attribute,script,language,table.sequenced(set)) -      end -      tfmdata.script=saved.script -      tfmdata.language=saved.language -      tfmdata.mode=saved.mode -      tfmdata.shared.features=saved.features -      dynamics[script][language][attribute]=dsla  -      return dsla -    end -  end -  return nil  -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -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 otf=fonts.otf -otf.default_language='latn' -otf.default_script='dflt' -local languages=otf.tables.languages -local scripts=otf.tables.scripts -function otf.features.language(tfmdata,value) -  if value then -    value=lower(value) -    if languages[value] then -      tfmdata.language=value -    end -  end -end -function otf.features.script(tfmdata,value) -  if value then -    value=lower(value) -    if scripts[value] then -      tfmdata.script=value -    end -  end -end -function otf.features.mode(tfmdata,value) -  if value then -    tfmdata.mode=lower(value) -  end -end -fonts.initializers.base.otf.language=otf.features.language -fonts.initializers.base.otf.script=otf.features.script -fonts.initializers.base.otf.mode=otf.features.mode -fonts.initializers.base.otf.method=otf.features.mode -fonts.initializers.node.otf.language=otf.features.language -fonts.initializers.node.otf.script=otf.features.script -fonts.initializers.node.otf.mode=otf.features.mode -fonts.initializers.node.otf.method=otf.features.mode -otf.features.register("features",true)    -table.insert(fonts.processors,"features")  - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-otb']={ -  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=table.concat -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=type,next,tonumber,tostring -local lpegmatch=lpeg.match -local otf=fonts.otf -local tfm=fonts.tfm -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 wildcard="*" -local default="dflt" -local split_at_space=lpeg.Ct(lpeg.splitat(" "))  -local pcache,fcache={},{}  -local function gref(descriptions,n) -  if type(n)=="number" then -    local name=descriptions[n].name -    if name then -      return format("U+%04X (%s)",n,name) -    else -      return format("U+%04X") -    end -  elseif n then -    local num,nam={},{} -    for i=1,#n do -      local ni=n[i] -      num[i]=format("U+%04X",ni) -      nam[i]=descriptions[ni].name or "?" -    end -    return format("%s (%s)",concat(num," "),concat(nam," ")) -  else -    return "?" -  end -end -local function cref(kind,lookupname) -  if lookupname then -    return format("feature %s, lookup %s",kind,lookupname) -  else -    return format("feature %s",kind) -  end -end -local function resolve_ligatures(tfmdata,ligatures,kind) -  kind=kind or "unknown" -  local unicodes=tfmdata.unicodes -  local characters=tfmdata.characters -  local descriptions=tfmdata.descriptions -  local changed=tfmdata.changed -  local done={} -  while true do -    local ok=false -    for k,v in next,ligatures do -      local lig=v[1] -      if not done[lig] then -        local ligs=lpegmatch(split_at_space,lig) -        if #ligs==2 then -          local uc=v[2] -          local c,f,s=characters[uc],ligs[1],ligs[2] -          local uft,ust=unicodes[f] or 0,unicodes[s] or 0 -          if not uft or not ust then -            logs.report("define otf","%s: unicode problem with base ligature %s = %s + %s",cref(kind),gref(descriptions,uc),gref(descriptions,uft),gref(descriptions,ust)) -          else -            if type(uft)=="number" then uft={ uft } end -            if type(ust)=="number" then ust={ ust } end -            for ufi=1,#uft do -              local uf=uft[ufi] -              for usi=1,#ust do -                local us=ust[usi] -                if changed[uf] or changed[us] then -                  if trace_baseinit and trace_ligatures then -                    logs.report("define otf","%s: base ligature %s + %s ignored",cref(kind),gref(descriptions,uf),gref(descriptions,us)) -                  end -                else -                  local first,second=characters[uf],us -                  if first and second then -                    local t=first.ligatures -                    if not t then -                      t={} -                      first.ligatures=t -                    end -                    if type(uc)=="number" then -                      t[second]={ type=0,char=uc } -                    else -                      t[second]={ type=0,char=uc[1] }  -                    end -                    if trace_baseinit and trace_ligatures then -                      logs.report("define otf","%s: base ligature %s + %s => %s",cref(kind),gref(descriptions,uf),gref(descriptions,us),gref(descriptions,uc)) -                    end -                  end -                end -              end -            end -          end -          ok,done[lig]=true,descriptions[uc].name -        end -      end -    end -    if ok then -      for d,n in next,done do -        local pattern=pcache[d] if not pattern then pattern="^("..d..") "       pcache[d]=pattern end -        local fnc=fcache[n] if not fnc   then fnc=function() return n.." " end fcache[n]=fnc   end -        for k,v in next,ligatures do -          v[1]=gsub(v[1],pattern,fnc) -        end -      end -    else -      break -    end -  end -end -local splitter=lpeg.splitat(" ") -local function prepare_base_substitutions(tfmdata,kind,value)  -  if value then -    local otfdata=tfmdata.shared.otfdata -    local validlookups,lookuplist=otf.collect_lookups(otfdata,kind,tfmdata.script,tfmdata.language) -    if validlookups then -      local ligatures={} -      local unicodes=tfmdata.unicodes  -      local indices=tfmdata.indices -      local characters=tfmdata.characters -      local descriptions=tfmdata.descriptions -      local changed=tfmdata.changed -      local actions={ -        substitution=function(p,lookup,k,glyph,unicode) -          local pv=p[2]  -          if pv then -            local upv=unicodes[pv] -            if upv then -              if type(upv)=="table" then -                upv=upv[1] -              end -              if characters[upv] then -                if trace_baseinit and trace_singles then -                  logs.report("define otf","%s: base substitution %s => %s",cref(kind,lookup),gref(descriptions,k),gref(descriptions,upv)) -                end -                changed[k]=upv -              end -            end -          end -        end, -        alternate=function(p,lookup,k,glyph,unicode) -          local pc=p[2]  -          if pc then -            if value==1 then -              pc=lpegmatch(splitter,pc) -            elseif value==2 then -              local a,b=lpegmatch(splitter,pc) -              pc=b or a -            else -              pc={ lpegmatch(splitter,pc) } -              pc=pc[value] or pc[#pc] -            end -            if pc then -              local upc=unicodes[pc] -              if upc then -                if type(upc)=="table" then -                  upc=upc[1] -                end -                if characters[upc] then -                  if trace_baseinit and trace_alternatives then -                    logs.report("define otf","%s: base alternate %s %s => %s",cref(kind,lookup),tostring(value),gref(descriptions,k),gref(descriptions,upc)) -                  end -                  changed[k]=upc -                end -              end -            end -          end -        end, -        ligature=function(p,lookup,k,glyph,unicode) -          local pc=p[2] -          if pc then -            if trace_baseinit and trace_ligatures then -              local upc={ lpegmatch(splitter,pc) } -              for i=1,#upc do upc[i]=unicodes[upc[i]] end -              logs.report("define otf","%s: base ligature %s => %s",cref(kind,lookup),gref(descriptions,upc),gref(descriptions,k)) -            end -            ligatures[#ligatures+1]={ pc,k } -          end -        end, -      } -      for k,c in next,characters do -        local glyph=descriptions[k] -        local lookups=glyph.slookups -        if lookups then -          for l=1,#lookuplist do -            local lookup=lookuplist[l] -            local p=lookups[lookup] -            if p then -              local a=actions[p[1]] -              if a then -                a(p,lookup,k,glyph,unicode) -              end -            end -          end -        end -        local lookups=glyph.mlookups -        if lookups then -          for l=1,#lookuplist do -            local lookup=lookuplist[l] -            local ps=lookups[lookup] -            if ps then -              for i=1,#ps do -                local p=ps[i] -                local a=actions[p[1]] -                if a then -                  a(p,lookup,k,glyph,unicode) -                end -              end -            end -          end -        end -      end -      resolve_ligatures(tfmdata,ligatures,kind) -    end -  else -    tfmdata.ligatures=tfmdata.ligatures or {}  -  end -end -local function prepare_base_kerns(tfmdata,kind,value)  -  if value then -    local otfdata=tfmdata.shared.otfdata -    local validlookups,lookuplist=otf.collect_lookups(otfdata,kind,tfmdata.script,tfmdata.language) -    if validlookups then -      local unicodes=tfmdata.unicodes  -      local indices=tfmdata.indices -      local characters=tfmdata.characters -      local descriptions=tfmdata.descriptions -      local sharedkerns={} -      for u,chr in next,characters do -        local d=descriptions[u] -        if d then -          local dk=d.mykerns  -          if dk then -            local s=sharedkerns[dk] -            if s==false then -            elseif s then -              chr.kerns=s -            else -              local t,done=chr.kerns or {},false -              for l=1,#lookuplist do -                local lookup=lookuplist[l] -                local kerns=dk[lookup] -                if kerns then -                  for k,v in next,kerns do -                    if v~=0 and not t[k] then  -                      t[k],done=v,true -                      if trace_baseinit and trace_kerns then -                        logs.report("define otf","%s: base kern %s + %s => %s",cref(kind,lookup),gref(descriptions,u),gref(descriptions,k),v) -                      end -                    end -                  end -                end -              end -              if done then -                sharedkerns[dk]=t -                chr.kerns=t  -              else -                sharedkerns[dk]=false -              end -            end -          end -        end -      end -    end -  end -end -local supported_gsub={ -  'liga','dlig','rlig','hlig', -  'pnum','onum','tnum','lnum', -  'zero', -  'smcp','cpsp','c2sc','ornm','aalt', -  'hwid','fwid', -  'ssty','rtlm', -} -local supported_gpos={ -  'kern' -} -function otf.features.register_base_substitution(tag) -  supported_gsub[#supported_gsub+1]=tag -end -function otf.features.register_base_kern(tag) -  supported_gsub[#supported_gpos+1]=tag -end -local basehash,basehashes={},1 -function fonts.initializers.base.otf.features(tfmdata,value) -  if true then -    local t=trace_preparing and os.clock() -    local features=tfmdata.shared.features -    if features then -      local h={} -      for f=1,#supported_gsub do -        local feature=supported_gsub[f] -        local value=features[feature] -        prepare_base_substitutions(tfmdata,feature,value) -        if value then -          h[#h+1]=feature.."="..tostring(value) -        end -      end -      for f=1,#supported_gpos do -        local feature=supported_gpos[f] -        local value=features[feature] -        prepare_base_kerns(tfmdata,feature,features[feature]) -        if value then -          h[#h+1]=feature.."="..tostring(value) -        end -      end -      local hash=concat(h," ") -      local base=basehash[hash] -      if not base then -        basehashes=basehashes+1 -        base=basehashes -        basehash[hash]=base -      end -      tfmdata.fullname=tfmdata.fullname.."-"..base -    end -    if trace_preparing then -      logs.report("otf define","preparation time is %0.3f seconds for %s",os.clock()-t,tfmdata.fullname or "?") -    end -  end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-otn']={ -  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,insert,remove=table.concat,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=type,next,tonumber,tostring -local lpegmatch=lpeg.match -local otf=fonts.otf -local tfm=fonts.tfm -local trace_lookups=false trackers.register("otf.lookups",function(v) trace_lookups=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_contexts=false trackers.register("otf.contexts",function(v) trace_contexts=v end) -local trace_marks=false trackers.register("otf.marks",function(v) trace_marks=v end) -local trace_kerns=false trackers.register("otf.kerns",function(v) trace_kerns=v end) -local trace_cursive=false trackers.register("otf.cursive",function(v) trace_cursive=v end) -local trace_preparing=false trackers.register("otf.preparing",function(v) trace_preparing=v end) -local trace_bugs=false trackers.register("otf.bugs",function(v) trace_bugs=v end) -local trace_details=false trackers.register("otf.details",function(v) trace_details=v end) -local trace_applied=false trackers.register("otf.applied",function(v) trace_applied=v end) -local trace_steps=false trackers.register("otf.steps",function(v) trace_steps=v end) -local trace_skips=false trackers.register("otf.skips",function(v) trace_skips=v end) -local trace_directions=false trackers.register("otf.directions",function(v) trace_directions=v end) -trackers.register("otf.verbose_chain",function(v) otf.setcontextchain(v and "verbose") end) -trackers.register("otf.normal_chain",function(v) otf.setcontextchain(v and "normal") end) -trackers.register("otf.replacements","otf.singles,otf.multiples,otf.alternatives,otf.ligatures") -trackers.register("otf.positions","otf.marks,otf.kerns,otf.cursive") -trackers.register("otf.actions","otf.replacements,otf.positions") -trackers.register("otf.injections","nodes.injections") -trackers.register("*otf.sample","otf.steps,otf.actions,otf.analyzing") -local insert_node_after=node.insert_after -local delete_node=nodes.delete -local copy_node=node.copy -local find_node_tail=node.tail or node.slide -local set_attribute=node.set_attribute -local has_attribute=node.has_attribute -local zwnj=0x200C -local zwj=0x200D -local wildcard="*" -local default="dflt" -local split_at_space=lpeg.splitters[" "] or lpeg.Ct(lpeg.splitat(" "))  -local glyph=node.id('glyph') -local glue=node.id('glue') -local kern=node.id('kern') -local disc=node.id('disc') -local whatsit=node.id('whatsit') -local state=attributes.private('state') -local markbase=attributes.private('markbase') -local markmark=attributes.private('markmark') -local markdone=attributes.private('markdone') -local cursbase=attributes.private('cursbase') -local curscurs=attributes.private('curscurs') -local cursdone=attributes.private('cursdone') -local kernpair=attributes.private('kernpair') -local set_mark=nodes.set_mark -local set_cursive=nodes.set_cursive -local set_kern=nodes.set_kern -local set_pair=nodes.set_pair -local markonce=true -local cursonce=true -local kernonce=true -local fontdata=fonts.ids -otf.features.process={} -local tfmdata=false -local otfdata=false -local characters=false -local descriptions=false -local marks=false -local indices=false -local unicodes=false -local currentfont=false -local lookuptable=false -local anchorlookups=false -local handlers={} -local rlmode=0 -local featurevalue=false -local context_setups=fonts.define.specify.context_setups -local context_numbers=fonts.define.specify.context_numbers -local context_merged=fonts.define.specify.context_merged -local special_attributes={ -  init=1, -  medi=2, -  fina=3, -  isol=4 -} -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 logprocess(...) -  if trace_steps then -    registermessage(...) -  end -  logs.report("otf direct",...) -end -local function logwarning(...) -  logs.report("otf direct",...) -end -local function gref(n) -  if type(n)=="number" then -    local description=descriptions[n] -    local name=description and description.name -    if name then -      return format("U+%04X (%s)",n,name) -    else -      return format("U+%04X",n) -    end -  elseif not n then -    return "<error in tracing>" -  else -    local num,nam={},{} -    for i=1,#n do -      local ni=n[i] -      num[#num+1]=format("U+%04X",ni) -      local dni=descriptions[ni] -      nam[#num]=(dni and dni.name) or "?" -    end -    return format("%s (%s)",concat(num," "),concat(nam," ")) -  end -end -local function cref(kind,chainname,chainlookupname,lookupname,index) -  if index then -    return format("feature %s, chain %s, sub %s, lookup %s, index %s",kind,chainname,chainlookupname,lookupname,index) -  elseif lookupname then -    return format("feature %s, chain %s, sub %s, lookup %s",kind,chainname or "?",chainlookupname or "?",lookupname) -  elseif chainlookupname then -    return format("feature %s, chain %s, sub %s",kind,chainname or "?",chainlookupname) -  elseif chainname then -    return format("feature %s, chain %s",kind,chainname) -  else -    return format("feature %s",kind) -  end -end -local function pref(kind,lookupname) -  return format("feature %s, lookup %s",kind,lookupname) -end -local function markstoligature(kind,lookupname,start,stop,char) -  local n=copy_node(start) -  local keep=start -  local current -  current,start=insert_node_after(start,start,n) -  local snext=stop.next -  current.next=snext -  if snext then -    snext.prev=current -  end -  start.prev,stop.next=nil,nil -  current.char,current.subtype,current.components=char,2,start -  return keep -end -local function toligature(kind,lookupname,start,stop,char,markflag,discfound)  -  if start~=stop then -    if discfound then -      local lignode=copy_node(start) -      lignode.font,lignode.char,lignode.subtype=start.font,char,2 -      local next,prev=stop.next,start.prev -      stop.next=nil -      lignode=node.do_ligature_n(start,stop,lignode) -      prev.next=lignode -      if next then -        next.prev=lignode -      end -      lignode.next,lignode.prev=next,prev -      start=lignode -    else  -      local deletemarks=markflag~="mark" -      local n=copy_node(start) -      local current -      current,start=insert_node_after(start,start,n) -      local snext=stop.next -      current.next=snext -      if snext then -        snext.prev=current -      end -      start.prev,stop.next=nil,nil -      current.char,current.subtype,current.components=char,2,start -      local head=current -      if deletemarks then -        if trace_marks then -          while start do -            if marks[start.char] then -              logwarning("%s: remove mark %s",pref(kind,lookupname),gref(start.char)) -            end -            start=start.next -          end -        end -      else -        local i=0 -        while start do -          if marks[start.char] then -            set_attribute(start,markdone,i) -            if trace_marks then -              logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i) -            end -            head,current=insert_node_after(head,current,copy_node(start)) -          else -            i=i+1 -          end -          start=start.next -        end -        start=current.next -        while start and start.id==glyph do -          if marks[start.char] then -            set_attribute(start,markdone,i) -            if trace_marks then -              logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i) -            end -          else -            break -          end -          start=start.next -        end -      end -      return head -    end -  else -    start.char=char -  end -  return start -end -function handlers.gsub_single(start,kind,lookupname,replacement) -  if trace_singles then -    logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(start.char),gref(replacement)) -  end -  start.char=replacement -  return start,true -end -local function alternative_glyph(start,alternatives,kind,chainname,chainlookupname,lookupname)  -  local value,choice,n=featurevalue or tfmdata.shared.features[kind],nil,#alternatives  -  if value=="random" then -    local r=math.random(1,n) -    value,choice=format("random, choice %s",r),alternatives[r] -  elseif value=="first" then -    value,choice=format("first, choice %s",1),alternatives[1] -  elseif value=="last" then -    value,choice=format("last, choice %s",n),alternatives[n] -  else -    value=tonumber(value) -    if type(value)~="number" then -      value,choice="default, choice 1",alternatives[1] -    elseif value>n then -      value,choice=format("no %s variants, taking %s",value,n),alternatives[n] -    elseif value==0 then -      value,choice=format("choice %s (no change)",value),start.char -    elseif value<1 then -      value,choice=format("no %s variants, taking %s",value,1),alternatives[1] -    else -      value,choice=format("choice %s",value),alternatives[value] -    end -  end -  if not choice then -    logwarning("%s: no variant %s for %s",cref(kind,chainname,chainlookupname,lookupname),value,gref(start.char)) -    choice,value=start.char,format("no replacement instead of %s",value) -  end -  return choice,value -end -function handlers.gsub_alternate(start,kind,lookupname,alternative,sequence) -  local choice,index=alternative_glyph(start,alternative,kind,lookupname) -  if trace_alternatives then -    logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(start.char),gref(choice),index) -  end -  start.char=choice -  return start,true -end -function handlers.gsub_multiple(start,kind,lookupname,multiple) -  if trace_multiples then -    logprocess("%s: replacing %s by multiple %s",pref(kind,lookupname),gref(start.char),gref(multiple)) -  end -  start.char=multiple[1] -  if #multiple>1 then -    for k=2,#multiple do -      local n=copy_node(start) -      n.char=multiple[k] -      local sn=start.next -      n.next=sn -      n.prev=start -      if sn then -        sn.prev=n -      end -      start.next=n -      start=n -    end -  end -  return start,true -end -function handlers.gsub_ligature(start,kind,lookupname,ligature,sequence)  -  local s,stop,discfound=start.next,nil,false -  local startchar=start.char -  if marks[startchar] then -    while s do -      local id=s.id -      if id==glyph and s.subtype<256 then -        if s.font==currentfont then -          local char=s.char -          local lg=ligature[1][char] -          if not lg then -            break -          else -            stop=s -            ligature=lg -            s=s.next -          end -        else -          break -        end -      else -        break -      end -    end -    if stop and ligature[2] then -      if trace_ligatures then -        local stopchar=stop.char -        start=markstoligature(kind,lookupname,start,stop,ligature[2]) -        logprocess("%s: replacing %s upto %s by ligature %s",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) -      else -        start=markstoligature(kind,lookupname,start,stop,ligature[2]) -      end -      return start,true -    end -  else -    local skipmark=sequence.flags[1] -    while s do -      local id=s.id -      if id==glyph and s.subtype<256 then -        if s.font==currentfont then -          local char=s.char -          if skipmark and marks[char] then -            s=s.next -          else -            local lg=ligature[1][char] -            if not lg then -              break -            else -              stop=s -              ligature=lg -              s=s.next -            end -          end -        else -          break -        end -      elseif id==disc then -        discfound=true -        s=s.next -      else -        break -      end -    end -    if stop and ligature[2] then -      if trace_ligatures then -        local stopchar=stop.char -        start=toligature(kind,lookupname,start,stop,ligature[2],skipmark,discfound) -        logprocess("%s: replacing %s upto %s by ligature %s",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) -      else -        start=toligature(kind,lookupname,start,stop,ligature[2],skipmark,discfound) -      end -      return start,true -    end -  end -  return start,false -end -function handlers.gpos_mark2base(start,kind,lookupname,markanchors,sequence) -  local markchar=start.char -  if marks[markchar] then -    local base=start.prev  -    if base and base.id==glyph and base.subtype<256 and base.font==currentfont then -      local basechar=base.char -      if marks[basechar] then -        while true do -          base=base.prev -          if base and base.id==glyph and base.subtype<256 and base.font==currentfont then -            basechar=base.char -            if not marks[basechar] then -              break -            end -          else -            if trace_bugs then -              logwarning("%s: no base for mark %s",pref(kind,lookupname),gref(markchar)) -            end -            return start,false -          end -        end -      end -      local baseanchors=descriptions[basechar] -      if baseanchors then -        baseanchors=baseanchors.anchors -      end -      if baseanchors then -        local baseanchors=baseanchors['basechar'] -        if baseanchors then -          local al=anchorlookups[lookupname] -          for anchor,ba in next,baseanchors do -            if al[anchor] then -              local ma=markanchors[anchor] -              if ma then -                local dx,dy,bound=set_mark(start,base,tfmdata.factor,rlmode,ba,ma) -                if trace_marks then -                  logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%s,%s)", -                    pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy) -                end -                return start,true -              end -            end -          end -          if trace_bugs then -            logwarning("%s, no matching anchors for mark %s and base %s",pref(kind,lookupname),gref(markchar),gref(basechar)) -          end -        end -      else -        fonts.register_message(currentfont,basechar,"no base anchors") -      end -    elseif trace_bugs then -      logwarning("%s: prev node is no char",pref(kind,lookupname)) -    end -  elseif trace_bugs then -    logwarning("%s: mark %s is no mark",pref(kind,lookupname),gref(markchar)) -  end -  return start,false -end -function handlers.gpos_mark2ligature(start,kind,lookupname,markanchors,sequence) -  local markchar=start.char -  if marks[markchar] then -    local base=start.prev  -    local index=1 -    if base and base.id==glyph and base.subtype<256 and base.font==currentfont then -      local basechar=base.char -      if marks[basechar] then -        index=index+1 -        while true do -          base=base.prev -          if base and base.id==glyph and base.subtype<256 and base.font==currentfont then -            basechar=base.char -            if marks[basechar] then -              index=index+1 -            else -              break -            end -          else -            if trace_bugs then -              logwarning("%s: no base for mark %s",pref(kind,lookupname),gref(markchar)) -            end -            return start,false -          end -        end -      end -      local i=has_attribute(start,markdone) -      if i then index=i end -      local baseanchors=descriptions[basechar] -      if baseanchors then -        baseanchors=baseanchors.anchors -        if baseanchors then -          local baseanchors=baseanchors['baselig'] -          if baseanchors then -            local al=anchorlookups[lookupname] -            for anchor,ba in next,baseanchors do -              if al[anchor] then -                local ma=markanchors[anchor] -                if ma then -                  ba=ba[index] -                  if ba then -                    local dx,dy,bound=set_mark(start,base,tfmdata.factor,rlmode,ba,ma,index) -                    if trace_marks then -                      logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%s,%s)", -                        pref(kind,lookupname),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy) -                    end -                    return start,true -                  end -                end -              end -            end -            if trace_bugs then -              logwarning("%s: no matching anchors for mark %s and baselig %s",pref(kind,lookupname),gref(markchar),gref(basechar)) -            end -          end -        end -      else -        fonts.register_message(currentfont,basechar,"no base anchors") -      end -    elseif trace_bugs then -      logwarning("%s: prev node is no char",pref(kind,lookupname)) -    end -  elseif trace_bugs then -    logwarning("%s: mark %s is no mark",pref(kind,lookupname),gref(markchar)) -  end -  return start,false -end -function handlers.gpos_mark2mark(start,kind,lookupname,markanchors,sequence) -  local markchar=start.char -  if marks[markchar] then -      local base=start.prev  -      if base and base.id==glyph and base.subtype<256 and base.font==currentfont then  -        local basechar=base.char -        local baseanchors=descriptions[basechar] -        if baseanchors then -          baseanchors=baseanchors.anchors -          if baseanchors then -            baseanchors=baseanchors['basemark'] -            if baseanchors then -              local al=anchorlookups[lookupname] -              for anchor,ba in next,baseanchors do -                if al[anchor] then -                  local ma=markanchors[anchor] -                  if ma then -                    local dx,dy,bound=set_mark(start,base,tfmdata.factor,rlmode,ba,ma) -                    if trace_marks then -                      logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%s,%s)", -                        pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy) -                    end -                    return start,true -                  end -                end -              end -              if trace_bugs then -                logwarning("%s: no matching anchors for mark %s and basemark %s",pref(kind,lookupname),gref(markchar),gref(basechar)) -              end -            end -          end -        else -          fonts.register_message(currentfont,basechar,"no base anchors") -        end -      elseif trace_bugs then -        logwarning("%s: prev node is no mark",pref(kind,lookupname)) -      end -  elseif trace_bugs then -    logwarning("%s: mark %s is no mark",pref(kind,lookupname),gref(markchar)) -  end -  return start,false -end -function handlers.gpos_cursive(start,kind,lookupname,exitanchors,sequence)  -  local alreadydone=cursonce and has_attribute(start,cursbase) -  if not alreadydone then -    local done=false -    local startchar=start.char -    if marks[startchar] then -      if trace_cursive then -        logprocess("%s: ignoring cursive for mark %s",pref(kind,lookupname),gref(startchar)) -      end -    else -      local nxt=start.next -      while not done and nxt and nxt.id==glyph and nxt.subtype<256 and nxt.font==currentfont do -        local nextchar=nxt.char -        if marks[nextchar] then -          nxt=nxt.next -        else -          local entryanchors=descriptions[nextchar] -          if entryanchors then -            entryanchors=entryanchors.anchors -            if entryanchors then -              entryanchors=entryanchors['centry'] -              if entryanchors then -                local al=anchorlookups[lookupname] -                for anchor,entry in next,entryanchors do -                  if al[anchor] then -                    local exit=exitanchors[anchor] -                    if exit then -                      local dx,dy,bound=set_cursive(start,nxt,tfmdata.factor,rlmode,exit,entry,characters[startchar],characters[nextchar]) -                      if trace_cursive then -                        logprocess("%s: moving %s to %s cursive (%s,%s) using anchor %s and bound %s in rlmode %s",pref(kind,lookupname),gref(startchar),gref(nextchar),dx,dy,anchor,bound,rlmode) -                      end -                      done=true -                      break -                    end -                  end -                end -              end -            end -          else -            fonts.register_message(currentfont,startchar,"no entry anchors") -          end -          break -        end -      end -    end -    return start,done -  else -    if trace_cursive and trace_details then -      logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(start.char),alreadydone) -    end -    return start,false -  end -end -function handlers.gpos_single(start,kind,lookupname,kerns,sequence) -  local startchar=start.char -  local dx,dy,w,h=set_pair(start,tfmdata.factor,rlmode,sequence.flags[4],kerns,characters[startchar]) -  if trace_kerns then -    logprocess("%s: shifting single %s by (%s,%s) and correction (%s,%s)",pref(kind,lookupname),gref(startchar),dx,dy,w,h) -  end -  return start,false -end -function handlers.gpos_pair(start,kind,lookupname,kerns,sequence) -  local snext=start.next -  if not snext then -    return start,false -  else -    local prev,done=start,false -    local factor=tfmdata.factor -    while snext and snext.id==glyph and snext.subtype<256 and snext.font==currentfont do -      local nextchar=snext.char -local krn=kerns[nextchar] -      if not krn and marks[nextchar] then -        prev=snext -        snext=snext.next -      else -        local krn=kerns[nextchar] -        if not krn then -        elseif type(krn)=="table" then -          if krn[1]=="pair" then -            local a,b=krn[3],krn[4] -            if a and #a>0 then -              local startchar=start.char -              local x,y,w,h=set_pair(start,factor,rlmode,sequence.flags[4],a,characters[startchar]) -              if trace_kerns then -                logprocess("%s: shifting first of pair %s and %s by (%s,%s) and correction (%s,%s)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h) -              end -            end -            if b and #b>0 then -              local startchar=start.char -              local x,y,w,h=set_pair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar]) -              if trace_kerns then -                logprocess("%s: shifting second of pair %s and %s by (%s,%s) and correction (%s,%s)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h) -              end -            end -          else -            logs.report("%s: check this out (old kern stuff)",pref(kind,lookupname)) -            local a,b=krn[3],krn[7] -            if a and a~=0 then -              local k=set_kern(snext,factor,rlmode,a) -              if trace_kerns then -                logprocess("%s: inserting first kern %s between %s and %s",pref(kind,lookupname),k,gref(prev.char),gref(nextchar)) -              end -            end -            if b and b~=0 then -              logwarning("%s: ignoring second kern xoff %s",pref(kind,lookupname),b*factor) -            end -          end -          done=true -        elseif krn~=0 then -          local k=set_kern(snext,factor,rlmode,krn) -          if trace_kerns then -            logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(prev.char),gref(nextchar)) -          end -          done=true -        end -        break -      end -    end -    return start,done -  end -end -local chainmores={} -local chainprocs={} -local function logprocess(...) -  if trace_steps then -    registermessage(...) -  end -  logs.report("otf subchain",...) -end -local function logwarning(...) -  logs.report("otf subchain",...) -end -function chainmores.chainsub(start,stop,kind,chainname,currentcontext,cache,lookuplist,chainlookupname,n) -  logprocess("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname)) -  return start,false -end -function chainmores.gsub_multiple(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname,n) -  logprocess("%s: gsub_multiple not yet supported",cref(kind,chainname,chainlookupname)) -  return start,false -end -function chainmores.gsub_alternate(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname,n) -  logprocess("%s: gsub_alternate not yet supported",cref(kind,chainname,chainlookupname)) -  return start,false -end -local function logprocess(...) -  if trace_steps then -    registermessage(...) -  end -  logs.report("otf chain",...) -end -local function logwarning(...) -  logs.report("otf chain",...) -end -function chainprocs.chainsub(start,stop,kind,chainname,currentcontext,cache,lookuplist,chainlookupname) -  logwarning("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname)) -  return start,false -end -function chainprocs.reversesub(start,stop,kind,chainname,currentcontext,cache,replacements) -  local char=start.char -  local replacement=replacements[char] -  if replacement then -    if trace_singles then -      logprocess("%s: single reverse replacement of %s by %s",cref(kind,chainname),gref(char),gref(replacement)) -    end -    start.char=replacement -    return start,true -  else -    return start,false -  end -end -local function delete_till_stop(start,stop,ignoremarks) -  if start~=stop then -    local done=false -    while not done do -      done=start==stop -      delete_node(start,start.next) -    end -  end -end -function chainprocs.gsub_single(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname,chainindex) -  if not chainindex then -    delete_till_stop(start,stop)  -  end -  local current=start -  local subtables=currentlookup.subtables -  while current do -    if current.id==glyph then -      local currentchar=current.char -      local lookupname=subtables[1] -      local replacement=cache.gsub_single[lookupname] -      if not replacement then -        if trace_bugs then -          logwarning("%s: no single hits",cref(kind,chainname,chainlookupname,lookupname,chainindex)) -        end -      else -        replacement=replacement[currentchar] -        if not replacement then -          if trace_bugs then -            logwarning("%s: no single for %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(currentchar)) -          end -        else -          if trace_singles then -            logprocess("%s: replacing single %s by %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(currentchar),gref(replacement)) -          end -          current.char=replacement -        end -      end -      return start,true -    elseif current==stop then -      break -    else -      current=current.next -    end -  end -  return start,false -end -chainmores.gsub_single=chainprocs.gsub_single -function chainprocs.gsub_multiple(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname) -  delete_till_stop(start,stop) -  local startchar=start.char -  local subtables=currentlookup.subtables -  local lookupname=subtables[1] -  local replacements=cache.gsub_multiple[lookupname] -  if not replacements then -    if trace_bugs then -      logwarning("%s: no multiple hits",cref(kind,chainname,chainlookupname,lookupname)) -    end -  else -    replacements=replacements[startchar] -    if not replacements then -      if trace_bugs then -        logwarning("%s: no multiple for %s",cref(kind,chainname,chainlookupname,lookupname),gref(startchar)) -      end -    else -      if trace_multiples then -        logprocess("%s: replacing %s by multiple characters %s",cref(kind,chainname,chainlookupname,lookupname),gref(startchar),gref(replacements)) -      end -      local sn=start.next -      for k=1,#replacements do -        if k==1 then -          start.char=replacements[k] -        else -          local n=copy_node(start)  -          n.char=replacements[k] -          n.next,n.prev=sn,start -          if sn then -            sn.prev=n -          end -          start.next,start=n,n -        end -      end -      return start,true -    end -  end -  return start,false -end -function chainprocs.gsub_alternate(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname) -  delete_till_stop(start,stop) -  local current=start -  local subtables=currentlookup.subtables -  while current do -    if current.id==glyph then -      local currentchar=current.char -      local lookupname=subtables[1] -      local alternatives=cache.gsub_alternate[lookupname] -      if not alternatives then -        if trace_bugs then -          logwarning("%s: no alternative hits",cref(kind,chainname,chainlookupname,lookupname)) -        end -      else -        alternatives=alternatives[currentchar] -        if not alternatives then -          if trace_bugs then -            logwarning("%s: no alternative for %s",cref(kind,chainname,chainlookupname,lookupname),gref(currentchar)) -          end -        else -          local choice,index=alternative_glyph(current,alternatives,kind,chainname,chainlookupname,lookupname) -          current.char=choice -          if trace_alternatives then -            logprocess("%s: replacing single %s by alternative %s (%s)",cref(kind,chainname,chainlookupname,lookupname),index,gref(currentchar),gref(choice),index) -          end -        end -      end -      return start,true -    elseif current==stop then -      break -    else -      current=current.next -    end -  end -  return start,false -end -function chainprocs.gsub_ligature(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname,chainindex) -  local startchar=start.char -  local subtables=currentlookup.subtables -  local lookupname=subtables[1] -  local ligatures=cache.gsub_ligature[lookupname] -  if not ligatures then -    if trace_bugs then -      logwarning("%s: no ligature hits",cref(kind,chainname,chainlookupname,lookupname,chainindex)) -    end -  else -    ligatures=ligatures[startchar] -    if not ligatures then -      if trace_bugs then -        logwarning("%s: no ligatures starting with %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar)) -      end -    else -      local s,discfound,last,nofreplacements=start.next,false,stop,0 -      while s do -        local id=s.id -        if id==disc then -          s=s.next -          discfound=true -        else -          local schar=s.char -          if marks[schar] then  -            s=s.next -          else -            local lg=ligatures[1][schar] -            if not lg then -              break -            else -              ligatures,last,nofreplacements=lg,s,nofreplacements+1 -              if s==stop then -                break -              else -                s=s.next -              end -            end -          end -        end -      end -      local l2=ligatures[2] -      if l2 then -        if chainindex then -          stop=last -        end -        if trace_ligatures then -          if start==stop then -            logprocess("%s: replacing character %s by ligature %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(l2)) -          else -            logprocess("%s: replacing character %s upto %s by ligature %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(stop.char),gref(l2)) -          end -        end -        start=toligature(kind,lookupname,start,stop,l2,currentlookup.flags[1],discfound) -        return start,true,nofreplacements -      elseif trace_bugs then -        if start==stop then -          logwarning("%s: replacing character %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar)) -        else -          logwarning("%s: replacing character %s upto %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(stop.char)) -        end -      end -    end -  end -  return start,false,0 -end -chainmores.gsub_ligature=chainprocs.gsub_ligature -function chainprocs.gpos_mark2base(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname) -  local markchar=start.char -  if marks[markchar] then -    local subtables=currentlookup.subtables -    local lookupname=subtables[1] -    local markanchors=cache.gpos_mark2base[lookupname] -    if markanchors then -      markanchors=markanchors[markchar] -    end -    if markanchors then -      local base=start.prev  -      if base and base.id==glyph and base.subtype<256 and base.font==currentfont then -        local basechar=base.char -        if marks[basechar] then -          while true do -            base=base.prev -            if base and base.id==glyph and base.subtype<256 and base.font==currentfont then -              basechar=base.char -              if not marks[basechar] then -                break -              end -            else -              if trace_bugs then -                logwarning("%s: no base for mark %s",pref(kind,lookupname),gref(markchar)) -              end -              return start,false -            end -          end -        end -        local baseanchors=descriptions[basechar].anchors -        if baseanchors then -          local baseanchors=baseanchors['basechar'] -          if baseanchors then -            local al=anchorlookups[lookupname] -            for anchor,ba in next,baseanchors do -              if al[anchor] then -                local ma=markanchors[anchor] -                if ma then -                  local dx,dy,bound=set_mark(start,base,tfmdata.factor,rlmode,ba,ma) -                  if trace_marks then -                    logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%s,%s)", -                      cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy) -                  end -                  return start,true -                end -              end -            end -            if trace_bugs then -              logwarning("%s, no matching anchors for mark %s and base %s",cref(kind,chainname,chainlookupname,lookupname),gref(markchar),gref(basechar)) -            end -          end -        end -      elseif trace_bugs then -        logwarning("%s: prev node is no char",cref(kind,chainname,chainlookupname,lookupname)) -      end -    elseif trace_bugs then -      logwarning("%s: mark %s has no anchors",cref(kind,chainname,chainlookupname,lookupname),gref(markchar)) -    end -  elseif trace_bugs then -    logwarning("%s: mark %s is no mark",cref(kind,chainname,chainlookupname),gref(markchar)) -  end -  return start,false -end -function chainprocs.gpos_mark2ligature(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname) -  local markchar=start.char -  if marks[markchar] then -    local subtables=currentlookup.subtables -    local lookupname=subtables[1] -    local markanchors=cache.gpos_mark2ligature[lookupname] -    if markanchors then -      markanchors=markanchors[markchar] -    end -    if markanchors then -      local base=start.prev  -      local index=1 -      if base and base.id==glyph and base.subtype<256 and base.font==currentfont then -        local basechar=base.char -        if marks[basechar] then -          index=index+1 -          while true do -            base=base.prev -            if base and base.id==glyph and base.subtype<256 and base.font==currentfont then -              basechar=base.char -              if marks[basechar] then -                index=index+1 -              else -                break -              end -            else -              if trace_bugs then -                logwarning("%s: no base for mark %s",cref(kind,chainname,chainlookupname,lookupname),markchar) -              end -              return start,false -            end -          end -        end -        local i=has_attribute(start,markdone) -        if i then index=i end -        local baseanchors=descriptions[basechar].anchors -        if baseanchors then -          local baseanchors=baseanchors['baselig'] -          if baseanchors then -            local al=anchorlookups[lookupname] -            for anchor,ba in next,baseanchors do -              if al[anchor] then -                local ma=markanchors[anchor] -                if ma then -                  ba=ba[index] -                  if ba then -                    local dx,dy,bound=set_mark(start,base,tfmdata.factor,rlmode,ba,ma,index) -                    if trace_marks then -                      logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%s,%s)", -                        cref(kind,chainname,chainlookupname,lookupname),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy) -                    end -                    return start,true -                  end -                end -              end -            end -            if trace_bugs then -              logwarning("%s: no matching anchors for mark %s and baselig %s",cref(kind,chainname,chainlookupname,lookupname),gref(markchar),gref(basechar)) -            end -          end -        end -      elseif trace_bugs then -        logwarning("feature %s, lookup %s: prev node is no char",kind,lookupname) -      end -    elseif trace_bugs then -      logwarning("%s: mark %s has no anchors",cref(kind,chainname,chainlookupname,lookupname),gref(markchar)) -    end -  elseif trace_bugs then -    logwarning("%s: mark %s is no mark",cref(kind,chainname,chainlookupname),gref(markchar)) -  end -  return start,false -end -function chainprocs.gpos_mark2mark(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname) -  local markchar=start.char -  if marks[markchar] then -      local subtables=currentlookup.subtables -      local lookupname=subtables[1] -      local markanchors=cache.gpos_mark2mark[lookupname] -      if markanchors then -        markanchors=markanchors[markchar] -      end -      if markanchors then -        local base=start.prev  -        if base and base.id==glyph and base.subtype<256 and base.font==currentfont then  -          local basechar=base.char -          local baseanchors=descriptions[basechar].anchors -          if baseanchors then -            baseanchors=baseanchors['basemark'] -            if baseanchors then -              local al=anchorlookups[lookupname] -              for anchor,ba in next,baseanchors do -                if al[anchor] then -                  local ma=markanchors[anchor] -                  if ma then -                    local dx,dy,bound=set_mark(start,base,tfmdata.factor,rlmode,ba,ma) -                    if trace_marks then -                      logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%s,%s)", -                        cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy) -                    end -                    return start,true -                  end -                end -              end -              if trace_bugs then -                logwarning("%s: no matching anchors for mark %s and basemark %s",gref(kind,chainname,chainlookupname,lookupname),gref(markchar),gref(basechar)) -              end -            end -          end -        elseif trace_bugs then -          logwarning("%s: prev node is no mark",cref(kind,chainname,chainlookupname,lookupname)) -        end -      elseif trace_bugs then -        logwarning("%s: mark %s has no anchors",cref(kind,chainname,chainlookupname,lookupname),gref(markchar)) -      end -  elseif trace_bugs then -    logwarning("%s: mark %s is no mark",cref(kind,chainname,chainlookupname),gref(markchar)) -  end -  return start,false -end -function chainprocs.gpos_cursive(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname) -  local alreadydone=cursonce and has_attribute(start,cursbase) -  if not alreadydone then -    local startchar=start.char -    local subtables=currentlookup.subtables -    local lookupname=subtables[1] -    local exitanchors=cache.gpos_cursive[lookupname] -    if exitanchors then -      exitanchors=exitanchors[startchar] -    end -    if exitanchors then -      local done=false -      if marks[startchar] then -        if trace_cursive then -          logprocess("%s: ignoring cursive for mark %s",pref(kind,lookupname),gref(startchar)) -        end -      else -        local nxt=start.next -        while not done and nxt and nxt.id==glyph and nxt.subtype<256 and nxt.font==currentfont do -          local nextchar=nxt.char -          if marks[nextchar] then -            nxt=nxt.next -          else -            local entryanchors=descriptions[nextchar] -            if entryanchors then -              entryanchors=entryanchors.anchors -              if entryanchors then -                entryanchors=entryanchors['centry'] -                if entryanchors then -                  local al=anchorlookups[lookupname] -                  for anchor,entry in next,entryanchors do -                    if al[anchor] then -                      local exit=exitanchors[anchor] -                      if exit then -                        local dx,dy,bound=set_cursive(start,nxt,tfmdata.factor,rlmode,exit,entry,characters[startchar],characters[nextchar]) -                        if trace_cursive then -                          logprocess("%s: moving %s to %s cursive (%s,%s) using anchor %s and bound %s in rlmode %s",pref(kind,lookupname),gref(startchar),gref(nextchar),dx,dy,anchor,bound,rlmode) -                        end -                        done=true -                        break -                      end -                    end -                  end -                end -              end -            else -              fonts.register_message(currentfont,startchar,"no entry anchors") -            end -            break -          end -        end -      end -      return start,done -    else -      if trace_cursive and trace_details then -        logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(start.char),alreadydone) -      end -      return start,false -    end -  end -  return start,false -end -function chainprocs.gpos_single(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname,chainindex,sequence) -  local startchar=start.char -  local subtables=currentlookup.subtables -  local lookupname=subtables[1] -  local kerns=cache.gpos_single[lookupname] -  if kerns then -    kerns=kerns[startchar] -    if kerns then -      local dx,dy,w,h=set_pair(start,tfmdata.factor,rlmode,sequence.flags[4],kerns,characters[startchar]) -      if trace_kerns then -        logprocess("%s: shifting single %s by (%s,%s) and correction (%s,%s)",cref(kind,chainname,chainlookupname),gref(startchar),dx,dy,w,h) -      end -    end -  end -  return start,false -end -function chainprocs.gpos_pair(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname,chainindex,sequence) -  local snext=start.next -  if snext then -    local startchar=start.char -    local subtables=currentlookup.subtables -    local lookupname=subtables[1] -    local kerns=cache.gpos_pair[lookupname] -    if kerns then -      kerns=kerns[startchar] -      if kerns then -        local prev,done=start,false -        local factor=tfmdata.factor -        while snext and snext.id==glyph and snext.subtype<256 and snext.font==currentfont do -          local nextchar=snext.char -          local krn=kerns[nextchar] -          if not krn and marks[nextchar] then -            prev=snext -            snext=snext.next -          else -            if not krn then -            elseif type(krn)=="table" then -              if krn[1]=="pair" then -                local a,b=krn[3],krn[4] -                if a and #a>0 then -                  local startchar=start.char -                  local x,y,w,h=set_pair(start,factor,rlmode,sequence.flags[4],a,characters[startchar]) -                  if trace_kerns then -                    logprocess("%s: shifting first of pair %s and %s by (%s,%s) and correction (%s,%s)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h) -                  end -                end -                if b and #b>0 then -                  local startchar=start.char -                  local x,y,w,h=set_pair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar]) -                  if trace_kerns then -                    logprocess("%s: shifting second of pair %s and %s by (%s,%s) and correction (%s,%s)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h) -                  end -                end -              else -                logs.report("%s: check this out (old kern stuff)",cref(kind,chainname,chainlookupname)) -                local a,b=krn[3],krn[7] -                if a and a~=0 then -                  local k=set_kern(snext,factor,rlmode,a) -                  if trace_kerns then -                    logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(prev.char),gref(nextchar)) -                  end -                end -                if b and b~=0 then -                  logwarning("%s: ignoring second kern xoff %s",cref(kind,chainname,chainlookupname),b*factor) -                end -              end -              done=true -            elseif krn~=0 then -              local k=set_kern(snext,factor,rlmode,krn) -              if trace_kerns then -                logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(prev.char),gref(nextchar)) -              end -              done=true -            end -            break -          end -        end -        return start,done -      end -    end -  end -  return start,false -end -local function show_skip(kind,chainname,char,ck,class) -  if ck[9] then -    logwarning("%s: skipping char %s (%s) in rule %s, lookuptype %s (%s=>%s)",cref(kind,chainname),gref(char),class,ck[1],ck[2],ck[9],ck[10]) -  else -    logwarning("%s: skipping char %s (%s) in rule %s, lookuptype %s",cref(kind,chainname),gref(char),class,ck[1],ck[2]) -  end -end -local function normal_handle_contextchain(start,kind,chainname,contexts,sequence,cache) -  local flags,done=sequence.flags,false -  local skipmark,skipligature,skipbase=flags[1],flags[2],flags[3] -  local someskip=skipmark or skipligature or skipbase  -  local markclass=sequence.markclass  -  local skipped=false -  for k=1,#contexts do -    local match,current,last=true,start,start -    local ck=contexts[k] -    local seq=ck[3] -    local s=#seq -    if s==1 then -      match=current.id==glyph and current.subtype<256 and current.font==currentfont and seq[1][current.char] -    else -      local f,l=ck[4],ck[5] -      if f==l then -        match=true -      else -        local n=f+1 -        last=last.next -          while n<=l do -            if last then -              local id=last.id -              if id==glyph then -                if last.subtype<256 and last.font==currentfont then -                  local char=last.char -                  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(kind,chainname,char,ck,class) -                      end -                      last=last.next -                    elseif seq[n][char] then -                      if n<l then -                        last=last.next -                      end -                      n=n+1 -                    else -                      match=false break -                    end -                  else -                    match=false break -                  end -                else -                  match=false break -                end -              elseif id==disc then  -                last=last.next -              else -                match=false break -              end -            else -              match=false break -            end -          end -      end -      if match and f>1 then -        local prev=start.prev -        if prev then -          local n=f-1 -          while n>=1 do -            if prev then -              local id=prev.id -              if id==glyph then -                if prev.subtype<256 and prev.font==currentfont then  -                  local char=prev.char -                  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(kind,chainname,char,ck,class) -                      end -                    elseif seq[n][char] then -                      n=n -1 -                    else -                      match=false break -                    end -                  else -                    match=false break -                  end -                else -                  match=false break -                end -              elseif id==disc then -              elseif seq[n][32] then -                n=n -1 -              else -                match=false break -              end -              prev=prev.prev -            elseif seq[n][32] then -              n=n -1 -            else -              match=false break -            end -          end -        elseif f==2 then -          match=seq[1][32] -        else -          for n=f-1,1 do -            if not seq[n][32] then -              match=false break -            end -          end -        end -      end -      if match and s>l then -        local current=last.next -        if current then -          local n=l+1 -          while n<=s do -            if current then -              local id=current.id -              if id==glyph then -                if current.subtype<256 and current.font==currentfont then  -                  local char=current.char -                  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(kind,chainname,char,ck,class) -                      end -                    elseif seq[n][char] then -                      n=n+1 -                    else -                      match=false break -                    end -                  else -                    match=false break -                  end -                else -                  match=false break -                end -              elseif id==disc then -              elseif seq[n][32] then  -                n=n+1 -              else -                match=false break -              end -              current=current.next -            elseif seq[n][32] then -              n=n+1 -            else -              match=false break -            end -          end -        elseif s-l==1 then -          match=seq[s][32] -        else -          for n=l+1,s do -            if not seq[n][32] then -              match=false break -            end -          end -        end -      end -    end -    if match then -      if trace_contexts then -        local rule,lookuptype,f,l=ck[1],ck[2],ck[4],ck[5] -        local char=start.char -        if ck[9] then -          logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %s (%s=>%s)",cref(kind,chainname),rule,gref(char),f-1,l-f+1,s-l,lookuptype,ck[9],ck[10]) -        else -          logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %s",cref(kind,chainname),rule,gref(char),f-1,l-f+1,s-l,lookuptype) -        end -      end -      local chainlookups=ck[6] -      if chainlookups then -        local nofchainlookups=#chainlookups -        if nofchainlookups==1 then -          local chainlookupname=chainlookups[1] -          local chainlookup=lookuptable[chainlookupname] -          local cp=chainprocs[chainlookup.type] -          if cp then -            start,done=cp(start,last,kind,chainname,ck,cache,chainlookup,chainlookupname,nil,sequence) -          else -            logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type) -          end -         else -          local i=1 -          repeat -if skipped then -  while true do -    local char=start.char -    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 -        start=start.next -      else -        break -      end -    else -      break -    end -  end -end -            local chainlookupname=chainlookups[i] -            local chainlookup=lookuptable[chainlookupname] -            local cp=chainmores[chainlookup.type] -            if cp then -              local ok,n -              start,ok,n=cp(start,last,kind,chainname,ck,cache,chainlookup,chainlookupname,i,sequence) -              if ok then -                done=true -                i=i+(n or 1) -              else -                i=i+1 -              end -            else -              logprocess("%s: multiple subchains for %s are not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type) -              i=i+1 -            end -            start=start.next -          until i>nofchainlookups -        end -      else -        local replacements=ck[7] -        if replacements then -          start,done=chainprocs.reversesub(start,last,kind,chainname,ck,cache,replacements)  -        else -          done=true  -          if trace_contexts then -            logprocess("%s: skipping match",cref(kind,chainname)) -          end -        end -      end -    end -  end -  return start,done -end -local verbose_handle_contextchain=function(font,...) -  logwarning("no verbose handler installed, reverting to 'normal'") -  otf.setcontextchain() -  return normal_handle_contextchain(...) -end -otf.chainhandlers={ -  normal=normal_handle_contextchain, -  verbose=verbose_handle_contextchain, -} -function otf.setcontextchain(method) -  if not method or method=="normal" or not otf.chainhandlers[method] then -    if handlers.contextchain then  -      logwarning("installing normal contextchain handler") -    end -    handlers.contextchain=normal_handle_contextchain -  else -    logwarning("installing contextchain handler '%s'",method) -    local handler=otf.chainhandlers[method] -    handlers.contextchain=function(...) -      return handler(currentfont,...)  -    end -  end -  handlers.gsub_context=handlers.contextchain -  handlers.gsub_contextchain=handlers.contextchain -  handlers.gsub_reversecontextchain=handlers.contextchain -  handlers.gpos_contextchain=handlers.contextchain -  handlers.gpos_context=handlers.contextchain -end -otf.setcontextchain() -local missing={}  -local function logprocess(...) -  if trace_steps then -    registermessage(...) -  end -  logs.report("otf process",...) -end -local function logwarning(...) -  logs.report("otf process",...) -end -local function report_missing_cache(typ,lookup) -  local f=missing[currentfont] if not f then f={} missing[currentfont]=f end -  local t=f[typ]        if not t then t={} f[typ]=t end -  if not t[lookup] then -    t[lookup]=true -    logwarning("missing cache for lookup %s of type %s in font %s (%s)",lookup,typ,currentfont,tfmdata.fullname) -  end -end -local resolved={} -function fonts.methods.node.otf.features(head,font,attr) -  if trace_steps then -    checkstep(head) -  end -  tfmdata=fontdata[font] -  local shared=tfmdata.shared -  otfdata=shared.otfdata -  local luatex=otfdata.luatex -  descriptions=tfmdata.descriptions -  characters=tfmdata.characters -  indices=tfmdata.indices -  unicodes=tfmdata.unicodes -  marks=tfmdata.marks -  anchorlookups=luatex.lookup_to_anchor -  currentfont=font -  rlmode=0 -  local featuredata=otfdata.shared.featuredata  -  local sequences=luatex.sequences -  lookuptable=luatex.lookups -  local done=false -  local script,language,s_enabled,a_enabled,dyn -  local attribute_driven=attr and attr~=0 -  if attribute_driven then -    local features=context_setups[context_numbers[attr]]  -    dyn=context_merged[attr] or 0 -    language,script=features.language or "dflt",features.script or "dflt" -    a_enabled=features  -    if dyn==2 or dyn==-2 then -      s_enabled=shared.features -    end -  else -    language,script=tfmdata.language or "dflt",tfmdata.script or "dflt" -    s_enabled=shared.features  -    dyn=0 -  end -  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 end -  local ra=rl   [attr]   if ra==nil then ra={} rl   [attr]=ra end -  for s=1,#sequences do -    local pardir,txtdir,success=0,{},false -    local sequence=sequences[s] -    local r=ra[s]  -    if r==nil then -      local chain=sequence.chain or 0 -      local features=sequence.features -      if not features then -        r=false  -      else -        local valid,attribute,kind,what=false,false -        for k,v in next,features do -          local s_e=s_enabled and s_enabled[k] -          local a_e=a_enabled and a_enabled[k] -          if s_e or a_e then -            local l=v[script] or v[wildcard] -            if l then -              if l[language] then -                valid,what=s_e or a_e,language -              elseif l[wildcard] then -                valid,what=s_e or a_e,wildcard -              end -              if valid then -                kind,attribute=k,special_attributes[k] or false -                if a_e and dyn<0 then -                  valid=false -                end -                if trace_applied then -                  local typ,action=match(sequence.type,"(.*)_(.*)") -                  logs.report("otf node mode", -                    "%s font: %03i, dynamic: %03i, kind: %s, lookup: %3i, script: %-4s, language: %-4s (%-4s), type: %s, action: %s, name: %s", -                    (valid and "+") or "-",font,attr or 0,kind,s,script,language,what,typ,action,sequence.name) -                end -                break -              end -            end -          end -        end -        if valid then -          r={ valid,attribute,chain,kind } -        else -          r=false  -        end -      end -      ra[s]=r -    end -    featurevalue=r and r[1]  -    if featurevalue then -      local attribute,chain,typ,subtables=r[2],r[3],sequence.type,sequence.subtables -      if chain<0 then -        local handler=handlers[typ] -        local thecache=featuredata[typ] or {} -        local start=find_node_tail(head)  -        while start do -          local id=start.id -          if id==glyph then -            if start.subtype<256 and start.font==font then -              local a=has_attribute(start,0) -              if a then -                a=a==attr -              else -                a=true -              end -              if a then -                for i=1,#subtables do -                  local lookupname=subtables[i] -                  local lookupcache=thecache[lookupname] -                  if lookupcache then -                    local lookupmatch=lookupcache[start.char] -                    if lookupmatch then -                      start,success=handler(start,r[4],lookupname,lookupmatch,sequence,featuredata,i) -                      if success then -                        break -                      end -                    end -                  else -                    report_missing_cache(typ,lookupname) -                  end -                end -                if start then start=start.prev end -              else -                start=start.prev -              end -            else -              start=start.prev -            end -          else -            start=start.prev -          end -        end -      else -        local handler=handlers[typ] -        local ns=#subtables -        local thecache=featuredata[typ] or {} -        local start=head  -        rlmode=0  -        if ns==1 then -          local lookupname=subtables[1] -          local lookupcache=thecache[lookupname] -          if not lookupcache then -            report_missing_cache(typ,lookupname) -          else -            while start do -              local id=start.id -              if id==glyph then -                if start.subtype<256 and start.font==font then -                  local a=has_attribute(start,0) -                  if a then -                    a=(a==attr) and (not attribute or has_attribute(start,state,attribute)) -                  else -                    a=not attribute or has_attribute(start,state,attribute) -                  end -                  if a then -                    local lookupmatch=lookupcache[start.char] -                    if lookupmatch then -                      local ok -                      start,ok=handler(start,r[4],lookupname,lookupmatch,sequence,featuredata,1) -                      if ok then -                        success=true -                      end -                    end -                    if start then start=start.next end -                  else -                    start=start.next -                  end -                else -                  start=start.next -                end -              elseif id==whatsit then -                local subtype=start.subtype -                if subtype==7 then -                  local dir=start.dir -                  if   dir=="+TRT" or dir=="+TLT" then -                    insert(txtdir,dir) -                  elseif dir=="-TRT" or dir=="-TLT" then -                    remove(txtdir) -                  end -                  local d=txtdir[#txtdir] -                  if d=="+TRT" then -                    rlmode=-1 -                  elseif d=="+TLT" then -                    rlmode=1 -                  else -                    rlmode=pardir -                  end -                  if trace_directions then -                    logs.report("fonts","directions after textdir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode) -                  end -                elseif subtype==6 then -                  local dir=start.dir -                  if dir=="TRT" then -                    pardir=-1 -                  elseif dir=="TLT" then -                    pardir=1 -                  else -                    pardir=0 -                  end -                  rlmode=pardir -                  if trace_directions then -                    logs.report("fonts","directions after pardir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode) -                  end -                end -                start=start.next -              else -                start=start.next -              end -            end -          end -        else -          while start do -            local id=start.id -            if id==glyph then -              if start.subtype<256 and start.font==font then -                local a=has_attribute(start,0) -                if a then -                  a=(a==attr) and (not attribute or has_attribute(start,state,attribute)) -                else -                  a=not attribute or has_attribute(start,state,attribute) -                end -                if a then -                  for i=1,ns do -                    local lookupname=subtables[i] -                    local lookupcache=thecache[lookupname] -                    if lookupcache then -                      local lookupmatch=lookupcache[start.char] -                      if lookupmatch then -                        local ok -                        start,ok=handler(start,r[4],lookupname,lookupmatch,sequence,featuredata,i) -                        if ok then -                          success=true -                          break -                        end -                      end -                    else -                      report_missing_cache(typ,lookupname) -                    end -                  end -                  if start then start=start.next end -                else -                  start=start.next -                end -              else -                start=start.next -              end -            elseif id==whatsit then -              local subtype=start.subtype -              if subtype==7 then -                local dir=start.dir -                if   dir=="+TRT" or dir=="+TLT" then -                  insert(txtdir,dir) -                elseif dir=="-TRT" or dir=="-TLT" then -                  remove(txtdir) -                end -                local d=txtdir[#txtdir] -                if d=="+TRT" then -                  rlmode=-1 -                elseif d=="+TLT" then -                  rlmode=1 -                else -                  rlmode=pardir -                end -                if trace_directions then -                  logs.report("fonts","directions after textdir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode) -                end -              elseif subtype==6 then -                local dir=start.dir -                if dir=="TRT" then -                  pardir=-1 -                elseif dir=="TLT" then -                  pardir=1 -                else -                  pardir=0 -                end -                rlmode=pardir -                if trace_directions then -                  logs.report("fonts","directions after pardir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode) -                end -              end -              start=start.next -            else -              start=start.next -            end -          end -        end -      end -      if success then -        done=true -      end -      if trace_steps then  -        registerstep(head) -      end -    end -  end -  return head,done -end -otf.features.prepare={} -local function split(replacement,original,cache,unicodes) -  local o,t,n={},{},0 -  for s in gmatch(original,"[^ ]+") do -    local us=unicodes[s] -    if type(us)=="number" then  -      o[#o+1]=us -    else -      o[#o+1]=us[1] -    end -  end -  for s in gmatch(replacement,"[^ ]+") do -    n=n+1 -    local us=unicodes[s] -    if type(us)=="number" then  -      t[o[n]]=us -    else -      t[o[n]]=us[1] -    end -  end -  return t -end -local function uncover(covers,result,cache,unicodes) -  for n=1,#covers do -    local c=covers[n] -    local cc=cache[c] -    if not cc then -      local t={} -      for s in gmatch(c,"[^ ]+") do -        local us=unicodes[s] -        if type(us)=="number" then -          t[us]=true -        else -          for i=1,#us do -            t[us[i]]=true -          end -        end -      end -      cache[c]=t -      result[#result+1]=t -    else -      result[#result+1]=cc -    end -  end -end -local function prepare_lookups(tfmdata) -  local otfdata=tfmdata.shared.otfdata -  local featuredata=otfdata.shared.featuredata -  local anchor_to_lookup=otfdata.luatex.anchor_to_lookup -  local lookup_to_anchor=otfdata.luatex.lookup_to_anchor -  local multiple=featuredata.gsub_multiple -  local alternate=featuredata.gsub_alternate -  local single=featuredata.gsub_single -  local ligature=featuredata.gsub_ligature -  local pair=featuredata.gpos_pair -  local position=featuredata.gpos_single -  local kerns=featuredata.gpos_pair -  local mark=featuredata.gpos_mark2mark -  local cursive=featuredata.gpos_cursive -  local unicodes=tfmdata.unicodes  -  local indices=tfmdata.indices -  local descriptions=tfmdata.descriptions -  local action={ -    substitution=function(p,lookup,glyph,unicode) -      local old,new=unicode,unicodes[p[2]] -      if type(new)=="table" then -        new=new[1] -      end -      local s=single[lookup] -      if not s then s={} single[lookup]=s end -      s[old]=new -    end, -    multiple=function (p,lookup,glyph,unicode) -      local old,new=unicode,{} -      local m=multiple[lookup] -      if not m then m={} multiple[lookup]=m end -      m[old]=new -      for pc in gmatch(p[2],"[^ ]+") do -        local upc=unicodes[pc] -        if type(upc)=="number" then -          new[#new+1]=upc -        else -          new[#new+1]=upc[1] -        end -      end -    end, -    alternate=function(p,lookup,glyph,unicode) -      local old,new=unicode,{} -      local a=alternate[lookup] -      if not a then a={} alternate[lookup]=a end -      a[old]=new -      for pc in gmatch(p[2],"[^ ]+") do -        local upc=unicodes[pc] -        if type(upc)=="number" then -          new[#new+1]=upc -        else -          new[#new+1]=upc[1] -        end -      end -    end, -    ligature=function (p,lookup,glyph,unicode) -      local first=true -      local t=ligature[lookup] -      if not t then t={} ligature[lookup]=t end -      for s in gmatch(p[2],"[^ ]+") do -        if first then -          local u=unicodes[s] -          if not u then -            logs.report("define otf","lookup %s: ligature %s => %s ignored due to invalid unicode",lookup,p[2],glyph.name) -            break -          elseif type(u)=="number" then -            if not t[u] then -              t[u]={ {} } -            end -            t=t[u] -          else -            local tt=t -            local tu -            for i=1,#u do -              local u=u[i] -              if i==1 then -                if not t[u] then -                  t[u]={ {} } -                end -                tu=t[u] -                t=tu -              else -                if not t[u] then -                  tt[u]=tu -                end -              end -            end -          end -          first=false -        else -          s=unicodes[s] -          local t1=t[1] -          if not t1[s] then -            t1[s]={ {} } -          end -          t=t1[s] -        end -      end -      t[2]=unicode -    end, -    position=function(p,lookup,glyph,unicode) -      local s=position[lookup] -      if not s then s={} position[lookup]=s end -      s[unicode]=p[2]  -    end, -    pair=function(p,lookup,glyph,unicode) -      local s=pair[lookup] -      if not s then s={} pair[lookup]=s end -      local others=s[unicode] -      if not others then others={} s[unicode]=others end -      local two=p[2] -      local upc=unicodes[two] -      if not upc then -        for pc in gmatch(two,"[^ ]+") do -          local upc=unicodes[pc] -          if type(upc)=="number" then -            others[upc]=p  -          else -            for i=1,#upc do -              others[upc[i]]=p  -            end -          end -        end -      elseif type(upc)=="number" then -        others[upc]=p  -      else -        for i=1,#upc do -          others[upc[i]]=p  -        end -      end -    end, -  } -  for unicode,glyph in next,descriptions do -    local lookups=glyph.slookups -    if lookups then -      for lookup,p in next,lookups do -        action[p[1]](p,lookup,glyph,unicode) -      end -    end -    local lookups=glyph.mlookups -    if lookups then -      for lookup,whatever in next,lookups do -        for i=1,#whatever do  -          local p=whatever[i] -          action[p[1]](p,lookup,glyph,unicode) -        end -      end -    end -    local list=glyph.mykerns -    if list then -      for lookup,krn in next,list do -        local k=kerns[lookup] -        if not k then k={} kerns[lookup]=k end -        k[unicode]=krn -      end -    end -    local oanchor=glyph.anchors -    if oanchor then -      for typ,anchors in next,oanchor do  -        if typ=="mark" then -          for name,anchor in next,anchors do -            local lookups=anchor_to_lookup[name] -            if lookups then -              for lookup,_ in next,lookups do -                local f=mark[lookup] -                if not f then f={} mark[lookup]=f end -                f[unicode]=anchors -              end -            end -          end -        elseif typ=="cexit" then  -          for name,anchor in next,anchors do -            local lookups=anchor_to_lookup[name] -            if lookups then -              for lookup,_ in next,lookups do -                local f=cursive[lookup] -                if not f then f={} cursive[lookup]=f end -                f[unicode]=anchors -              end -            end -          end -        end -      end -    end -  end -end -luatex=luatex or {}  -local function prepare_contextchains(tfmdata) -  local otfdata=tfmdata.shared.otfdata -  local lookups=otfdata.lookups -  if lookups then -    local featuredata=otfdata.shared.featuredata -    local contextchain=featuredata.gsub_contextchain  -    local reversecontextchain=featuredata.gsub_reversecontextchain  -    local characters=tfmdata.characters -    local unicodes=tfmdata.unicodes -    local indices=tfmdata.indices -    local cache=luatex.covers -    if not cache then -      cache={} -      luatex.covers=cache -    end -    for lookupname,lookupdata in next,otfdata.lookups do -      local lookuptype=lookupdata.type -      if not lookuptype then -        logs.report("otf process","missing lookuptype for %s",lookupname) -      else -        local rules=lookupdata.rules -        if rules then -          local fmt=lookupdata.format -          if fmt=="coverage" then -            if lookuptype~="chainsub" and lookuptype~="chainpos" then -              logs.report("otf process","unsupported coverage %s for %s",lookuptype,lookupname) -            else -              local contexts=contextchain[lookupname] -              if not contexts then -                contexts={} -                contextchain[lookupname]=contexts -              end -              local t={} -              for nofrules=1,#rules do  -                local rule=rules[nofrules] -                local coverage=rule.coverage -                if coverage and coverage.current then -                  local current,before,after,sequence=coverage.current,coverage.before,coverage.after,{} -                  if before then -                    uncover(before,sequence,cache,unicodes) -                  end -                  local start=#sequence+1 -                  uncover(current,sequence,cache,unicodes) -                  local stop=#sequence -                  if after then -                    uncover(after,sequence,cache,unicodes) -                  end -                  if sequence[1] then -                    t[#t+1]={ nofrules,lookuptype,sequence,start,stop,rule.lookups } -                    for unic,_ in next,sequence[start] do -                      local cu=contexts[unic] -                      if not cu then -                        contexts[unic]=t -                      end -                    end -                  end -                end -              end -            end -          elseif fmt=="reversecoverage" then -            if lookuptype~="reversesub" then -              logs.report("otf process","unsupported reverse coverage %s for %s",lookuptype,lookupname) -            else -              local contexts=reversecontextchain[lookupname] -              if not contexts then -                contexts={} -                reversecontextchain[lookupname]=contexts -              end -              local t={} -              for nofrules=1,#rules do -                local rule=rules[nofrules] -                local reversecoverage=rule.reversecoverage -                if reversecoverage and reversecoverage.current then -                  local current,before,after,replacements,sequence=reversecoverage.current,reversecoverage.before,reversecoverage.after,reversecoverage.replacements,{} -                  if before then -                    uncover(before,sequence,cache,unicodes) -                  end -                  local start=#sequence+1 -                  uncover(current,sequence,cache,unicodes) -                  local stop=#sequence -                  if after then -                    uncover(after,sequence,cache,unicodes) -                  end -                  if replacements then -                    replacements=split(replacements,current[1],cache,unicodes) -                  end -                  if sequence[1] then -                    t[#t+1]={ nofrules,lookuptype,sequence,start,stop,rule.lookups,replacements } -                    for unic,_ in next,sequence[start] do -                      local cu=contexts[unic] -                      if not cu then -                        contexts[unic]=t -                      end -                    end -                  end -                end -              end -            end -          elseif fmt=="glyphs" then -            if lookuptype~="chainsub" and lookuptype~="chainpos" then -              logs.report("otf process","unsupported coverage %s for %s",lookuptype,lookupname) -            else -              local contexts=contextchain[lookupname] -              if not contexts then -                contexts={} -                contextchain[lookupname]=contexts -              end -              local t={} -              for nofrules=1,#rules do -                local rule=rules[nofrules] -                local glyphs=rule.glyphs -                if glyphs and glyphs.names then -                  local fore,back,names,sequence=glyphs.fore,glyphs.back,glyphs.names,{} -                  if fore and fore~="" then -                    fore=lpegmatch(split_at_space,fore) -                    uncover(fore,sequence,cache,unicodes) -                  end -                  local start=#sequence+1 -                  names=lpegmatch(split_at_space,names) -                  uncover(names,sequence,cache,unicodes) -                  local stop=#sequence -                  if back and back~="" then -                    back=lpegmatch(split_at_space,back) -                    uncover(back,sequence,cache,unicodes) -                  end -                  if sequence[1] then -                    t[#t+1]={ nofrules,lookuptype,sequence,start,stop,rule.lookups } -                    for unic,_ in next,sequence[start] do -                      local cu=contexts[unic] -                      if not cu then -                        contexts[unic]=t -                      end -                    end -                  end -                end -              end -            end -          end -        end -      end -    end -  end -end -function fonts.initializers.node.otf.features(tfmdata,value) -  if true then  -    if not tfmdata.shared.otfdata.shared.initialized then -      local t=trace_preparing and os.clock() -      local otfdata=tfmdata.shared.otfdata -      local featuredata=otfdata.shared.featuredata -      featuredata.gsub_multiple={} -      featuredata.gsub_alternate={} -      featuredata.gsub_single={} -      featuredata.gsub_ligature={} -      featuredata.gsub_contextchain={} -      featuredata.gsub_reversecontextchain={} -      featuredata.gpos_pair={} -      featuredata.gpos_single={} -      featuredata.gpos_mark2base={} -      featuredata.gpos_mark2ligature=featuredata.gpos_mark2base -      featuredata.gpos_mark2mark=featuredata.gpos_mark2base -      featuredata.gpos_cursive={} -      featuredata.gpos_contextchain=featuredata.gsub_contextchain -      featuredata.gpos_reversecontextchain=featuredata.gsub_reversecontextchain -      prepare_contextchains(tfmdata) -      prepare_lookups(tfmdata) -      otfdata.shared.initialized=true -      if trace_preparing then -        logs.report("otf process","preparation time is %0.3f seconds for %s",os.clock()-t,tfmdata.fullname or "?") -      end -    end -  end -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -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,tostring,match,format,concat=type,tostring,string.match,string.format,table.concat -if not trackers then trackers={ register=function() end } end -local trace_analyzing=false trackers.register("otf.analyzing",function(v) trace_analyzing=v end) -local trace_cjk=false trackers.register("cjk.injections",function(v) trace_cjk=v end) -trackers.register("cjk.analyzing","otf.analyzing") -fonts=fonts            or {} -fonts.analyzers=fonts.analyzers       or {} -fonts.analyzers.initializers=fonts.analyzers.initializers or { node={ otf={} } } -fonts.analyzers.methods=fonts.analyzers.methods   or { node={ otf={} } } -local otf=fonts.otf -local tfm=fonts.tfm -local initializers=fonts.analyzers.initializers -local methods=fonts.analyzers.methods -local glyph=node.id('glyph') -local glue=node.id('glue') -local penalty=node.id('penalty') -local set_attribute=node.set_attribute -local has_attribute=node.has_attribute -local traverse_id=node.traverse_id -local traverse_node_list=node.traverse -local fontdata=fonts.ids -local state=attributes.private('state') -local fcs=(fonts.color and fonts.color.set)  or function() end -local fcr=(fonts.color and fonts.color.reset) or function() end -local a_to_script=otf.a_to_script -local a_to_language=otf.a_to_language -function fonts.initializers.node.otf.analyze(tfmdata,value,attr) -  local script,language -  if attr and attr>0 then -    script,language=a_to_script[attr],a_to_language[attr] -  else -    script,language=tfmdata.script,tfmdata.language -  end -  local action=initializers[script] -  if action then -    if type(action)=="function" then -      return action(tfmdata,value) -    else -      local action=action[language] -      if action then -        return action(tfmdata,value) -      end -    end -  end -  return nil -end -function fonts.methods.node.otf.analyze(head,font,attr) -  local tfmdata=fontdata[font] -  local script,language -  if attr and attr>0 then -    script,language=a_to_script[attr],a_to_language[attr] -  else -    script,language=tfmdata.script,tfmdata.language -  end -  local action=methods[script] -  if action then -    if type(action)=="function" then -      return action(head,font,attr) -    else -      action=action[language] -      if action then -        return action(head,font,attr) -      end -    end -  end -  return head,false -end -otf.features.register("analyze",true)   -table.insert(fonts.triggers,"analyze") -fonts.analyzers.methods.latn=fonts.analyzers.aux.setstate -local zwnj=0x200C -local zwj=0x200D -local isol={ -  [0x0600]=true,[0x0601]=true,[0x0602]=true,[0x0603]=true, -  [0x0608]=true,[0x060B]=true,[0x0621]=true,[0x0674]=true, -  [0x06DD]=true,[zwnj]=true, -} -local isol_fina={ -  [0x0622]=true,[0x0623]=true,[0x0624]=true,[0x0625]=true, -  [0x0627]=true,[0x0629]=true,[0x062F]=true,[0x0630]=true, -  [0x0631]=true,[0x0632]=true,[0x0648]=true,[0x0671]=true, -  [0x0672]=true,[0x0673]=true,[0x0675]=true,[0x0676]=true, -  [0x0677]=true,[0x0688]=true,[0x0689]=true,[0x068A]=true, -  [0x068B]=true,[0x068C]=true,[0x068D]=true,[0x068E]=true, -  [0x068F]=true,[0x0690]=true,[0x0691]=true,[0x0692]=true, -  [0x0693]=true,[0x0694]=true,[0x0695]=true,[0x0696]=true, -  [0x0697]=true,[0x0698]=true,[0x0699]=true,[0x06C0]=true, -  [0x06C3]=true,[0x06C4]=true,[0x06C5]=true,[0x06C6]=true, -  [0x06C7]=true,[0x06C8]=true,[0x06C9]=true,[0x06CA]=true, -  [0x06CB]=true,[0x06CD]=true,[0x06CF]=true,[0x06D2]=true, -  [0x06D3]=true,[0x06D5]=true,[0x06EE]=true,[0x06EF]=true, -  [0x0759]=true,[0x075A]=true,[0x075B]=true,[0x076B]=true, -  [0x076C]=true,[0x0771]=true,[0x0773]=true,[0x0774]=true, -	[0x0778]=true,[0x0779]=true,[0xFEF5]=true,[0xFEF7]=true, -	[0xFEF9]=true,[0xFEFB]=true, -} -local isol_fina_medi_init={ -  [0x0626]=true,[0x0628]=true,[0x062A]=true,[0x062B]=true, -  [0x062C]=true,[0x062D]=true,[0x062E]=true,[0x0633]=true, -  [0x0634]=true,[0x0635]=true,[0x0636]=true,[0x0637]=true, -  [0x0638]=true,[0x0639]=true,[0x063A]=true,[0x063B]=true, -  [0x063C]=true,[0x063D]=true,[0x063E]=true,[0x063F]=true, -  [0x0640]=true,[0x0641]=true,[0x0642]=true,[0x0643]=true, -  [0x0644]=true,[0x0645]=true,[0x0646]=true,[0x0647]=true, -  [0x0649]=true,[0x064A]=true,[0x066E]=true,[0x066F]=true, -  [0x0678]=true,[0x0679]=true,[0x067A]=true,[0x067B]=true, -  [0x067C]=true,[0x067D]=true,[0x067E]=true,[0x067F]=true, -  [0x0680]=true,[0x0681]=true,[0x0682]=true,[0x0683]=true, -  [0x0684]=true,[0x0685]=true,[0x0686]=true,[0x0687]=true, -  [0x069A]=true,[0x069B]=true,[0x069C]=true,[0x069D]=true, -  [0x069E]=true,[0x069F]=true,[0x06A0]=true,[0x06A1]=true, -  [0x06A2]=true,[0x06A3]=true,[0x06A4]=true,[0x06A5]=true, -  [0x06A6]=true,[0x06A7]=true,[0x06A8]=true,[0x06A9]=true, -  [0x06AA]=true,[0x06AB]=true,[0x06AC]=true,[0x06AD]=true, -  [0x06AE]=true,[0x06AF]=true,[0x06B0]=true,[0x06B1]=true, -  [0x06B2]=true,[0x06B3]=true,[0x06B4]=true,[0x06B5]=true, -  [0x06B6]=true,[0x06B7]=true,[0x06B8]=true,[0x06B9]=true, -  [0x06BA]=true,[0x06BB]=true,[0x06BC]=true,[0x06BD]=true, -  [0x06BE]=true,[0x06BF]=true,[0x06C1]=true,[0x06C2]=true, -  [0x06CC]=true,[0x06CE]=true,[0x06D0]=true,[0x06D1]=true, -  [0x06FA]=true,[0x06FB]=true,[0x06FC]=true,[0x06FF]=true, -  [0x0750]=true,[0x0751]=true,[0x0752]=true,[0x0753]=true, -  [0x0754]=true,[0x0755]=true,[0x0756]=true,[0x0757]=true, -  [0x0758]=true,[0x075C]=true,[0x075D]=true,[0x075E]=true, -  [0x075F]=true,[0x0760]=true,[0x0761]=true,[0x0762]=true, -  [0x0763]=true,[0x0764]=true,[0x0765]=true,[0x0766]=true, -  [0x0767]=true,[0x0768]=true,[0x0769]=true,[0x076A]=true, -  [0x076D]=true,[0x076E]=true,[0x076F]=true,[0x0770]=true, -  [0x0772]=true,[0x0775]=true,[0x0776]=true,[0x0777]=true, -  [0x077A]=true,[0x077B]=true,[0x077C]=true,[0x077D]=true, -  [0x077E]=true,[0x077F]=true,[zwj]=true, -} -local arab_warned={} -local function warning(current,what) -  local char=current.char -  if not arab_warned[char] then -    log.report("analyze","arab: character %s (U+%04X) has no %s class",char,char,what) -    arab_warned[char]=true -  end -end -function fonts.analyzers.methods.nocolor(head,font,attr) -  for n in traverse_node_list(head,glyph) do -    if not font or n.font==font then -      fcr(n) -    end -  end -  return head,true -end -local function finish(first,last) -  if last then -    if first==last then -      local fc=first.char -      if isol_fina_medi_init[fc] or isol_fina[fc] then -        set_attribute(first,state,4)  -        if trace_analyzing then fcs(first,"font:isol") end -      else -        warning(first,"isol") -        set_attribute(first,state,0)  -        if trace_analyzing then fcr(first) end -      end -    else -      local lc=last.char -      if isol_fina_medi_init[lc] or isol_fina[lc] then -        set_attribute(last,state,3)  -        if trace_analyzing then fcs(last,"font:fina") end -      else -        warning(last,"fina") -        set_attribute(last,state,0)  -        if trace_analyzing then fcr(last) end -      end -    end -    first,last=nil,nil -  elseif first then -    local fc=first.char -    if isol_fina_medi_init[fc] or isol_fina[fc] then -      set_attribute(first,state,4)  -      if trace_analyzing then fcs(first,"font:isol") end -    else -      warning(first,"isol") -      set_attribute(first,state,0)  -      if trace_analyzing then fcr(first) end -    end -    first=nil -  end -  return first,last -end -function fonts.analyzers.methods.arab(head,font,attr)  -  local tfmdata=fontdata[font] -  local marks=tfmdata.marks -  local first,last,current,done=nil,nil,head,false -  while current do -    if current.id==glyph and current.subtype<256 and current.font==font and not has_attribute(current,state) then -      done=true -      local char=current.char -      if marks[char] then -        set_attribute(current,state,5)  -        if trace_analyzing then fcs(current,"font:mark") end -      elseif isol[char] then  -        first,last=finish(first,last) -        set_attribute(current,state,4)  -        if trace_analyzing then fcs(current,"font:isol") end -        first,last=nil,nil -      elseif not first then -        if isol_fina_medi_init[char] then -          set_attribute(current,state,1)  -          if trace_analyzing then fcs(current,"font:init") end -          first,last=first or current,current -        elseif isol_fina[char] then -          set_attribute(current,state,4)  -          if trace_analyzing then fcs(current,"font:isol") end -          first,last=nil,nil -        else  -          first,last=finish(first,last) -        end -      elseif isol_fina_medi_init[char] then -        first,last=first or current,current -        set_attribute(current,state,2)  -        if trace_analyzing then fcs(current,"font:medi") end -      elseif isol_fina[char] then -        if not has_attribute(last,state,1) then -          set_attribute(last,state,2)  -          if trace_analyzing then fcs(last,"font:medi") end -        end -        set_attribute(current,state,3)  -        if trace_analyzing then fcs(current,"font:fina") end -        first,last=nil,nil -      elseif char>=0x0600 and char<=0x06FF then -        if trace_analyzing then fcs(current,"font:rest") end -        first,last=finish(first,last) -      else  -        first,last=finish(first,last) -      end -    else -      first,last=finish(first,last) -    end -    current=current.next -  end -  first,last=finish(first,last) -  return head,done -end - -end -- closure - -do -- begin closure to overcome local limits and interference - -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=string.format,table.insert -local type,next=type,next -local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end) -local otf=fonts.otf -local tfm=fonts.tfm -local extra_lists={ -  tlig={ -    { -      endash="hyphen hyphen", -      emdash="hyphen hyphen hyphen", -      quotedblleft="quoteleft quoteleft", -      quotedblright="quoteright quoteright", -      quotedblleft="grave grave", -      quotedblright="quotesingle quotesingle", -      quotedblbase="comma comma", -      exclamdown="exclam grave", -      questiondown="question grave", -      guillemotleft="less less", -      guillemotright="greater greater", -    }, -  }, -  trep={ -    { -      [0x0022]=0x201D, -      [0x0027]=0x2019, -      [0x0060]=0x2018, -    }, -  }, -  anum={ -    {  -      [0x0030]=0x0660, -      [0x0031]=0x0661, -      [0x0032]=0x0662, -      [0x0033]=0x0663, -      [0x0034]=0x0664, -      [0x0035]=0x0665, -      [0x0036]=0x0666, -      [0x0037]=0x0667, -      [0x0038]=0x0668, -      [0x0039]=0x0669, -    }, -    {  -      [0x0030]=0x06F0, -      [0x0031]=0x06F1, -      [0x0032]=0x06F2, -      [0x0033]=0x06F3, -      [0x0034]=0x06F4, -      [0x0035]=0x06F5, -      [0x0036]=0x06F6, -      [0x0037]=0x06F7, -      [0x0038]=0x06F8, -      [0x0039]=0x06F9, -    }, -  }, -} -local extra_features={  -  tlig={ -    { -      features={ { scripts={ { script="*",langs={ "*" },} },tag="tlig",comment="added bij mkiv" },}, -      name="ctx_tlig_1", -      subtables={ { name="ctx_tlig_1_s" } }, -      type="gsub_ligature", -      flags={}, -    }, -  }, -  trep={ -    { -      features={ { scripts={ { script="*",langs={ "*" },} },tag="trep",comment="added bij mkiv" },}, -      name="ctx_trep_1", -      subtables={ { name="ctx_trep_1_s" } }, -      type="gsub_single", -      flags={}, -    }, -  }, -  anum={ -    { -      features={ { scripts={ { script="arab",langs={ "dflt","ARA" },} },tag="anum",comment="added bij mkiv" },}, -      name="ctx_anum_1", -      subtables={ { name="ctx_anum_1_s" } }, -      type="gsub_single", -      flags={}, -    }, -    { -      features={ { scripts={ { script="arab",langs={ "FAR" },} },tag="anum",comment="added bij mkiv" },}, -      name="ctx_anum_2", -      subtables={ { name="ctx_anum_2_s" } }, -      type="gsub_single", -      flags={}, -    }, -  }, -} -fonts.otf.enhancers["add some missing characters"]=function(data,filename) -end -fonts.otf.enhancers["enrich with features"]=function(data,filename) -  local used={} -  for i=1,#otf.glists do -    local g=data[otf.glists[i]] -    if g then -      for i=1,#g do -        local f=g[i].features -        if f then -          for i=1,#f do -            local t=f[i].tag -            if t then used[t]=true end -          end -        end -      end -    end -  end -  local glyphs=data.glyphs -  local indices=data.map.map -  data.gsub=data.gsub or {} -  for kind,specifications in next,extra_features do -    if not used[kind] then -      local done=0 -      for s=1,#specifications do -        local added=false -        local specification=specifications[s] -        local list=extra_lists[kind][s] -        local name=specification.name.."_s" -        if specification.type=="gsub_ligature" then -          for unicode,index in next,indices do -            local glyph=glyphs[index] -            local ligature=list[glyph.name] -            if ligature then -              local o=glyph.lookups or {} -              o[name]={ -                { -                  ["type"]="ligature", -                  ["specification"]={ -                    char=glyph.name, -                    components=ligature, -                  } -                } -              } -              glyph.lookups,done,added=o,done+1,true -            end -          end -        elseif specification.type=="gsub_single" then -          for unicode,index in next,indices do -            local glyph=glyphs[index] -            local r=list[unicode] -            if r then -              local replacement=indices[r] -              if replacement and glyphs[replacement] then -                local o=glyph.lookups or {} -                o[name]={ -                  { -                    ["type"]="substitution", -                    ["specification"]={ -                      variant=glyphs[replacement].name, -                    } -                  } -                } -                glyph.lookups,done,added=o,done+1,true -              end -            end -          end -        end -        if added then -          insert(data.gsub,s,table.fastcopy(specification))  -        end -      end -      if done>0 then -        if trace_loading then -          logs.report("load otf","enhance: registering %s feature (%s glyphs affected)",kind,done) -        end -      end -    end -  end -end -otf.tables.features['tlig']='TeX Ligatures' -otf.tables.features['trep']='TeX Replacements' -otf.tables.features['anum']='Arabic Digits' -otf.features.register_base_substitution('tlig') -otf.features.register_base_substitution('trep') -otf.features.register_base_substitution('anum') -fonts.initializers.base.otf.equaldigits=fonts.initializers.common.equaldigits -fonts.initializers.node.otf.equaldigits=fonts.initializers.common.equaldigits -fonts.initializers.base.otf.lineheight=fonts.initializers.common.lineheight -fonts.initializers.node.otf.lineheight=fonts.initializers.common.lineheight -fonts.initializers.base.otf.compose=fonts.initializers.common.compose -fonts.initializers.node.otf.compose=fonts.initializers.common.compose - -end -- closure - -do -- begin closure to overcome local limits and interference - -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 format,concat,gmatch,match,find,lower=string.format,table.concat,string.gmatch,string.match,string.find,string.lower -local tostring,next=tostring,next -local lpegmatch=lpeg.match -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.*") -fonts=fonts    or {} -fonts.define=fonts.define or {} -fonts.tfm=fonts.tfm  or {} -fonts.ids=fonts.ids  or {} -fonts.vf=fonts.vf   or {} -fonts.used=fonts.used  or {} -local tfm=fonts.tfm -local vf=fonts.vf -local define=fonts.define -tfm.version=1.01 -tfm.cache=containers.define("fonts","tfm",tfm.version,false)  -define.method="afm or tfm"  -define.specify=fonts.define.specify or {} -define.methods=fonts.define.methods or {} -tfm.fonts=tfm.fonts    or {} -tfm.readers=tfm.readers   or {} -tfm.internalized=tfm.internalized or {}  -tfm.readers.sequence={ 'otf','ttf','afm','tfm' } -tfm.auto_afm=true -local readers=tfm.readers -local sequence=readers.sequence -fonts.version=1.05 -fonts.cache=containers.define("fonts","def",fonts.version,false) -local splitter,specifiers=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(" ") -define.defaultlookup="file" -local prefixpattern=P(false) -function define.add_specifier(symbol) -  specifiers=specifiers..symbol -  local method=S(specifiers) -  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 -function define.add_lookup(str,default) -  prefixpattern=prefixpattern+P(str) -end -define.add_lookup("file") -define.add_lookup("name") -define.add_lookup("spec") -function define.get_specification(str) -  return lpegmatch(splitter,str) -end -function define.register_split(symbol,action) -  define.add_specifier(symbol) -  define.specify[symbol]=action -end -function define.makespecification(specification,lookup,name,sub,method,detail,size) -  size=size or 655360 -  if trace_defining then -    logs.report("define font","%s -> lookup: %s, name: %s, sub: %s, method: %s, detail: %s", -      specification,(lookup~="" and lookup) or "[file]",(name~="" and name) or "-", -      (sub~="" and sub) or "-",(method~="" and method) or "-",(detail~="" and detail) or "-") -  end -  if not lookup or lookup=="" then -    lookup=define.defaultlookup -  end -  local t={ -    lookup=lookup, -    specification=specification, -    size=size, -    name=name, -    sub=sub, -    method=method, -    detail=detail, -    resolved="", -    forced="", -    features={}, -  } -  return t -end -function define.analyze(specification,size) -  local lookup,name,sub,method,detail=define.get_specification(specification or "") -  return define.makespecification(specification,lookup,name,sub,method,detail,size) -end -local sortedhashkeys=table.sortedhashkeys -function tfm.hash_features(specification) -  local features=specification.features -  if features then -    local t={} -    local normal=features.normal -    if normal and next(normal) then -      local f=sortedhashkeys(normal) -      for i=1,#f do -        local v=f[i] -        if v~="number" and v~="features" then  -          t[#t+1]=v..'='..tostring(normal[v]) -        end -      end -    end -    local vtf=features.vtf -    if vtf and next(vtf) then -      local f=sortedhashkeys(vtf) -      for i=1,#f do -        local v=f[i] -        t[#t+1]=v..'='..tostring(vtf[v]) -      end -    end -    if #t>0 then -      return concat(t,"+") -    end -  end -  return "unknown" -end -fonts.designsizes={} -function tfm.hash_instance(specification,force) -  local hash,size,fallbacks=specification.hash,specification.size,specification.fallbacks -  if force or not hash then -    hash=tfm.hash_features(specification) -    specification.hash=hash -  end -  if size<1000 and fonts.designsizes[hash] then -    size=math.round(tfm.scaled(size,fonts.designsizes[hash])) -    specification.size=size -  end -    if fallbacks then -      return hash..' @ '..tostring(size)..' @ '..fallbacks -    else -      return hash..' @ '..tostring(size) -    end -end -define.resolvers=resolvers -function define.resolvers.file(specification) -  local suffix=file.suffix(specification.name) -  if fonts.formats[suffix] then -    specification.forced=suffix -    specification.name=file.removesuffix(specification.name) -  end -end -function define.resolvers.name(specification) -  local resolve=fonts.names.resolve -  if resolve then -    local resolved,sub=fonts.names.resolve(specification) -    specification.resolved,specification.sub=resolved,sub -    if resolved then -      local suffix=file.suffix(resolved) -      if fonts.formats[suffix] then -        specification.forced=suffix -        specification.name=file.removesuffix(resolved) -      else -        specification.name=resolved -      end -    end -  else -    define.resolvers.file(specification) -  end -end -function define.resolvers.spec(specification) -  local resolvespec=fonts.names.resolvespec -  if resolvespec then -    specification.resolved,specification.sub=fonts.names.resolvespec(specification) -    if specification.resolved then -      specification.forced=file.extname(specification.resolved) -      specification.name=file.removesuffix(specification.resolved) -    end -  else -    define.resolvers.name(specification) -  end -end -function define.resolve(specification) -  if not specification.resolved or specification.resolved=="" then  -    local r=define.resolvers[specification.lookup] -    if r then -      r(specification) -    end -  end -  if specification.forced=="" then -    specification.forced=nil -  else -    specification.forced=specification.forced -  end -  specification.hash=lower(specification.name..' @ '..tfm.hash_features(specification)) -  if specification.sub and specification.sub~="" then -    specification.hash=specification.sub..' @ '..specification.hash -  end -  return specification -end -function tfm.read(specification) -  local hash=tfm.hash_instance(specification) -  local tfmtable=tfm.fonts[hash]  -  if not tfmtable then -    local forced=specification.forced or "" -    if forced~="" then -      tfmtable=readers[lower(forced)](specification) -      if not tfmtable then -        logs.report("define font","forced type %s of %s not found",forced,specification.name) -      end -    else -      for s=1,#sequence do  -        local reader=sequence[s] -        if readers[reader] then  -          if trace_defining then -            logs.report("define font","trying (reader sequence driven) type %s for %s with file %s",reader,specification.name,specification.filename or "unknown") -          end -          tfmtable=readers[reader](specification) -          if tfmtable then -            break -          else -            specification.filename=nil -          end -        end -      end -    end -    if tfmtable then -      if directive_embedall then -        tfmtable.embedding="full" -      elseif tfmtable.filename and fonts.dontembed[tfmtable.filename] then -        tfmtable.embedding="no" -      else -        tfmtable.embedding="subset" -      end -      tfm.fonts[hash]=tfmtable -      fonts.designsizes[specification.hash]=tfmtable.designsize -    end -  end -  if not tfmtable then -    logs.report("define font","font with name %s is not found",specification.name) -  end -  return tfmtable -end -function tfm.read_and_define(name,size)  -  local specification=define.analyze(name,size) -  local method=specification.method -  if method and define.specify[method] then -    specification=define.specify[method](specification) -  end -  specification=define.resolve(specification) -  local hash=tfm.hash_instance(specification) -  local id=define.registered(hash) -  if not id then -    local fontdata=tfm.read(specification) -    if fontdata then -      fontdata.hash=hash -      id=font.define(fontdata) -      define.register(fontdata,id) -      tfm.cleanup_table(fontdata) -    else -      id=0  -    end -  end -  return fonts.ids[id],id -end -local function check_tfm(specification,fullname) -  local foundname=resolvers.findbinfile(fullname,'tfm') or ""  -  if foundname=="" then -    foundname=resolvers.findbinfile(fullname,'ofm') or ""  -  end -  if foundname~="" then -    specification.filename,specification.format=foundname,"ofm" -    return tfm.read_from_tfm(specification) -  end -end -local function check_afm(specification,fullname) -  local foundname=resolvers.findbinfile(fullname,'afm') or ""  -  if foundname=="" and tfm.auto_afm then -    local encoding,shortname=match(fullname,"^(.-)%-(.*)$")  -    if encoding and shortname and fonts.enc.known[encoding] then -      shortname=resolvers.findbinfile(shortname,'afm') or ""  -      if shortname~="" then -        foundname=shortname -        if trace_loading then -          logs.report("load afm","stripping encoding prefix from filename %s",afmname) -        end -      end -    end -  end -  if foundname~="" then -    specification.filename,specification.format=foundname,"afm" -    return tfm.read_from_afm(specification) -  end -end -function readers.tfm(specification) -  local fullname,tfmtable=specification.filename or "",nil -  if fullname=="" then -    local forced=specification.forced or "" -    if forced~="" then -      tfmtable=check_tfm(specification,specification.name.."."..forced) -    end -    if not tfmtable then -      tfmtable=check_tfm(specification,specification.name) -    end -  else -    tfmtable=check_tfm(specification,fullname) -  end -  return tfmtable -end -function readers.afm(specification,method) -  local fullname,tfmtable=specification.filename or "",nil -  if fullname=="" then -    local forced=specification.forced or "" -    if forced~="" then -      tfmtable=check_afm(specification,specification.name.."."..forced) -    end -    if not tfmtable then -      method=method or define.method or "afm or tfm" -      if method=="tfm" then -        tfmtable=check_tfm(specification,specification.name) -      elseif method=="afm" then -        tfmtable=check_afm(specification,specification.name) -      elseif method=="tfm or afm" then -        tfmtable=check_tfm(specification,specification.name) or check_afm(specification,specification.name) -      else  -        tfmtable=check_afm(specification,specification.name) or check_tfm(specification,specification.name) -      end -    end -  else -    tfmtable=check_afm(specification,fullname) -  end -  return tfmtable -end -local function check_otf(forced,specification,suffix,what) -  local name=specification.name -  if forced then -    name=file.addsuffix(name,suffix,true) -  end -  local fullname,tfmtable=resolvers.findbinfile(name,suffix) or "",nil  -  if fullname=="" then -    local fb=fonts.names.old_to_new[name] -    if fb then -      fullname=resolvers.findbinfile(fb,suffix) or "" -    end -  end -  if fullname=="" then -    local fb=fonts.names.new_to_old[name] -    if fb then -      fullname=resolvers.findbinfile(fb,suffix) or "" -    end -  end -  if fullname~="" then -    specification.filename,specification.format=fullname,what  -    tfmtable=tfm.read_from_open_type(specification)        -  end -  return tfmtable -end -function readers.opentype(specification,suffix,what) -  local forced=specification.forced or "" -  if forced=="otf" then -    return check_otf(true,specification,forced,"opentype") -  elseif forced=="ttf" or forced=="ttc" or forced=="dfont" then -    return check_otf(true,specification,forced,"truetype") -  else -    return check_otf(false,specification,suffix,what) -  end -end -function readers.otf (specification) return readers.opentype(specification,"otf","opentype") end -function readers.ttf (specification) return readers.opentype(specification,"ttf","truetype") end -function readers.ttc (specification) return readers.opentype(specification,"ttf","truetype") end  -function readers.dfont(specification) return readers.opentype(specification,"ttf","truetype") end -function define.check(features,defaults)  -  local done=false -  if features and next(features) then -    for k,v in next,defaults do -      if features[k]==nil then -        features[k],done=v,true -      end -    end -  else -    features,done=table.fastcopy(defaults),true -  end -  return features,done  -end -define.last=nil -function define.register(fontdata,id) -  if fontdata and id then -    local hash=fontdata.hash -    if not tfm.internalized[hash] then -      if trace_defining then -        logs.report("define font","loading at 2 id %s, hash: %s",id or "?",hash or "?") -      end -      fonts.identifiers[id]=fontdata -      fonts.characters [id]=fontdata.characters -      fonts.quads   [id]=fontdata.parameters.quad -      tfm.internalized[hash]=id -    end -  end -end -function define.registered(hash) -  local id=tfm.internalized[hash] -  return id,id and fonts.ids[id] -end -local cache_them=false -function tfm.make(specification) -  local fvm=define.methods[specification.features.vtf.preset] -  if fvm then -    return fvm(specification) -  else -    return nil -  end -end -function define.read(specification,size,id)  -  statistics.starttiming(fonts) -  if type(specification)=="string" then -    specification=define.analyze(specification,size) -  end -  local method=specification.method -  if method and define.specify[method] then -    specification=define.specify[method](specification) -  end -  specification=define.resolve(specification) -  local hash=tfm.hash_instance(specification) -  if cache_them then -    local fontdata=containers.read(fonts.cache,hash)  -  end -  local fontdata=define.registered(hash)  -  if not fontdata then -    if specification.features.vtf and specification.features.vtf.preset then -      fontdata=tfm.make(specification) -    else -      fontdata=tfm.read(specification) -      if fontdata then -        tfm.check_virtual_id(fontdata) -      end -    end -    if cache_them then -      fontdata=containers.write(fonts.cache,hash,fontdata)  -    end -    if fontdata then -      fontdata.hash=hash -      fontdata.cache="no" -      if id then -        define.register(fontdata,id) -      end -    end -  end -  define.last=fontdata or id  -  if not fontdata then -    logs.report("define font","unknown font %s, loading aborted",specification.name) -  elseif trace_defining and type(fontdata)=="table" then -    logs.report("define font","using %s font with id %s, name:%s size:%s bytes:%s encoding:%s fullname:%s filename:%s", -      fontdata.type     or "unknown", -      id           or "?", -      fontdata.name     or "?", -      fontdata.size     or "default", -      fontdata.encodingbytes or "?", -      fontdata.encodingname or "unicode", -      fontdata.fullname   or "?", -      file.basename(fontdata.filename or "?")) -  end -  statistics.stoptiming(fonts) -  return fontdata -end -function vf.find(name) -  name=file.removesuffix(file.basename(name)) -  if tfm.resolve_vf then -    local format=fonts.logger.format(name) -    if format=='tfm' or format=='ofm' then -      if trace_defining then -        logs.report("define font","locating vf for %s",name) -      end -      return resolvers.findbinfile(name,"ovf") -    else -      if trace_defining then -        logs.report("define font","vf for %s is already taken care of",name) -      end -      return nil  -    end -  else -    if trace_defining then -      logs.report("define font","locating vf for %s",name) -    end -    return resolvers.findbinfile(name,"ovf") -  end -end -callbacks.register('define_font',define.read,"definition of fonts (tfmtable preparation)") -callbacks.register('find_vf_file',vf.find,"locating virtual fonts, insofar needed")  - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-xtx']={ -  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 texsprint,count=tex.sprint,tex.count -local format,concat,gmatch,match,find,lower=string.format,table.concat,string.gmatch,string.match,string.find,string.lower -local tostring,next=tostring,next -local lpegmatch=lpeg.match -local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end) -local list={} -fonts.define.specify.colonized_default_lookup="file" -local function isstyle(s) -  local style=string.lower(s):split("/") -  for _,v in ipairs(style) do -    if v=="b" then -      list.style="bold" -    elseif v=="i" then -      list.style="italic" -    elseif v=="bi" or v=="ib" then -      list.style="bolditalic" -    elseif v:find("^s=") then -      list.optsize=v:split("=")[2] -    elseif v=="aat" or v=="icu" or v=="gr" then -      logs.report("load font","unsupported font option: %s",v) -    elseif not v:is_empty() then -      list.style=v:gsub("[^%a%d]","") -    end -  end -end -fonts=fonts   or {} -fonts.otf=fonts.otf or {} -local otf=fonts.otf -otf.tables=otf.tables or {} -otf.tables.defaults={ -  dflt={ -    "ccmp","locl","rlig","liga","clig", -    "kern","mark","mkmk","itlc", -  }, -  arab={ -    "ccmp","locl","isol","fina","fin2", -    "fin3","medi","med2","init","rlig", -    "calt","liga","cswh","mset","curs", -    "kern","mark","mkmk", -  }, -  deva={ -    "ccmp","locl","init","nukt","akhn", -    "rphf","blwf","half","pstf","vatu", -    "pres","blws","abvs","psts","haln", -    "calt","blwm","abvm","dist","kern", -    "mark","mkmk", -  }, -  khmr={ -    "ccmp","locl","pref","blwf","abvf", -    "pstf","pres","blws","abvs","psts", -    "clig","calt","blwm","abvm","dist", -    "kern","mark","mkmk", -  }, -  thai={ -    "ccmp","locl","liga","kern","mark", -    "mkmk", -  }, -  hang={ -    "ccmp","ljmo","vjmo","tjmo", -  }, -} -otf.tables.defaults.beng=otf.tables.defaults.deva -otf.tables.defaults.guru=otf.tables.defaults.deva -otf.tables.defaults.gujr=otf.tables.defaults.deva -otf.tables.defaults.orya=otf.tables.defaults.deva -otf.tables.defaults.taml=otf.tables.defaults.deva -otf.tables.defaults.telu=otf.tables.defaults.deva -otf.tables.defaults.knda=otf.tables.defaults.deva -otf.tables.defaults.mlym=otf.tables.defaults.deva -otf.tables.defaults.sinh=otf.tables.defaults.deva -otf.tables.defaults.syrc=otf.tables.defaults.arab -otf.tables.defaults.mong=otf.tables.defaults.arab -otf.tables.defaults.nko=otf.tables.defaults.arab -otf.tables.defaults.tibt=otf.tables.defaults.khmr -otf.tables.defaults.lao=otf.tables.defaults.thai -local function parse_script(script) -  if otf.tables.scripts[script] then -    local dflt -    if otf.tables.defaults[script] then -      logs.report("load font","auto-selecting default features for script: %s",script) -      dflt=otf.tables.defaults[script] -    else -      logs.report("load font","auto-selecting default features for script: dflt (was %s)",script) -      dflt=otf.tables.defaults["dflt"] -    end -    for _,v in next,dflt do -      list[v]="yes" -    end -  else -    logs.report("load font","unknown script: %s",script) -  end -end -local function issome ()  list.lookup=fonts.define.specify.colonized_default_lookup end -local function isfile ()  list.lookup='file' end -local function isname ()  list.lookup='name' end -local function thename(s)  list.name=s end -local function issub (v)  list.sub=v end -local function iskey (k,v) -  if k=="script" then -    parse_script(v) -  end -  list[k]=v -end -local function istrue (s)  list[s]=true end -local function isfalse(s)  list[s]=false end -local spaces=lpeg.P(" ")^0 -local namespec=(1-lpeg.S("/:("))^0  -local filespec=(lpeg.R("az","AZ")*lpeg.P(":"))^-1*(1-lpeg.S(":("))^1 -local crapspec=spaces*lpeg.P("/")*(((1-lpeg.P(":"))^0)/isstyle)*spaces -local filename=(lpeg.P("file:")/isfile*(filespec/thename))+(lpeg.P("[")*lpeg.P(true)/isfile*(((1-lpeg.P("]"))^0)/thename)*lpeg.P("]")) -local fontname=(lpeg.P("name:")/isname*(namespec/thename))+lpeg.P(true)/issome*(namespec/thename) -local sometext=(lpeg.R("az","AZ","09")+lpeg.S("+-."))^1 -local truevalue=lpeg.P("+")*spaces*(sometext/istrue) -local falsevalue=lpeg.P("-")*spaces*(sometext/isfalse) -local keyvalue=lpeg.P("+")+(lpeg.C(sometext)*spaces*lpeg.P("=")*spaces*lpeg.C(sometext))/iskey -local somevalue=sometext/istrue -local subvalue=lpeg.P("(")*(lpeg.C(lpeg.P(1-lpeg.S("()"))^1)/issub)*lpeg.P(")")  -local option=spaces*(keyvalue+falsevalue+truevalue+somevalue)*spaces -local options=lpeg.P(":")*spaces*(lpeg.P(";")^0*option)^0 -local pattern=(filename+fontname)*subvalue^0*crapspec^0*options^0 -local normalize_meanings=fonts.otf.meanings.normalize -function fonts.define.specify.colonized(specification)  -  list={} -  lpegmatch(pattern,specification.specification) -  if list.style then -    specification.style=list.style -    list.style=nil -  end -  if list.optsize then -    specification.optsize=list.optsize -    list.optsize=nil -  end -  if list.name then -    if resolvers.find_file(list.name,"tfm") then -      list.lookup="file" -      list.name=file.addsuffix(list.name,"tfm") -    elseif resolvers.find_file(list.name,"ofm") then -      list.lookup="file" -      list.name=file.addsuffix(list.name,"ofm") -    end -    specification.name=list.name -    list.name=nil -  end -  if list.lookup then -    specification.lookup=list.lookup -    list.lookup=nil -  end -  if list.sub then -    specification.sub=list.sub -    list.sub=nil -  end -  specification.features.normal=normalize_meanings(list) -  return specification -end -fonts.define.register_split(":",fonts.define.specify.colonized) - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-dum']={ -  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" -} -fonts=fonts or {} -fonts.otf.pack=false -fonts.tfm.resolve_vf=false  -fonts.tfm.fontname_mode="specification" -fonts.tfm.readers=fonts.tfm.readers or {} -fonts.tfm.readers.sequence={ 'otf','ttf','tfm' } -fonts.tfm.readers.afm=nil -fonts.define=fonts.define or {} -fonts.define.specify.colonized_default_lookup="name" -function fonts.define.get_specification(str) -  return "",str,"",":",str -end -fonts.logger=fonts.logger or {} -function fonts.logger.save() -end -fonts.names=fonts.names or {} -fonts.names.version=1.001  -fonts.names.basename="luatex-fonts-names.lua" -fonts.names.new_to_old={} -fonts.names.old_to_new={} -local data,loaded=nil,false -local fileformats={ "lua","tex","other text files" } -function fonts.names.resolve(name,sub) -  if not loaded then -    local basename=fonts.names.basename -    if basename and basename~="" then -      for i=1,#fileformats do -        local format=fileformats[i] -        local foundname=resolvers.find_file(basename,format) or "" -        if foundname~="" then -          data=dofile(foundname) -          break -        end -      end -    end -    loaded=true -  end -  if type(data)=="table" and data.version==fonts.names.version then -    local condensed=string.gsub(string.lower(name),"[^%a%d]","") -    local found=data.mappings and data.mappings[condensed] -    if found then -      local fontname,filename,subfont=found[1],found[2],found[3] -      if subfont then -        return filename,fontname -      else -        return filename,false -      end -    else -      return name,false  -    end -  end -end -fonts.names.resolvespec=fonts.names.resolve -table.insert(fonts.triggers,"itlc") -local function itlc(tfmdata,value) -  if value then -    local metadata=tfmdata.shared.otfdata.metadata -    if metadata then -      local italicangle=metadata.italicangle -      if italicangle and italicangle~=0 then -        local uwidth=(metadata.uwidth or 40)/2 -        for unicode,d in next,tfmdata.descriptions do -          local it=d.boundingbox[3]-d.width+uwidth -          if it~=0 then -            d.italic=it -          end -        end -        tfmdata.has_italic=true -      end -    end -  end -end -fonts.initializers.base.otf.itlc=itlc -fonts.initializers.node.otf.itlc=itlc -function fonts.initializers.common.slant(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.slant_factor=value -end -function fonts.initializers.common.extend(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.extend_factor=value -end -table.insert(fonts.triggers,"slant") -table.insert(fonts.triggers,"extend") -fonts.initializers.base.otf.slant=fonts.initializers.common.slant -fonts.initializers.node.otf.slant=fonts.initializers.common.slant -fonts.initializers.base.otf.extend=fonts.initializers.common.extend -fonts.initializers.node.otf.extend=fonts.initializers.common.extend -fonts.protrusions=fonts.protrusions    or {} -fonts.protrusions.setups=fonts.protrusions.setups or {} -local setups=fonts.protrusions.setups -local function map_opbd_onto_protrusion(tfmdata,value,opbd) -  local characters,descriptions=tfmdata.characters,tfmdata.descriptions -  local otfdata=tfmdata.shared.otfdata -  local singles=otfdata.shared.featuredata.gpos_single -  local script,language=tfmdata.script,tfmdata.language -  local done,factor,left,right=false,1,1,1 -  local setup=setups[value] -  if setup then -    factor=setup.factor or 1 -    left=setup.left  or 1 -    right=setup.right or 1 -  else -    factor=tonumber(value) or 1 -  end -  if opbd~="right" then -    local validlookups,lookuplist=fonts.otf.collect_lookups(otfdata,"lfbd",script,language) -    if validlookups then -      for i=1,#lookuplist do -        local lookup=lookuplist[i] -        local data=singles[lookup] -        if data then -          if trace_protrusion then -            logs.report("fonts","set left protrusion using lfbd lookup '%s'",lookup) -          end -          for k,v in next,data do -            local p=- (v[1]/1000)*factor*left -            characters[k].left_protruding=p -            if trace_protrusion then -              logs.report("opbd","lfbd -> %s -> 0x%05X (%s) -> %0.03f (%s)",lookup,k,utfchar(k),p,concat(v," ")) -            end -          end -          done=true -        end -      end -    end -  end -  if opbd~="left" then -    local validlookups,lookuplist=fonts.otf.collect_lookups(otfdata,"rtbd",script,language) -    if validlookups then -      for i=1,#lookuplist do -        local lookup=lookuplist[i] -        local data=singles[lookup] -        if data then -          if trace_protrusion then -            logs.report("fonts","set right protrusion using rtbd lookup '%s'",lookup) -          end -          for k,v in next,data do -            local p=(v[1]/1000)*factor*right -            characters[k].right_protruding=p -            if trace_protrusion then -              logs.report("opbd","rtbd -> %s -> 0x%05X (%s) -> %0.03f (%s)",lookup,k,utfchar(k),p,concat(v," ")) -            end -          end -        end -        done=true -      end -    end -  end -  tfmdata.auto_protrude=done -end -function fonts.initializers.common.protrusion(tfmdata,value) -  if value then -    local opbd=tfmdata.shared.features.opbd -    if opbd then -      map_opbd_onto_protrusion(tfmdata,value,opbd) -    elseif 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.auto_protrude=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 -end -fonts.expansions=fonts.expansions    or {} -fonts.expansions.setups=fonts.expansions.setups or {} -local setups=fonts.expansions.setups -function fonts.initializers.common.expansion(tfmdata,value) -  if value then -    local setup=setups[value] -    if setup then -      local stretch,shrink,step,factor=setup.stretch or 0,setup.shrink or 0,setup.step or 0,setup.factor or 1 -      tfmdata.stretch,tfmdata.shrink,tfmdata.step,tfmdata.auto_expand=stretch*10,shrink*10,step*10,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 -table.insert(fonts.manipulators,"protrusion") -table.insert(fonts.manipulators,"expansion") -fonts.initializers.base.otf.protrusion=fonts.initializers.common.protrusion -fonts.initializers.node.otf.protrusion=fonts.initializers.common.protrusion -fonts.initializers.base.otf.expansion=fonts.initializers.common.expansion -fonts.initializers.node.otf.expansion=fonts.initializers.common.expansion -function fonts.register_message() -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.otf.meanings=fonts.otf.meanings or {} -fonts.otf.meanings.normalize=fonts.otf.meanings.normalize or function(t) -  if t.rand then -    t.rand="random" -  end -end -function fonts.otf.name_to_slot(name) -  local tfmdata=fonts.ids[font.current()] -  if tfmdata and tfmdata.shared then -    local otfdata=tfmdata.shared.otfdata -    local unicode=otfdata.luatex.unicodes[name] -    return unicode and (type(unicode)=="number" and unicode or unicode[1]) -  end -end -function fonts.otf.char(n) -  if type(n)=="string" then -    n=fonts.otf.name_to_slot(n) -  end -  if type(n)=="number" then -    tex.sprint("\\char"..n) -  end -end -fonts.strippables=table.tohash { -  0x000AD,0x017B4,0x017B5,0x0200B,0x0200C,0x0200D,0x0200E,0x0200F,0x0202A,0x0202B, -  0x0202C,0x0202D,0x0202E,0x02060,0x02061,0x02062,0x02063,0x0206A,0x0206B,0x0206C, -  0x0206D,0x0206E,0x0206F,0x0FEFF,0x1D173,0x1D174,0x1D175,0x1D176,0x1D177,0x1D178, -  0x1D179,0x1D17A,0xE0001,0xE0020,0xE0021,0xE0022,0xE0023,0xE0024,0xE0025,0xE0026, -  0xE0027,0xE0028,0xE0029,0xE002A,0xE002B,0xE002C,0xE002D,0xE002E,0xE002F,0xE0030, -  0xE0031,0xE0032,0xE0033,0xE0034,0xE0035,0xE0036,0xE0037,0xE0038,0xE0039,0xE003A, -  0xE003B,0xE003C,0xE003D,0xE003E,0xE003F,0xE0040,0xE0041,0xE0042,0xE0043,0xE0044, -  0xE0045,0xE0046,0xE0047,0xE0048,0xE0049,0xE004A,0xE004B,0xE004C,0xE004D,0xE004E, -  0xE004F,0xE0050,0xE0051,0xE0052,0xE0053,0xE0054,0xE0055,0xE0056,0xE0057,0xE0058, -  0xE0059,0xE005A,0xE005B,0xE005C,0xE005D,0xE005E,0xE005F,0xE0060,0xE0061,0xE0062, -  0xE0063,0xE0064,0xE0065,0xE0066,0xE0067,0xE0068,0xE0069,0xE006A,0xE006B,0xE006C, -  0xE006D,0xE006E,0xE006F,0xE0070,0xE0071,0xE0072,0xE0073,0xE0074,0xE0075,0xE0076, -  0xE0077,0xE0078,0xE0079,0xE007A,0xE007B,0xE007C,0xE007D,0xE007E,0xE007F, -} - -end -- closure - -do -- begin closure to overcome local limits and interference - -if not modules then modules={} end modules ['font-clr']={ -  version=1.001, -  comment="companion to font-otf.lua (font color)", -  author="Khaled Hosny and Elie Roux", -  copyright="Luaotfload Development Team", -  license="GPL" -} -fonts.triggers=fonts.triggers      or {} -fonts.initializers=fonts.initializers    or {} -fonts.initializers.common=fonts.initializers.common or {} -local initializers,format=fonts.initializers,string.format -table.insert(fonts.triggers,"color") -function initializers.common.color(tfmdata,value) -  local sanitized -  if value then -    value=tostring(value) -    if #value==6 or #value==8 then -      sanitized=value -    elseif #value==7 then -      _,_,sanitized=value:find("(......)") -    elseif #value>8 then -      _,_,sanitized=value:find("(........)") -    else -    end -  end -  if sanitized then -    tfmdata.color=sanitized -    add_color_callback() -  end -end -initializers.base.otf.color=initializers.common.color -initializers.node.otf.color=initializers.common.color -local function hex2dec(hex,one) -  if one then -    return format("%.1g",tonumber(hex,16)/255) -  else -    return format("%.3g",tonumber(hex,16)/255) -  end -end -local res -local function pageresources(a) -  local res2 -  if not res then -    res="/TransGs1<</ca 1/CA 1>>" -  end -  res2=format("/TransGs%s<</ca %s/CA %s>>",a,a,a) -  res=format("%s%s",res,res:find(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=hex:find('(..)(..)(..)') -    elseif #hex==8 then -      _,_,r,g,b,a=hex:find('(..)(..)(..)(..)') -      a=hex2dec(a,true) -      pageresources(a) -    end -  else -    return nil -  end -  r=hex2dec(r) -  g=hex2dec(g) -  b=hex2dec(b) -  if a then -    push=format('/TransGs%g gs %s %s %s rg',a,r,g,b) -    pop='0 g /TransGs1 gs' -  else -    push=format('%s %s %s rg',r,g,b) -    pop='0 g' -  end -  return push,pop -end -local glyph=node.id('glyph') -local hlist=node.id('hlist') -local vlist=node.id('vlist') -local whatsit=node.id('whatsit') -local pgi=node.id('page_insert') -local sbox=node.id('sub_box') -local function lookup_next_color(head) -  for n in node.traverse(head) do -    if n.id==glyph then -      if fonts.ids[n.font] and fonts.ids[n.font].color then -        return fonts.ids[n.font].color -      else -        return -1 -      end -    elseif n.id==vlist or n.id==hlist or n.id==sbox then -      local r=lookup_next_color(n.list) -      if r==-1 then -        return -1 -      elseif r then -        return r -      end -    elseif n.id==whatsit or n.id==pgi then -      return -1 -    end -  end -  return nil -end -local function node_colorize(head,current_color,next_color) -  for n in node.traverse(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 -      n.list,current_color=node_colorize(n.list,current_color,next_color_in) -    elseif n.id==glyph then -      local tfmdata=fonts.ids[n.font] -      if tfmdata and tfmdata.color then -        if tfmdata.color~=current_color then -          local pushcolor=hex_to_rgba(tfmdata.color) -          local push=node.new(whatsit,8) -          push.mode=1 -          push.data=pushcolor -          head=node.insert_before(head,n,push) -          current_color=tfmdata.color -        end -        local next_color_in=lookup_next_color (n.next) or next_color -        if next_color_in~=tfmdata.color then -          local _,popcolor=hex_to_rgba(tfmdata.color) -          local pop=node.new(whatsit,8) -          pop.mode=1 -          pop.data=popcolor -          head=node.insert_after(head,n,pop) -          current_color=nil -        end -      end -    end -  end -  return head,current_color -end -local function font_colorize(head) -  if res then -   local r="/ExtGState<<"..res..">>" -   tex.pdfpageresources=tex.pdfpageresources:gsub(r,"") -  end -  local h=node_colorize(head,nil,nil) -  if res and res:find("%S") then  -   local r="/ExtGState<<"..res..">>" -   tex.pdfpageresources=tex.pdfpageresources..r -  end -  return h -end -local color_callback_activated=0 -function add_color_callback() -  if color_callback_activated==0 then -    luatexbase.add_to_callback("pre_output_filter",font_colorize,"loaotfload.colorize") -    color_callback_activated=1 -  end -end - -end -- closure diff --git a/luaotfload-legacy-tool.lua b/luaotfload-legacy-tool.lua deleted file mode 100755 index 30ab13b..0000000 --- a/luaotfload-legacy-tool.lua +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env texlua ---[[ -This file is copyright 2010 Elie Roux and Khaled Hosny and is under CC0 -license (see http://creativecommons.org/publicdomain/zero/1.0/legalcode). - -This file is a wrapper for the luaotfload's font names module. It is part of the -luaotfload bundle, please see the luaotfload documentation for more info. ---]] - -kpse.set_program_name("luatex") - -require("lualibs")                    ---> current -require("luaotfload-legacy-database") ---> old -require("alt_getopt")                 ---> ? - -local name      = "mkluatexfontdb" -local version   = "1.31 (legacy)" - -local names    = fonts.names - -local function help_msg() -    texio.write(string.format([[ -Usage: %s [OPTION]... - -================================================================================ -                        please update your luatex binary -             this version is unsupported and likely to break things -================================================================================ -     -Rebuild the LuaTeX font database. - -Valid options: -  -f --force                   force re-indexing all fonts -  -q --quiet                   don't output anything -  -v --verbose=LEVEL           be more verbose (print the searched directories) -  -vv                          print the loaded fonts -  -vvv                         print all steps of directory searching -  -V --version                 print version and exit -  -h --help                    print this message - -The output database file is named otfl-names.lua and is placed under: - -   %s - -contact: https://github.com/lualatex/luaotfload - -]], name, names.path.localdir)) -end - -local function version_msg() -    texio.write(string.format( -        "%s version %s, database version %s.\n", name, version, names.version)) -end - ---[[ -Command-line processing. -Here we fill cmdargs with the good values, and then analyze it. ---]] - -local long_opts = { -    force            = "f", -    quiet            = "q", -    help             = "h", -    verbose          = 1  , -    version          = "V", -} - -local short_opts = "fqpvVh" - -local force_reload = nil - -local function process_cmdline() -    local opts, optind, optarg = alt_getopt.get_ordered_opts (arg, short_opts, long_opts) -    local log_level = 1 -    for i,v in ipairs(opts) do -        if     v == "q" then -            log_level = 0 -        elseif v == "v" then -            if log_level > 0 then -                log_level = log_level + 1 -            else -                log_level = 2 -            end -        elseif v == "V" then -            version_msg() -            os.exit(0) -        elseif v == "h" then -            help_msg() -            os.exit(0) -        elseif v == "f" then -            force_reload = 1 -        end -    end -    names.set_log_level(log_level) -end - -local function generate(force) -    local fontnames, saved -    fontnames = names.update(fontnames, force) -    logs.report("%s fonts in the database", #fontnames.mappings) -    saved = names.save(fontnames) -end - -process_cmdline() -generate(force_reload) diff --git a/luaotfload-legacy.lua b/luaotfload-legacy.lua deleted file mode 100644 index 8bb1790..0000000 --- a/luaotfload-legacy.lua +++ /dev/null @@ -1,402 +0,0 @@ -module("luaotfload", package.seeall) - -luaotfload.module = { -    name          = "luaotfload-legacy", -    version       = 1.31, -    date          = "2013/04/25", -    description   = "Unsupported Luaotfload", -    author        = "Elie Roux & Hans Hagen", -    copyright     = "Elie Roux", -    license       = "GPL v2" -} - -local error, warning, info, log = luatexbase.provides_module(luaotfload.module) - ---[[doc-- - -   This used to be a necessary initalization in order not to rebuild an -   existing font.  Maybe 600 should be replaced by |\pdfpkresolution| -   or |texconfig.pk_dpi| (and it should be replaced dynamically), but -   we don't have access (yet) to the |texconfig| table, so we let it be -   600. Anyway, it does still work fine even if |\pdfpkresolution| is -   changed. - ---doc]]-- - -kpse.init_prog("", 600, "/") - ---[[doc-- - -   The minimal required \luatex version. -   We are tolerant folks. - ---doc]]-- - -local luatex_version = 60 -if tex.luatexversion < luatex_version then -    warning("LuaTeX v%.2f is old, v%.2f is required, v0.76 recommended.", -             tex.luatexversion/100, -             luatex_version   /100) -end - ---[[doc-- - -    \subsection{Module loading} -    We load the outdated \context files with this function. It -    automatically adds the |otfl-| prefix to it, so that we call it with -    the actual \context name. - ---doc]]-- - -function luaotfload.loadmodule(tofind) -    local found = kpse.find_file(tofind,"tex") -    if found then -        log("loading file %s.", found) -        dofile(found) -    else -        error("file %s not found.", tofind) -    end -end -local loadmodule = luaotfload.loadmodule - ---[[doc-- - -    Keep away from these lines! - ---doc]]-- -loadmodule"luaotfload-legacy-merged.lua" - -if not fonts then -  loadmodule("otfl-luat-dum.lua") -- not used in context at all -  loadmodule("otfl-luat-ovr.lua") -- override some luat-dum functions -  loadmodule("otfl-data-con.lua") -- maybe some day we don't need this one -  loadmodule("otfl-font-ini.lua") -  loadmodule("otfl-node-dum.lua") -  loadmodule("otfl-node-inj.lua") ---[[doc-- -   By default \context takes some private attributes for internal use. To -   avoide attribute clashes with other packages, we override the function -   that allocates new attributes, making it a wraper around -   |luatexbase.new_attribute()|. We also prefix attributes with |otfl@| to -   avoid possiple name clashes. ---doc]]-- -  loadmodule("luaotfload-legacy-attributes.lua") -- patch attributes ---[[doc-- -   Font handling modules. ---doc]]-- -  loadmodule("otfl-font-tfm.lua") -  loadmodule("otfl-font-cid.lua") -  loadmodule("otfl-font-ott.lua") -  loadmodule("otfl-font-map.lua") -  loadmodule("otfl-font-otf.lua") -  loadmodule("otfl-font-otd.lua") -  loadmodule("otfl-font-oti.lua") -  loadmodule("otfl-font-otb.lua") -  loadmodule("otfl-font-otn.lua") -  loadmodule("otfl-font-ota.lua") -  loadmodule("otfl-font-otc.lua") -  loadmodule("otfl-font-def.lua") ---[[doc-- -   \textsf{old luaotfload} specific modules. ---doc]]-- -  loadmodule("otfl-font-xtx.lua") -  loadmodule("otfl-font-dum.lua") -  loadmodule("otfl-font-clr.lua") -end -loadmodule"luaotfload-legacy-database.lua" --- unmerged coz needed in db script - ---[[doc-- - -    This is a patch for |otfl-font-def.lua|, that defines a reader for ofm -    fonts, this is necessary if we set the forced field of the specification -    to |ofm|. - ---doc]]-- - -if fonts and fonts.tfm and fonts.tfm.readers then -    fonts.tfm.readers.ofm = fonts.tfm.readers.tfm -end - ---[[doc-- - -    \subsection{Post-processing TFM table} -    Here we do some final touches to the loaded TFM table before passing it -    to the \tex end. -    First we create a callback for patching fonts on the fly, to be used by -    other packages. - ---doc]]-- - -luatexbase.create_callback("luaotfload.patch_font", "simple", function() end) - ---[[doc-- - -    then define a function where font manipulation will take place. - ---doc]]-- - -local function def_font(...) -    local fontdata = fonts.define.read(...) -    if type(fontdata) == "table" and fontdata.shared then ---[[doc-- - -    Then we populate |MathConstants| table, which is required for -    OpenType math. - -    Note: actually it isn’t, but you’re asking for it by using outdated -    code. - ---doc]]-- -        local otfdata = fontdata.shared.otfdata -        if otfdata.metadata.math then -            local mc = { } -            for k,v in next, otfdata.metadata.math do -                if k:find("Percent") then -                    -- keep percent values as is -                    mc[k] = v -                else -                    mc[k] = v / fontdata.units * fontdata.size -                end -            end -            -- for \overwithdelims -            mc.FractionDelimiterSize             = 1.01 * fontdata.size -            mc.FractionDelimiterDisplayStyleSize = 2.39 * fontdata.size - -            fontdata.MathConstants = mc -        end ---[[doc-- - -    Execute any registered font patching callbacks. - ---doc]]-- -        luatexbase.call_callback("luaotfload.patch_font", fontdata) -    end -    return fontdata -end - ---[[doc-- -\subsection{\context override} - -    We have a unified function for both file and name resolver. This -    line is commented as it makes database reload too often. This means -    that in some cases, a font in the database will not be found if -    it's not in the texmf tree. A similar thing will reappear in next -    version. - ---doc]]-- - ---fonts.define.resolvers.file = fonts.define.resolvers.name - ---[[doc-- - -    Overriding some defaults set in \context code. - ---doc]]-- - -fonts.mode = "node" - ---[[doc-- - -    The following features are useful in math (e.g. in XITS Math font), -    but \textsf{luaotfload} does not recognize them in |base| mode. - ---doc]]-- - -local register_base_sub = fonts.otf.features.register_base_substitution -local gsubs = { -    "ss01", "ss02", "ss03", "ss04", "ss05", -    "ss06", "ss07", "ss08", "ss09", "ss10", -    "ss11", "ss12", "ss13", "ss14", "ss15", -    "ss16", "ss17", "ss18", "ss19", "ss20", -} - -for _,v in next, gsubs do -    register_base_sub(v) -end - ---[[doc-- - -    Finally we register the callbacks - ---doc]]-- - -luatexbase.add_to_callback("pre_linebreak_filter", -                            nodes.simple_font_handler, -                           "luaotfload.pre_linebreak_filter") -luatexbase.add_to_callback("hpack_filter", -                            nodes.simple_font_handler, -                           "luaotfload.hpack_filter") -luatexbase.reset_callback("define_font") -luatexbase.add_to_callback("define_font", -                            def_font, -                           "luaotfload.define_font", 1) -luatexbase.add_to_callback("find_vf_file", -                            fonts.vf.find, -                           "luaotfload.find_vf_file") ---[[doc-- - -    XXX: see https://github.com/wspr/unicode-math/issues/185 -    \luatex does not provide interface to accessing -    |(Script)ScriptPercentScaleDown| math constants, so we -    emulate \xetex behaviour by setting |\fontdimen10| and -    |\fontdimen11|. - -    Note: actually, it does now, but not unless you update. - ---doc]]-- - -local function set_sscale_diments(fontdata) -    local mc = fontdata.MathConstants -    if mc then -        if mc["ScriptPercentScaleDown"] then -            fontdata.parameters[10] = mc.ScriptPercentScaleDown -        else -- resort to plain TeX default -            fontdata.parameters[10] = 70 -        end -        if mc["ScriptScriptPercentScaleDown"] then -            fontdata.parameters[11] = mc.ScriptScriptPercentScaleDown -        else -- resort to plain TeX default -            fontdata.parameters[11] = 50 -        end -    end -end - -luatexbase.add_to_callback("luaotfload.patch_font", set_sscale_diments, "unicodemath.set_sscale_diments") - ---[[doc-- -  Version 2.3c of fontspec dropped a couple features that are now -  provided in the luaotfload auxiliary libraries. To avoid breaking -  Mik\TEX (again), which is sorta the entire point of distributing the -  legacy codebase, we temporarily restore those functions here. - -  Note that apart from cosmetic changes these are still the same as in -  pre-TL2013 fontspec, relying on pairs() and other inefficient methods. ---doc]]-- - -luaotfload.aux      = luaotfload.aux or { } -local aux           = luaotfload.aux - -local stringlower   = string.lower -local fontid        = font.id - -local identifiers   = fonts.identifiers - -local check_script = function (id, script) -  local s = stringlower(script) -  if id and id > 0 then -    local tfmdata = identifiers[id] -    local otfdata = tfmdata.shared and tfmdata.shared.otfdata -    if otfdata then -      local features = otfdata.luatex.features -      for i, _ in pairs(features) do -        for j, _ in pairs(features[i]) do -          if features[i][j][s] then -            fontspec.log("script '%s' exists in font '%s'", -                         script, tfmdata.fullname) -            return true -          end -        end -      end -    end -  end -end - -local check_language = function (id, script, language) -  local s = stringlower(script) -  local l = stringlower(language) -  if id and id > 0 then -    local tfmdata = identifiers[id] -    local otfdata = tfmdata.shared and tfmdata.shared.otfdata -    if otfdata then -      local features = otfdata.luatex.features -      for i, _ in pairs(features) do -        for j, _ in pairs(features[i]) do -          if features[i][j][s] and features[i][j][s][l] then -            fontspec.log("language '%s' for script '%s' exists in font '%s'", -                         language, script, tfmdata.fullname) -            return true -          end -        end -      end -    end -  end -end - -local check_feature = function (id, script, language, feature) -  local s = stringlower(script) -  local l = stringlower(language) -  local f = stringlower(feature:gsub("^[+-]", ""):gsub("=.*$", "")) -  if id and id > 0 then -    local tfmdata = identifiers[id] -    local otfdata = tfmdata.shared and tfmdata.shared.otfdata -    if otfdata then -      local features = otfdata.luatex.features -      for i, _ in pairs(features) do -        if features[i][f] and features[i][f][s] then -          if features[i][f][s][l] == true then -            fontspec.log("feature '%s' for language '%s' and script '%s' exists in font '%s'", -                         feature, language, script, tfmdata.fullname) -            return true -          end -        end -      end -    end -  end -end - -local get_math_dimension = function(fnt, str) -  if type(fnt) == "string" then -    fnt = fontid(fnt) -  end -  local tfmdata = identifiers[fnt] -  if tfmdata then -    local mathdata = tfmdata.MathConstants -    if mathdata then -      return mathdata[str] -    end -  end -end - -aux.provides_script       = check_script -aux.provides_language     = check_language -aux.provides_feature      = check_feature -aux.get_math_dimension    = get_math_dimension - -local set_capheight = function (tfmdata) -    local capheight -    local shared = tfmdata.shared -    if shared then -      local metadata       = shared.otfdata.metadata -      local units_per_em   = metadata.units_per_em or tfmdata.units -      local os2_capheight  = shared.otfdata.pfminfo.os2_capheight -      local size           = tfmdata.size - -      if os2_capheight > 0 then -          capheight = os2_capheight / units_per_em * size -      else -          local X8 = string.byte"X" -          if tfmdata.characters[X8] then -              capheight = tfmdata.characters[X8].height -          else -              capheight = metadata.ascent / units_per_em * size -          end -      end -    else -        local X8 = string.byte"X" -        if tfmdata.characters[X8] then -            capheight = tfmdata.characters[X8].height -        end -    end -    if capheight then -        tfmdata.parameters[8] = capheight -    end -end -luatexbase.add_to_callback("luaotfload.patch_font", -                           set_capheight, -                           "luaotfload.set_capheight") - ---[[doc-- -End of auxiliary functionality that was moved from fontspec.lua. ---doc]]-- - --- vim:ts=2:sw=2:expandtab:ft=lua | 
