summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/font-ctx.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/font-ctx.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/font-ctx.lua314
1 files changed, 273 insertions, 41 deletions
diff --git a/Master/texmf-dist/tex/context/base/font-ctx.lua b/Master/texmf-dist/tex/context/base/font-ctx.lua
index 2f51c5229bc..76e9f095a48 100644
--- a/Master/texmf-dist/tex/context/base/font-ctx.lua
+++ b/Master/texmf-dist/tex/context/base/font-ctx.lua
@@ -1,14 +1,19 @@
if not modules then modules = { } end modules ['font-ctx'] = {
version = 1.001,
- comment = "companion to font-ini.tex",
+ 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"
}
-local texsprint, count = tex.sprint, tex.count
-local format, concat, gmatch, match, find, lower = string.format, table.concat, string.gmatch, string.match, string.find, string.lower
-local tostring, next = tostring, next
+-- needs a cleanup: merge of replace, lang/script etc
+
+local texsprint, count, texsetcount = tex.sprint, tex.count, tex.setcount
+local format, concat, gmatch, match, find, lower, gsub, byte = string.format, table.concat, string.gmatch, string.match, string.find, string.lower, string.gsub, string.byte
+
+local tostring, next, type = tostring, next, type
+local lpegmatch = lpeg.match
+local round = math.round
local ctxcatcodes = tex.ctxcatcodes
@@ -16,7 +21,7 @@ local trace_defining = false trackers.register("fonts.defining", function(v) tr
local tfm = fonts.tfm
local define = fonts.define
-local fontdata = fonts.ids
+local fontdata = fonts.identifiers
local specify = define.specify
specify.context_setups = specify.context_setups or { }
@@ -46,7 +51,7 @@ name*context specification
function specify.predefined(specification)
local detail = specification.detail
if detail ~= "" then
- -- detail = detail:gsub("["..define.splitsymbols.."].*$","") -- get rid of *whatever specs and such
+ -- detail = gsub(detail,"["..define.splitsymbols.."].*$","") -- get rid of *whatever specs and such
if define.methods[detail] then -- since these may be appended at the
specification.features.vtf = { preset = detail } -- tex end by default
end
@@ -66,22 +71,25 @@ local settings_to_hash = aux.settings_to_hash
local default_features = fonts.otf.features.default
local function preset_context(name,parent,features) -- currently otf only
+ if features == "" and find(parent,"=") then
+ features = parent
+ parent = ""
+ end
if features == "" then
- if find(parent,"=") then
- features = parent
- parent = ""
- end
+ features = { }
+ elseif type(features) == "string" then
+ features = normalize_meanings(settings_to_hash(features))
+ else
+ features = normalize_meanings(features)
end
- local number = (setups[name] and setups[name].number) or 0
- local t = (features == "" and { }) or normalize_meanings(settings_to_hash(features))
-- todo: synonyms, and not otf bound
if parent ~= "" then
for p in gmatch(parent,"[^, ]+") do
local s = setups[p]
if s then
for k,v in next, s do
- if t[k] == nil then
- t[k] = v
+ if features[k] == nil then
+ features[k] = v
end
end
end
@@ -91,25 +99,26 @@ local function preset_context(name,parent,features) -- currently otf only
-- we need to preset them (we hash the features and adding a default
-- setting during initialization may result in a different hash)
for k,v in next, triggers do
- if type(t[v]) == "nil" then
+ if features[v] == nil then -- not false !
local vv = default_features[v]
- if vv then t[v] = vv end
+ if vv then features[v] = vv end
end
end
-- sparse 'm so that we get a better hash and less test (experimental
-- optimization)
- local tt = { } -- maybe avoid tt
- for k,v in next, t do
- if v then tt[k] = v end
+ local t = { } -- can we avoid t ?
+ for k,v in next, features do
+ if v then t[k] = v end
end
-- needed for dynamic features
+ local number = (setups[name] and setups[name].number) or 0
if number == 0 then
number = #numbers + 1
numbers[number] = name
end
- tt.number = number
- setups[name] = tt
- return number
+ t.number = number
+ setups[name] = t
+ return number, t
end
local function context_number(name) -- will be replaced
@@ -267,13 +276,16 @@ local P, C, Cc = lpeg.P, lpeg.C, lpeg.Cc
local space = P(" ")
local spaces = space^0
-local value = C((1-space)^1)
+local leftparent = (P"(")
+local rightparent = (P")")
+local value = C((leftparent * (1-rightparent)^0 * rightparent + (1-space))^1)
+local dimension = C((space/"" + P(1))^1)
local rest = C(P(1)^0)
local scale_none = Cc(0)
-local scale_at = P("at") * Cc(1) * spaces * value
-local scale_sa = P("sa") * Cc(2) * spaces * value
-local scale_mo = P("mo") * Cc(3) * spaces * value
-local scale_scaled = P("scaled") * Cc(4) * spaces * value
+local scale_at = P("at") * Cc(1) * spaces * dimension -- value
+local scale_sa = P("sa") * Cc(2) * spaces * dimension -- value
+local scale_mo = P("mo") * Cc(3) * spaces * dimension -- value
+local scale_scaled = P("scaled") * Cc(4) * spaces * dimension -- value
local sizepattern = spaces * (scale_at + scale_sa + scale_mo + scale_scaled + scale_none)
local splitpattern = spaces * value * spaces * rest
@@ -287,7 +299,7 @@ local get_specification = define.get_specification
function define.command_1(str)
statistics.starttiming(fonts)
- local fullname, size = splitpattern:match(str)
+ local fullname, size = lpegmatch(splitpattern,str)
local lookup, name, sub, method, detail = get_specification(fullname)
if not name then
logs.report("define font","strange definition '%s'",str)
@@ -295,40 +307,50 @@ function define.command_1(str)
elseif name == "unknown" then
texsprint(ctxcatcodes,"\\fcglet\\somefontname\\defaultfontfile")
else
- texsprint(ctxcatcodes,format("\\fcxdef\\somefontname{%s}",name))
+ texsprint(ctxcatcodes,"\\fcxdef\\somefontname{",name,"}")
end
-- we can also use a count for the size
if size and size ~= "" then
- local mode, size = sizepattern:match(size)
+ local mode, size = lpegmatch(sizepattern,size)
if size and mode then
count.scaledfontmode = mode
- texsprint(ctxcatcodes,format("\\def\\somefontsize{%s}",size))
+ texsprint(ctxcatcodes,"\\def\\somefontsize{",size,"}")
else
count.scaledfontmode = 0
- texsprint(ctxcatcodes,format("\\let\\somefontsize\\empty",size))
+ texsprint(ctxcatcodes,"\\let\\somefontsize\\empty")
end
elseif true then
-- so we don't need to check in tex
count.scaledfontmode = 2
---~ texsprint(ctxcatcodes,format("\\def\\somefontsize{*}",size))
- texsprint(ctxcatcodes,format("\\let\\somefontsize\\empty",size))
+ texsprint(ctxcatcodes,"\\let\\somefontsize\\empty")
else
count.scaledfontmode = 0
- texsprint(ctxcatcodes,format("\\let\\somefontsize\\empty",size))
+ texsprint(ctxcatcodes,"\\let\\somefontsize\\empty")
end
specification = define.makespecification(str,lookup,name,sub,method,detail,size)
end
local n = 0
-function define.command_2(global,cs,str,size,classfeatures,fontfeatures,classfallbacks,fontfallbacks,mathsize,textsize)
+-- we can also move rscale to here (more consistent)
+
+function define.command_2(global,cs,str,size,classfeatures,fontfeatures,classfallbacks,fontfallbacks,mathsize,textsize,relativeid)
+ if trace_defining then
+ logs.report("define font","memory usage before: %s",statistics.memused())
+ end
-- name is now resolved and size is scaled cf sa/mo
local lookup, name, sub, method, detail = get_specification(str or "")
-- asome settings can be overloaded
- if lookup and lookup ~= "" then specification.lookup = lookup end
+ if lookup and lookup ~= "" then
+ specification.lookup = lookup
+ end
+ if relativeid and relativeid ~= "" then -- experimental hook
+ local id = tonumber(relativeid) or 0
+ specification.relativeid = id > 0 and id
+ end
specification.name = name
specification.size = size
- specification.sub = sub
+ specification.sub = (sub and sub ~= "" and sub) or specification.sub
specification.mathsize = mathsize
specification.textsize = textsize
if detail and detail ~= "" then
@@ -340,9 +362,6 @@ function define.command_2(global,cs,str,size,classfeatures,fontfeatures,classfal
elseif classfeatures and classfeatures ~= "" then
specification.method, specification.detail = "*", classfeatures
end
- if trace_defining then
- logs.report("define font","memory usage before: %s",statistics.memused())
- end
if fontfallbacks and fontfallbacks ~= "" then
specification.fallbacks = fontfallbacks
elseif classfallbacks and classfallbacks ~= "" then
@@ -351,6 +370,7 @@ function define.command_2(global,cs,str,size,classfeatures,fontfeatures,classfal
local tfmdata = define.read(specification,size) -- id not yet known
if not tfmdata then
logs.report("define font","unable to define %s as \\%s",name,cs)
+ texsetcount("global","lastfontid",-1)
elseif type(tfmdata) == "number" then
if trace_defining then
logs.report("define font","reusing %s with id %s as \\%s (features: %s/%s, fallbacks: %s/%s)",name,tfmdata,cs,classfeatures,fontfeatures,classfallbacks,fontfallbacks)
@@ -358,6 +378,7 @@ function define.command_2(global,cs,str,size,classfeatures,fontfeatures,classfal
tex.definefont(global,cs,tfmdata)
-- resolved (when designsize is used):
texsprint(ctxcatcodes,format("\\def\\somefontsize{%isp}",fontdata[tfmdata].size))
+ texsetcount("global","lastfontid",tfmdata)
else
-- local t = os.clock(t)
local id = font.define(tfmdata)
@@ -374,6 +395,7 @@ function define.command_2(global,cs,str,size,classfeatures,fontfeatures,classfal
--~ if specification.fallbacks then
--~ fonts.collections.prepare(specification.fallbacks)
--~ end
+ texsetcount("global","lastfontid",id)
end
if trace_defining then
logs.report("define font","memory usage after: %s",statistics.memused())
@@ -381,6 +403,28 @@ function define.command_2(global,cs,str,size,classfeatures,fontfeatures,classfal
statistics.stoptiming(fonts)
end
+local enable_auto_r_scale = false
+
+experiments.register("fonts.autorscale", function(v)
+ enable_auto_r_scale = v
+end)
+
+local calculate_scale = fonts.tfm.calculate_scale
+
+function fonts.tfm.calculate_scale(tfmtable, scaledpoints, relativeid)
+ local scaledpoints, delta, units = calculate_scale(tfmtable, scaledpoints, relativeid)
+ if enable_auto_r_scale and relativeid then -- for the moment this is rather context specific
+ local relativedata = fontdata[relativeid]
+ local id_x_height = relativedata and relativedata.parameters and relativedata.parameters.x_height
+ local tf_x_height = id_x_height and tfmtable.parameters and tfmtable.parameters.x_height * delta
+ if tf_x_height then
+ scaledpoints = (id_x_height/tf_x_height) * scaledpoints
+ delta = scaledpoints/units
+ end
+ end
+ return scaledpoints, delta, units
+end
+
--~ table.insert(readers.sequence,1,'vtf')
--~ function readers.vtf(specification)
@@ -390,3 +434,191 @@ end
--~ return nil
--~ end
--~ end
+
+-- we need a place for this .. outside the generic scope
+
+local dimenfactors = number.dimenfactors
+
+function fonts.dimenfactor(unit,tfmdata)
+ if unit == "ex" then
+ return (tfmdata and tfmdata.parameters.x_height) or 655360
+ elseif unit == "em" then
+ return (tfmdata and tfmdata.parameters.em_height) or 655360
+ else
+ return dimenfactors[unit] or unit
+ end
+end
+
+function fonts.cleanname(name)
+ texsprint(ctxcatcodes,fonts.names.cleanname(name))
+end
+
+local p, f = 1, "%0.1fpt" -- normally this value is changed only once
+
+local stripper = lpeg.patterns.strip_zeros
+
+function fonts.nbfs(amount,precision)
+ if precision ~= p then
+ p = precision
+ f = "%0." .. p .. "fpt"
+ end
+ texsprint(ctxcatcodes,lpegmatch(stripper,format(f,amount/65536)))
+end
+
+-- for the moment here, this will become a chain of extras that is
+-- hooked into the ctx registration (or scaler or ...)
+
+function fonts.set_digit_width(font)
+ local tfmtable = fontdata[font]
+ local parameters = tfmtable.parameters
+ local width = parameters.digitwidth
+ if not width then
+ width = round(parameters.quad/2) -- maybe tex.scale
+ local characters = tfmtable.characters
+ for i=48,57 do
+ local wd = round(characters[i].width)
+ if wd > width then
+ width = wd
+ end
+ end
+ parameters.digitwidth = width
+ end
+ return width
+end
+
+fonts.get_digit_width = fonts.set_digit_width
+
+-- soon to be obsolete:
+
+local loaded = { -- prevent loading (happens in cont-sys files)
+ ["original-base.map" ] = true,
+ ["original-ams-base.map" ] = true,
+ ["original-ams-euler.map"] = true,
+ ["original-public-lm.map"] = true,
+}
+
+function fonts.map.loadfile(name)
+ name = file.addsuffix(name,"map")
+ if not loaded[name] then
+ pdf.mapfile(name)
+ loaded[name] = true
+ end
+end
+
+local loaded = { -- prevent double loading
+}
+
+function fonts.map.loadline(how,line)
+ if line then
+ how = how .. " " .. line
+ elseif how == "" then
+ how = "= " .. line
+ end
+ if not loaded[how] then
+ pdf.mapline(how)
+ loaded[how] = true
+ end
+end
+
+function fonts.map.reset()
+ pdf.mapfile("")
+end
+
+fonts.map.reset() -- resets the default file
+
+-- we need an 'do after the banner hook'
+
+-- pdf.mapfile("mkiv-base.map") -- loads the default file
+
+local nounicode = byte("?")
+
+local function name_to_slot(name) -- maybe some day rawdata
+ local tfmdata = fonts.ids[font.current()]
+ local shared = tfmdata and tfmdata.shared
+ local fntdata = shared and shared.otfdata or shared.afmdata
+ if fntdata then
+ local unicode = fntdata.luatex.unicodes[name]
+ if not unicode then
+ return nounicode
+ elseif type(unicode) == "number" then
+ return unicode
+ else -- multiple unicodes
+ return unicode[1]
+ end
+ end
+ return nounicode
+end
+
+fonts.name_to_slot = name_to_slot
+
+function fonts.char(n) -- todo: afm en tfm
+ if type(n) == "string" then
+ n = name_to_slot(n)
+ end
+ if type(n) == "number" then
+ texsprint(ctxcatcodes,format("\\char%s ",n))
+ end
+end
+
+-- moved from ini:
+
+fonts.color = { } -- dummy in ini
+
+local attribute = attributes.private('color')
+local mapping = (attributes and attributes.list[attribute]) or { }
+
+local set_attribute = node.set_attribute
+local unset_attribute = node.unset_attribute
+
+function fonts.color.set(n,c)
+ local mc = mapping[c]
+ if not mc then
+ unset_attribute(n,attribute)
+ else
+ set_attribute(n,attribute,mc)
+ end
+end
+
+function fonts.color.reset(n)
+ unset_attribute(n,attribute)
+end
+
+-- this will become obsolete:
+
+fonts.otf.name_to_slot = name_to_slot
+fonts.afm.name_to_slot = name_to_slot
+
+fonts.otf.char = fonts.char
+fonts.afm.char = fonts.char
+
+-- this will change ...
+
+function fonts.show_char_data(n)
+ local tfmdata = fonts.ids[font.current()]
+ if tfmdata then
+ if type(n) == "string" then
+ n = utf.byte(n)
+ end
+ local chr = tfmdata.characters[n]
+ if chr then
+ write_nl(format("%s @ %s => U%04X => %s => ",tfmdata.fullname,tfmdata.size,n,utf.char(n)) .. serialize(chr,false))
+ end
+ end
+end
+
+function fonts.show_font_parameters()
+ local tfmdata = fonts.ids[font.current()]
+ if tfmdata then
+ local parameters, mathconstants = tfmdata.parameters, tfmdata.MathConstants
+ local hasparameters, hasmathconstants = parameters and next(parameters), mathconstants and next(mathconstants)
+ if hasparameters then
+ write_nl(format("%s @ %s => parameters => ",tfmdata.fullname,tfmdata.size) .. serialize(parameters,false))
+ end
+ if hasmathconstants then
+ write_nl(format("%s @ %s => math constants => ",tfmdata.fullname,tfmdata.size) .. serialize(mathconstants,false))
+ end
+ if not hasparameters and not hasmathconstants then
+ write_nl(format("%s @ %s => no parameters and/or mathconstants",tfmdata.fullname,tfmdata.size))
+ end
+ end
+end