grph-trf.mkxl /size: 37 Kb    last modification: 2023-12-21 09:44
1%D \module
2%D   [       file=grph-trf,
3%D        version=2006.08.26, % overhaul/split of 1997.03.31 core-fig
4%D          title=\CONTEXT\ Graphic Macros,
5%D       subtitle=Transformations,
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\writestatus{loading}{ConTeXt Graphic Macros / Transformations}
15
16\unprotect
17
18%D We probably use too many dimens as the width calculations can go away. Some of
19%D this is an inheritance of limited backends (some supported fractions, some
20%D 1000's, some dimentions) so we calculate all of them. Nowadays scaling is always
21%D available so we could simplify the code. On the other hand, we now get some extra
22%D values for free.
23%D
24%D We could move the calculations to \LUA\ and clean up this lot anyway. On the
25%D other hand, there is some danger of messing up so it has a real low priority.
26
27\registerctxluafile{grph-trf}{autosuffix}
28
29% See below
30
31\newdimension\d_grph_rotate_x_size
32\newdimension\d_grph_rotate_y_size
33\newdimension\d_grph_rotate_x_offset
34\newdimension\d_grph_rotate_y_offset
35\newdimension\d_grph_rotate_x_position
36\newdimension\d_grph_rotate_y_position
37
38\newdimension\d_grph_rotate_new_width
39\newdimension\d_grph_rotate_new_height
40\newdimension\d_grph_rotate_new_depth
41
42% local:
43
44\newdimension\d_grph_scale_x_size
45\newdimension\d_grph_scale_y_size
46\newdimension\d_grph_scale_x_offset
47\newdimension\d_grph_scale_y_offset
48
49\newdimension\d_grph_scale_h_size
50\newdimension\d_grph_scale_v_size
51
52\newconditional\c_grph_scale_done
53\newconditional\c_grph_scale_scaling_done
54\newconditional\c_grph_scale_limit_factors \c_grph_scale_limit_factors\conditionaltrue
55
56\newdimension\d_grph_scale_wd
57\newdimension\d_grph_scale_ht
58\newdimension\d_grph_scale_dp
59
60\newconditional\c_grph_scale_swap_factor % global
61
62\newdimension\d_grph_scale_used_x_size   % global
63\newdimension\d_grph_scale_used_y_size   % global
64
65\newinteger\c_grph_scale_used_x_scale
66\newinteger\c_grph_scale_used_y_scale
67
68\let\m_grph_scale_used_x_scale\!!plusone
69\let\m_grph_scale_used_y_scale\!!plusone
70
71\newdimension\d_grph_scale_outer_v_size % we cannot manipulate any global vsize !
72
73% scratch:
74
75\lettonothing\m_grph_scale_temp
76\lettonothing\m_grph_scale_temp_x
77\lettonothing\m_grph_scale_temp_y
78
79% public:
80
81\mutable\let\finalscaleboxxscale \!!plusone
82\mutable\let\finalscaleboxyscale \!!plusone
83\mutable\let\finalscaleboxwidth  \!!zeropoint
84\mutable\let\finalscaleboxheight \!!zeropoint
85
86% we can let sx/sy win (first check)
87
88\installcorenamespace{scale}
89\installcorenamespace{scalegrid}
90\installcorenamespace{scalenorm}
91\installcorenamespace{scalefact}
92
93\installcommandhandler \??scale {scale} \??scale % we can have instances
94
95\setupscale
96  [\c!sx=\scaleparameter\c!s,
97   \c!sy=\scaleparameter\c!s,
98   \c!s=1,
99  %\c!scale=,
100  %\c!xscale=,
101  %\c!yscale=,
102  %\c!width=,
103  %\c!height=,
104  %\c!lines=,
105  %\c!factor=,
106  %\c!hfactor=,
107  %\c!wfactor=,
108  %\c!grid=,
109  %\c!equalwidth=,
110  %\c!equalheight=,
111   \c!maxwidth=\scaleparameter\c!width,
112   \c!maxheight=\scaleparameter\c!height]
113
114% \permanent\tolerant\protected\def\scale[#1]#*[#2]%
115%   {\bgroup
116%    % this is quite common so we might make this a helper
117%    \ifarguments
118%      \lettonothing\currentscale
119%    \or
120%      \ifhastok={#1}%
121%        \lettonothing\currentscale
122%        \setupcurrentscale[#1]%
123%      \else
124%        \cdef\currentscale{#1}%
125%      \fi
126%    \or
127%      \cdef\currentscale{#1}%
128%      \setupcurrentscale[#2]%
129%    \fi
130%    %
131%    \dowithnextboxcs\grph_scale_finish\naturalhbox} % intercept direction
132
133\newinteger\c_grph_scale_nesting
134
135\def\grph_scale_set_nesting
136  {\advanceby\c_grph_scale_nesting\plusone
137   \letcsname\??scale>\the\c_grph_scale_nesting:\s!parent\endcsname\??scale
138   \cdef\currentscale{>\the\c_grph_scale_nesting}}
139
140\permanent\tolerant\protected\def\scale[#S#1]#*[#S#2]%
141  {\bgroup
142   \ifarguments
143     \grph_scale_set_nesting
144   \or
145     \ifhastok={#1}%
146       \grph_scale_set_nesting
147       \setupcurrentscale[#1]%
148     \else
149       \cdef\currentscale{#1}%
150       \ifempty\currentscale
151         \grph_scale_set_nesting
152       \fi
153     \fi
154   \or
155     \cdef\currentscale{#1}%
156     \ifempty\currentscale
157       \grph_scale_set_nesting
158     \fi
159     \setupcurrentscale[#2]%
160   \fi
161   %
162   \dowithnextboxcs\grph_scale_finish\naturalhbox} % intercept direction
163
164\def\grph_scale_finish
165  {% todo: p_scale_
166   \edef\p_scale      {\scaleparameter\c!scale      }%
167   \edef\p_xscale     {\scaleparameter\c!xscale     }%
168   \edef\p_yscale     {\scaleparameter\c!yscale     }%
169   \edef\p_width      {\scaleparameter\c!width      }%
170   \edef\p_height     {\scaleparameter\c!height     }%
171   \edef\p_depth      {\scaleparameter\c!depth      }%
172   \edef\p_lines      {\scaleparameter\c!lines      }%
173   \edef\p_factor     {\scaleparameter\c!factor     }%
174   \edef\p_hfactor    {\scaleparameter\c!hfactor    }%
175   \edef\p_wfactor    {\scaleparameter\c!wfactor    }%
176 % \edef\p_grid       {\scaleparameter\c!grid       }% used once
177   \edef\p_maxwidth   {\scaleparameter\c!maxwidth   }%
178   \edef\p_maxheight  {\scaleparameter\c!maxheight  }%
179   \edef\p_sx         {\scaleparameter\c!sx         }%
180   \edef\p_sy         {\scaleparameter\c!sy         }%
181   \edef\p_equalwidth {\scaleparameter\c!equalwidth }%
182   \edef\p_equalheight{\scaleparameter\c!equalheight}%
183   %
184   \d_grph_scale_dp\dp\nextbox
185   \ifx\p_depth\v!no \ifzeropt\d_grph_scale_dp \else
186     \setbox\nextbox\naturalhpack{\raise\d_grph_scale_dp\box\nextbox}% new
187     \d_grph_scale_dp\dp\nextbox
188   \fi \fi
189   \d_grph_scale_wd\wd\nextbox
190   \d_grph_scale_ht\ht\nextbox
191   \d_grph_scale_dp\dp\nextbox
192   %
193   \glet\finalscaleboxxscale \!!plusone
194   \glet\finalscaleboxyscale \!!plusone
195   \xdef\finalscaleboxwidth {\the\d_grph_scale_wd}%
196   \xdef\finalscaleboxheight{\the\d_grph_scale_ht}%
197   %
198   \forgetall
199   \dontcomplain
200   %
201   \c_grph_scale_done\conditionalfalse
202   \grph_scale_calculate
203   \ifconditional\c_grph_scale_done
204     \grph_scale_apply
205   \fi
206   \grph_scale_position
207   %
208   \box\nextbox
209   \egroup}
210
211\def\grph_scale_apply
212  {\d_grph_scale_wd\finalscaleboxxscale\d_grph_scale_wd
213   \d_grph_scale_ht\finalscaleboxyscale\d_grph_scale_ht
214   \d_grph_scale_dp\finalscaleboxyscale\d_grph_scale_dp
215   \ifdim\d_grph_scale_wd=\wd\nextbox
216     \ifdim\d_grph_scale_ht=\ht\nextbox
217       \ifdim\d_grph_scale_dp=\dp\nextbox
218        % \grph_scale_apply_nop
219       \else
220          \grph_scale_apply_yes
221       \fi
222     \else
223       \grph_scale_apply_yes
224     \fi
225   \else
226     \grph_scale_apply_yes
227   \fi}
228
229\def\grph_scale_apply_yes
230  {\setbox\nextbox\hcontainer
231     {\dostartscaling \finalscaleboxxscale \finalscaleboxyscale
232      \smashedbox\nextbox
233      \dostopscaling}%
234   \wd\nextbox\d_grph_scale_wd
235   \ht\nextbox\d_grph_scale_ht
236   \dp\nextbox\d_grph_scale_dp}
237
238\def\m_grph_scale_stamp_c{11}
239
240\def\grph_scale_calculate
241  {\ifdim\d_grph_scale_ht>\zeropoint \ifdim\d_grph_scale_wd>\zeropoint
242     \edef\m_grph_scale_stamp_a{\p_scale\p_xscale\p_yscale\p_factor\p_wfactor\p_hfactor\p_lines\p_width\p_height}%
243     \edef\m_grph_scale_stamp_b{\p_sx\p_sy}%
244     \ifempty\m_grph_scale_stamp_a
245       \ifx\m_grph_scale_stamp_b\m_grph_scale_stamp_c
246         % no scaling, don't change this (previous attempts failed anyway)
247         \insidefloattrue % trick
248         \grph_scale_calculations_yes
249       \else
250         \grph_scale_check_sx_sy
251         \grph_scale_calculations_nop
252       \fi
253     \else
254       \ifempty\m_grph_scale_stamp_b
255         % no need to check further
256       \else
257         \grph_scale_check_sx_sy
258       \fi
259       \grph_scale_calculations_yes
260     \fi
261   \fi \fi}
262
263\def\grph_scale_check_sx_sy
264  {\ifdim\p_sx\onepoint=\onepoint\else\edef\p_width {\the\dimexpr\p_sx\d_grph_scale_wd}\fi
265   \ifdim\p_sy\onepoint=\onepoint\else\edef\p_height{\the\dimexpr\p_sy\d_grph_scale_ht}\fi}
266
267\def\grph_scale_rounded#1%
268  {\thewithoutunit\dimexpr#1\points*100+32768\scaledpoint\relax}
269
270\def\grph_scale_calculations_nop
271  {\c_grph_scale_done\conditionaltrue
272   \xdef\finalscaleboxwidth {\the\dimexpr\p_sx\d_grph_scale_wd\relax}%
273   \xdef\finalscaleboxheight{\the\dimexpr\p_sy\d_grph_scale_ht\relax}%
274   \glet\finalscaleboxxscale\p_sx
275   \glet\finalscaleboxyscale\p_sy
276   \ifempty\finalscaleboxxscale\let\finalscaleboxxscale\!!plusone\fi
277   \ifempty\finalscaleboxyscale\let\finalscaleboxyscale\!!plusone\fi}
278
279\let\grph_scale_calculations_report\relax
280
281\def\grph_scale_calculations_yes
282  {\c_grph_scale_done\conditionaltrue
283   % initial values
284   \d_grph_scale_x_offset\zeropoint
285   \d_grph_scale_y_offset\zeropoint
286   \d_grph_scale_x_size  \d_grph_scale_wd
287   \d_grph_scale_y_size  \d_grph_scale_ht % alleen ht wordt geschaald!
288   % final values
289   \global\d_grph_scale_used_x_size \zeropoint % see note * (core-fig)
290   \global\d_grph_scale_used_y_size \zeropoint % see note * (core-fig)
291   \c_grph_scale_used_x_scale       \plusone   % see note * (core-fig)
292   \c_grph_scale_used_y_scale       \plusone   % see note * (core-fig)
293   \let\m_grph_scale_used_x_scale   \!!plusone
294   \let\m_grph_scale_used_y_scale   \!!plusone
295   % preparations
296   \c_grph_scale_scaling_done\conditionalfalse
297   \grph_scale_check_parameters
298   % calculators
299   % beware, they operate in sequence, and calculate missing dimensions / messy
300   % grph_scale_by_nature % when? needed?
301   \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_factor   \fi
302   \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_scale    \fi
303   \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_dimension\fi
304   % used in actual scaling
305   \xdef\finalscaleboxwidth  {\the\d_grph_scale_used_x_size}%
306   \xdef\finalscaleboxheight {\the\d_grph_scale_used_y_size}%
307   \glet\finalscaleboxxscale \m_grph_scale_used_x_scale
308   \glet\finalscaleboxyscale \m_grph_scale_used_y_scale
309   \grph_scale_calculations_report}
310
311\defcsname\??scalegrid\v!yes     \endcsname{\getnoflines   \d_grph_scale_used_y_size\edef\p_height{\the\noflines\lineheight}}
312\defcsname\??scalegrid\v!height  \endcsname{\getrawnoflines\d_grph_scale_used_y_size\edef\p_height{\the\dimexpr\noflines\lineheight+\strutdepth}}
313\defcsname\??scalegrid\v!depth   \endcsname{\getrawnoflines\d_grph_scale_used_y_size\edef\p_height{\the\dimexpr\noflines\lineheight-\strutdepth}}
314\defcsname\??scalegrid\v!halfline\endcsname{\getrawnoflines\d_grph_scale_used_y_size\edef\p_height{\the\dimexpr\noflines\lineheight+.5\lineheight}}
315\defcsname\??scalegrid\v!fit     \endcsname{\getrawnoflines\d_grph_scale_used_y_size\edef\p_height{\the\noflines\lineheight}}
316\letcsname\??scalegrid\empty     \endcsname\donothing
317
318\def\grph_scale_check_parameters % resolve self referencing loops
319  {\ifempty\p_maxwidth \else \edef\p_maxwidth {\the\dimexpr\p_maxwidth        }\fi
320   \ifempty\p_maxheight\else \edef\p_maxheight{\the\dimexpr\p_maxheight       }\fi
321   \ifempty\p_lines    \else \edef\p_height   {\the\dimexpr\p_lines\lineheight}\fi
322   \begincsname\??scalegrid\scaleparameter\c!grid\endcsname}
323
324\def\grph_scale_by_nature % where ! ! ! ! !
325  {\ifempty\p_width \else \global\d_grph_scale_used_x_size\p_width \fi
326   \ifempty\p_height\else \global\d_grph_scale_used_y_size\p_height\fi
327   \ifempty\p_scale \else        \c_grph_scale_used_x_scale\p_scale
328                                 \c_grph_scale_used_y_scale\p_scale \fi
329   \ifempty\p_xscale\else        \c_grph_scale_used_x_scale\p_xscale\fi
330   \ifempty\p_yscale\else        \c_grph_scale_used_y_scale\p_yscale\fi}
331
332% \defineexternalfigure[width-6][factor=auto,maxwidth=\textheight,maxheight=\textwidth]
333% \defineexternalfigure[width-7][factor=auto,maxwidth=\textwidth,maxheight=\textheight]
334% \placefigure{none}{\rotate[frame=on,offset=overlay]{\externalfigure[t:/sources/cow.pdf][width-6]}} \page
335% \placefigure{none}{\framed[frame=on,offset=overlay]{\externalfigure[t:/sources/cow.pdf][width-7]}}
336
337%D The \type {min} option makes sure that the smallest available space determines
338%D the max size (so we can get a bleed on the other axis):
339%D
340%D \startlinecorrection
341%D \startcombination[nx=2,ny=2,distance=4cm]
342%D     {\externalfigure[hacker][factor=max,maxwidth=6cm,maxheight=6cm]} {}
343%D     {\externalfigure[mill]  [factor=max,maxwidth=6cm,maxheight=6cm]} {}
344%D     {\externalfigure[hacker][factor=min,maxwidth=6cm,maxheight=6cm]} {}
345%D     {\externalfigure[mill]  [factor=min,maxwidth=6cm,maxheight=6cm]} {}
346%D \stopcombination
347%D \stoplinecorrection
348
349\def\m_grph_scale_factor_set{\v!min,\v!max,\v!fit,\v!broad,\v!auto} % can be an \edef
350
351\def\grph_scale_by_factor
352  {\ifinset\p_factor\m_grph_scale_factor_set
353     \grph_scale_by_factor_a
354   \orelse\ifinset\p_hfactor\m_grph_scale_factor_set
355     \grph_scale_by_factor_b
356   \orelse\ifinset\p_wfactor\m_grph_scale_factor_set
357     \grph_scale_by_factor_c
358   \else
359     \grph_scale_by_factor_d
360   \fi}
361
362\def\grph_scale_by_factor_a
363  {\grph_scale_apply_size
364   \ifdim\d_grph_scale_x_size >\d_grph_scale_y_size
365     \grph_scale_calculate_norm  \d_grph_scale_used_x_size\p_factor\p_maxwidth\hsize\d_grph_scale_h_size
366     \grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size
367     \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size
368   \else
369     \grph_scale_calculate_norm  \d_grph_scale_used_y_size\p_factor\p_maxheight\d_grph_scale_outer_v_size\d_grph_scale_v_size
370     \grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size
371     \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size
372   \fi
373   \grph_scale_by_factor_indeed}
374
375\def\grph_scale_by_factor_b
376  {\grph_scale_apply_size
377   \grph_scale_calculate_norm  \d_grph_scale_used_y_size\p_hfactor\p_maxheight\d_grph_scale_outer_v_size\d_grph_scale_v_size
378   \grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size
379   \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size
380   \grph_scale_by_factor_indeed}
381
382\def\grph_scale_by_factor_c
383  {\grph_scale_apply_size
384   \grph_scale_calculate_norm  \d_grph_scale_used_x_size\p_wfactor\p_maxwidth\hsize\d_grph_scale_h_size
385   \grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size
386   \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size
387   \grph_scale_by_factor_indeed}
388
389\def\grph_scale_by_factor_d
390  {\grph_scale_calculate_norm\d_grph_scale_used_y_size\p_factor \p_height \textheight\d_grph_scale_v_size
391   \grph_scale_calculate_norm\d_grph_scale_used_y_size\p_hfactor\p_height \textheight\d_grph_scale_v_size
392   \grph_scale_calculate_norm\d_grph_scale_used_x_size\p_wfactor\p_width  \hsize     \hsize}
393
394\def\grph_scale_by_factor_indeed
395  {\grph_scale_calculate_fact\p_factor
396   \c_grph_scale_scaling_done\conditionaltrue
397   \ifconditional\c_grph_scale_limit_factors
398     \ifdim\d_grph_scale_used_x_size\ifconditional\c_grph_scale_swap_factor<\else>\fi\d_grph_scale_h_size
399       \global\d_grph_scale_used_y_size\zeropoint
400       \global\d_grph_scale_used_x_size\d_grph_scale_h_size
401     \orelse\ifdim\d_grph_scale_used_y_size\ifconditional\c_grph_scale_swap_factor<\else>\fi\d_grph_scale_v_size
402       \global\d_grph_scale_used_x_size\zeropoint
403       \global\d_grph_scale_used_y_size\d_grph_scale_v_size
404     \fi
405   \fi
406   \grph_scale_by_dimension}
407
408\def\grph_scale_by_scale
409  {\edef\m_grph_scale_temp{\p_scale\p_xscale\p_yscale}%
410   \ifempty\m_grph_scale_temp \else
411     \grph_scale_apply_scale\m_grph_scale_used_x_scale\p_xscale
412     \grph_scale_apply_scale\m_grph_scale_used_y_scale\p_yscale
413   % \global\d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size\relax % no global needed here
414   % \global\d_grph_scale_used_y_size\m_grph_scale_used_y_scale\d_grph_scale_y_size\relax % no global needed here
415     % wrong: we need to recalculate the scale
416     \global\d_grph_scale_used_x_size\zeropoint
417     \global\d_grph_scale_used_y_size\zeropoint
418     %
419     \ifempty\p_maxwidth
420       \ifempty\p_maxheight\orelse\ifdim\d_grph_scale_y_size>\p_maxheight\relax
421         \global\d_grph_scale_used_y_size\p_maxheight
422       \fi
423     \orelse\ifdim\d_grph_scale_x_size>\p_maxwidth\relax
424       \global\d_grph_scale_used_x_size\p_maxwidth
425     \fi
426   \fi}
427
428\def\grph_scale_by_dimension
429  {\ifdim\d_grph_scale_used_x_size>\zeropoint
430     \ifdim\d_grph_scale_used_y_size>\zeropoint
431       \grph_scale_by_dimension_a
432     \else
433       \grph_scale_by_dimension_b
434     \fi
435   \else
436     \ifdim\d_grph_scale_used_y_size>\zeropoint
437       \grph_scale_by_dimension_c
438     \else
439       \grph_scale_by_dimension_d
440     \fi
441   \fi}
442
443\def\grph_scale_by_dimension_a
444  {\grph_scale_by_dimension_indeed
445     {\grph_scale_calculate_scale\m_grph_scale_used_y_scale\d_grph_scale_used_y_size\d_grph_scale_y_size
446      \grph_scale_calculate_scale\m_grph_scale_used_x_scale\d_grph_scale_used_x_size\d_grph_scale_x_size}%
447     {\grph_scale_calculate_scale\m_grph_scale_used_y_scale\d_grph_scale_used_y_size\d_grph_scale_y_size
448      \grph_scale_calculate_scale\m_grph_scale_used_x_scale\d_grph_scale_used_x_size\d_grph_scale_x_size}%
449     {\grph_scale_calculate_scale\m_grph_scale_used_y_scale\d_grph_scale_used_y_size\d_grph_scale_y_size
450      \grph_scale_calculate_scale\m_grph_scale_used_x_scale\d_grph_scale_used_x_size\d_grph_scale_x_size}}
451
452\def\grph_scale_by_dimension_b
453  {\grph_scale_by_dimension_indeed
454     {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size
455      \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size}%
456     {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size
457      \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size}%
458     {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size
459      \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size}}
460
461\def\grph_scale_by_dimension_c
462  {\grph_scale_by_dimension_indeed % weird .. three same cases
463     {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size
464      \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size}%
465     {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size
466      \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size}%
467     {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size
468      \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size}}
469
470\def\grph_scale_by_dimension_d
471  {\grph_scale_by_dimension_indeed
472     {\grph_scale_apply_scale\m_grph_scale_used_x_scale\p_xscale
473      \grph_scale_apply_scale\m_grph_scale_used_y_scale\p_yscale
474      \global\d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size
475      \global\d_grph_scale_used_y_size\m_grph_scale_used_y_scale\d_grph_scale_y_size}%
476     {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size
477      \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size}%
478     {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size
479      \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size}}
480
481\def\grph_scale_by_dimension_indeed#1#2#3%
482  {#1\relax
483   \ifempty\p_maxwidth\orelse\ifdim\d_grph_scale_used_x_size>\p_maxwidth\relax
484     \global\d_grph_scale_used_x_size\p_maxwidth
485     #2\relax
486   \fi
487   \ifempty\p_maxheight\orelse\ifdim\d_grph_scale_used_y_size>\p_maxheight\relax
488     \global\d_grph_scale_used_y_size\p_maxheight
489      #3\relax
490   \fi}
491
492% we can use \lastnamedcs if we want to squeeze out some more
493
494\def\grph_scale_calculate_norm#1#2% todo: swap 1 and 2 and pass one less
495  {\csname\??scalenorm\ifcsname\??scalenorm#2\endcsname#2\else\s!unknown\fi\endcsname#1#2}
496
497\def\grph_scale_calculate_fact#1%
498  {\csname\??scalefact\ifcsname\??scalefact#1\endcsname#1\else\s!unknown\fi\endcsname}
499
500\defcsname\??scalenorm\v!max    \endcsname#1#-#-#2#-{\global#1#2}
501\defcsname\??scalenorm\v!fit    \endcsname#1#-#-#-#2{\global#1#2}
502\defcsname\??scalenorm\v!broad  \endcsname#1#-#-#-#2{\global#1\dimexpr#2-4\externalfigureparameter\c!bodyfont\relax}
503\defcsname\??scalenorm\s!unknown\endcsname#1#2#-#-#-{\global#1\dimexpr#2\dimexpr\externalfigureparameter\c!bodyfont/10\relax\relax} % brr ex
504\defcsname\??scalenorm\v!auto   \endcsname#1#-#2#-#-{\ifempty#2\else\global#1#2\fi}
505\defcsname\??scalenorm\empty    \endcsname#1#-#2#-#-{\ifempty#2\else\global#1#2\fi}
506\defcsname\??scalenorm\s!default\endcsname#1#-#2#-#-{\ifempty#2\else\global#1#2\fi}
507
508\defcsname\??scalefact\v!min    \endcsname{\global\c_grph_scale_swap_factor\conditionaltrue}
509\defcsname\??scalefact\s!unknown\endcsname{\global\c_grph_scale_swap_factor\conditionalfalse}
510
511\defcsname\??scalenorm\v!min\endcsname#-#-#-#-#-% an ugly hack
512  {\d_grph_scale_used_x_size\hsize
513   \d_grph_scale_used_y_size\vsize}
514
515\def\grph_scale_calculate_scales#1#2%
516  {\edef\m_grph_scale_used_x_scale{\luaexpr{\number#1/\number#2}}%
517   \let\m_grph_scale_used_y_scale\m_grph_scale_used_x_scale}
518
519\def\grph_scale_calculate_scale#1#2#3%
520  {\edef#1{\luaexpr{\number#2/\number#3}}}
521
522\def\grph_scale_apply_scale#1#2% #1 = parameter / scale can be empty
523  {% no overflow
524   \edef#1{\luaexpr
525     {\number
526      \ifempty#2%
527        \ifempty\p_scale            \plusthousand \else
528        \ifnum  \p_scale=\zerocount \plusthousand \else
529                                    \p_scale      \fi\fi
530      \orelse\ifnum#2=\zerocount
531        \ifempty\p_scale            \plusthousand \else
532        \ifnum  \p_scale=\zerocount \plusthousand \else
533                                    \p_scale      \fi\fi
534      \else
535                                    #2%
536      \fi
537      /1000}}}
538
539\def\grph_scale_apply_size
540  {\ifempty\p_maxheight
541     \d_grph_scale_outer_v_size\textheight
542     \ifinner
543       \d_grph_scale_outer_v_size \vsize % \textheight =\vsize
544       \scratchdimen\vsize % \scratchdimen=\textheight
545     \orelse\ifinsidefloat
546       \d_grph_scale_outer_v_size \vsize % \textheight =\vsize
547       \scratchdimen\vsize % \scratchdimen=\textheight
548     \orelse\ifinpagebody
549       \d_grph_scale_outer_v_size \vsize % \textheight =\vsize
550       \scratchdimen\vsize % \scratchdimen=\textheight
551     \orelse\ifdim\pagegoal<\maxdimen
552       \ifdim\pagetotal<\pagegoal
553         \scratchdimen\dimexpr\pagegoal-\pagetotal\relax
554       \else
555         \scratchdimen\d_grph_scale_outer_v_size % \textheight
556       \fi
557     \else
558       \scratchdimen\d_grph_scale_outer_v_size % \textheight
559     \fi
560   \else
561     \scratchdimen\p_maxheight
562     \d_grph_scale_outer_v_size\scratchdimen
563   \fi
564   \ifempty\p_height
565     \d_grph_scale_v_size\scratchdimen
566   \else
567     \d_grph_scale_v_size\p_height
568   \fi
569   \ifempty\p_width
570     \d_grph_scale_h_size\hsize
571   \else
572     \d_grph_scale_h_size\p_width
573   \fi}
574
575% \startcombination
576%     {\externalfigure[cow.pdf] [frame=on,height=3cm,equalwidth=6cm]} {a cow}
577%     {\externalfigure[mill.png][frame=on,height=3cm,equalwidth=6cm]} {a mill}
578% \stopcombination
579
580\def\grph_scale_position
581  {\ifempty\p_equalwidth \else
582    \scratchdimen\p_equalwidth\relax
583    \ifdim\d_grph_scale_wd<\scratchdimen
584      \setbox\nextbox\naturalhpack to \scratchdimen{\hss\box\nextbox\hss}%
585    \fi
586   \fi
587   \ifempty\p_equalheight \else
588     \scratchdimen\p_equalheight\relax
589     \ifdim\d_grph_scale_ht<\scratchdimen
590       \setbox\nextbox\naturalvpack to \scratchdimen{\vss\box\nextbox\vss}%
591     \fi
592   \fi}
593
594\permanent\protected\def\fastscale#1%
595  {\ifnum#1=1000\relax
596     \expandafter\grph_scale_fast_nop
597   \else
598     \expandafter\grph_scale_fast_yes
599   \fi{#1}}
600
601\def\grph_scale_fast_nop#1%
602  {\hbox}
603
604\def\grph_scale_fast_yes#1%
605  {\edef\finalscaleboxxscale{\toscaled\dimexpr#1\onepoint/1000\relax}% brrr
606   \let\finalscaleboxyscale\finalscaleboxxscale
607   \dowithnextboxcs\grph_scale_fast_finish\hbox} % container ?
608
609\def\grph_scale_fast_finish
610  {\grph_scale_apply
611   \box\nextbox
612   \endgroup}
613
614\permanent\protected\def\fastsxsy#1#2%
615  {\bgroup
616   \edef\p_sx{#1}%
617   \edef\p_sy{#2}%
618   \dowithnextboxcs\grph_scale_fast_sx_xy_finish\hbox} % container?
619
620\def\grph_scale_fast_sx_xy_finish
621  {\grph_scale_check_sx_sy
622   \d_grph_scale_wd\wd\nextbox
623   \d_grph_scale_ht\ht\nextbox
624   \d_grph_scale_dp\dp\nextbox
625   \grph_scale_calculations_nop
626   \grph_scale_apply
627   \box\nextbox
628   \egroup}
629
630%D \macros
631%D   {clip, setupclipping}
632%D
633%D Although related to figures, clipping can be applied to arbitrary content. We can
634%D use \METAPOST\ to provide a non rectangular clipping path.
635%D
636%D \starttyping
637%D \startMPclip{fun}
638%D   clip currentpicture to fullcircle
639%D     shifted (.5,.5) xscaled \width yscaled \height ;
640%D \stopMPclip
641%D \stoptyping
642%D
643%D We get a rectangular piece of the figure when we say:
644%D
645%D \starttyping
646%D \clip[x=2,y=1]{\externalfigure[photo]}
647%D \stoptyping
648%D
649%D When we want to clip to the oval we defined a few lines ago, we say:
650%D
651%D \starttyping
652%D \clip[nx=1,ny=1,x=1,y=1,mp=fun]{\externalfigure[photo]}
653%D \stoptyping
654%D
655%D The general characteristics of clipping can be set up with
656%D
657%D \showsetup{setupclipping}
658
659\installcorenamespace{clipping}
660
661\installdirectcommandhandler \??clipping {clipping}
662
663\permanent\tolerant\protected\def\clip[#S#1]% nb top->bottom left->right
664  {\bgroup
665   \ifparameter#1\or
666     \setupcurrentclipping[#1]%
667   \fi
668   \dowithnextboxcs\grph_clip_finish\hbox}
669
670\def\grph_clip_finish
671  {\ifcstok{\clippingparameter\c!state}\v!start
672     \grph_clip_yes_finish
673   \else
674     \grph_clip_nop_finish
675   \fi}
676
677\def\grph_clip_yes_finish
678  {\ifdim\clippingparameter\c!width>\zeropoint
679     \scratchwidth  \clippingparameter\c!width
680     \scratchxoffset\clippingparameter\c!hoffset
681   \else
682     \scratchwidth\dimexpr\wd\nextbox/\clippingparameter\c!nx\relax
683     \scratchxoffset\dimexpr\clippingparameter\c!x\scratchwidth-\scratchwidth\relax
684     \scratchwidth\clippingparameter\c!sx\scratchwidth
685   \fi
686   \relax % sure
687   \ifdim\clippingparameter\c!height>\zeropoint
688     \scratchheight\clippingparameter\c!height
689     \scratchyoffset\dimexpr\ht\nextbox-\clippingparameter\c!voffset-\scratchheight\relax
690   \else
691     \scratchheight\dimexpr\ht\nextbox/\clippingparameter\c!ny\relax
692     \scratchyoffset\dimexpr-\clippingparameter\c!y\scratchheight-\clippingparameter\c!sy\scratchheight+\scratchheight\relax
693     \scratchheight\clippingparameter\c!sy\scratchheight
694     \advanceby\scratchyoffset \ht\nextbox
695   \fi
696   \setbox\nextbox\naturalhpack
697     {\advanceby\scratchxoffset -\clippingparameter\c!leftoffset  \relax
698      \advanceby\scratchyoffset -\clippingparameter\c!bottomoffset\relax
699      \hskip-\scratchxoffset
700      \lower\scratchyoffset
701      \box\nextbox}%
702   \wd\nextbox\zeropoint
703   \ht\nextbox\zeropoint
704   \dp\nextbox\zeropoint
705   \setbox\nextbox\naturalhpack
706     {\advanceby\scratchwidth \dimexpr\clippingparameter\c!leftoffset  +\clippingparameter\c!rightoffset\relax
707      \advanceby\scratchheight\dimexpr\clippingparameter\c!bottomoffset+\clippingparameter\c!topoffset  \relax
708      \dostartclipping{\clippingparameter\c!mp}\scratchwidth\scratchheight
709        \box\nextbox
710      \dostopclipping}%
711   \setbox\nextbox\hcontainer
712     {\hskip-\clippingparameter\c!leftoffset
713      \lower \clippingparameter\c!bottomoffset
714      \box\nextbox}%
715   \wd\nextbox\scratchwidth
716   \ht\nextbox\scratchheight
717   \dp\nextbox\zeropoint
718   \box\nextbox
719   \egroup}
720
721\def\grph_clip_nop_finish
722  {\box\nextbox
723   \egroup}
724
725\setupclipping
726  [\c!state=\v!start,
727   \c!n=\plusone, % was \plustwo
728   \c!nx=\clippingparameter\c!n,\c!x=\plusone,\c!sx=\plusone,
729   \c!ny=\clippingparameter\c!n,\c!y=\plusone,\c!sy=\plusone,
730   \c!width=\zeropoint,
731   \c!height=\zeropoint,
732   \c!hoffset=\zeropoint,
733   \c!voffset=\zeropoint,
734   \c!offset=\zeropoint,
735   \c!leftoffset=\clippingparameter\c!offset,
736   \c!rightoffset=\clippingparameter\c!offset,
737   \c!topoffset=\clippingparameter\c!offset,
738   \c!bottomoffset=\clippingparameter\c!offset,
739   \c!mp=]
740
741%D \startbuffer
742%D \startuseMPgraphic{test}
743%D   path p ; p := fullcircle scaled 4cm ;
744%D   draw p withpen pencircle scaled 1cm ;
745%D   setbounds currentpicture to boundingbox p ;
746%D \stopuseMPgraphic
747%D
748%D \hbox to \hsize \bgroup
749%D   \hss
750%D   \ruledhbox{\useMPgraphic{test}}%
751%D   \hss
752%D   \ruledhbox{\clip{\useMPgraphic{test}}}%
753%D   \hss
754%D \egroup
755%D \stopbuffer
756%D
757%D \typebuffer \getbuffer
758
759%D Mirroring.
760
761\permanent\protected\def\mirror
762  {\bgroup
763   \dowithnextboxcs\grph_mirror_finish\hbox}
764
765\def\grph_mirror_finish
766  {\scratchdimen\wd\nextbox
767   % better use an hbox (if no \forgetall, leftskip etc may creep in)
768   %\setbox\nextbox\vbox{\forgetall\dostartmirroring\hskip-\wd\nextbox\box\nextbox\dostopmirroring}%
769   \setbox\nextbox\naturalhpack
770     {\dostartmirroring
771      \hskip-\wd\nextbox
772      \box\nextbox
773      \dostopmirroring}%
774   \wd\nextbox\scratchdimen
775   \box\nextbox
776   \egroup}
777
778%D A couple of examples, demonstrating how the depth is taken care of:
779%D
780%D \startbuffer
781%D test\rotate[frame=on, rotation=0]  {gans}%
782%D test\rotate[frame=on, rotation=90] {gans}%
783%D test\rotate[frame=on, rotation=180]{gans}%
784%D test\rotate[frame=on, rotation=270]{gans}%
785%D test
786%D \stopbuffer
787%D
788%D \typebuffer \getbuffer
789%D
790%D When we rotate over arbitrary angles, we need to relocate the resulting box
791%D because rotation brings that box onto the negative axis. The calculations (mostly
792%D sin and cosine) need to be tuned for the way a box is packages (i.e. the refence
793%D point). A typical example of drawing, scribbling, and going back to the days of
794%D school math.
795%D
796%D We do a bit more calculations than needed, simply because that way it's easier to
797%D debug the code.
798
799\installcorenamespace {rotate}
800\installcorenamespace {rotatelocation}
801\installcorenamespace {rotatepreset}
802
803%D These are set at the \LUA\ end (it's a cheaper operation than setting a dimen
804%D register and these are actually kind of constants not used in further
805%D calculations):
806
807% mutable\dimendef\d_grph_rotate_x_size    \zeropoint
808% mutable\dimendef\d_grph_rotate_y_size    \zeropoint
809% mutable\dimendef\d_grph_rotate_x_offset  \zeropoint
810% mutable\dimendef\d_grph_rotate_y_offset  \zeropoint
811% mutable\dimendef\d_grph_rotate_x_position\zeropoint
812% mutable\dimendef\d_grph_rotate_y_position\zeropoint
813%
814% mutable\dimendef\d_grph_rotate_new_width \zeropoint
815% mutable\dimendef\d_grph_rotate_new_height\zeropoint
816% mutable\dimendef\d_grph_rotate_new_depth \zeropoint
817
818%D These aren't:
819
820\newdimension\d_grph_rotate_used_height
821
822\newdimension\d_grph_rotate_width
823\newdimension\d_grph_rotate_height
824\newdimension\d_grph_rotate_depth
825
826\newdimension\d_grph_rotate_saved_width
827\newdimension\d_grph_rotate_saved_height
828\newdimension\d_grph_rotate_saved_depth
829
830\newconditional\c_grph_rotate_obey_depth
831\newconditional\c_grph_rotate_not_fit
832\newconditional\c_grph_rotate_center
833
834\installframedcommandhandler \??rotate {rotate} \??rotate
835
836\setuprotate
837  [\c!rotation=90,
838   \c!location=\v!normal,
839   \c!width=\v!fit,
840   \c!height=\v!fit,
841   \c!offset=\v!overlay,
842   \c!frame=\v!off]
843
844\lettonothing\p_rotation_location
845\lettonothing\p_rotation_rotation
846
847\permanent\tolerant\protected\def\rotate[#S#1]% \bgroup: \rotate kan argument zijn
848  {\bgroup
849   \ifparameter#1\or
850     \setupcurrentrotate[#1]%
851   \fi
852   \edef\p_rotation_location{\rotateparameter\c!location}%
853   \edef\p_rotation_rotation{\rotateparameter\c!rotation}%
854   \ifcsname\??rotatelocation\p_rotation_location\endcsname
855      \expandafter\lastnamedcs
856   \else
857      \expandafter\grph_rotate_default
858   \fi}
859
860\def\grph_rotate_framed
861  {\resetrotateparameter\c!location
862   \dowithnextboxcs\grph_rotate_finish\vbox
863   \inheritedrotateframed}
864
865\def\grph_rotate_normal
866  {\dowithnextboxcs\grph_rotate_finish\vbox}
867
868\def\grph_rotate_finish
869  {\grph_rotate_finish_indeed
870   \egroup}
871
872\def\grph_rotate_default
873  {\c_grph_rotate_not_fit\conditionalfalse
874   \c_grph_rotate_center\conditionalfalse
875   \c_grph_rotate_obey_depth\conditionaltrue
876   \grph_rotate_framed}
877
878\letcsname\??rotatelocation\v!default\endcsname\grph_rotate_default
879
880\defcsname\??rotatelocation\v!depth\endcsname
881  {\c_grph_rotate_not_fit\conditionalfalse
882   \c_grph_rotate_center\conditionalfalse
883   \c_grph_rotate_obey_depth\conditionaltrue
884   \grph_rotate_normal}
885
886\defcsname\??rotatelocation\v!fit\endcsname
887  {\c_grph_rotate_not_fit\conditionaltrue
888   \c_grph_rotate_center\conditionalfalse
889   \c_grph_rotate_obey_depth\conditionaltrue
890   \grph_rotate_normal}
891
892\defcsname\??rotatelocation\v!broad\endcsname
893  {\c_grph_rotate_not_fit\conditionalfalse
894   \c_grph_rotate_center\conditionalfalse
895   \c_grph_rotate_obey_depth\conditionalfalse
896   \grph_rotate_normal}
897
898\defcsname\??rotatelocation\v!high\endcsname
899  {\c_grph_rotate_not_fit\conditionalfalse
900   \c_grph_rotate_center\conditionalfalse
901   \c_grph_rotate_obey_depth\conditionalfalse
902   \grph_rotate_framed}
903
904\defcsname\??rotatelocation\v!middle\endcsname
905  {\c_grph_rotate_not_fit\conditionalfalse
906   \c_grph_rotate_center\conditionaltrue
907   \c_grph_rotate_obey_depth\conditionalfalse  % hm, depth ?
908   \grph_rotate_normal}
909
910\permanent\protected\def\dorotatebox#1% {angle} \hbox/\vbox/\vtop % a fast low level one
911  {\ifcase#1\relax
912     \expandafter\gobbleoneargument
913   \else
914     \expandafter\grph_rotate_box
915   \fi{#1}}
916
917\def\grph_rotate_box#1% {angle} \hbox/\vbox/\vtop
918  {\bgroup
919   \hbox\bgroup % compatibility hack
920     \edef\p_rotation_rotation{#1}%
921     \dowithnextboxcs\grph_rotate_finish_box}
922
923\def\grph_rotate_finish_box
924  {\c_grph_rotate_not_fit\conditionalfalse      % this is the same as broad but
925   \c_grph_rotate_center\conditionalfalse       % without the following grab as
926   \c_grph_rotate_obey_depth\conditionalfalse   % we call finish directly
927   \grph_rotate_finish_indeed
928   \egroup
929   \egroup}
930
931\def\grph_rotate_finish_indeed
932  {\naturalhpack\bgroup
933     \ifempty\p_rotation_rotation
934       \grph_rotate_finish_nop
935     \else
936       \grph_rotate_finish_yes
937     \fi
938   \egroup}
939
940\def\grph_rotate_finish_nop
941  {\boxcursor\box\nextbox}
942
943\defcsname\??rotatepreset\v!left\endcsname
944  {\edef\p_rotation_rotation{90}}
945
946\defcsname\??rotatepreset\v!right\endcsname
947  {\edef\p_rotation_rotation{270}}
948
949\defcsname\??rotatepreset\v!inner\endcsname
950  {\signalrightpage
951   \doifelserightpage{\def\p_rotation_rotation{270}}{\def\p_rotation_rotation{90}}}
952
953\defcsname\??rotatepreset\v!outer\endcsname
954  {\signalrightpage
955   \doifelserightpage{\def\p_rotation_rotation{90}}{\def\p_rotation_rotation{270}}}
956
957\letcsname\??rotatepreset\v!default\endcsname\empty
958
959\def\grph_rotate_finish_yes
960  {\begincsname\??rotatepreset\p_rotation_rotation\endcsname
961   \setbox\nextbox\naturalvpack{\box\nextbox}% not really needed
962   \dontcomplain
963   \ifconditional\c_grph_rotate_center
964     \d_grph_rotate_saved_width \wd\nextbox
965     \d_grph_rotate_saved_height\ht\nextbox
966     \d_grph_rotate_saved_depth \dp\nextbox
967     \setbox\nextbox\naturalhpack{\hskip-.5\wd\nextbox\lower.5\ht\nextbox\box\nextbox}%
968     \smashbox\nextbox
969   \fi
970   %
971   \d_grph_rotate_width \wd\nextbox
972   \d_grph_rotate_height\ht\nextbox
973   \d_grph_rotate_depth \dp\nextbox
974   %
975   \setbox\nextbox\naturalvpack{\naturalhpack{\raise\dp\nextbox\box\nextbox}}% can we do without
976   %
977   \d_grph_rotate_used_height\ht\nextbox
978   %
979   \clf_analyzerotate % rather accurate
980     \p_rotation_rotation\space
981     \d_grph_rotate_width
982     \d_grph_rotate_height
983     \d_grph_rotate_depth
984     \d_grph_rotate_used_height
985     \c_grph_rotate_not_fit
986     \c_grph_rotate_obey_depth
987   \relax
988   %
989   \setbox\nextbox\naturalvpack to \d_grph_rotate_y_size
990     {\vfilll
991      \hcontainer to \d_grph_rotate_x_size
992        {\dostartrotation\p_rotation_rotation
993           \wd\nextbox\zeropoint
994           \ht\nextbox\zeropoint
995           \box\nextbox
996         \dostoprotation
997         \hfill}%
998      \kern\d_grph_rotate_y_position}%
999   %
1000   \setbox\nextbox\naturalhpack
1001     {\kern\dimexpr\d_grph_rotate_x_position+\d_grph_rotate_x_offset\relax
1002      \lower\d_grph_rotate_y_offset
1003      \box\nextbox}%
1004   %
1005   \ifconditional\c_grph_rotate_center
1006     \setbox\nextbox\naturalhpack{\hskip.5\d_grph_rotate_saved_width\lower-.5\d_grph_rotate_saved_height\box\nextbox}%
1007     \wd\nextbox\d_grph_rotate_saved_width
1008     \ht\nextbox\d_grph_rotate_saved_height
1009     \dp\nextbox\d_grph_rotate_saved_depth
1010   \else
1011     \wd\nextbox\d_grph_rotate_new_width
1012     \ht\nextbox\d_grph_rotate_new_height
1013     \dp\nextbox\d_grph_rotate_new_depth
1014   \fi
1015   %
1016   \boxcursor\box\nextbox}
1017
1018% \dostepwiserecurse{0}{360}{10}
1019%   {\startlinecorrection[blank]
1020%    \hbox
1021%      {\setuprotate[rotation=#1]%
1022%       \traceboxplacementtrue
1023%       \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=depth] {\ruledhbox{\bfb  (depth)}}}}%
1024%       \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=fit]   {\ruledhbox{\bfb    (fit)}}}}%
1025%       \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=broad] {\ruledhbox{\bfb  (broad)}}}}%
1026%       \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=normal]{\ruledhbox{\bfb (normal)}}}}%
1027%       \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=high]  {\ruledhbox{\bfb   (high)}}}}}
1028%    \stoplinecorrection}
1029
1030% \def\Test{\ruledhbox{%
1031%     \def\DemoX{\vl\kern.5\emwidth\vl}%
1032%     \kern\emwidth\ruledhpack{\green\rotate[rotation=20]  {\ruledhpack{\DemoX}}}%
1033%     \kern\emwidth\ruledhpack{\blue \rotate[rotation=0]   {\ruledhpack{\DemoX}}}%
1034%     \kern\emwidth\ruledhpack{\red  \rotate[rotation=-20] {\ruledhpack{\DemoX}}}%
1035%     \kern\emwidth\ruledhpack{\green\rotate[rotation=200] {\ruledhpack{\DemoX}}}%
1036%     \kern\emwidth\ruledhpack{\blue \rotate[rotation=180] {\ruledhpack{\DemoX}}}%
1037%     \kern\emwidth\ruledhpack{\red  \rotate[rotation=-200]{\ruledhpack{\DemoX}}}%
1038%     \kern\emwidth}}
1039
1040% \startTEXpage[offset=10pt,align=middle]
1041%     \setuprotate[location=fit]     \Test \par {\infofont\setstrut\strut fit}     \par
1042%     \setuprotate[location=depth]   \Test \par {\infofont\setstrut\strut depth}   \par
1043%     \setuprotate[location=broad]   \Test \par {\infofont\setstrut\strut broad}   \par
1044%     \setuprotate[location=high]    \Test \par {\infofont\setstrut\strut high}    \par
1045%     \setuprotate[location=middle]  \Test \par {\infofont\setstrut\strut middle}  \par
1046%     \setuprotate[location=default] \Test \par {\infofont\setstrut\strut default} \par
1047% \stopTEXpage
1048
1049\protect \endinput
1050