summaryrefslogtreecommitdiff
path: root/luaotfload-fonts.lua
diff options
context:
space:
mode:
authorKhaled Hosny <khaledhosny@eglug.org>2010-02-28 18:54:38 +0200
committerKhaled Hosny <khaledhosny@eglug.org>2010-02-28 18:54:38 +0200
commitb80b94ca5aedf47f75ed6052985d4c1f167d6a89 (patch)
tree29847605cebc927b3343188d68f9a40bfd2a7083 /luaotfload-fonts.lua
parentc46a92a2b93e3baa85cc9e130af1613142f9f524 (diff)
downloadluaotfload-b80b94ca5aedf47f75ed6052985d4c1f167d6a89.tar.gz
Prepare for merging luaotfload-fonts in luaotfload
Diffstat (limited to 'luaotfload-fonts.lua')
-rw-r--r--luaotfload-fonts.lua375
1 files changed, 0 insertions, 375 deletions
diff --git a/luaotfload-fonts.lua b/luaotfload-fonts.lua
deleted file mode 100644
index aeba0f1..0000000
--- a/luaotfload-fonts.lua
+++ /dev/null
@@ -1,375 +0,0 @@
--- This lua script is made to generate the font database for LuaTeX, in order
--- for it to be able to load a font according to its name, like XeTeX does.
---
--- It is part of the luaotfload bundle, see luaotfload's README for legal
--- notice.
-
--- some usual initializations
-luaotfload = luaotfload or { }
-luaotfload.fonts = { }
-
-luaotfload.fonts.module = {
- name = "luaotfload.fonts",
- version = 1.001,
- date = "2010/01/12",
- description = "luaotfload font database.",
- author = "Khaled Hosny and Elie Roux",
- copyright = "Luaotfload Development Team",
- license = "CC0"
-}
-
-kpse.set_program_name("luatex")
-
-local luaextra_file = kpse.find_file("luaextra.lua")
-if not luaextra_file then
- texio.write_nl("Error: cannot find 'luaextra.lua', exiting.")
- os.exit(1)
-end
-dofile(luaextra_file)
-
-local splitpath, expandpath, glob, basename = file.split_path, kpse.expand_path, dir.glob, file.basename
-local upper, format, rep = string.upper, string.format, string.rep
-
-function kpse.do_file(name)
- return dofile(kpse.find_file(name))
-end
-
--- the file name of the font database
-luaotfload.fonts.basename = "otfl-names.lua"
-
--- the path to add to TEXMFVAR or TEXMFSYSVAR to get the final directory in
--- normal cases
-luaotfload.fonts.subtexmfvardir = "/tex/"
-
--- the directory in which the database will be saved, can be overwritten
-luaotfload.fonts.directory = kpse.expand_var("$TEXMFVAR") .. luaotfload.fonts.subtexmfvardir
-
--- the version of the database, to be checked by the lookup function of
--- luaotfload
-luaotfload.fonts.version = 2.004
-
--- Log facilities:
--- - level 0 is quiet
--- - level 1 is the progress bar
--- - level 2 prints the searched directories
--- - level 3 prints all the loaded fonts
--- - level 4 prints all informations when searching directories (debug only)
-luaotfload.fonts.log_level = 1
-
-local lastislog = 0
-
-function luaotfload.fonts.log(lvl, fmt, ...)
- if lvl <= luaotfload.fonts.log_level then
- lastislog = 1
- texio.write_nl(format("luaotfload | %s", format(fmt,...)))
- end
-end
-
-local log = luaotfload.fonts.log
-
--- The progress bar
-local function progress(current, total)
- if luaotfload.fonts.log_level == 1 then
--- local width = os.getenv("COLUMNS") -2 --doesn't work
- local width = 78
- local percent = current/total
- local gauge = format("[%s]", string.rpadd(" ", width, " "))
- if percent > 0 then
- local done = string.rpadd("=", (width * percent) - 1, "=") .. ">"
- gauge = format("[%s]", string.rpadd(done, width, " ") )
- end
- if lastislog == 1 then
- texio.write_nl("")
- lastislog = 0
- end
- io.stderr:write("\r"..gauge)
- io.stderr:flush()
- end
-end
-
-function fontloader.fullinfo(...)
- local t = { }
- local f = fontloader.open(...)
- local m = f and fontloader.to_table(f)
- fontloader.close(f)
- -- see http://www.microsoft.com/typography/OTSPEC/features_pt.htm#size
- if m.fontstyle_name then
- for _,v in pairs(m.fontstyle_name) do
- if v.lang == 1033 then
- t.fontstyle_name = v.name
- end
- end
- end
- if m.names then
- for _,v in pairs(m.names) do
- if v.lang == "English (US)" then
- t.names = {
- -- see http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html
- fullname = v.names.compatfull or v.names.fullname, -- 18, 4
- family = v.names.preffamilyname or v.names.family, -- 17, 1
- subfamily = t.fontstyle_name or v.names.prefmodifiers or v.names.subfamily, -- opt. style, 16, 2
- psname = v.names.postscriptname --or t.fontname
- }
- end
- end
- end
- t.fontname = m.fontname
- t.fullname = m.fullname
- t.familyname = m.familyname
- t.filename = m.origname
- t.weight = m.pfminfo.weight
- t.width = m.pfminfo.width
- t.slant = m.italicangle
- -- don't waste the space with zero values
- t.size = {
- m.design_size ~= 0 and m.design_size or nil,
- m.design_range_top ~= 0 and m.design_range_top or nil,
- m.design_range_bottom ~= 0 and m.design_range_bottom or nil,
- }
- return t
-end
-
-local function load_font(filename, names, texmf)
- log(3, "Loading font: %s", filename)
- local mappings = names.mappings or { }
- local families = names.families or { }
- local checksums = names.checksums or { }
- if filename then
- local checksum = file.checksum(filename)
- if checksums[checksum] and checksums[checksum] == filename then
- log(3, "Font already indexed: %s", filename)
- return
- end
- checksums[checksum] = filename
- local info = fontloader.info(filename)
- if info then
- if type(info) == "table" and #info > 1 then
- for index,_ in ipairs(info) do
- local fullinfo = fontloader.fullinfo(filename, index-1)
- if texmf then
- fullinfo.filename = basename(filename)
- end
- mappings[#mappings+1] = fullinfo
- if fullinfo.names.family then
- if not families[fullinfo.names.family] then
- families[fullinfo.names.family] = { }
- end
- table.insert(families[fullinfo.names.family], #mappings)
- else
- log(3, "Warning: font with broken names table: %s, ignored", filename)
- end
- end
- else
- local fullinfo = fontloader.fullinfo(filename)
- if texmf then
- fullinfo.filename = basename(filename)
- end
- mappings[#mappings+1] = fullinfo
- if fullinfo.names.family then
- if not families[fullinfo.names.family] then
- families[fullinfo.names.family] = { }
- end
- table.insert(families[fullinfo.names.family], #mappings)
- else
- log(3, "Warning: font with broken names table: %s, ignored", filename)
- end
- end
- else
- log(1, "Failed to load %s", filename)
- end
- names.mappings = names.mappings or mappings
- names.families = names.families or families
- names.checksums = names.checksums or checksums
- end
-end
-
--- We need to detect the OS (especially cygwin) to convert paths.
-local system = LUAROCKS_UNAME_S or io.popen("uname -s"):read("*l")
-if system then
- if system:match("^CYGWIN") then
- system = 'cygwin'
- elseif system:match("^Windows") then
- system = 'windows'
- else
- system = 'unix'
- end
-else
- system = 'unix' -- ?
-end
-log(2, "Detecting system: %s", system)
-
--- path normalization:
--- - a\b\c -> a/b/c
--- - a/../b -> b
--- - /cygdrive/a/b -> a:/b
-local function path_normalize(path)
- if system ~= 'unix' then
- path = path:gsub('\\', '/')
- path = path:lower()
- end
- path = file.collapse_path(path)
- if system == "cygwin" then
- path = path:gsub('^/cygdrive/(%a)/', '%1:/')
- end
- return path
-end
-
--- this function scans a directory and populates the list of fonts
--- with all the fonts it finds.
--- - dirname is the name of the directory to scan
--- - names is the font database to fill
--- - recursive is whether we scan all directories recursively (always false
--- in this script)
--- - texmf is a boolean saying if we are scanning a texmf directory (always
--- true in this script)
--- - scanned_fonts contains the list of alread scanned fonts, in order for them
--- not to be scanned twice. The function populates this list with the
--- fonts it scans.
-local function scan_dir(dirname, names, recursive, texmf, scanned_fonts)
- local list, found = { }, { }
- local nbfound = 0
- for _,ext in ipairs { "otf", "ttf", "ttc", "dfont" } do
- if recursive then pat = "/**." else pat = "/*." end
- log(4, "Scanning '%s' for '%s' fonts", dirname, ext)
- found = glob(dirname .. pat .. ext)
- -- note that glob fails silently on broken symlinks, which happens
- -- sometimes in TeX Live.
- log(4, "%s fonts found", #found)
- nbfound = nbfound + #found
- table.append(list, found)
- log(4, "Scanning '%s' for '%s' fonts", dirname, upper(ext))
- found = glob(dirname .. pat .. upper(ext))
- table.append(list, found)
- nbfound = nbfound + #found
- end
- log(2, "%d fonts found in '%s'", nbfound, dirname)
- for _,fnt in ipairs(list) do
- fnt = path_normalize(fnt)
- if not scanned_fonts[fnt] then
- load_font(fnt, names, texmf)
- scanned_fonts[fnt] = true
- end
- end
-end
-
--- The function that scans all fonts in the texmf tree, through kpathsea
--- variables OPENTYPEFONTS and TTFONTS of texmf.cnf
-local function scan_texmf_tree(names)
- if expandpath("$OSFONTDIR"):is_empty() then
- log(1, "Scanning TEXMF fonts:")
- else
- log(1, "Scanning TEXMF and OS fonts:")
- end
- local scanned_fonts = {}
- local fontdirs = expandpath("$OPENTYPEFONTS")
- fontdirs = fontdirs .. string.gsub(expandpath("$TTFONTS"), "^\.", "")
- if not fontdirs:is_empty() then
- local explored_dirs = {}
- fontdirs = splitpath(fontdirs)
- -- hack, don't scan current dir
- table.remove(fontdirs, 1)
- count = 0
- for _,d in ipairs(fontdirs) do
- if not explored_dirs[d] then
- count = count + 1
- progress(count, #fontdirs)
- scan_dir(d, names, false, true, scanned_fonts)
- explored_dirs[d] = true
- end
- end
- end
- return scanned_fonts
-end
-
--- this function takes raw data returned by fc-list, parses it, normalizes the
--- paths and makes a list out of it.
-local function read_fcdata(data)
- local list = { }
- for line in data:lines() do
- line = line:gsub(": ", "")
- local ext = string.lower(string.match(line,"^.+%.([^/\\]-)$"))
- if ext == "otf" or ext == "ttf" or ext == "ttc" or ext == "dfont" then
- list[#list+1] = path_normalize(line:gsub(": ", ""))
- end
- end
- return list
-end
-
--- This function scans the OS fonts through fontcache (fc-list), it executes
--- only if OSFONTDIR is empty (which is the case under most Unix by default).
--- If OSFONTDIR is non-empty, this means that the system fonts it contains have
--- already been scanned, and thus we don't scan them again.
-local function scan_os_fonts(names, scanned_fonts)
- if expandpath("$OSFONTDIR"):is_empty() then
- log(1, "Scanning system fonts:")
- log(2, "Executing 'fc-list : file'")
- local data = io.popen("fc-list : file", 'r')
- log(2, "Parsing the result...")
- local list = read_fcdata(data)
- data:close()
- log(2, "%d fonts found", #list)
- log(2, "Scanning...", #list)
- count = 0
- for _,fnt in ipairs(list) do
- count = count + 1
- progress(count, #list)
- if not scanned_fonts[fnt] then
- load_font(fnt, names, false)
- scanned_fonts[fnt] = true
- end
- end
- end
-end
-
-local function fontnames_init()
- return {
- mappings = { },
- families = { },
- checksums = { },
- version = luaotfload.fonts.version,
- }
-end
-
--- The main function, scans everything and writes the file.
-local function reload(force)
- texio.write("luaotfload | Generating font names database.")
- local fnames
- if force then
- fnames = fontnames_init()
- else
- fnames = kpse.do_file(luaotfload.fonts.basename)
- if fnames and fnames.version and fnames.version == luaotfload.fonts.version then
- else
- log(2, "Old font names database version, generating new one")
- fnames = fontnames_init()
- end
- end
- local savepath = luaotfload.fonts.directory
- savepath = path_normalize(savepath)
- if not lfs.isdir(savepath) then
- log(1, "Creating directory %s", savepath)
- lfs.mkdir(savepath)
- if not lfs.isdir(savepath) then
- texio.write_nl(string.format("Error: cannot create directory '%s', exiting.\n", savepath))
- os.exit(1)
- end
- end
- savepath = savepath .. '/' .. luaotfload.fonts.basename
- local fh = io.open(savepath, 'a+')
- if not fh then
- texio.write_nl(string.format("Error: cannot write file '%s', exiting.\n", savepath))
- os.exit(1)
- end
- fh:close()
- -- we save the scanned fonts in a variable in order for scan_os_fonts
- -- not to rescan them
- local scanned_fonts = scan_texmf_tree(fnames)
- scan_os_fonts (fnames, scanned_fonts)
- log(1, "%s fonts in %s families saved in the database",
- #fnames.mappings, #table.keys(fnames.families))
- io.savedata(savepath, table.serialize(fnames, true))
- log(1, "Saved font names database in %s\n", savepath)
-end
-
-luaotfload.fonts.scan = scan_dir
-luaotfload.fonts.reload = reload