You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
300 lines
9.6 KiB
300 lines
9.6 KiB
if not modules then modules = { } end modules ['luatex-fonts-gbn'] = {
|
|
version = 1.001,
|
|
comment = "companion to luatex-*.tex",
|
|
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
|
|
copyright = "PRAGMA ADE / ConTeXt Development Team",
|
|
license = "see context related readme files"
|
|
}
|
|
|
|
-- generic [base|node] mode handler
|
|
|
|
if context then
|
|
os.exit()
|
|
end
|
|
|
|
local next = next
|
|
|
|
local fonts = fonts
|
|
local nodes = nodes
|
|
|
|
local nuts = nodes.nuts -- context abstraction of direct nodes
|
|
|
|
local traverse_id = nuts.traverse_id
|
|
local flush_node = nuts.flush_node
|
|
|
|
local glyph_code = nodes.nodecodes.glyph
|
|
local disc_code = nodes.nodecodes.disc
|
|
|
|
local tonode = nuts.tonode
|
|
local tonut = nuts.tonut
|
|
|
|
local getfont = nuts.getfont
|
|
local getchar = nuts.getchar
|
|
local getid = nuts.getid
|
|
local getboth = nuts.getboth
|
|
local getprev = nuts.getprev
|
|
local getnext = nuts.getnext
|
|
local getdisc = nuts.getdisc
|
|
local setchar = nuts.setchar
|
|
local setlink = nuts.setlink
|
|
local setprev = nuts.setprev
|
|
|
|
-- from now on we apply ligaturing and kerning here because it might interfere with complex
|
|
-- opentype discretionary handling where the base ligature pass expect some weird extra
|
|
-- pointers (which then confuse the tail slider that has some checking built in)
|
|
|
|
local n_ligaturing = node.ligaturing
|
|
local n_kerning = node.kerning
|
|
|
|
local d_ligaturing = nuts.ligaturing
|
|
local d_kerning = nuts.kerning
|
|
|
|
local basemodepass = true
|
|
|
|
local function l_warning() logs.report("fonts","don't call 'node.ligaturing' directly") l_warning = nil end
|
|
local function k_warning() logs.report("fonts","don't call 'node.kerning' directly") k_warning = nil end
|
|
|
|
function node.ligaturing(...)
|
|
if basemodepass and l_warning then
|
|
l_warning()
|
|
end
|
|
return n_ligaturing(...)
|
|
end
|
|
|
|
function node.kerning(...)
|
|
if basemodepass and k_warning then
|
|
k_warning()
|
|
end
|
|
return n_kerning(...)
|
|
end
|
|
|
|
function nuts.ligaturing(...)
|
|
if basemodepass and l_warning then
|
|
l_warning()
|
|
end
|
|
return d_ligaturing(...)
|
|
end
|
|
|
|
function nuts.kerning(...)
|
|
if basemodepass and k_warning then
|
|
k_warning()
|
|
end
|
|
return d_kerning(...)
|
|
end
|
|
|
|
-- direct.ligaturing = nuts.ligaturing
|
|
-- direct.kerning = nuts.kerning
|
|
|
|
function nodes.handlers.setbasemodepass(v)
|
|
basemodepass = v
|
|
end
|
|
|
|
local function nodepass(head,groupcode,size,packtype,direction)
|
|
local fontdata = fonts.hashes.identifiers
|
|
if fontdata then
|
|
local usedfonts = { }
|
|
local basefonts = { }
|
|
local prevfont = nil
|
|
local basefont = nil
|
|
local variants = nil
|
|
local redundant = nil
|
|
local nofused = 0
|
|
for n in traverse_id(glyph_code,head) do
|
|
local font = getfont(n)
|
|
if font ~= prevfont then
|
|
if basefont then
|
|
basefont[2] = getprev(n)
|
|
end
|
|
prevfont = font
|
|
local used = usedfonts[font]
|
|
if not used then
|
|
local tfmdata = fontdata[font] --
|
|
if tfmdata then
|
|
local shared = tfmdata.shared -- we need to check shared, only when same features
|
|
if shared then
|
|
local processors = shared.processes
|
|
if processors and #processors > 0 then
|
|
usedfonts[font] = processors
|
|
nofused = nofused + 1
|
|
elseif basemodepass then
|
|
basefont = { n, nil }
|
|
basefonts[#basefonts+1] = basefont
|
|
end
|
|
end
|
|
local resources = tfmdata.resources
|
|
variants = resources and resources.variants
|
|
variants = variants and next(variants) and variants or false
|
|
end
|
|
else
|
|
local tfmdata = fontdata[prevfont]
|
|
if tfmdata then
|
|
local resources = tfmdata.resources
|
|
variants = resources and resources.variants
|
|
variants = variants and next(variants) and variants or false
|
|
end
|
|
end
|
|
end
|
|
if variants then
|
|
local char = getchar(n)
|
|
if (char >= 0xFE00 and char <= 0xFE0F) or (char >= 0xE0100 and char <= 0xE01EF) then
|
|
local hash = variants[char]
|
|
if hash then
|
|
local p = getprev(n)
|
|
if p and getid(p) == glyph_code then
|
|
local variant = hash[getchar(p)]
|
|
if variant then
|
|
setchar(p,variant)
|
|
end
|
|
end
|
|
end
|
|
-- per generic user request we always remove selectors
|
|
if not redundant then
|
|
redundant = { n }
|
|
else
|
|
redundant[#redundant+1] = n
|
|
end
|
|
end
|
|
end
|
|
end
|
|
local nofbasefonts = #basefonts
|
|
if redundant then
|
|
for i=1,#redundant do
|
|
local r = redundant[i]
|
|
local p, n = getboth(r)
|
|
if r == head then
|
|
head = n
|
|
setprev(n)
|
|
else
|
|
setlink(p,n)
|
|
end
|
|
if nofbasefonts > 0 then
|
|
for i=1,nofbasefonts do
|
|
local bi = basefonts[i]
|
|
if r == bi[1] then
|
|
bi[1] = n
|
|
end
|
|
if r == bi[2] then
|
|
bi[2] = n
|
|
end
|
|
end
|
|
end
|
|
flush_node(r)
|
|
end
|
|
end
|
|
for d in traverse_id(disc_code,head) do
|
|
local _, _, r = getdisc(d)
|
|
if r then
|
|
for n in traverse_id(glyph_code,r) do
|
|
local font = getfont(n)
|
|
if font ~= prevfont then
|
|
prevfont = font
|
|
local used = usedfonts[font]
|
|
if not used then
|
|
local tfmdata = fontdata[font] --
|
|
if tfmdata then
|
|
local shared = tfmdata.shared -- we need to check shared, only when same features
|
|
if shared then
|
|
local processors = shared.processes
|
|
if processors and #processors > 0 then
|
|
usedfonts[font] = processors
|
|
nofused = nofused + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if next(usedfonts) then
|
|
for font, processors in next, usedfonts do
|
|
for i=1,#processors do
|
|
head = processors[i](head,font,0,direction,nofused) or head
|
|
end
|
|
end
|
|
end
|
|
if basemodepass and nofbasefonts > 0 then
|
|
for i=1,nofbasefonts do
|
|
local range = basefonts[i]
|
|
local start = range[1]
|
|
local stop = range[2]
|
|
if start then
|
|
local front = head == start
|
|
local prev, next
|
|
if stop then
|
|
next = getnext(stop)
|
|
start, stop = d_ligaturing(start,stop)
|
|
start, stop = d_kerning(start,stop)
|
|
else
|
|
prev = getprev(start)
|
|
start = d_ligaturing(start)
|
|
start = d_kerning(start)
|
|
end
|
|
if prev then
|
|
setlink(prev,start)
|
|
end
|
|
if next then
|
|
setlink(stop,next)
|
|
end
|
|
if front and head ~= start then
|
|
head = start
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return head
|
|
end
|
|
|
|
local function basepass(head)
|
|
if basemodepass then
|
|
head = d_ligaturing(head)
|
|
head = d_kerning(head)
|
|
end
|
|
return head
|
|
end
|
|
|
|
local protectpass = node.direct.protect_glyphs
|
|
local injectpass = nodes.injections.handler
|
|
|
|
-- This is the only official public interface and this one can be hooked into a callback (chain) and
|
|
-- everything else can change!@ Functione being visibel doesn't mean that it's part of the api.
|
|
|
|
function nodes.handlers.nodepass(head,...)
|
|
if head then
|
|
return tonode(nodepass(tonut(head),...))
|
|
end
|
|
end
|
|
|
|
function nodes.handlers.basepass(head)
|
|
if head then
|
|
return tonode(basepass(tonut(head)))
|
|
end
|
|
end
|
|
|
|
function nodes.handlers.injectpass(head)
|
|
if head then
|
|
return tonode(injectpass(tonut(head)))
|
|
end
|
|
end
|
|
|
|
function nodes.handlers.protectpass(head)
|
|
if head then
|
|
protectpass(tonut(head))
|
|
return head
|
|
end
|
|
end
|
|
|
|
function nodes.simple_font_handler(head,groupcode,size,packtype,direction)
|
|
if head then
|
|
head = tonut(head)
|
|
head = nodepass(head,groupcode,size,packtype,direction)
|
|
head = injectpass(head)
|
|
if not basemodepass then
|
|
head = basepass(head)
|
|
end
|
|
protectpass(head)
|
|
head = tonode(head)
|
|
end
|
|
return head
|
|
end
|
|
|