diff options
author | Philipp Gesang <phg42.2a@gmail.com> | 2013-07-23 15:38:32 -0700 |
---|---|---|
committer | Philipp Gesang <phg42.2a@gmail.com> | 2013-07-23 15:38:32 -0700 |
commit | daeb3c1fddf826deb325cbe2a6567083c828ca13 (patch) | |
tree | 12aed96922ab72b4889899d8b4499d5e1600362a | |
parent | 36abb3e8cf8d2d24bf5cfb770cdba2731de655c5 (diff) | |
parent | 2331b6838f623d4800e79e92c50ce55f955d7776 (diff) | |
download | luaotfload-daeb3c1fddf826deb325cbe2a6567083c828ca13.tar.gz |
Merge pull request #111 from phi-gamma/master
update to v2.3b
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | luaotfload-auxiliary.lua | 31 | ||||
-rw-r--r-- | luaotfload-basics-gen.lua | 22 | ||||
-rw-r--r-- | luaotfload-basics-nod.lua | 79 | ||||
-rw-r--r-- | luaotfload-colors.lua | 2 | ||||
-rw-r--r-- | luaotfload-database.lua | 106 | ||||
-rw-r--r-- | luaotfload-features.lua | 10 | ||||
-rw-r--r-- | luaotfload-merged.lua | 766 | ||||
-rw-r--r-- | luaotfload-override.lua | 2 | ||||
-rwxr-xr-x | luaotfload-tool.lua | 77 | ||||
-rw-r--r-- | luaotfload-typo-krn.lua | 4 | ||||
-rw-r--r-- | luaotfload.dtx | 33 | ||||
-rwxr-xr-x | mktests | 134 |
13 files changed, 821 insertions, 451 deletions
@@ -67,8 +67,9 @@ ZIPS = $(CTAN_ZIP) $(TDS_ZIP) LUA = texlua DO_TEX = luatex --interaction=batchmode $< >/dev/null -# (with the next version of latexmk: -pdf -pdflatex=lualatex) -DO_LATEX = latexmk -pdf -e '$$pdflatex = q(lualatex %O %S)' -silent $< >/dev/null +DO_LATEXMK = latexmk -e '$$max_repeat = 5' -pdf -lualatex -silent $< >/dev/null +# latexmk does only one run on my machine, so we’re not going to rely on it +DO_LATEX = lualatex -interaction=batchmode $< >/dev/null DO_GRAPHVIZ = dot -Tpdf -o $@ $< > /dev/null DO_GLYPHS = $(LUA) $(GLYPHSCRIPT) > /dev/null DO_CHARS = $(LUA) $(CHARSCRIPT) > /dev/null @@ -101,6 +102,7 @@ $(GRAPHED): $(DOT) $(COMPILED): $(DTX) $(DO_LATEX) + $(DO_LATEX) $(UNPACKED): $(DTX) $(DO_TEX) diff --git a/luaotfload-auxiliary.lua b/luaotfload-auxiliary.lua index d6c8eaa..0a3ace8 100644 --- a/luaotfload-auxiliary.lua +++ b/luaotfload-auxiliary.lua @@ -48,10 +48,33 @@ local rewrite_fontname = function (tfmdata, specification) tfmdata.name = [["]] .. specification .. [["]] end -luatexbase.add_to_callback( - "luaotfload.patch_font", - rewrite_fontname, - "luaotfload.rewrite_fontname") +local rewriting = false + +local start_rewrite_fontname = function () + if rewriting == false then + luatexbase.add_to_callback ( + "luaotfload.patch_font", + rewrite_fontname, + "luaotfload.rewrite_fontname") + rewriting = true + logs.names_report ("log", 0, "aux", + "start rewriting tfmdata.name field") + end +end + +aux.start_rewrite_fontname = start_rewrite_fontname + +local stop_rewrite_fontname = function () + if rewriting == true then + luatexbase.remove_fromt_callback + ("luaotfload.patch_font", "luaotfload.rewrite_fontname") + rewriting = false + logs.names_report ("log", 0, "aux", + "stop rewriting tfmdata.name field") + end +end + +aux.stop_rewrite_fontname = stop_rewrite_fontname --- as of 2.3 the compatibility hacks for TL 2013 are made optional diff --git a/luaotfload-basics-gen.lua b/luaotfload-basics-gen.lua index a5da2fd..26c1edc 100644 --- a/luaotfload-basics-gen.lua +++ b/luaotfload-basics-gen.lua @@ -149,19 +149,29 @@ do local cachepaths = kpse.expand_var('$TEXMFCACHE') or "" - -- quite like tex live or so + -- quite like tex live or so (the weird $TEXMFCACHE test seems to be needed on miktex) - if cachepaths == "$TEXMFCACHE" then + if cachepaths == "" or cachepaths == "$TEXMFCACHE" then cachepaths = kpse.expand_var('$TEXMFVAR') or "" end - -- this also happened to be used + -- this also happened to be used (the weird $TEXMFVAR test seems to be needed on miktex) - if cachepaths == "$TEXMFVAR" then + if cachepaths == "" or cachepaths == "$TEXMFVAR" then cachepaths = kpse.expand_var('$VARTEXMF') or "" end - -- and this is a last resort + -- and this is a last resort (hm, we could use TEMP or TEMPDIR) + + if cachepaths == "" then + local fallbacks = { "TMPDIR", "TEMPDIR", "TMP", "TEMP", "HOME", "HOMEPATH" } + for i=1,#fallbacks do + cachepaths = os.getenv(fallbacks[i]) or "" + if cachepath ~= "" and lfs.isdir(cachepath) then + break + end + end + end if cachepaths == "" then cachepaths = "." @@ -267,7 +277,7 @@ function caches.savedata(path,name,data) local luaname, lucname = makefullname(path,name) if luaname then texio.write(string.format("(save: %s)",luaname)) - table.tofile(luaname,data,true,{ reduce = true }) + table.tofile(luaname,data,true) if lucname and type(caches.compile) == "function" then os.remove(lucname) -- better be safe texio.write(string.format("(save: %s)",lucname)) diff --git a/luaotfload-basics-nod.lua b/luaotfload-basics-nod.lua index 5ab9df7..50a1e86 100644 --- a/luaotfload-basics-nod.lua +++ b/luaotfload-basics-nod.lua @@ -88,17 +88,80 @@ function nodes.delete(head,current) return nodes.remove(head,current,true) end -nodes.before = node.insert_before -nodes.after = node.insert_after - function nodes.pool.kern(k) local n = new_node("kern",1) n.kern = k return n end -function nodes.endofmath(n) - for n in traverse_id(math_code,n.next) do - return n - end -end +-- experimental + +local getfield = node.getfield or function(n,tag) return n[tag] end +local setfield = node.setfield or function(n,tag,value) n[tag] = value end + +nodes.getfield = getfield +nodes.setfield = setfield + +nodes.getattr = getfield +nodes.setattr = setfield + +if node.getid then nodes.getid = node.getid else function nodes.getid (n) return getfield(n,"id") end end +if node.getsubtype then nodes.getsubtype = node.getsubtype else function nodes.getsubtype(n) return getfield(n,"subtype") end end +if node.getnext then nodes.getnext = node.getnext else function nodes.getnext (n) return getfield(n,"next") end end +if node.getprev then nodes.getprev = node.getprev else function nodes.getprev (n) return getfield(n,"prev") end end +if node.getchar then nodes.getchar = node.getchar else function nodes.getchar (n) return getfield(n,"char") end end +if node.getfont then nodes.getfont = node.getfont else function nodes.getfont (n) return getfield(n,"font") end end +if node.getlist then nodes.getlist = node.getlist else function nodes.getlist (n) return getfield(n,"list") end end + +function nodes.tonut (n) return n end +function nodes.tonode(n) return n end + +-- being lazy ... just copy a bunch ... not all needed in generic but we assume +-- nodes to be kind of private anyway + +nodes.tostring = node.tostring or tostring +nodes.copy = node.copy +nodes.copy_list = node.copy_list +nodes.delete = node.delete +nodes.dimensions = node.dimensions +nodes.end_of_math = node.end_of_math +nodes.flush_list = node.flush_list +nodes.flush_node = node.flush_node +nodes.free = node.free +nodes.insert_after = node.insert_after +nodes.insert_before = node.insert_before +nodes.hpack = node.hpack +nodes.new = node.new +nodes.tail = node.tail +nodes.traverse = node.traverse +nodes.traverse_id = node.traverse_id +nodes.slide = node.slide +nodes.vpack = node.vpack + +nodes.first_glyph = node.first_glyph +nodes.first_character = node.first_character +nodes.has_glyph = node.has_glyph or node.first_glyph + +nodes.current_attr = node.current_attr +nodes.do_ligature_n = node.do_ligature_n +nodes.has_field = node.has_field +nodes.last_node = node.last_node +nodes.usedlist = node.usedlist +nodes.protrusion_skippable = node.protrusion_skippable +nodes.write = node.write + +nodes.has_attribute = node.has_attribute +nodes.set_attribute = node.set_attribute +nodes.unset_attribute = node.unset_attribute + +nodes.protect_glyphs = node.protect_glyphs +nodes.unprotect_glyphs = node.unprotect_glyphs +nodes.kerning = node.kerning +nodes.ligaturing = node.ligaturing +nodes.mlist_to_hlist = node.mlist_to_hlist + +-- in generic code, at least for some time, we stay nodes, while in context +-- we can go nuts (e.g. experimental); this split permits us us keep code +-- used elsewhere stable but at the same time play around in context + +nodes.nuts = nodes diff --git a/luaotfload-colors.lua b/luaotfload-colors.lua index b95e836..ac9291d 100644 --- a/luaotfload-colors.lua +++ b/luaotfload-colors.lua @@ -87,7 +87,7 @@ local sanitize_color_expression = function (digits) local sanitized = lpegmatch(valid_digits, digits) if not sanitized then luaotfload.warning( - "“%s” is not a valid rgb[a] color expression", digits) + "%q is not a valid rgb[a] color expression", digits) return nil end return sanitized diff --git a/luaotfload-database.lua b/luaotfload-database.lua index e0b977b..1b75458 100644 --- a/luaotfload-database.lua +++ b/luaotfload-database.lua @@ -1,5 +1,5 @@ if not modules then modules = { } end modules ['luaotfload-database'] = { - version = "2.3a", + version = "2.3b", comment = "companion to luaotfload.lua", author = "Khaled Hosny, Elie Roux, Philipp Gesang", copyright = "Luaotfload Development Team", @@ -27,7 +27,6 @@ local require = require local tonumber = tonumber local unpack = table.unpack - local fontloaderinfo = fontloader.info local fontloaderopen = fontloader.open local iolines = io.lines @@ -38,6 +37,8 @@ local kpsefind_file = kpse.find_file local kpselookup = kpse.lookup local kpsereadable_file = kpse.readable_file local lfsattributes = lfs.attributes +local lfschdir = lfs.chdir +local lfscurrentdir = lfs.currentdir local lfsdir = lfs.dir local mathabs = math.abs local mathmin = math.min @@ -54,6 +55,7 @@ local tablesort = table.sort local texiowrite_nl = texio.write_nl local utf8gsub = unicode.utf8.gsub local utf8lower = unicode.utf8.lower + --- these come from Lualibs/Context local getwritablepath = caches.getwritablepath local filebasename = file.basename @@ -172,25 +174,31 @@ find_files_indeed = function (acc, dirs, filter) return acc end + local pwd = lfscurrentdir () local dir = dirs[#dirs] dirs[#dirs] = nil - local newdirs, newfiles = { }, { } - for ent in lfsdir (dir) do - if ent ~= "." and ent ~= ".." then - local fullpath = dir .. "/" .. ent - if filter (fullpath) == true then - if lfsisdir (fullpath) then - newdirs[#newdirs+1] = fullpath - elseif lfsisfile (fullpath) then - newfiles[#newfiles+1] = fullpath + if lfschdir (dir) then + lfschdir (pwd) + + local newfiles = { } + for ent in lfsdir (dir) do + if ent ~= "." and ent ~= ".." then + local fullpath = dir .. "/" .. ent + if filter (fullpath) == true then + if lfsisdir (fullpath) then + dirs[#dirs+1] = fullpath + elseif lfsisfile (fullpath) then + newfiles[#newfiles+1] = fullpath + end end end end + return find_files_indeed (tableappend (acc, newfiles), + dirs, filter) end - return find_files_indeed (tableappend (acc, newfiles), - tableappend (dirs, newdirs), - filter) + --- could not cd into, so we skip it + return find_files_indeed (acc, dirs, filter) end local dummyfilter = function () return true end @@ -363,11 +371,11 @@ load_names = function (dry_run) local db_version, nms_version = data.version, names.version if db_version ~= nms_version then - report("log", 0, "db", + report("both", 0, "db", [[Version mismatch; expected %4.3f, got %4.3f]], nms_version, db_version) if not fonts_reloaded then - report("log", 0, "db", [[force rebuild]]) + report("both", 0, "db", [[Force rebuild]]) return update_names({ }, true, false) end end @@ -643,7 +651,7 @@ end resolve_cached = function (_, _, specification) if not names.lookups then names.lookups = load_lookups() end local request = hash_request(specification) - report("both", 4, "cache", "Looking for “%s” in cache ...", + report("both", 4, "cache", "Looking for %q in cache ...", request) local found = names.lookups[request] @@ -927,7 +935,7 @@ resolve = function (_, _, specification) -- the 1st two parameters are used by C if not fonts_reloaded then --- last straw: try reloading the database return reload_db( - "unresolved font name: ‘" .. name .. "’", + "unresolved font name: '" .. name .. "'", resolve, nil, nil, specification ) end @@ -954,7 +962,7 @@ end --- string -> ('a -> 'a) -> 'a list -> 'a reload_db = function (why, caller, ...) - report("both", 1, "db", "Reload initiated; reason: “%s”", why) + report("both", 1, "db", "Reload initiated; reason: %q", why) names.data = update_names(names.data, false, false) local success = save_names() if success then @@ -1056,7 +1064,7 @@ find_closest = function (name, limit) local dist = distances[i] local namelst = by_distance[dist] report(false, 0, "query", - "Distance from “" .. name .. "”: " .. dist + "Distance from \"" .. name .. "\": " .. dist .. "\n " .. tableconcat(namelst, "\n ") ) end @@ -1174,7 +1182,7 @@ local load_font = function (fullname, fontnames, newfontnames, texmf) if names.blacklist[fullname] or names.blacklist[basename] then report("log", 2, "db", - "Ignoring blacklisted font “%s”", fullname) + "Ignoring blacklisted font %q", fullname) return false end @@ -1205,7 +1213,7 @@ local load_font = function (fullname, fontnames, newfontnames, texmf) newmappings[location] = fullinfo --- keep newentrystatus.index[index+1] = location --- is this actually used anywhere? end - report("log", 2, "db", "Font “%s” already indexed", basename) + report("log", 2, "db", "Font %q already indexed", basename) return false end @@ -1238,7 +1246,7 @@ local load_font = function (fullname, fontnames, newfontnames, texmf) end else --- missing info - report("log", 1, "db", "Failed to load “%s”", basename) + report("log", 1, "db", "Failed to load %q", basename) return false end return true @@ -1319,7 +1327,7 @@ local create_blacklist = function (blacklist, whitelist) local result = { } local dirs = { } - report("info", 2, "db", "Blacklisting “%d” files and directories", + report("info", 2, "db", "Blacklisting %q files and directories", #blacklist) for i=1, #blacklist do local entry = blacklist[i] @@ -1330,7 +1338,7 @@ local create_blacklist = function (blacklist, whitelist) end end - report("info", 2, "db", "Whitelisting “%d” files", #whitelist) + report("info", 2, "db", "Whitelisting %q files", #whitelist) for i=1, #whitelist do result[whitelist[i]] = nil end @@ -1379,7 +1387,7 @@ read_blacklist = function () line = stringsub(line, 1, cmt - 1) end line = stringstrip(line) - report("log", 2, "db", "Blacklisted file “%s”", line) + report("log", 2, "db", "Blacklisted file %q", line) blacklist[#blacklist+1] = line end end @@ -1412,28 +1420,34 @@ process_dir_tree = function (acc, dirs) return acc end + local pwd = lfscurrentdir () local dir = dirs[#dirs] dirs[#dirs] = nil - local newdirs, newfiles = { }, { } - local blacklist = names.blacklist - for ent in lfsdir (dir) do - --- filter right away - if ent ~= "." and ent ~= ".." and not blacklist[ent] then - local fullpath = dir .. "/" .. ent - if lfsisdir (fullpath) - and not lpegmatch (p_blacklist, fullpath) - then - newdirs[#newdirs+1] = fullpath - elseif lfsisfile (fullpath) then - if lpegmatch (p_font_extensions, stringlower(ent)) then - newfiles[#newfiles+1] = fullpath + if lfschdir (dir) then + lfschdir (pwd) + + local newfiles = { } + local blacklist = names.blacklist + for ent in lfsdir (dir) do + --- filter right away + if ent ~= "." and ent ~= ".." and not blacklist[ent] then + local fullpath = dir .. "/" .. ent + if lfsisdir (fullpath) + and not lpegmatch (p_blacklist, fullpath) + then + dirs[#dirs+1] = fullpath + elseif lfsisfile (fullpath) then + if lpegmatch (p_font_extensions, stringlower(ent)) then + newfiles[#newfiles+1] = fullpath + end end end end + return process_dir_tree (tableappend (acc, newfiles), dirs) end - return process_dir_tree (tableappend (acc, newfiles), - tableappend (dirs, newdirs)) + --- cannot cd; skip + return process_dir_tree (acc, dirs) end --- string -> string list @@ -1467,7 +1481,7 @@ local scan_dir = function (dirname, fontnames, newfontnames, local found = find_font_files (dirname) if not found then report ("both", 3, "db", - "No such directory: “%s”; skipping.", dirname) + "No such directory: %q; skipping.", dirname) return 0, 0 end report ("both", 3, "db", "Scanning directory %s", dirname) @@ -1481,10 +1495,10 @@ local scan_dir = function (dirname, fontnames, newfontnames, local new if dry_run == true then report ("both", 1, "db", - "Would have been loading “%s”", fullname) + "Would have been loading %q", fullname) else report ("both", 4, "db", - "Loading font “%s”", fullname) + "Loading font %q", fullname) local new = load_font (fullname, fontnames, newfontnames, texmf) if new == true then @@ -1841,7 +1855,7 @@ local gen_fast_lookups = function (fontnames) local known = filenames.base[base] or filenames.bare[bare] if known then --- known report("both", 3, "db", - "Font file “%s” already indexed (%d)", + "Font file %q already indexed (%d)", base, idx) report("both", 3, "db", "> old location: %s", (filenames.full[known] or "texmf")) @@ -2023,7 +2037,7 @@ local purge_from_cache = function (category, path, list, all) local n = 0 for i=1,#list do local filename = list[i] - if string.find(filename,"luatex%-cache") then -- safeguard + if stringfind(filename,"luatex%-cache") then -- safeguard if all then report("info", 5, "cache", "removing %s", filename) osremove(filename) diff --git a/luaotfload-features.lua b/luaotfload-features.lua index a07992b..4088379 100644 --- a/luaotfload-features.lua +++ b/luaotfload-features.lua @@ -778,7 +778,7 @@ local set_default_features = function (speclist) if support_incomplete[script] then report("log", 0, "load", "support for the requested script: " - .. "“%s” may be incomplete", script) + .. "%q may be incomplete", script) end else script = "dflt" @@ -792,7 +792,7 @@ local set_default_features = function (speclist) local requested = defaults[script] if not requested then report("log", 0, "load", - "no defaults for script “%s”, falling back to “dflt”", + "no defaults for script %q, falling back to \"dflt\"", script) requested = defaults.dflt end @@ -924,7 +924,7 @@ end --doc]]-- local handle_invalid_option = function (opt) - report("log", 0, "load", "font option “%s” unknown.", opt) + report("log", 0, "load", "font option %q unknown.", opt) return "", false end @@ -942,7 +942,7 @@ local check_garbage = function (_,i, garbage) "warning: path in file: lookups is deprecated; ") report("log", 0, "load", "use bracket syntax instead!") report("log", 0, "load", - "position: %d; full match: “%s”", + "position: %d; full match: %q", i, garbage) return true end @@ -1134,7 +1134,7 @@ local handle_request = function (specification) --- in an anonymous lookup; --- we try to behave as friendly as possible --- just go with it ... - report("log", 1, "load", "invalid request “%s” of type anon", + report("log", 1, "load", "invalid request %q of type anon", specification.specification) report("log", 1, "load", "use square bracket syntax or consult the documentation.") diff --git a/luaotfload-merged.lua b/luaotfload-merged.lua index 52c199a..c17a541 100644 --- a/luaotfload-merged.lua +++ b/luaotfload-merged.lua @@ -1,6 +1,6 @@ -- merged file : luatex-fonts-merged.lua -- parent file : luatex-fonts.lua --- merge date : 06/10/13 12:24:08 +-- merge date : 07/14/13 14:53:44 do -- begin closure to overcome local limits and interference @@ -95,6 +95,7 @@ if not modules then modules={} end modules ['l-lpeg']={ license="see context related readme files" } lpeg=require("lpeg") +if not lpeg.print then function lpeg.print(...) print(lpeg.pcode(...)) end end local type,next,tostring=type,next,tostring local byte,char,gmatch,format=string.byte,string.char,string.gmatch,string.format local floor=math.floor @@ -213,7 +214,7 @@ patterns.decafloat=sign^-1*(digit^0*period*digit^1+digit^1*period*digit^0+digit^ patterns.propername=(uppercase+lowercase+underscore)*(uppercase+lowercase+underscore+digit)^0*endofstring patterns.somecontent=(anything-newline-space)^1 patterns.beginline=#(1-newline) -patterns.longtostring=Cs(whitespace^0/""*nonwhitespace^0*((whitespace^0/" "*(patterns.quoted+nonwhitespace)^1)^0)) +patterns.longtostring=Cs(whitespace^0/""*((patterns.quoted+nonwhitespace^1+whitespace^1/""*(P(-1)+Cc(" ")))^0)) local function anywhere(pattern) return P { P(pattern)+1*V(1) } end @@ -1066,6 +1067,7 @@ local noquotes,hexify,handle,reduce,compact,inline,functions local reserved=table.tohash { 'and','break','do','else','elseif','end','false','for','function','if', 'in','local','nil','not','or','repeat','return','then','true','until','while', + 'NaN','goto', } local function simple_table(t) if #t>0 then @@ -1691,6 +1693,7 @@ local function readall(f) return f:read('*all') else local done=f:seek("set",0) + local step if size<1024*1024 then step=1024*1024 elseif size>16*1024*1024 then @@ -2214,17 +2217,24 @@ end function file.joinpath(tab,separator) return tab and concat(tab,separator or io.pathseparator) end +local someslash=S("\\/") local stripper=Cs(P(fwslash)^0/""*reslasher) -local isnetwork=fwslash*fwslash*(1-fwslash)+(1-fwslash-colon)^1*colon +local isnetwork=someslash*someslash*(1-someslash)+(1-fwslash-colon)^1*colon local isroot=fwslash^1*-1 local hasroot=fwslash^1 +local reslasher=lpeg.replacer(S("\\/"),"/") local deslasher=lpeg.replacer(S("\\/")^1,"/") function file.join(...) local lst={... } local one=lst[1] if lpegmatch(isnetwork,one) then + local one=lpegmatch(reslasher,one) local two=lpegmatch(deslasher,concat(lst,"/",2)) - return one.."/"..two + if lpegmatch(hasroot,two) then + return one..two + else + return one.."/"..two + end elseif lpegmatch(isroot,one) then local two=lpegmatch(deslasher,concat(lst,"/",2)) if lpegmatch(hasroot,two) then @@ -2241,7 +2251,9 @@ end local drivespec=R("az","AZ")^1*colon local anchors=fwslash+drivespec local untouched=periods+(1-period)^1*P(-1) -local splitstarter=(Cs(drivespec*(bwslash/"/"+fwslash)^0)+Cc(false))*Ct(lpeg.splitat(S("/\\")^1)) +local mswindrive=Cs(drivespec*(bwslash/"/"+fwslash)^0) +local mswinuncpath=(bwslash+fwslash)*(bwslash+fwslash)*Cc("//") +local splitstarter=(mswindrive+mswinuncpath+Cc(false))*Ct(lpeg.splitat(S("/\\")^1)) local absolute=fwslash function file.collapsepath(str,anchor) if not str then @@ -2653,7 +2665,7 @@ local format_i=function(f) if f and f~="" then return format("format('%%%si',a%s)",f,n) else - return format("a%s",n) + return format("format('%%i',a%s)",n) end end local format_d=format_i @@ -3044,13 +3056,22 @@ if not caches.namespace or caches.namespace=="" or caches.namespace=="context" t end do local cachepaths=kpse.expand_var('$TEXMFCACHE') or "" - if cachepaths=="" or cachepaths == "$TEXMFCACHE" then + if cachepaths=="" or cachepaths=="$TEXMFCACHE" then cachepaths=kpse.expand_var('$TEXMFVAR') or "" end - if cachepaths=="" or cachepaths == "$TEXMFVAR" then + if cachepaths=="" or cachepaths=="$TEXMFVAR" then cachepaths=kpse.expand_var('$VARTEXMF') or "" end if cachepaths=="" then + local fallbacks={ "TMPDIR","TEMPDIR","TMP","TEMP","HOME","HOMEPATH" } + for i=1,#fallbacks do + cachepaths=os.getenv(fallbacks[i]) or "" + if cachepath~="" and lfs.isdir(cachepath) then + break + end + end + end + if cachepaths=="" then cachepaths="." end cachepaths=string.split(cachepaths,os.type=="windows" and ";" or ":") @@ -3143,7 +3164,7 @@ function caches.savedata(path,name,data) local luaname,lucname=makefullname(path,name) if luaname then texio.write(string.format("(save: %s)",luaname)) - table.tofile(luaname,data,true,{ reduce=false }) + table.tofile(luaname,data,true) if lucname and type(caches.compile)=="function" then os.remove(lucname) texio.write(string.format("(save: %s)",lucname)) @@ -3355,18 +3376,63 @@ end function nodes.delete(head,current) return nodes.remove(head,current,true) end -nodes.before=node.insert_before -nodes.after=node.insert_after function nodes.pool.kern(k) local n=new_node("kern",1) n.kern=k return n end -function nodes.endofmath(n) - for n in traverse_id(math_code,n.next) do - return n - end -end +local getfield=node.getfield or function(n,tag) return n[tag] end +local setfield=node.setfield or function(n,tag,value) n[tag]=value end +nodes.getfield=getfield +nodes.setfield=setfield +nodes.getattr=getfield +nodes.setattr=setfield +if node.getid then nodes.getid=node.getid else function nodes.getid (n) return getfield(n,"id") end end +if node.getsubtype then nodes.getsubtype=node.getsubtype else function nodes.getsubtype(n) return getfield(n,"subtype") end end +if node.getnext then nodes.getnext=node.getnext else function nodes.getnext (n) return getfield(n,"next") end end +if node.getprev then nodes.getprev=node.getprev else function nodes.getprev (n) return getfield(n,"prev") end end +if node.getchar then nodes.getchar=node.getchar else function nodes.getchar (n) return getfield(n,"char") end end +if node.getfont then nodes.getfont=node.getfont else function nodes.getfont (n) return getfield(n,"font") end end +if node.getlist then nodes.getlist=node.getlist else function nodes.getlist (n) return getfield(n,"list") end end +function nodes.tonut (n) return n end +function nodes.tonode(n) return n end +nodes.tostring=node.tostring or tostring +nodes.copy=node.copy +nodes.copy_list=node.copy_list +nodes.delete=node.delete +nodes.dimensions=node.dimensions +nodes.end_of_math=node.end_of_math +nodes.flush_list=node.flush_list +nodes.flush_node=node.flush_node +nodes.free=node.free +nodes.insert_after=node.insert_after +nodes.insert_before=node.insert_before +nodes.hpack=node.hpack +nodes.new=node.new +nodes.tail=node.tail +nodes.traverse=node.traverse +nodes.traverse_id=node.traverse_id +nodes.slide=node.slide +nodes.vpack=node.vpack +nodes.first_glyph=node.first_glyph +nodes.first_character=node.first_character +nodes.has_glyph=node.has_glyph or node.first_glyph +nodes.current_attr=node.current_attr +nodes.do_ligature_n=node.do_ligature_n +nodes.has_field=node.has_field +nodes.last_node=node.last_node +nodes.usedlist=node.usedlist +nodes.protrusion_skippable=node.protrusion_skippable +nodes.write=node.write +nodes.has_attribute=node.has_attribute +nodes.set_attribute=node.set_attribute +nodes.unset_attribute=node.unset_attribute +nodes.protect_glyphs=node.protect_glyphs +nodes.unprotect_glyphs=node.unprotect_glyphs +nodes.kerning=node.kerning +nodes.ligaturing=node.ligaturing +nodes.mlist_to_hlist=node.mlist_to_hlist +nodes.nuts=nodes end -- closure @@ -4415,7 +4481,8 @@ function constructors.collectprocessors(what,tfmdata,features,trace,report) local whathandler=handlers[what] local whatfeatures=whathandler.features local whatprocessors=whatfeatures.processors - local processors=whatprocessors[properties.mode] + local mode=properties.mode + local processors=whatprocessors[mode] if processors then for i=1,#processors do local step=processors[i] @@ -4432,7 +4499,7 @@ function constructors.collectprocessors(what,tfmdata,features,trace,report) end end elseif trace then - report("no feature processors for mode %a for font %a",mode,tfmdata.properties.fullname) + report("no feature processors for mode %a for font %a",mode,properties.fullname) end end return processes @@ -4443,7 +4510,8 @@ function constructors.applymanipulators(what,tfmdata,features,trace,report) local whathandler=handlers[what] local whatfeatures=whathandler.features local whatmanipulators=whatfeatures.manipulators - local manipulators=whatmanipulators[properties.mode] + local mode=properties.mode + local manipulators=whatmanipulators[mode] if manipulators then for i=1,#manipulators do local step=manipulators[i] @@ -4452,7 +4520,7 @@ function constructors.applymanipulators(what,tfmdata,features,trace,report) if value then local action=step.action if trace then - report("applying feature manipulator %a for mode %a for font %a",feature,mode,tfmdata.properties.fullname) + report("applying feature manipulator %a for mode %a for font %a",feature,mode,properties.fullname) end if action then action(tfmdata,feature,value) @@ -7527,11 +7595,24 @@ local injections=nodes.injections local nodecodes=nodes.nodecodes local glyph_code=nodecodes.glyph local kern_code=nodecodes.kern -local nodepool=nodes.pool +local nuts=nodes.nuts +local nodepool=nuts.pool local newkern=nodepool.kern -local traverse_id=node.traverse_id -local insert_node_before=node.insert_before -local insert_node_after=node.insert_after +local tonode=nuts.tonode +local tonut=nuts.tonut +local getfield=nuts.getfield +local getnext=nuts.getnext +local getprev=nuts.getprev +local getid=nuts.getid +local getattr=nuts.getattr +local getfont=nuts.getfont +local getsubtype=nuts.getsubtype +local getchar=nuts.getchar +local setfield=nuts.setfield +local setattr=nuts.setattr +local traverse_id=nuts.traverse_id +local insert_node_before=nuts.insert_before +local insert_node_after=nuts.insert_after local a_kernpair=attributes.private('kernpair') local a_ligacomp=attributes.private('ligacomp') local a_markbase=attributes.private('markbase') @@ -7550,21 +7631,21 @@ function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmne local dx,dy=factor*(exit[1]-entry[1]),factor*(exit[2]-entry[2]) local ws,wn=tfmstart.width,tfmnext.width local bound=#cursives+1 - start[a_cursbase]=bound - nxt[a_curscurs]=bound + setattr(start,a_cursbase,bound) + setattr(nxt,a_curscurs,bound) cursives[bound]={ rlmode,dx,dy,ws,wn } return dx,dy,bound end function injections.setpair(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=current[a_kernpair] + local bound=getattr(current,a_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 - current[a_kernpair]=bound + setattr(current,a_kernpair,bound) kerns[bound]={ rlmode,x,y,w,h,r2lflag,tfmchr.width } end return x,y,w,h,bound @@ -7575,7 +7656,7 @@ function injections.setkern(current,factor,rlmode,x,tfmchr) local dx=factor*x if dx~=0 then local bound=#kerns+1 - current[a_kernpair]=bound + setattr(current,a_kernpair,bound) kerns[bound]={ rlmode,dx } return dx,bound else @@ -7584,25 +7665,25 @@ function injections.setkern(current,factor,rlmode,x,tfmchr) end function injections.setmark(start,base,factor,rlmode,ba,ma,index) local dx,dy=factor*(ba[1]-ma[1]),factor*(ba[2]-ma[2]) - local bound=base[a_markbase] + local bound=getattr(base,a_markbase) local index=1 if bound then local mb=marks[bound] if mb then index=#mb+1 mb[index]={ dx,dy,rlmode } - start[a_markmark]=bound - start[a_markdone]=index + setattr(start,a_markmark,bound) + setattr(start,a_markdone,index) return dx,dy,bound else - report_injections("possible problem, %U is base mark without data (id %a)",base.char,bound) + report_injections("possible problem, %U is base mark without data (id %a)",getchar(base),bound) end end index=index or 1 bound=#marks+1 - base[a_markbase]=bound - start[a_markmark]=bound - start[a_markdone]=index + setattr(base,a_markbase,bound) + setattr(start,a_markmark,bound) + setattr(start,a_markdone,index) marks[bound]={ [index]={ dx,dy,rlmode } } return dx,dy,bound end @@ -7612,15 +7693,15 @@ end local function trace(head) report_injections("begin run") for n in traverse_id(glyph_code,head) do - if n.subtype<256 then - local kp=n[a_kernpair] - local mb=n[a_markbase] - local mm=n[a_markmark] - local md=n[a_markdone] - local cb=n[a_cursbase] - local cc=n[a_curscurs] - local char=n.char - report_injections("font %s, char %U, glyph %c",n.font,char,char) + if getsubtype(n)<256 then + local kp=getattr(n,a_kernpair) + local mb=getattr(n,a_markbase) + local mm=getattr(n,a_markmark) + local md=getattr(n,a_markdone) + local cb=getattr(n,a_cursbase) + local cc=getattr(n,a_curscurs) + local char=getchar(n) + report_injections("font %s, char %U, glyph %c",getfont(n),char,char) if kp then local k=kerns[kp] if k[3] then @@ -7661,21 +7742,23 @@ local function show_result(head) local current=head local skipping=false while current do - local id=current.id + local id=getid(current) if id==glyph_code then - report_injections("char: %C, width %p, xoffset %p, yoffset %p",current.char,current.width,current.xoffset,current.yoffset) + report_injections("char: %C, width %p, xoffset %p, yoffset %p", + getchar(current),getfield(current,"width"),getfield(current,"xoffset"),getfield(current,"yoffset")) skipping=false elseif id==kern_code then - report_injections("kern: %p",current.kern) + report_injections("kern: %p",getfield(current,"kern")) skipping=false elseif not skipping then report_injections() skipping=true end - current=current.next + current=getnext(current) end end function injections.handler(head,where,keep) + head=tonut(head) local has_marks,has_cursives,has_kerns=next(marks),next(cursives),next(kerns) if has_marks or has_cursives then if trace_injections then @@ -7685,17 +7768,18 @@ function injections.handler(head,where,keep) if has_kerns then local nf,tm=nil,nil for n in traverse_id(glyph_code,head) do - if n.subtype<256 then + if getsubtype(n)<256 then nofvalid=nofvalid+1 valid[nofvalid]=n - if n.font~=nf then - nf=n.font - tm=fontdata[nf].resources.marks + local f=getfont(n) + if f~=nf then + nf=f + tm=fontdata[nf].resources.marks end if tm then - mk[n]=tm[n.char] + mk[n]=tm[getchar(n)] end - local k=n[a_kernpair] + local k=getattr(n,a_kernpair) if k then local kk=kerns[k] if kk then @@ -7715,15 +7799,16 @@ function injections.handler(head,where,keep) else local nf,tm=nil,nil for n in traverse_id(glyph_code,head) do - if n.subtype<256 then + if getsubtype(n)<256 then nofvalid=nofvalid+1 valid[nofvalid]=n - if n.font~=nf then - nf=n.font + local f=getfont(n) + if f~=nf then + nf=f tm=fontdata[nf].resources.marks end if tm then - mk[n]=tm[n.char] + mk[n]=tm[getchar(n)] end end end @@ -7732,7 +7817,7 @@ function injections.handler(head,where,keep) local cx={} if has_kerns and next(ky) then for n,k in next,ky do - n.yoffset=k + setfield(n,"yoffset",k) end end if has_cursives then @@ -7741,9 +7826,9 @@ function injections.handler(head,where,keep) for i=1,nofvalid do local n=valid[i] if not mk[n] then - local n_cursbase=n[a_cursbase] + local n_cursbase=getattr(n,a_cursbase) if p_cursbase then - local n_curscurs=n[a_curscurs] + local n_curscurs=getattr(n,a_curscurs) if p_cursbase==n_curscurs then local c=cursives[n_curscurs] if c then @@ -7766,20 +7851,20 @@ function injections.handler(head,where,keep) end end elseif maxt>0 then - local ny=n.yoffset + local ny=getfield(n,"yoffset") for i=maxt,1,-1 do ny=ny+d[i] local ti=t[i] - ti.yoffset=ti.yoffset+ny + setfield(ti,"yoffset",getfield(ti,"yoffset")+ny) end maxt=0 end if not n_cursbase and maxt>0 then - local ny=n.yoffset + local ny=getfield(n,"yoffset") for i=maxt,1,-1 do ny=ny+d[i] local ti=t[i] - ti.yoffset=ny + setfield(ti,"yoffset",ny) end maxt=0 end @@ -7787,11 +7872,11 @@ function injections.handler(head,where,keep) end end if maxt>0 then - local ny=n.yoffset + local ny=getfield(n,"yoffset") for i=maxt,1,-1 do ny=ny+d[i] local ti=t[i] - ti.yoffset=ny + setfield(ti,"yoffset",ny) end maxt=0 end @@ -7802,46 +7887,52 @@ function injections.handler(head,where,keep) if has_marks then for i=1,nofvalid do local p=valid[i] - local p_markbase=p[a_markbase] + local p_markbase=getattr(p,a_markbase) if p_markbase then local mrks=marks[p_markbase] local nofmarks=#mrks - for n in traverse_id(glyph_code,p.next) do - local n_markmark=n[a_markmark] + for n in traverse_id(glyph_code,getnext(p)) do + local n_markmark=getattr(n,a_markmark) if p_markbase==n_markmark then - local index=n[a_markdone] or 1 + local index=getattr(n,a_markdone) or 1 local d=mrks[index] if d then local rlmode=d[3] local k=wx[p] + local px=getfield(p,"xoffset") + local ox=0 if k then local x=k[2] local w=k[4] if w then if rlmode and rlmode>=0 then - n.xoffset=p.xoffset-p.width+d[1]-(w-x) + ox=px-getfield(p,"width")+d[1]-(w-x) else - n.xoffset=p.xoffset-d[1]-x + ox=px-d[1]-x end else if rlmode and rlmode>=0 then - n.xoffset=p.xoffset-p.width+d[1] + ox=px-getfield(p,"width")+d[1] else - n.xoffset=p.xoffset-d[1]-x + ox=px-d[1]-x end end else if rlmode and rlmode>=0 then - n.xoffset=p.xoffset-p.width+d[1] + ox=px-getfield(p,"width")+d[1] else - n.xoffset=p.xoffset-d[1] + ox=px-d[1] end end + setfield(n,"xoffset",ox) + local py=getfield(p,"yoffset") + local oy=0 if mk[p] then - n.yoffset=p.yoffset+d[2] + oy=py+d[2] else - n.yoffset=n.yoffset+p.yoffset+d[2] + oy=getfield(n,"yoffset")+py+d[2] end + setfield(n,"yoffset",oy) if nofmarks==1 then break else @@ -7899,6 +7990,7 @@ function injections.handler(head,where,keep) if not keep then kerns={} end +head=tonode(head) return head,true elseif not keep then kerns,cursives,marks={},{},{} @@ -7908,14 +8000,14 @@ function injections.handler(head,where,keep) trace(head) end for n in traverse_id(glyph_code,head) do - if n.subtype<256 then - local k=n[a_kernpair] + if getsubtype(n)<256 then + local k=getattr(n,a_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 + setfield(n,"yoffset",y) end if w then local wx=w-x @@ -7946,10 +8038,10 @@ function injections.handler(head,where,keep) if not keep then kerns={} end - return head,true + return tonode(head),true else end - return head,false + return tonode(head),false end end -- closure @@ -7977,6 +8069,7 @@ analyzers.useunicodemarks=false local a_state=attributes.private('state') local nodecodes=nodes.nodecodes local glyph_code=nodecodes.glyph +local disc_code=nodecodes.disc local math_code=nodecodes.math local traverse_id=node.traverse_id local traverse_node_list=node.traverse @@ -8043,7 +8136,7 @@ function analyzers.setstate(head,font) first,last,n=nil,nil,0 end elseif id==disc_code then - current[a_state]=s_midi + current[a_state]=s_medi last=current else if first and first==last then @@ -8095,7 +8188,7 @@ local function analyzeprocessor(head,font,attr) end registerotffeature { name="analyze", - description="analysis of (for instance) character classes", + description="analysis of character classes", default=true, initializers={ node=analyzeinitializer, @@ -8358,12 +8451,25 @@ registertracker("otf.positions","otf.marks,otf.kerns,otf.cursive") registertracker("otf.actions","otf.replacements,otf.positions") registertracker("otf.injections","nodes.injections") registertracker("*otf.sample","otf.steps,otf.actions,otf.analyzing") -local 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 flush_node_list=node.flush_list -local end_of_math=node.end_of_math +local nuts=nodes.nuts +local tonode=nuts.tonode +local tonut=nuts.tonut +local getfield=nuts.getfield +local getnext=nuts.getnext +local getprev=nuts.getprev +local getid=nuts.getid +local getattr=nuts.getattr +local getfont=nuts.getfont +local getsubtype=nuts.getsubtype +local getchar=nuts.getchar +local setfield=nuts.setfield +local setattr=nuts.setattr +local insert_node_after=nuts.insert_after +local delete_node=nuts.delete +local copy_node=nuts.copy +local find_node_tail=nuts.tail +local flush_node_list=nuts.flush_list +local end_of_math=nuts.end_of_math local setmetatableindex=table.setmetatableindex local zwnj=0x200C local zwj=0x200D @@ -8472,83 +8578,83 @@ local function pref(kind,lookupname) return formatters["feature %a, lookup %a"](kind,lookupname) end local function copy_glyph(g) - local components=g.components + local components=getfield(g,"components") if components then - g.components=nil + setfield(g,"components",nil) local n=copy_node(g) - g.components=components + setfield(g,"components",components) return n else return copy_node(g) end end local function markstoligature(kind,lookupname,head,start,stop,char) - if start==stop and start.char==char then + if start==stop and getchar(start)==char then return head,start else - local prev=start.prev - local next=stop.next - start.prev=nil - stop.next=nil + local prev=getprev(start) + local next=getnext(stop) + setfield(start,"prev",nil) + setfield(stop,"next",nil) local base=copy_glyph(start) if head==start then head=base end - base.char=char - base.subtype=ligature_code - base.components=start + setfield(base,"char",char) + setfield(base,"subtype",ligature_code) + setfield(base,"components",start) if prev then - prev.next=base + setfield(prev,"next",base) end if next then - next.prev=base + setfield(next,"prev",base) end - base.next=next - base.prev=prev + setfield(base,"next",next) + setfield(base,"prev",prev) return head,base end end local function getcomponentindex(start) - if start.id~=glyph_code then + if getid(start)~=glyph_code then return 0 - elseif start.subtype==ligature_code then + elseif getsubtype(start)==ligature_code then local i=0 - local components=start.components + local components=getfield(start,"components") while components do i=i+getcomponentindex(components) - components=components.next + components=getnext(components) end return i - elseif not marks[start.char] then + elseif not marks[getchar(start)] then return 1 else return 0 end end local function toligature(kind,lookupname,head,start,stop,char,markflag,discfound) - if start==stop and start.char==char then - start.char=char + if start==stop and getchar(start)==char then + setfield(start,"char",char) return head,start end - local prev=start.prev - local next=stop.next - start.prev=nil - stop.next=nil + local prev=getprev(start) + local next=getnext(stop) + setfield(start,"prev",nil) + setfield(stop,"next",nil) local base=copy_glyph(start) if start==head then head=base end - base.char=char - base.subtype=ligature_code - base.components=start + setfield(base,"char",char) + setfield(base,"subtype",ligature_code) + setfield(base,"components",start) if prev then - prev.next=base + setfield(prev,"next",base) end if next then - next.prev=base + setfield(next,"prev",base) end - base.next=next - base.prev=prev + setfield(base,"next",next) + setfield(base,"prev",prev) if not discfound then local deletemarks=markflag~="mark" local components=start @@ -8557,42 +8663,42 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun local head=base local current=base while start do - local char=start.char + local char=getchar(start) if not marks[char] then baseindex=baseindex+componentindex componentindex=getcomponentindex(start) elseif not deletemarks then - start[a_ligacomp]=baseindex+(start[a_ligacomp] or componentindex) + setattr(start,a_ligacomp,baseindex+(getattr(start,a_ligacomp) or componentindex)) if trace_marks then - logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),start[a_ligacomp]) + logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),getattr(start,a_ligacomp)) end head,current=insert_node_after(head,current,copy_node(start)) elseif trace_marks then logwarning("%s: delete mark %s",pref(kind,lookupname),gref(char)) end - start=start.next + start=getnext(start) end - local start=current.next - while start and start.id==glyph_code do - local char=start.char + local start=getnext(current) + while start and getid(start)==glyph_code do + local char=getchar(start) if marks[char] then - start[a_ligacomp]=baseindex+(start[a_ligacomp] or componentindex) + setattr(start,a_ligacomp,baseindex+(getattr(start,a_ligacomp) or componentindex)) if trace_marks then - logwarning("%s: set mark %s, gets index %s",pref(kind,lookupname),gref(char),start[a_ligacomp]) + logwarning("%s: set mark %s, gets index %s",pref(kind,lookupname),gref(char),getattr(start,a_ligacomp)) end else break end - start=start.next + start=getnext(start) end end return head,base end function handlers.gsub_single(head,start,kind,lookupname,replacement) if trace_singles then - logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(start.char),gref(replacement)) + logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(getchar(start)),gref(replacement)) end - start.char=replacement + setfield(start,"char",replacement) return head,start,true end local function get_alternative_glyph(start,alternatives,value,trace_alternatives) @@ -8618,7 +8724,7 @@ local function get_alternative_glyph(start,alternatives,value,trace_alternatives return false,trace_alternatives and formatters["invalid value %a, %s"](value,"out of range") end elseif value==0 then - return start.char,trace_alternatives and formatters["invalid value %a, %s"](value,"no change") + return getchar(start),trace_alternatives and formatters["invalid value %a, %s"](value,"no change") elseif value<1 then return alternatives[1],trace_alternatives and formatters["invalid value %a, taking %a"](value,1) else @@ -8629,25 +8735,25 @@ end local function multiple_glyphs(head,start,multiple) local nofmultiples=#multiple if nofmultiples>0 then - start.char=multiple[1] + setfield(start,"char",multiple[1]) if nofmultiples>1 then - local sn=start.next + local sn=getnext(start) for k=2,nofmultiples do local n=copy_node(start) - n.char=multiple[k] - n.next=sn - n.prev=start + setfield(n,"char",multiple[k]) + setfield(n,"next",sn) + setfield(n,"prev",start) if sn then - sn.prev=n + setfield(sn,"prev",n) end - start.next=n + setfield(start,"next",n) start=n end end return head,start,true else if trace_multiples then - logprocess("no multiple for %s",gref(start.char)) + logprocess("no multiple for %s",gref(getchar(start))) end return head,start,false end @@ -8657,34 +8763,34 @@ function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence local choice,comment=get_alternative_glyph(start,alternative,value,trace_alternatives) if choice then if trace_alternatives then - logprocess("%s: replacing %s by alternative %a to %s, %s",pref(kind,lookupname),gref(start.char),choice,gref(choice),comment) + logprocess("%s: replacing %s by alternative %a to %s, %s",pref(kind,lookupname),gref(getchar(start)),choice,gref(choice),comment) end - start.char=choice + setfield(start,"char",choice) else if trace_alternatives then - logwarning("%s: no variant %a for %s, %s",pref(kind,lookupname),value,gref(start.char),comment) + logwarning("%s: no variant %a for %s, %s",pref(kind,lookupname),value,gref(getchar(start)),comment) end end return head,start,true end function handlers.gsub_multiple(head,start,kind,lookupname,multiple) if trace_multiples then - logprocess("%s: replacing %s by multiple %s",pref(kind,lookupname),gref(start.char),gref(multiple)) + logprocess("%s: replacing %s by multiple %s",pref(kind,lookupname),gref(getchar(start)),gref(multiple)) end return multiple_glyphs(head,start,multiple) end function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence) - local s,stop,discfound=start.next,nil,false - local startchar=start.char + local s,stop,discfound=getnext(start),nil,false + local startchar=getchar(start) if marks[startchar] then while s do - local id=s.id - if id==glyph_code and s.font==currentfont and s.subtype<256 then - local lg=ligature[s.char] + local id=getid(s) + if id==glyph_code and getfont(s)==currentfont and getsubtype(s)<256 then + local lg=ligature[getchar(s)] if lg then stop=s ligature=lg - s=s.next + s=getnext(s) else break end @@ -8696,9 +8802,9 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence) local lig=ligature.ligature if lig then if trace_ligatures then - local stopchar=stop.char + local stopchar=getchar(stop) head,start=markstoligature(kind,lookupname,head,start,stop,lig) - logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) + logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(getchar(start))) else head,start=markstoligature(kind,lookupname,head,start,stop,lig) end @@ -8709,18 +8815,18 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence) else local skipmark=sequence.flags[1] while s do - local id=s.id - if id==glyph_code and s.subtype<256 then - if s.font==currentfont then - local char=s.char + local id=getid(s) + if id==glyph_code and getsubtype(s)<256 then + if getfont(s)==currentfont then + local char=getchar(s) if skipmark and marks[char] then - s=s.next + s=getnext(s) else local lg=ligature[char] if lg then stop=s ligature=lg - s=s.next + s=getnext(s) else break end @@ -8730,7 +8836,7 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence) end elseif id==disc_code then discfound=true - s=s.next + s=getnext(s) else break end @@ -8739,9 +8845,9 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence) local lig=ligature.ligature if lig then if trace_ligatures then - local stopchar=stop.char + local stopchar=getchar(stop) head,start=toligature(kind,lookupname,head,start,stop,lig,skipmark,discfound) - logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) + logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(getchar(start))) else head,start=toligature(kind,lookupname,head,start,stop,lig,skipmark,discfound) end @@ -8753,16 +8859,16 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence) return head,start,false end function handlers.gpos_mark2base(head,start,kind,lookupname,markanchors,sequence) - local markchar=start.char + local markchar=getchar(start) if marks[markchar] then - local base=start.prev - if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then - local basechar=base.char + local base=getprev(start) + if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then + local basechar=getchar(base) if marks[basechar] then while true do - base=base.prev - if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then - basechar=base.char + base=getprev(base) + if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then + basechar=getchar(base) if not marks[basechar] then break end @@ -8811,16 +8917,16 @@ function handlers.gpos_mark2base(head,start,kind,lookupname,markanchors,sequence return head,start,false end function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequence) - local markchar=start.char + local markchar=getchar(start) if marks[markchar] then - local base=start.prev - if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then - local basechar=base.char + local base=getprev(start) + if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then + local basechar=getchar(base) if marks[basechar] then while true do - base=base.prev - if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then - basechar=base.char + base=getprev(base) + if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then + basechar=getchar(base) if not marks[basechar] then break end @@ -8832,7 +8938,7 @@ function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequ end end end - local index=start[a_ligacomp] + local index=getattr(start,a_ligacomp) local baseanchors=descriptions[basechar] if baseanchors then baseanchors=baseanchors.anchors @@ -8877,22 +8983,22 @@ function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequ return head,start,false end function handlers.gpos_mark2mark(head,start,kind,lookupname,markanchors,sequence) - local markchar=start.char + local markchar=getchar(start) if marks[markchar] then - local base=start.prev - local slc=start[a_ligacomp] + local base=getprev(start) + local slc=getattr(start,a_ligacomp) if slc then while base do - local blc=base[a_ligacomp] + local blc=getattr(base,a_ligacomp) if blc and blc~=slc then - base=base.prev + base=getprev(base) else break end end end - if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then - local basechar=base.char + if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then + local basechar=getchar(base) local baseanchors=descriptions[basechar] if baseanchors then baseanchors=baseanchors.anchors @@ -8930,20 +9036,20 @@ function handlers.gpos_mark2mark(head,start,kind,lookupname,markanchors,sequence return head,start,false end function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence) - local alreadydone=cursonce and start[a_cursbase] + local alreadydone=cursonce and getattr(start,a_cursbase) if not alreadydone then local done=false - local startchar=start.char + local startchar=getchar(start) 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_code and nxt.font==currentfont and nxt.subtype<256 do - local nextchar=nxt.char + local nxt=getnext(start) + while not done and nxt and getid(nxt)==glyph_code and getfont(nxt)==currentfont and getsubtype(nxt)<256 do + local nextchar=getchar(nxt) if marks[nextchar] then - nxt=nxt.next + nxt=getnext(nxt) else local entryanchors=descriptions[nextchar] if entryanchors then @@ -8977,13 +9083,13 @@ function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence) return head,start,done else if trace_cursive and trace_details then - logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(start.char),alreadydone) + logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(getchar(start)),alreadydone) end return head,start,false end end function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence) - local startchar=start.char + local startchar=getchar(start) local dx,dy,w,h=setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,characters[startchar]) if trace_kerns then logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),dx,dy,w,h) @@ -8991,19 +9097,19 @@ function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence) return head,start,false end function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence) - local snext=start.next + local snext=getnext(start) if not snext then return head,start,false else local prev,done=start,false local factor=tfmdata.parameters.factor local lookuptype=lookuptypes[lookupname] - while snext and snext.id==glyph_code and snext.font==currentfont and snext.subtype<256 do - local nextchar=snext.char + while snext and getid(snext)==glyph_code and getfont(snext)==currentfont and getsubtype(snext)<256 do + local nextchar=getchar(snext) local krn=kerns[nextchar] if not krn and marks[nextchar] then prev=snext - snext=snext.next + snext=getnext(snext) else local krn=kerns[nextchar] if not krn then @@ -9011,14 +9117,14 @@ function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence) if lookuptype=="pair" then local a,b=krn[2],krn[3] if a and #a>0 then - local startchar=start.char + local startchar=getchar(start) local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar]) if trace_kerns then logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h) end end if b and #b>0 then - local startchar=start.char + local startchar=getchar(start) local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar]) if trace_kerns then logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h) @@ -9031,7 +9137,7 @@ function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence) elseif krn~=0 then local k=setkern(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)) + logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar)) end done=true end @@ -9066,13 +9172,13 @@ function chainmores.chainsub(head,start,stop,kind,chainname,currentcontext,looku return head,start,false end function chainprocs.reversesub(head,start,stop,kind,chainname,currentcontext,lookuphash,replacements) - local char=start.char + local char=getchar(start) local replacement=replacements[char] if replacement then if trace_singles then logprocess("%s: single reverse replacement of %s by %s",cref(kind,chainname),gref(char),gref(replacement)) end - start.char=replacement + setfield(start,"char",replacement) return head,start,true else return head,start,false @@ -9083,9 +9189,9 @@ local function delete_till_stop(start,stop,ignoremarks) if start==stop then elseif ignoremarks then repeat - local next=start.next - if not marks[next.char] then - local components=next.components + local next=getnext(start) + if not marks[getchar(next)] then + local components=getfield(next,"components") if components then flush_node_list(components) end @@ -9095,8 +9201,8 @@ local function delete_till_stop(start,stop,ignoremarks) until next==stop else repeat - local next=start.next - local components=next.components + local next=getnext(start) + local components=getfield(next,"components") if components then flush_node_list(components) end @@ -9113,8 +9219,8 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo logwarning("todo: check if we need to loop over the replacements: %s",concat(subtables," ")) end while current do - if current.id==glyph_code then - local currentchar=current.char + if getid(current)==glyph_code then + local currentchar=getchar(current) local lookupname=subtables[1] local replacement=lookuphash[lookupname] if not replacement then @@ -9131,14 +9237,14 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo 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 + setfield(current,"char",replacement) end end return head,start,true elseif current==stop then break else - current=current.next + current=getnext(current) end end return head,start,false @@ -9146,7 +9252,7 @@ end chainmores.gsub_single=chainprocs.gsub_single function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) delete_till_stop(start,stop) - local startchar=start.char + local startchar=getchar(start) local subtables=currentlookup.subtables local lookupname=subtables[1] local replacements=lookuphash[lookupname] @@ -9175,8 +9281,8 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext local subtables=currentlookup.subtables local value=featurevalue==true and tfmdata.shared.features[kind] or featurevalue while current do - if current.id==glyph_code then - local currentchar=current.char + if getid(current)==glyph_code then + local currentchar=getchar(current) local lookupname=subtables[1] local alternatives=lookuphash[lookupname] if not alternatives then @@ -9191,7 +9297,7 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext if trace_alternatives then logprocess("%s: replacing %s by alternative %a to %s, %s",cref(kind,chainname,chainlookupname,lookupname),gref(char),choice,gref(choice),comment) end - start.char=choice + setfield(start,"char",choice) else if trace_alternatives then logwarning("%s: no variant %a for %s, %s",cref(kind,chainname,chainlookupname,lookupname),value,gref(char),comment) @@ -9205,14 +9311,14 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext elseif current==stop then break else - current=current.next + current=getnext(current) end end return head,start,false end chainmores.gsub_alternate=chainprocs.gsub_alternate function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex) - local startchar=start.char + local startchar=getchar(start) local subtables=currentlookup.subtables local lookupname=subtables[1] local ligatures=lookuphash[lookupname] @@ -9227,20 +9333,20 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext, logwarning("%s: no ligatures starting with %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar)) end else - local s=start.next + local s=getnext(start) local discfound=false local last=stop local nofreplacements=0 local skipmark=currentlookup.flags[1] while s do - local id=s.id + local id=getid(s) if id==disc_code then - s=s.next + s=getnext(s) discfound=true else - local schar=s.char + local schar=getchar(s) if skipmark and marks[schar] then - s=s.next + s=getnext(s) else local lg=ligatures[schar] if lg then @@ -9248,7 +9354,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext, if s==stop then break else - s=s.next + s=getnext(s) end else break @@ -9265,7 +9371,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext, if start==stop then logprocess("%s: replacing character %s by ligature %s case 3",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(l2)) else - logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(stop.char),gref(l2)) + logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(getchar(stop)),gref(l2)) end end head,start=toligature(kind,lookupname,head,start,stop,l2,currentlookup.flags[1],discfound) @@ -9274,7 +9380,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext, 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)) + logwarning("%s: replacing character %s upto %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(getchar(stop))) end end end @@ -9283,7 +9389,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext, end chainmores.gsub_ligature=chainprocs.gsub_ligature function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) - local markchar=start.char + local markchar=getchar(start) if marks[markchar] then local subtables=currentlookup.subtables local lookupname=subtables[1] @@ -9292,14 +9398,14 @@ function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext markanchors=markanchors[markchar] end if markanchors then - local base=start.prev - if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then - local basechar=base.char + local base=getprev(start) + if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then + local basechar=getchar(base) if marks[basechar] then while true do - base=base.prev - if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then - basechar=base.char + base=getprev(base) + if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then + basechar=getchar(base) if not marks[basechar] then break end @@ -9346,7 +9452,7 @@ function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext return head,start,false end function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) - local markchar=start.char + local markchar=getchar(start) if marks[markchar] then local subtables=currentlookup.subtables local lookupname=subtables[1] @@ -9355,14 +9461,14 @@ function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcon markanchors=markanchors[markchar] end if markanchors then - local base=start.prev - if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then - local basechar=base.char + local base=getprev(start) + if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then + local basechar=getchar(base) if marks[basechar] then while true do - base=base.prev - if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then - basechar=base.char + base=getprev(base) + if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then + basechar=getchar(base) if not marks[basechar] then break end @@ -9374,7 +9480,7 @@ function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcon end end end - local index=start[a_ligacomp] + local index=getattr(start,a_ligacomp) local baseanchors=descriptions[basechar].anchors if baseanchors then local baseanchors=baseanchors['baselig'] @@ -9413,7 +9519,7 @@ function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcon return head,start,false end function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) - local markchar=start.char + local markchar=getchar(start) if marks[markchar] then local subtables=currentlookup.subtables local lookupname=subtables[1] @@ -9422,20 +9528,20 @@ function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext markanchors=markanchors[markchar] end if markanchors then - local base=start.prev - local slc=start[a_ligacomp] + local base=getprev(start) + local slc=getattr(start,a_ligacomp) if slc then while base do - local blc=base[a_ligacomp] + local blc=getattr(base,a_ligacomp) if blc and blc~=slc then - base=base.prev + base=getprev(base) else break end end end - if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then - local basechar=base.char + if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then + local basechar=getchar(base) local baseanchors=descriptions[basechar].anchors if baseanchors then baseanchors=baseanchors['basemark'] @@ -9471,9 +9577,9 @@ function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext return head,start,false end function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) - local alreadydone=cursonce and start[a_cursbase] + local alreadydone=cursonce and getattr(start,a_cursbase) if not alreadydone then - local startchar=start.char + local startchar=getchar(start) local subtables=currentlookup.subtables local lookupname=subtables[1] local exitanchors=lookuphash[lookupname] @@ -9487,11 +9593,11 @@ function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,l 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_code and nxt.font==currentfont and nxt.subtype<256 do - local nextchar=nxt.char + local nxt=getnext(start) + while not done and nxt and getid(nxt)==glyph_code and getfont(nxt)==currentfont and getsubtype(nxt)<256 do + local nextchar=getchar(nxt) if marks[nextchar] then - nxt=nxt.next + nxt=getnext(nxt) else local entryanchors=descriptions[nextchar] if entryanchors then @@ -9525,7 +9631,7 @@ function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,l return head,start,done else if trace_cursive and trace_details then - logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(start.char),alreadydone) + logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(getchar(start)),alreadydone) end return head,start,false end @@ -9533,7 +9639,7 @@ function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,l return head,start,false end function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence) - local startchar=start.char + local startchar=getchar(start) local subtables=currentlookup.subtables local lookupname=subtables[1] local kerns=lookuphash[lookupname] @@ -9549,9 +9655,9 @@ function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lo return head,start,false end function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence) - local snext=start.next + local snext=getnext(start) if snext then - local startchar=start.char + local startchar=getchar(start) local subtables=currentlookup.subtables local lookupname=subtables[1] local kerns=lookuphash[lookupname] @@ -9561,26 +9667,26 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look local lookuptype=lookuptypes[lookupname] local prev,done=start,false local factor=tfmdata.parameters.factor - while snext and snext.id==glyph_code and snext.font==currentfont and snext.subtype<256 do - local nextchar=snext.char + while snext and getid(snext)==glyph_code and getfont(snext)==currentfont and getsubtype(snext)<256 do + local nextchar=getchar(snext) local krn=kerns[nextchar] if not krn and marks[nextchar] then prev=snext - snext=snext.next + snext=getnext(snext) else if not krn then elseif type(krn)=="table" then if lookuptype=="pair" then local a,b=krn[2],krn[3] if a and #a>0 then - local startchar=start.char + local startchar=getchar(start) local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar]) if trace_kerns then logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",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 startchar=getchar(start) local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar]) if trace_kerns then logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h) @@ -9592,7 +9698,7 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look if a and a~=0 then local k=setkern(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)) + logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar)) end end if b and b~=0 then @@ -9603,7 +9709,7 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look elseif krn~=0 then local k=setkern(snext,factor,rlmode,krn) if trace_kerns then - logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(prev.char),gref(nextchar)) + logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar)) end done=true end @@ -9640,7 +9746,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq local seq=ck[3] local s=#seq if s==1 then - match=current.id==glyph_code and current.font==currentfont and current.subtype<256 and seq[1][current.char] + match=getid(current)==glyph_code and getfont(current)==currentfont and getsubtype(current)<256 and seq[1][getchar(current)] else local f,l=ck[4],ck[5] if f==1 and f==l then @@ -9648,13 +9754,13 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq if f==l then else local n=f+1 - last=last.next + last=getnext(last) while n<=l do if last then - local id=last.id + local id=getid(last) if id==glyph_code then - if last.font==currentfont and last.subtype<256 then - local char=last.char + if getfont(last)==currentfont and getsubtype(last)<256 then + local char=getchar(last) local ccd=descriptions[char] if ccd then local class=ccd.class @@ -9663,10 +9769,10 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq if trace_skips then show_skip(kind,chainname,char,ck,class) end - last=last.next + last=getnext(last) elseif seq[n][char] then if n<l then - last=last.next + last=getnext(last) end n=n+1 else @@ -9682,7 +9788,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq break end elseif id==disc_code then - last=last.next + last=getnext(last) else match=false break @@ -9695,15 +9801,15 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq end end if match and f>1 then - local prev=start.prev + local prev=getprev(start) if prev then local n=f-1 while n>=1 do if prev then - local id=prev.id + local id=getid(prev) if id==glyph_code then - if prev.font==currentfont and prev.subtype<256 then - local char=prev.char + if getfont(prev)==currentfont and getsubtype(prev)<256 then + local char=getchar(prev) local ccd=descriptions[char] if ccd then local class=ccd.class @@ -9733,7 +9839,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq match=false break end - prev=prev.prev + prev=getprev(prev) elseif seq[n][32] then n=n -1 else @@ -9753,15 +9859,15 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq end end if match and s>l then - local current=last and last.next + local current=last and getnext(last) if current then local n=l+1 while n<=s do if current then - local id=current.id + local id=getid(current) if id==glyph_code then - if current.font==currentfont and current.subtype<256 then - local char=current.char + if getfont(current)==currentfont and getsubtype(current)<256 then + local char=getchar(current) local ccd=descriptions[char] if ccd then local class=ccd.class @@ -9791,7 +9897,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq match=false break end - current=current.next + current=getnext(current) elseif seq[n][32] then n=n+1 else @@ -9814,7 +9920,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq if match then if trace_contexts then local rule,lookuptype,f,l=ck[1],ck[2],ck[4],ck[5] - local char=start.char + local char=getchar(start) if ck[9] then logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a, %a => %a", cref(kind,chainname),rule,gref(char),f-1,l-f+1,s-l,lookuptype,ck[9],ck[10]) @@ -9844,12 +9950,12 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq repeat if skipped then while true do - local char=start.char + local char=getchar(start) 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 + start=getnext(start) else break end @@ -9874,7 +9980,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq i=i+1 end if start then - start=start.next + start=getnext(start) else end until i>nofchainlookups @@ -10001,6 +10107,7 @@ local function featuresprocessor(head,font,attr) if not lookuphash then return head,false end + head=tonut(head) if trace_steps then checkstep(head) end @@ -10033,10 +10140,10 @@ local function featuresprocessor(head,font,attr) local handler=handlers[typ] local start=find_node_tail(head) while start do - local id=start.id + local id=getid(start) if id==glyph_code then - if start.font==font and start.subtype<256 then - local a=start[0] + if getfont(start)==font and getsubtype(start)<256 then + local a=getattr(start,0) if a then a=a==attr else @@ -10047,7 +10154,7 @@ local function featuresprocessor(head,font,attr) local lookupname=subtables[i] local lookupcache=lookuphash[lookupname] if lookupcache then - local lookupmatch=lookupcache[start.char] + local lookupmatch=lookupcache[getchar(start)] if lookupmatch then head,start,success=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) if success then @@ -10058,15 +10165,15 @@ local function featuresprocessor(head,font,attr) report_missing_cache(typ,lookupname) end end - if start then start=start.prev end + if start then start=getprev(start) end else - start=start.prev + start=getprev(start) end else - start=start.prev + start=getprev(start) end else - start=start.prev + start=getprev(start) end end else @@ -10081,17 +10188,17 @@ local function featuresprocessor(head,font,attr) report_missing_cache(typ,lookupname) else while start do - local id=start.id + local id=getid(start) if id==glyph_code then - if start.font==font and start.subtype<256 then - local a=start[0] + if getfont(start)==font and getsubtype(start)<256 then + local a=getattr(start,0) if a then - a=(a==attr) and (not attribute or start[a_state]==attribute) + a=(a==attr) and (not attribute or getattr(start,a_state)==attribute) else - a=not attribute or start[a_state]==attribute + a=not attribute or getattr(start,a_state)==attribute end if a then - local lookupmatch=lookupcache[start.char] + local lookupmatch=lookupcache[getchar(start)] if lookupmatch then local ok head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1) @@ -10099,17 +10206,17 @@ local function featuresprocessor(head,font,attr) success=true end end - if start then start=start.next end + if start then start=getnext(start) end else - start=start.next + start=getnext(start) end else - start=start.next + start=getnext(start) end elseif id==whatsit_code then - local subtype=start.subtype + local subtype=getsubtype(start) if subtype==dir_code then - local dir=start.dir + local dir=getfield(start,"dir") if dir=="+TRT" or dir=="+TLT" then topstack=topstack+1 dirstack[topstack]=dir @@ -10128,7 +10235,7 @@ local function featuresprocessor(head,font,attr) report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir) end elseif subtype==localpar_code then - local dir=start.dir + local dir=getfield(start,"dir") if dir=="TRT" then rlparmode=-1 elseif dir=="TLT" then @@ -10141,31 +10248,31 @@ local function featuresprocessor(head,font,attr) report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode) end end - start=start.next + start=getnext(start) elseif id==math_code then - start=end_of_math(start).next + start=getnext(end_of_math(start)) else - start=start.next + start=getnext(start) end end end else while start do - local id=start.id + local id=getid(start) if id==glyph_code then - if start.font==font and start.subtype<256 then - local a=start[0] + if getfont(start)==font and getsubtype(start)<256 then + local a=getattr(start,0) if a then - a=(a==attr) and (not attribute or start[a_state]==attribute) + a=(a==attr) and (not attribute or getattr(start,a_state)==attribute) else - a=not attribute or start[a_state]==attribute + a=not attribute or getattr(start,a_state)==attribute end if a then for i=1,ns do local lookupname=subtables[i] local lookupcache=lookuphash[lookupname] if lookupcache then - local lookupmatch=lookupcache[start.char] + local lookupmatch=lookupcache[getchar(start)] if lookupmatch then local ok head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) @@ -10180,17 +10287,17 @@ local function featuresprocessor(head,font,attr) report_missing_cache(typ,lookupname) end end - if start then start=start.next end + if start then start=getnext(start) end else - start=start.next + start=getnext(start) end else - start=start.next + start=getnext(start) end elseif id==whatsit_code then - local subtype=start.subtype + local subtype=getsubtype(start) if subtype==dir_code then - local dir=start.dir + local dir=getfield(start,"dir") if dir=="+TRT" or dir=="+TLT" then topstack=topstack+1 dirstack[topstack]=dir @@ -10209,7 +10316,7 @@ local function featuresprocessor(head,font,attr) report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir) end elseif subtype==localpar_code then - local dir=start.dir + local dir=getfield(start,"dir") if dir=="TRT" then rlparmode=-1 elseif dir=="TLT" then @@ -10222,11 +10329,11 @@ local function featuresprocessor(head,font,attr) report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode) end end - start=start.next + start=getnext(start) elseif id==math_code then - start=end_of_math(start).next + start=getnext(end_of_math(start)) else - start=start.next + start=getnext(start) end end end @@ -10238,6 +10345,7 @@ local function featuresprocessor(head,font,attr) registerstep(head) end end + head=tonode(head) return head,done end local function generic(lookupdata,lookupname,unicode,lookuphash) diff --git a/luaotfload-override.lua b/luaotfload-override.lua index f647826..19cd505 100644 --- a/luaotfload-override.lua +++ b/luaotfload-override.lua @@ -134,9 +134,9 @@ local set_logout = function (s, finalizers) texiowrite_nl = texio.write_nl writeln = writeln_orig end - return finalizers --else --- remains “log” end + return finalizers end logs.set_logout = set_logout diff --git a/luaotfload-tool.lua b/luaotfload-tool.lua index 4afd9d1..801ae72 100755 --- a/luaotfload-tool.lua +++ b/luaotfload-tool.lua @@ -4,7 +4,7 @@ -- DESCRIPTION: database functionality -- REQUIREMENTS: luaotfload 2.2 -- AUTHOR: Khaled Hosny, Élie Roux, Philipp Gesang --- VERSION: 2.3a +-- VERSION: 2.3b -- LICENSE: GPL v2 -- MODIFIED: 2013-06-02 19:23:54+0200 ----------------------------------------------------------------------- @@ -161,8 +161,12 @@ require"luaotfload-override.lua" --- this populates the logs.* namespace require"luaotfload-database" require"alt_getopt" -local version = "2.3" -- same version number as luaotfload -local names = fonts.names +local names = fonts.names + +local status_file = "luaotfload-status" +local status = require (status_file) + +local version = "2.3b" local sanitize_string = names.sanitize_string @@ -190,11 +194,11 @@ This tool is part of the luaotfload package. Valid options are: -V --version print version and exit -h --help print this message - --diagnose=CHECK run a self test procedure; one of “files”, - “permissions”, or “repository” + --diagnose=CHECK run a self test procedure; one of "files", + "permissions", or "repository" - --alias=<name> force behavior of “luaotfload-tool” or legacy - “mkluatexfontdb” + --alias=<name> force behavior of "luaotfload-tool" or legacy + "mkluatexfontdb" ------------------------------------------------------------------------------- DATABASE @@ -228,7 +232,7 @@ The font database will be saved to FONT CACHE --cache=<directive> operate on font cache, where <directive> is - “show”, “purge”, or “erase” + "show", "purge", or "erase" The font cache will be written to %s @@ -248,8 +252,8 @@ Valid options: -vvv print all steps of directory searching -V --version print version and exit -h --help print this message - --alias=<name> force behavior of “luaotfload-tool” or legacy - “mkluatexfontdb” + --alias=<name> force behavior of "luaotfload-tool" or legacy + "mkluatexfontdb" The font database will be saved to %s @@ -280,11 +284,13 @@ end local version_msg = function ( ) texiowrite_nl(stringformat( - "%s version “%s”\n" .. -- no \z due to 5.1 compatibility - "database version “%s”\n" .. - "Lua interpreter: %s; version “%s”\n", + "%s version %q\n" .. -- no \z due to 5.1 compatibility + "revision %q\n" .. + "database version %q\n" .. + "Lua interpreter: %s; version %q\n", config.luaotfload.self, version, + status.notes.revision, names.version, runtime[1], runtime[2])) @@ -776,21 +782,21 @@ actions.query = function (job) if success then logs.names_report(false, 0, - "resolve", "Font “%s” found!", query) + "resolve", "Font %q found!", query) if subfont then logs.names_report(false, 0, "resolve", - "Resolved file name “%s”, subfont nr. “%s”", + "Resolved file name %q, subfont nr. %q", foundname, subfont) else logs.names_report(false, 0, "resolve", - "Resolved file name “%s”", foundname) + "Resolved file name %q", foundname) end if job.show_info then show_font_info(foundname, query, job.full_info, job.warnings) end else logs.names_report(false, 0, - "resolve", "Cannot find “%s”.", query) + "resolve", "Cannot find %q.", query) if job.fuzzy == true then logs.names_report(false, 0, "resolve", "Looking for close matches, this may take a while ...") @@ -953,10 +959,10 @@ do logs.names_report (false, 0, "diagnose", ...) end - local verify_files = function (errcnt, info) + local verify_files = function (errcnt, status) out "================ verify files =================" - local hashes = info.hashes - local notes = info.notes + local hashes = status.hashes + local notes = status.notes if not hashes or #hashes == 0 then out ("FAILED: cannot read checksums from %s.", status_file) return 1/0 @@ -1022,8 +1028,16 @@ do return lpegmatch (p_permissions, raw) end + local trailingslashes = P"/"^1 * P(-1) + local stripslashes = C((1 - trailingslashes)^0) + local get_permissions = function (t, location) + if stringsub (location, #location) == "/" then + --- strip trailing slashes (lfs idiosyncrasy on Win) + location = lpegmatch (stripslashes, location) + end local attributes = lfsattributes (location) + if not attributes and t == "f" then attributes = get_tentative_attributes (location) if not attributes then @@ -1129,8 +1143,8 @@ do if kpsefind_file ("https.lua", "lua") == nil then check_upstream = function (errcnt) out [[============= upstream repository ============= - Github API access requires the luasec library. WARNING: Cannot retrieve repository data. + Github API access requires the luasec library. Grab it from <https://github.com/brunoos/luasec> and retry.]] return errcnt @@ -1295,7 +1309,7 @@ do release_url) return true else - out "There weren’t any new releases in the meantime." + out "There weren't any new releases in the meantime." out "Luaotfload is up to date." end return false @@ -1321,7 +1335,6 @@ do --- github api stuff end local anamneses = { "files", "repository", "permissions" } - local status_file = "luaotfload-status" actions.diagnose = function (job) local errcnt = 0 @@ -1333,21 +1346,23 @@ do asked = tabletohash (asked, true) end - out "Loading file hashes." - local info = require (status_file) - if asked.files == true then - errcnt = verify_files (errcnt, info) + errcnt = verify_files (errcnt, status) + asked.files = nil end if asked.permissions == true then errcnt = check_permissions (errcnt) + asked.permissions = nil end if asked.repository == true then - --errcnt = check_upstream (info.notes.revision) - check_upstream (info.notes.revision) + check_upstream (status.notes.revision) + asked.repository = nil end - + local rest = next (asked) + if rest ~= nil then --> something unknown + out ("Unknown diagnostic %q.", rest) + end if errcnt == 0 then --> success out ("Everything appears to be in order, \z you may sleep well.") @@ -1524,7 +1539,7 @@ local process_cmdline = function ( ) -- unit -> jobspec result.help_version = "mkluatexfontdb" action_pending["generate"] = true result.log_level = math.max(1, result.log_level) - logs.set_logout"stdout" + logs.set_logout("stdout", finalizers) elseif nopts == 0 then action_pending["help"] = true result.help_version = "short" diff --git a/luaotfload-typo-krn.lua b/luaotfload-typo-krn.lua index fb28d3b..fb39404 100644 --- a/luaotfload-typo-krn.lua +++ b/luaotfload-typo-krn.lua @@ -20,7 +20,7 @@ local insert_node_before = node.insert_before local insert_node_after = node.insert_after local end_of_math = node.end_of_math -local texattribute = tex.attribute +local texsetattribute = tex.setattribute local unsetvalue = attributes.unsetvalue local nodepool = nodes.pool @@ -316,7 +316,7 @@ function kerns.set(factor) else factor = unsetvalue end - texattribute[a_kerns] = factor + texsetattribute(a_kerns,factor) return factor end diff --git a/luaotfload.dtx b/luaotfload.dtx index d647efb..3892bd8 100644 --- a/luaotfload.dtx +++ b/luaotfload.dtx @@ -40,7 +40,7 @@ \input docstrip.tex \Msg{************************************************************************} \Msg{* Installation} -\Msg{* Package: luaotfload v2.3a OpenType layout system} +\Msg{* Package: luaotfload v2.3b OpenType layout system} \Msg{************************************************************************} \keepsilent @@ -111,7 +111,7 @@ and the derived files %<*driver> \NeedsTeXFormat{LaTeX2e} \ProvidesFile{luaotfload.drv}% - [2013/07/10 v2.3a OpenType layout system]% + [2013/07/23 v2.3b OpenType layout system]% \documentclass{ltxdoc} \usepackage{metalogo,multicol,mdwlist,fancyvrb,xspace} \usepackage[x11names]{xcolor} @@ -231,7 +231,7 @@ and the derived files % \GetFileInfo{luaotfload.drv} % % \title{The \identifier{luaotfload} package} -% \date{2013/07/10 v2.3a} +% \date{2013/07/23 v2.3b} % \author{Elie Roux · Khaled Hosny · Philipp Gesang\\ % Home: \url{https://github.com/lualatex/luaotfload}\\ % Support: \email{lualatex-dev@tug.org}} @@ -1478,8 +1478,8 @@ config.luaotfload.index_file = config.luaotfload.index_file or "luaot luaotfload.module = { name = "luaotfload", - version = 2.3001, - date = "2013/07/10", + version = 2.3002, + date = "2013/07/23", description = "OpenType layout system.", author = "Elie Roux & Hans Hagen", copyright = "Elie Roux", @@ -1712,14 +1712,13 @@ loadmodule"merged.lua" if fonts then if not fonts._merge_loaded_message_done_ then - --- a program talking first person -- HH sure believes in strong AI ... - log[[“I am using the merged version of 'luaotfload.lua' here. If]] - log[[ you run into problems or experience unexpected behaviour,]] - log[[ and if you have ConTeXt installed you can try to delete the]] - log[[ file 'luaotfload-font-merged.lua' as I might then use the]] - log[[ possibly updated libraries. The merged version is not]] - log[[ supported as it is a frozen instance. Problems can be]] - log[[ reported to the ConTeXt mailing list.”]] + log [["I am using the merged version of 'luaotfload.lua' here.]] + log [[ If you run into problems or experience unexpected]] + log [[ behaviour, and if you have ConTeXt installed you can try]] + log [[ to delete the file 'luaotfload-merged.lua' as I might]] + log [[ then use the possibly updated libraries. The merged]] + log [[ version is not supported as it is a frozen instance.]] + log [[ Problems can be reported to the ConTeXt mailing list."]] end fonts._merge_loaded_message_done_ = true @@ -1911,7 +1910,7 @@ request_resolvers.anon = function (specification) local exists, _ = lfsisfile(name) if exists then --- garbage; we do this because we are nice, --- not because it is correct - logs.names_report("log", 1, "load", "file “%s” exists", name) + logs.names_report("log", 1, "load", "file %q exists", name) logs.names_report("log", 1, "load", "... overriding borked anon: lookup with path: lookup") specification.name = name @@ -1935,7 +1934,7 @@ request_resolvers.path = function (specification) local exists, _ = lfsisfile(name) if not exists then -- resort to file: lookup logs.names_report("log", 1, "load", - "path lookup of “%s” unsuccessful, falling back to file:", + "path lookup of %q unsuccessful, falling back to file:", name) request_resolvers.file(specification) else @@ -2044,6 +2043,8 @@ loadmodule"features.lua" --- contains what was “font-ltx” and “font-otc loadmodule"extralibs.lua" --- load additional Context libraries loadmodule"auxiliary.lua" --- additionaly high-level functionality (new) +luaotfload.aux.start_rewrite_fontname () --- to be migrated to fontspec + -- vim:tw=71:sw=4:ts=4:expandtab % \end{macrocode} @@ -2069,7 +2070,7 @@ loadmodule"auxiliary.lua" --- additionaly high-level functionality (new) \else \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{luaotfload}% - [2013/07/10 v2.3a OpenType layout system] + [2013/07/23 v2.3b OpenType layout system] \RequirePackage{luatexbase} \fi \ifnum\luatexversion<76 @@ -0,0 +1,134 @@ +#!/usr/bin/env texlua +----------------------------------------------------------------------- +-- FILE: mktests +-- USAGE: ./mktests +-- DESCRIPTION: test the behavior of Luaotfload +-- REQUIREMENTS: Luatex > 0.76, Luaotfload +-- AUTHOR: Philipp Gesang (Phg), <phg42.2a@gmail.com> +-- VERSION: 2.3 +-- CREATED: 2013-07-11 11:32:24+0200 +----------------------------------------------------------------------- +-- +--===================================================================-- +-- NOTE +-- this is a stub, to be completed long-term +-- suggestions welcome +--===================================================================-- + + +local tests = { } + +config = { luaotfload = { + names_dir = "names", + cache_dir = "fonts", + index_file = "luaotfload-names.lua", + resolver = "normal", + update_live = true, --- suppress db updates +}} + +kpse.set_program_name "luatex" + +require "lualibs" +require "luaotfload-basics-gen.lua" +require "luaotfload-override.lua" +require "luaotfload-database" + +local names = fonts.names + +----------------------------------------------------------------------- +--- helper functions +----------------------------------------------------------------------- + +local pprint_resolve = function (input, output, result) + texio.write_nl (string.format ("[%s] “%s” -> “%s”", + result == true and "passed" or "failed", + input, + output)) +end + +local pprint_result = function (name, failed, total) + if failed == 0 then + texio.write_nl (string.format ("[%s] all %d passed", name, total)) + else + texio.write_nl (string.format ("[%s] %d of %d failed", + name, + failed, + total)) + end +end + +----------------------------------------------------------------------- +--- font tests +----------------------------------------------------------------------- + +--- test sets + +local infer_regular_style = { + --- inferring which one is the correct style for “regular”; can be + --- obscured by synonyms like “book” etc. + { "Iwona", "Iwona-Regular.otf" }, -- trivial case + { "DejaVu Serif", "DejaVuSerif.ttf" }, + { "Adobe Garamond Pro", "agaramondpro_regular.otf" }, + { "Garamond Premier Pro", "GaramondPremrPro-Capt.otf" }, +} + +local font_name_tests = { + infer_regular_style, +} + +local resolve_font_name = function () + local failed, total = 0, 0 + local resolve_name = names.resolve + for nset = 1, #font_name_tests do + local set = font_name_tests[nset] + for ntest = 1, #set do + local test = set[ntest] + local input, output = test[1], test[2] + local input_spec = { + name = input, + lookup = "name", + specification = "name:" .. input, + optsize = 0, + } + local result = resolve_name (nil, nil, input_spec) == output + total = total + 1 + if not result then + failed = failed + 1 + end + pprint_resolve (input, output, result) + end + end + return failed, total +end + +tests ["resolve_font_name"] = resolve_font_name + +----------------------------------------------------------------------- +--- runner +----------------------------------------------------------------------- + +local main = function () + local failed, total = 0, 0 + for name, test in next, tests do + texio.write_nl ("[" .. name .. "]") + local newfailed, newtotal = test () + total = total + 1 + pprint_result (name, newfailed, newtotal) + failed = failed + newfailed + total = total + newtotal + end + + if failed == 0 then + texio.write_nl (string.format ("[report] all %d tests passed.", total)) + else + texio.write_nl (string.format ("[report] %d of %d tests failed (%d %%).", + failed, + total, + failed / total * 100)) + end + texio.write_nl "" + os.exit (0) +end + +return main () + |