summaryrefslogtreecommitdiff
path: root/tex/context/base/font-chk.lua
blob: fd4e2e2496194572a4abde333eefaed2335861af (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
if not modules then modules = { } end modules ['font-chk'] = {
    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"
}

-- possible optimization: delayed initialization of vectors
-- move to the nodes namespace

local report_fonts   = logs.reporter("fonts","checking")

local fonts          = fonts

fonts.checkers       = fonts.checkers or { }
local checkers       = fonts.checkers

local fonthashes     = fonts.hashes
local fontdata       = fonthashes.identifiers
local fontcharacters = fonthashes.characters

local is_character   = characters.is_character
local chardata       = characters.data

local tasks          = nodes.tasks
local enableaction   = tasks.enableaction
local disableaction  = tasks.disableaction

local glyph          = node.id('glyph')
local traverse_id    = node.traverse_id
local remove_node    = nodes.remove

-- maybe in fonts namespace
-- deletion can be option

local cleanup = false

-- to tfmdata.properties ?

local function onetimemessage(font,char,message)
    local tfmdata = fontdata[font]
    local shared = tfmdata.shared
    local messages = shared.messages
    if not messages then
        messages = { }
        shared.messages = messages
    end
    local category = messages[message]
    if not category then
        category = { }
        messages[message] = category
    end
    if not category[char] then
        report_fonts("char U+%05X in font '%s' with id %s: %s",char,tfmdata.properties.fullname,font,message)
        category[char] = true
    end
end

fonts.loggers.onetimemessage = onetimemessage

function checkers.missing(head)
    local lastfont, characters, found = nil, nil, nil
    for n in traverse_id(glyph,head) do
        local font = n.font
        local char = n.char
        if font ~= lastfont then
            characters = fontcharacters[font]
        end
        if not characters[char] and is_character[chardata[char].category] then
            if cleanup then
                onetimemessage(font,char,"missing (will be deleted)")
            else
                onetimemessage(font,char,"missing")
            end
            if not found then
                found = { n }
            else
                found[#found+1] = n
            end
        end
    end
    if found and cleanup then
        for i=1,#found do
            head = remove_node(head,found[i],true)
        end
    end
    return head, false
end

trackers.register("fonts.missing", function(v)
    if v then
        enableaction("processors","fonts.checkers.missing")
    else
        disableaction("processors","fonts.checkers.missing")
    end
    cleanup = v == "remove"
end)

function commands.checkcharactersinfont()
    enableaction("processors","fonts.checkers.missing")
end

function commands.removemissingcharacters()
    enableaction("processors","fonts.checkers.missing")
    cleanup = true
end