1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
|
if not modules then modules = { } end modules ['font-map'] = {
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 match, format, find, concat, gsub = string.match, string.format, string.find, table.concat, string.gsub
local lpegmatch = lpeg.match
local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
local ctxcatcodes = tex and tex.ctxcatcodes
--[[ldx--
<p>Eventually this code will disappear because map files are kind
of obsolete. Some code may move to runtime or auxiliary modules.</p>
<p>The name to unciode related code will stay of course.</p>
--ldx]]--
fonts = fonts or { }
fonts.map = fonts.map or { }
fonts.map.data = fonts.map.data or { }
fonts.map.encodings = fonts.map.encodings or { }
fonts.map.done = fonts.map.done or { }
fonts.map.loaded = fonts.map.loaded or { }
fonts.map.direct = fonts.map.direct or { }
fonts.map.line = fonts.map.line or { }
function fonts.map.line.pdfmapline(tag,str)
return "\\loadmapline[" .. tag .. "][" .. str .. "]"
end
function fonts.map.line.pdftex(e) -- so far no combination of slant and extend
if e.name and e.fontfile then
local fullname = e.fullname or ""
if e.slant and e.slant ~= 0 then
if e.encoding then
return fonts.map.line.pdfmapline("=",format('%s %s "%g SlantFont" <%s <%s',e.name,fullname,e.slant,e.encoding,e.fontfile))
else
return fonts.map.line.pdfmapline("=",format('%s %s "%g SlantFont" <%s',e.name,fullname,e.slant,e.fontfile))
end
elseif e.extend and e.extend ~= 1 and e.extend ~= 0 then
if e.encoding then
return fonts.map.line.pdfmapline("=",format('%s %s "%g ExtendFont" <%s <%s',e.name,fullname,e.extend,e.encoding,e.fontfile))
else
return fonts.map.line.pdfmapline("=",format('%s %s "%g ExtendFont" <%s',e.name,fullname,e.extend,e.fontfile))
end
else
if e.encoding then
return fonts.map.line.pdfmapline("=",format('%s %s <%s <%s',e.name,fullname,e.encoding,e.fontfile))
else
return fonts.map.line.pdfmapline("=",format('%s %s <%s',e.name,fullname,e.fontfile))
end
end
else
return nil
end
end
function fonts.map.flush(backend) -- will also erase the accumulated data
local flushline = fonts.map.line[backend or "pdftex"] or fonts.map.line.pdftex
for _, e in pairs(fonts.map.data) do
tex.sprint(ctxcatcodes,flushline(e))
end
fonts.map.data = { }
end
fonts.map.line.dvips = fonts.map.line.pdftex
fonts.map.line.dvipdfmx = function() end
function fonts.map.convert_entries(filename)
if not fonts.map.loaded[filename] then
fonts.map.data, fonts.map.encodings = fonts.map.load_file(filename,fonts.map.data, fonts.map.encodings)
fonts.map.loaded[filename] = true
end
end
function fonts.map.load_file(filename, entries, encodings)
entries = entries or { }
encodings = encodings or { }
local f = io.open(filename)
if f then
local data = f:read("*a")
if data then
for line in gmatch(data,"(.-)[\n\t]") do
if find(line,"^[%#%%%s]") then
-- print(line)
else
local extend, slant, name, fullname, fontfile, encoding
line = gsub(line,'"(.+)"', function(s)
extend = find(s,'"([^"]+) ExtendFont"')
slant = find(s,'"([^"]+) SlantFont"')
return ""
end)
if not name then
-- name fullname encoding fontfile
name, fullname, encoding, fontfile = match(line,"^(%S+)%s+(%S*)[%s<]+(%S*)[%s<]+(%S*)%s*$")
end
if not name then
-- name fullname (flag) fontfile encoding
name, fullname, fontfile, encoding = match(line,"^(%S+)%s+(%S*)[%d%s<]+(%S*)[%s<]+(%S*)%s*$")
end
if not name then
-- name fontfile
name, fontfile = match(line,"^(%S+)%s+[%d%s<]+(%S*)%s*$")
end
if name then
if encoding == "" then encoding = nil end
entries[name] = {
name = name, -- handy
fullname = fullname,
encoding = encoding,
fontfile = fontfile,
slant = tonumber(slant),
extend = tonumber(extend)
}
encodings[name] = encoding
elseif line ~= "" then
-- print(line)
end
end
end
end
f:close()
end
return entries, encodings
end
function fonts.map.load_lum_table(filename)
local lumname = file.replacesuffix(file.basename(filename),"lum")
local lumfile = resolvers.find_file(lumname,"map") or ""
if lumfile ~= "" and lfs.isfile(lumfile) then
if trace_loading or trace_unimapping then
logs.report("load otf","enhance: loading %s ",lumfile)
end
lumunic = dofile(lumfile)
return lumunic, lumfile
end
end
local hex = lpeg.R("AF","09")
local hexfour = (hex*hex*hex*hex) / function(s) return tonumber(s,16) end
local hexsix = (hex^1) / function(s) return tonumber(s,16) end
local dec = (lpeg.R("09")^1) / tonumber
local period = lpeg.P(".")
local unicode = lpeg.P("uni") * (hexfour * (period + lpeg.P(-1)) * lpeg.Cc(false) + lpeg.Ct(hexfour^1) * lpeg.Cc(true))
local ucode = lpeg.P("u") * (hexsix * (period + lpeg.P(-1)) * lpeg.Cc(false) + lpeg.Ct(hexsix ^1) * lpeg.Cc(true))
local index = lpeg.P("index") * dec * lpeg.Cc(false)
local parser = unicode + ucode + index
local parsers = { }
function fonts.map.make_name_parser(str)
if not str or str == "" then
return parser
else
local p = parsers[str]
if not p then
p = lpeg.P(str) * period * dec * lpeg.Cc(false)
parsers[str] = p
end
return p
end
end
--~ local parser = fonts.map.make_name_parser("Japan1")
--~ local parser = fonts.map.make_name_parser()
--~ local function test(str)
--~ local b, a = lpegmatch(parser,str)
--~ print((a and table.serialize(b)) or b)
--~ end
--~ test("a.sc")
--~ test("a")
--~ test("uni1234")
--~ test("uni1234.xx")
--~ test("uni12349876")
--~ test("index1234")
--~ test("Japan1.123")
function fonts.map.tounicode16(unicode)
if unicode < 0x10000 then
return format("%04X",unicode)
else
return format("%04X%04X",unicode/1024+0xD800,unicode%1024+0xDC00)
end
end
function fonts.map.tounicode16sequence(unicodes)
local t = { }
for l=1,#unicodes do
local unicode = unicodes[l]
if unicode < 0x10000 then
t[l] = format("%04X",unicode)
else
t[l] = format("%04X%04X",unicode/1024+0xD800,unicode%1024+0xDC00)
end
end
return concat(t)
end
--~ This is quite a bit faster but at the cost of some memory but if we
--~ do this we will also use it elsewhere so let's not follow this route
--~ now. I might use this method in the plain variant (no caching there)
--~ but then I need a flag that distinguishes between code branches.
--~
--~ local cache = { }
--~
--~ function fonts.map.tounicode16(unicode)
--~ local s = cache[unicode]
--~ if not s then
--~ if unicode < 0x10000 then
--~ s = format("%04X",unicode)
--~ else
--~ s = format("%04X%04X",unicode/1024+0xD800,unicode%1024+0xDC00)
--~ end
--~ cache[unicode] = s
--~ end
--~ return s
--~ end
|