summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/font-otr.lua
diff options
context:
space:
mode:
authorHans Hagen <pragma@wxs.nl>2017-03-20 18:51:53 +0100
committerContext Git Mirror Bot <phg42.2a@gmail.com>2017-03-20 18:51:53 +0100
commit8e0089484acf80066e7393b1245d59dda211be09 (patch)
treea444a174ea8de55816cb4a9c3def00fb4521e7d8 /tex/context/base/mkiv/font-otr.lua
parent8f5c555274eb48fcaaa3d7f340ee77710846fb7e (diff)
downloadcontext-8e0089484acf80066e7393b1245d59dda211be09.tar.gz
2017-03-20 17:38:00
Diffstat (limited to 'tex/context/base/mkiv/font-otr.lua')
-rw-r--r--tex/context/base/mkiv/font-otr.lua747
1 files changed, 412 insertions, 335 deletions
diff --git a/tex/context/base/mkiv/font-otr.lua b/tex/context/base/mkiv/font-otr.lua
index 43a059bb9..eab33f8b6 100644
--- a/tex/context/base/mkiv/font-otr.lua
+++ b/tex/context/base/mkiv/font-otr.lua
@@ -75,12 +75,13 @@ local setmetatableindex = table.setmetatableindex
local formatters = string.formatters
local sortedkeys = table.sortedkeys
local sortedhash = table.sortedhash
-local stripstring = string.strip
+local stripstring = string.nospaces
local utf16_to_utf8_be = utf.utf16_to_utf8_be
local report = logs.reporter("otf reader")
local trace_cmap = false -- only for checking issues
+local trace_cmap_detail = false -- only for checking issues
fonts = fonts or { }
local handlers = fonts.handlers or { }
@@ -703,6 +704,34 @@ local panosewidths = {
-- We implement a reader per table.
+-- helper
+
+local helpers = { }
+readers.helpers = helpers
+
+local function gotodatatable(f,fontdata,tag,criterium)
+ if criterium and f then
+ local datatable = fontdata.tables[tag]
+ if datatable then
+ local tableoffset = datatable.offset
+ setposition(f,tableoffset)
+ return tableoffset
+ end
+ end
+end
+
+local function setvariabledata(fontdata,tag,data)
+ local variabledata = fontdata.variabledata
+ if variabledata then
+ variabledata[tag] = data
+ else
+ fontdata.variabledata = { [tag] = data }
+ end
+end
+
+helpers.gotodatatable = gotodatatable
+helpers.setvariabledata = setvariabledata
+
-- The name table is probably the first one to load. After all this one provides
-- useful information about what we deal with. The complication is that we need
-- to filter the best one available.
@@ -718,14 +747,13 @@ local platformnames = {
}
function readers.name(f,fontdata,specification)
- local datatable = fontdata.tables.name
- if datatable then
- setposition(f,datatable.offset)
+ local tableoffset = gotodatatable(f,fontdata,"name",true)
+ if tableoffset then
local format = readushort(f)
local nofnames = readushort(f)
local offset = readushort(f)
-- we can also provide a raw list as extra, todo as option
- local start = datatable.offset + offset
+ local start = tableoffset + offset
local namelists = {
unicode = { },
windows = { },
@@ -748,25 +776,15 @@ function readers.name(f,fontdata,specification)
if encoding and language then
local index = readushort(f)
local name = reservednames[index]
- if name then
- namelist[#namelist+1] = {
- platform = platform,
- encoding = encoding,
- language = language,
- name = name,
- length = readushort(f),
- offset = start + readushort(f),
- }
- else
-namelist[#namelist+1] = {
- platform = platform,
- encoding = encoding,
- language = language,
- length = readushort(f),
- offset = start + readushort(f),
-}
--- skipshort(f,2)
- end
+ namelist[#namelist+1] = {
+ platform = platform,
+ encoding = encoding,
+ language = language,
+ name = name,
+ index = index,
+ length = readushort(f),
+ offset = start + readushort(f),
+ }
else
skipshort(f,3)
end
@@ -803,6 +821,7 @@ namelist[#namelist+1] = {
for i=1,#namelist do
local name = namelist[i]
local nametag = name.name
+ local index = name.index
if not done[nametag or i] then
local encoding = name.encoding
local language = name.language
@@ -824,7 +843,7 @@ namelist[#namelist+1] = {
language = language,
}
end
- extras[i-1] = content
+ extras[index] = content
done[nametag or i] = true
end
end
@@ -896,9 +915,8 @@ end
-- properties table afterwards.
readers["os/2"] = function(f,fontdata)
- local datatable = fontdata.tables["os/2"]
- if datatable then
- setposition(f,datatable.offset)
+ local tableoffset = gotodatatable(f,fontdata,"os/2",true)
+ if tableoffset then
local version = readushort(f)
local windowsmetrics = {
version = version,
@@ -957,9 +975,8 @@ readers["os/2"] = function(f,fontdata)
end
readers.head = function(f,fontdata)
- local datatable = fontdata.tables.head
- if datatable then
- setposition(f,datatable.offset)
+ local tableoffset = gotodatatable(f,fontdata,"head",true)
+ if tableoffset then
local fontheader = {
version = readfixed(f),
revision = readfixed(f),
@@ -990,68 +1007,60 @@ end
-- variables are not used but nofmetrics is quite important.
readers.hhea = function(f,fontdata,specification)
- if specification.details then
- local datatable = fontdata.tables.hhea
- if datatable then
- setposition(f,datatable.offset)
- fontdata.horizontalheader = {
- version = readfixed(f), -- two ushorts: major minor
- ascender = readfword(f),
- descender = readfword(f),
- linegap = readfword(f),
- maxadvancewidth = readufword(f),
- minleftsidebearing = readfword(f),
- minrightsidebearing = readfword(f),
- maxextent = readfword(f),
- caretsloperise = readshort(f),
- caretsloperun = readshort(f),
- caretoffset = readshort(f),
- reserved_1 = readshort(f),
- reserved_2 = readshort(f),
- reserved_3 = readshort(f),
- reserved_4 = readshort(f),
- metricdataformat = readshort(f),
- nofmetrics = readushort(f),
- }
- else
- fontdata.horizontalheader = {
- nofmetrics = 0,
- }
- end
+ local tableoffset = gotodatatable(f,fontdata,"hhea",specification.details)
+ if tableoffset then
+ fontdata.horizontalheader = {
+ version = readfixed(f), -- two ushorts: major minor
+ ascender = readfword(f),
+ descender = readfword(f),
+ linegap = readfword(f),
+ maxadvancewidth = readufword(f),
+ minleftsidebearing = readfword(f),
+ minrightsidebearing = readfword(f),
+ maxextent = readfword(f),
+ caretsloperise = readshort(f),
+ caretsloperun = readshort(f),
+ caretoffset = readshort(f),
+ reserved_1 = readshort(f),
+ reserved_2 = readshort(f),
+ reserved_3 = readshort(f),
+ reserved_4 = readshort(f),
+ metricdataformat = readshort(f),
+ nofmetrics = readushort(f),
+ }
+ else
+ fontdata.horizontalheader = {
+ nofmetrics = 0,
+ }
end
end
readers.vhea = function(f,fontdata,specification)
- if specification.details then
- local datatable = fontdata.tables.vhea
- if datatable then
- setposition(f,datatable.offset)
- local version = readfixed(f)
- fontdata.verticalheader = {
- version = version,
- ascender = readfword(f),
- descender = readfword(f),
- linegap = readfword(f),
- maxadvanceheight = readufword(f),
- mintopsidebearing = readfword(f),
- minbottomsidebearing = readfword(f),
- maxextent = readfword(f),
- caretsloperise = readshort(f),
- caretsloperun = readshort(f),
- caretoffset = readshort(f),
- reserved_1 = readshort(f),
- reserved_2 = readshort(f),
- reserved_3 = readshort(f),
- reserved_4 = readshort(f),
- metricdataformat = readshort(f),
- nofmetrics = readushort(f),
- }
--- inspect(fontdata.verticalheader)
- else
- fontdata.verticalheader = {
- nofmetrics = 0,
- }
- end
+ local tableoffset = gotodatatable(f,fontdata,"vhea",specification.details)
+ if tableoffset then
+ fontdata.verticalheader = {
+ version = readfixed(f),
+ ascender = readfword(f),
+ descender = readfword(f),
+ linegap = readfword(f),
+ maxadvanceheight = readufword(f),
+ mintopsidebearing = readfword(f),
+ minbottomsidebearing = readfword(f),
+ maxextent = readfword(f),
+ caretsloperise = readshort(f),
+ caretsloperun = readshort(f),
+ caretoffset = readshort(f),
+ reserved_1 = readshort(f),
+ reserved_2 = readshort(f),
+ reserved_3 = readshort(f),
+ reserved_4 = readshort(f),
+ metricdataformat = readshort(f),
+ nofmetrics = readushort(f),
+ }
+ else
+ fontdata.verticalheader = {
+ nofmetrics = 0,
+ }
end
end
@@ -1061,44 +1070,40 @@ end
-- fontdata.maximumprofile can be bad
readers.maxp = function(f,fontdata,specification)
- if specification.details then
- local datatable = fontdata.tables.maxp
- if datatable then
- setposition(f,datatable.offset)
- local version = readfixed(f)
- local nofglyphs = readushort(f)
- fontdata.nofglyphs = nofglyphs
- if version == 0.5 then
- fontdata.maximumprofile = {
- version = version,
- nofglyphs = nofglyphs,
- }
- return
- elseif version == 1.0 then
- fontdata.maximumprofile = {
- version = version,
- nofglyphs = nofglyphs,
- points = readushort(f),
- contours = readushort(f),
- compositepoints = readushort(f),
- compositecontours = readushort(f),
- zones = readushort(f),
- twilightpoints = readushort(f),
- storage = readushort(f),
- functiondefs = readushort(f),
- instructiondefs = readushort(f),
- stackelements = readushort(f),
- sizeofinstructions = readushort(f),
- componentelements = readushort(f),
- componentdepth = readushort(f),
- }
- return
- end
+ local tableoffset = gotodatatable(f,fontdata,"maxp",specification.details)
+ if tableoffset then
+ local version = readfixed(f)
+ local nofglyphs = readushort(f)
+ fontdata.nofglyphs = nofglyphs
+ if version == 0.5 then
+ fontdata.maximumprofile = {
+ version = version,
+ nofglyphs = nofglyphs,
+ }
+ elseif version == 1.0 then
+ fontdata.maximumprofile = {
+ version = version,
+ nofglyphs = nofglyphs,
+ points = readushort(f),
+ contours = readushort(f),
+ compositepoints = readushort(f),
+ compositecontours = readushort(f),
+ zones = readushort(f),
+ twilightpoints = readushort(f),
+ storage = readushort(f),
+ functiondefs = readushort(f),
+ instructiondefs = readushort(f),
+ stackelements = readushort(f),
+ sizeofinstructions = readushort(f),
+ componentelements = readushort(f),
+ componentdepth = readushort(f),
+ }
+ else
+ fontdata.maximumprofile = {
+ version = version,
+ nofglyphs = 0,
+ }
end
- fontdata.maximumprofile = {
- version = version,
- nofglyphs = 0,
- }
end
end
@@ -1106,86 +1111,78 @@ end
-- course).
readers.hmtx = function(f,fontdata,specification)
- if specification.glyphs then
- local datatable = fontdata.tables.hmtx
- if datatable then
- setposition(f,datatable.offset)
- local horizontalheader = fontdata.horizontalheader
- local nofmetrics = horizontalheader.nofmetrics
- local glyphs = fontdata.glyphs
- local nofglyphs = fontdata.nofglyphs
- local width = 0 -- advance
- local leftsidebearing = 0
- for i=0,nofmetrics-1 do
- local glyph = glyphs[i]
- width = readshort(f)
- leftsidebearing = readshort(f)
- if width ~= 0 then
- glyph.width = width
- end
- -- if leftsidebearing ~= 0 then
- -- glyph.lsb = leftsidebearing
- -- end
+ local tableoffset = gotodatatable(f,fontdata,"hmtx",specification.glyphs)
+ if tableoffset then
+ local horizontalheader = fontdata.horizontalheader
+ local nofmetrics = horizontalheader.nofmetrics
+ local glyphs = fontdata.glyphs
+ local nofglyphs = fontdata.nofglyphs
+ local width = 0 -- advance
+ local leftsidebearing = 0
+ for i=0,nofmetrics-1 do
+ local glyph = glyphs[i]
+ width = readshort(f)
+ leftsidebearing = readshort(f)
+ if width ~= 0 then
+ glyph.width = width
end
- -- The next can happen in for instance a monospace font or in a cjk font
- -- with fixed widths.
- for i=nofmetrics,nofglyphs-1 do
- local glyph = glyphs[i]
- if width ~= 0 then
- glyph.width = width
- end
- -- if leftsidebearing ~= 0 then
- -- glyph.lsb = leftsidebearing
- -- end
+ -- if leftsidebearing ~= 0 then
+ -- glyph.lsb = leftsidebearing
+ -- end
+ end
+ -- The next can happen in for instance a monospace font or in a cjk font
+ -- with fixed widths.
+ for i=nofmetrics,nofglyphs-1 do
+ local glyph = glyphs[i]
+ if width ~= 0 then
+ glyph.width = width
end
+ -- if leftsidebearing ~= 0 then
+ -- glyph.lsb = leftsidebearing
+ -- end
end
+ -- hm, there can be a lsb here
end
end
readers.vmtx = function(f,fontdata,specification)
- if specification.glyphs then
- local datatable = fontdata.tables.vmtx
- if datatable then
- setposition(f,datatable.offset)
- local verticalheader = fontdata.verticalheader
- local nofmetrics = verticalheader.nofmetrics
- local glyphs = fontdata.glyphs
- local nofglyphs = fontdata.nofglyphs
- local vheight = 0
- local vdefault = verticalheader.ascender + verticalheader.descender
- local topsidebearing = 0
- for i=0,nofmetrics-1 do
- local glyph = glyphs[i]
- vheight = readshort(f)
- topsidebearing = readshort(f)
- if vheight ~= 0 and vheight ~= vdefault then
- glyph.vheight = vheight
- end
- -- if topsidebearing ~= 0 then
- -- glyph.tsb = topsidebearing
- -- end
+ local tableoffset = gotodatatable(f,fontdata,"vmtx",specification.glyphs)
+ if tableoffset then
+ local verticalheader = fontdata.verticalheader
+ local nofmetrics = verticalheader.nofmetrics
+ local glyphs = fontdata.glyphs
+ local nofglyphs = fontdata.nofglyphs
+ local vheight = 0
+ local vdefault = verticalheader.ascender + verticalheader.descender
+ local topsidebearing = 0
+ for i=0,nofmetrics-1 do
+ local glyph = glyphs[i]
+ vheight = readshort(f)
+ topsidebearing = readshort(f)
+ if vheight ~= 0 and vheight ~= vdefault then
+ glyph.vheight = vheight
end
- -- The next can happen in for instance a monospace font or in a cjk font
- -- with fixed heights.
- for i=nofmetrics,nofglyphs-1 do
- local glyph = glyphs[i]
- if vheight ~= 0 and vheight ~= vdefault then
- glyph.vheight = vheight
- end
- -- if topsidebearing ~= 0 then
- -- glyph.tsb = topsidebearing
- -- end
+ -- if topsidebearing ~= 0 then
+ -- glyph.tsb = topsidebearing
+ -- end
+ end
+ -- The next can happen in for instance a monospace font or in a cjk font
+ -- with fixed heights.
+ for i=nofmetrics,nofglyphs-1 do
+ local glyph = glyphs[i]
+ if vheight ~= 0 and vheight ~= vdefault then
+ glyph.vheight = vheight
end
+ -- if topsidebearing ~= 0 then
+ -- glyph.tsb = topsidebearing
+ -- end
end
end
end
readers.vorg = function(f,fontdata,specification)
if specification.glyphs then
- local datatable = fontdata.tables.vorg
- if datatable then
- report("todo: %s","vorg")
- end
+ -- reportskippedtable("vorg")
end
end
@@ -1194,9 +1191,8 @@ end
-- description is somewhat fuzzy but it is a hybrid with overloads.
readers.post = function(f,fontdata,specification)
- local datatable = fontdata.tables.post
- if datatable then
- setposition(f,datatable.offset)
+ local tableoffset = gotodatatable(f,fontdata,"post",true)
+ if tableoffset then
local version = readfixed(f)
fontdata.postscript = {
version = version,
@@ -1225,7 +1221,7 @@ readers.post = function(f,fontdata,specification)
for i=0,nofglyphs-1 do
local nameindex = readushort(f)
if nameindex >= 258 then
- maxnames = maxnames + 1
+ maxnames = maxnames + 1
nameindex = nameindex - 257
indices[nameindex] = i
else
@@ -1238,7 +1234,7 @@ readers.post = function(f,fontdata,specification)
report("quit post name fetching at %a of %a: %s",i,maxnames,"no index")
break
else
- local length = readbyte(f)
+ local length = readbyte(f)
if length > 0 then
glyphs[mapping].name = readstring(f,length)
else
@@ -1365,7 +1361,7 @@ formatreaders[4] = function(f,fontdata,offset)
elseif offset == 0xFFFF then
-- bad encoding
elseif offset == 0 then
- if trace_cmap then
+ if trace_cmap_detail then
report("format 4.%i segment %2i from %C upto %C at index %H",1,segment,startchar,endchar,(startchar + delta) % 65536)
end
for unicode=startchar,endchar do
@@ -1398,7 +1394,7 @@ formatreaders[4] = function(f,fontdata,offset)
end
else
local shift = (segment-nofsegments+offset/2) - startchar
- if trace_cmap then
+ if trace_cmap_detail then
report("format 4.%i segment %2i from %C upto %C at index %H",0,segment,startchar,endchar,(startchar + delta) % 65536)
end
for unicode=startchar,endchar do
@@ -1448,7 +1444,7 @@ formatreaders[6] = function(f,fontdata,offset)
local count = readushort(f)
local stop = start+count-1
local nofdone = 0
- if trace_cmap then
+ if trace_cmap_detail then
report("format 6 from %C to %C",2,start,stop)
end
for unicode=start,stop do
@@ -1485,7 +1481,7 @@ formatreaders[12] = function(f,fontdata,offset)
local first = readulong(f)
local last = readulong(f)
local index = readulong(f)
- if trace_cmap then
+ if trace_cmap_detail then
report("format 12 from %C to %C starts at index %i",first,last,index)
end
for unicode=first,last do
@@ -1529,7 +1525,7 @@ formatreaders[13] = function(f,fontdata,offset)
local last = readulong(f)
local index = readulong(f)
if first < privateoffset then
- if trace_cmap then
+ if trace_cmap_detail then
report("format 13 from %C to %C get index %i",first,last,index)
end
local glyph = glyphs[index]
@@ -1635,76 +1631,82 @@ local function checkcmap(f,fontdata,records,platform,encoding,format)
local p = platforms[platform]
local e = encodings[p]
local n = reader(f,fontdata,data) or 0
- report("cmap checked: platform %i (%s), encoding %i (%s), format %i, new unicodes %i",platform,p,encoding,e and e[encoding] or "?",format,n)
+ if trace_cmap then
+ report("cmap checked: platform %i (%s), encoding %i (%s), format %i, new unicodes %i",platform,p,encoding,e and e[encoding] or "?",format,n)
+ end
return n
end
function readers.cmap(f,fontdata,specification)
- if specification.glyphs then
- local datatable = fontdata.tables.cmap
- if datatable then
- local tableoffset = datatable.offset
- setposition(f,tableoffset)
- local version = readushort(f)
- local noftables = readushort(f)
- local records = { }
- local unicodecid = false
- local variantcid = false
- local variants = { }
- local duplicates = fontdata.duplicates or { }
- fontdata.duplicates = duplicates
- for i=1,noftables do
- local platform = readushort(f)
- local encoding = readushort(f)
- local offset = readulong(f)
- local record = records[platform]
- if not record then
- records[platform] = {
- [encoding] = {
- offsets = { offset },
- formats = { },
- }
+ local tableoffset = gotodatatable(f,fontdata,"cmap",specification.glyphs)
+ if tableoffset then
+ local version = readushort(f)
+ local noftables = readushort(f)
+ local records = { }
+ local unicodecid = false
+ local variantcid = false
+ local variants = { }
+ local duplicates = fontdata.duplicates or { }
+ fontdata.duplicates = duplicates
+ for i=1,noftables do
+ local platform = readushort(f)
+ local encoding = readushort(f)
+ local offset = readulong(f)
+ local record = records[platform]
+ if not record then
+ records[platform] = {
+ [encoding] = {
+ offsets = { offset },
+ formats = { },
+ }
+ }
+ else
+ local subtables = record[encoding]
+ if not subtables then
+ record[encoding] = {
+ offsets = { offset },
+ formats = { },
}
else
- local subtables = record[encoding]
- if not subtables then
- record[encoding] = {
- offsets = { offset },
- formats = { },
- }
- else
- local offsets = subtables.offsets
- offsets[#offsets+1] = offset
- end
+ local offsets = subtables.offsets
+ offsets[#offsets+1] = offset
end
end
+ end
+ if trace_cmap then
report("found cmaps:")
- for platform, record in sortedhash(records) do
- local p = platforms[platform]
- local e = encodings[p]
- local sp = supported[platform]
- local ps = p or "?"
+ end
+ for platform, record in sortedhash(records) do
+ local p = platforms[platform]
+ local e = encodings[p]
+ local sp = supported[platform]
+ local ps = p or "?"
+ if trace_cmap then
if sp then
report(" platform %i: %s",platform,ps)
else
report(" platform %i: %s (unsupported)",platform,ps)
end
- for encoding, subtables in sortedhash(record) do
- local se = sp and sp[encoding]
- local es = e and e[encoding] or "?"
+ end
+ for encoding, subtables in sortedhash(record) do
+ local se = sp and sp[encoding]
+ local es = e and e[encoding] or "?"
+ if trace_cmap then
if se then
report(" encoding %i: %s",encoding,es)
else
report(" encoding %i: %s (unsupported)",encoding,es)
end
- local offsets = subtables.offsets
- local formats = subtables.formats
- for i=1,#offsets do
- local offset = tableoffset + offsets[i]
- setposition(f,offset)
- formats[readushort(f)] = offset
- end
- record[encoding] = formats
+ end
+ local offsets = subtables.offsets
+ local formats = subtables.formats
+ for i=1,#offsets do
+ local offset = tableoffset + offsets[i]
+ setposition(f,offset)
+ formats[readushort(f)] = offset
+ end
+ record[encoding] = formats
+ if trace_cmap then
local list = sortedkeys(formats)
for i=1,#list do
if not (se and se[list[i]]) then
@@ -1714,27 +1716,27 @@ function readers.cmap(f,fontdata,specification)
report(" formats: % t",list)
end
end
- --
- local ok = false
- for i=1,#sequence do
- local si = sequence[i]
- local sp, se, sf = si[1], si[2], si[3]
- if checkcmap(f,fontdata,records,sp,se,sf) > 0 then
- ok = true
- end
- end
- if not ok then
- report("no useable unicode cmap found")
+ end
+ --
+ local ok = false
+ for i=1,#sequence do
+ local si = sequence[i]
+ local sp, se, sf = si[1], si[2], si[3]
+ if checkcmap(f,fontdata,records,sp,se,sf) > 0 then
+ ok = true
end
- --
- fontdata.cidmaps = {
- version = version,
- noftables = noftables,
- records = records,
- }
- else
- fontdata.cidmaps = { }
end
+ if not ok then
+ report("no useable unicode cmap found")
+ end
+ --
+ fontdata.cidmaps = {
+ version = version,
+ noftables = noftables,
+ records = records,
+ }
+ else
+ fontdata.cidmaps = { }
end
end
@@ -1778,42 +1780,39 @@ end
-- can also be available. Todo: we need a 'fake' lookup for this (analogue to ff).
function readers.kern(f,fontdata,specification)
- if specification.kerns then
- local datatable = fontdata.tables.kern
- if datatable then
- setposition(f,datatable.offset)
- local version = readushort(f)
- local noftables = readushort(f)
- for i=1,noftables do
- local version = readushort(f)
- local length = readushort(f)
- local coverage = readushort(f)
- -- bit 8-15 of coverage: format 0 or 2
- local format = bit32.rshift(coverage,8) -- is this ok?
- if format == 0 then
- local nofpairs = readushort(f)
- local searchrange = readushort(f)
- local entryselector = readushort(f)
- local rangeshift = readushort(f)
- local kerns = { }
- local glyphs = fontdata.glyphs
- for i=1,nofpairs do
- local left = readushort(f)
- local right = readushort(f)
- local kern = readfword(f)
- local glyph = glyphs[left]
- local kerns = glyph.kerns
- if kerns then
- kerns[right] = kern
- else
- glyph.kerns = { [right] = kern }
- end
+ local tableoffset = gotodatatable(f,fontdata,"kern",specification.kerns)
+ if tableoffset then
+ local version = readushort(f)
+ local noftables = readushort(f)
+ for i=1,noftables do
+ local version = readushort(f)
+ local length = readushort(f)
+ local coverage = readushort(f)
+ -- bit 8-15 of coverage: format 0 or 2
+ local format = bit32.rshift(coverage,8) -- is this ok?
+ if format == 0 then
+ local nofpairs = readushort(f)
+ local searchrange = readushort(f)
+ local entryselector = readushort(f)
+ local rangeshift = readushort(f)
+ local kerns = { }
+ local glyphs = fontdata.glyphs
+ for i=1,nofpairs do
+ local left = readushort(f)
+ local right = readushort(f)
+ local kern = readfword(f)
+ local glyph = glyphs[left]
+ local kerns = glyph.kerns
+ if kerns then
+ kerns[right] = kern
+ else
+ glyph.kerns = { [right] = kern }
end
- elseif format == 2 then
- report("todo: kern classes")
- else
- report("todo: kerns")
end
+ elseif format == 2 then
+ report("todo: kern classes")
+ else
+ report("todo: kerns")
end
end
end
@@ -1847,7 +1846,7 @@ end
-- some properties in order to read following tables. When details is true we also
-- initialize the glyphs data.
-local function getinfo(maindata,sub,platformnames,rawfamilynames,metricstoo)
+local function getinfo(maindata,sub,platformnames,rawfamilynames,metricstoo,instancenames)
local fontdata = sub and maindata.subfonts and maindata.subfonts[sub] or maindata
local names = fontdata.names
local info = nil
@@ -1872,6 +1871,25 @@ local function getinfo(maindata,sub,platformnames,rawfamilynames,metricstoo)
if not familyname then familyname = family end
if not subfamilyname then subfamilyname = subfamily end
end
+ if platformnames then
+ platformnames = fontdata.platformnames
+ end
+ if instancenames then
+ local variabledata = fontdata.variabledata
+ if variabledata then
+ local instances = variabledata and variabledata.instances
+ if instances then
+ instancenames = { }
+ for i=1,#instances do
+ instancenames[i] = lower(stripstring(instances[i].subfamily))
+ end
+ else
+ instancenames = nil
+ end
+ else
+ instancenames = nil
+ end
+ end
info = { -- we inherit some inconsistencies/choices from ff
subfontindex = fontdata.subfontindex or sub or 0,
-- filename = filename,
@@ -1902,7 +1920,8 @@ local function getinfo(maindata,sub,platformnames,rawfamilynames,metricstoo)
capheight = metrics.capheight, -- not always present and probably crap
ascender = metrics.typoascender,
descender = metrics.typodescender,
- platformnames = platformnames and fontdata.platformnames or nil,
+ platformnames = platformnames or nil,
+ instancenames = instancenames or nil,
}
if metricstoo then
local keys = {
@@ -1960,6 +1979,7 @@ local function loadtables(f,specification,offset)
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)))
@@ -1975,7 +1995,8 @@ local function loadtables(f,specification,offset)
length = length,
}
end
- if tables.cff then
+ fontdata.foundtables = sortedkeys(tables)
+ if tables.cff or tables.cff2 then
fontdata.format = "opentype"
else
fontdata.format = "truetype"
@@ -1996,23 +2017,35 @@ local function prepareglyps(fontdata)
fontdata.mapping = { }
end
-local function readtable(tag,f,fontdata,specification)
+local function readtable(tag,f,fontdata,specification,...)
local reader = readers[tag]
if reader then
-- local t = os.clock()
- reader(f,fontdata,specification)
+ reader(f,fontdata,specification,...)
-- report("reading table %a took %0.4f seconds",tag,os.clock()-t)
end
end
+local variablefonts_supported = context and true or false
+
local function readdata(f,offset,specification)
+
local fontdata = loadtables(f,specification,offset)
+
if specification.glyphs then
prepareglyps(fontdata)
end
- --
+
+ if not variablefonts_supported then
+ specification.instance = nil
+ specification.variable = nil
+ specification.factors = nil
+ end
+
+ fontdata.temporary = { }
+
readtable("name",f,fontdata,specification)
- --
+
local askedname = specification.askedname
if askedname then
local fullname = getname(fontdata,"fullname") or ""
@@ -2022,7 +2055,35 @@ local function readdata(f,offset,specification)
return -- keep searching
end
end
- --
+
+ readtable("stat",f,fontdata,specification)
+ readtable("avar",f,fontdata,specification)
+ readtable("fvar",f,fontdata,specification)
+
+ if variablefonts_supported then
+
+ if not specification.factors then
+ local instance = specification.instance
+ if type(instance) == "string" then
+ local factors = helpers.getfactors(fontdata,instance)
+ specification.factors = factors
+ fontdata.factors = factors
+ fontdata.instance = instance
+ report("user instance: %s, factors: % t",instance,factors)
+ end
+ end
+ if not fontdata.factors then
+ if fontdata.variabledata then
+ local factors = helpers.getfactors(fontdata,true)
+ specification.factors = factors
+ fontdata.factors = factors
+ fontdata.instance = instance
+ report("font instance: %s, factors: % t",instance,factors)
+ end
+ end
+
+ end
+
readtable("os/2",f,fontdata,specification)
readtable("head",f,fontdata,specification)
readtable("maxp",f,fontdata,specification)
@@ -2032,32 +2093,35 @@ local function readdata(f,offset,specification)
readtable("vmtx",f,fontdata,specification)
readtable("vorg",f,fontdata,specification)
readtable("post",f,fontdata,specification)
+
+ readtable("mvar",f,fontdata,specification)
+ readtable("hvar",f,fontdata,specification)
+ readtable("vvar",f,fontdata,specification)
+
+ readtable("gdef",f,fontdata,specification)
+
readtable("cff" ,f,fontdata,specification)
+ readtable("cff2",f,fontdata,specification)
+
readtable("cmap",f,fontdata,specification)
- readtable("loca",f,fontdata,specification)
- readtable("glyf",f,fontdata,specification)
+ readtable("loca",f,fontdata,specification) -- maybe load it in glyf
+ readtable("glyf",f,fontdata,specification) -- loads gvar
+
readtable("colr",f,fontdata,specification)
readtable("cpal",f,fontdata,specification)
readtable("svg" ,f,fontdata,specification)
+
readtable("kern",f,fontdata,specification)
- readtable("gdef",f,fontdata,specification)
readtable("gsub",f,fontdata,specification)
readtable("gpos",f,fontdata,specification)
+
readtable("math",f,fontdata,specification)
- --
- -- there are no proper fonts yet:
- --
- readtable("fvar",f,fontdata,specification) -- probably
- readtable("hvar",f,fontdata,specification)
- readtable("vvar",f,fontdata,specification)
- readtable("mvar",f,fontdata,specification) -- probably
- readtable("vorg",f,fontdata,specification)
- --
+
fontdata.locations = nil
fontdata.tables = nil
fontdata.cidmaps = nil
fontdata.dictionaries = nil
- -- fontdata.cff = nil
+ -- fontdata.cff = nil
return fontdata
end
@@ -2132,7 +2196,7 @@ local function loadfontdata(specification)
end
end
-local function loadfont(specification,n)
+local function loadfont(specification,n,instance)
if type(specification) == "string" then
specification = {
filename = specification,
@@ -2147,6 +2211,7 @@ local function loadfont(specification,n)
-- true or number:
subfont = n or true,
tounicode = false,
+ instance = instance
}
end
-- if shapes only then
@@ -2162,6 +2227,10 @@ local function loadfont(specification,n)
if specification.platformnames then
specification.platformnames = true -- not really used any more
end
+ if specification.instance or instance then
+ specification.variable = true
+ specification.instance = specification.instance or instance
+ end
local function message(str)
report("fatal error in file %a: %s\n%s",specification.filename,str,debug.traceback())
end
@@ -2173,11 +2242,14 @@ end
-- we need even less, but we can have a 'detail' variant
-function readers.loadshapes(filename,n)
+function readers.loadshapes(filename,n,instance,streams)
local fontdata = loadfont {
filename = filename,
shapes = true,
+ streams = streams,
+ variable = true,
subfont = n,
+ instance = instance,
}
if fontdata then
-- easier on luajit but still we can hit the 64 K stack constants issue
@@ -2202,7 +2274,7 @@ function readers.loadshapes(filename,n)
}
end
-function readers.loadfont(filename,n)
+function readers.loadfont(filename,n,instance)
local fontdata = loadfont {
filename = filename,
glyphs = true,
@@ -2212,9 +2284,9 @@ function readers.loadfont(filename,n)
-- kerns = true,
-- globalkerns = true, -- only for testing, e.g. cambria has different gpos and kern
subfont = n,
+ instance = instance,
}
if fontdata then
- --
return {
tableversion = tableversion,
creator = "context mkiv",
@@ -2224,11 +2296,13 @@ function readers.loadfont(filename,n)
descriptions = fontdata.descriptions,
format = fontdata.format,
goodies = { },
- metadata = getinfo(fontdata,n,false,false,true), -- no platformnames here !
+ metadata = getinfo(fontdata,n,false,false,true,true), -- no platformnames here !
properties = {
hasitalics = fontdata.hasitalics or false,
maxcolorclass = fontdata.maxcolorclass,
hascolor = fontdata.hascolor or false,
+ instance = fontdata.instance,
+ factors = fontdata.factors,
},
resources = {
-- filename = fontdata.filename,
@@ -2247,7 +2321,8 @@ function readers.loadfont(filename,n)
mathconstants = fontdata.mathconstants,
colorpalettes = fontdata.colorpalettes,
svgshapes = fontdata.svgshapes,
- variable = fontdata.variable,
+ variabledata = fontdata.variabledata,
+ foundtables = fontdata.foundtables,
},
}
end
@@ -2259,6 +2334,7 @@ function readers.getinfo(filename,specification) -- string, nil|number|table
local subfont = nil
local platformnames = false
local rawfamilynames = false
+ local instancenames = true
if type(specification) == "table" then
subfont = tonumber(specification.subfont)
platformnames = specification.platformnames
@@ -2270,20 +2346,21 @@ function readers.getinfo(filename,specification) -- string, nil|number|table
filename = filename,
details = true,
platformnames = platformnames,
+ instancenames = true,
-- rawfamilynames = rawfamilynames,
}
if fontdata then
local subfonts = fontdata.subfonts
if not subfonts then
- return getinfo(fontdata,nil,platformnames,rawfamilynames)
+ return getinfo(fontdata,nil,platformnames,rawfamilynames,false,instancenames)
elseif not subfont then
local info = { }
for i=1,#subfonts do
- info[i] = getinfo(fontdata,i,platformnames,rawfamilynames)
+ info[i] = getinfo(fontdata,i,platformnames,rawfamilynames,false,instancenames)
end
return info
elseif subfont >= 1 and subfont <= #subfonts then
- return getinfo(fontdata,subfont,platformnames,rawfamilynames)
+ return getinfo(fontdata,subfont,platformnames,rawfamilynames,false,instancenames)
else
return {
filename = filename,