From 744095aa4676553437db0d71c281a74557a3222f Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Sun, 18 Nov 2018 16:12:36 +0100 Subject: 2018-11-18 14:16:00 --- tex/generic/context/luatex/luatex-basics-gen.lua | 9 + tex/generic/context/luatex/luatex-core.lua | 4 +- tex/generic/context/luatex/luatex-fonts-merged.lua | 1164 +++++++++++++------- 3 files changed, 753 insertions(+), 424 deletions(-) (limited to 'tex/generic') diff --git a/tex/generic/context/luatex/luatex-basics-gen.lua b/tex/generic/context/luatex/luatex-basics-gen.lua index 64f3be218..ee0367fa4 100644 --- a/tex/generic/context/luatex/luatex-basics-gen.lua +++ b/tex/generic/context/luatex/luatex-basics-gen.lua @@ -18,6 +18,7 @@ local match, gmatch, gsub, lower = string.match, string.gmatch, string.gsub, str local formatters, split, format, dump = string.formatters, string.split, string.format, string.dump local loadfile, type = loadfile, type local setmetatable, getmetatable, collectgarbage = setmetatable, getmetatable, collectgarbage +local floor = math.floor local dummyfunction = function() end @@ -405,3 +406,11 @@ if arg then end end end + +-- another one + +if not number.idiv then + function number.idiv(i,d) + return floor(i/d) -- i//d in 5.3 + end +end diff --git a/tex/generic/context/luatex/luatex-core.lua b/tex/generic/context/luatex/luatex-core.lua index 7fcfb8100..35518c0e8 100644 --- a/tex/generic/context/luatex/luatex-core.lua +++ b/tex/generic/context/luatex/luatex-core.lua @@ -54,7 +54,7 @@ local function luatex_io_open(name,how) end local function luatex_io_open_readonly(name,how) - if how then + if not how then how = 'r' else how = gsub(how,'[^rb]','') @@ -174,6 +174,8 @@ if saferoption == 1 then lfs.rmdir = installdummy("lfs.rmdir") lfs.mkdir = installdummy("lfs.mkdir") + debug = nil + end if saferoption == 1 or shellescape ~= 1 then diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index 0a14e6082..5499f8f18 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 : 10/18/18 00:07:52 +-- merge date : 11/18/18 14:07:44 do -- begin closure to overcome local limits and interference @@ -1107,7 +1107,6 @@ local table,string=table,string local concat,sort,insert,remove=table.concat,table.sort,table.insert,table.remove local format,lower,dump=string.format,string.lower,string.dump local getmetatable,setmetatable=getmetatable,setmetatable -local getinfo=debug.getinfo local lpegmatch,patterns=lpeg.match,lpeg.patterns local floor=math.floor local stripper=patterns.stripper @@ -1669,20 +1668,23 @@ local function do_serialize(root,name,depth,level,indexed) end elseif tv=="function" then if functions then - local f=getinfo(v).what=="C" and dump(dummy) or dump(v) - if tk=="number" then - if hexify then - handle(format("%s [0x%X]=load(%q),",depth,k,f)) + local getinfo=debug and debug.getinfo + if getinfo then + local f=getinfo(v).what=="C" and dump(dummy) or dump(v) + if tk=="number" then + if hexify then + handle(format("%s [0x%X]=load(%q),",depth,k,f)) + else + handle(format("%s [%s]=load(%q),",depth,k,f)) + end + elseif tk=="boolean" then + handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f)) + elseif tk~="string" then + elseif noquotes and not reserved[k] and lpegmatch(propername,k) then + handle(format("%s %s=load(%q),",depth,k,f)) else - handle(format("%s [%s]=load(%q),",depth,k,f)) + handle(format("%s [%q]=load(%q),",depth,k,f)) end - elseif tk=="boolean" then - handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f)) - elseif tk~="string" then - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=load(%q),",depth,k,f)) - else - handle(format("%s [%q]=load(%q),",depth,k,f)) end end else @@ -4649,6 +4651,10 @@ function strings.newcollector() end end end +local f_16_16=formatters["%0.5N"] +function number.to16dot16(n) + return f_16_16(n/65536.0) +end end -- closure @@ -4661,6 +4667,7 @@ if not modules then modules={} end modules ['util-fil']={ copyright="PRAGMA ADE / ConTeXt Development Team", license="see context related readme files" } +local tonumber=tonumber local byte=string.byte local char=string.char utilities=utilities or {} @@ -4819,17 +4826,17 @@ end function files.readfixed2(f) local a,b=byte(f:read(2),1,2) if a>=0x80 then - return (a-0x100)+b/0x100 + tonumber((a-0x100).."."..b) else - return (a )+b/0x100 + tonumber((a ).."."..b) end end function files.readfixed4(f) local a,b,c,d=byte(f:read(4),1,4) if a>=0x80 then - return (0x100*a+b-0x10000)+(0x100*c+d)/0x10000 + tonumber((0x100*a+b-0x10000).."."..(0x100*c+d)) else - return (0x100*a+b )+(0x100*c+d)/0x10000 + tonumber((0x100*a+b ).."."..(0x100*c+d)) end end if bit32 then @@ -4963,6 +4970,7 @@ local match,gmatch,gsub,lower=string.match,string.gmatch,string.gsub,string.lowe local formatters,split,format,dump=string.formatters,string.split,string.format,string.dump local loadfile,type=loadfile,type local setmetatable,getmetatable,collectgarbage=setmetatable,getmetatable,collectgarbage +local floor=math.floor local dummyfunction=function() end local dummyreporter=function(c) @@ -5273,6 +5281,11 @@ if arg then end end end +if not number.idiv then + function number.idiv(i,d) + return floor(i/d) + end +end end -- closure @@ -9921,23 +9934,20 @@ function constructors.finalize(tfmdata) if not properties.virtualized then properties.virtualized=tfmdata.type=="virtual" end - if not tfmdata.properties then - tfmdata.properties={ - fontname=tfmdata.fontname, - filename=tfmdata.filename, - fullname=tfmdata.fullname, - name=tfmdata.name, - psname=tfmdata.psname, - encodingbytes=tfmdata.encodingbytes or 1, - embedding=tfmdata.embedding or "subset", - tounicode=tfmdata.tounicode or 1, - cidinfo=tfmdata.cidinfo or nil, - format=tfmdata.format or "type1", - direction=tfmdata.direction or 0, - writingmode=tfmdata.writingmode or "horizontal", - identity=tfmdata.identity or "horizontal", - } - end + properties.fontname=tfmdata.fontname + properties.filename=tfmdata.filename + properties.fullname=tfmdata.fullname + properties.name=tfmdata.name + properties.psname=tfmdata.psname + properties.encodingbytes=tfmdata.encodingbytes or 1 + properties.embedding=tfmdata.embedding or "subset" + properties.tounicode=tfmdata.tounicode or 1 + properties.cidinfo=tfmdata.cidinfo or nil + properties.format=tfmdata.format or "type1" + properties.direction=tfmdata.direction or 0 + properties.writingmode=tfmdata.writingmode or "horizontal" + properties.identity=tfmdata.identity or "horizontal" + properties.usedbitmap=tfmdata.usedbitmap if not tfmdata.resources then tfmdata.resources={} end @@ -11244,6 +11254,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 @@ -11520,19 +11531,29 @@ 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 + 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 @@ -11556,6 +11577,15 @@ local platformnames={ typographicsubfamily=true, 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 @@ -11608,6 +11638,17 @@ function readers.name(f,fontdata,specification) local names={} local done={} local extras={} + 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 @@ -11619,14 +11660,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, @@ -11650,22 +11684,15 @@ function readers.name(f,fontdata,specification) fontdata.extras=extras if specification.platformnames then 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 @@ -11748,10 +11775,13 @@ 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), + version=version, + fontversion=number.to16dot16(fontversion), + fontversionnumber=fontversion, + checksum=readushort(f)*0x10000+readushort(f), magic=readulong(f), flags=readushort(f), units=readushort(f), @@ -11777,7 +11807,7 @@ readers.hhea=function(f,fontdata,specification) local tableoffset=gotodatatable(f,fontdata,"hhea",specification.details) if tableoffset then fontdata.horizontalheader={ - version=readfixed(f), + version=readulong(f), ascender=readfword(f), descender=readfword(f), linegap=readfword(f), @@ -11805,7 +11835,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), @@ -11832,15 +11862,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, @@ -11877,7 +11907,7 @@ 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) leftsidebearing=readshort(f) if width~=0 then glyph.width=width @@ -11923,7 +11953,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, @@ -11936,11 +11966,11 @@ readers.post=function(f,fontdata,specification) maxmemtype1=readulong(f), } if not specification.glyphs then - elseif version==1.0 then + elseif version==0x00010000 then 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={} @@ -11971,8 +12001,6 @@ readers.post=function(f,fontdata,specification) end end end - elseif version==2.5 then - elseif version==3.0 then end else fontdata.postscript={} @@ -12529,14 +12557,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, + capheight=metrics.capheight or fontdata.maxy, ascender=metrics.typoascender, descender=metrics.typodescender, platformnames=platformnames or nil, instancenames=instancenames or nil, + tableoffsets=fontdata.tableoffsets, } if metricstoo then local keys={ @@ -12594,7 +12624,7 @@ local function loadtables(f,specification,offset) } for i=1,fontdata.noftables do local tag=lower(stripstring(readstring(f,4))) - local checksum=readulong(f) + local checksum=readushort(f)*0x10000+readushort(f) local offset=readulong(f) local length=readulong(f) if offset+length>filesize then @@ -12612,7 +12642,7 @@ local function loadtables(f,specification,offset) else fontdata.format="truetype" end - return fontdata + return fontdata,tables end local function prepareglyps(fontdata) local glyphs=setmetatableindex(function(t,k) @@ -12633,7 +12663,7 @@ local function readtable(tag,f,fontdata,specification,...) end local variablefonts_supported=(context and true) or (logs and logs.application and true) or false 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) end @@ -12743,9 +12773,18 @@ local function readdata(f,offset,specification) readtable("gpos",f,fontdata,specification) readtable("math",f,fontdata,specification) fontdata.locations=nil - fontdata.tables=nil fontdata.cidmaps=nil fontdata.dictionaries=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 local function loadfontdata(specification) @@ -12849,7 +12888,7 @@ 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 @@ -12871,12 +12910,25 @@ function readers.loadshapes(filename,n,instance,streams) v.index=nil v.math=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 { 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", @@ -12940,10 +12992,12 @@ function readers.getinfo(filename,specification) 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 @@ -12952,6 +13006,7 @@ function readers.getinfo(filename,specification) details=true, platformnames=platformnames, instancenames=true, + tableoffsets=tableoffsets, } if fontdata then local subfonts=fontdata.subfonts @@ -14219,7 +14274,7 @@ if not modules then modules={} end modules ['font-cff']={ copyright="PRAGMA ADE / ConTeXt Development Team", license="see context related readme files" } -local next,type,tonumber=next,type,tonumber +local next,type,tonumber,rawget=next,type,tonumber,rawget local byte,char,gmatch=string.byte,string.char,string.gmatch local concat,remove,unpack=table.concat,table.remove,table.unpack local floor,abs,round,ceil,min,max=math.floor,math.abs,math.round,math.ceil,math.min,math.max @@ -14227,6 +14282,8 @@ local P,C,R,S,C,Cs,Ct=lpeg.P,lpeg.C,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Ct local lpegmatch=lpeg.match local formatters=string.formatters local bytetable=string.bytetable +local idiv=number.idiv +local rshift,band,extract=bit32.rshift,bit32.band,bit32.extract local readers=fonts.handlers.otf.readers local streamreader=readers.streamreader local readstring=streamreader.readstring @@ -14421,8 +14478,25 @@ do end+P("\05")/function() result.fontbbox={ unpack(stack,1,4) } top=0 - end -+P("\13")/function() + end+P("\06")/function() + result.bluevalues={ unpack(stack,1,top) } + top=0 + end+P("\07")/function() + result.otherblues={ unpack(stack,1,top) } + top=0 + end+P("\08")/function() + result.familyblues={ unpack(stack,1,top) } + top=0 + end+P("\09")/function() + result.familyotherblues={ unpack(stack,1,top) } + top=0 + end+P("\10")/function() + result.strhw=stack[top] + top=0 + end+P("\11")/function() + result.strvw=stack[top] + top=0 + end+P("\13")/function() result.uniqueid=stack[top] top=0 end+P("\14")/function() @@ -14488,6 +14562,21 @@ do end+P("\08")/function() result.strokewidth=stack[top] top=0 + end+P("\09")/function() + result.bluescale=stack[top] + top=0 + end+P("\10")/function() + result.bluesnap=stack[top] + top=0 + end+P("\11")/function() + result.bluefuzz=stack[top] + top=0 + end+P("\12")/function() + result.stemsnaph={ unpack(stack,1,top) } + top=0 + end+P("\13")/function() + result.stemsnapv={ unpack(stack,1,top) } + top=0 end+P("\20")/function() result.syntheticbase=stack[top] top=0 @@ -14531,24 +14620,24 @@ do top=0 end ) - local p_last=P("\x0F")/"0"+P("\x1F")/"1"+P("\x2F")/"2"+P("\x3F")/"3"+P("\x4F")/"4"+P("\x5F")/"5"+P("\x6F")/"6"+P("\x7F")/"7"+P("\x8F")/"8"+P("\x9F")/"9"+P("\xAF")/""+P("\xBF")/""+P("\xCF")/""+P("\xDF")/""+P("\xEF")/""+R("\xF0\xFF")/"" local remap={ ["\x00"]="00",["\x01"]="01",["\x02"]="02",["\x03"]="03",["\x04"]="04",["\x05"]="05",["\x06"]="06",["\x07"]="07",["\x08"]="08",["\x09"]="09",["\x0A"]="0.",["\x0B"]="0E",["\x0C"]="0E-",["\x0D"]="0",["\x0E"]="0-",["\x0F"]="0", - ["\x10"]="10",["\x11"]="11",["\x12"]="12",["\x13"]="13",["\x14"]="14",["\x15"]="15",["\x16"]="16",["\x17"]="17",["\x18"]="18",["\x19"]="19",["\x1A"]="0.",["\x1B"]="0E",["\x1C"]="0E-",["\x1D"]="0",["\x1E"]="0-",["\x1F"]="0", - ["\x20"]="20",["\x21"]="21",["\x22"]="22",["\x23"]="23",["\x24"]="24",["\x25"]="25",["\x26"]="26",["\x27"]="27",["\x28"]="28",["\x29"]="29",["\x2A"]="0.",["\x2B"]="0E",["\x2C"]="0E-",["\x2D"]="0",["\x2E"]="0-",["\x2F"]="0", - ["\x30"]="30",["\x31"]="31",["\x32"]="32",["\x33"]="33",["\x34"]="34",["\x35"]="35",["\x36"]="36",["\x37"]="37",["\x38"]="38",["\x39"]="39",["\x3A"]="0.",["\x3B"]="0E",["\x3C"]="0E-",["\x3D"]="0",["\x3E"]="0-",["\x3F"]="0", - ["\x40"]="40",["\x41"]="41",["\x42"]="42",["\x43"]="43",["\x44"]="44",["\x45"]="45",["\x46"]="46",["\x47"]="47",["\x48"]="48",["\x49"]="49",["\x4A"]="0.",["\x4B"]="0E",["\x4C"]="0E-",["\x4D"]="0",["\x4E"]="0-",["\x4F"]="0", - ["\x50"]="50",["\x51"]="51",["\x52"]="52",["\x53"]="53",["\x54"]="54",["\x55"]="55",["\x56"]="56",["\x57"]="57",["\x58"]="58",["\x59"]="59",["\x5A"]="0.",["\x5B"]="0E",["\x5C"]="0E-",["\x5D"]="0",["\x5E"]="0-",["\x5F"]="0", - ["\x60"]="60",["\x61"]="61",["\x62"]="62",["\x63"]="63",["\x64"]="64",["\x65"]="65",["\x66"]="66",["\x67"]="67",["\x68"]="68",["\x69"]="69",["\x6A"]="0.",["\x6B"]="0E",["\x6C"]="0E-",["\x6D"]="0",["\x6E"]="0-",["\x6F"]="0", - ["\x70"]="70",["\x71"]="71",["\x72"]="72",["\x73"]="73",["\x74"]="74",["\x75"]="75",["\x76"]="76",["\x77"]="77",["\x78"]="78",["\x79"]="79",["\x7A"]="0.",["\x7B"]="0E",["\x7C"]="0E-",["\x7D"]="0",["\x7E"]="0-",["\x7F"]="0", - ["\x80"]="80",["\x81"]="81",["\x82"]="82",["\x83"]="83",["\x84"]="84",["\x85"]="85",["\x86"]="86",["\x87"]="87",["\x88"]="88",["\x89"]="89",["\x8A"]="0.",["\x8B"]="0E",["\x8C"]="0E-",["\x8D"]="0",["\x8E"]="0-",["\x8F"]="0", - ["\x90"]="90",["\x91"]="91",["\x92"]="92",["\x93"]="93",["\x94"]="94",["\x95"]="95",["\x96"]="96",["\x97"]="97",["\x98"]="98",["\x99"]="99",["\x9A"]="0.",["\x9B"]="0E",["\x9C"]="0E-",["\x9D"]="0",["\x9E"]="0-",["\x9F"]="0", + ["\x10"]="10",["\x11"]="11",["\x12"]="12",["\x13"]="13",["\x14"]="14",["\x15"]="15",["\x16"]="16",["\x17"]="17",["\x18"]="18",["\x19"]="19",["\x1A"]="1.",["\x1B"]="1E",["\x1C"]="1E-",["\x1D"]="1",["\x1E"]="1-",["\x1F"]="1", + ["\x20"]="20",["\x21"]="21",["\x22"]="22",["\x23"]="23",["\x24"]="24",["\x25"]="25",["\x26"]="26",["\x27"]="27",["\x28"]="28",["\x29"]="29",["\x2A"]="2.",["\x2B"]="2E",["\x2C"]="2E-",["\x2D"]="2",["\x2E"]="2-",["\x2F"]="2", + ["\x30"]="30",["\x31"]="31",["\x32"]="32",["\x33"]="33",["\x34"]="34",["\x35"]="35",["\x36"]="36",["\x37"]="37",["\x38"]="38",["\x39"]="39",["\x3A"]="3.",["\x3B"]="3E",["\x3C"]="3E-",["\x3D"]="3",["\x3E"]="3-",["\x3F"]="3", + ["\x40"]="40",["\x41"]="41",["\x42"]="42",["\x43"]="43",["\x44"]="44",["\x45"]="45",["\x46"]="46",["\x47"]="47",["\x48"]="48",["\x49"]="49",["\x4A"]="4.",["\x4B"]="4E",["\x4C"]="4E-",["\x4D"]="4",["\x4E"]="4-",["\x4F"]="4", + ["\x50"]="50",["\x51"]="51",["\x52"]="52",["\x53"]="53",["\x54"]="54",["\x55"]="55",["\x56"]="56",["\x57"]="57",["\x58"]="58",["\x59"]="59",["\x5A"]="5.",["\x5B"]="5E",["\x5C"]="5E-",["\x5D"]="5",["\x5E"]="5-",["\x5F"]="5", + ["\x60"]="60",["\x61"]="61",["\x62"]="62",["\x63"]="63",["\x64"]="64",["\x65"]="65",["\x66"]="66",["\x67"]="67",["\x68"]="68",["\x69"]="69",["\x6A"]="6.",["\x6B"]="6E",["\x6C"]="6E-",["\x6D"]="6",["\x6E"]="6-",["\x6F"]="6", + ["\x70"]="70",["\x71"]="71",["\x72"]="72",["\x73"]="73",["\x74"]="74",["\x75"]="75",["\x76"]="76",["\x77"]="77",["\x78"]="78",["\x79"]="79",["\x7A"]="7.",["\x7B"]="7E",["\x7C"]="7E-",["\x7D"]="7",["\x7E"]="7-",["\x7F"]="7", + ["\x80"]="80",["\x81"]="81",["\x82"]="82",["\x83"]="83",["\x84"]="84",["\x85"]="85",["\x86"]="86",["\x87"]="87",["\x88"]="88",["\x89"]="89",["\x8A"]="8.",["\x8B"]="8E",["\x8C"]="8E-",["\x8D"]="8",["\x8E"]="8-",["\x8F"]="8", + ["\x90"]="90",["\x91"]="91",["\x92"]="92",["\x93"]="93",["\x94"]="94",["\x95"]="95",["\x96"]="96",["\x97"]="97",["\x98"]="98",["\x99"]="99",["\x9A"]="9.",["\x9B"]="9E",["\x9C"]="9E-",["\x9D"]="9",["\x9E"]="9-",["\x9F"]="9", ["\xA0"]=".0",["\xA1"]=".1",["\xA2"]=".2",["\xA3"]=".3",["\xA4"]=".4",["\xA5"]=".5",["\xA6"]=".6",["\xA7"]=".7",["\xA8"]=".8",["\xA9"]=".9",["\xAA"]="..",["\xAB"]=".E",["\xAC"]=".E-",["\xAD"]=".",["\xAE"]=".-",["\xAF"]=".", ["\xB0"]="E0",["\xB1"]="E1",["\xB2"]="E2",["\xB3"]="E3",["\xB4"]="E4",["\xB5"]="E5",["\xB6"]="E6",["\xB7"]="E7",["\xB8"]="E8",["\xB9"]="E9",["\xBA"]="E.",["\xBB"]="EE",["\xBC"]="EE-",["\xBD"]="E",["\xBE"]="E-",["\xBF"]="E", ["\xC0"]="E-0",["\xC1"]="E-1",["\xC2"]="E-2",["\xC3"]="E-3",["\xC4"]="E-4",["\xC5"]="E-5",["\xC6"]="E-6",["\xC7"]="E-7",["\xC8"]="E-8",["\xC9"]="E-9",["\xCA"]="E-.",["\xCB"]="E-E",["\xCC"]="E-E-",["\xCD"]="E-",["\xCE"]="E--",["\xCF"]="E-", ["\xD0"]="-0",["\xD1"]="-1",["\xD2"]="-2",["\xD3"]="-3",["\xD4"]="-4",["\xD5"]="-5",["\xD6"]="-6",["\xD7"]="-7",["\xD8"]="-8",["\xD9"]="-9",["\xDA"]="-.",["\xDB"]="-E",["\xDC"]="-E-",["\xDD"]="-",["\xDE"]="--",["\xDF"]="-", } - local p_nibbles=P("\30")*Cs(((1-p_last)/remap)^0+p_last)/function(n) + local p_last=S("\x0F\x1F\x2F\x3F\x4F\x5F\x6F\x7F\x8F\x9F\xAF\xBF")+R("\xF0\xFF") + local p_nibbles=P("\30")*Cs(((1-p_last)/remap)^0*(P(1)/remap))/function(n) top=top+1 stack[top]=tonumber(n) or 0 end @@ -15169,7 +15258,7 @@ do if trace_charstrings then showstate("stem") end - stems=stems+top/2 + stems=stems+idiv(top,2) top=0 end local function getmask() @@ -15188,13 +15277,13 @@ do if trace_charstrings then showstate(operator==19 and "hintmark" or "cntrmask") end - stems=stems+top/2 + stems=stems+idiv(top,2) top=0 if stems==0 then elseif stems<=8 then return 1 else - return floor((stems+7)/8) + return idiv(stems+7,8) end end local function unsupported(t) @@ -15233,7 +15322,7 @@ do local function hsbw() if version==1 then if trace_charstrings then - showstate("dotsection") + showstate("hsbw") end width=stack[top] end @@ -15419,76 +15508,98 @@ do [036]=hflex1, [037]=flex1, } - local c_endchar=char(14) - local passon do - local rshift=bit32.rshift - local band=bit32.band - local round=math.round - local encode=table.setmetatableindex(function(t,i) - for i=-2048,-1130 do - t[i]=char(28,band(rshift(i,8),0xFF),band(i,0xFF)) - end - for i=-1131,-108 do - local v=0xFB00-i-108 - t[i]=char(band(rshift(v,8),0xFF),band(v,0xFF)) - end - for i=-107,107 do - t[i]=char(i+139) - end - for i=108,1131 do - local v=0xF700+i-108 - t[i]=char(band(rshift(v,8),0xFF),band(v,0xFF)) - end - for i=1132,2048 do - t[i]=char(28,band(rshift(i,8),0xFF),band(i,0xFF)) - end - return t[i] - end) - local function setvsindex() - local vsindex=stack[top] - updateregions(vsindex) - top=top-1 + local chars=setmetatableindex(function (t,k) + local v=char(k) + t[k]=v + return v + end) + local c_endchar=chars[14] + local encode={} + setmetatableindex(encode,function(t,i) + for i=-2048,-1130 do + t[i]=char(28,band(rshift(i,8),0xFF),band(i,0xFF)) end - local function blend() - local n=stack[top] - top=top-1 - if not axis then - elseif n==1 then - top=top-nofregions - local v=stack[top] + for i=-1131,-108 do + local v=0xFB00-i-108 + t[i]=char(band(rshift(v,8),0xFF),band(v,0xFF)) + end + for i=-107,107 do + t[i]=chars[i+139] + end + for i=108,1131 do + local v=0xF700+i-108 + t[i]=char(extract(v,8,8),extract(v,0,8)) + end + for i=1132,2048 do + t[i]=char(28,band(rshift(i,8),0xFF),band(i,0xFF)) + end + setmetatableindex(encode,function(t,k) + local r=round(k) + local v=rawget(t,r) + if v then + return v + end + local v1=floor(k) + local v2=floor((k-v1)*0x10000) + return char(255,extract(v1,8,8),extract(v1,0,8),extract(v2,8,8),extract(v2,0,8)) + end) + return t[i] + end) + readers.cffencoder=encode + local function p_setvsindex() + local vsindex=stack[top] + updateregions(vsindex) + top=top-1 + end + local function p_blend() + local n=stack[top] + top=top-1 + if not axis then + elseif n==1 then + top=top-nofregions + local v=stack[top] + for r=1,nofregions do + v=v+stack[top+r]*factors[r] + end + stack[top]=round(v) + else + top=top-nofregions*n + local d=top + local k=top-n + for i=1,n do + k=k+1 + local v=stack[k] for r=1,nofregions do - v=v+stack[top+r]*factors[r] - end - stack[top]=round(v) - else - top=top-nofregions*n - local d=top - local k=top-n - for i=1,n do - k=k+1 - local v=stack[k] - for r=1,nofregions do - v=v+stack[d+r]*factors[r] - end - stack[k]=round(v) - d=d+nofregions + v=v+stack[d+r]*factors[r] end + stack[k]=round(v) + d=d+nofregions end end - passon=function(operation) - if operation==15 then - setvsindex() - elseif operation==16 then - blend() - else - for i=1,top do - r=r+1 - result[r]=encode[stack[i]] - end - r=r+1 - result[r]=char(operation) - top=0 - end + end + local function p_getstem() + local n=0 + if top%2~=0 then + n=1 + end + if top>n then + stems=stems+idiv(top-n,2) + end + end + local function p_getmask() + local n=0 + if top%2~=0 then + n=1 + end + if top>n then + stems=stems+idiv(top-n,2) + end + if stems==0 then + return 0 + elseif stems<=8 then + return 1 + else + return idiv(stems+7,8) end end local process @@ -15576,19 +15687,90 @@ do elseif t==12 then i=i+1 local t=tab[i] - local a=subactions[t] - if a then - a(t) + if justpass then + if t>=34 or t<=37 then + for i=1,top do + r=r+1;result[r]=encode[stack[i]] + end + r=r+1;result[r]=chars[12] + r=r+1;result[r]=chars[t] + top=0 + else + local a=subactions[t] + if a then + a(t) + else + top=0 + end + end else - if trace_charstrings then - showvalue("",t) + local a=subactions[t] + if a then + a(t) + else + if trace_charstrings then + showvalue("",t) + end + top=0 end - top=0 end i=i+1 elseif justpass then - passon(t) - i=i+1 + if t==15 then + p_setvsindex() + i=i+1 + elseif t==16 then + local s=p_blend() or 0 + i=i+s+1 + elseif t==1 or t==3 or t==18 or operation==23 then + p_getstem() +if true then + if top>0 then + for i=1,top do + r=r+1;result[r]=encode[stack[i]] + end + top=0 + end + r=r+1;result[r]=chars[t] +else + top=0 +end + i=i+1 + elseif t==19 or t==20 then + local s=p_getmask() or 0 +if true then + if top>0 then + for i=1,top do + r=r+1;result[r]=encode[stack[i]] + end + top=0 + end + r=r+1;result[r]=chars[t] + for j=1,s do + i=i+1 + r=r+1;result[r]=chars[tab[i]] + end +else + i=i+s + top=0 +end + i=i+1 + elseif t==9 then + top=0 + i=i+1 + elseif t==13 then + local s=hsbw() or 0 + i=i+s+1 + else + if top>0 then + for i=1,top do + r=r+1;result[r]=encode[stack[i]] + end + top=0 + end + r=r+1;result[r]=chars[t] + i=i+1 + end else local a=actions[t] if a then @@ -15609,18 +15791,20 @@ do end end local function setbias(globals,locals) - if version==1 then - return - false, - false - else local g,l=#globals,#locals return ((g<1240 and 107) or (g<33900 and 1131) or 32768)+1, ((l<1240 and 107) or (l<33900 and 1131) or 32768)+1 - end end local function processshape(tab,index) + if not tab then + glyphs[index]={ + boundingbox={ 0,0,0,0 }, + width=0, + name=charset and charset[index] or nil, + } + return + end tab=bytetable(tab) x=0 y=0 @@ -15733,15 +15917,18 @@ do glyphs=glphs or {} globalbias,localbias=setbias(globals,locals) nominalwidth,defaultwidth=setwidths(dictionary.private) - startparsing(fontdata,data,streams) - for index=1,#charstrings do - processshape(charstrings[index],index-1) - charstrings[index]=nil + if charstrings then + startparsing(fontdata,data,streams) + for index=1,#charstrings do + processshape(charstrings[index],index-1) + end + stopparsing(fontdata,data) + else + report("no charstrings") end - stopparsing(fontdata,data) return glyphs end - parsecharstring=function(fontdata,data,dictionary,tab,glphs,index,doshapes,tversion) + parsecharstring=function(fontdata,data,dictionary,tab,glphs,index,doshapes,tversion,streams) keepcurve=doshapes version=tversion strings=data.strings @@ -15750,6 +15937,7 @@ do charset=false vsindex=dictionary.vsindex or 0 glyphs=glphs or {} + justpass=streams==true globalbias,localbias=setbias(globals,locals) nominalwidth,defaultwidth=setwidths(dictionary.private) processshape(tab,index-1) @@ -15903,7 +16091,7 @@ local function readfdselect(f,fontdata,data,glyphs,doshapes,version,streams) local format=readbyte(f) if format==1 then for i=0,nofglyphs do - local index=readbyte(i) + local index=readbyte(f) fdindex[i]=index if index>maxindex then maxindex=index @@ -15932,30 +16120,33 @@ local function readfdselect(f,fontdata,data,glyphs,doshapes,version,streams) end if maxindex>=0 then local cidarray=cid.fdarray - setposition(f,header.offset+cidarray) - local dictionaries=readlengths(f) - for i=1,#dictionaries do - dictionaries[i]=readstring(f,dictionaries[i]) - end - parsedictionaries(data,dictionaries) - cid.dictionaries=dictionaries - readcidprivates(f,data) - for i=1,#dictionaries do - readlocals(f,data,dictionaries[i]) - end - startparsing(fontdata,data,streams) - for i=1,#charstrings do - parsecharstring(fontdata,data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes,version) - charstrings[i]=nil + if cidarray then + setposition(f,header.offset+cidarray) + local dictionaries=readlengths(f) + for i=1,#dictionaries do + dictionaries[i]=readstring(f,dictionaries[i]) + end + parsedictionaries(data,dictionaries) + cid.dictionaries=dictionaries + readcidprivates(f,data) + for i=1,#dictionaries do + readlocals(f,data,dictionaries[i]) + end + startparsing(fontdata,data,streams) + for i=1,#charstrings do + parsecharstring(fontdata,data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes,version,streams) + end + stopparsing(fontdata,data) + else + report("no cid array") end - stopparsing(fontdata,data) end end local gotodatatable=readers.helpers.gotodatatable local function cleanup(data,dictionaries) end function readers.cff(f,fontdata,specification) - local tableoffset=gotodatatable(f,fontdata,"cff",specification.details) + local tableoffset=gotodatatable(f,fontdata,"cff",specification.details or specification.glyphs) if tableoffset then local header=readheader(f) if header.major~=1 then @@ -15976,14 +16167,16 @@ function readers.cff(f,fontdata,specification) parsedictionaries(data,dictionaries,"cff") local dic=dictionaries[1] local cid=dic.cid - fontdata.cffinfo={ - familynamename=dic.familyname, + local cffinfo={ + familyname=dic.familyname, fullname=dic.fullname, boundingbox=dic.boundingbox, weight=dic.weight, italicangle=dic.italicangle, underlineposition=dic.underlineposition, underlinethickness=dic.underlinethickness, + defaultwidth=dic.defaultwidthx, + nominalwidth=dic.nominalwidthx, monospaced=dic.monospaced, } fontdata.cidinfo=cid and { @@ -15991,12 +16184,30 @@ function readers.cff(f,fontdata,specification) ordering=cid.ordering, supplement=cid.supplement, } - if specification.glyphs then - local all=specification.shapes or false + fontdata.cffinfo=cffinfo + local all=specification.shapes or specification.streams or false + if specification.glyphs or all then if cid and cid.fdselect then - readfdselect(f,fontdata,data,glyphs,all,"cff") + readfdselect(f,fontdata,data,glyphs,all,"cff",specification.streams) else - readnoselect(f,fontdata,data,glyphs,all,"cff") + readnoselect(f,fontdata,data,glyphs,all,"cff",specification.streams) + end + end + local private=dic.private + if private then + local data=private.data + if type(data)=="table" then + cffinfo.defaultwidth=data.defaultwidth or cffinfo.defaultwidth + cffinfo.nominalwidth=data.nominalwidth or cffinfo.nominalwidth + cffinfo.bluevalues=data.bluevalues + cffinfo.otherblues=data.otherblues + cffinfo.familyblues=data.familyblues + cffinfo.familyotherblues=data.familyotherblues + cffinfo.bluescale=data.bluescale + cffinfo.blueshift=data.blueshift + cffinfo.bluefuzz=data.bluefuzz + cffinfo.stdhw=data.stdhw + cffinfo.stdvw=data.stdvw end end cleanup(data,dictionaries) @@ -16030,7 +16241,7 @@ function readers.cff2(f,fontdata,specification) end data.factors=specification.factors local cid=data.dictionaries[1].cid - local all=specification.shapes or false + local all=specification.shapes or specification.streams or false if cid and cid.fdselect then readfdselect(f,fontdata,data,glyphs,all,"cff2",specification.streams) else @@ -16060,7 +16271,7 @@ function readers.cffcheck(filename) dictionaries=dictionaries, strings=strings, glyphs=glyphs, - nofglyphs=4, + nofglyphs=0, } parsedictionaries(data,dictionaries,"cff") local cid=data.dictionaries[1].cid @@ -16087,8 +16298,10 @@ if not modules then modules={} end modules ['font-ttf']={ local next,type,unpack=next,type,unpack local band,rshift=bit32.band,bit32.rshift local sqrt,round=math.sqrt,math.round -local char=string.char +local char,rep=string.char,string.rep local concat=table.concat +local idiv=number.idiv +local setmetatableindex=table.setmetatableindex local report=logs.reporter("otf reader","ttf") local trace_deltas=false local readers=fonts.handlers.otf.readers @@ -16153,22 +16366,41 @@ local function mergecomposites(glyphs,shapes) local yscale=matrix[4] local xoffset=matrix[5] local yoffset=matrix[6] - for i=1,#subpoints do - local p=subpoints[i] - local x=p[1] - local y=p[2] - nofpoints=nofpoints+1 - points[nofpoints]={ - xscale*x+xrotate*y+xoffset, - yscale*y+yrotate*x+yoffset, - p[3] - } + local count=#subpoints + if xscale==1 and yscale==1 and xrotate==0 and yrotate==0 then + for i=1,count do + local p=subpoints[i] + nofpoints=nofpoints+1 + points[nofpoints]={ + p[1]+xoffset, + p[2]+yoffset, + p[3] + } + end + else + for i=1,count do + local p=subpoints[i] + local x=p[1] + local y=p[2] + nofpoints=nofpoints+1 + points[nofpoints]={ + xscale*x+xrotate*y+xoffset, + yscale*y+yrotate*x+yoffset, + p[3] + } + end end - for i=1,#subcontours do + local subcount=#subcontours + if subcount==1 then nofcontours=nofcontours+1 - contours[nofcontours]=offset+subcontours[i] + contours[nofcontours]=offset+subcontours[1] + else + for i=1,#subcontours do + nofcontours=nofcontours+1 + contours[nofcontours]=offset+subcontours[i] + end end - offset=offset+#subpoints + offset=offset+count else report("missing contours composite %s, component %s of %s, glyph %s",index,i,#components,subindex) end @@ -16178,7 +16410,7 @@ local function mergecomposites(glyphs,shapes) shape.components=nil return contours,points end - for index=1,#glyphs do + for index=0,#glyphs-1 do local shape=shapes[index] if shape then local components=shape.components @@ -16188,7 +16420,7 @@ local function mergecomposites(glyphs,shapes) end end end -local function readnothing(f,nofcontours) +local function readnothing(f) return { type="nothing", } @@ -16282,8 +16514,8 @@ local function applyaxis(glyph,shape,deltas,dowidth) end end local quadratic=false -local function contours2outlines_normal(glyphs,shapes) - for index=1,#glyphs do +local function contours2outlines_normal(glyphs,shapes) + for index=0,#glyphs-1 do local shape=shapes[index] if shape then local glyph=glyphs[index] @@ -16398,7 +16630,7 @@ local function contours2outlines_normal(glyphs,shapes) end end local function contours2outlines_shaped(glyphs,shapes,keepcurve) - for index=1,#glyphs do + for index=0,#glyphs-1 do local shape=shapes[index] if shape then local glyph=glyphs[index] @@ -16577,115 +16809,128 @@ local function toshort(n) end return char(band(rshift(n,8),0xFF),band(n,0xFF)) end +local chars=setmetatableindex(function(t,k) + for i=0,255 do local v=char(i) t[i]=v end return t[k] +end) local function repackpoints(glyphs,shapes) local noboundingbox={ 0,0,0,0 } local result={} - for index=1,#glyphs do + local xpoints={} + local ypoints={} + for index=0,#glyphs-1 do local shape=shapes[index] if shape then local r=0 local glyph=glyphs[index] - if false then - else - local contours=shape.contours - local nofcontours=contours and #contours or 0 - local boundingbox=glyph.boundingbox or noboundingbox - r=r+1 result[r]=toshort(nofcontours) - r=r+1 result[r]=toshort(boundingbox[1]) - r=r+1 result[r]=toshort(boundingbox[2]) - r=r+1 result[r]=toshort(boundingbox[3]) - r=r+1 result[r]=toshort(boundingbox[4]) - if nofcontours>0 then - for i=1,nofcontours do - r=r+1 result[r]=toshort(contours[i]-1) - end - r=r+1 result[r]=s_zero - local points=shape.points - local currentx=0 - local currenty=0 - local xpoints={} - local ypoints={} - local x=0 - local y=0 - local lastflag=nil - local nofflags=0 - for i=1,#points do - local pt=points[i] - local px=pt[1] - local py=pt[2] - local fl=pt[3] and 0x01 or 0x00 - if px==currentx then - fl=fl+0x10 + local contours=shape.contours + local nofcontours=contours and #contours or 0 + local boundingbox=glyph.boundingbox or noboundingbox + r=r+1 result[r]=toshort(nofcontours) + r=r+1 result[r]=toshort(boundingbox[1]) + r=r+1 result[r]=toshort(boundingbox[2]) + r=r+1 result[r]=toshort(boundingbox[3]) + r=r+1 result[r]=toshort(boundingbox[4]) + if nofcontours>0 then + for i=1,nofcontours do + r=r+1 result[r]=toshort(contours[i]-1) + end + r=r+1 result[r]=s_zero + local points=shape.points + local currentx=0 + local currenty=0 + local x=0 + local y=0 + local lastflag=nil + local nofflags=0 + for i=1,#points do + local pt=points[i] + local px=pt[1] + local py=pt[2] + local fl=pt[3] and 0x01 or 0x00 + if px==currentx then + fl=fl+0x10 + else + local dx=round(px-currentx) + x=x+1 + if dx<-255 or dx>255 then + xpoints[x]=toshort(dx) + elseif dx<0 then + fl=fl+0x02 + xpoints[x]=chars[-dx] + elseif dx>0 then + fl=fl+0x12 + xpoints[x]=chars[dx] else - local dx=round(px-currentx) - if dx<-255 or dx>255 then - x=x+1 xpoints[x]=toshort(dx) - elseif dx<0 then - fl=fl+0x02 - x=x+1 xpoints[x]=char(-dx) - elseif dx>0 then - fl=fl+0x12 - x=x+1 xpoints[x]=char(dx) - else - fl=fl+0x02 - x=x+1 xpoints[x]=c_zero - end + fl=fl+0x02 + xpoints[x]=c_zero end - if py==currenty then - fl=fl+0x20 + end + if py==currenty then + fl=fl+0x20 + else + local dy=round(py-currenty) + y=y+1 + if dy<-255 or dy>255 then + ypoints[y]=toshort(dy) + elseif dy<0 then + fl=fl+0x04 + ypoints[y]=chars[-dy] + elseif dy>0 then + fl=fl+0x24 + ypoints[y]=chars[dy] else - local dy=round(py-currenty) - if dy<-255 or dy>255 then - y=y+1 ypoints[y]=toshort(dy) - elseif dy<0 then - fl=fl+0x04 - y=y+1 ypoints[y]=char(-dy) - elseif dy>0 then - fl=fl+0x24 - y=y+1 ypoints[y]=char(dy) - else - fl=fl+0x04 - y=y+1 ypoints[y]=c_zero - end - end - currentx=px - currenty=py - if lastflag==fl then - nofflags=nofflags+1 - else - if nofflags==1 then - r=r+1 result[r]=char(lastflag) - elseif nofflags==2 then - r=r+1 result[r]=char(lastflag,lastflag) - elseif nofflags>2 then - lastflag=lastflag+0x08 - r=r+1 result[r]=char(lastflag,nofflags-1) - end - nofflags=1 - lastflag=fl + fl=fl+0x04 + ypoints[y]=c_zero end end - if nofflags==1 then - r=r+1 result[r]=char(lastflag) - elseif nofflags==2 then - r=r+1 result[r]=char(lastflag,lastflag) - elseif nofflags>2 then - lastflag=lastflag+0x08 - r=r+1 result[r]=char(lastflag,nofflags-1) - end - r=r+1 result[r]=concat(xpoints) - r=r+1 result[r]=concat(ypoints) + currentx=px + currenty=py + if lastflag==fl then + nofflags=nofflags+1 + else + if nofflags==1 then + r=r+1 result[r]=chars[lastflag] + elseif nofflags==2 then + r=r+1 result[r]=char(lastflag,lastflag) + elseif nofflags>2 then + lastflag=lastflag+0x08 + r=r+1 result[r]=char(lastflag,nofflags-1) + end + nofflags=1 + lastflag=fl + end + end + if nofflags==1 then + r=r+1 result[r]=chars[lastflag] + elseif nofflags==2 then + r=r+1 result[r]=char(lastflag,lastflag) + elseif nofflags>2 then + lastflag=lastflag+0x08 + r=r+1 result[r]=char(lastflag,nofflags-1) + end + r=r+1 result[r]=concat(xpoints,"",1,x) + r=r+1 result[r]=concat(ypoints,"",1,y) + end + local stream=concat(result,"",1,r) + local length=#stream + local padding=idiv(length+3,4)*4-length + if padding>0 then + if padding==1 then + padding="\0" + elseif padding==2 then + padding="\0\0" + else + padding="\0\0\0" end + padding=stream..padding end - glyph.stream=concat(result,"",1,r) - else + glyph.stream=stream end end end +local flags={} local function readglyph(f,nofcontours) local points={} - local instructions={} - local flags={} local contours={} for i=1,nofcontours do contours[i]=readshort(f)+1 @@ -16698,9 +16943,15 @@ local function readglyph(f,nofcontours) local flag=readbyte(f) flags[i]=flag if band(flag,0x08)~=0 then - for j=1,readbyte(f) do + local n=readbyte(f) + if n==1 then i=i+1 flags[i]=flag + else + for j=1,n do + i=i+1 + flags[i]=flag + end end end i=i+1 @@ -16708,15 +16959,13 @@ local function readglyph(f,nofcontours) local x=0 for i=1,nofpoints do local flag=flags[i] - local short=band(flag,0x02)~=0 - local same=band(flag,0x10)~=0 - if short then - if same then + if band(flag,0x02)~=0 then + if band(flag,0x10)~=0 then x=x+readbyte(f) else x=x-readbyte(f) end - elseif same then + elseif band(flag,0x10)~=0 then else x=x+readshort(f) end @@ -16725,15 +16974,13 @@ local function readglyph(f,nofcontours) local y=0 for i=1,nofpoints do local flag=flags[i] - local short=band(flag,0x04)~=0 - local same=band(flag,0x20)~=0 - if short then - if same then + if band(flag,0x04)~=0 then + if band(flag,0x20)~=0 then y=y+readbyte(f) else y=y-readbyte(f) end - elseif same then + elseif band(flag,0x20)~=0 then else y=y+readshort(f) end @@ -16816,7 +17063,7 @@ local function readcomposite(f) if band(flags,0x0100)~=0 then instructions=true end - if not band(flags,0x0020)~=0 then + if band(flags,0x0020)==0 then break end end @@ -16831,21 +17078,27 @@ function readers.loca(f,fontdata,specification) if datatable then local offset=fontdata.tables.glyf.offset local format=fontdata.fontheader.indextolocformat + local profile=fontdata.maximumprofile + local nofglyphs=profile and profile.nofglyphs local locations={} setposition(f,datatable.offset) if format==1 then - local nofglyphs=datatable.length/4-2 + if not nofglyphs then + nofglyphs=idiv(datatable.length,4)-1 + end for i=0,nofglyphs do locations[i]=offset+readulong(f) end fontdata.nofglyphs=nofglyphs else - local nofglyphs=datatable.length/2-2 + if not nofglyphs then + nofglyphs=idiv(datatable.length,2)-1 + end for i=0,nofglyphs do locations[i]=offset+readushort(f)*2 end - fontdata.nofglyphs=nofglyphs end + fontdata.nofglyphs=nofglyphs fontdata.locations=locations end end @@ -16860,15 +17113,16 @@ function readers.glyf(f,fontdata,specification) local filesize=fontdata.filesize local nothing={ 0,0,0,0 } local shapes={} - local loadshapes=specification.shapes or specification.instance - for index=0,nofglyphs do + local loadshapes=specification.shapes or specification.instance or specification.streams + for index=0,nofglyphs-1 do local location=locations[index] + local length=locations[index+1]-location if location>=filesize then report("discarding %s glyphs due to glyph location bug",nofglyphs-index+1) fontdata.nofglyphs=index-1 fontdata.badfont=true break - elseif location>0 then + elseif length>0 then setposition(f,location) local nofcontours=readshort(f) glyphs[index].boundingbox={ @@ -16879,7 +17133,7 @@ function readers.glyf(f,fontdata,specification) } if not loadshapes then elseif nofcontours==0 then - shapes[index]=readnothing(f,nofcontours) + shapes[index]=readnothing(f) elseif nofcontours>0 then shapes[index]=readglyph(f,nofcontours) else @@ -16887,7 +17141,7 @@ function readers.glyf(f,fontdata,specification) end else if loadshapes then - shapes[index]={} + shapes[index]=readnothing(f) end glyphs[index].boundingbox=nothing end @@ -16904,7 +17158,13 @@ function readers.glyf(f,fontdata,specification) contours2outlines_shaped(glyphs,shapes,specification.shapes) end elseif specification.shapes then - contours2outlines_normal(glyphs,shapes) + if specification.streams then + repackpoints(glyphs,shapes) + else + contours2outlines_normal(glyphs,shapes) + end + elseif specification.streams then + repackpoints(glyphs,shapes) end end end @@ -19117,7 +19377,7 @@ do end local function loadvariations(f,fontdata,variationsoffset,lookuptypes,featurehash,featureorder) setposition(f,variationsoffset) - local version=readulong(f) + local version=readulong(f) local nofrecords=readulong(f) local records={} for i=1,nofrecords do @@ -19986,8 +20246,7 @@ function readers.avar(f,fontdata,specification) end return false end - local majorversion=readushort(f) - local minorversion=readushort(f) + local version=readulong(f) local reserved=readushort(f) local nofaxis=readushort(f) local segments={} @@ -26345,22 +26604,17 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip else end end - else + else local discfound=false - local lastdisc=nil local hasmarks=marks[startchar] while current do local char,id=ischar(current,currentfont) if char then if skiphash and skiphash[char] then current=getnext(current) - else - local lg=ligature[char] + else + local lg=ligature[char] if lg then - if not discfound and lastdisc then - discfound=lastdisc - lastdisc=nil - end if marks[char] then hasmarks=true end @@ -26374,42 +26628,82 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip elseif char==false then break elseif id==disc_code then - local replace=getfield(current,"replace") - if replace then - while replace do - local char,id=ischar(replace,currentfont) - if char then - local lg=ligature[char] - if lg then - if marks[char] then - hasmarks=true - end - ligature=lg - replace=getnext(replace) - else - return head,start,false,false - end - else - return head,start,false,false - end - end - stop=current - end - lastdisc=current - current=getnext(current) + discfound=current + break else break end end + if discfound then + local pre,post,replace=getdisc(discfound) + local match + if replace then + local char=ischar(replace,currentfont) + if char and ligature[char] then + match=true + end + end + if not match and pre then + local char=ischar(pre,currentfont) + if char and ligature[char] then + match=true + end + end + if not match and not pre or not replace then + local n=getnext(discfound) + local char=ischar(n,currentfont) + if char and ligature[char] then + match=true + end + end + if match then + local ishead=head==start + local prev=getprev(start) + if stop then + setnext(stop) + local tail=getprev(stop) + local copy=copy_node_list(start) + local liat=find_node_tail(copy) + if pre and replace then + setlink(liat,pre) + end + if replace then + setlink(tail,replace) + end + pre=copy + replace=start + else + setnext(start) + local copy=copy_node(start) + if pre then + setlink(copy,pre) + end + if replace then + setlink(start,replace) + end + pre=copy + replace=start + end + setdisc(discfound,pre,post,replace) + if prev then + setlink(prev,discfound) + else + setprev(discfound) + head=discfound + end + start=discfound + return head,start,true,true + end + end local lig=ligature.ligature if lig then if stop then if trace_ligatures then local stopchar=getchar(stop) - head,start=toligature(head,start,stop,lig,dataset,sequence,skiphash,discfound,hasmarks) + head,start=toligature(head,start,stop,lig,dataset,sequence,skiphash,false,hasmarks) logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(lig)) else - head,start=toligature(head,start,stop,lig,dataset,sequence,skiphash,discfound,hasmarks) + head,start=toligature(head,start,stop,lig,dataset,sequence,skiphash,false,hasmarks) end else resetinjection(start) @@ -26418,11 +26712,11 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(dataset,sequence),gref(startchar),gref(lig)) end end - return head,start,true,discfound + return head,start,true,false else end end - return head,start,false,discfound + return head,start,false,false end function handlers.gpos_single(head,start,dataset,sequence,kerns,rlmode,skiphash,step,injection) local startchar=getchar(start) @@ -28901,9 +29195,10 @@ do a=true end if a then - local ok - head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step) - if start then + local ok,df + head,start,ok,df=handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step) + if df then + elseif start then start=getnext(start) end else @@ -28957,21 +29252,24 @@ do a=true end if a then + local ok,df for i=m[1],m[2] do local step=steps[i] local lookupcache=step.coverage local lookupmatch=lookupcache[char] if lookupmatch then - local ok - head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step) - if ok then + head,start,ok,df=handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step) + if df then + break + elseif ok then break elseif not start then break end end end - if start then + if df then + elseif start then start=getnext(start) end else @@ -31472,7 +31770,7 @@ do done=f_used(n) hashed[pdf]=done end - return nil,done,nil + return done end else local openpdf=pdfe.new @@ -31485,7 +31783,7 @@ do done=f_used(n) hashed[pdf]=done end - return nil,done,nil + return done end end end @@ -31506,6 +31804,10 @@ local function pdftovirtual(tfmdata,pdfshapes,kind) local b,e=getactualtext(tounicode(0xFFFD)) local actualb={ "pdf","page",b } local actuale={ "pdf","page",e } + local vfimage=lpdf and lpdf.vfimage or function(wd,ht,dp,data,name) + local name=storepdfdata(data) + return { "image",{ filename=name,width=wd,height=ht,depth=dp } } + end for unicode,character in sortedhash(characters) do local index=character.index if index then @@ -31524,21 +31826,18 @@ local function pdftovirtual(tfmdata,pdfshapes,kind) dy=0 end if data then - local setcode,name,nilcode=storepdfdata(data) - if name then - local bt=unicode and getactualtext(unicode) - local wd=character.width or 0 - local ht=character.height or 0 - local dp=character.depth or 0 - character.commands={ - not unicode and actualb or { "pdf","page",(getactualtext(unicode)) }, - downcommand[dp+dy*hfactor], - rightcommand[dx*hfactor], - { "image",{ filename=name,width=wd,height=ht,depth=dp } }, - actuale, - } - character[kind]=true - end + local bt=unicode and getactualtext(unicode) + local wd=character.width or 0 + local ht=character.height or 0 + local dp=character.depth or 0 + character.commands={ + not unicode and actualb or { "pdf","page",(getactualtext(unicode)) }, + downcommand[dp+dy*hfactor], + rightcommand[dx*hfactor], + vfimage(wd,ht,dp,data,name), + actuale, + } + character[kind]=true end end end @@ -32508,7 +32807,7 @@ local match,lower,gsub,strip,find=string.match,string.lower,string.gsub,string.s local char,byte,sub=string.char,string.byte,string.sub local abs=math.abs local bxor,rshift=bit32.bxor,bit32.rshift -local P,S,R,Cmt,C,Ct,Cs,Carg,Cf,Cg=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg,lpeg.Cf,lpeg.Cg +local P,S,R,V,Cmt,C,Ct,Cs,Carg,Cf,Cg,Cc=lpeg.P,lpeg.S,lpeg.R,lpeg.V,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg,lpeg.Cf,lpeg.Cg,lpeg.Cc local lpegmatch,patterns=lpeg.match,lpeg.patterns local trace_indexing=false trackers.register("afm.indexing",function(v) trace_indexing=v end) local trace_loading=false trackers.register("afm.loading",function(v) trace_loading=v end) @@ -32551,14 +32850,21 @@ do local routines,vector,chars,n,m local initialize=function(str,position,size) n=0 - m=size + m=size return position+1 end local setroutine=function(str,position,index,size,filename) - local forward=position+tonumber(size) + if routines[index] then + return false + end + local forward=position+size local stream=decrypt(sub(str,position+1,forward),4330,4) routines[index]={ byte(stream,1,#stream) } - return forward + n=n+1 + if n>=m then + return #str + end + return forward+1 end local setvector=function(str,position,name,size,filename) local forward=position+tonumber(size) @@ -32598,7 +32904,7 @@ do local p_np=spacing*(P("NP")+P("|")) local p_nd=spacing*(P("ND")+P("|")) local p_filterroutines= - (1-subroutines)^0*subroutines*spaces*Cmt(cardinal,initialize)*(Cmt(cardinal*spaces*cardinal*p_rd*Carg(1),setroutine)*p_np+P(1))^1 + (1-subroutines)^0*subroutines*spaces*Cmt(cardinal,initialize)*(Cmt(cardinal*spaces*cardinal*p_rd*Carg(1),setroutine)*p_np+(1-p_nd))^1 local p_filtershapes= (1-charstrings)^0*charstrings*spaces*Cmt(cardinal,initialize)*(Cmt(name*spaces*cardinal*p_rd*Carg(1),setshapes)*p_nd+P(1))^1 local p_filternames=Ct ( @@ -32607,7 +32913,18 @@ do local p_filterencoding=(1-encoding)^0*encoding*spaces*digits*spaces*array*(1-dup)^0*Cf( Ct("")*Cg(spacing*dup*spaces*cardinal*spaces*name*spaces*put)^1 ,rawset) - local function loadpfbvector(filename,shapestoo) + local key=spacing*P("/")*R("az","AZ") + local str=spacing*Cs { (P("(")/"")*((1-P("\\(")-P("\\)")-S("()"))+V(1))^0*(P(")")/"") } + local num=spacing*(R("09")+S("+-."))^1/tonumber + local arr=spacing*Ct (S("[{")*(num)^0*spacing*S("]}")) + local boo=spacing*(P("true")*Cc(true)+P("false")*Cc(false)) + local nam=spacing*P("/")*Cs(R("az","AZ")^1) + local p_filtermetadata=( + P("/")*Carg(1)*(( + C("version")*str+C("Copyright")*str+C("Notice")*str+C("FullName")*str+C("FamilyName")*str+C("Weight")*str+C("ItalicAngle")*num+C("isFixedPitch")*boo+C("UnderlinePosition")*num+C("UnderlineThickness")*num+C("FontName")*nam+C("FontMatrix")*arr+C("FontBBox")*arr + ) )/function(t,k,v) t[lower(k)]=v end+P(1) + )^0*Carg(1) + local function loadpfbvector(filename,shapestoo,streams) local data=io.loaddata(resolvers.findfile(filename)) if not data then report_pfb("no data in %a",filename) @@ -32625,9 +32942,10 @@ do binary=decrypt(binary,55665,4) local names={} local encoding=lpegmatch(p_filterencoding,ascii) + local metadata=lpegmatch(p_filtermetadata,ascii,1,{}) local glyphs={} routines,vector,chars={},{},{} - if shapestoo then + if shapestoo or streams then lpegmatch(p_filterroutines,binary,1,filename) lpegmatch(p_filtershapes,binary,1,filename) local data={ @@ -32639,13 +32957,13 @@ do } }, } - fonts.handlers.otf.readers.parsecharstrings(false,data,glyphs,true,true) + fonts.handlers.otf.readers.parsecharstrings(false,data,glyphs,true,"cff",streams) else lpegmatch(p_filternames,binary,1,filename) end names=vector routines,vector,chars=nil,nil,nil - return names,encoding,glyphs + return names,encoding,glyphs,metadata end local pfb=handlers.pfb or {} handlers.pfb=pfb @@ -33731,6 +34049,7 @@ if not modules then modules={} end modules ['font-tfm']={ local next,type=next,type local match,format=string.match,string.format local concat,sortedhash=table.concat,table.sortedhash +local idiv=number.idiv local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end) local trace_features=false trackers.register("tfm.features",function(v) trace_features=v end) local report_defining=logs.reporter("fonts","defining") @@ -33793,7 +34112,8 @@ local function read_from_tfm(specification) properties.psname=tfmdata.psname properties.fullname=tfmdata.fullname properties.filename=specification.filename - properties.format=fonts.formats.tfm + properties.format=tfmdata.format or fonts.formats.tfm + properties.usedbitmap=tfmdata.usedbitmap tfmdata.properties=properties tfmdata.resources=resources tfmdata.parameters=parameters @@ -33837,6 +34157,9 @@ local function read_from_tfm(specification) end end shared.processes=next(features) and tfm.setfeatures(tfmdata,features) or nil +if size<0 then + size=idiv(65536*-size,100) +end parameters.factor=1 parameters.size=size parameters.slant=parameters.slant or parameters[1] or 0 @@ -33994,7 +34317,7 @@ do local originals=tfmdata.characters local indices={} local parentfont={ "font",1 } - local private=tfmdata or fonts.constructors.privateoffset + local private=tfmdata.privateoffset or fonts.constructors.privateoffset local reported=encdone[tfmfile][encfile] local backmap=vector and table.swapped(vector) local done={} @@ -34084,21 +34407,16 @@ CMapName currentdict /CMap defineresource pop end end end ]] - local flushstreamobject=lpdf and lpdf.flushstreamobject - local setfontattributes=pdf.setfontattributes - if flushstreamobject then - else + local flushstreamobject=lpdf and lpdf.flushstreamobject + local setfontattributes=lpdf and lpdf.setfontattributes + if not flushstreamobject then flushstreamobject=function(data) - return pdf.obj { - immediate=true, - type="stream", - string=data, - } + return pdf.obj { immediate=true,type="stream",string=data } end end if not setfontattributes then setfontattributes=function(id,data) - print(format("your luatex is too old so no tounicode bitmap font%i",id)) + return pdf.setfontattributes(id,data) end end function tfm.addtounicode(tfmdata) -- cgit v1.2.3