diff options
author | Philipp Gesang <phg42.2a@gmail.com> | 2014-02-12 07:50:06 +0100 |
---|---|---|
committer | Philipp Gesang <phg42.2a@gmail.com> | 2014-02-12 07:50:06 +0100 |
commit | 9138da7d4a53d65bc15f3a5dc73fd373db40bdf7 (patch) | |
tree | 702093c750d81aa2e8810f484627b51d6b485c27 /luaotfload-auxiliary.lua | |
parent | ffa5a347f68805e218c61c344c0b8a895c4bb8db (diff) | |
download | luaotfload-9138da7d4a53d65bc15f3a5dc73fd373db40bdf7.tar.gz |
[*] move source files to ./src
Diffstat (limited to 'luaotfload-auxiliary.lua')
-rw-r--r-- | luaotfload-auxiliary.lua | 783 |
1 files changed, 0 insertions, 783 deletions
diff --git a/luaotfload-auxiliary.lua b/luaotfload-auxiliary.lua deleted file mode 100644 index 716af98..0000000 --- a/luaotfload-auxiliary.lua +++ /dev/null @@ -1,783 +0,0 @@ -#!/usr/bin/env texlua ------------------------------------------------------------------------ --- FILE: luaotfload-auxiliary.lua --- DESCRIPTION: part of luaotfload --- REQUIREMENTS: luaotfload 2.5 --- AUTHOR: Khaled Hosny, Élie Roux, Philipp Gesang --- VERSION: 2.5 --- MODIFIED: 2014-01-02 21:24:25+0100 ------------------------------------------------------------------------ --- - ---- this file addresses issue #24 ---- https://github.com/lualatex/luaotfload/issues/24# - -luaotfload = luaotfload or {} -luaotfload.aux = luaotfload.aux or { } - -local aux = luaotfload.aux -local log = luaotfload.log -local report = log.report -local fonthashes = fonts.hashes -local identifiers = fonthashes.identifiers - -local fontid = font.id -local texsprint = tex.sprint - -local dofile = dofile -local getmetatable = getmetatable -local setmetatable = setmetatable -local utf8 = unicode.utf8 -local stringlower = string.lower -local stringformat = string.format -local stringgsub = string.gsub -local stringbyte = string.byte -local stringfind = string.find -local tablecopy = table.copy - ------------------------------------------------------------------------ ---- font patches ------------------------------------------------------------------------ - ---- https://github.com/khaledhosny/luaotfload/issues/54 - -local rewrite_fontname = function (tfmdata, specification) - tfmdata.name = [["]] .. specification .. [["]] -end - -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 - 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 - report ("log", 0, "aux", - "stop rewriting tfmdata.name field") - end -end - -aux.stop_rewrite_fontname = stop_rewrite_fontname - - ---[[doc-- -This sets two dimensions apparently relied upon by the unicode-math -package. ---doc]]-- - -local set_sscale_dimens = function (fontdata) - local mathconstants = fontdata.MathConstants - local parameters = fontdata.parameters - if mathconstants then - parameters[10] = mathconstants.ScriptPercentScaleDown or 70 - parameters[11] = mathconstants.ScriptScriptPercentScaleDown or 50 - end - return fontdata -end - -luatexbase.add_to_callback( - "luaotfload.patch_font", - set_sscale_dimens, - "luaotfload.aux.set_sscale_dimens") - ---- fontobj -> int -local lookup_units = function (fontdata) - local metadata = fontdata.shared and fontdata.shared.rawdata.metadata - if metadata and metadata.units_per_em then - return metadata.units_per_em - elseif fontdata.parameters and fontdata.parameters.units then - return fontdata.parameters.units - elseif fontdata.units then --- v1.x - return fontdata.units - end - return 1000 -end - ---[[doc-- -This callback corrects some values of the Cambria font. ---doc]]-- ---- fontobj -> unit -local patch_cambria_domh = function (fontdata) - local mathconstants = fontdata.MathConstants - if mathconstants and fontdata.psname == "CambriaMath" then - --- my test Cambria has 2048 - local units_per_em = fontdata.units_per_em or lookup_units(fontdata) - local sz = fontdata.parameters.size or fontdata.size - local mh = 2800 / units_per_em * sz - if mathconstants.DisplayOperatorMinHeight < mh then - mathconstants.DisplayOperatorMinHeight = mh - end - end -end - -luatexbase.add_to_callback( - "luaotfload.patch_font", - patch_cambria_domh, - "luaotfload.aux.patch_cambria_domh") - ---[[doc-- - -Comment from fontspec: - - “Here we patch fonts tfm table to emulate \XeTeX's \cs{fontdimen8}, - which stores the caps-height of the font. (Cf.\ \cs{fontdimen5} which - stores the x-height.) - - Falls back to measuring the glyph if the font doesn't contain the - necessary information. - This needs to be extended for fonts that don't contain an `X'.” - ---doc]]-- - -local set_capheight = function (fontdata) - local shared = fontdata.shared - local parameters = fontdata.parameters - local capheight - if shared and shared.rawdata.metadata.pfminfo then - local units_per_em = parameters.units - local size = parameters.size - local os2_capheight = shared.rawdata.metadata.pfminfo.os2_capheight - - if os2_capheight > 0 then - capheight = os2_capheight / units_per_em * size - else - local X8 = stringbyte"X" - if fontdata.characters[X8] then - capheight = fontdata.characters[X8].height - else - capheight = parameters.ascender / units_per_em * size - end - end - else - local X8 = stringbyte"X" - if fontdata.characters[X8] then - capheight = fontdata.characters[X8].height - end - end - if capheight then - --- is this legit? afaics there’s nothing else on the - --- array part of that table - fontdata.parameters[8] = capheight - end -end - -luatexbase.add_to_callback( - "luaotfload.patch_font", - set_capheight, - "luaotfload.aux.set_capheight") - ------------------------------------------------------------------------ ---- glyphs and characters ------------------------------------------------------------------------ - -local agl = fonts.encodings.agl - ---- int -> int -> bool -local font_has_glyph = function (font_id, codepoint) - local fontdata = fonts.hashes.identifiers[font_id] - if fontdata then - if fontdata.characters[codepoint] ~= nil then return true end - end - return false -end - -aux.font_has_glyph = font_has_glyph - ---- undocumented - -local raw_slot_of_name = function (font_id, glyphname) - local fontdata = font.fonts[font_id] - if fontdata.type == "virtual" then --- get base font for glyph idx - local codepoint = agl.unicodes[glyphname] - local glyph = fontdata.characters[codepoint] - if fontdata.characters[codepoint] then - return codepoint - end - end - return false -end - ---[[doc-- - - This one is approximately “name_to_slot” from the microtype package; - note that it is all about Adobe Glyph names and glyph slots in the - font. The names and values may diverge from actual Unicode. - - http://www.adobe.com/devnet/opentype/archives/glyph.html - - The “unsafe” switch triggers a fallback lookup in the raw fonts - table. As some of the information is stored as references, this may - have unpredictable side-effects. - ---doc]]-- - ---- int -> string -> bool -> (int | false) -local slot_of_name = function (font_id, glyphname, unsafe) - local fontdata = identifiers[font_id] - if fontdata then - local unicode = fontdata.resources.unicodes[glyphname] - if unicode then - if type(unicode) == "number" then - return unicode - else - return unicode[1] --- for multiple components - end --- else --- --- missing - end - elseif unsafe == true then -- for Robert - return raw_slot_of_name(font_id, glyphname) - end - return false -end - -aux.slot_of_name = slot_of_name - ---[[doc-- - - Inverse of above; not authoritative as to my knowledge the official - inverse of the AGL is the AGLFN. Maybe this whole issue should be - dealt with in a separate package that loads char-def.lua and thereby - solves the problem for the next couple decades. - - http://partners.adobe.com/public/developer/en/opentype/aglfn13.txt - ---doc]]-- - -local indices - ---- int -> (string | false) -local name_of_slot = function (codepoint) - if not indices then --- this will load the glyph list - local unicodes = agl.unicodes - indices = table.swapped(unicodes) - end - local glyphname = indices[codepoint] - if glyphname then - return glyphname - end - return false -end - -aux.name_of_slot = name_of_slot - ---[[doc-- - - In Context, characters.data is where the data from char-def.lua - resides. The file is huge (>3.7 MB as of 2013) and not part of the - isolated font loader. Nevertheless, we include a partial version - generated by the mkcharacters script that contains only the - a subset of the fields of each character defined. - - Currently, these are (compare the mkcharacters script!) - - · "direction" - · "mirror" - · "category" - · "textclass" - - The directional information is required for packages like Simurgh [0] - to work correctly. In an early stage [1] it was necessary to load - further files from Context directly, including the full blown version - of char-def. Since we have no use for most of the so imported - functionality, the required parts have been isolated and are now - instated along with luaotfload-characters.lua. We can extend the set - of imported features easily should it not be enough. - - [0] https://github.com/persian-tex/simurgh - [1] http://tex.stackexchange.com/a/132301/14066 - ---doc]]-- - -characters = characters or { } --- should be created in basics-gen -characters.data = nil -local chardef = "luaotfload-characters" - -do - local setmetatableindex = function (t, f) - local mt = getmetatable (t) - if mt then - mt.__index = f - else - setmetatable (t, { __index = f }) - end - end - - --- there are some special tables for each field that provide access - --- to fields of the character table by means of a metatable - - local mkcharspecial = function (characters, tablename, field) - - local chardata = characters.data - - if chardata then - local newspecial = { } - characters [tablename] = newspecial --> e.g. “characters.data.mirrors” - - local idx = function (t, char) - local c = chardata [char] - if c then - local m = c [field] --> e.g. “mirror” - if m then - t [char] = m - return m - end - end - newspecial [char] = false - return char - end - - setmetatableindex (newspecial, idx) - end - - end - - local mkcategories = function (characters) -- different from the others - - local chardata = characters.data - - setmetatable (characters, { __index = function (t, char) - if char then - local c = chardata [char] - c = c.category or char - t [char] = c - return c - end - end}) - - end - - local load_failed = false - local chardata --> characters.data; loaded on demand - - local load_chardef = function () - - report ("both", 1, "aux", "Loading character metadata from %s.", chardef) - chardata = dofile (kpse.find_file (chardef, "lua")) - - if chardata == nil then - warning ("Could not load %s; continuing \z - with empty character table.", - chardef) - chardata = { } - load_failed = true - end - - characters = { } --- nuke metatable - characters.data = chardata - - --- institute some of the functionality from char-ini.lua - - mkcharspecial (characters, "mirrors", "mirror") - mkcharspecial (characters, "directions", "direction") - mkcharspecial (characters, "textclasses", "textclass") - mkcategories (characters) - - end - - local charindex = function (t, k) - if chardata == nil and load_failed ~= true then - load_chardef () - end - - return characters [k] - end - - setmetatableindex (characters, charindex) - -end - ------------------------------------------------------------------------ ---- features / scripts / languages ------------------------------------------------------------------------ ---- lots of arrowcode ahead - ---[[doc-- -This function, modeled after “check_script()” from fontspec, returns -true if in the given font, the script “asked_script” is accounted for in at -least one feature. ---doc]]-- - ---- int -> string -> bool -local provides_script = function (font_id, asked_script) - asked_script = stringlower(asked_script) - if font_id and font_id > 0 then - local fontdata = identifiers[font_id].shared.rawdata - if fontdata then - local fontname = fontdata.metadata.fontname - local features = fontdata.resources.features - for method, featuredata in next, features do - --- where method: "gpos" | "gsub" - for feature, data in next, featuredata do - if data[asked_script] then - report ("log", 1, "aux", - "font no %d (%s) defines feature %s for script %s", - font_id, fontname, feature, asked_script) - return true - end - end - end - report ("log", 0, "aux", - "font no %d (%s) defines no feature for script %s", - font_id, fontname, asked_script) - end - end - report ("log", 0, "aux", "no font with id %d", font_id) - return false -end - -aux.provides_script = provides_script - ---[[doc-- -This function, modeled after “check_language()” from fontspec, returns -true if in the given font, the language with tage “asked_language” is -accounted for in the script with tag “asked_script” in at least one -feature. ---doc]]-- - ---- int -> string -> string -> bool -local provides_language = function (font_id, asked_script, asked_language) - asked_script = stringlower(asked_script) - asked_language = stringlower(asked_language) - if font_id and font_id > 0 then - local fontdata = identifiers[font_id].shared.rawdata - if fontdata then - local fontname = fontdata.metadata.fontname - local features = fontdata.resources.features - for method, featuredata in next, features do - --- where method: "gpos" | "gsub" - for feature, data in next, featuredata do - local scriptdata = data[asked_script] - if scriptdata and scriptdata[asked_language] then - report ("log", 1, "aux", - "font no %d (%s) defines feature %s " - .. "for script %s with language %s", - font_id, fontname, feature, - asked_script, asked_language) - return true - end - end - end - report ("log", 0, "aux", - "font no %d (%s) defines no feature " - .. "for script %s with language %s", - font_id, fontname, asked_script, asked_language) - end - end - report ("log", 0, "aux", "no font with id %d", font_id) - return false -end - -aux.provides_language = provides_language - ---[[doc-- -We strip the syntax elements from feature definitions (shouldn’t -actually be there in the first place, but who cares ...) ---doc]]-- - -local lpeg = require"lpeg" -local C, P, S = lpeg.C, lpeg.P, lpeg.S -local lpegmatch = lpeg.match - -local sign = S"+-" -local rhs = P"=" * P(1)^0 * P(-1) -local strip_garbage = sign^-1 * C((1 - rhs)^1) - ---s = "+foo" --> foo ---ss = "-bar" --> bar ---sss = "baz" --> baz ---t = "foo=bar" --> foo ---tt = "+bar=baz" --> bar ---ttt = "-baz=true" --> baz --- ---print(lpeg.match(strip_garbage, s)) ---print(lpeg.match(strip_garbage, ss)) ---print(lpeg.match(strip_garbage, sss)) ---print(lpeg.match(strip_garbage, t)) ---print(lpeg.match(strip_garbage, tt)) ---print(lpeg.match(strip_garbage, ttt)) - ---[[doc-- -This function, modeled after “check_feature()” from fontspec, returns -true if in the given font, the language with tag “asked_language” is -accounted for in the script with tag “asked_script” in feature -“asked_feature”. ---doc]]-- - ---- int -> string -> string -> string -> bool -local provides_feature = function (font_id, asked_script, - asked_language, asked_feature) - asked_script = stringlower(asked_script) - asked_language = stringlower(asked_language) - asked_feature = lpegmatch(strip_garbage, asked_feature) - - if font_id and font_id > 0 then - local fontdata = identifiers[font_id].shared.rawdata - if fontdata then - local features = fontdata.resources.features - local fontname = fontdata.metadata.fontname - for method, featuredata in next, features do - --- where method: "gpos" | "gsub" - local feature = featuredata[asked_feature] - if feature then - local scriptdata = feature[asked_script] - if scriptdata and scriptdata[asked_language] then - report ("log", 1, "aux", - "font no %d (%s) defines feature %s " - .. "for script %s with language %s", - font_id, fontname, asked_feature, - asked_script, asked_language) - return true - end - end - end - report ("log", 0, "aux", - "font no %d (%s) does not define feature %s for script %s with language %s", - font_id, fontname, asked_feature, asked_script, asked_language) - end - end - report ("log", 0, "aux", "no font with id %d", font_id) - return false -end - -aux.provides_feature = provides_feature - ------------------------------------------------------------------------ ---- font dimensions ------------------------------------------------------------------------ - ---- int -> string -> int -local get_math_dimension = function (font_id, dimenname) - if type(font_id) == "string" then - font_id = fontid(font_id) --- safeguard - end - local fontdata = identifiers[font_id] - local mathdata = fontdata.mathparameters - if mathdata then - return mathdata[dimenname] or 0 - end - return 0 -end - -aux.get_math_dimension = get_math_dimension - ---- int -> string -> unit -local sprint_math_dimension = function (font_id, dimenname) - if type(font_id) == "string" then - font_id = fontid(font_id) - end - local dim = get_math_dimension(font_id, dimenname) - texsprint(luatexbase.catcodetables["latex-package"], dim, "sp") -end - -aux.sprint_math_dimension = sprint_math_dimension - ------------------------------------------------------------------------ ---- extra database functions ------------------------------------------------------------------------ - -local namesresolve = fonts.names.resolve -local namesscan_dir = fonts.names.scan_dir - ---[====[-- TODO -> port this to new db model - ---- local directories ------------------------------------------------- - ---- migrated from luaotfload-database.lua ---- https://github.com/lualatex/luaotfload/pull/61#issuecomment-17776975 - ---- string -> (int * int) -local scan_external_dir = function (dir) - local old_names, new_names = names.data() - if not old_names then - old_names = load_names() - end - new_names = tablecopy(old_names) - local n_scanned, n_new = scan_dir(dir, old_names, new_names) - --- FIXME - --- This doesn’t seem right. If a db update is triggered after this - --- point, then the added fonts will be saved along with it -- - --- which is not as “temporarily” as it should be. (This should be - --- addressed during a refactoring of names_resolve().) - names.data = new_names - return n_scanned, n_new -end - -aux.scan_external_dir = scan_external_dir - ---]====]-- - -aux.scan_external_dir = function () - print "ERROR: scan_external_dir() is not implemented" -end - ---- db queries -------------------------------------------------------- - ---- https://github.com/lualatex/luaotfload/issues/74 ---- string -> (string * int) -local resolve_fontname = function (name) - local foundname, subfont, success = namesresolve(nil, nil, { - name = name, - lookup = "name", - optsize = 0, - specification = "name:" .. name, - }) - if success then - return foundname, subfont - end - return false, false -end - -aux.resolve_fontname = resolve_fontname - ---- string list -> (string * int) -local resolve_fontlist -resolve_fontlist = function (names, n) - if not n then - return resolve_fontlist(names, 1) - end - local this = names[n] - if this then - local foundname, subfont = resolve_fontname(this) - if foundname then - return foundname, subfont - end - return resolve_fontlist(names, n+1) - end - return false, false -end - -aux.resolve_fontlist = resolve_fontlist - ---- loaded fonts ------------------------------------------------------ - ---- just a proof of concept - ---- fontobj -> string list -> (string list) list -local get_font_data get_font_data = function (tfmdata, keys, acc, n) - if not acc then - return get_font_data(tfmdata, keys, {}, 1) - end - local key = keys[n] - if key then - local val = tfmdata[key] - if val then - acc[#acc+1] = val - else - acc[#acc+1] = false - end - return get_font_data(tfmdata, keys, acc, n+1) - end - return acc -end - ---[[doc-- - - The next one operates on the fonts.hashes.identifiers table. - It returns a list containing tuples of font ids and the - contents of the fields specified in the first argument. - Font table entries that were created indirectly -- e.g. by - \letterspacefont or during font expansion -- will not be - listed. - ---doc]]-- - -local default_keys = { "fullname" } - ---- string list -> (int * string list) list -local get_loaded_fonts get_loaded_fonts = function (keys, acc, lastid) - if not acc then - if not keys then - keys = default_keys - end - return get_loaded_fonts(keys, {}, lastid) - end - local id, tfmdata = next(identifiers, lastid) - if id then - local data = get_font_data(tfmdata, keys) - acc[#acc+1] = { id, data } - return get_loaded_fonts (keys, acc, id) - end - return acc -end - -aux.get_loaded_fonts = get_loaded_fonts - ---- Raw access to the font.* namespace is unsafe so no documentation on ---- this one. -local get_raw_fonts = function ( ) - local res = { } - for i, v in font.each() do - if v.filename then - res[#res+1] = { i, v } - end - end - return res -end - -aux.get_raw_fonts = get_raw_fonts - ------------------------------------------------------------------------ ---- font parameters ------------------------------------------------------------------------ ---- analogy of font-hsh - -fonthashes.parameters = fonthashes.parameters or { } -fonthashes.quads = fonthashes.quads or { } - -local parameters = fonthashes.parameters or { } -local quads = fonthashes.quads or { } - -setmetatable(parameters, { __index = function (t, font_id) - local tfmdata = identifiers[font_id] - if not tfmdata then --- unsafe; avoid - tfmdata = font.fonts[font_id] - end - if tfmdata and type(tfmdata) == "table" then - local fontparameters = tfmdata.parameters - t[font_id] = fontparameters - return fontparameters - end - return nil -end}) - ---[[doc-- - - Note that the reason as to why we prefer functions over table indices - is that functions are much safer against unintended manipulation. - This justifies the overhead they cost. - ---doc]]-- - ---- int -> (number | false) -local get_quad = function (font_id) - local quad = quads[font_id] - if quad then - return quad - end - local fontparameters = parameters[font_id] - if fontparameters then - local quad = fontparameters.quad or 0 - quads[font_id] = quad - return quad - end - return false -end - -aux.get_quad = get_quad - --- vim:tw=71:sw=2:ts=2:expandtab |