From 218228536ed709be8ab2dde4a00dc27249ceed8a Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Sun, 16 Apr 2017 13:20:40 +0200 Subject: 2017-04-16 12:47:00 --- tex/generic/context/luatex/luatex-fonts-merged.lua | 457 ++++++++++++++++----- 1 file changed, 343 insertions(+), 114 deletions(-) (limited to 'tex/generic') diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index 68bcd8007..c671651ef 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date : 04/08/17 12:09:31 +-- merge date : 04/16/17 12:32:21 do -- begin closure to overcome local limits and interference @@ -8171,14 +8171,7 @@ local function readlongdatetime(f) end local tableversion=0.004 readers.tableversion=tableversion -local privateoffset=fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -local reportedskipped={} -local function reportskippedtable(tag) - if not reportedskipped[tag] then - report("loading of table %a skipped (reported once only)",tag) - reportedskipped[tag]=true - end -end +local privateoffset=fonts.constructors and fonts.constructors.privateoffset or 0xF0000 local reservednames={ [0]="copyright", "family", "subfamily", @@ -8382,6 +8375,14 @@ local function gotodatatable(f,fontdata,tag,criterium) 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) + end + end +end local function setvariabledata(fontdata,tag,data) local variabledata=fontdata.variabledata if variabledata then @@ -8392,6 +8393,7 @@ local function setvariabledata(fontdata,tag,data) end helpers.gotodatatable=gotodatatable helpers.setvariabledata=setvariabledata +helpers.reportskippedtable=reportskippedtable local platformnames={ postscriptname=true, fullname=true, @@ -8763,8 +8765,7 @@ readers.vmtx=function(f,fontdata,specification) end end readers.vorg=function(f,fontdata,specification) - if specification.glyphs then - end + reportskippedtable(f,fontdata,"vorg",specification.glyphs) end readers.post=function(f,fontdata,specification) local tableoffset=gotodatatable(f,fontdata,"post",true) @@ -8825,9 +8826,7 @@ readers.post=function(f,fontdata,specification) end end readers.cff=function(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("cff") - end + reportskippedtable(f,fontdata,"cff",specification.glyphs) end local formatreaders={} local duplicatestoo=true @@ -9246,29 +9245,37 @@ function readers.cmap(f,fontdata,specification) end end function readers.loca(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("loca") - end + reportskippedtable(f,fontdata,"loca",specification.glyphs) end function readers.glyf(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("glyf") - end + reportskippedtable(f,fontdata,"glyf",specification.glyphs) end function readers.colr(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("colr") - end + reportskippedtable(f,fontdata,"colr",specification.glyphs) end function readers.cpal(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("cpal") - end + reportskippedtable(f,fontdata,"cpal",specification.glyphs) end function readers.svg(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("svg") - end + reportskippedtable(f,fontdata,"svg",specification.glyphs) +end +function readers.sbix(f,fontdata,specification) + reportskippedtable(f,fontdata,"sbix",specification.glyphs) +end +function readers.cbdt(f,fontdata,specification) + reportskippedtable(f,fontdata,"cbdt",specification.glyphs) +end +function readers.cblc(f,fontdata,specification) + reportskippedtable(f,fontdata,"cblc",specification.glyphs) +end +function readers.ebdt(f,fontdata,specification) + reportskippedtable(f,fontdata,"ebdt",specification.glyphs) +end +function readers.ebsc(f,fontdata,specification) + reportskippedtable(f,fontdata,"ebsc",specification.glyphs) +end +function readers.eblc(f,fontdata,specification) + reportskippedtable(f,fontdata,"eblc",specification.glyphs) end function readers.kern(f,fontdata,specification) local tableoffset=gotodatatable(f,fontdata,"kern",specification.kerns) @@ -9308,24 +9315,16 @@ function readers.kern(f,fontdata,specification) end end function readers.gdef(f,fontdata,specification) - if specification.details then - reportskippedtable("gdef") - end + reportskippedtable(f,fontdata,"gdef",specification.details) end function readers.gsub(f,fontdata,specification) - if specification.details then - reportskippedtable("gsub") - end + reportskippedtable(f,fontdata,"gsub",specification.details) end function readers.gpos(f,fontdata,specification) - if specification.details then - reportskippedtable("gpos") - end + reportskippedtable(f,fontdata,"gpos",specification.details) end function readers.math(f,fontdata,specification) - if specification.glyphs then - reportskippedtable("math") - end + reportskippedtable(f,fontdata,"math",specification.details) end local function getinfo(maindata,sub,platformnames,rawfamilynames,metricstoo,instancenames) local fontdata=sub and maindata.subfonts and maindata.subfonts[sub] or maindata @@ -9560,6 +9559,11 @@ local function readdata(f,offset,specification) readtable("colr",f,fontdata,specification) readtable("cpal",f,fontdata,specification) readtable("svg",f,fontdata,specification) + readtable("sbix",f,fontdata,specification) + readtable("cbdt",f,fontdata,specification) + readtable("cblc",f,fontdata,specification) + readtable("ebdt",f,fontdata,specification) + readtable("eblc",f,fontdata,specification) readtable("kern",f,fontdata,specification) readtable("gsub",f,fontdata,specification) readtable("gpos",f,fontdata,specification) @@ -9753,6 +9757,7 @@ function readers.loadfont(filename,n,instance) mathconstants=fontdata.mathconstants, colorpalettes=fontdata.colorpalettes, svgshapes=fontdata.svgshapes, + sbixshapes=fontdata.sbixshapes, variabledata=fontdata.variabledata, foundtables=fontdata.foundtables, }, @@ -15269,6 +15274,72 @@ function readers.svg(f,fontdata,specification) end fontdata.hascolor=true end +function readers.sbix(f,fontdata,specification) + local tableoffset=gotodatatable(f,fontdata,"sbix",specification.glyphs) + if tableoffset then + local version=readushort(f) + local flags=readushort(f) + local nofstrikes=readulong(f) + local strikes={} + local nofglyphs=fontdata.nofglyphs + for i=1,nofstrikes do + strikes[i]=readulong(f) + end + local shapes={} + local done=0 + for i=1,nofstrikes do + local strikeoffset=strikes[i]+tableoffset + setposition(f,strikeoffset) + strikes[i]={ + ppem=readushort(f), + ppi=readushort(f), + offset=strikeoffset + } + end + sort(strikes,function(a,b) + if b.ppem==a.ppem then + return b.ppi0 then + setposition(f,strikeoffset+glyphoffset) + shapes[i]={ + x=readshort(f), + y=readshort(f), + tag=readtag(f), + data=readstring(f,datasize-8), + ppem=strikeppem, + ppi=strikeppi, + } + done=done+1 + if done==nofglyphs then + break + end + end + end + glyphoffset=nextoffset + end + end + fontdata.sbixshapes=shapes + end +end function readers.stat(f,fontdata,specification) local tableoffset=gotodatatable(f,fontdata,"stat",true) if tableoffset then @@ -17755,8 +17826,10 @@ local otf=fonts.handlers.otf otf.version=3.028 otf.cache=containers.define("fonts","otl",otf.version,true) otf.svgcache=containers.define("fonts","svg",otf.version,true) +otf.sbixcache=containers.define("fonts","sbix",otf.version,true) otf.pdfcache=containers.define("fonts","pdf",otf.version,true) otf.svgenabled=false +otf.sbixenabled=false local otfreaders=otf.readers local hashes=fonts.hashes local definers=fonts.definers @@ -17812,6 +17885,7 @@ function otf.load(filename,sub,instance) if data then local resources=data.resources local svgshapes=resources.svgshapes + local sbixshapes=resources.sbixshapes if svgshapes then resources.svgshapes=nil if otf.svgenabled then @@ -17826,6 +17900,20 @@ function otf.load(filename,sub,instance) } end end + if sbixshapes then + resources.sbixshapes=nil + if otf.sbixenabled then + local timestamp=os.date() + containers.write(otf.sbixcache,hash,{ + sbixshapes=sbixshapes, + timestamp=timestamp, + }) + data.properties.sbix={ + hash=hash, + timestamp=timestamp, + } + end + end otfreaders.compact(data) otfreaders.rehash(data,"unicodes") otfreaders.addunicodetable(data) @@ -25817,6 +25905,7 @@ if not modules then modules={} end modules ['font-ocl']={ } local tostring,next,format=tostring,next,string.format local round,max=math.round,math.round +local sortedkeys,sortedhash=table.sortedkeys,table.sortedhash local formatters=string.formatters local tounicode=fonts.mappings.tounicode local otf=fonts.handlers.otf @@ -25944,44 +26033,78 @@ fonts.handlers.otf.features.register { node=initializecolr, } } -local otfsvg=otf.svg or {} -otf.svg=otfsvg -otf.svgenabled=true do local nofstreams=0 - local f_name=formatters[ [[svg-glyph-%05i]] ] + local f_name=formatters[ [[pdf-glyph-%05i]] ] local f_used=context and formatters[ [[original:///%s]] ] or formatters[ [[%s]] ] + local hashed={} local cache={} - function otfsvg.storepdfdata(pdf) - nofstreams=nofstreams+1 - local o,n=epdf.openMemStream(pdf,#pdf,f_name(nofstreams)) - cache[n]=o - return nil,f_used(n),nil + function otf.storepdfdata(pdf) + local done=hashed[pdf] + if not done then + nofstreams=nofstreams+1 + local o,n=epdf.openMemStream(pdf,#pdf,f_name(nofstreams)) + cache[n]=o + done=f_used(n) + hashed[pdf]=done + end + return nil,done,nil end - if context then - local storepdfdata=otfsvg.storepdfdata - local initialized=false - function otfsvg.storepdfdata(pdf) - if not initialized then - if resolvers.setmemstream then - local f_setstream=formatters[ [[resolvers.setmemstream("svg-glyph-%05i",%q,true)]] ] - local f_getstream=formatters[ [[memstream:///svg-glyph-%05i]] ] - local f_nilstream=formatters[ [[resolvers.resetmemstream("svg-glyph-%05i",true)]] ] - storepdfdata=function(pdf) - nofstreams=nofstreams+1 - return - f_setstream(nofstreams,pdf), - f_getstream(nofstreams), - f_nilstream(nofstreams) - end - otfsvg.storepdfdata=storepdfdata +end +local function pdftovirtual(tfmdata,pdfshapes,kind) + if not tfmdata or not pdfshapes or not kind then + return + end + local characters=tfmdata.characters + local properties=tfmdata.properties + local parameters=tfmdata.parameters + local hfactor=parameters.hfactor + properties.virtualized=true + tfmdata.fonts={ + { id=0 } + } + local getactualtext=otf.getactualtext + local storepdfdata=otf.storepdfdata + for unicode,character in sortedhash(characters) do + local index=character.index + if index then + local pdf=pdfshapes[index] + local typ=type(pdf) + local data=nil + local dx=nil + local dy=nil + if typ=="table" then + data=pdf.data + dx=pdf.dx or 0 + dy=pdf.dy or 0 + elseif typ=="string" then + data=pdf + dx=0 + dy=0 + end + if data then + local setcode,name,nilcode=storepdfdata(data) + if name then + local bt,et=getactualtext(unicode) + local wd=character.width or 0 + local ht=character.height or 0 + local dp=character.depth or 0 + character.commands={ + { "special","pdf:direct:"..bt }, + { "down",dp+dy*hfactor }, + { "right",dx*hfactor }, + { "image",{ filename=name,width=wd,height=ht,depth=dp } }, + { "special","pdf:direct:"..et }, + } + character[kind]=true end - initialized=true end - return storepdfdata(pdf) end end end +local otfsvg=otf.svg or {} +otf.svg=otfsvg +otf.svgenabled=true do local report_svg=logs.reporter("fonts","svg conversion") local loaddata=io.loaddata @@ -26054,7 +26177,7 @@ do end statistics.stoptiming() if statistics.elapsedseconds then - report_svg("svg conversion time %s",statistics.elapsedseconds()) + report_svg("svg conversion time %s",statistics.elapsedseconds() or "-") end end return pdfshapes @@ -26062,10 +26185,7 @@ do end local function initializesvg(tfmdata,kind,value) if value and otf.svgenabled then - local characters=tfmdata.characters - local descriptions=tfmdata.descriptions - local properties=tfmdata.properties - local svg=properties.svg + local svg=tfmdata.properties.svg local hash=svg and svg.hash local timestamp=svg and svg.timestamp if not hash then @@ -26082,40 +26202,7 @@ local function initializesvg(tfmdata,kind,value) timestamp=timestamp, }) end - if not pdfshapes or not next(pdfshapes) then - return - end - properties.virtualized=true - tfmdata.fonts={ - { id=0 } - } - local getactualtext=otf.getactualtext - local storepdfdata=otfsvg.storepdfdata - local nop={ "nop" } - for unicode,character in next,characters do - local index=character.index - if index then - local pdf=pdfshapes[index] - if pdf then - local setcode,name,nilcode=storepdfdata(pdf) - if name then - local bt,et=getactualtext(unicode) - local wd=character.width or 0 - local ht=character.height or 0 - local dp=character.depth or 0 - character.commands={ - { "special","pdf:direct:"..bt }, - { "down",dp }, - setcode and { "lua",setcode } or nop, - { "image",{ filename=name,width=wd,height=ht,depth=dp } }, - nilcode and { "lua",nilcode } or nop, - { "special","pdf:direct:"..et }, - } - character.svg=true - end - end - end - end + pdftovirtual(tfmdata,pdfshapes,"svg") end end fonts.handlers.otf.features.register { @@ -26126,6 +26213,91 @@ fonts.handlers.otf.features.register { node=initializesvg, } } +local otfsbix=otf.sbix or {} +otf.sbix=otfsbix +otf.sbixenabled=true +do + local report_sbix=logs.reporter("fonts","sbix conversion") + local loaddata=io.loaddata + local savedata=io.savedata + local remove=os.remove + local runner=sandbox and sandbox.registerrunner { + name="otfsbix", + program="gm", + template="convert -quality 100 temp-otf-sbix-shape.sbix temp-otf-sbix-shape.pdf > temp-otf-svg-shape.log", + } + if not runner then + runner=function() + return os.execute("gm convert -quality 100 temp-otf-sbix-shape.sbix temp-otf-sbix-shape.pdf > temp-otf-svg-shape.log") + end + end + function otfsbix.topdf(sbixshapes) + local pdfshapes={} + local sbixfile="temp-otf-sbix-shape.sbix" + local pdffile="temp-otf-sbix-shape.pdf" + local nofdone=0 + local indices=sortedkeys(sbixshapes) + local nofindices=#indices + report_sbix("processing %i sbix containers",nofindices) + statistics.starttiming() + for i=1,nofindices do + local index=indices[i] + local entry=sbixshapes[index] + local data=entry.data + local x=entry.x + local y=entry.y + savedata(sbixfile,data) + runner() + pdfshapes[index]={ + x=x~=0 and x or nil, + y=y~=0 and y or nil, + data=loaddata(pdffile), + } + nofdone=nofdone+1 + if nofdone%100==0 then + report_sbix("%i shapes processed",nofdone) + end + end + report_sbix("processing %i pdf results",nofindices) + remove(sbixfile) + remove(pdffile) + statistics.stoptiming() + if statistics.elapsedseconds then + report_sbix("sbix conversion time %s",statistics.elapsedseconds() or "-") + end + return pdfshapes + end +end +local function initializesbix(tfmdata,kind,value) + if value and otf.sbixenabled then + local sbix=tfmdata.properties.sbix + local hash=sbix and sbix.hash + local timestamp=sbix and sbix.timestamp + if not hash then + return + end + local pdffile=containers.read(otf.pdfcache,hash) + local pdfshapes=pdffile and pdffile.pdfshapes + if not pdfshapes or pdffile.timestamp~=timestamp then + local sbixfile=containers.read(otf.sbixcache,hash) + local sbixshapes=sbixfile and sbixfile.sbixshapes + pdfshapes=sbixshapes and otfsbix.topdf(sbixshapes) or {} + containers.write(otf.pdfcache,hash,{ + pdfshapes=pdfshapes, + timestamp=timestamp, + }) + end + pdftovirtual(tfmdata,pdfshapes,"sbix") + end +end +fonts.handlers.otf.features.register { + name="sbix", + description="sbix glyphs", + manipulators={ + base=initializesbix, + node=initializesbix, + } +} end -- closure @@ -26142,7 +26314,6 @@ local format,insert,sortedkeys,tohash=string.format,table.insert,table.sortedkey local type,next=type,next local lpegmatch=lpeg.match local utfbyte,utflen,utfsplit=utf.byte,utf.len,utf.split -local settings_to_array=utilities.parsers.settings_to_array local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end) local report_otf=logs.reporter("fonts","otf loading") local fonts=fonts @@ -26974,6 +27145,8 @@ registerotffeature { name='blockligatures', description='block certain ligatures', } +local settings_to_array=utilities.parsers and utilities.parsers.settings_to_array + or function(s) return string.split(s,",") end local function blockligatures(str) local t=settings_to_array(str) for i=1,#t do @@ -28783,8 +28956,9 @@ if not modules then modules={} end modules ['font-def']={ local lower,gsub=string.lower,string.gsub local tostring,next=tostring,next local lpegmatch=lpeg.match -local suffixonly,removesuffix=file.suffix,file.removesuffix +local suffixonly,removesuffix,basename=file.suffix,file.removesuffix,file.basename local formatters=string.formatters +local sortedhash,sortedkeys=table.sortedhash,table.sortedkeys local allocate=utilities.storage.allocate local trace_defining=false trackers .register("fonts.defining",function(v) trace_defining=v end) local directive_embedall=false directives.register("fonts.embedall",function(v) directive_embedall=v end) @@ -28904,9 +29078,9 @@ function resolvers.name(specification) features.normal=normal end normal.instance=instance -if not callbacks.supported.glyph_stream_provider then - normal.variableshapes=true -end + if not callbacks.supported.glyph_stream_provider then + normal.variableshapes=true + end end local suffix=lower(suffixonly(resolved)) if fonts.formats[suffix] then @@ -28985,6 +29159,60 @@ local function checkembedding(tfmdata) end tfmdata.embedding=embedding end +local function checkfeatures(tfmdata) + local resources=tfmdata.resources + local shared=tfmdata.shared + if resources and shared then + local features=resources.features + local usedfeatures=shared.features + if features and usedfeatures then + local usedlanguage=usedfeatures.language or "dflt" + local usedscript=usedfeatures.script or "dflt" + local function check(what) + if what then + local foundlanguages={} + for feature,scripts in next,what do + if usedscript=="auto" or scripts["*"] then + elseif not scripts[usedscript] then + else + for script,languages in next,scripts do + if languages["*"] then + elseif not languages[usedlanguage] then + report_defining("font %!font:name!, feature %a, script %a, no language %a", + tfmdata,feature,script,usedlanguage) + end + end + end + for script,languages in next,scripts do + for language in next,languages do + foundlanguages[language]=true + end + end + end + if false then + foundlanguages["*"]=nil + foundlanguages=sortedkeys(foundlanguages) + for feature,scripts in sortedhash(what) do + for script,languages in next,scripts do + if not languages["*"] then + for i=1,#foundlanguages do + local language=foundlanguages[i] + if not languages[language] then + report_defining("font %!font:name!, feature %a, script %a, no language %a", + tfmdata,feature,script,language) + end + end + end + end + end + end + end + end + check(features.gsub) + check(features.gpos) + end + end +end function definers.loadfont(specification) local hash=constructors.hashinstance(specification) local tfmdata=loadedfonts[hash] @@ -29018,6 +29246,7 @@ function definers.loadfont(specification) checkembedding(tfmdata) loadedfonts[hash]=tfmdata designsizes[specification.hash]=tfmdata.parameters.designsize + checkfeatures(tfmdata) end end if not tfmdata then @@ -29110,7 +29339,7 @@ function definers.read(specification,size,id) local parameters=tfmdata.parameters or {} report_defining("using %a font with id %a, name %a, size %a, bytes %a, encoding %a, fullname %a, filename %a", properties.format or "unknown",id,properties.name,parameters.size,properties.encodingbytes, - properties.encodingname,properties.fullname,file.basename(properties.filename)) + properties.encodingname,properties.fullname,basename(properties.filename)) end statistics.stoptiming(fonts) return tfmdata -- cgit v1.2.3