diff options
author | Luigi Scarso <luigi.scarso@gmail.com> | 2019-02-22 23:11:47 +0000 |
---|---|---|
committer | Luigi Scarso <luigi.scarso@gmail.com> | 2019-02-22 23:11:47 +0000 |
commit | 5c6357cdb820b4f628d036ba7b2248f221d50c0b (patch) | |
tree | 6365552f2737faaffe63a395272da242ee2c4f03 /Master/texmf-dist/tex/context/base/mkiv/font-otr.lua | |
parent | b4568bc71e054f3d1fd6404b45d2322631778284 (diff) |
ConTeXt version 2019.02.22 19:35
git-svn-id: svn://tug.org/texlive/trunk@50086 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkiv/font-otr.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/mkiv/font-otr.lua | 275 |
1 files changed, 170 insertions, 105 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/font-otr.lua b/Master/texmf-dist/tex/context/base/mkiv/font-otr.lua index 5bac75052ac..c7ff6b72689 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/font-otr.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/font-otr.lua @@ -25,7 +25,7 @@ if not modules then modules = { } end modules ['font-otr'] = { -- are just a unicode string but it doesn't save that much. It will be an option -- some day. --- Optimizing the widths wil be done anyway as it save quite some on a cjk font +-- Optimizing the widths will be done anyway as it save quite some on a cjk font -- and the existing (old) code if okay. -- todo: more messages (only if really needed) @@ -67,6 +67,7 @@ if not modules then modules = { } end modules ['font-otr'] = { local next, type, tonumber = next, type, tonumber local byte, lower, char, gsub = string.byte, string.lower, string.char, string.gsub +local fullstrip = string.fullstrip local floor, round = math.floor, math.round local P, R, S, C, Cs, Cc, Ct, Carg, Cmt = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.Carg, lpeg.Cmt local lpegmatch = lpeg.match @@ -121,11 +122,47 @@ local read2dot14 = streamreader.read2dot14 -- 16-bit signed fixed num 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 function streamreader.readtag(f) return lower(stripstring(readstring(f,4))) end +local short = 2 +local ushort = 2 +local ulong = 4 + +directives.register("fonts.streamreader",function() + + streamreader = utilities.streams + + openfile = streamreader.open + closefile = streamreader.close + setposition = streamreader.setposition + skipshort = streamreader.skipshort + readbytes = streamreader.readbytes + readstring = streamreader.readstring + readbyte = streamreader.readcardinal1 + readushort = streamreader.readcardinal2 + readuint = streamreader.readcardinal3 + readulong = streamreader.readcardinal4 + readshort = streamreader.readinteger2 + readlong = streamreader.readinteger4 + readfixed = streamreader.readfixed4 + read2dot14 = streamreader.read2dot14 + readfword = readshort + readufword = readushort + readoffset = readushort + readcardinaltable = streamreader.readcardinaltable + readintegertable = streamreader.readintegertable + + function streamreader.readtag(f) + return lower(stripstring(readstring(f,4))) + end + +end) + -- date represented in number of seconds since 12:00 midnight, January 1, 1904. The value is represented as a -- signed 64-bit integer @@ -704,20 +741,30 @@ 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 + local tables = fontdata.tables + if tables then + local datatable = tables[tag] + if datatable then + local tableoffset = datatable.offset + setposition(f,tableoffset) + return tableoffset + end + else + report("no tables") end end end local function reportskippedtable(f,fontdata,tag,criterium) if criterium and f then - local datatable = fontdata.tables[tag] - if datatable then - report("loading of table %a skipped",tag) + local tables = fontdata.tables + if tables then + local datatable = tables[tag] + if datatable then + report("loading of table %a skipped",tag) + end + else + report("no tables") end end end @@ -749,6 +796,16 @@ local platformnames = { compatiblefullname = true, } +local platformextras = { + uniqueid = true, + version = true, + copyright = true, + license = true, + licenseurl = true, + manufacturer = true, + vendorurl = true, +} + function readers.name(f,fontdata,specification) local tableoffset = gotodatatable(f,fontdata,"name",true) if tableoffset then @@ -819,6 +876,18 @@ function readers.name(f,fontdata,specification) -- and extend when we run into it (todo: proper reverse hash) .. we're only -- interested in english anyway -- + local function decoded(platform,encoding,content) + local decoder = decoders[platform] + if decoder then + decoder = decoder[encoding] + end + if decoder then + return decoder(content) + else + return content + end + end + -- local function filter(platform,e,l) local namelist = namelists[platform] for i=1,#namelist do @@ -830,14 +899,7 @@ function readers.name(f,fontdata,specification) local language = name.language if (not e or encoding == e) and (not l or language == l) then setposition(f,name.offset) - local content = readstring(f,name.length) - local decoder = decoders[platform] - if decoder then - decoder = decoder[encoding] - end - if decoder then - content = decoder(content) - end + local content = decoded(platform,encoding,readstring(f,name.length)) if nametag then names[nametag] = { content = content, @@ -864,23 +926,16 @@ function readers.name(f,fontdata,specification) fontdata.extras = extras -- if specification.platformnames then - local collected = { } + local collected = { } + local platformextras = specification.platformextras and platformextras for platform, namelist in next, namelists do local filtered = false for i=1,#namelist do local entry = namelist[i] local name = entry.name - if platformnames[name] then + if platformnames[name] or (platformextras and platformextras[name]) then setposition(f,entry.offset) - local content = readstring(f,entry.length) - local encoding = entry.encoding - local decoder = decoders[platform] - if decoder then - decoder = decoder[encoding] - end - if decoder then - content = decoder(content) - end + local content = decoded(platform,entry.encoding,readstring(f,entry.length)) if filtered then filtered[name] = content else @@ -923,7 +978,7 @@ readers["os/2"] = function(f,fontdata) local version = readushort(f) local windowsmetrics = { version = version, - averagewidth = readshort(f), + averagewidth = readshort(f), -- ushort? weightclass = readushort(f), widthclass = readushort(f), fstype = readushort(f), @@ -953,7 +1008,7 @@ readers["os/2"] = function(f,fontdata) if version >= 1 then windowsmetrics.codepageranges = { readulong(f), readulong(f) } end - if version >= 3 then + if version >= 2 then windowsmetrics.xheight = readshort(f) windowsmetrics.capheight = readshort(f) windowsmetrics.defaultchar = readushort(f) @@ -980,24 +1035,28 @@ end readers.head = function(f,fontdata) local tableoffset = gotodatatable(f,fontdata,"head",true) if tableoffset then + local version = readulong(f) + local fontversion = readulong(f) local fontheader = { - version = readfixed(f), - revision = readfixed(f), - checksum = readulong(f), - magic = readulong(f), - flags = readushort(f), - units = readushort(f), - created = readlongdatetime(f), - modified = readlongdatetime(f), - xmin = readshort(f), - ymin = readshort(f), - xmax = readshort(f), - ymax = readshort(f), - macstyle = readushort(f), - smallpixels = readushort(f), - directionhint = readshort(f), - indextolocformat = readshort(f), - glyphformat = readshort(f), + version = version, + fontversion = number.to16dot16(fontversion), + fontversionnumber = fontversion, + -- checksum = readulong(f), + checksum = readushort(f) * 0x10000 + readushort(f), + magic = readulong(f), + flags = readushort(f), + units = readushort(f), + created = readlongdatetime(f), + modified = readlongdatetime(f), + xmin = readshort(f), + ymin = readshort(f), + xmax = readshort(f), + ymax = readshort(f), + macstyle = readushort(f), + smallpixels = readushort(f), + directionhint = readshort(f), + indextolocformat = readshort(f), + glyphformat = readshort(f), } fontdata.fontheader = fontheader else @@ -1013,7 +1072,7 @@ readers.hhea = function(f,fontdata,specification) local tableoffset = gotodatatable(f,fontdata,"hhea",specification.details) if tableoffset then fontdata.horizontalheader = { - version = readfixed(f), -- two ushorts: major minor + version = readulong(f), ascender = readfword(f), descender = readfword(f), linegap = readfword(f), @@ -1042,7 +1101,7 @@ readers.vhea = function(f,fontdata,specification) local tableoffset = gotodatatable(f,fontdata,"vhea",specification.details) if tableoffset then fontdata.verticalheader = { - version = readfixed(f), + version = readulong(f), ascender = readfword(f), descender = readfword(f), linegap = readfword(f), @@ -1075,15 +1134,15 @@ end readers.maxp = function(f,fontdata,specification) local tableoffset = gotodatatable(f,fontdata,"maxp",specification.details) if tableoffset then - local version = readfixed(f) + local version = readulong(f) local nofglyphs = readushort(f) fontdata.nofglyphs = nofglyphs - if version == 0.5 then + if version == 0x00005000 then fontdata.maximumprofile = { version = version, nofglyphs = nofglyphs, } - elseif version == 1.0 then + elseif version == 0x00010000 then fontdata.maximumprofile = { version = version, nofglyphs = nofglyphs, @@ -1124,15 +1183,14 @@ readers.hmtx = function(f,fontdata,specification) local leftsidebearing = 0 for i=0,nofmetrics-1 do local glyph = glyphs[i] - width = readshort(f) + width = readshort(f) -- readushort leftsidebearing = readshort(f) if width ~= 0 then glyph.width = width end --- for now --- 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. @@ -1145,7 +1203,6 @@ readers.hmtx = function(f,fontdata,specification) -- glyph.lsb = leftsidebearing -- end end - -- hm, there can be a lsb here end end @@ -1195,7 +1252,7 @@ end readers.post = function(f,fontdata,specification) local tableoffset = gotodatatable(f,fontdata,"post",true) if tableoffset then - local version = readfixed(f) + local version = readulong(f) fontdata.postscript = { version = version, italicangle = round(1000*readfixed(f))/1000, @@ -1209,12 +1266,12 @@ readers.post = function(f,fontdata,specification) } if not specification.glyphs then -- enough done - elseif version == 1.0 then + elseif version == 0x00010000 then -- mac encoding (258 glyphs) for index=0,#standardromanencoding do glyphs[index].name = standardromanencoding[index] end - elseif version == 2.0 then + elseif version == 0x00020000 then local glyphs = fontdata.glyphs local nofglyphs = readushort(f) local indices = { } @@ -1245,10 +1302,6 @@ readers.post = function(f,fontdata,specification) end end end - elseif version == 2.5 then - -- depricated, will be done when needed - elseif version == 3.0 then - -- no ps name information end else fontdata.postscript = { } @@ -1321,34 +1374,18 @@ formatreaders[4] = function(f,fontdata,offset) -- skipshort(f,3) -- searchrange entryselector rangeshift -- - local endchars = { } - local startchars = { } - local deltas = { } - local offsets = { } - local indices = { } local mapping = fontdata.mapping local glyphs = fontdata.glyphs local duplicates = fontdata.duplicates local nofdone = 0 - -- - for i=1,nofsegments do - endchars[i] = readushort(f) - end - local reserved = readushort(f) -- 0 - for i=1,nofsegments do - startchars[i] = readushort(f) - end - for i=1,nofsegments do - deltas[i] = readshort(f) - end - for i=1,nofsegments do - offsets[i] = readushort(f) - end + local endchars = readcardinaltable(f,nofsegments,ushort) + local reserved = readushort(f) -- 0 + local startchars = readcardinaltable(f,nofsegments,ushort) + local deltas = readcardinaltable(f,nofsegments,ushort) + local offsets = readcardinaltable(f,nofsegments,ushort) -- format length language nofsegments searchrange entryselector rangeshift 4-tables - local size = (length - 2 * 2 - 5 * 2 - 4 * 2 * nofsegments) / 2 - for i=1,size-1 do - indices[i] = readushort(f) - end + local size = (length - 2 * 2 - 5 * 2 - 4 * 2 * nofsegments) / 2 + local indices = readcardinaltable(f,size-1,ushort) -- for segment=1,nofsegments do local startchar = startchars[segment] @@ -1927,14 +1964,16 @@ local function getinfo(maindata,sub,platformnames,rawfamilynames,metricstoo,inst designsize = fontdata.designsize, minsize = fontdata.minsize, maxsize = fontdata.maxsize, + boundingbox = fontheader and { fontheader.xmin or 0, fontheader.ymin or 0, fontheader.xmax or 0, fontheader.ymax or 0 } or nil, monospaced = (tonumber(postscript.monospaced or 0) > 0) or metrics.panosewidth == "monospaced", averagewidth = metrics.averagewidth, - xheight = metrics.xheight, - capheight = metrics.capheight, -- not always present and probably crap + xheight = metrics.xheight, -- can be missing + capheight = metrics.capheight or fontdata.maxy, -- can be missing ascender = metrics.typoascender, descender = metrics.typodescender, platformnames = platformnames or nil, instancenames = instancenames or nil, + tableoffsets = fontdata.tableoffsets, } if metricstoo then local keys = { @@ -1996,7 +2035,8 @@ local function loadtables(f,specification,offset) } for i=1,fontdata.noftables do local tag = lower(stripstring(readstring(f,4))) - local checksum = readulong(f) -- not used + -- 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 @@ -2008,13 +2048,14 @@ local function loadtables(f,specification,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 + return fontdata, tables end local function prepareglyps(fontdata) @@ -2043,7 +2084,7 @@ local variablefonts_supported = (context and true) or (logs and logs.application local function readdata(f,offset,specification) - local fontdata = loadtables(f,specification,offset) + local fontdata, tables = loadtables(f,specification,offset) if specification.glyphs then prepareglyps(fontdata) @@ -2182,10 +2223,20 @@ local function readdata(f,offset,specification) readtable("math",f,fontdata,specification) fontdata.locations = nil - fontdata.tables = nil fontdata.cidmaps = nil fontdata.dictionaries = nil -- fontdata.cff = nil + + if specification.tableoffsets then + fontdata.tableoffsets = tables + setmetatableindex(tables, { + version = fontdata.version, + noftables = fontdata.noftables, + searchrange = fontdata.searchrange, + entryselector = fontdata.entryselector, + rangeshift = fontdata.rangeshift, + }) + end return fontdata end @@ -2209,12 +2260,9 @@ local function loadfontdata(specification) fontdata = readdata(f,0,specification) elseif version == "ttcf" then local subfont = tonumber(specification.subfont) - local offsets = { } local ttcversion = readulong(f) local nofsubfonts = readulong(f) - for i=1,nofsubfonts do - offsets[i] = readulong(f) - end + local offsets = readcardinaltable(f,nofsubfonts,ulong) if subfont then -- a number of not if subfont >= 1 and subfont <= nofsubfonts then fontdata = readdata(f,offsets[subfont],specification) @@ -2296,12 +2344,13 @@ local function loadfont(specification,n,instance) 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()) + report("fatal error in file %a: %s\n%s",specification.filename,str,debug and debug.traceback()) end local ok, result = xpcall(loadfontdata,message,specification) if ok then return result end +-- return loadfontdata(specification) end -- we need even less, but we can have a 'detail' variant @@ -2323,13 +2372,26 @@ function readers.loadshapes(filename,n,instance,streams) v.math = nil -- v.name = nil end + local names = fontdata.names + if names then + for k, v in next, names do + names[k] = fullstrip(v.content) + end + end end return fontdata and { - -- version = 0.123 -- todo - filename = filename, - format = fontdata.format, - glyphs = fontdata.glyphs, - units = fontdata.fontheader.units, + -- version = 0.123 -- todo + filename = filename, + format = fontdata.format, + glyphs = fontdata.glyphs, + units = fontdata.fontheader.units, + cffinfo = fontdata.cffinfo, + fontheader = fontdata.fontheader, + horizontalheader = fontdata.horizontalheader, + verticalheader = fontdata.verticalheader, + maximumprofile = fontdata.maximumprofile, + names = fontdata.names, + postscript = fontdata.postscript, } or { filename = filename, format = "unknown", @@ -2385,7 +2447,7 @@ function readers.loadfont(filename,n,instance) mathconstants = fontdata.mathconstants, colorpalettes = fontdata.colorpalettes, svgshapes = fontdata.svgshapes, - sbixshapes = fontdata.sbixshapes, + pngshapes = fontdata.pngshapes, variabledata = fontdata.variabledata, foundtables = fontdata.foundtables, }, @@ -2400,10 +2462,12 @@ function readers.getinfo(filename,specification) -- string, nil|number|table local platformnames = false local rawfamilynames = false local instancenames = true + local tableoffsets = false if type(specification) == "table" then subfont = tonumber(specification.subfont) platformnames = specification.platformnames rawfamilynames = specification.rawfamilynames + tableoffsets = specification.tableoffsets else subfont = tonumber(specification) end @@ -2412,6 +2476,7 @@ function readers.getinfo(filename,specification) -- string, nil|number|table details = true, platformnames = platformnames, instancenames = true, + tableoffsets = tableoffsets, -- rawfamilynames = rawfamilynames, } if fontdata then |