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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
|
if not modules then modules = { } end modules ['typo-drp'] = {
version = 1.001,
comment = "companion to typo-drp.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
}
-- This ons is sensitive for order (e.g. when combined with first line
-- processing.
local tonumber, type, next = tonumber, type, next
local ceil = math.ceil
local utfbyte = utf.byte
local utfchar = utf.char
local trace_initials = false trackers.register("typesetters.initials", function(v) trace_initials = v end)
local report_initials = logs.reporter("nodes","initials")
local initials = typesetters.paragraphs or { }
typesetters.initials = initials or { }
local nodes = nodes
local tasks = nodes.tasks
local nuts = nodes.nuts
local tonut = nuts.tonut
local tonode = nuts.tonode
local getnext = nuts.getnext
local getprev = nuts.getprev
local getchar = nuts.getchar
local getid = nuts.getid
local getsubtype = nuts.getsubtype
local getfield = nuts.getfield
local getattr = nuts.getattr
local setfield = nuts.setfield
local setattr = nuts.setattr
local hpack_nodes = nuts.hpack
local nodecodes = nodes.nodecodes
local whatsitcodes = nodes.whatsitcodes
local nodepool = nuts.pool
local new_kern = nodepool.kern
local insert_before = nuts.insert_before
local insert_after = nuts.insert_after
local variables = interfaces.variables
local v_default = variables.default
local v_margin = variables.margin
local texget = tex.get
local texsetattribute = tex.setattribute
local unsetvalue = attributes.unsetvalue
local glyph_code = nodecodes.glyph
local hlist_code = nodecodes.hlist
local kern_node = nodecodes.kern
local whatsit_code = nodecodes.whatsit
local localpar_code = whatsitcodes.localpar
local actions = { }
initials.actions = actions
local a_initial = attributes.private("initial")
local a_color = attributes.private('color')
local a_transparency = attributes.private('transparency')
local a_colorspace = attributes.private('colormodel')
local settings = nil
function initials.set(specification)
settings = specification or { }
settings.enabled = true
tasks.enableaction("processors","typesetters.initials.handler")
if trace_initials then
report_initials("enabling initials")
end
texsetattribute(a_initial,1)
end
commands.setinitial = initials.set
-- dropped caps experiment (will be done properly when luatex
-- stores the state in the local par node) .. btw, search still
-- works with dropped caps, as does an export
-- we need a 'par' attribute and in fact for dropped caps we don't need
-- need an attribute ... dropit will become s state counter (or end up
-- in the localpar user data
-- for the moment, each paragraph gets a number as id (attribute) ..problem
-- with nesting .. or anyhow, needed for tagging anyway
-- todo: prevent linebreak .. but normally a initial ends up at the top of
-- a page so this has a low priority
actions[v_default] = function(head,setting)
local done = false
if getid(head) == whatsit_code and getsubtype(head) == localpar_code then
-- begin of par
local first = getnext(head)
-- parbox .. needs to be set at 0
if first and getid(first) == hlist_code then
first = getnext(first)
end
-- we need to skip over kerns and glues (signals)
while first and getid(first) ~= glyph_code do
first = getnext(first)
end
if first and getid(first) == glyph_code then
local char = getchar(first)
local prev = getprev(first)
local next = getnext(first)
-- if getid(prev) == hlist_code then
-- -- set the width to 0
-- end
if next and getid(next) == kern_node then
setfield(next,"kern",0)
end
if setting.font then
setfield(first,"font",setting.font)
end
if setting.dynamic > 0 then
setattr(first,0,setting.dynamic)
end
-- can be a helper
local ma = setting.ma or 0
local ca = setting.ca
local ta = setting.ta
if ca and ca > 0 then
setattr(first,a_colorspace,ma == 0 and 1 or ma)
setattr(first,a_color,ca)
end
if ta and ta > 0 then
setattr(first,a_transparency,ta)
end
--
local width = getfield(first,"width")
local height = getfield(first,"height")
local depth = getfield(first,"depth")
local distance = setting.distance or 0
local voffset = setting.voffset or 0
local hoffset = setting.hoffset or 0
local parindent = tex.parindent
local baseline = texget("baselineskip").width
local lines = tonumber(setting.n) or 0
--
setfield(first,"xoffset",- width - hoffset - distance - parindent)
setfield(first,"yoffset",- voffset) -- no longer - height here
-- We pack so that successive handling cannot touch the dropped cap. Packaging
-- in a hlist is also needed because we cannot locally adapt e.g. parindent (not
-- yet stored in with localpar).
setfield(first,"prev",nil)
setfield(first,"next",nil)
local h = hpack_nodes(first)
setfield(h,"width",0)
setfield(h,"height",0)
setfield(h,"depth",0)
setfield(prev,"next",h)
setfield(next,"prev",h)
setfield(h,"next",next)
setfield(h,"prev",prev)
first = h
-- end of packaging
if setting.location == v_margin then
-- okay
else
if lines == 0 then -- safeguard, not too precise
lines = ceil((height+voffset) / baseline)
end
-- We cannot set parshape yet ... when we can I'll add a slope
-- option (positive and negative, in emwidth).
local hangafter = - lines
local hangindent = width + distance + parindent
if trace_initials then
report_initials("setting hangafter to %i and hangindent to %p",hangafter,hangindent)
end
tex.hangafter = hangafter
tex.hangindent = hangindent
if parindent ~= 0 then
insert_after(first,first,new_kern(-parindent))
end
end
done = true
end
end
return head, done
end
function initials.handler(head)
head = tonut(head)
local start = head
local attr = nil
while start do
attr = getattr(start,a_initial)
if attr then
break
elseif getid(start) == glyph then
break
else
start = getnext(start)
end
end
if attr then
-- here as we can process nested boxes first so we need to keep state
tasks.disableaction("processors","typesetters.initials.handler")
-- texsetattribute(attribute,unsetvalue)
local alternative = settings.alternative or v_default
local action = actions[alternative] or actions[v_default]
if action then
if trace_initials then
report_initials("processing initials, alternative %a",alternative)
end
local head, done = action(head,settings)
return tonode(head), done
end
end
return tonode(head), false
end
|