s-languages-hyphenation.lua /size: 6742 b    last modification: 2021-10-28 13:51
1if not modules then modules = { } end modules ['s-languages-hyphenation'] = {
2    version   = 1.001,
3    comment   = "companion to s-languages-hyphenation.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9moduledata.languages             = moduledata.languages             or { }
10moduledata.languages.hyphenation = moduledata.languages.hyphenation or { }
11
12local a_colormodel    = attributes.private('colormodel')
13
14local tex             = tex
15local context         = context
16
17local nodecodes       = nodes.nodecodes
18local nuts            = nodes.nuts
19local nodepool        = nuts.pool
20
21local disc_code       = nodecodes.disc
22local glyph_code      = nodecodes.glyph
23
24local emwidths        = fonts.hashes.emwidths
25local exheights       = fonts.hashes.exheights
26
27local newkern         = nodepool.kern
28local newrule         = nodepool.rule
29local newglue         = nodepool.glue
30
31local insertnodeafter = nuts.insertafter
32
33local nextglyph       = nuts.traversers.glyph
34
35local tonut           = nodes.tonut
36local tonode          = nodes.tonode
37local getid           = nuts.getid
38local getnext         = nuts.getnext
39local getdisc         = nuts.getdisc
40local getattr         = nuts.getattr
41local getfont         = nuts.getfont
42local getfield        = nuts.getfield
43local getlanguage     = nuts.getlanguage
44local setlanguage     = nuts.setlanguage
45local setlink         = nuts.setlink
46local setdisc         = nuts.setdisc
47local setfield        = nuts.setfield
48local free_node       = nuts.free
49
50local tracers         = nodes.tracers
51local colortracers    = tracers and tracers.colors
52local setnodecolor    = colortracers.set
53
54-- maybe this will become code code
55
56local states      = table.setmetatableindex(function(t,k)
57    return {
58        lefthyphenmin  = tex.lefthyphenmin,
59        righthyphenmin = tex.righthyphenmin,
60        hyphenationmin = tex.hyphenationmin,
61        prehyphenchar  = tex.prehyphenchar,
62        posthyphenchar = tex.posthyphenchar,
63    }
64end)
65
66local currentlanguage = language.current or function() return tex.language end
67
68interfaces.implement {
69    name    = "storelanguagestate",
70    actions = function()
71        states[currentlanguage()] = {
72            lefthyphenmin  = tex.lefthyphenmin,
73            righthyphenmin = tex.righthyphenmin,
74            hyphenationmin = tex.hyphenationmin,
75            prehyphenchar  = tex.prehyphenchar,
76            posthyphenchar = tex.posthyphenchar,
77        }
78    end
79}
80
81function moduledata.languages.getstate(l)
82    return states[l] -- code
83end
84
85-- end
86
87local function identify(head,marked)
88    local current = tonut(head)
89    local prev    = nil
90    while current do
91        local id   = getid(current)
92        local next = getnext(current)
93        if id == disc_code then
94            if prev and next then -- asume glyphs
95                marked[#marked+1] = prev
96                local pre, post, replace, pre_tail, post_tail, replace_tail = getdisc(current,true)
97                if replace then
98                    setlink(prev,replace)
99                    setlink(replace_tail,next)
100                    setdisc(pre,post,nil)
101                    prev = tail
102                else
103                    setlink(prev,next)
104                end
105                free_node(current)
106            end
107        elseif id == glyph_code then
108            prev = current
109        else
110            prev = nil
111        end
112        current = next
113    end
114end
115
116local function mark(head,marked,w,h,d,how)
117    head = tonut(head)
118    for i=1,#marked do
119        local current = marked[i]
120        local font    = getfont(current)
121        local em      = emwidths[font]
122        local ex      = exheights[font]
123        local width   = w*em
124        local rule    = newrule(width,h*ex,d*ex)
125        head, current = insertnodeafter(head,current,newkern(-width/2))
126        head, current = insertnodeafter(head,current,rule)
127        head, current = insertnodeafter(head,current,newkern(-width/2))
128        head, current = insertnodeafter(head,current,newglue(0))
129        setnodecolor(rule,how) -- ,getattr(current,a_colormodel))
130    end
131end
132
133local langs        = { }
134local tags         = { }
135local noflanguages = 0
136local colorbytag   = false
137
138function moduledata.languages.hyphenation.showhyphens(head)
139    if noflanguages > 0 then
140        local marked = { }
141        local cached = { }
142        -- somehow assigning -1 fails
143        for n in nextglyph, tonut(head) do
144            cached[n] = {
145                getlanguage(n),
146                getfield(n,"left"),
147                getfield(n,"right")
148            }
149        end
150        for i=1,noflanguages do
151            local m = { }
152            local l = langs[i]
153            local s = states[l]
154            marked[i] = m
155            local lmin = s.lefthyphenmin
156            local rmin = s.righthyphenmin
157            for n in next, cached do
158                setlanguage(n,l)
159                setfield(n,"left",lmin)
160                setfield(n,"right",rmin)
161            end
162            languages.hyphenators.methods.original(head)
163            identify(head,m)
164        end
165        for i=noflanguages,1,-1 do
166            local l = noflanguages - i + 1
167            mark(head,marked[i],1/16,l/2,l/4,"hyphenation:"..(colorbytag and tags[i] or i))
168        end
169        for n, d in next, cached do
170            setlanguage(n,d[1])
171            setfield(n,"left",d[2])
172            setfield(n,"right",d[3])
173        end
174        return head, true
175    else
176        return head, false
177    end
178end
179
180function moduledata.languages.hyphenation.startcomparepatterns(list)
181    if list and list ~= "" then
182        tags = utilities.parsers.settings_to_array(list)
183    end
184    noflanguages = #tags
185    context.begingroup()
186    for i=1,noflanguages do
187        langs[i] = tags[i] and languages.getnumber(tags[i])
188        context.language{tags[i]}
189    end
190    context.endgroup()
191    nodes.tasks.enableaction("processors","moduledata.languages.hyphenation.showhyphens")
192end
193
194function moduledata.languages.hyphenation.stopcomparepatterns()
195    noflanguages = 0
196    nodes.tasks.disableaction("processors","moduledata.languages.hyphenation.showhyphens")
197end
198
199function moduledata.languages.hyphenation.showcomparelegend(list)
200    if list and list ~= "" then
201        tags = utilities.parsers.settings_to_array(list)
202    end
203    for i=1,#tags do
204        if i > 1 then
205            context.enspace()
206        end
207        context.color( { "hyphenation:"..(colorbytag and tags[i] or i) }, tags[i])
208    end
209end
210
211nodes.tasks.appendaction("processors","before","moduledata.languages.hyphenation.showhyphens")
212nodes.tasks.disableaction("processors","moduledata.languages.hyphenation.showhyphens")
213