-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcharstrings.lua
174 lines (151 loc) · 5.97 KB
/
charstrings.lua
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
digitalkhatt = digitalkhatt or { }
local charstringsCache = {}
local byte, lower, char, gsub = string.byte, string.lower, string.char, string.gsub
local streamreader = utilities.files
local openfile = streamreader.open
local closefile = streamreader.close
----- skipbytes = streamreader.skip
local setposition = streamreader.setposition
local skipshort = streamreader.skipshort
local readbytes = streamreader.readbytes
local readstring = streamreader.readstring
local readbyte = streamreader.readcardinal1 -- 8-bit unsigned integer
local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer
local readuint = streamreader.readcardinal3 -- 24-bit unsigned integer
local readulong = streamreader.readcardinal4 -- 32-bit unsigned integer
----- readchar = streamreader.readinteger1 -- 8-bit signed integer
local readshort = streamreader.readinteger2 -- 16-bit signed integer
local readlong = streamreader.readinteger4 -- 32-bit unsigned integer
local readfixed = streamreader.readfixed4
local read2dot14 = streamreader.read2dot14 -- 16-bit signed fixed number with the low 14 bits of fraction (2.14) (F2DOT14)
local readfword = readshort -- 16-bit signed integer that describes a quantity in FUnits
local readufword = readushort -- 16-bit unsigned integer that describes a quantity in FUnits
local readoffset = readushort
local readcardinaltable = streamreader.readcardinaltable
local readintegertable = streamreader.readintegertable
local setmetatableindex = table.setmetatableindex
local sortedkeys = table.sortedkeys
local sortedhash = table.sortedhash
local stripstring = string.nospaces
local fonts = fonts or { }
local handlers = fonts.handlers or { }
local otf = handlers.otf or { }
local readers = otf.readers or { }
local helpers = readers.helpers
local report = logs.reporter("otf reader")
local function loadtables(f,specification,offset)
if offset then
setposition(f,offset)
end
local tables = { }
local basename = file.basename(specification.filename)
local filesize = specification.filesize or 0
local filetime = specification.filetime
local fontdata = { -- some can/will go
filename = basename,
filesize = filesize,
filetime = filetime,
version = readstring(f,4),
noftables = readushort(f),
searchrange = readushort(f), -- not needed
entryselector = readushort(f), -- not needed
rangeshift = readushort(f), -- not needed
tables = tables,
foundtables = false,
}
for i=1,fontdata.noftables do
local tag = lower(stripstring(readstring(f,4)))
-- local checksum = readulong(f) -- not used
local checksum = readushort(f) * 0x10000 + readushort(f)
local offset = readulong(f)
local length = readulong(f)
if offset + length > filesize then
report("bad %a table in file %a",tag,basename)
end
tables[tag] = {
checksum = checksum,
offset = offset,
length = length,
}
end
-- inspect(tables)
fontdata.foundtables = sortedkeys(tables)
if tables.cff or tables.cff2 then
fontdata.format = "opentype"
else
fontdata.format = "truetype"
end
return fontdata, tables
end
local function prepareglyps(fontdata)
local glyphs = setmetatableindex(function(t,k)
local v = {
-- maybe more defaults
index = k,
}
t[k] = v
return v
end)
fontdata.glyphs = glyphs
fontdata.mapping = { }
end
local function readtable(tag,f,fontdata,specification,...)
local reader = readers[tag]
if reader then
return reader(f,fontdata,specification,...)
end
end
local function readdata(f,offset,specification)
local fontdata, tables = loadtables(f,specification,offset)
readtable("name",f,fontdata,specification)
readtable("stat",f,fontdata,specification)
readtable("avar",f,fontdata,specification)
readtable("fvar",f,fontdata,specification)
specification.digitalkhatt = true
prepareglyps(fontdata)
local data = readtable("dkcff2",f,fontdata,specification)
if data then
return {f = f, specification = specification, data = data, fontdata = fontdata}
end
end
local parsecharstrings = digitalkhatt.parsecharstrings
digitalkhatt.readVarGlyph = function(spec, gid)
local filename = spec.properties.filename
local instance = spec.properties.instance
local charstrings = charstringsCache[filename]
if not charstrings then
local fontspec = {
filename = filename,
shapes = true,
streams = nil,
variable = true,
subfont = nil,
instance = instance,
glyphs = true,
}
local f = openfile(filename,true)
local fileattr = lfs.attributes(filename)
fontspec.filesize = fileattr and fileattr.size or 0
charstrings = readdata(f,0,fontspec)
charstringsCache[filename] = charstrings
end
if charstrings then
local fontdata = charstrings.fontdata
--local variabledata = fontdata.variabledata
--local specification = charstrings.specification
local data = charstrings.data
if type(instance) == "string" then
local factors = helpers.getfactors(fontdata,instance)
if factors then
--specification.factors = factors
fontdata.factors = factors
fontdata.instance = instance
data.digitalkhatt_gid = gid + 1
local glyphs = {}
data.factors = factors --specification.factors
parsecharstrings(false,data,glyphs,true,"cff",nil)
return glyphs[gid]
end
end
end
end