summaryrefslogtreecommitdiff
path: root/tex/context/base/typo-rep.lua
blob: c70e90f275d6ce9ef84ff2ebbce45d861a4fe7da (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
if not modules then modules = { } end modules ['typo-rep'] = {
    version   = 1.001,
    comment   = "companion to node-ini.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

-- This was rather boring to program (more of the same) but I could
-- endure it by listening to a couple cd's by The Scene and The Lau
-- on the squeezebox on my desk.

local trace_stripping = false  trackers.register("nodes.stripping",  function(v) trace_stripping = v end)
                               trackers.register("fonts.stripping",  function(v) trace_stripping = v end)

local report_fonts = logs.new("fonts")

local delete_node   = nodes.delete
local replace_node  = nodes.replace
local copy_node     = node.copy
local has_attribute = node.has_attribute

local chardata  = characters.data
local collected = false
local glyph     = node.id("glyph")
local attribute = attributes.private("stripping")
local fontdata  = fonts.ids

nodes.stripping  = nodes.stripping or { }
local stripping  = nodes.stripping
stripping.glyphs = stripping.glyphs or { }
local glyphs     = stripping.glyphs

local function initialize()
    for k,v in next, chardata do
        if v.category == "cf" and v.visible ~= "yes" then
            if not glyphs[k]  then
                glyphs[k] = true
            end
        end
    end
    initialize = nil
end

local function process(what,head,current,char)
    if what == true then
        if trace_stripping then
            report_fonts("deleting 0x%05X from text",char)
        end
        head, current = delete_node(head,current)
    elseif type(what) == "function" then
        head, current = what(head,current)
        current = current.next
        if trace_stripping then
            report_fonts("processing 0x%05X in text",char)
        end
    elseif what then  -- assume node
        head, current = replace_node(head,current,copy_node(what))
        current = current.next
        if trace_stripping then
            report_fonts("replacing 0x%05X in text",char)
        end
    end
    return head, current
end

function nodes.stripping.process(head)
    local current, done = head, false
    while current do
        if current.id == glyph then
            -- it's more efficient to keep track of what needs to be kept
            local todo = has_attribute(current,attribute)
            if todo == 1 then
                local char = current.char
                local what = glyphs[char]
                if what then
                    head, current = process(what,head,current,char)
                    done = true
                else -- handling of spacing etc has to be done elsewhere
                    current = current.next
                end
            else
                current = current.next
            end
        else
            current = current.next
        end
    end
    return head, done
end

tasks.appendaction("processors","fonts","nodes.stripping.process",nil,"nodes.process_characters")
tasks.disableaction("processors","nodes.stripping.process")

function nodes.stripping.enable()
    if initialize then initialize() end
    tasks.enableaction("processors","nodes.stripping.process")
    function nodes.stripping.enable() end
end

-- bonus:

local initializers, methods = fonts.initializers, fonts.methods

local function processformatters(head,font)
    local how = fontdata[font].shared.features.formatters -- slow
    if how == nil or how == "strip" then -- nil when forced
        local current, done = head, false
        while current do
            if current.id == glyph and current.subtype<256 and current.font == font then
                local char = current.char
                local what = glyphs[char]
                if what then
                    head, current = process(what,head,current,char)
                    done = true
                else -- handling of spacing etc has to be done elsewhere
                    current = current.next
                end
            else
                current = current.next
            end
        end
        return head, done
    else
        return head, false
    end
end

function initializers.common.formatters(tfmdata,value)
    if initialize then initialize() end
end

initializers.base.otf.formatters = initializers.common.formatters
initializers.node.otf.formatters = initializers.common.formatters

methods.node.otf.formatters = processformatters
methods.base.otf.formatters = processformatters