if not modules then modules = { } end modules ['font-vf'] = { version = 1.001, comment = "companion to font-ini.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } --[[ldx--

This is very experimental code! Not yet adapted to recent changes. This will change.

--ldx]]-- -- define.methods elsewhere ! fonts = fonts or { } fonts.vf = fonts.vf or { } local vf = fonts.vf local tfm = fonts.tfm fonts.define = fonts.define or { } fonts.define.methods = fonts.define.methods or { } vf.combinations = vf.combinations or { } vf.aux = vf.aux or { } vf.aux.combine = vf.aux.combine or { } function fonts.define.methods.install(tag, rules) vf.combinations[tag] = rules fonts.define.methods[tag] = function(specification) return vf.combine(specification,tag) end end function vf.aux.combine.assign(g, name, from, to, start, force) local f, id = vf.aux.combine.load(g,name) if f and id then -- optimize for whole range, then just g = f if not from then from, to = 0, 0xFF00 end if not to then to = from end if not start then start = from end local fc, gc = f.characters, g.characters local fd, gd = f.descriptions, g.descriptions local hn = #g.fonts+1 g.fonts[hn] = { id = id } -- no need to be sparse for i=from,to do if fc[i] and (force or not gc[i]) then gc[i] = table.fastcopy(fc[i]) -- can be optimized gc[i].commands = { { 'slot', hn, start } } gd[i] = fd[i] end start = start + 1 end if not g.parameters and #g.fonts > 0 then -- share this code ! g.parameters = table.fastcopy(f.parameters) g.italicangle = f.italicangle g.ascender = f.ascender g.descender = f.descender g.factor = f.factor -- brrr end end end function vf.aux.combine.process(g,list) if list then for _,v in next, list do (vf.aux.combine.commands[v[1]] or nop)(g,v) end end end function vf.aux.combine.load(g,name) return tfm.read_and_define(name or g.specification.name,g.specification.size) end function vf.aux.combine.names(g,name,force) local f, id = tfm.read_and_define(name,g.specification.size) if f and id then local fc, gc = f.characters, g.characters local fd, gd = f.descriptions, g.descriptions g.fonts[#g.fonts+1] = { id = id } -- no need to be sparse local hn = #g.fonts for k, v in next, fc do if force or not gc[k] then gc[k] = table.fastcopy(v) gc[k].commands = { { 'slot', hn, k } } gd[i] = fd[i] end end if not g.parameters and #g.fonts > 0 then -- share this code ! g.parameters = table.fastcopy(f.parameters) g.italicangle = f.italicangle g.ascender = f.ascender g.descender = f.descender g.factor = f.factor -- brrr end end end vf.aux.combine.commands = { ["initialize"] = function(g,v) vf.aux.combine.assign (g,g.name) end, ["include-method"] = function(g,v) vf.aux.combine.process (g,vf.combinations[v[2]]) end, -- name ["copy-parameters"] = function(g,v) vf.aux.combine.parameters(g,v[2]) end, -- name ["copy-range"] = function(g,v) vf.aux.combine.assign (g,v[2],v[3],v[4],v[5],true) end, -- name, from-start, from-end, to-start ["copy-char"] = function(g,v) vf.aux.combine.assign (g,v[2],v[3],v[3],v[4],true) end, -- name, from, to ["fallback-range"] = function(g,v) vf.aux.combine.assign (g,v[2],v[3],v[4],v[5],false) end, -- name, from-start, from-end, to-start ["fallback-char"] = function(g,v) vf.aux.combine.assign (g,v[2],v[3],v[3],v[4],false) end, -- name, from, to ["copy_names"] = function(g,v) vf.aux.combine.names (g,v[2],true) end, ["fallback_names"] = function(g,v) vf.aux.combine.names (g,v[2],false) end, } function vf.combine(specification,tag) local g = { name = specification.name, -- type = 'virtual', virtualized = true, fonts = { }, characters = { }, descriptions = { }, specification = table.fastcopy(specification) } vf.aux.combine.process(g,vf.combinations[tag]) return g end vf.aux.combine.commands["feature"] = function(g,v) local key, value = v[2], v[3] if key then if value == nil then value = true end if g.specification and g.specification.features.normal then g.specification.features.normal[key] = value -- otf? end end end -- simple example with features fonts.define.methods.install( "ligatures", { { "feature", "liga" } , { "feature", "dlig" } , { "initialize" } , } ) --~ fonts.define.methods.install ( --~ "ligatures-x", { --~ { "feature", "liga" } , --~ { "feature", "dlig" } , --~ { "initialize" } , --~ { "lineheight" } --~ } --~ ) --~ fonts.define.methods.install( --~ "lmsymbol10", { --~ { "fallback_names", "lmsy10.afm" } , --~ { "fallback_names", "msam10.afm" } , --~ { "fallback_names", "msbm10.afm" } --~ } --~ ) --~ \font\TestFont=dummy@lmsymbol10 at 24pt -- docu case --~ fonts.define.methods.install( --~ "weird", { --~ { "copy-range", "lmroman10-regular" } , --~ { "copy-char", "lmroman10-regular", 65, 66 } , --~ { "copy-range", "lmsans10-regular", 0x0100, 0x01FF } , --~ { "copy-range", "lmtypewriter10-regular", 0x0200, 0xFF00 } , --~ { "fallback-range", "lmtypewriter10-regular", 0x0000, 0x0200 } --~ } --~ ) -- demo case -> move to module fonts.define.methods["demo-1"] = function(specification) local name = specification.name -- symbolic name local size = specification.size -- given size local f, id = tfm.read_and_define('lmroman10-regular',size) if f and id then local capscale, digscale = 0.85, 0.75 -- f.name, f.type = name, 'virtual' f.name, f.virtualized = name, true f.fonts = { { id = id }, { name = 'lmsans10-regular' , size = size*capscale }, -- forced extra name { name = 'lmtypewriter10-regular', size = size*digscale } -- forced extra name } local i_is_of_category = characters.i_is_of_category local characters, descriptions = f.characters, f.descriptions local red = {'special','pdf: 1 0 0 rg'} local green = {'special','pdf: 0 1 0 rg'} local blue = {'special','pdf: 0 0 1 rg'} local black = {'special','pdf: 0 g'} for u,v in next, characters do if u and i_is_of_category(u,'lu') then v.width = capscale*v.width v.commands = { red, {'slot',2,u}, black } elseif u and i_is_of_category(u,'nd') then v.width = digscale*v.width v.commands = { blue, {'slot',3,u}, black } else v.commands = { green, {'slot',1,u}, black } end end end return f end