diff options
Diffstat (limited to 'otfl-font-cid.lua')
-rw-r--r-- | otfl-font-cid.lua | 100 |
1 files changed, 57 insertions, 43 deletions
diff --git a/otfl-font-cid.lua b/otfl-font-cid.lua index a9bd3c5..4a4c4d2 100644 --- a/otfl-font-cid.lua +++ b/otfl-font-cid.lua @@ -8,18 +8,19 @@ if not modules then modules = { } end modules ['font-cid'] = { local format, match, lower = string.format, string.match, string.lower local tonumber = tonumber -local lpegmatch = lpeg.match +local P, S, R, C, V, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.match -local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end) +local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end) local report_otf = logs.reporter("fonts","otf loading") -local fonts = fonts +local fonts = fonts -fonts.cid = fonts.cid or { } -local cid = fonts.cid -cid.map = cid.map or { } -cid.max = cid.max or 10 +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 -- @@ -28,8 +29,6 @@ cid.max = cid.max or 10 -- 1..95 0020 -- 99 3000 -local P, S, R, C = lpeg.P, lpeg.S, lpeg.R, lpeg.C - local number = C(R("09","af","AF")^1) local space = S(" \n\r\t") local spaces = space^0 @@ -37,7 +36,7 @@ local period = P(".") local periods = period * period local name = P("/") * C((1-space)^1) -local unicodes, names = { }, { } +local unicodes, names = { }, { } -- we could use Carg now local function do_one(a,b) unicodes[tonumber(a)] = tonumber(b,16) @@ -55,15 +54,15 @@ local function do_name(a,b) names[tonumber(a)] = b end -local grammar = lpeg.P { "start", - start = number * spaces * number * lpeg.V("series"), - series = (spaces * (lpeg.V("one") + lpeg.V("range") + lpeg.V("named")) )^1, +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 } -function cid.load(filename) +local function loadcidfile(filename) local data = io.loaddata(filename) if data then unicodes, names = { }, { } @@ -77,75 +76,90 @@ function cid.load(filename) unicodes = unicodes, names = names } - else - return nil 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 cidmap = cid.map[hashname] - if not cidmap then + local found = cidmap[hashname] + if not found then if trace_loading then report_otf("checking cidmap, registry: %s, ordering: %s, supplement: %s, filename: %s",registry,ordering,supplement,filename) end local fullname = resolvers.findfile(filename,'cid') or "" if fullname ~= "" then - cidmap = cid.load(fullname) - if cidmap then + found = loadcidfile(fullname) + if found then if trace_loading then report_otf("using cidmap file %s",filename) end - cid.map[hashname] = cidmap - cidmap.usedname = file.basename(filename) - return cidmap + cidmap[hashname] = found + found.usedname = file.basename(filename) end end end - return cidmap + return found end -function cid.getmap(registry,ordering,supplement) - -- cf Arthur R. we can safely scan upwards since cids are downward compatible - local supplement = tonumber(supplement) +-- 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 + -- check for already loaded file + local filename = format(registry,ordering,supplement) + local found = cidmap[lower(filename)] + if found then + return found + end if trace_loading then report_otf("needed cidmap, registry: %s, ordering: %s, supplement: %s",registry,ordering,supplement) end - local cidmap = locate(registry,ordering,supplement) - if not cidmap then + found = locate(registry,ordering,supplement) + if not found then + local supnum = tonumber(supplement) local cidnum = nil -- next highest (alternatively we could start high) - if supplement < cid.max then - for supplement=supplement+1,cid.max do - local c = locate(registry,ordering,supplement) + if supnum < cidmax then + for s=supnum+1,cidmax do + local c = locate(registry,ordering,s) if c then - cidmap, cidnum = c, supplement + found, cidnum = c, s break end end end -- next lowest (least worse fit) - if not cidmap and supplement > 0 then - for supplement=supplement-1,0,-1 do - local c = locate(registry,ordering,supplement) + if not found and supnum > 0 then + for s=supnum-1,0,-1 do + local c = locate(registry,ordering,s) if c then - cidmap, cidnum = c, supplement + found, cidnum = c, s break end end end - -- prevent further lookups - if cidmap and cidnum > 0 then + -- prevent further lookups -- somewhat tricky + registry = lower(registry) + ordering = lower(ordering) + if found and cidnum > 0 then for s=0,cidnum-1 do - filename = format(template,registry,ordering,s) - if not cid.map[filename] then - cid.map[filename] = cidmap -- copy of ref + local filename = format(template,registry,ordering,s) + if not cidmap[filename] then + cidmap[filename] = found end end end end - return cidmap + return found end |