summaryrefslogtreecommitdiff
path: root/tex/context/base/mkii/supp-emp.mkii
blob: ba9e09e3a4c4736a054eaca88a83afd1e90087e2 (plain)
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
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
%D \module
%D   [       file=supp-emp,
%D        version=2000.08.09,
%D          title=\CONTEXT\ Support Macros,
%D       subtitle=\EMTEX\ specials to \PDF\ conversion,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

%M \input supp-emp

%D When \THANH, the author of \PDFTEX, and I were exchanging
%D some emails on \PDFTEX\ functionality, positional
%D information popped up as potential extension. Actually, it
%D did not take that much time to cook up the basic
%D functionality and the author had implemented it before I
%D could even start to think about real advanced applications.
%D
%D I'm sure that \TEX\ programmers can spend many days on how
%D and what kind of information is needed if you want to have
%D access to positions, but since high level macros will
%D probably be used anyway, even things like multiple reference
%D points have proved to be rather unimportant at the system
%D level.
%D
%D Therefore, \PDFTEX\ provides just these three primitives:
%D
%D \starttabulate[|l|l|]
%D \NC \type {\pdfsavepos}  \NC marks the current position          \NC \NR
%D \NC \type {\pdflastxpos} \NC the last marked horizontal position \NC \NR
%D \NC \type {\pdflastypos} \NC the last marked vertical position   \NC \NR
%D \stoptabulate
%D
%D Based on these three primitives, very advanced systems can
%D be build, and for some time now, \CONTEXT\ has such a
%D system in its core. However, not everyone uses \CONTEXT, so
%D we will demonstrate position tracking in generic applications.
%D
%D Because \PDFTEX\ produces its output directly, many of those
%D nice tricks provided by back||ends by means of \type
%D {\special} fail when producing \PDF\ code directly. Take for
%D instance \EMTEX\ specials. When someone sent me a mail
%D asking if \PDFTEX\ did support those specials, the original
%D answer was \quotation {no}, but in the last few years I have learned
%D that you must never underestimate \TEX's capabilities.
%D
%D I must admit that I never use those specials myself, but
%D from the way they were used in the macros I was sent, I
%D learned that they depend on the back||end's capability to
%D access the current position. For those who know \TEX\ this
%D may be bad news, since pure \TEX\ does not provide any
%D positional information. So in order to use those specials,
%D you must be sure that they are supported by every driver you
%D use. However, the good news is that \PDFTEX\ does support
%D position tracking, so here is our generic example.
%D
%D The two \EMTEX\ specials we need to implement are packaged
%D into the macros \type {\EMmoveto} and \type {\EMlineto},
%D like:
%D
%D \starttyping
%D \def\EMmoveto{\special{em:moveto}}
%D \def\EMlineto{\special{em:lineto}}
%D \stoptyping
%D
%D They are used in macro packages to draw lines, and the
%D results are often boxes with content like the following:
%D
%D \startbuffer
%D \vbox to 2cm
%D   {\offinterlineskip \EMmoveto
%D    \hskip 7cm        \EMlineto
%D    \vskip 2cm        \EMlineto
%D    \vskip-2cm        \EMlineto}
%D \stopbuffer
%D
%D \typebuffer
%D
%D This box will contain a triangle, and when typeset, it should
%D look like:
%D
%D \startlinecorrection[blank]
%D \getbuffer
%D \stoplinecorrection

\def\EMlinewd{.4}

\ifx\dosetpositionpt\undefined % non context part

%D These two macros can be implemented as follows. When moving
%D to a position, we only have to register the new coordinates.
%D Once they are known, we use them to draw a line and
%D afterwards we save these end coordinates as starting point
%D for the next line segment. So, at each point specified by
%D \type {\EMlineto} we need to know the coordinates.

\def\EMmoveto
  {\EMgetposition\EMlastmovex\EMlastmovey}

%D The primitives \type {\pdflastxpos} and \type
%D {\pdflastypos} return a number, representing the $x$ and
%D $y$ coordinate in scaled points, \TEX's smallest unit of
%D length. We need to convert this number into base points as
%D used by \POSTSCRIPT\ and \PDF. When done, we insert some
%D literal \PDF\ code into the text using \type {\pdfliteral}.
%D Here, the \type {m} means \quote {moveto}, the \type {l}
%D means \quote {lineto} and the \type {S} operator \quote
%D {strokes} (draws) the line. The macro \type {\EMlinewd}
%D holds the linewidth in basepoints.

\def\EMlineto
  {\bgroup
   \EMgetposition\EMlastlinex\EMlastliney
   \count0=\EMlastmovex \advance\count0 -\EMlastlinex
   \count2=\EMlastmovey \advance\count2 -\EMlastliney
   \divide\count0 65536
   \divide\count2 65536
   \PDFcode{\EMlinewd\space w 0 0 m \the\count0 \space\the\count2 \space l S}%
   \global\let\EMlastmovex\EMlastlinex
   \global\let\EMlastmovey\EMlastliney
   \egroup}

%D We need a fresh start, so we first set the current position
%D to zero.

\def\resetEMspecials
  {\gdef\EMlastmovex{0}\gdef\EMlastmovey{0}}

%D Next comes the macro that keeps track of the position. The
%D current position is marked with \type {\pdfsavepos} and its
%D coordinates are written to a file whenever the page is
%D shipped out, since \type {\write} postpones its action
%D until that moment. The file has entries like:
%D
%D \starttyping
%D \EMsetpos 1 4661756 46651918
%D \EMsetpos 2 5000359 46990521
%D \EMsetpos 3 4661756 46313315
%D \EMsetpos 4 5338962 46990521
%D \EMsetpos 5 4661756 45974712
%D \stoptyping
%D
%D These lines are written with the command:
%D
%D \starttyping
%D \write\EMfile
%D   {\EMsetpos\number\EMcounter
%D    \space\number\pdflastxpos\space\number\pdflastypos}%
%D \stoptyping
%D
%D In reality the argument to \type {\write} looks slightly
%D more complicated, because we have to make sure that the
%D number of the current position is frozen and \type
%D {\EMsetpos} is not expanded. We do so by explicitly
%D expanding the number beforehand and preventing expansion of
%D \type {\EMsetpos}.

\def\EMgetposition#1#2%
  {\bgroup
   \pdfsavepos
   \global\advance\EMcounter 1
   \expandafter\write\expandafter\EMfile\expandafter
     {\expandafter\noexpand\expandafter\EMsetpos\number\EMcounter
      \space\number\pdflastxpos\space\number\pdflastypos}%
   \EMsetcounters
   \xdef#1{\the\count0}%
   \xdef#2{\the\count2}%
   \egroup}

%D The counter mentioned a few lines ago needs to be
%D declared before it can be used.

\newcount\EMcounter

%D We also need a dedicated file slot.

\newwrite\EMfile

%D Before we open the file for writing, we read in the data
%D written in the previous pass, but only if the file is
%D present.

\def\EMfilename{\jobname.emp}

\def\startEMspecials%
  {\resetEMspecials
   \openin\scratchread=\EMfilename \relax
   \ifeof\scratchread\else \input \EMfilename \relax \fi
   \closein\scratchread
   \immediate\openout\EMfile=\EMfilename\relax}

\def\stopEMspecials
  {\closeout\EMfile}

%D Just to be sure, we test if \type {\scratchread} is defined,
%D and if not, we allocate a slot.

\ifx\undefined\scratchread \newread\scratchread \fi

%D This leaves us two commands. The \type {\EMsetpos} command
%D that ends up in the file stores each position in a macro.
%D When this macro is expanded, it assigns the coordinates to
%D two scratch counters.

\def\EMsetpos#1 #2 #3 % number x y
  {\expandafter\xdef\csname EM:#1\endcsname{\count0=#2 \count2=#3}}

%D This position is recalled with its companion macro. First we
%D set the counters to zero. When the position is unknown,
%D nothing happens since the \type {\csname...} will expand to
%D \type {\relax}.

\def\EMsetcounters
  {\count0=0 \count2=0
   \csname EM:\the\EMcounter\endcsname}

%D These macros are rather independent of the macro package you
%D use. For instance, in \CONTEXT\ the following works well:
%D
%D \startbuffer[pos-en]
%D \setuppositioning[unit=ex]
%D \startpositioning
%D   \dostepwiserecurse{-10}{10}{1}
%D     {\position(0,\recurselevel){\EMmoveto}
%D      \position(\recurselevel,0){\EMlineto}}
%D \stoppositioning
%D \stopbuffer
%D
%D \startbuffer[pos-nl]
%D \setuppositioning[uniteenheid=ex]
%D \startpositioning
%D   \dostepwiserecurse{-10}{10}{1}
%D     {\position(0,\recurselevel){\EMmoveto}
%D      \position(\recurselevel,0){\EMlineto}}
%D \stoppositioning
%D \stopbuffer
%D
%D \typebuffer[pos-en]
%D
%D Here, we hook the \EMTEX\ macros into an existing text
%D positioning mechanism, which positions the commands
%D using \TEX's skips and kerns.
%D
%D \startlinecorrection[blank]
%D \getbuffer[pos-nl]
%D \stoplinecorrection
%D
%D Of course one should start and end the file with:
%D
%D \starttyping
%D \startEMspecials
%D \stopEMspecials
%D \stoptyping
%D
%D and, if needed, reset the begin position at each page using:
%D
%D \starttyping
%D \resetEMspecials
%D \stoptyping

\fi % end of non context part

\ifx\dosetpositionpt\undefined \else % context part

% \edef\EMlinewd{\withoutpt\the\linewidth}

%D A few pages ago, we mentioned that \CONTEXT\ has built||in
%D position tracking. This means that when we want to implement
%D this kind of trickery in this macro package, we can fall
%D back on existing functionality. In the following alternative
%D we will also use a few skips. This keeps the source readable
%D and \CONTEXT\ has plenty of unused registers to accomodate
%D this strategy.

\newcount\EMcounter \def\EMvariable{EM:\the\EMcounter}

\newskip \EMlastmovex \newskip \EMlastmovey
\newskip \EMlastlinex \newskip \EMlastliney

\def\resetEMspecials
  {\global\EMlastmovex=0pt \global\EMlastmovey=\EMlastmovex}

\resetEMspecials \appendtoks\resetEMspecials\to\everyshipout

%D Watch how we reset the specials after a page is flushed. We
%D don't have to bother about files here, because saving and
%D recalling is already implemented. Although not needed, we
%D define the start||stop macros, so that \CONTEXT\ users who
%D key them in are not confronted with error messages.

\let\startEMspecials\relax \let\stopEMspecials\relax

\def\EMgetposition#1#2%
  {\global\advance\EMcounter 1
   \setposition\EMvariable
   \global#1=\POSx\EMvariable
   \global#2=\POSy\EMvariable}

\def\EMmoveto
  {\EMgetposition\EMlastmovex\EMlastmovey}

\def\EMlineto
  {\EMgetposition\EMlastlinex\EMlastliney
   \global\advance\EMlastmovex -\EMlastlinex
   \global\advance\EMlastmovey -\EMlastliney
   \ScaledPointsToBigPoints{\number\EMlastmovex}\EMx
   \ScaledPointsToBigPoints{\number\EMlastmovey}\EMy
   \PDFcode{\EMlinewd\space w 0 0 m \EMx \space \EMy \space l S}%
   \global\EMlastmovex\EMlastlinex
   \global\EMlastmovey\EMlastliney}

%D The command \type {\setposition} registers a position by
%D name (here \type {\EMvariable}), while \type {\POSx} and
%D \type {\POSy} give you access to the coordinates.
%D
%D These three commands are containes in a suite of low level
%D commands that can be used to register and get access to
%D positional information. The current mechanism is not yet
%D complete, but already provides enough hooks for advanced
%D embedded graphics. Its functionality is a natural extension
%D to the \METAPOST\ support already present in \CONTEXT.
%D Therefore, more advanced examples can be found in the
%D \METAFUN\ manual, since they fall beyond the scope of this
%D module.

\fi % end of context part

%D As a bonus, I will now provide a few macros that will make
%D this mechanism transparant to \DVI\ as well as \PDF\
%D output. We will use \type {\pdfiteral} as trigger.

\ifx\PDFcode\undefined
  \ifx\pdfliteral\undefined
    \def\PDFcode#1{\special{PDF: #1}}
  \else
    \let\PDFcode\pdfliteral
  \fi
\fi

\ifx\PDFcode\undefined
  \def\EMpdfordvi#1#2{#2}
\else\ifx\pdfoutput\undefined
  \def\EMpdfordvi#1#2{#2}
\else
  \def\EMpdfordvi#1#2{\ifcase\pdfoutput#2\else#1\fi}
\fi\fi


%D We save some of the macros we defined previously:

\let\pdfEMmoveto\EMmoveto \let\pdfstartEMspecials\startEMspecials
\let\pdfEMlineto\EMlineto \let\pdfstopEMspecials \stopEMspecials

%D We now redefine them to support \DVI\ and \PDF.

\def\EMmoveto{\EMpdfordvi\pdfEMmoveto{\special{em:moveto}}}
\def\EMlineto{\EMpdfordvi\pdfEMlineto{\special{em:lineto}}}

\def\startEMspecials{\EMpdfordvi\pdfstartEMspecials\relax}
\def\stopEMspecials {\EMpdfordvi\pdfstopEMspecials \relax}

%D If there is any real demand for this in \CONTEXT, I will
%D hook these macros in the special drivers, so that their
%D support becomes more natural.

%D You may want to change the default linewidth. The following
%D macro does the job. Beware of the fact that \type
%D {\special}'s may interfere with the typesetting process.
%D
%D \starttyping
%D \setEMlinewidth{1pt}
%D \stoptyping

\def\setEMlinewidth#1% this could be done more efficient for
  {\bgroup           % context alone, but it's a hack anyway
   \dimen0=#1\relax
   \count0=\dimen0
   \divide\count0 65536
   \pdfordvi\relax{\special{em:linewidth \the\dimen0}}%
   \xdef\EMlinewd{\the\count0}%
   \egroup}

%D You may wonder to what extent positional tracking is
%D \PDFTEX\ specific. In \CONTEXT, we also support position
%D tracking in \DVI\ by using specials and analyzing the \DVI\
%D file afterwards using \DVIPOS. Since many of the advanced
%D \TEX\ features depend on some kind of back||end, we don't
%D consider it to be a disadvantage. Of course, the \PDFTEX\
%D way is not only cleaner, but also faster. It was more out
%D of curiosity than out of need that we provided the \DVI\
%D methods as well. Also, it is always good to have more roads
%D to reach the same goal.

\endinput