diff options
Diffstat (limited to 'Build')
-rw-r--r-- | Build/source/texk/web2c/mfluadir/mfluac.c | 8 | ||||
-rw-r--r-- | Build/source/texk/web2c/mfluadir/mfluac.h | 5 | ||||
-rw-r--r-- | Build/source/texk/web2c/mfluadir/mfluaextra.h | 3 | ||||
-rw-r--r-- | Build/source/texk/web2c/mfluadir/mfluatrap/mflua.lua | 7 | ||||
-rw-r--r-- | Build/source/texk/web2c/mfluadir/mfluatrap/mflua_ttx_backend.lua | 653 |
5 files changed, 587 insertions, 89 deletions
diff --git a/Build/source/texk/web2c/mfluadir/mfluac.c b/Build/source/texk/web2c/mfluadir/mfluac.c index aea6a8a7e96..391e157c76c 100644 --- a/Build/source/texk/web2c/mfluadir/mfluac.c +++ b/Build/source/texk/web2c/mfluadir/mfluac.c @@ -13,6 +13,11 @@ #if defined(JIT) #include <luajit.h> #endif + +/* See shell_cmd_is_allowed below */ +shellenabledp = 1; +restrictedshell = 0; + /**************************************************************/ /* */ /* private functions */ @@ -1414,3 +1419,6 @@ int mfluarunscript(halfword j, halfword first, halfword limit) } return 0; } + +/* TODO: check if shell_cmd_is_allowed make se sense */ +int shell_cmd_is_allowed(const char *cmd, char **safecmd, char **cmdname){return 1;} diff --git a/Build/source/texk/web2c/mfluadir/mfluac.h b/Build/source/texk/web2c/mfluadir/mfluac.h index 10f7240c51e..ed793cfc5c0 100644 --- a/Build/source/texk/web2c/mfluadir/mfluac.h +++ b/Build/source/texk/web2c/mfluadir/mfluac.h @@ -46,6 +46,11 @@ extern int mfluaprinttransitionlineto(integer, integer); extern int mfluaPREmakeellipse(integer, integer, integer, integer, integer, integer); extern int mfluaPOSTmakeellipse(integer, integer, integer, integer, integer, integer); +/* TODO: check if shell_cmd_is_allowed makes sense */ +extern int shellenabledp; +extern int restrictedshell; +extern int shell_cmd_is_allowed(const char *, char **, char **); + #include <lauxlib.h> extern int luaopen_kpse(lua_State * L); diff --git a/Build/source/texk/web2c/mfluadir/mfluaextra.h b/Build/source/texk/web2c/mfluadir/mfluaextra.h index f1753c94054..4e5fb50aa2e 100644 --- a/Build/source/texk/web2c/mfluadir/mfluaextra.h +++ b/Build/source/texk/web2c/mfluadir/mfluaextra.h @@ -21,4 +21,5 @@ #define INPUT_FORMAT kpse_mf_format #define INI_PROGRAM "inimflua" #define VIR_PROGRAM "virmflua" -#define MFLua
\ No newline at end of file +#define MFLua + diff --git a/Build/source/texk/web2c/mfluadir/mfluatrap/mflua.lua b/Build/source/texk/web2c/mfluadir/mfluatrap/mflua.lua index 1f8cd8c175b..ec9864a18bd 100644 --- a/Build/source/texk/web2c/mfluadir/mfluatrap/mflua.lua +++ b/Build/source/texk/web2c/mfluadir/mfluatrap/mflua.lua @@ -441,7 +441,6 @@ chMF(mflua.MF,print_scaled);mflua.MF.print_scaled = print_scaled local function print_two(x,y) -- {prints `|(x,y)|'} local res -- debug - -- print("print_two(x,y)",x,y) res = '(' .. print_scaled(x) .. ',' .. print_scaled(y) .. ')' return res end @@ -1544,12 +1543,12 @@ local function _store_current_contour() if (#bezier_octant_contour == 0) then local _t = {} for i,v in ipairs(bezier_octant_I) do _t[i] = v end - bezier_octant_contour[1] = _t + bezier_octant_contour[1] = _t; else local _cnt=0 for i,v in ipairs(bezier_octant_contour) do _cnt=_cnt+#v end local _t = {} - for i,v in ipairs(bezier_octant_I) do if i>_cnt then _t[#_t+1] = v end end + for i,v in ipairs(bezier_octant_I) do if i>_cnt then _t[#_t+1] = v; end end bezier_octant_contour[#bezier_octant_contour+1] = _t end mflua.do_add_to.bezier_octant_contour = bezier_octant_contour @@ -1754,7 +1753,7 @@ local function print_specification_contour(h) end_loop_2=true else bezier_contour['p'] = print_two_true(x_coord(p),y_coord(p),octant); - bezier_contour['control1'] = print_two_true(right_x(p),right_y(p),octant) + bezier_contour['control1'] = print_two_true(right_x(p),right_y(p),octant) bezier_contour['control2'] = print_two_true(left_x(q),left_y(q),octant) bezier_contour['q'] = print_two_true(x_coord(q),y_coord(q),octant) beziers_contour[#beziers_contour+1] = bezier_contour diff --git a/Build/source/texk/web2c/mfluadir/mfluatrap/mflua_ttx_backend.lua b/Build/source/texk/web2c/mfluadir/mfluatrap/mflua_ttx_backend.lua index 851ff284ef3..2f3f36fa095 100644 --- a/Build/source/texk/web2c/mfluadir/mfluatrap/mflua_ttx_backend.lua +++ b/Build/source/texk/web2c/mfluadir/mfluatrap/mflua_ttx_backend.lua @@ -1,21 +1,26 @@ --- --- --- Experimental ttx back end --- --- - - local format = string.format local table_insert = table.insert +local table_remove = table.remove local table_concat = table.concat +local table_sort = table.sort local print_int = mflua.MF.print_int local abs = math.abs +local math_floor = math.floor +local math_tointeger = math.tointeger or math.floor + +local print_scaled = mflua.MF.print_scaled +local unity = mflua.MF.unity + +local GF = mflua.GF +local GF_chars = GF.chars local ttx = {} local xmlstream = {} - local scrt = {} -- general table for local use + + + local function DUMP(t) if type(t) == 'table' then print("table",#table) @@ -23,6 +28,64 @@ local function DUMP(t) end end +local function print_err(msg) + print(format("! ttx backend: %s",tostring(msg))) +end + +local function tointeger(n) + return math_tointeger(n) +end + +local function _normalize(w,n) + n = tonumber(n) or 5 + n = math_floor(abs(n)) + n = (n<25 and n) or 24 + local fmt = format("%%0.%sf", n) + local W = tonumber(format(fmt,w)) + nx = tointeger(W) + if nx==W then + return nx + else + return w + end +end + +local function normalize(w,n) + return print_scaled(w) +end + +local function _normalize_and_simplify(w,n) + n = tonumber(n) or 2 + n = math_floor(abs(n)) + n = (n<25 and n) or 24 + local fmt = format("%%0.%sf", n) + local W = tonumber(format(fmt,w)) + nx = tointeger(W) + if nx==W then + return nx + else + return W + end +end + +local function normalize_and_simplify(w,n) + return print_scaled(w) +end + + +local function toscaled(n) + return tonumber(format("%0.0f",n*unity)) +end + +local function table_sorted(t) + if type(t)=='table' then + table_sort(t) + return t + else + return {t} + end +end + local xml_comment = 'c' local xml_processing_instruction = 'p' @@ -153,6 +216,38 @@ local function get_children(source,target) return res end +-- +-- remove the first xml_element inserted +-- with name. Return the element removed +-- false otherwise +local function remove_child(t,name) + for i=1,#t do + if t[i][0]==xml_element and t[i][1]==tostring(name) then + return table.remove(t,i) + end + end + return false +end + +-- +-- call remove_child on all elements of +-- names + +local function remove_children(t,names) + local res = {} + local name, r + for _,v in pairs(names) do + name = tostring(v) + r = remove_child(t,name) + if r then + table_insert(res,r) + end + end + return res +end + + + -------------------------------------------------------------------------------- -- -- Serialization @@ -189,7 +284,7 @@ local function serialize_processing_instruction(t) end end for j=1,#_t do - elem[#elem+1]=format([[ %s="%s"]],_t[j],toattr(t[_t[j]])) + elem[#elem+1]=format([[ %s="%s"]],_t[j],toattr(t[_t[j]])) end elem[#elem+1]='?>' elem[#elem+1]="\n" @@ -247,7 +342,9 @@ local function serialize_elem(t) elem[#elem+1]=format([[ %s="%s"]],_t[j],toattr(t[_t[j]])) -- end elem[#elem+1]='>' + if type(t[2])~= 'string' then elem[#elem+1]="\n" + end xmlstream[#xmlstream+1] = table_concat(elem) elem = {} for j=2,#t do @@ -281,11 +378,18 @@ local OS_2,panose -- handy to have local name local cmap local post -local CFF, CFFFont, Private -- handy to have +local CFF, CFFFont, Private -- only a single CFFFont, for the moment local FFTM local GDEF local hmtx +-- For variable fonts +local extranames -- handy to have +local CFF2 +local HVAR,VarStore,VarRegionList,Regions,VarRegionAxis,VarData,AdvWidthMap +local fvar + + -- Important, child of CFFFont local CharStrings @@ -325,6 +429,11 @@ local function put_CFF(name,value) table_insert(CFF,new_element(name, {['value']=tostring(value)})) end +local function put_CFF2(name,value) + table_insert(CFF2,new_element(name, {['value']=tostring(value)})) +end + + local function put_CFFFont(name,value) table_insert(CFFFont,new_element(name, {['value']=tostring(value)})) end @@ -371,18 +480,68 @@ end ---for i=1,255 do table_insert(GlyphOrder,new_element('GlyphID', {['id']=i, ['name']="uni"..tostring(i)})) end ---local ttFont = dofile('ttx_sample.lua') ---savettfont(ttFont) - - -------------------------------------------------------------------------------- -- -- Create & save xml font -------------------------------------------------------------------------------- local function checkall(tfm) - -- several checks here + -- several checks & fixes here + local gf_chars = {} + if GF then + for k,_ in pairs(GF.chars) do + if type(k)=='number' then + table_insert(gf_chars,k) + end + end + table_sort(gf_chars) + end + -- + -- fix head + if ttx.userdata.update_head and + type(ttx.userdata.update_head)=='function' then + ttx.userdata.update_head(tfm) + elseif GF then + remove_children(head,{'xMin', 'xMax','yMin','yMax','modified'}) + put_head('xMin',GF_chars.min_m); + put_head('yMin',GF_chars.min_n); + put_head('xMax',GF_chars.max_m-GF_chars.min_m+1); + put_head('yMax',GF_chars.max_n-GF_chars.min_n+1); + -- Date is UTC + put_head('modified',os.date("!%c")); + end + -- + -- fix CFFFont, only one for the moment + if ttx.userdata.update_CFFFont and + type(ttx.userdata.update_CFFFont)=='function' then + ttx.userdata.update_CFFFont(CFFont) + elseif GF then + remove_child(CFFFont,'FontBBox') + put_CFFFont('FontBBox', + format("%s %s %s %s",GF_chars.min_m,GF_chars.min_n, + GF_chars.max_m-GF_chars.min_m+1, + GF_chars.max_n-GF_chars.min_n+1)) + end + -- + -- fix OS_2 + if ttx.userdata.update_OS_2 and + type(ttx.userdata.update_OS_2)=='function' then + ttx.userdata.update_CFFFont(OS_2) + elseif mflua.chartable then + local design_size=tonumber ( print_scaled(MFbuiltin.designsize()) ) --pt + local emsize = ttx.emsize or 1000 + local avgx = 0 + local avgx_cnt=0 + for k,v in pairs(mflua.chartable) do + if tonumber(v.char_wd) > 0 then + avgx = tonumber(v.char_wd)*emsize/design_size+avgx + avgx_cnt=avgx_cnt+1 + end + end + avgx = math_floor(avgx/avgx_cnt+0.5) + remove_child(OS_2,'xAvgCharWidth') + put_OS_2('xAvgCharWidth',avgx) + end -- fix cmap0 -- local t = {} -- for k,_ in pairs(scrt.cmap.rawcmap0) do t[#t+1]=k end @@ -427,7 +586,7 @@ local function _eval_tonumber(q,offset) end local function setup(tfm,index,chartable) - -- Default emsize is 1000 of CFF + -- Default emsize is 1000 for CFF and CFF2 ttx.emsize = ttx.emsize or 1000 scrt.font_space = tfm.printfloat(ttx.emsize*(tfm.font.space),3) @@ -442,14 +601,27 @@ local function setup(tfm,index,chartable) name = new_element('name') cmap = new_element('cmap') post = new_element('post') - CFF = new_element('CFF') + if ttx.cffver==1 then + CFF = new_element('CFF') + CFF2 = nil + elseif ttx.cffver==2 then + CFF2 = new_element('CFF2') + CFF = nil + end -- FFTM = new_element('FFTM') --FontForge TimeStamp table GDEF = new_element('GDEF') + if ttx.cffver==2 then + HVAR = new_element('HVAR') + end hmtx = new_element('hmtx') -- handy panose = new_element('panose') - CFFFont = new_element('CFFFont',{['name']="SourceCode"}) + if ttx.cffver==1 then + CFFFont = new_element('CFFFont',{['name']= (ttx.userdata.CFFFont['FullName'] or "mfluatestfont"..tostring(math.random(0,1000000)))}) + elseif ttx.cffver==2 then + CFFFont = new_element('CFFFont',{['name']="CFF2Font"}) + end Private = new_element('Private') CharStrings= new_element('CharStrings') @@ -462,9 +634,43 @@ local function setup(tfm,index,chartable) table_insert(ttFont,name) table_insert(ttFont,cmap) table_insert(ttFont,post) - table_insert(ttFont,CFF) --- table_insert(ttFont,FFTM) + if ttx.cffver==1 then + table_insert(ttFont,CFF) + elseif ttx.cffver==2 then + table_insert(ttFont,CFF2) + end + -- table_insert(ttFont,FFTM) table_insert(ttFont,GDEF) + + if ttx.cffver==2 then + table_insert(ttFont,HVAR) + insert_child(HVAR,{'Version', ['value']="0x00010000"}) + VarStore = new_element('VarStore',{['Format']="1"}) + insert_child(VarStore,{'Format',['value']="1"}) + VarRegionList = new_element('VarRegionList') + -- For the moment, 1 axis and 1 region + Regions = {new_element('Region',{['index']="0"})} + VarRegionAxis = new_element('VarRegionAxis',{['index']="0"}) + insert_child(VarRegionAxis,new_element('StartCoord',{['value']="-1.0"})) + insert_child(VarRegionAxis,new_element('PeakCoord',{['value']="-1.0"})) + insert_child(VarRegionAxis,new_element('EndCoord',{['value']="0.0"})) + -- insert_child(VarRegionAxis,new_element('StartCoord',{['value']="0.0"})) + -- insert_child(VarRegionAxis,new_element('PeakCoord',{['value']="1.0"})) + -- insert_child(VarRegionAxis,new_element('EndCoord',{['value']="1.0"})) + insert_child(Regions[1],VarRegionAxis) + insert_children(VarRegionList,Regions) + insert_child(VarStore,VarRegionList) + VarData = new_element('VarData',{['index']="0"}) + insert_child(VarData,new_element('NumShorts',{['value']="1"})) + insert_child(VarData,new_element('VarRegionIndex',{['value']="0"})) + insert_child(VarData,new_element('Item',{['index']="0", ['value']="[-125]"})) + insert_child(VarStore,VarData) + AdvWidthMap = new_element('AdvWidthMap') + insert_child(AdvWidthMap,new_element('Map', {['index']="0", ['outer']="0", ['inner']="0"})) + insert_child(HVAR,VarStore) + --insert_child(HVAR,AdvWidthMap) + end + table_insert(ttFont,hmtx) table_insert(GlyphOrder,GlyphID) @@ -539,61 +745,88 @@ local function setup(tfm,index,chartable) put_post(k,v) end end - - put_CFF('major',"1") - put_CFF('minor',"0") - insert_child(CFF,CFFFont) - - if ttx.userdata.CFFFont then - for k,v in pairs(mflua.ttx.userdata.CFFFont) do - put_CFFFont(k,v) - end + if ttx.cffver==2 then + insert_child(post,{'psNames'}) + extranames = new_element('extraNames') + insert_child(post,extranames) end - insert_child(CFFFont,{'Encoding', ['name']=mflua.ttx.userdata.CFFFont.Encoding}) + if ttx.cffver==1 then + put_CFF('major',"1") + put_CFF('minor',"0") + insert_child(CFF,CFFFont) + elseif ttx.cffver==2 then + put_CFF2('major',"2") + put_CFF2('minor',"0") + insert_child(CFF2,CFFFont) + end - insert_child(CFFFont,Private) - if ttx.userdata.CFFFont.Private then - for k,v in pairs(ttx.userdata.CFFFont.Private) do - put_Private(k,v) + if ttx.cffver==1 then + if ttx.userdata.CFFFont then + for k,v in pairs(mflua.ttx.userdata.CFFFont) do + put_CFFFont(k,v) + end end - end - local subrs = new_element('Subrs') - scrt.subrs = subrs - if ttx.userdata.CFFFont.Private.Subrs then - for k,v in pairs(ttx.userdata.CFFFont.Private.Subrs) do - insert_child(subrs,{'CharString', ['index']=k, v}) + insert_child(CFFFont,{'Encoding', ['name']=mflua.ttx.userdata.CFFFont.Encoding}) + + insert_child(CFFFont,Private) + if ttx.userdata.CFFFont.Private then + for k,v in pairs(ttx.userdata.CFFFont.Private) do + put_Private(k,v) + end + end + + local subrs = new_element('Subrs') + scrt.subrs = subrs + if ttx.userdata.CFFFont.Private.Subrs then + for k,v in pairs(ttx.userdata.CFFFont.Private.Subrs) do + insert_child(subrs,{'CharString', ['index']=k, v}) + end end - end insert_child(Private,subrs) + elseif ttx.cffver==2 then + insert_child(CFFFont,{'FontMatrix', ['value']=mflua.ttx.userdata.CFF2Font['FontMatrix']}) + local FDArray = new_element('FDArray') + local FontDict = new_element('FontDict', {['index']="0"}) + insert_child(FontDict,{'FontMatrix', ['value']=mflua.ttx.userdata.CFF2Font['FontMatrix']}) + insert_child(FontDict,{'Private'}) + insert_child(FDArray,FontDict) + insert_child(CFFFont,FDArray) + end + -- .notdef char local notdef = new_element('CharString', {['name']=".notdef"}) - insert_child(notdef,"107 endchar\n") + if ttx.cffver == 1 then + insert_child(notdef,"endchar\n") + elseif ttx.cffver == 2 then + insert_child(notdef,"0 0 0 0 0 0 rrcurveto \n") + end + insert_child_at_beginning(CharStrings, notdef) insert_child(CFFFont,CharStrings) + if CFF2 and mflua.ttx.userdata.varstore then + insert_child(CFFFont,mflua.ttx.userdata.varstore) + end + + -- -- TODO: check GlobalSubrs!! -- local globsubrs = new_element('GlobalSubrs') - insert_child(CFF,globsubrs) + if ttx.cffver==1 then + insert_child(CFF,globsubrs) + elseif ttx.cffver==2 then + insert_child(CFF2,globsubrs) + end if ttx.userdata.CFF.GlobalSubrs then for k,v in pairs(ttx.userdata.CFF.GlobalSubrs) do insert_child(globsubrs,{'CharString', ['index']=k, v}) end end - - -- - -- fontforge timestamp table. - -- - -- put_FFTM('version', "1") - -- put_FFTM('FFTimeStamp', "Fri Oct 7 21:32:10 2016") - -- put_FFTM('sourceCreated', "Tue Apr 4 13:38:00 2017") - -- put_FFTM('sourceModified', "Wed Apr 5 16:26:11 2017") - local glyphclassdef = new_element('GlyphClassDef',{['Format']="2"}) insert_child(GDEF,{'Version',['value']="0x00010000"}) @@ -605,7 +838,27 @@ local function setup(tfm,index,chartable) insert_child(LigCaretList,new_element('Coverage',{['Format']="2"})) insert_child(GDEF,LigCaretList) - insert_child(hmtx, get_mtx('.notdef',scrt.font_space,"0")) + + insert_child(hmtx, get_mtx('.notdef', + ttx.userdata.char_notdef['width'], + ttx.userdata.char_notdef['lsb'])) + + if CFF2 and ttx.userdata.fvar then + local fvar = new_element('fvar') + local v, axis, _e + for i=1,#ttx.userdata.fvar.Axis do + v = ttx.userdata.fvar.Axis[i] + axis = new_element('Axis') + _e = new_element('AxisTag'); _e[2] = v['AxisTag']; insert_child(axis,_e) + _e = new_element('MinValue'); _e[2] = v['MinValue']; insert_child(axis,_e) + _e = new_element('DefaultValue'); _e[2] = v['DefaultValue']; insert_child(axis,_e) + _e = new_element('MaxValue'); _e[2] = v['MaxValue']; insert_child(axis,_e) + _e = new_element('AxisNameID'); _e[2] = v['AxisNameID']; insert_child(axis,_e) + end + insert_child(fvar,axis) + insert_child(ttFont,fvar) + end + end @@ -622,6 +875,33 @@ local function reverse(cycle) return t end + +local function sort(cycle) + local t={} + local curve + local p,q, index + local xmin,ymin = 4096,4096 + index = 1 + for i=1,#cycle do + curve=cycle[i] + p=curve[1]; + t = _eval_tonumber(p) + -- Align to leftmost x and y + --if t[1]<=xmin and t[2]<=ymin then index = i;xmin,ymin=t[1],t[2] end + -- Align to the leftmost x + if t[1]<=xmin then index = i;xmin,ymin=t[1],t[2] end + end + t={} + for i=index,#cycle do t[#t+1]=cycle[i] end + for i=1,index-1 do t[#t+1]=cycle[i] end + for i=1,#t do + curve=t[i] + p,c1,c2,q=curve[1],curve[2],curve[3],curve[4] + end + return t +end + + local function _reverse(cycle) local cv1, cv2 local p,c1,c2,q @@ -639,20 +919,101 @@ local function _reverse(cycle) end +-- local function updateminmax(p,c1,c2,q) +-- ttx = ttx or {} +-- ttx.userdata = ttx.userdata or {} +-- ttx.userdata.head = ttx.userdata.head or {} +-- local t; +-- -- hm not ok, too raw +-- -- we need at least 3 bisections +-- t = {p[1],c1[1],c2[1],q[1]} +-- table_sort(t) +-- ttx.userdata.head['xMin']= math_floor(t[1]) +-- ttx.userdata.head['xMax']= math_floor(t[4]) +-- t = {p[2],c1[2],c2[2],q[2]} +-- table_sort(t) +-- ttx.userdata.head['yMin']= math_floor(t[1]) +-- ttx.userdata.head['yMax']= math_floor(t[4]) +-- end + + +local function update_char_lsb(glyph_name,char_wd_emunit,index) + local err = true + if ttx.userdata.update_char_lsb and + type(ttx.userdata.update_char_lsb)=='function' then + ttx.userdata.update_char_lsb(glyph_name,char_wd_emunit,index) + return + end + if GF_chars[index] then + insert_child(hmtx, get_mtx(glyph_name, + char_wd_emunit,GF_chars[index].min_m)) + return + end + if err then print_err("update_char_lsb failed") end +end + + + + + +local function isvhline(py,c1y,c2y,qy) + if (py==c1y) and (c1y==c2y) and (c2y==qy) then + return true + end + --local abs = math.abs + local eps = ttx.eps or 0.01 + local d1,d2,d3,d4 = abs(py-c1y), abs(c1y-c2y), abs(c2y-qy),abs(py-qy) + if d1<eps and d2<eps and d3<eps and d4<eps then + return true + end + return false +end + + +local function isline(px,py,c1x,c1y,c2x,c2y,qx,qy) + local px,py,c1x,c1y,c2x,c2y,qx,qy = 0,0,c1x-px,c1y-py,c2x-px,c2y-py,qx-px,qy-py + local eps = ttx.deps or 0.01 + local atan2,abs = math.atan2, math.abs + a = atan2(qy,qx) + a1 = atan2(c1y,c1x) + a2 = atan2(c2y,c2x) + if abs(a-a1)<eps and abs(a-a2)<eps and abs(a1-a2)<eps then + return true + end + return false +end + + +local function insert_stem(index,stem_type) + if mflua and mflua.userdata and mflua.userdata.char and mflua.userdata.char[index] and mflua.userdata.char[index][stem_type] then + -- stem[i]={base, delta} + local stem = mflua.userdata.char[index][stem_type] + local content = {} + for i=1,#stem do + --table_insert(content, format("%s %s", normalize(stem[i][1]),normalize(stem[i][2]))) + table_insert(content, format("%s %s",stem[i][1],stem[i][2])) + end + table_insert(content,stem_type) + return table_concat(content, " ") + end + return nil +end + + local function make_glyph(valid_curves,char,cycles,tfm) -- Write the ttx - -- - -- print('BEZ MFbuiltin.hppp='..print_scaled(MFbuiltin.hppp())) - -- print('BEZ MFbuiltin.vppp='..print_scaled(MFbuiltin.vppp())) - -- print('BEZ MFbuiltin.designsize='..print_scaled(MFbuiltin.designsize())) + + if #cycles == 0 and #valid_curves==0 then + print("no outlines ") + --return + end local tfm = tfm - local mflua_index = tonumber( char['index'] ) -- better a string or a number + local mflua_index = tointeger( char['index'] ) -- better a string or a number local index = mflua_index if mflua.ttx.userdata.charindex and mflua.ttx.userdata.charindex[index] then index = mflua.ttx.userdata.charindex[index] end - local design_size=tonumber ( print_scaled(MFbuiltin.designsize()) ) --pt local char_wd=tonumber( char['char_wd'] ) -- pt local char_ht=tonumber( char['char_ht'] ) -- pt @@ -664,36 +1025,44 @@ local function make_glyph(valid_curves,char,cycles,tfm) local glyphclassdef = scrt.gdef.glyphclassdef - --local xheight = 0.458333 * design_size -- must be read from tfm !! - local x_resolution = math.floor(0.5+tonumber( print_scaled(MFbuiltin.hppp()) )* 72.27) - local y_resolution = math.floor(0.5+tonumber( print_scaled(MFbuiltin.vppp()) )* 72.27) + local x_resolution = math_floor(0.5+tonumber( print_scaled(MFbuiltin.hppp()) )* 72.27) + local y_resolution = math_floor(0.5+tonumber( print_scaled(MFbuiltin.vppp()) )* 72.27) assert(x_resolution==y_resolution, format('Error on _make_glyph x_res=%d and y_res=%d differ',x_resolution,y_resolution)) local resolution = x_resolution local emsize = ttx.emsize -- 1000, type 1, also known as em_unit: 1000 emsize = 1em local em_unit = emsize - local em_unit_for_pixel = (72.27/design_size) * (emsize / resolution) local bp_for_pt = 72/72.27 - local char_wd_emunit = (char_wd/design_size) *em_unit - local char_ht_emunit = (char_ht/design_size) *em_unit - local char_dp_emunit = (char_dp/design_size) *em_unit - + local char_wd_emunit = tonumber(format("%0.0f", (char_wd/design_size) *em_unit)) + local char_ht_emunit = tonumber(format("%0.0f", (char_ht/design_size) *em_unit)) + local char_dp_emunit = tonumber(format("%0.0f", (char_dp/design_size) *em_unit)) local glyph_name = tostring(char['charname']) + if glyph_name and glyph_name ~= '' and not(index==0) then table_insert(GlyphOrder,get_GlyphID(index,glyph_name)) end + local content = {} - if (abs(char_wd_emunit-scrt.font_space)>1e-4) then - table_insert(content,format("%0.3f w",char_wd_emunit-scrt.font_space,print_int(1000*(tfm.font.space)))) + table_insert(content," ") + if CFF2 and (abs(char_wd_emunit-scrt.font_space)>1e-4) then + table_insert(content,format("%0.3f w",char_wd_emunit-scrt.font_space)) end - --table_insert(content,"stem ?") -- TODO + + + table_insert(content,insert_stem(mflua_index,"hstem")) + table_insert(content,insert_stem(mflua_index,"vstem")) --table_insert(content,"mask ?") -- TODO + local origin = {0,0} - for i,cycle in pairs(cycles) do + for i,_cycle in pairs(cycles) do + local cycle local p,c1,c2,q,offset - cycle = reverse(cycle) + --cycle = reverse(_cycle) + cycle = _cycle + -- do we need a sort ? + --cycle = sort(cycle) for i1,curve in ipairs(cycle) do p,c1,c2,q,offset=curve[1],curve[2],curve[3],curve[4],curve[5] p =_eval_tonumber(p ,offset) @@ -705,18 +1074,119 @@ local function make_glyph(valid_curves,char,cycles,tfm) q[1],q[2] = q[1] *em_unit_for_pixel, q[2]*em_unit_for_pixel c1[1],c1[2] = c1[1]*em_unit_for_pixel, c1[2]*em_unit_for_pixel c2[1],c2[2] = c2[1]*em_unit_for_pixel, c2[2]*em_unit_for_pixel - if i1==1 then - table_insert(content,format("%0.2f %0.2f rmoveto",p[1]-origin[1],p[2]-origin[2])) - origin = {p[1],p[2]} + + + p[1],p[2] = toscaled(p[1]), toscaled(p[2]) + q[1],q[2] = toscaled(q[1]), toscaled(q[2]) + c1[1],c1[2] = toscaled(c1[1]), toscaled(c1[2]) + c2[1],c2[2] = toscaled(c2[1]), toscaled(c2[2]) + + + if CFF then + -- print(format("p1 %s path=(%0.14f,%0.14f) (%0.14f,%0.14f) (%0.14f,%0.14f) (%0.14f,%0.14f)", index, + -- p[1], p[2], + -- c1[1], c1[2], + -- c2[1], c2[2], + -- q[1],q[2])) + -- print(format("p2 %s path=(%0.4f,%0.4f) (%0.4f,%0.4f) (%0.4f,%0.4f) (%0.4f,%0.4f)", index, + -- p[1], p[2], + -- c1[1], c1[2], + -- c2[1], c2[2], + -- q[1],q[2])) + -- print(format("p3 %s path=(%s,%s) (%s,%s) (%s,%s) (%s,%s)", index, + -- normalize(p[1]), normalize(p[2]), + -- normalize(c1[1]), normalize(c1[2]), + -- normalize(c2[1]), normalize(c2[2]), + -- normalize(q[1]), normalize(q[2]))) + + if i1==1 then + --print(format("m %s %s %s rmoveto",index, normalize(p[1]-origin[1]),normalize(p[2]-origin[2]))) + table_insert(content,format("%s %s rmoveto",normalize(p[1]-origin[1]),normalize(p[2]-origin[2]))) + origin = {p[1],p[2]} + end + if isvhline(p[2],c1[2],c2[2], q[2]) then -- check horizontal line + --print(format("h %s %s hlineto", index, normalize(q[1]-p[1]))) + table_insert(content,format("%s hlineto", normalize(q[1]-p[1]))) + elseif isvhline(p[1],c1[1],c2[1], q[1]) then -- check vertical line + --print(format("v %s %s vlineto", index,normalize(q[2]-p[2]))) + table_insert(content,format("%s vlineto", normalize(q[2]-p[2]))) + elseif isline(p[1],p[2],c1[1],c1[2],c2[1],c2[2],q[1],q[2]) then -- check a line + --print(format("r %s %s %s rlineto", index, normalize(q[1]-p[1]), normalize(q[2]-p[2]))) + table_insert(content,format("%s %s rlineto", normalize(q[1]-p[1]), normalize(q[2]-p[2]))) + else + local prec = 3; + -- p[1] = normalize_and_simplify(p[1],prec);p[2] = normalize_and_simplify(p[2],prec); + -- c1[1] = normalize_and_simplify(c1[1],prec);c1[2] = normalize_and_simplify(c1[2],prec); + -- c2[1] = normalize_and_simplify(c2[1],prec);c2[2] = normalize_and_simplify(c2[2],prec); + -- q[1] = normalize_and_simplify(q[1],prec);q[2] = normalize_and_simplify(q[2],prec); + + + table_insert(content,(format("%s %s %s %s %s %s rrcurveto", + normalize_and_simplify(c1[1] -p[1],prec), normalize_and_simplify(c1[2]-p[2],prec), + normalize_and_simplify(c2[1]-c1[1],prec), normalize_and_simplify(c2[2]-c1[2],prec), + normalize_and_simplify(q[1] -c2[1],prec), normalize_and_simplify(q[2]-c2[2],prec)))) + + end + + elseif CFF2 then -- + -- reverse the key, because we reverse the cycle + local kp = table.concat({curve[4],curve[3],curve[2],curve[1]}) + local deltas_width = {{0,0},{0,0}, {0,0},{0,0}, {0,0},{0,0}, {0,0},{0,0}} + local origin_deltas_width = {0,0} + local a, b, c, d, da, Da, db, Db, dc, Dc, dd, Dd + if mflua.userdata.deltas_width[glyph_name] then + deltas_width = mflua.userdata.deltas_width[glyph_name][kp] + -- Original from MF, we have to reverse it; d..c..b..a is the key, + -- da and Da are the delta min and delta max, + -- where delta is (variated_instance - reference_instance) + -- delta are not affected by offset, but scaling are cannot be discarded + a, b, c, d, da, Da, db, Db, dc, Dc, dd, Dd = table.unpack(deltas_width) + deltas_width = {dd, Dd,dc, Dc,db, Db,da, Da} + for _,v in ipairs(deltas_width) do + v[1],v[2]=v[1]*em_unit_for_pixel, v[2]*em_unit_for_pixel + end + end + da, Da, db, Db, dc, Dc, dd, Dd = table.unpack(deltas_width) + -- One axis only, width + -- Condensed Regular (still not Extended) + local blend + if i1==1 then + blend = format("%0.2f %0.2f 2 blend",da[1]-origin_deltas_width[1],da[2]-origin_deltas_width[2]) ; + table_insert(content,format("%0.0f %0.0f %s rmoveto",p[1]-origin[1],p[2]-origin[2],blend)) + origin = {p[1],p[2]} + origin_deltas_width ={da[1],da[2]} + end + blend = format("%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f 6 blend", + db[1]-da[1],db[2]-da[2], + dc[1]-db[1],dc[2]-db[2], + dd[1]-dc[1],dd[2]-dc[2]) + + table_insert(content,format("%0.0f %0.0f %0.0f %0.0f %0.0f %0.0f %s rrcurveto", + c1[1] -p[1], c1[2]-p[2], + c2[1]-c1[1], c2[2]-c1[2], + q[1] -c2[1], q[2]-c2[2],blend)) + + + + -- if i1==1 then + -- blend = '0 0 2 blend' ; + -- table_insert(content,format("%0.0f %0.0f %s rmoveto",p[1]-origin[1],p[2]-origin[2],blend)) + -- origin = {p[1],p[2]} + -- end + -- --table_insert(content,format("%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f rrcurveto", + -- if i1==1 then blend = '0 0 0 0 0 0 6 blend' ; else blend = '0 0 0 0 -10 0 6 blend' end + -- table_insert(content,format("%0.0f %0.0f %0.0f %0.0f %0.0f %0.0f %s rrcurveto", + -- c1[1] -p[1], c1[2]-p[2], + -- c2[1]-c1[1], c2[2]-c1[2], + -- q[1] -c2[1], q[2]-c2[2],blend)) end - --table_insert(content,format("%0.2f %0.2f %0.2f %0.2f %0.2f %0.2f rrcurveto", - table_insert(content,format("%0.0f %0.0f %0.0f %0.0f %0.0f %0.0f rrcurveto", - c1[1] -p[1], c1[2]-p[2], - c2[1]-c1[1], c2[2]-c1[2], - q[1] -c2[1], q[2]-c2[2],p[1],p[2],c1[1],c1[2],c2[1],c2[2],q[1],q[2])) end end - table_insert(content,"endchar\n") + if ttx.cffver == 1 then + table_insert(content,"endchar\n") + elseif ttx.cffver == 2 then + table_insert(content,"") + end local CharString = new_element('CharString', {['name']=glyph_name}) insert_child(CharString,table_concat(content,"\n")) @@ -726,8 +1196,21 @@ local function make_glyph(valid_curves,char,cycles,tfm) insert_child(cmap4_3,get_map(format("0x%x",index),glyph_name)) insert_child(glyphclassdef, get_ClassDef(glyph_name,"1")) - insert_child(hmtx, get_mtx(glyph_name,char_wd_emunit,"80")) + update_char_lsb(glyph_name,char_wd_emunit,mflua_index) + + if ttx.cffver==2 then + local psName = new_element('psName', {['name']=glyph_name}) + local Item = new_element('Item', {['index']=format("%d",index), ['value']="[-125]"}) + local Map = new_element('Map', {['index']=format("%d",index), ['outer']="0", ['inner']="0"}) + local VarStore = get_children(HVAR,{'VarStore'}) + local VarData = get_children(VarStore[1],{'VarData'}) + --local AdvWidthMap = get_children(HVAR,{'AdvWidthMap'}) + insert_child(VarData[1],Item) + --insert_child(AdvWidthMap[1],Map) + insert_child(extranames,psName) + + end end -- make_glyph @@ -739,5 +1222,7 @@ ttx.make_glyph = make_glyph ttx.makefont = makefont ttx.setup = setup ttx.userdata = {} - +ttx.cffver = 1 +ttx.eps = 0.01 +ttx.deps = 0.01 return ttx |