summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/font-con.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/font-con.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/font-con.lua359
1 files changed, 278 insertions, 81 deletions
diff --git a/Master/texmf-dist/tex/context/base/font-con.lua b/Master/texmf-dist/tex/context/base/font-con.lua
index 5d30842ef7f..92809968857 100644
--- a/Master/texmf-dist/tex/context/base/font-con.lua
+++ b/Master/texmf-dist/tex/context/base/font-con.lua
@@ -7,12 +7,15 @@ if not modules then modules = { } end modules ['font-con'] = {
}
+-- some names of table entries will be changed (no _)
+
local utf = unicode.utf8
local next, tostring, rawget = next, tostring, rawget
local format, match, lower, gsub = string.format, string.match, string.lower, string.gsub
local utfbyte = utf.byte
local sort, insert, concat, sortedkeys, serialize, fastcopy = table.sort, table.insert, table.concat, table.sortedkeys, table.serialize, table.fastcopy
+local derivetable = table.derive
local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
local trace_scaling = false trackers.register("fonts.scaling" , function(v) trace_scaling = v end)
@@ -25,32 +28,128 @@ local report_defining = logs.reporter("fonts","defining")
<p>Here we only implement a few helper functions.</p>
--ldx]]--
-local fonts = fonts
-local constructors = { }
-fonts.constructors = constructors
-local handlers = { }
-fonts.handlers = handlers
+local fonts = fonts
+local constructors = { }
+fonts.constructors = constructors
+local handlers = { }
+fonts.handlers = handlers
-local specifiers = fonts.specifiers
-local contextsetups = specifiers.contextsetups
-local contextnumbers = specifiers.contextnumbers
+local specifiers = fonts.specifiers
+local contextsetups = specifiers.contextsetups
+local contextnumbers = specifiers.contextnumbers
-local allocate = utilities.storage.allocate
-local setmetatableindex = table.setmetatableindex
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
-- will be directives
-constructors.dontembed = allocate()
-constructors.mathactions = { }
-constructors.autocleanup = true
-constructors.namemode = "fullpath" -- will be a function
+constructors.dontembed = allocate()
+constructors.autocleanup = true
+constructors.namemode = "fullpath" -- will be a function
+
+constructors.version = 1.01
+constructors.cache = containers.define("fonts", "constructors", constructors.version, false)
+
+constructors.privateoffset = 0xF0000 -- 0x10FFFF
+
+-- Some experimental helpers (handy for tracing):
+--
+-- todo: extra:
+--
+-- extra_space => space.extra
+-- space => space.width
+-- space_stretch => space.stretch
+-- space_shrink => space.shrink
-constructors.version = 1.01
-constructors.cache = containers.define("fonts", "constructors", constructors.version, false)
+-- We do keep the x-height, extra_space, space_shrink and space_stretch
+-- around as these are low level official names.
-constructors.privateoffset = 0xF0000 -- 0x10FFFF
+constructors.keys = {
+ properties = {
+ encodingbytes = "number",
+ embedding = "number",
+ cidinfo = {
+ },
+ format = "string",
+ fontname = "string",
+ fullname = "string",
+ filename = "filename",
+ psname = "string",
+ name = "string",
+ virtualized = "boolean",
+ hasitalics = "boolean",
+ autoitalicamount = "basepoints",
+ nostackmath = "boolean",
+ noglyphnames = "boolean",
+ mode = "string",
+ hasmath = "boolean",
+ mathitalics = "boolean",
+ textitalics = "boolean",
+ finalized = "boolean",
+ },
+ parameters = {
+ mathsize = "number",
+ scriptpercentage = "float",
+ scriptscriptpercentage = "float",
+ units = "cardinal",
+ designsize = "scaledpoints",
+ expansion = {
+ stretch = "integerscale", -- might become float
+ shrink = "integerscale", -- might become float
+ step = "integerscale", -- might become float
+ auto = "boolean",
+ },
+ protrusion = {
+ auto = "boolean",
+ },
+ slantfactor = "float",
+ extendfactor = "float",
+ factor = "float",
+ hfactor = "float",
+ vfactor = "float",
+ size = "scaledpoints",
+ units = "scaledpoints",
+ scaledpoints = "scaledpoints",
+ slantperpoint = "scaledpoints",
+ spacing = {
+ width = "scaledpoints",
+ stretch = "scaledpoints",
+ shrink = "scaledpoints",
+ extra = "scaledpoints",
+ },
+ xheight = "scaledpoints",
+ quad = "scaledpoints",
+ ascender = "scaledpoints",
+ descender = "scaledpoints",
+ synonyms = {
+ space = "spacing.width",
+ spacestretch = "spacing.stretch",
+ spaceshrink = "spacing.shrink",
+ extraspace = "spacing.extra",
+ x_height = "xheight",
+ space_stretch = "spacing.stretch",
+ space_shrink = "spacing.shrink",
+ extra_space = "spacing.extra",
+ em = "quad",
+ ex = "xheight",
+ slant = "slantperpoint",
+ },
+ },
+ description = {
+ width = "basepoints",
+ height = "basepoints",
+ depth = "basepoints",
+ boundingbox = { },
+ },
+ character = {
+ width = "scaledpoints",
+ height = "scaledpoints",
+ depth = "scaledpoints",
+ italic = "scaledpoints",
+ },
+}
--- This might become an interface;
+-- This might become an interface:
local designsizes = allocate()
constructors.designsizes = designsizes
@@ -99,7 +198,7 @@ excessive memory usage in CJK fonts, we no longer pass the boundingbox.)</p>
-- The scaler is only used for otf and afm and virtual fonts. If
-- a virtual font has italic correction make sure to set the
--- italic_correction flag. Some more flags will be added in
+-- hasitalics flag. Some more flags will be added in
-- the future.
--[[ldx--
@@ -145,39 +244,75 @@ function constructors.calculatescale(tfmdata,scaledpoints)
return scaledpoints, scaledpoints / (parameters.units or 1000) -- delta
end
-function constructors.assignmathparameters(target,tfmdata)
+local unscaled = {
+ ScriptPercentScaleDown = true,
+ ScriptScriptPercentScaleDown = true,
+ RadicalDegreeBottomRaisePercent = true
+}
+
+function constructors.assignmathparameters(target,original) -- simple variant, not used in context
-- when a tfm file is loaded, it has already been scaled
- -- and it never enters the scaled so this is otf only
+ -- and it never enters the scaled so this is otf only and
+ -- even then we do some extra in the context math plugins
local mathparameters = original.mathparameters
if mathparameters and next(mathparameters) then
local targetparameters = target.parameters
+ local targetproperties = target.properties
local targetmathparameters = { }
- local factor = targetparameters.factor
+ local factor = targetproperties.math_is_scaled and 1 or targetparameters.factor
for name, value in next, mathparameters do
- if name == "RadicalDegreeBottomRaisePercent" then
+ if unscaled[name] then
targetmathparameters[name] = value
else
targetmathparameters[name] = value * factor
end
end
- if not targetmathparameters.AccentBaseHeight then
- targetmathparameters.AccentBaseHeight = nil -- safeguard, still needed?
- end
if not targetmathparameters.FractionDelimiterSize then
- targetmathparameters.FractionDelimiterSize = 0
+ targetmathparameters.FractionDelimiterSize = 1.01 * targetparameters.size
end
if not mathparameters.FractionDelimiterDisplayStyleSize then
- targetmathparameters.FractionDelimiterDisplayStyleSize = 0
+ targetmathparameters.FractionDelimiterDisplayStyleSize = 2.40 * targetparameters.size
end
target.mathparameters = targetmathparameters
end
end
+function constructors.beforecopyingcharacters(target,original)
+ -- can be used for additional tweaking
+end
+
+function constructors.aftercopyingcharacters(target,original)
+ -- can be used for additional tweaking
+end
+
+function constructors.enhanceparameters(parameters)
+ local xheight = parameters.x_height
+ local quad = parameters.quad
+ local space = parameters.space
+ local stretch = parameters.space_stretch
+ local shrink = parameters.space_shrink
+ local extra = parameters.extra_space
+ local slant = parameters.slant
+ parameters.xheight = xheight
+ parameters.spacestretch = stretch
+ parameters.spaceshrink = shrink
+ parameters.extraspace = extra
+ parameters.em = quad
+ parameters.ex = xheight
+ parameters.slantperpoint = slant
+ parameters.spacing = {
+ width = space,
+ stretch = stretch,
+ shrink = shrink,
+ extra = extra,
+ }
+end
+
function constructors.scale(tfmdata,specification)
local target = { } -- the new table
--
if tonumber(specification) then
- specification = { size = specification }
+ specification = { size = specification }
end
--
local scaledpoints = specification.size
@@ -194,10 +329,9 @@ function constructors.scale(tfmdata,specification)
local mathparameters = tfmdata.mathparameters or { }
--
local targetcharacters = { }
- local targetdescriptions = table.derive(descriptions)
- local targetparameters = table.derive(parameters)
- -- local targetmathparameters = table.fastcopy(mathparameters) -- happens elsewhere
- local targetproperties = table.derive(properties)
+ local targetdescriptions = derivetable(descriptions)
+ local targetparameters = derivetable(parameters)
+ local targetproperties = derivetable(properties)
local targetgoodies = goodies -- we need to loop so no metatable
target.characters = targetcharacters
target.descriptions = targetdescriptions
@@ -213,9 +347,10 @@ function constructors.scale(tfmdata,specification)
-- specification.textsize : natural (text)size
-- parameters.mathsize : 1=text 2=script 3=scriptscript >1000 enforced size (feature value other than yes)
--
- local mathsize = tonumber(specification.mathsize) or 0
- local textsize = tonumber(specification.textsize) or scaledpoints
- local forcedsize = tonumber(parameters.mathsize ) or 0
+ local mathsize = tonumber(specification.mathsize) or 0
+ local textsize = tonumber(specification.textsize) or scaledpoints
+ local forcedsize = tonumber(parameters.mathsize ) or 0
+ local extrafactor = tonumber(specification.factor ) or 1
if (mathsize == 2 or forcedsize == 2) and parameters.scriptpercentage then
scaledpoints = parameters.scriptpercentage * textsize / 100
elseif (mathsize == 3 or forcedsize == 3) and parameters.scriptscriptpercentage then
@@ -302,17 +437,17 @@ function constructors.scale(tfmdata,specification)
target.auto_protrude = protrusion.auto
end
-- widening
- local extend_factor = parameters.extend_factor or 0
- if extend_factor ~= 0 and extend_factor ~= 1 then
- hdelta = hdelta * extend_factor
- target.extend = extend_factor * 1000 -- extent ?
+ local extendfactor = parameters.extendfactor or 0
+ if extendfactor ~= 0 and extendfactor ~= 1 then
+ hdelta = hdelta * extendfactor
+ target.extend = extendfactor * 1000 -- extent ?
else
target.extend = 1000 -- extent ?
end
-- slanting
- local slant_factor = parameters.slant_factor or 0
- if slant_factor ~= 0 then
- target.slant = slant_factor * 1000
+ local slantfactor = parameters.slantfactor or 0
+ if slantfactor ~= 0 then
+ target.slant = slantfactor * 1000
else
target.slant = 0
end
@@ -324,19 +459,20 @@ function constructors.scale(tfmdata,specification)
targetparameters.units = units
targetparameters.scaledpoints = askedscaledpoints
--
- local isvirtual = properties.virtualized or tfmdata.type == "virtual"
- local hasquality = target.auto_expand or target.auto_protrude
- local hasitalic = properties.italic_correction
- local stackmath = not properties.no_stackmath
- local nonames = properties.noglyphnames
- local nodemode = properties.mode == "node"
+ local isvirtual = properties.virtualized or tfmdata.type == "virtual"
+ local hasquality = target.auto_expand or target.auto_protrude
+ local hasitalics = properties.hasitalics
+ local autoitalicamount = properties.autoitalicamount
+ local stackmath = not properties.nostackmath
+ local nonames = properties.noglyphnames
+ local nodemode = properties.mode == "node"
--
if changed and not next(changed) then
changed = false
end
--
target.type = isvirtual and "virtual" or "real"
- -- this will move to some subtable so that it is copied at once
+ --
target.postprocessors = tfmdata.postprocessors
--
local targetslant = (parameters.slant or parameters[1] or 0)
@@ -347,7 +483,7 @@ function constructors.scale(tfmdata,specification)
local targetquad = (parameters.quad or parameters[6] or 0)*hdelta
local targetextra_space = (parameters.extra_space or parameters[7] or 0)*hdelta
--
- targetparameters.slant = targetslant
+ targetparameters.slant = targetslant -- slantperpoint
targetparameters.space = targetspace
targetparameters.space_stretch = targetspace_stretch
targetparameters.space_shrink = targetspace_shrink
@@ -363,25 +499,27 @@ function constructors.scale(tfmdata,specification)
if descender then
targetparameters.descender = delta * descender
end
- -- copies, might disappear
- targetparameters.xheight = targetparameters.xheight or parameters.x_height
- targetparameters.extraspace = targetparameters.extraspace or parameters.extra_space
- targetparameters.spacestretch = targetparameters.spacestretch or parameters.space_stretch
- targetparameters.spaceshrink = targetparameters.spaceshrink or parameters.space_shrink
+ --
+ constructors.enhanceparameters(targetparameters) -- official copies for us
--
local protrusionfactor = (targetquad ~= 0 and 1000/targetquad) or 0
local scaledwidth = defaultwidth * hdelta
local scaledheight = defaultheight * vdelta
local scaleddepth = defaultdepth * vdelta
--
- local hasmath = (properties.has_math or next(mathparameters)) and true
+ if trace_defining then
+ report_defining("scaling by (%s,%s): name '%s', fullname: '%s', filename: '%s'",
+ hdelta,vdelta,name or "noname",fullname or "nofullname",filename or "nofilename")
+ end
+ --
+ local hasmath = (properties.hasmath or next(mathparameters)) and true
if hasmath then
if trace_defining then
report_defining("math enabled for: name '%s', fullname: '%s', filename: '%s'",
name or "noname",fullname or "nofullname",filename or "nofilename")
end
constructors.assignmathparameters(target,tfmdata) -- does scaling and whatever is needed
- properties.has_math = true
+ properties.hasmath = true
target.nomath = false
target.MathConstants = target.mathparameters
else
@@ -389,29 +527,75 @@ function constructors.scale(tfmdata,specification)
report_defining("math disabled for: name '%s', fullname: '%s', filename: '%s'",
name or "noname",fullname or "nofullname",filename or "nofilename")
end
- properties.has_math = false
+ properties.hasmath = false
target.nomath = true
target.mathparameters = nil -- nop
end
--
- local sharedkerns = { }
+ local italickey = "italic"
+ --
+ -- some context specific trickery (this will move to a plugin)
+ --
+ if hasmath then
+ if properties.mathitalics then
+ italickey = "italic_correction"
+ if trace_defining then
+ report_defining("math italics disabled for: name '%s', fullname: '%s', filename: '%s'",
+ name or "noname",fullname or "nofullname",filename or "nofilename")
+ end
+ end
+ autoitalicamount = false -- new
+ else
+ if properties.textitalics then
+ italickey = "italic_correction"
+ if trace_defining then
+ report_defining("text italics disabled for: name '%s', fullname: '%s', filename: '%s'",
+ name or "noname",fullname or "nofullname",filename or "nofilename")
+ end
+ if properties.delaytextitalics then
+ autoitalicamount = false
+ end
+ end
+ end
+ --
+ -- end of context specific trickery
+ --
+ constructors.beforecopyingcharacters(target,tfmdata)
+ --
+ local sharedkerns = { }
+ --
+ -- we can have a dumb mode (basemode without math etc) that skips most
--
for unicode, character in next, characters do
- local chr, description, index
+ local chr, description, index, touni
if changed then
- -- basemode hack
+ -- basemode hack (we try to catch missing tounicodes, e.g. needed for ssty in math cambria)
local c = changed[unicode]
if c then
- description = descriptions[c] or character
+ description = descriptions[c] or descriptions[unicode] or character
character = characters[c] or character
index = description.index or c
+ if tounicode then
+ touni = tounicode[index] -- nb: index!
+ if not touni then -- goodie
+ local d = descriptions[unicode] or characters[unicode]
+ local i = d.index or unicode
+ touni = tounicode[i] -- nb: index!
+ end
+ end
else
description = descriptions[unicode] or character
index = description.index or unicode
+ if tounicode then
+ touni = tounicode[index] -- nb: index!
+ end
end
else
description = descriptions[unicode] or character
index = description.index or unicode
+ if tounicode then
+ touni = tounicode[index] -- nb: index!
+ end
end
local width = description.width
local height = description.height
@@ -454,15 +638,12 @@ function constructors.scale(tfmdata,specification)
}
end
end
+ if touni then
+ chr.tounicode = touni
+ end
-- if trace_scaling then
-- report_defining("t=%s, u=%s, i=%s, n=%s c=%s",k,chr.tounicode or "",index or 0,description.name or '-',description.class or '-')
-- end
- if tounicode then
- local tu = tounicode[index] -- nb: index!
- if tu then
- chr.tounicode = tu
- end
- end
if hasquality then
-- we could move these calculations elsewhere (saves calculations)
local ve = character.expansion_factor
@@ -478,11 +659,21 @@ function constructors.scale(tfmdata,specification)
chr.right_protruding = protrusionfactor*width*vr
end
end
- -- todo: hasitalic
- if hasitalic then
- local vi = description.italic or character.italic
+ --
+ if autoitalicamount then
+ local vi = description.italic
+ if not vi then
+ local vi = description.boundingbox[3] - description.width + autoitalicamount
+ if vi > 0 then -- < 0 indicates no overshoot or a very small auto italic
+ chr[italickey] = vi*hdelta
+ end
+ elseif vi ~= 0 then
+ chr[italickey] = vi*hdelta
+ end
+ elseif hasitalics then
+ local vi = description.italic
if vi and vi ~= 0 then
- chr.italic = vi*hdelta
+ chr[italickey] = vi*hdelta
end
end
-- to be tested
@@ -613,6 +804,9 @@ function constructors.scale(tfmdata,specification)
end
targetcharacters[unicode] = chr
end
+ --
+ constructors.aftercopyingcharacters(target,tfmdata)
+ --
return target
end
@@ -653,12 +847,12 @@ function constructors.finalize(tfmdata)
parameters.size = tfmdata.size
end
--
- if not parameters.extend_factor then
- parameters.extend_factor = tfmdata.extend or 0
+ if not parameters.extendfactor then
+ parameters.extendfactor = tfmdata.extend or 0
end
--
- if not parameters.slant_factor then
- parameters.slant_factor = tfmdata.slant or 0
+ if not parameters.slantfactor then
+ parameters.slantfactor = tfmdata.slant or 0
end
--
if not parameters.designsize then
@@ -711,8 +905,8 @@ function constructors.finalize(tfmdata)
-- tfmdata.fonts
-- tfmdata.unscaled
--
- if not properties.has_math then
- properties.has_math = not tfmdata.nomath
+ if not properties.hasmath then
+ properties.hasmath = not tfmdata.nomath
end
--
tfmdata.MathConstants = nil
@@ -997,7 +1191,7 @@ a helper function.</p>
function constructors.checkedfeatures(what,features)
local defaults = handlers[what].features.defaults
if features and next(features) then
- features = fastcopy(features) -- can be inherited
+ features = fastcopy(features) -- can be inherited (mt) but then no loops possible
for key, value in next, defaults do
if features[key] == nil then
features[key] = value
@@ -1031,7 +1225,7 @@ function constructors.initializefeatures(what,tfmdata,features,trace,report)
for i=1,#initializers do
local step = initializers[i]
local feature = step.name
--- we could intercept mode here .. needs a rewrite of this whole loop then btu it's cleaner that way
+-- we could intercept mode here .. needs a rewrite of this whole loop then but it's cleaner that way
local value = features[feature]
if not value then
-- disabled
@@ -1100,6 +1294,9 @@ function constructors.collectprocessors(what,tfmdata,features,trace,report)
end
end
end
+ elseif trace then
+ report("no feature processors for mode %s for font %s",
+ mode or 'unknown', tfmdata.properties.fullname or 'unknown')
end
end
return processes