Skip to content

Instantly share code, notes, and snippets.

@doraTeX
Created October 4, 2016 17:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save doraTeX/a802bfa15ae094f183ed1f3840a2c357 to your computer and use it in GitHub Desktop.
Save doraTeX/a802bfa15ae094f183ed1f3840a2c357 to your computer and use it in GitHub Desktop.
Show information of a TTC file (derived from zrdecompttc.lua https://gist.github.com/zr-tex8r/7058922 )
-- ttcinfo.lua
prog_name = "ttcinfo"
version = "0.1"
mod_date = "2016/10/05"
verbose = true
----------------------------------------
ttc_file, ttf_base, ttf_ext, ttf_idb = nil
----------------------------------------
do
local reader_meta = {
__tostring = function(self)
return "reader("..self.name..")"
end;
__index = {
cdata = function(self, ofs, len)
return make_cdata(self:read(ofs, len))
end;
read = function(self, ofs, len)
self.file:seek("set", ofs)
local data = self.file:read(len)
sure(data:len() == len, 1)
return data
end;
close = function(self)
self.file:close()
end;
}
}
function make_reader(fname)
local file = io.open(fname, "rb")
sure(file, "cannot open for input", fname)
return setmetatable({
name = fname, file = file
}, reader_meta)
end
end
----------------------------------------
do
local cdata_meta = {
__tostring = function(self)
return "cdata(pos="..self._pos..")"
end;
__index = {
pos = function(self, p)
if not p then return self._pos end
self._pos = p
return self
end;
_unum = function(self, b)
local v, data = 0, self.data
sure(#data >= self._pos + b, 11)
for i = 1, b do
self._pos = self._pos + 1
v = v * 256 + data:byte(self._pos)
end
return v
end;
_setunum = function(self, b, v)
local t, data = {}, self.data
t[1] = data:sub(1, self._pos)
self._pos = self._pos + b
sure(#data >= self._pos, 12)
t[b + 2] = data:sub(self._pos + 1)
for i = 1, b do
t[b + 2 - i] = string.char(v % 256)
v = math.floor(v / 256)
end
self.data = table.concat(t, "")
return self
end;
str = function(self, b)
local data = self.data
self._pos = self._pos + b
sure(#data >= self._pos, 13)
return data:sub(self._pos - b + 1, self._pos)
end;
setstr = function(self, s)
local t, data = {}, self.data
t[1], t[2] = data:sub(1, self._pos), s
self._pos = self._pos + #s
sure(#data >= self._pos, 14)
t[3] = data:sub(self._pos + 1)
self.data = table.concat(t, "")
return self
end;
ushort = function(self)
return self:_unum(2)
end;
ulong = function(self)
return self:_unum(4)
end;
setulong = function(self, v)
return self:_setunum(4, v)
end;
ulongs = function(self, num)
local t = {}
for i = 1, num do
t[i] = self:_unum(4)
end
return t
end;
}
}
function make_cdata(data)
return setmetatable({
data = data, _pos = 0
}, cdata_meta)
end
function empty_cdata(len)
return make_cdata(("\0"):rep(len))
end
end
----------------------------------------
do
local RDX = 0x10000 * 0x10000
local MAGIC = 0x5F0F3CF5
local SGOAL = 0xB1B0AFBA
function ttf_offset(reader)
local cd = reader:cdata(0, 12)
local tag = cd:str(4); info("tag", tag)
sure(tag == "ttcf", "TTC header missing")
local ver = cd:ulong(); info("version", ver)
local num = cd:ulong(); info("#fonts", num)
cd = reader:cdata(12, 4 * num)
local res = cd:ulongs(num); info("offset", stt(res))
return res
end
local function check_sum(cd)
local sum, len = 0, #cd.data
sure(len % 4 == 0, 19)
cd:pos(0)
for i = 1, len / 4 do
sum = sum + cd:ulong()
if sum >= RDX then sum = sum - RDX end
end
return sum
end
local function madd(a, b)
local sum = a + b
if sum >= RDX then sum = sum - RDX end
return sum
end
local function msub(a, b)
local sum = a - b
if sum < 0 then sum = sum + RDX end
return sum
end
function ttf_flavor(reader, fofs)
local tag = reader:cdata(fofs, 4):str(4)
return (tag == "OTTO") and "otf" or "ttf"
end
end
----------------------------------------
do
local stt_meta = {
__tostring = function(self)
return "{"..concat(self, ",").."}"
end
}
function stt(tbl)
return setmetatable(tbl, stt_meta)
end
function concat(tbl, ...)
local t = {}
for i = 1, #tbl do t[i] = tostring(tbl[i]) end
return table.concat(t, ...)
end
function info(...)
if not verbose then return end
local t = { prog_name, ... }
io.stderr:write(concat(t, ": ").."\n")
end
function abort(...)
verbose = true; info(...)
os.exit(-1)
end
function sure(val, a1, ...)
if val then return val end
if type(a1) == "number" then
a1 = "error("..a1..")"
end
abort(a1, ...)
end
end
----------------------------------------
do
local suffix = "_1"
local function show_usage()
io.stdout:write(([[
This is %s v%s <%s> by 'doraTeX' (derived from zrdecompttc.lua by 'ZR')
Usage: %s[.lua] <ttc_file>
]]):format(prog_name, version, mod_date, prog_name))
os.exit(0)
end
local function out_name()
local base, t, ext = ttf_base
if base then
local _, _, b, e = base:find("^(.+)%.([a-zA-Z]+)$")
if b then base, ext = b, e end
t = not (base:find("%d"))
else
local ps = sure(ttc_file:find("[^/\\]+$"), 1)
base = ttc_file:sub(ps)
t = (base:sub(-4):lower() == ".ttc") and -5 or -1
base, t = base:sub(1, t), true
end
if t then base = base..suffix end
local _, _, h, i, t = base:find("^(.-)(%d+)(%D*)$")
base = h:gsub("%%","%%%%").."%0"..(#i).."d"..
t:gsub("%%","%%%%")..".%s"
return base, i - 1, ext
end
function read_option()
if #arg == 0 then show_usage() end
local idx = 1
while idx <= #arg do
local opt = arg[idx]
if opt:sub(1, 1) ~= "-" then break end
if opt == "-h" or opt == "--help" then
show_usage()
else abort("invalid option", opt)
end
idx = idx + 1
end
sure(#arg == idx, "wrong number of arguments")
ttc_file = arg[idx]
ttf_base, ttf_idb, ttf_ext = out_name()
end
local function write_open(file)
local ofile = io.open(file, "wb")
sure(ofile, "cannot open for output", file)
return ofile
end
function main()
read_option()
local reader = make_reader(ttc_file)
local tofs = ttf_offset(reader)
for i = 1, #tofs do
local ext = ttf_ext or ttf_flavor(reader, tofs[i])
local ttf_name = ttf_base:format(ttf_idb + i, ext)
info("Font #"..i, ttf_name)
end
reader:close()
end
end
----------------------------------------
main()
-- EOF
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment