You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
5.4 KiB
177 lines
5.4 KiB
if not modules then modules = { } end modules ['font-cid'] = {
|
|
version = 1.001,
|
|
comment = "companion to font-ini.mkiv",
|
|
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
|
|
copyright = "PRAGMA ADE / ConTeXt Development Team",
|
|
license = "see context related readme files"
|
|
}
|
|
|
|
local format, match, lower = string.format, string.match, string.lower
|
|
local tonumber = tonumber
|
|
local P, S, R, C, V, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.match
|
|
|
|
local fonts, logs, trackers = fonts, logs, trackers
|
|
|
|
local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
|
|
|
|
local report_otf = logs.reporter("fonts","otf loading")
|
|
|
|
local cid = { }
|
|
fonts.cid = cid
|
|
|
|
local cidmap = { }
|
|
local cidmax = 10
|
|
|
|
-- original string parser: 0.109, lpeg parser: 0.036 seconds for Adobe-CNS1-4.cidmap
|
|
--
|
|
-- 18964 18964 (leader)
|
|
-- 0 /.notdef
|
|
-- 1..95 0020
|
|
-- 99 3000
|
|
|
|
local number = C(R("09","af","AF")^1)
|
|
local space = S(" \n\r\t")
|
|
local spaces = space^0
|
|
local period = P(".")
|
|
local periods = period * period
|
|
local name = P("/") * C((1-space)^1)
|
|
|
|
local unicodes, names = { }, { } -- we could use Carg now
|
|
|
|
local function do_one(a,b)
|
|
unicodes[tonumber(a)] = tonumber(b,16)
|
|
end
|
|
|
|
local function do_range(a,b,c)
|
|
c = tonumber(c,16)
|
|
for i=tonumber(a),tonumber(b) do
|
|
unicodes[i] = c
|
|
c = c + 1
|
|
end
|
|
end
|
|
|
|
local function do_name(a,b)
|
|
names[tonumber(a)] = b
|
|
end
|
|
|
|
local grammar = P { "start",
|
|
start = number * spaces * number * V("series"),
|
|
series = (spaces * (V("one") + V("range") + V("named")))^1,
|
|
one = (number * spaces * number) / do_one,
|
|
range = (number * periods * number * spaces * number) / do_range,
|
|
named = (number * spaces * name) / do_name
|
|
}
|
|
|
|
local function loadcidfile(filename)
|
|
local data = io.loaddata(filename)
|
|
if data then
|
|
unicodes, names = { }, { }
|
|
lpegmatch(grammar,data)
|
|
local supplement, registry, ordering = match(filename,"^(.-)%-(.-)%-()%.(.-)$")
|
|
return {
|
|
supplement = supplement,
|
|
registry = registry,
|
|
ordering = ordering,
|
|
filename = filename,
|
|
unicodes = unicodes,
|
|
names = names,
|
|
}
|
|
end
|
|
end
|
|
|
|
cid.loadfile = loadcidfile -- we use the frozen variant
|
|
local template = "%s-%s-%s.cidmap"
|
|
|
|
local function locate(registry,ordering,supplement)
|
|
local filename = format(template,registry,ordering,supplement)
|
|
local hashname = lower(filename)
|
|
local found = cidmap[hashname]
|
|
if not found then
|
|
if trace_loading then
|
|
report_otf("checking cidmap, registry %a, ordering %a, supplement %a, filename %a",registry,ordering,supplement,filename)
|
|
end
|
|
local fullname = resolvers.findfile(filename,'cid') or ""
|
|
if fullname ~= "" then
|
|
found = loadcidfile(fullname)
|
|
if found then
|
|
if trace_loading then
|
|
report_otf("using cidmap file %a",filename)
|
|
end
|
|
cidmap[hashname] = found
|
|
found.usedname = file.basename(filename)
|
|
end
|
|
end
|
|
end
|
|
return found
|
|
end
|
|
|
|
-- cf Arthur R. we can safely scan upwards since cids are downward compatible
|
|
|
|
function cid.getmap(specification)
|
|
if not specification then
|
|
report_otf("invalid cidinfo specification, table expected")
|
|
return
|
|
end
|
|
local registry = specification.registry
|
|
local ordering = specification.ordering
|
|
local supplement = specification.supplement
|
|
local filename = format(registry,ordering,supplement)
|
|
local lowername = lower(filename)
|
|
local found = cidmap[lowername]
|
|
if found then
|
|
return found
|
|
end
|
|
if ordering == "Identity" then
|
|
local found = {
|
|
supplement = supplement,
|
|
registry = registry,
|
|
ordering = ordering,
|
|
filename = filename,
|
|
unicodes = { },
|
|
names = { },
|
|
}
|
|
cidmap[lowername] = found
|
|
return found
|
|
end
|
|
-- check for already loaded file
|
|
if trace_loading then
|
|
report_otf("cidmap needed, registry %a, ordering %a, supplement %a",registry,ordering,supplement)
|
|
end
|
|
found = locate(registry,ordering,supplement)
|
|
if not found then
|
|
local supnum = tonumber(supplement)
|
|
local cidnum = nil
|
|
-- next highest (alternatively we could start high)
|
|
if supnum < cidmax then
|
|
for s=supnum+1,cidmax do
|
|
local c = locate(registry,ordering,s)
|
|
if c then
|
|
found, cidnum = c, s
|
|
break
|
|
end
|
|
end
|
|
end
|
|
-- next lowest (least worse fit)
|
|
if not found and supnum > 0 then
|
|
for s=supnum-1,0,-1 do
|
|
local c = locate(registry,ordering,s)
|
|
if c then
|
|
found, cidnum = c, s
|
|
break
|
|
end
|
|
end
|
|
end
|
|
-- prevent further lookups -- somewhat tricky
|
|
registry = lower(registry)
|
|
ordering = lower(ordering)
|
|
if found and cidnum > 0 then
|
|
for s=0,cidnum-1 do
|
|
local filename = format(template,registry,ordering,s)
|
|
if not cidmap[filename] then
|
|
cidmap[filename] = found
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return found
|
|
end
|
|
|