meta-imp-txt.mkiv /size: 12 Kb    last modification: 2020-07-01 14:35
1
%D \module
2
%D [ file=meta-txt,
3
%D version=2000.07.06,
4
%D title=\METAPOST\ Graphics,
5
%D subtitle=Text Tricks,
6
%D author=Hans Hagen,
7
%D date=\currentdate,
8
%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9
%C
10
%C This module is part of the \CONTEXT\ macro||package and is
11
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
12
%C details.
13 14
%D In this library some handy text manipulations are defined. Some can and will be
15
%D improved as soon as the \TEX||\METAPOST\ interface is stable. Some of the
16
%D solutions may look weird, which is entirely my fault, since I implemented them in
17
%D the process of getting grip on this kind of manipulations. Undoubtly better
18
%D \METAPOST\ code is possible, but my way of learning this kind of trickery happens
19
%D to be by \quote {trial and error} and \quote {look and feel} (as well as
20
%D identifying tricks in Hobby's code).
21 22
% textext ipv btex ... etex
23 24
% we need a proper prefix here
25 26
\unprotect
27 28
\definesystemvariable
{
sh
}
% ShapedText .. todo: commandhandler
29 30
\unexpanded
\def
\setupshapetexts
31
{
\dodoubleempty\getparameters
[
\??sh
]
}
32 33
\setupshapetexts
34
[
\c!bodyfont
=]
35 36
\startMPextensions
37
loadmodule
"
text
"
;
38
\stopMPextensions
39 40
\ifdefined
\parwidth
\else
41
\newdimen
\parwidth
42
\newdimen
\parheight
43
\newdimen
\parvoffset
44
\newdimen
\parhoffset
45
\newcount
\parlines
46
\newtoks
\partoks
47
\newbox
\shapetextbox
48
\newcount
\parfirst
49
\fi
50 51
\unexpanded
\def
\startshapetext
[#
1
]
%
52
{
\global
\newcounter
\currentshapetext
53
\global\setbox
\shapetextbox
\vbox
\bgroup
54
\switchtobodyfont
[
\@@shbodyfont
]
%
55
\dontcomplain
56
\hsize
\parwidth
57
\setuptolerance
[
\v!verytolerant
,
\v!stretch
]
%
58
\scratchcounter
\zerocount
59
\scratchtoks
\emptytoks
60
\def
\docommand
##
1
%
61
{
\setbox
\scratchbox
\hpack
{
\useMPgraphic
{
##1
}
}
%
62
\global
\parfirst
\zerocount
63
\getMPdata
64
\setshapecharacteristics
65
\advance
\scratchcounter
by
\parlines
66
\expandafter
\appendtoks
\the
\partoks
\to\scratchtoks
}
%
67
\processcommalist
[#
1
]
\docommand
68
\xdef
\totalparlines
{
\the
\scratchcounter
}
%
69
\global
\partoks
\scratchtoks
70
\parshape
\the
\scratchcounter
\the
\scratchtoks
\relax
71
\setshapecharacteristics
% extra dummy
72
\def\par
{
\endgraf
\adaptparshape
}
%
73
\everypar
{
\begstrut
}}
74 75
\unexpanded
\def
\stopshapetext
76
{
\endstrut
77
\egroup
78
\global
\newcounter
\currentshapetext
79
\getshapecharacteristics
}
80 81
\unexpanded
\def
\adaptparshape
82
{
\def
\docommand
##
1
%
83
{
\ifcase
\scratchcounter
84
\expandafter
\appendtoks\space
##
1
\to\scratchtoks
85
\else
86
\advance
\scratchcounter
\minusone
87
\fi
}
%
88
\scratchcounter
\prevgraf
89
\doglobal
\decrement
(
\totalparlines
,
\scratchcounter
)
%
90
\multiply
\scratchcounter
\plustwo
91
\scratchtoks
\emptytoks
92
\expanded
{
\processseparatedlist
[
\the
\partoks
][
\space
]
}
\docommand
93
\global
\partoks
\scratchtoks
94
\parshape
\totalparlines
\the
\partoks
\relax
}
95 96
\unexpanded
\def
\getshapecharacteristics
97
{
\doglobal
\increment
\currentshapetext
98
\doifelsedefined
{
parlines
:
\currentshapetext
}
99
{
\getvalue
{
parlines
:
\currentshapetext
}}
100
{
\global
\parlines
\plusone
101
\global
\parfirst
\zerocount
102
\global
\parvoffset
\zeropoint
103
\global
\parhoffset
\zeropoint
104
\global
\parwidth
\hsize
105
\global
\parheight
\vsize
}}
106 107
\unexpanded
\def
\setshapecharacteristics
108
{
\doglobal
\increment
\currentshapetext
109
\setxvalue
{
parlines
:
\currentshapetext
}
%
110
{
\global
\parlines
\the
\parlines
111
\global
\parfirst
\the
\parfirst
112
\global
\parvoffset
\the
\parvoffset
113
\global
\parhoffset
\the
\parhoffset
114
\global
\parwidth
\the
\parwidth
115
\global
\parheight
\the
\parheight
}}
116 117
\unexpanded
\def
\getshapetext
% option: unvbox
118
{
\vbox
\bgroup
119
\forgetall
120
\dontcomplain
121
\setbox
\scratchbox
\vbox
to
\parheight
122
{
\switchtobodyfont
[
\@@shbodyfont
]
%
123
\splittopskip
\strutheight
124
\vskip
\parvoffset
125
\ifcase
\parfirst
\else\vskip
\lineheight
\fi
126
\hskip
\parhoffset
127
\hbox
{
\vsplit
\shapetextbox
to
\parlines
\lineheight
}}
%
128
\wd
\scratchbox
\parwidth
129
\ht
\scratchbox
\parheight
130
\dp
\scratchbox
\zeropoint
131
\box
\scratchbox
132
\getshapecharacteristics
133
\egroup
}
134 135
\doifundefined
{
RotFont
}{
\definefont
[
RotFont
][
RegularBold
*
default
]
}
136 137
\unexpanded
\def
\getfollowtoken
#
1
%
138
{
\hbox
\bgroup
139
\strut
140
\ctxlua{
mp
.
follow_text
(
#
1
)
}
%
141
\egroup
}
142 143
\definefontfeature
[
mp
:
tp
][
liga
=
no
]
144 145
\startMPdefinitions
146
def
mfun_follow_draw
(
expr
alternative
)
=
147
if
unknown
RotPath
:
path
RotPath
;
RotPath
:
=
origin
;
fi
;
148
% if unknown RotColor : color RotColor ; RotColor := black ; fi ;
149
if
unknown
TraceRot
:
boolean
TraceRot
;
TraceRot
:
=
false
;
fi
;
150
if
unknown
ExtraRot
:
numeric
ExtraRot
;
ExtraRot
:
=
0
;
fi
;
151
picture
pic
[
]
;
152
numeric
len
[
]
;
len
[
0
]
:
=
0
;
153
numeric
n
;
n
:
=
lua.mp.follow_size
(
)
;
154
for
i
=
1
upto
n
:
155
pic
[
i
]
:
=
lua.mp.follow_slot
(
i
)
;
156
pic
[
i
]
:
=
pic
[
i
]
shifted
-
llcorner
pic
[
i
]
;
157
len
[
i
]
:
=
len
[
i
-1
]
+
lua.mp.follow_width
(
i
)
;
158
endfor
;
159
numeric
al
,
at
,
pl
,
pc
,
wid
,
pos
;
pair
ap
,
ad
;
160
al
:
=
arclength
RotPath
;
161
if
al
=
0
:
162
al
:
=
len
[
n
]
+
ExtraRot
;
163
RotPath
:
=
origin
--
(
al
,
0
)
;
164
fi
;
165
if
al
<
len
[
n
]
:
166
RotPath
:
=
RotPath
scaled
(
(
len
[
n
]
+
ExtraRot
)
/
al
)
;
167
al
:
=
arclength
RotPath
;
168
fi
;
169
if
alternative
=
1
:
170
pl
:
=
(
al
-
len
[
n
]
)
/
(
if
n
>
1
:
(
n
-1
)
else
:
1
fi
)
;
171
pc
:
=
0
;
172
else
:
% centered / MP
173
pl
:
=
0
;
174
pc
:
=
arclength
RotPath
/
2
-
len
[
n
]
/
2
;
175
fi
;
176
if
TraceRot
:
177
draw
RotPath
withpen
pencircle
scaled
1
pt
withcolor
blue
;
178
fi
;
179
for
i
=
1
upto
n
:
180
% wid := abs(xpart urcorner pic[i] - xpart llcorner pic[i]) ;
181
wid
:
=
lua.mp.follow_width
(
i
)
;
182
pos
:
=
len
[
i
]
-
wid
/
2
+
(
i
-1
)
*
pl
+
pc
;
183
at
:
=
arctime
pos
of
RotPath
;
184
ap
:
=
point
at
of
RotPath
;
185
ad
:
=
direction
at
of
RotPath
;
186
if
mfun_trial_run
:
187
% skip (ok, somewhat inefficient as we can consider a
188
% dedicated store and textext variant (todo)
189
else
:
190
pic
[
i
]
:
=
pic
[
i
]
shifted
(
-
wid
/
2
,
0
)
rotated
(
angle
(
ad
)
)
shifted
ap
;
191
draw
pic
[
i
]
;
% withcolor RotColor ;
192
if
TraceRot
:
193
draw
boundingbox
pic
[
i
]
withpen
pencircle
scaled
.25
pt
withcolor
red
;
194
draw
ap
withpen
pencircle
scaled
.50
pt
withcolor
green
;
195
fi
;
196
fi
;
197
endfor
;
198
if
TraceRot
:
199
draw
boundingbox
currentpicture
withpen
pencircle
scaled
.25
pt
withcolor
blue
;
200
fi
;
201
enddef
;
202
\stopMPdefinitions
203 204
\startluacode
205
local
context
=
context
206 207
local
nodecodes
=
nodes
.
nodecodes
208
local
kerncodes
=
nodes
.
kerncodes
209 210
local
visible_code
=
{
211
[
nodecodes
.
glyph
]
=
true
,
212
[
nodecodes
.
glue
]
=
true
,
213
[
nodecodes
.
hlist
]
=
true
,
214
[
nodecodes
.
vlist
]
=
true
,
215
[
nodecodes
.
rule
]
=
true
,
216
}
217 218
local
kern_code
=
nodecodes
.
kern
219
local
c_userkern
=
kerncodes
.
userkern
220
local
a_fontkern
=
attributes
.
private
(
"
fontkern
"
)
221 222
local
copynode
=
nodes
.
copy
223
local
freenode
=
nodes
.
free
224 225
local
topoints
=
number
.
topoints
226
local
mpprint
=
mp
.
print
227 228
local
n
=
nil
229
local
s
=
0
230 231
function
mp
.
follow_reset
(
)
232
for
i
=
1
,
#
n
do
233
freenode
(
n
[
i
]
)
234
end
235
n
=
nil
236
s
=
0
237
end
238 239
function
mp
.
follow_initialize
(
b
)
240
if
not
n
then
241
local
head
=
tex
.
takebox
(
b
)
.
list
242
if
head
then
243
n
=
{
}
244
s
=
0
245
head
=
node
.
flatten_discretionaries
(
head
)
246
local
current
=
head
247
while
current
do
248
local
id
=
current
.
id
249
if
visible_code
[
id
]
then
250
s
=
s
+
1
251
head
,
current
,
n
[
s
]
=
nodes
.
remove
(
head
,
current
)
252
elseif
id
=
=
kern_code
and
current
.
subtype
=
=
c_userkern
and
not
current
[
a_fontkern
]
then
253
s
=
s
+
1
254
head
,
current
,
n
[
s
]
=
nodes
.
remove
(
head
,
current
)
255
else
256
current
=
current
.
next
257
end
258
end
259
nodes
.
flush_list
(
head
)
260
end
261
end
262
end
263 264
function
mp
.
follow_size
(
)
265
mpprint
(
s
)
266
end
267 268
function
mp
.
follow_slot
(
i
)
269
mpprint
(
'
textext("\\getfollowtoken{
'
.
.
i
.
.
'
}")
'
)
270
end
271 272
function
mp
.
follow_text
(
s
)
273
context
(
copynode
(
n
[
s
]
)
)
274
end
275 276
function
mp
.
follow_width
(
i
)
277
mpprint
(
topoints
(
n
[
i
]
.
width
)
)
278
end
279
\stopluacode
280 281
\unexpanded
\def
\dofollowtokens
#
1
#
2
%
282
{
\vbox
\bgroup
283
\forgetall
284
\dontcomplain
285
\setbox
\scratchbox
\hbox
{
\addff
{
mp
:
tp
}
#
2
}
%
286
\ctxlua{
mp
.
follow_initialize
(
\number
\scratchbox
)
}
%
287
\startMPcode
288
\includeMPgraphic
{
followtokens
}
;
289
mfun_follow_draw
(
\number
#
1
)
;
290
\stopMPcode
291
\ctxlua{
mp
.
follow_reset
(
)
}
%
292
\egroup
}
293 294
\unexpanded
\def
\followtokens
{
\dofollowtokens
\plusone
}
295
\unexpanded
\def
\followtokenscentered
{
\dofollowtokens
\zerocount
}
296 297
% stretched variant:
298
%
299
% \followtokens
300
% {This is just a dummy text, kerned by T{\kern
301
% -.1667em\lower .5ex\hbox {E}}{\kern -.125emX} and typeset
302
% in a circle using {\setMFPfont M}{\setMFPfont
303
% E}{\setMFPfont T}{\setMFPfont A}{\setMFPfont
304
% P}{\setMFPfont O}{\setMFPfont S}{\setMFPfont T}.\quad}
305 306
% centered variant:
307
%
308
% \def\followtokengraphicscale#1{%%
309
% \startuseMPgraphic {followtokens}
310
% path RotPath; RotPath := reverse halfcircle scaled #1 ;
311
% draw RotPath ;
312
% setbounds currentpicture to boundingbox fullcircle scaled 12cm ;
313
% \stopuseMPgraphic}
314
%
315
% \startoverlay
316
% {\followtokengraphicscale{12cm}%%
317
% \followtokenscentered{There was question on the list about this kind of graphics.}}
318
% {\followtokengraphicscale{10cm}%%
319
% \followtokenscentered{And Marco patched followingtokens to handle a centered text.}}
320
% {\followtokengraphicscale{8cm}%%
321
% \followtokenscentered{That ended up as variant branch in the main macro.}}
322
% {\followtokengraphicscale{6cm}%%
323
% \followtokenscentered{So now we have two commands.}}
324
% \stopoverlay
325 326
% \followtokengraphicscale{6cm}
327
% \followtokens{Hans Hagen uses {\darkred\TeX}, {\darkgreen\Lua}, {\darkblue \MetaPost} and friends.}
328 329
\startuseMPgraphic
{
fuzzycount
}
330
begingroup
331
save
height
,
span
,
drift
,
d
,
cp
;
332
height
:
=
3
/
5
*
\baselinedistance
;
333
span
:
=
1
/
3
*
height
;
334
drift
:
=
1
/
10
*
height
;
335
pickup
pencircle
scaled
(
1
/
12
*
height
)
;
336
def
d
=
(
uniformdeviate
drift
)
enddef
;
337
for
i
:
=
1
upto
\MPvar
{
n
}
:
338
draw
339
if
(
i
mod
5
)
=
0
:
(
(
-
d
-4.5
span
,
d
)
--
(
+
d
-0.5
span
,
height
-
d
)
)
340
else
:
(
(
-
d
,
+
d
)
--
(
+
d
,
height
-
d
)
)
fi
341
shifted
(
span
*
i
,
d
-
drift
)
;
342
endfor
;
343
picture
cp
;
cp
:
=
currentpicture
;
% for readability
344
setbounds
currentpicture
to
345
(
llcorner
cp
shifted
(
0
,
-
ypart
llcorner
cp
)
--
346
lrcorner
cp
shifted
(
0
,
-
ypart
lrcorner
cp
)
--
347
urcorner
cp
--
ulcorner
cp
--
cycle
)
;
348
endgroup
;
349
\stopuseMPgraphic
350 351
\setupMPvariables
352
[
fuzzycount
]
353
[
n
=
1
0
]
354 355
\unexpanded
\def
\fuzzycount
#
1
%
356
{{
\tx\useMPgraphic
{
fuzzycount
}{
n
=#
1
}}}
357 358
\defineconversion
[
fuzzy
][
\fuzzycount
]
359 360
%%%%%%%
361 362
\setupMPvariables
363
[
EnglishRule
]
364
[
height
=
1
ex
,
365
width
=
\the
\localhsize
,
% without \the, problems in non e-tex
366
color
=
darkgray
]
367 368
\defineblank
369
[
EnglishRule
]
370
[
medium
]
371 372
\startuniqueMPgraphic
{
EnglishRule
}
{
height,width,color
}
373
x
1
=
0
;
x
3
=
\MPvar
{
width
}
;
x
2
=
x
4
=
.5
x
3
;
374
y
1
=
y
3
=
0
;
y
2
=
-
y
4
=
\MPvar
{
height
}
/
2
;
375
fill
z
1.
.
z
2.
.
z
3
&
z
3.
.
z
4.
.
z
1
&
cycle
withcolor
\MPvar
{
color
}
;
376
\stopuniqueMPgraphic
377 378
\unexpanded
\def
\EnglishRule
379
{
\startlinecorrection
[
EnglishRule
]
380
\setlocalhsize
\noindent
\reuseMPgraphic
{
EnglishRule
}
381
\stoplinecorrection
}
382 383
%D The following macro returns a tight bound character sequence.
384
%D
385
%D \useMPlibrary[txt]
386
%D
387
%D \startlinecorrection
388
%D \TightText{\ss\bf 123}{0cm}{3cm}{red}
389
%D \stoplinecorrection
390 391
\unexpanded
\def
\TightText
#
1
#
2
#
3
#
4
%
392
{
\hpack
393
{
\startMPcode
394
picture
p
;
p
:
=
image
(
graphictext
"
#1
"
withfillcolor
red
)
;
395
draw
p
xsized
#
2
ysized
#
3
withcolor
\MPcolor
{
#4
}
;
396
\stopMPcode
}}
397 398
\protect
\endinput
399