1if not modules then modules = { } end modules ['typo-pnc'] = {
2 version = 1.001,
3 comment = "companion to typo-pnc.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
9local nodes = nodes
10local fonts = fonts
11
12local enableaction = nodes.tasks.enableaction
13
14local nuts = nodes.nuts
15local tonut = nodes.tonut
16
17local nodecodes = nodes.nodecodes
18local gluecodes = nodes.gluecodes
19local glyph_code = nodecodes.glyph
20local glue_code = nodecodes.glue
21local spaceskip_code = gluecodes.spaceskip
22
23local new_kern = nuts.pool.kern
24local insertafter = nuts.insertafter
25
26local nextglyph = nuts.traversers.glyph
27
28local getchar = nuts.getchar
29local getfont = nuts.getfont
30local getboth = nuts.getboth
31local getnext = nuts.getnext
32local getattr = nuts.getattr
33local getid = nuts.getid
34local getsubtype = nuts.getsubtype
35local getwidth = nuts.getwidth
36local setwidth = nuts.setwidth
37local findattribute = nuts.findattribute
38
39local glyph_code = nodes.nodecodes.glyph
40
41local parameters = fonts.hashes.parameters
42local categories = characters.categories
43
44local texsetattribute = tex.setattribute
45local unsetvalue = attributes.unsetvalue
46
47local period = 0x2E
48local factor = 0.5
49
50
51
52typesetters = typesetters or { }
53local typesetters = typesetters
54
55local periodkerns = typesetters.periodkerns or { }
56typesetters.periodkerns = periodkerns
57
58local report = logs.reporter("period kerns")
59local trace = false
60
61trackers.register("typesetters.periodkerns",function(v) trace = v end)
62
63periodkerns.mapping = periodkerns.mapping or { }
64periodkerns.factors = periodkerns.factors or { }
65local a_periodkern = attributes.private("periodkern")
66
67storage.register("typesetters/periodkerns/mapping", periodkerns.mapping, "typesetters.periodkerns.mapping")
68storage.register("typesetters/periodkerns/factors", periodkerns.factors, "typesetters.periodkerns.factors")
69
70local mapping = periodkerns.mapping
71local factors = periodkerns.factors
72
73function periodkerns.handler(head)
74 local _, start = findattribute(head,a_periodkern,glyph_code)
75 if start then
76 for current, char, font in nextglyph, start do
77 if char == period then
78 local a = getattr(current,a_periodkern)
79 if a then
80 local factor = mapping[a]
81 if factor then
82 local prev, next = getboth(current)
83 if prev and next and getid(prev) == glyph_code and getid(next) == glyph_code then
84 local pchar = getchar(prev)
85 local pcode = categories[pchar]
86 if pcode == "lu" or pcode == "ll" then
87 local nchar = getchar(next)
88 local ncode = categories[nchar]
89 if ncode == "lu" or ncode == "ll" then
90 local next2 = getnext(next)
91 if next2 and getid(next2) == glyph_code and getchar(next2) == period then
92
93 local fontspace, inserted
94 if factor ~= 0 then
95 fontspace = parameters[getfont(current)].space
96 inserted = factor * fontspace
97 insertafter(head,current,new_kern(inserted))
98 if trace then
99 report("inserting space at %C . [%p] %C .",pchar,inserted,nchar)
100 end
101 end
102 local next3 = getnext(next2)
103 if next3 and getid(next3) == glue_code and getsubtype(next3) == spaceskip_code then
104 local width = getwidth(next3)
105 local space = fontspace or parameters[getfont(current)].space
106 if width > space then
107 local next4 = getnext(next3)
108 if next4 and getid(next4) == glyph_code then
109 local fchar = getchar(next4)
110 if categories[fchar] ~= "lu" then
111
112 if trace then
113 if inserted then
114 report("reverting space at %C . [%p] %C . [%p->%p] %C",pchar,inserted,nchar,width,space,fchar)
115 else
116 report("reverting space at %C . %C . [%p->%p] %C",pchar,nchar,width,space,fchar)
117 end
118 end
119 setwidth(next3,space)
120 else
121 if trace then
122 if inserted then
123 report("keeping space at %C . [%p] %C . [%p] %C",pchar,inserted,nchar,width,fchar)
124 else
125 report("keeping space at %C . %C . [%p] %C",pchar,nchar,width,fchar)
126 end
127 end
128 end
129 end
130 end
131 end
132 end
133 end
134 end
135 end
136 end
137 end
138 end
139 end
140 end
141 return head
142end
143
144local enabled = false
145
146function periodkerns.set(factor)
147 factor = tonumber(factor) or 0
148 if not enabled then
149 enableaction("processors","typesetters.periodkerns.handler")
150 enabled = true
151 end
152 local a = factors[factor]
153 if not a then
154 a = #mapping + 1
155 factors[factors], mapping[a] = a, factor
156 end
157 factor = a
158 texsetattribute(a_periodkern,factor)
159 return factor
160end
161
162
163
164interfaces.implement {
165 name = "setperiodkerning",
166 actions = periodkerns.set,
167 arguments = "string"
168}
169
170
171 |