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