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
|
if not modules then modules = { } end modules ['typo-par'] = {
version = 1.001,
comment = "companion to typo-par.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
}
-- A playground for experiments.
local utfbyte = utf.byte
local utfchar = utf.char
local trace_paragraphs = false trackers.register("typesetters.paragraphs", function(v) trace_paragraphs = v end)
local trace_dropper = false trackers.register("typesetters.paragraphs.dropper",function(v) trace_dropper = v end)
local report_paragraphs = logs.reporter("nodes","paragraphs")
local report_dropper = logs.reporter("nodes","dropped")
typesetters.paragraphs = typesetters.paragraphs or { }
local paragraphs = typesetters.paragraphs
local nodecodes = nodes.nodecodes
local whatsitcodes = nodes.whatsitcodes
local tasks = nodes.tasks
local variables = interfaces.variables
local texattribute = tex.attribute
local unsetvalue = attributes.unsetvalue
local has_attribute = node.has_attribute
local set_attribute = node.set_attribute
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 a_paragraph = attributes.private("paragraphspecial")
local a_color = attributes.private('color')
local a_transparency = attributes.private('transparency')
local a_colorspace = attributes.private('colormodel')
local dropper = {
enabled = false,
-- font = 0,
-- n = 0,
-- distance = 0,
-- hoffset = 0,
-- voffset = 0,
}
local droppers = { }
typesetters.paragraphs.droppers = droppers
function droppers.set(specification)
dropper = specification or { }
end
function droppers.freeze()
if dropper.enabled then
dropper.font = font.current()
end
end
-- 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 dropper ends up atthe top of
-- a page so this has a low priority
local function process(namespace,attribute,head)
local done = false
if head.id == whatsit_code and head.subtype == localpar_code then
-- begin of par
local a = has_attribute(head,attribute)
if a and a > 0 then
if dropper.enabled then
dropper.enabled = false -- dangerous for e.g. nested || in tufte
local first = head.next
if first and first.id == hlist_code then
-- parbox .. needs to be set at 0
first = first.next
end
if first and first.id == glyph_code then
-- if texattribute[a_paragraph] >= 0 then
-- texattribute[a_paragraph] = unsetvalue
-- end
local char = first.char
local prev = first.prev
local next = first.next
-- if prev.id == hlist_code then
-- -- set the width to 0
-- end
if next and next.id == kern_node then
next.kern = 0
end
first.font = dropper.font or first.font
-- can be a helper
local ma = dropper.ma or 0
local ca = dropper.ca
local ta = dropper.ta
if ca and ca > 0 then
set_attribute(first,a_colorspace,ma == 0 and 1 or ma)
set_attribute(first,a_color,ca)
end
if ta and ta > 0 then
set_attribute(first,a_transparency,ta)
end
--
local width = first.width
local height = first.height
local depth = first.depth
local distance = dropper.distance or 0
local voffset = dropper.voffset or 0
local hoffset = dropper.hoffset or 0
first.xoffset = - width - hoffset - distance
first.yoffset = - height - voffset
if true then
-- needed till we can store parindent with localpar
first.prev = nil
first.next = nil
local h = node.hpack(first)
h.width = 0
h.height = 0
h.depth = 0
prev.next = h
next.prev = h
h.next = next
h.prev = prev
end
if dropper.location == variables.margin then
-- okay
else
local lines = tonumber(dropper.n) or 0
if lines == 0 then -- safeguard, not too precise
lines = math.ceil((height+voffset) / tex.baselineskip.width)
end
tex.hangafter = - lines
tex.hangindent = width + distance
end
done = true
end
end
end
end
return head, done
end
local enabled = false
function paragraphs.set(n)
if n == variables.reset or not tonumber(n) or n == 0 then
texattribute[a_paragraph] = unsetvalue
else
if not enabled then
tasks.enableaction("processors","typesetters.paragraphs.handler")
if trace_paragraphs then
report_paragraphs("enabling paragraphs")
end
enabled = true
end
texattribute[a_paragraph] = n
end
end
paragraphs.attribute = a_paragraph
paragraphs.handler = nodes.installattributehandler {
name = "paragraphs",
namespace = paragraphs,
processor = process,
}
|