diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/font-ext.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/font-ext.lua | 313 |
1 files changed, 297 insertions, 16 deletions
diff --git a/Master/texmf-dist/tex/context/base/font-ext.lua b/Master/texmf-dist/tex/context/base/font-ext.lua index 4ea9cf3caa0..331ffbdfa91 100644 --- a/Master/texmf-dist/tex/context/base/font-ext.lua +++ b/Master/texmf-dist/tex/context/base/font-ext.lua @@ -8,18 +8,18 @@ if not modules then modules = { } end modules ['font-ext'] = { local utf = unicode.utf8 local next, type, byte = next, type, string.byte -local gmatch, concat = string.gmatch, table.concat +local gmatch, concat, format = string.gmatch, table.concat, string.format local utfchar = utf.char local getparameters = utilities.parsers.getparameters -local allocate = utilities.storage.allocate - local trace_protrusion = false trackers.register("fonts.protrusion", function(v) trace_protrusion = v end) local trace_expansion = false trackers.register("fonts.expansion", function(v) trace_expansion = v end) local report_expansions = logs.reporter("fonts","expansions") local report_protrusions = logs.reporter("fonts","protrusions") +-- todo: byte(..) => 0xHHHH + --[[ldx-- <p>When we implement functions that deal with features, most of them will depend of the font format. Here we define the few that are kind @@ -27,6 +27,7 @@ of neutral.</p> --ldx]]-- local fonts = fonts +local fontdata = fonts.hashes.identifiers local otffeatures = fonts.constructors.newfeatures("otf") local registerotffeature = otffeatures.register @@ -34,6 +35,10 @@ local registerotffeature = otffeatures.register local afmfeatures = fonts.constructors.newfeatures("afm") local registerafmfeature = afmfeatures.register +local allocate = utilities.storage.allocate +local settings_to_array = utilities.parsers.settings_to_array +local setmetatableindex = table.setmetatableindex + -- -- -- -- -- -- -- shared -- -- -- -- -- -- @@ -475,7 +480,7 @@ fonts.goodies.register("protrusions", function(...) return fonts.goodies.report( -- -- -- local function initializenostackmath(tfmdata,value) - tfmdata.properties.no_stackmath = value and true + tfmdata.properties.nostackmath = value and true end registerotffeature { @@ -487,20 +492,16 @@ registerotffeature { } } -local function initializeitlc(tfmdata,value) +local function initializeitlc(tfmdata,value) -- hm, always value if value then - -- the magic 40 and it formula come from Dohyun Kim + -- the magic 40 and it formula come from Dohyun Kim but we might need another guess local parameters = tfmdata.parameters local italicangle = parameters.italicangle if italicangle and italicangle ~= 0 then - local uwidth = (parameters.uwidth or 40)/2 - for unicode, d in next, tfmdata.descriptions do - local it = d.boundingbox[3] - d.width + uwidth - if it ~= 0 then - d.italic = it - end - end - tfmdata.properties.italic_correction = true + local properties = tfmdata.properties + local factor = tonumber(value) or 1 + properties.hasitalics = true + properties.autoitalicamount = factor * (parameters.uwidth or 40)/2 end end end @@ -523,6 +524,30 @@ registerafmfeature { } } +local function initializetextitalics(tfmdata,value) -- yes no delay + local delay = value == "delay" + tfmdata.properties.textitalics = delay and true or value + tfmdata.properties.delaytextitalics = delay +end + +registerotffeature { + name = "textitalics", + description = "use alternative text italic correction", + initializers = { + base = initializetextitalics, + node = initializetextitalics, + } +} + +registerafmfeature { + name = "textitalics", + description = "use alternative text italic correction", + initializers = { + base = initializetextitalics, + node = initializetextitalics, + } +} + -- slanting local function initializeslant(tfmdata,value) @@ -534,7 +559,7 @@ local function initializeslant(tfmdata,value) elseif value < -1 then value = -1 end - tfmdata.parameters.slant_factor = value + tfmdata.parameters.slantfactor = value end registerotffeature { @@ -564,7 +589,7 @@ local function initializeextend(tfmdata,value) elseif value < -10 then value = -10 end - tfmdata.parameters.extend_factor = value + tfmdata.parameters.extendfactor = value end registerotffeature { @@ -585,6 +610,202 @@ registerafmfeature { } } +-- For Wolfgang Schuster: +-- +-- \definefontfeature[thisway][default][script=hang,language=zhs,dimensions={2,2,2}] +-- \definedfont[file:kozminpr6nregular*thisway] +-- +-- For the moment we don't mess with the descriptions. + +local function manipulatedimensions(tfmdata,key,value) + if type(value) == "string" and value ~= "" then + local characters = tfmdata.characters + local parameters = tfmdata.parameters + local emwidth = parameters.quad + local exheight = parameters.xheight + local spec = settings_to_array(value) + local width = (spec[1] or 0) * emwidth + local height = (spec[2] or 0) * exheight + local depth = (spec[3] or 0) * exheight + if width > 0 then + local resources = tfmdata.resources + local additions = { } + local private = resources.private + for unicode, old_c in next, characters do + local oldwidth = old_c.width + if oldwidth ~= width then + -- Defining the tables in one step is more efficient + -- than adding fields later. + private = private + 1 + local new_c + local commands = { + { "right", (width - oldwidth) / 2 }, + { "slot", 1, private }, + } + if height > 0 then + if depth > 0 then + new_c = { + width = width, + height = height, + depth = depth, + commands = commands, + } + else + new_c = { + width = width, + height = height, + commands = commands, + } + end + else + if depth > 0 then + new_c = { + width = width, + depth = depth, + commands = commands, + } + else + new_c = { + width = width, + commands = commands, + } + end + end + setmetatableindex(new_c,old_c) + characters[unicode] = new_c + additions[private] = old_c + end + end + for k, v in next, additions do + characters[k] = v + end + resources.private = private + elseif height > 0 and depth > 0 then + for unicode, old_c in next, characters do + old_c.height = height + old_c.depth = depth + end + elseif height > 0 then + for unicode, old_c in next, characters do + old_c.height = height + end + elseif depth > 0 then + for unicode, old_c in next, characters do + old_c.depth = depth + end + end + end +end + +registerotffeature { + name = "dimensions", + description = "force dimensions", + manipulators = { + base = manipulatedimensions, + node = manipulatedimensions, + } +} + +-- for zhichu chen (see mailing list archive): we might add a few more variants +-- in due time +-- +-- \definefontfeature[boxed][default][boundingbox=yes] % paleblue +-- +-- maybe: +-- +-- \definecolor[DummyColor][s=.75,t=.5,a=1] {\DummyColor test} \nopdfcompression +-- +-- local gray = { "special", "pdf: /Tr1 gs .75 g" } +-- local black = { "special", "pdf: /Tr0 gs 0 g" } + +local push = { "push" } +local pop = { "pop" } +local gray = { "special", "pdf: .75 g" } +local black = { "special", "pdf: 0 g" } + +local downcache = { } -- handy for huge cjk fonts +local rulecache = { } -- handy for huge cjk fonts + +setmetatableindex(downcache,function(t,d) + local v = { "down", d } + t[d] = v + return v +end) + +setmetatableindex(rulecache,function(t,h) + local v = { } + t[h] = v + setmetatableindex(v,function(t,w) + local v = { "rule", h, w } + t[w] = v + return v + end) + return v +end) + +local function showboundingbox(tfmdata,key,value) + if value then + local vfspecials = backends.pdf.tables.vfspecials + local gray = vfspecials and (vfspecials.rulecolors[value] or vfspecials.rulecolors.palegray) or gray + local characters = tfmdata.characters + local resources = tfmdata.resources + local additions = { } + local private = resources.private + for unicode, old_c in next, characters do + private = private + 1 + local width = old_c.width or 0 + local height = old_c.height or 0 + local depth = old_c.depth or 0 + local new_c + if depth == 0 then + new_c = { + width = width, + height = height, + commands = { + push, + gray, + rulecache[height][width], + black, + pop, + { "slot", 1, private }, + } + } + else + new_c = { + width = width, + height = height, + depth = depth, + commands = { + push, + downcache[depth], + gray, + rulecache[height+depth][width], + black, + pop, + { "slot", 1, private }, + } + } + end + setmetatableindex(new_c,old_c) + characters[unicode] = new_c + additions[private] = old_c + end + for k, v in next, additions do + characters[k] = v + end + resources.private = private + end +end + +registerotffeature { + name = "boundingbox", + description = "show boundingbox", + manipulators = { + base = showboundingbox, + node = showboundingbox, + } +} + -- -- historic stuff, move from font-ota (handled differently, typo-rep) -- -- local delete_node = nodes.delete @@ -651,3 +872,63 @@ registerafmfeature { -- node = processformatters, -- } -- } + +-- a handy helper (might change or be moved to another namespace) + +local new_special = nodes.pool.special +local new_glyph = nodes.pool.glyph +local hpack_node = node.hpack + +function fonts.helpers.addprivate(tfmdata,name,characterdata) + local properties = tfmdata.properties + local privates = properties.privates + local lastprivate = properties.lastprivate + if lastprivate then + lastprivate = lastprivate + 1 + else + lastprivate = 0xE000 + end + if not privates then + privates = { } + properties.privates = privates + end + privates[name] = lastprivate + properties.lastprivate = lastprivate + tfmdata.characters[lastprivate] = characterdata + if properties.finalized then + properties.lateprivates = true + end + return lastprivate +end + +function fonts.helpers.getprivatenode(tfmdata,name) + local properties = tfmdata.properties + local privates = properties and properties.privates + if privates then + local p = privates[name] + if p then + local char = tfmdata.characters[p] + local commands = char.commands + if commands then + local fake = hpack_node(new_special(commands[1][2])) + fake.width = char.width + fake.height = char.height + fake.depth = char.depth + return fake + else + -- todo: set current attribibutes + return new_glyph(properties.id,p) + end + end + end +end + +function fonts.helpers.hasprivate(tfmdata,name) + local properties = tfmdata.properties + local privates = properties and properties.privates + return privates and privates[name] or false +end + +function commands.getprivatechar(name) + context(fonts.helpers.getprivatenode(fontdata[font.current()],name)) +end |