summaryrefslogtreecommitdiff
path: root/tex/context/base/font-vf.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/font-vf.lua')
-rw-r--r--tex/context/base/font-vf.lua213
1 files changed, 213 insertions, 0 deletions
diff --git a/tex/context/base/font-vf.lua b/tex/context/base/font-vf.lua
new file mode 100644
index 000000000..4f99c47b9
--- /dev/null
+++ b/tex/context/base/font-vf.lua
@@ -0,0 +1,213 @@
+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--
+<p>This is very experimental code! Not yet adapted to recent
+changes. This will change.</p>
+--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