Current File : //usr/share/texlive/texmf-dist/tex/luatex/luaotfload/fontloader-font-imp-effects.lua |
if not modules then modules = { } end modules ['font-imp-effects'] = {
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"
}
-- todo: pickup from goodies: if type(effect) then ...
local next, type, tonumber = next, type, tonumber
local is_boolean = string.is_boolean
local fonts = fonts
local handlers = fonts.handlers
local registerotffeature = handlers.otf.features.register
local registerafmfeature = handlers.afm.features.register
local settings_to_hash = utilities.parsers.settings_to_hash_colon_too
local helpers = fonts.helpers
local prependcommands = helpers.prependcommands
local charcommand = helpers.commands.char
local leftcommand = helpers.commands.left
local rightcommand = helpers.commands.right
local upcommand = helpers.commands.up
local downcommand = helpers.commands.down
local dummycommand = helpers.commands.dummy
----- constructors = fonts.constructors
----- getmathparameter = constructors.getmathparameter
----- setmathparameter = constructors.setmathparameter
local report_effect = logs.reporter("fonts","effect")
local report_slant = logs.reporter("fonts","slant")
local report_extend = logs.reporter("fonts","extend")
local report_squeeze = logs.reporter("fonts","squeeze")
local trace = false
trackers.register("fonts.effect", function(v) trace = v end)
trackers.register("fonts.slant", function(v) trace = v end)
trackers.register("fonts.extend", function(v) trace = v end)
trackers.register("fonts.squeeze",function(v) trace = v end)
local function initializeslant(tfmdata,value)
value = tonumber(value)
if not value then
value = 0
elseif value > 1 then
value = 1
elseif value < -1 then
value = -1
end
if trace then
report_slant("applying %0.3f",value)
end
tfmdata.parameters.slantfactor = value
end
local specification = {
name = "slant",
description = "slant glyphs",
initializers = {
base = initializeslant,
node = initializeslant,
}
}
registerotffeature(specification)
registerafmfeature(specification)
local function initializeextend(tfmdata,value)
value = tonumber(value)
if not value then
value = 0
elseif value > 10 then
value = 10
elseif value < -10 then
value = -10
end
if trace then
report_extend("applying %0.3f",value)
end
tfmdata.parameters.extendfactor = value
end
local specification = {
name = "extend",
description = "scale glyphs horizontally",
initializers = {
base = initializeextend,
node = initializeextend,
}
}
registerotffeature(specification)
registerafmfeature(specification)
local function initializesqueeze(tfmdata,value)
value = tonumber(value)
if not value then
value = 0
elseif value > 10 then
value = 10
elseif value < -10 then
value = -10
end
if trace then
report_squeeze("applying %0.3f",value)
end
tfmdata.parameters.squeezefactor = value
end
local specification = {
name = "squeeze",
description = "scale glyphs vertically",
initializers = {
base = initializesqueeze,
node = initializesqueeze,
}
}
registerotffeature(specification)
registerafmfeature(specification)
local effects = {
inner = 0,
normal = 0,
outer = 1,
outline = 1,
both = 2,
hidden = 3,
}
local function initializeeffect(tfmdata,value)
local spec
if type(value) == "number" then
spec = { width = value }
else
spec = settings_to_hash(value)
end
local effect = spec.effect or "both"
local width = tonumber(spec.width) or 0
local mode = effects[effect]
if not mode then
report_effect("invalid effect %a",effect)
elseif width == 0 and mode == 0 then
report_effect("invalid width %a for effect %a",width,effect)
else
local parameters = tfmdata.parameters
local properties = tfmdata.properties
parameters.mode = mode
parameters.width = width * 1000
if is_boolean(spec.auto) == true then
local squeeze = 1 - width/20
local average = (1 - squeeze) * width * 100
spec.squeeze = squeeze
spec.extend = 1 + width/2
spec.wdelta = average
spec.hdelta = average/2
spec.ddelta = average/2
spec.vshift = average/2
end
local factor = tonumber(spec.factor) or 0
local hfactor = tonumber(spec.hfactor) or factor
local vfactor = tonumber(spec.vfactor) or factor
local delta = tonumber(spec.delta) or 1
local wdelta = tonumber(spec.wdelta) or delta
local hdelta = tonumber(spec.hdelta) or delta
local ddelta = tonumber(spec.ddelta) or hdelta
local vshift = tonumber(spec.vshift) or 0
local slant = spec.slant
local extend = spec.extend
local squeeze = spec.squeeze
if slant then
initializeslant(tfmdata,slant)
end
if extend then
initializeextend(tfmdata,extend)
end
if squeeze then
initializesqueeze(tfmdata,squeeze)
end
properties.effect = {
effect = effect,
width = width,
factor = factor,
hfactor = hfactor,
vfactor = vfactor,
wdelta = wdelta,
hdelta = hdelta,
ddelta = ddelta,
vshift = vshift,
slant = tfmdata.parameters.slantfactor,
extend = tfmdata.parameters.extendfactor,
squeeze = tfmdata.parameters.squeezefactor,
}
end
end
local rules = {
"RadicalRuleThickness",
"OverbarRuleThickness",
"FractionRuleThickness",
"UnderbarRuleThickness",
}
-- local commands = char.commands
-- if commands then
-- local command = commands[1]
-- if command and command[1] == "right" then
-- commands[1] = rightcommand[command[2]-snap]
-- end
-- end
-- radicals are not yet ok
local setmathparameters
local setmathcharacters
if CONTEXTLMTXMODE and CONTEXTLMTXMODE > 0 then
setmathparameters = function(tfmdata,characters,mathparameters,dx,dy,squeeze,multiplier)
if delta ~= 0 then
for i=1,#rules do
local name = rules[i]
local value = mathparameters[name]
if value then
mathparameters[name] = (squeeze or 1) * (value + dy)
end
end
end
end
setmathcharacters = function()
end
else
setmathparameters = function(tfmdata,characters,mathparameters,dx,dy,squeeze,multiplier)
if delta ~= 0 then
for i=1,#rules do
local name = rules[i]
local value = mathparameters[name]
if value then
mathparameters[name] = (squeeze or 1) * (value + dy)
end
end
end
end
setmathcharacters = function(tfmdata,characters,mathparameters,dx,dy,squeeze,wdelta,hdelta,ddelta)
-- still not the perfect rule
local function wdpatch(char)
if wsnap ~= 0 then
char.width = char.width + wdelta/2
end
end
local function htpatch(char)
if hsnap ~= 0 then
local height = char.height
if height then
char.height = char.height + 2 * dy
end
end
end
local character = characters[0x221A]
if character and character.next then
local char = character
local next = character.next
wdpatch(char)
htpatch(char)
while next do
char = characters[next]
wdpatch(char)
htpatch(char)
next = char.next
end
if char then
local v = char.vert_variants
if v then
local top = v[#v]
if top then
local char = characters[top.glyph]
htpatch(char)
end
end
end
end
end
end
-- local show_effect = { "lua", function(f,c)
-- report_effect("font id %i, char %C",f,c)
-- inspect(fonts.hashes.characters[f][c])
-- end }
local shiftmode = CONTEXTLMTXMODE and CONTEXTLMTXMODE > 0
local function manipulateeffect(tfmdata)
local effect = tfmdata.properties.effect
if effect then
local characters = tfmdata.characters
local parameters = tfmdata.parameters
local mathparameters = tfmdata.mathparameters
local multiplier = effect.width * 100
local factor = parameters.factor
local hfactor = parameters.hfactor
local vfactor = parameters.vfactor
local wdelta = effect.wdelta * hfactor * multiplier
local hdelta = effect.hdelta * vfactor * multiplier
local ddelta = effect.ddelta * vfactor * multiplier
local vshift = effect.vshift * vfactor * multiplier
local squeeze = effect.squeeze
local hshift = wdelta / 2
local dx = multiplier * vfactor
local dy = vshift
local factor = (1 + effect.factor) * factor
local hfactor = (1 + effect.hfactor) * hfactor
local vfactor = (1 + effect.vfactor) * vfactor
if shiftmode then
parameters.hshift = hshift
parameters.vshift = vshift
else
vshift = vshift ~= 0 and upcommand[vshift] or false
hshift = rightcommand[hshift]
end
for unicode, character in next, characters do
local oldwidth = character.width
local oldheight = character.height
local olddepth = character.depth
if oldwidth and oldwidth > 0 then
character.width = oldwidth + wdelta
if not shiftmode then
local commands = character.commands
if vshift then
if commands then
prependcommands ( commands,
-- show_effect,
hshift,
vshift
)
else
character.commands = {
-- show_effect,
hshift,
vshift,
charcommand[unicode]
}
end
else
if commands then
prependcommands ( commands,
-- show_effect,
hshift
)
else
character.commands = {
-- show_effect,
hshift,
charcommand[unicode]
}
end
end
end
end
if oldheight and oldheight > 0 then
character.height = oldheight + hdelta
end
if olddepth and olddepth > 0 then
character.depth = olddepth + ddelta
end
end
if mathparameters then
setmathparameters(tfmdata,characters,mathparameters,dx,dy,squeeze,multiplier)
setmathcharacters(tfmdata,characters,mathparameters,dx,dy,squeeze,wdelta,hdelta,ddelta)
end
parameters.factor = factor
parameters.hfactor = hfactor
parameters.vfactor = vfactor
if trace then
report_effect("applying")
report_effect(" effect : %s", effect.effect)
report_effect(" width : %s => %s", effect.width, multiplier)
report_effect(" factor : %s => %s", effect.factor, factor )
report_effect(" hfactor : %s => %s", effect.hfactor,hfactor)
report_effect(" vfactor : %s => %s", effect.vfactor,vfactor)
report_effect(" wdelta : %s => %s", effect.wdelta, wdelta)
report_effect(" hdelta : %s => %s", effect.hdelta, hdelta)
report_effect(" ddelta : %s => %s", effect.ddelta, ddelta)
end
end
end
local specification = {
name = "effect",
description = "apply effects to glyphs",
initializers = {
base = initializeeffect,
node = initializeeffect,
},
manipulators = {
base = manipulateeffect,
node = manipulateeffect,
},
}
registerotffeature(specification)
registerafmfeature(specification)
local function initializeoutline(tfmdata,value)
value = tonumber(value)
if not value then
value = 0
else
value = tonumber(value) or 0
end
local parameters = tfmdata.parameters
local properties = tfmdata.properties
parameters.mode = effects.outline
parameters.width = value * 1000
properties.effect = {
effect = effect,
width = width,
}
end
local specification = {
name = "outline",
description = "outline glyphs",
initializers = {
base = initializeoutline,
node = initializeoutline,
}
}
registerotffeature(specification)
registerafmfeature(specification)