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