1if not modules then modules = { } end modules ['font-cid'] = {
2 version = 1.001,
3 comment = "companion to font-ini.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9local format, match, lower = string.format, string.match, string.lower
10local tonumber = tonumber
11local P, S, R, C, V, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.match
12
13local fonts, logs, trackers = fonts, logs, trackers
14
15local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
16
17local report_otf = logs.reporter("fonts","otf loading")
18
19local cid = { }
20fonts.cid = cid
21
22local cidmap = { }
23local cidmax = 10
24
25
26
27
28
29
30
31
32local number = C(R("09","af","AF")^1)
33local space = S(" \n\r\t")
34local spaces = space^0
35local period = P(".")
36local periods = period * period
37local name = P("/") * C((1-space)^1)
38
39local unicodes, names = { }, { }
40
41local function do_one(a,b)
42 unicodes[tonumber(a)] = tonumber(b,16)
43end
44
45local function do_range(a,b,c)
46 c = tonumber(c,16)
47 for i=tonumber(a),tonumber(b) do
48 unicodes[i] = c
49 c = c + 1
50 end
51end
52
53local function do_name(a,b)
54 names[tonumber(a)] = b
55end
56
57local grammar = P { "start",
58 start = number * spaces * number * V("series"),
59 series = (spaces * (V("one") + V("range") + V("named")))^1,
60 one = (number * spaces * number) / do_one,
61 range = (number * periods * number * spaces * number) / do_range,
62 named = (number * spaces * name) / do_name
63}
64
65local function loadcidfile(filename)
66 local data = io.loaddata(filename)
67 if data then
68 unicodes, names = { }, { }
69 lpegmatch(grammar,data)
70 local supplement, registry, ordering = match(filename,"^(.-)%-(.-)%-()%.(.-)$")
71 return {
72 supplement = supplement,
73 registry = registry,
74 ordering = ordering,
75 filename = filename,
76 unicodes = unicodes,
77 names = names,
78 }
79 end
80end
81
82cid.loadfile = loadcidfile
83local template = "%s-%s-%s.cidmap"
84
85local function locate(registry,ordering,supplement)
86 local filename = format(template,registry,ordering,supplement)
87 local hashname = lower(filename)
88 local found = cidmap[hashname]
89 if not found then
90 if trace_loading then
91 report_otf("checking cidmap, registry %a, ordering %a, supplement %a, filename %a",registry,ordering,supplement,filename)
92 end
93 local fullname = resolvers.findfile(filename,'cid') or ""
94 if fullname ~= "" then
95 found = loadcidfile(fullname)
96 if found then
97 if trace_loading then
98 report_otf("using cidmap file %a",filename)
99 end
100 cidmap[hashname] = found
101 found.usedname = file.basename(filename)
102 end
103 end
104 end
105 return found
106end
107
108
109
110function cid.getmap(specification)
111 if not specification then
112 report_otf("invalid cidinfo specification, table expected")
113 return
114 end
115 local registry = specification.registry
116 local ordering = specification.ordering
117 local supplement = specification.supplement
118 local filename = format(registry,ordering,supplement)
119 local lowername = lower(filename)
120 local found = cidmap[lowername]
121 if found then
122 return found
123 end
124 if ordering == "Identity" then
125 local found = {
126 supplement = supplement,
127 registry = registry,
128 ordering = ordering,
129 filename = filename,
130 unicodes = { },
131 names = { },
132 }
133 cidmap[lowername] = found
134 return found
135 end
136
137 if trace_loading then
138 report_otf("cidmap needed, registry %a, ordering %a, supplement %a",registry,ordering,supplement)
139 end
140 found = locate(registry,ordering,supplement)
141 if not found then
142 local supnum = tonumber(supplement)
143 local cidnum = nil
144
145 if supnum < cidmax then
146 for s=supnum+1,cidmax do
147 local c = locate(registry,ordering,s)
148 if c then
149 found, cidnum = c, s
150 break
151 end
152 end
153 end
154
155 if not found and supnum > 0 then
156 for s=supnum-1,0,-1 do
157 local c = locate(registry,ordering,s)
158 if c then
159 found, cidnum = c, s
160 break
161 end
162 end
163 end
164
165 registry = lower(registry)
166 ordering = lower(ordering)
167 if found and cidnum > 0 then
168 for s=0,cidnum-1 do
169 local filename = format(template,registry,ordering,s)
170 if not cidmap[filename] then
171 cidmap[filename] = found
172 end
173 end
174 end
175 end
176 return found
177end
178 |