1if not modules then modules = { } end modules ['luatex-fonts-gbn'] = {
2 version = 1.001,
3 comment = "companion to luatex-*.tex",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9
10
11if context then
12 os.exit()
13end
14
15local next = next
16
17local fonts = fonts
18local nodes = nodes
19
20local nuts = nodes.nuts
21
22local traverseid = nuts.traverseid
23local flushnode = nuts.flushnode
24
25local glyph_code = nodes.nodecodes.glyph
26local disc_code = nodes.nodecodes.disc
27
28local tonode = nuts.tonode
29local tonut = nuts.tonut
30
31local getfont = nuts.getfont
32local getchar = nuts.getchar
33local getid = nuts.getid
34local getboth = nuts.getboth
35local getprev = nuts.getprev
36local getnext = nuts.getnext
37local getdisc = nuts.getdisc
38local setchar = nuts.setchar
39local setlink = nuts.setlink
40local setprev = nuts.setprev
41
42
43
44
45
46local n_ligaturing = node.ligaturing
47local n_kerning = node.kerning
48
49local d_ligaturing = nuts.ligaturing
50local d_kerning = nuts.kerning
51
52local basemodepass = true
53
54local function l_warning() logs.report("fonts","don't call 'node.ligaturing' directly") l_warning = nil end
55local function k_warning() logs.report("fonts","don't call 'node.kerning' directly") k_warning = nil end
56
57function node.ligaturing(...)
58 if basemodepass and l_warning then
59 l_warning()
60 end
61 return n_ligaturing(...)
62end
63
64function node.kerning(...)
65 if basemodepass and k_warning then
66 k_warning()
67 end
68 return n_kerning(...)
69end
70
71function nuts.ligaturing(...)
72 if basemodepass and l_warning then
73 l_warning()
74 end
75 return d_ligaturing(...)
76end
77
78function nuts.kerning(...)
79 if basemodepass and k_warning then
80 k_warning()
81 end
82 return d_kerning(...)
83end
84
85
86
87
88function nodes.handlers.setbasemodepass(v)
89 basemodepass = v
90end
91
92local function nodepass(head,groupcode,size,packtype,direction)
93 local fontdata = fonts.hashes.identifiers
94 if fontdata then
95 local usedfonts = { }
96 local basefonts = { }
97 local prevfont = nil
98 local basefont = nil
99 local variants = nil
100 local redundant = nil
101 local nofused = 0
102 for n in traverseid(glyph_code,head) do
103 local font = getfont(n)
104 if font ~= prevfont then
105 if basefont then
106 basefont[2] = getprev(n)
107 end
108 prevfont = font
109 local used = usedfonts[font]
110 if not used then
111 local tfmdata = fontdata[font]
112 if tfmdata then
113 local shared = tfmdata.shared
114 if shared then
115 local processors = shared.processes
116 if processors and #processors > 0 then
117 usedfonts[font] = processors
118 nofused = nofused + 1
119 elseif basemodepass then
120 basefont = { n, nil }
121 basefonts[#basefonts+1] = basefont
122 end
123 end
124 local resources = tfmdata.resources
125 variants = resources and resources.variants
126 variants = variants and next(variants) and variants or false
127 end
128 else
129 local tfmdata = fontdata[prevfont]
130 if tfmdata then
131 local resources = tfmdata.resources
132 variants = resources and resources.variants
133 variants = variants and next(variants) and variants or false
134 end
135 end
136 end
137 if variants then
138 local char = getchar(n)
139 if (char >= 0xFE00 and char <= 0xFE0F) or (char >= 0xE0100 and char <= 0xE01EF) then
140 local hash = variants[char]
141 if hash then
142 local p = getprev(n)
143 if p and getid(p) == glyph_code then
144 local variant = hash[getchar(p)]
145 if variant then
146 setchar(p,variant)
147 end
148 end
149 end
150
151 if not redundant then
152 redundant = { n }
153 else
154 redundant[#redundant+1] = n
155 end
156 end
157 end
158 end
159 local nofbasefonts = #basefonts
160 if redundant then
161 for i=1,#redundant do
162 local r = redundant[i]
163 local p, n = getboth(r)
164 if r == head then
165 head = n
166 setprev(n)
167 else
168 setlink(p,n)
169 end
170 if nofbasefonts > 0 then
171 for i=1,nofbasefonts do
172 local bi = basefonts[i]
173 if r == bi[1] then
174 bi[1] = n
175 end
176 if r == bi[2] then
177 bi[2] = n
178 end
179 end
180 end
181 flushnode(r)
182 end
183 end
184 for d in traverseid(disc_code,head) do
185 local _, _, r = getdisc(d)
186 if r then
187 for n in traverseid(glyph_code,r) do
188 local font = getfont(n)
189 if font ~= prevfont then
190 prevfont = font
191 local used = usedfonts[font]
192 if not used then
193 local tfmdata = fontdata[font]
194 if tfmdata then
195 local shared = tfmdata.shared
196 if shared then
197 local processors = shared.processes
198 if processors and #processors > 0 then
199 usedfonts[font] = processors
200 nofused = nofused + 1
201 end
202 end
203 end
204 end
205 end
206 end
207 end
208 end
209 if next(usedfonts) then
210 for font, processors in next, usedfonts do
211 for i=1,#processors do
212 head = processors[i](head,font,0,direction,nofused) or head
213 end
214 end
215 end
216 if basemodepass and nofbasefonts > 0 then
217 for i=1,nofbasefonts do
218 local range = basefonts[i]
219 local start = range[1]
220 local stop = range[2]
221 if start then
222 local front = head == start
223 local prev, next
224 if stop then
225 next = getnext(stop)
226 start, stop = d_ligaturing(start,stop)
227 start, stop = d_kerning(start,stop)
228 else
229 prev = getprev(start)
230 start = d_ligaturing(start)
231 start = d_kerning(start)
232 end
233 if prev then
234 setlink(prev,start)
235 end
236 if next then
237 setlink(stop,next)
238 end
239 if front and head ~= start then
240 head = start
241 end
242 end
243 end
244 end
245 end
246 return head
247end
248
249local function basepass(head)
250 if basemodepass then
251 head = d_ligaturing(head)
252 head = d_kerning(head)
253 end
254 return head
255end
256
257local protectpass = node.direct.protectglyphs or node.direct.protect_glyphs
258local injectpass = nodes.injections.handler
259
260
261
262
263function nodes.handlers.nodepass(head,...)
264 if head then
265 return tonode(nodepass(tonut(head),...))
266 end
267end
268
269function nodes.handlers.basepass(head)
270 if head then
271 return tonode(basepass(tonut(head)))
272 end
273end
274
275function nodes.handlers.injectpass(head)
276 if head then
277 return tonode(injectpass(tonut(head)))
278 end
279end
280
281function nodes.handlers.protectpass(head)
282 if head then
283 protectpass(tonut(head))
284 return head
285 end
286end
287
288function nodes.simple_font_handler(head,groupcode,size,packtype,direction)
289 if head then
290 head = tonut(head)
291 head = nodepass(head,groupcode,size,packtype,direction)
292 head = injectpass(head)
293 if not basemodepass then
294 head = basepass(head)
295 end
296 protectpass(head)
297 head = tonode(head)
298 end
299 return head
300end
301 |