summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/grph-trf.mkiv
diff options
context:
space:
mode:
authorContext Git Mirror Bot <phg42.2a@gmail.com>2016-01-12 17:15:07 +0100
committerContext Git Mirror Bot <phg42.2a@gmail.com>2016-01-12 17:15:07 +0100
commit8d8d528d2ad52599f11250cfc567fea4f37f2a8b (patch)
tree94286bc131ef7d994f9432febaf03fe23d10eef8 /tex/context/base/mkiv/grph-trf.mkiv
parentf5aed2e51223c36c84c5f25a6cad238b2af59087 (diff)
downloadcontext-8d8d528d2ad52599f11250cfc567fea4f37f2a8b.tar.gz
2016-01-12 16:26:00
Diffstat (limited to 'tex/context/base/mkiv/grph-trf.mkiv')
-rw-r--r--tex/context/base/mkiv/grph-trf.mkiv1238
1 files changed, 1238 insertions, 0 deletions
diff --git a/tex/context/base/mkiv/grph-trf.mkiv b/tex/context/base/mkiv/grph-trf.mkiv
new file mode 100644
index 000000000..099efa114
--- /dev/null
+++ b/tex/context/base/mkiv/grph-trf.mkiv
@@ -0,0 +1,1238 @@
+%D \module
+%D [ file=grph-trf,
+%D version=2006.08.26, % overhaul/split of 1997.03.31 core-fig
+%D title=\CONTEXT\ Graphic Macros,
+%D subtitle=Transformations,
+%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.
+
+\writestatus{loading}{ConTeXt Graphic Macros / Transformations}
+
+\unprotect
+
+%D We probably use too many dimens as the width calculations can
+%D go away. Some of this is an inheritance of limited backends
+%D (some supported fractions, some 1000's, some dimentions) so
+%D we calculate all of them. Nowadays scaling is always available
+%D so we could simplify the code. On the other hand, we now get
+%D some extra values for free.
+%D
+%D We could move the calculations to \LUA\ and clean up this
+%D lot anyway. On the other hand, there is some danger of messing
+%D up so it has a real low priority.
+
+% local:
+
+\newdimen\d_grph_scale_x_size
+\newdimen\d_grph_scale_y_size
+\newdimen\d_grph_scale_x_offset
+\newdimen\d_grph_scale_y_offset
+
+\newdimen\d_grph_scale_h_size
+\newdimen\d_grph_scale_v_size
+
+\newconditional\c_grph_scale_done
+\newconditional\c_grph_scale_scaling_done
+\newconditional\c_grph_scale_limit_factors \settrue\c_grph_scale_limit_factors
+
+\newdimen\d_grph_scale_wd
+\newdimen\d_grph_scale_ht
+\newdimen\d_grph_scale_dp
+
+% global
+
+\newdimen\d_grph_scale_used_x_size
+\newdimen\d_grph_scale_used_y_size
+
+\newcount\c_grph_scale_used_x_scale
+\newcount\c_grph_scale_used_y_scale
+
+\let \m_grph_scale_used_x_scale\!!plusone
+\let \m_grph_scale_used_y_scale\!!plusone
+
+\newdimen\d_grph_scale_outer_v_size % we cannot manipulate any global vsize !
+
+% scratch:
+
+\let\m_grph_scale_temp \empty
+\let\m_grph_scale_temp_x\empty
+\let\m_grph_scale_temp_y\empty
+
+% public:
+
+\let\finalscaleboxxscale \!!plusone
+\let\finalscaleboxyscale \!!plusone
+\let\finalscaleboxwidth \!!zeropoint
+\let\finalscaleboxheight \!!zeropoint
+
+% we can let sx/sy win (first check)
+
+\installcorenamespace{scale}
+\installcorenamespace{scalegrid}
+\installcorenamespace{scalenorm}
+
+\installcommandhandler \??scale {scale} \??scale % we can have instances
+
+\setupscale
+ [\c!sx=\scaleparameter\c!s,
+ \c!sy=\scaleparameter\c!s,
+ \c!s=1,
+ %\c!scale=,
+ %\c!xscale=,
+ %\c!yscale=,
+ %\c!width=,
+ %\c!height=,
+ %\c!lines=,
+ %\c!factor=,
+ %\c!hfactor=,
+ %\c!wfactor=,
+ %\c!grid=,
+ %\c!equalwidth=,
+ %\c!equalheight=,
+ \c!maxwidth=\scaleparameter\c!width,
+ \c!maxheight=\scaleparameter\c!height]
+
+\unexpanded\def\scale{\dodoubleempty\grph_scale}
+
+% we could have: \freezeparameter\c!scale etc (less backtracking when used multiple)
+
+\def\grph_scale[#1][#2]%
+ {\bgroup
+ % this is quite common so we might make this a helper
+ \ifsecondargument
+ \edef\currentscale{#1}%
+ \setupcurrentscale[#2]%
+ \else\iffirstargument
+ \doifelseassignment{#1}
+ {\let\currentscale\empty
+ \setupcurrentscale[#1]}
+ {\edef\currentscale{#1}}%
+ \else
+ \let\currentscale\empty
+ \fi\fi
+ %
+ \dowithnextboxcs\grph_scale_finish\hbox}
+
+\def\grph_scale_finish
+ {% todo: p_scale_
+ \edef\p_scale {\scaleparameter\c!scale }%
+ \edef\p_xscale {\scaleparameter\c!xscale }%
+ \edef\p_yscale {\scaleparameter\c!yscale }%
+ \edef\p_width {\scaleparameter\c!width }%
+ \edef\p_height {\scaleparameter\c!height }%
+ \edef\p_depth {\scaleparameter\c!depth }%
+ \edef\p_lines {\scaleparameter\c!lines }%
+ \edef\p_factor {\scaleparameter\c!factor }%
+ \edef\p_hfactor {\scaleparameter\c!hfactor }%
+ \edef\p_wfactor {\scaleparameter\c!wfactor }%
+ % \edef\p_grid {\scaleparameter\c!grid }% used once
+ \edef\p_maxwidth {\scaleparameter\c!maxwidth }%
+ \edef\p_maxheight {\scaleparameter\c!maxheight }%
+ \edef\p_sx {\scaleparameter\c!sx }%
+ \edef\p_sy {\scaleparameter\c!sy }%
+ \edef\p_equalwidth {\scaleparameter\c!equalwidth }%
+ \edef\p_equalheight{\scaleparameter\c!equalheight}%
+ %
+ \d_grph_scale_dp\dp\nextbox
+ \ifx\p_depth\v!no \ifzeropt\d_grph_scale_dp \else
+ \setbox\nextbox\hpack{\raise\d_grph_scale_dp\box\nextbox}% new
+ \d_grph_scale_dp\dp\nextbox
+ \fi \fi
+ \d_grph_scale_wd\wd\nextbox
+ \d_grph_scale_ht\ht\nextbox
+ \d_grph_scale_dp\dp\nextbox
+ %
+ \global\let\finalscaleboxxscale \!!plusone
+ \global\let\finalscaleboxyscale \!!plusone
+ \xdef \finalscaleboxwidth {\the\d_grph_scale_wd}%
+ \xdef \finalscaleboxheight{\the\d_grph_scale_ht}%
+ %
+ \forgetall
+ \dontcomplain
+ %
+ \setfalse\c_grph_scale_done
+ \grph_scale_calculate
+ \ifconditional\c_grph_scale_done
+ \grph_scale_apply
+ \fi
+ \grph_scale_position
+ %
+ \box\nextbox
+ \egroup}
+
+\def\grph_scale_apply
+ {\d_grph_scale_wd\finalscaleboxxscale\d_grph_scale_wd
+ \d_grph_scale_ht\finalscaleboxyscale\d_grph_scale_ht
+ \d_grph_scale_dp\finalscaleboxyscale\d_grph_scale_dp
+ \setbox\nextbox\hpack
+ {\dostartscaling \finalscaleboxxscale \finalscaleboxyscale
+ \smashedbox\nextbox
+ \dostopscaling}%
+ \wd\nextbox\d_grph_scale_wd
+ \ht\nextbox\d_grph_scale_ht
+ \dp\nextbox\d_grph_scale_dp}
+
+\def\m_grph_scale_stamp_c{11}
+
+\def\grph_scale_calculate
+ {\ifdim\d_grph_scale_ht>\zeropoint \ifdim\d_grph_scale_wd>\zeropoint
+ \edef\m_grph_scale_stamp_a{\p_scale\p_xscale\p_yscale\p_factor\p_wfactor\p_hfactor\p_lines\p_width\p_height}%
+ \edef\m_grph_scale_stamp_b{\p_sx\p_sy}%
+ \ifx\m_grph_scale_stamp_a\empty
+ \ifx\m_grph_scale_stamp_b\m_grph_scale_stamp_c
+ % no scaling, don't change this (previous attempts failed anyway)
+ \insidefloattrue % trick
+ \grph_scale_calculations_yes
+ \else
+ \grph_scale_check_sx_sy
+ \grph_scale_calculations_nop
+ \fi
+ \else
+ \ifx\m_grph_scale_stamp_b\empty
+ % no need to check further
+ \else
+ \grph_scale_check_sx_sy
+ \fi
+ \grph_scale_calculations_yes
+ \fi
+ \fi \fi}
+
+\def\grph_scale_check_sx_sy
+ {\ifdim\p_sx\onepoint=\onepoint\else\edef\p_width {\the\dimexpr\p_sx\d_grph_scale_wd}\fi
+ \ifdim\p_sy\onepoint=\onepoint\else\edef\p_height{\the\dimexpr\p_sy\d_grph_scale_ht}\fi}
+
+\def\grph_scale_rounded#1%
+ {\expandafter\expandafter\expandafter\grph_scale_rounded_indeed
+ \expandafter\WITHOUTPT\the\dimexpr#1\points*100+32768\scaledpoint\relax.\relax}
+
+\def\grph_scale_rounded_indeed#1.#2\relax{#1}
+
+\def\grph_scale_calculations_nop
+ {\settrue\c_grph_scale_done
+ \xdef\finalscaleboxwidth {\the\dimexpr\p_sx\d_grph_scale_wd\relax}%
+ \xdef\finalscaleboxheight{\the\dimexpr\p_sy\d_grph_scale_ht\relax}%
+ \glet\finalscaleboxxscale\p_sx
+ \glet\finalscaleboxyscale\p_sy
+ \ifx\finalscaleboxxscale\empty\let\finalscaleboxxscale\!!plusone\fi
+ \ifx\finalscaleboxyscale\empty\let\finalscaleboxyscale\!!plusone\fi}
+
+\let\grph_scale_calculations_report\relax
+
+% \def\grph_scale_calculations_report
+% {\writestatus
+% {scaled}%
+% {wd:\finalscaleboxwidth,ht:\finalscaleboxheight
+% ,xscale:\finalscaleboxxscale,yscale:\finalscaleboxyscale}}
+
+% \def\grph_scale_calculations_yes
+% {\settrue\c_grph_scale_done
+% % initial values
+% \d_grph_scale_x_offset\zeropoint
+% \d_grph_scale_y_offset\zeropoint
+% \d_grph_scale_x_size \d_grph_scale_wd
+% \d_grph_scale_y_size \d_grph_scale_ht % alleen ht wordt geschaald!
+% % final values
+% \global\d_grph_scale_used_x_size \zeropoint % see note * (core-fig)
+% \global\d_grph_scale_used_y_size \zeropoint % see note * (core-fig)
+% \c_grph_scale_used_x_scale \plusone % see note * (core-fig)
+% \c_grph_scale_used_y_scale \plusone % see note * (core-fig)
+% \let\m_grph_scale_used_x_scale \!!plusone
+% \let\m_grph_scale_used_y_scale \!!plusone
+% % preparations
+% \setfalse\c_grph_scale_scaling_done
+% \grph_scale_check_parameters
+% % calculators
+% % beware, they operate in sequence, and calculate missing dimensions / messy
+% % grph_scale_by_nature % when? needed?
+% \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_factor \fi
+% \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_scale \fi
+% \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_dimension\fi
+% % used in actual scaling
+% \xdef\finalscaleboxwidth {\the\d_grph_scale_used_x_size}%
+% \xdef\finalscaleboxheight {\the\d_grph_scale_used_y_size}%
+% \xdef\finalscaleboxxscale {\luaexpr{\number\c_grph_scale_used_x_scale/1000}}%
+% \xdef\finalscaleboxyscale {\luaexpr{\number\c_grph_scale_used_y_scale/1000}}%
+% \grph_scale_calculations_report}
+
+\def\grph_scale_calculations_yes
+ {\settrue\c_grph_scale_done
+ % initial values
+ \d_grph_scale_x_offset\zeropoint
+ \d_grph_scale_y_offset\zeropoint
+ \d_grph_scale_x_size \d_grph_scale_wd
+ \d_grph_scale_y_size \d_grph_scale_ht % alleen ht wordt geschaald!
+ % final values
+ \global\d_grph_scale_used_x_size \zeropoint % see note * (core-fig)
+ \global\d_grph_scale_used_y_size \zeropoint % see note * (core-fig)
+ \c_grph_scale_used_x_scale \plusone % see note * (core-fig)
+ \c_grph_scale_used_y_scale \plusone % see note * (core-fig)
+ \let\m_grph_scale_used_x_scale \!!plusone
+ \let\m_grph_scale_used_y_scale \!!plusone
+ % preparations
+ \setfalse\c_grph_scale_scaling_done
+ \grph_scale_check_parameters
+ % calculators
+ % beware, they operate in sequence, and calculate missing dimensions / messy
+ % grph_scale_by_nature % when? needed?
+ \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_factor \fi
+ \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_scale \fi
+ \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_dimension\fi
+ % used in actual scaling
+ \xdef\finalscaleboxwidth {\the\d_grph_scale_used_x_size}%
+ \xdef\finalscaleboxheight {\the\d_grph_scale_used_y_size}%
+ \glet\finalscaleboxxscale \m_grph_scale_used_x_scale
+ \glet\finalscaleboxyscale \m_grph_scale_used_y_scale
+ \grph_scale_calculations_report}
+
+\setvalue{\??scalegrid\v!yes }{\getnoflines \d_grph_scale_used_y_size\edef\p_height{\the\noflines\lineheight}}
+\setvalue{\??scalegrid\v!height }{\getrawnoflines\d_grph_scale_used_y_size\edef\p_height{\the\dimexpr\noflines\lineheight+\strutdepth}}
+\setvalue{\??scalegrid\v!depth }{\getrawnoflines\d_grph_scale_used_y_size\edef\p_height{\the\dimexpr\noflines\lineheight-\strutdepth}}
+\setvalue{\??scalegrid\v!halfline}{\getrawnoflines\d_grph_scale_used_y_size\edef\p_height{\the\dimexpr\noflines\lineheight+.5\lineheight}}
+\setvalue{\??scalegrid\v!fit }{\getrawnoflines\d_grph_scale_used_y_size\edef\p_height{\the\noflines\lineheight}}
+\letvalue{\??scalegrid\empty }\donothing
+
+\def\grph_scale_check_parameters % resolve self referencing loops
+ {\ifx\p_maxwidth \empty\else \edef\p_maxwidth {\the\dimexpr\p_maxwidth }\fi
+ \ifx\p_maxheight\empty\else \edef\p_maxheight{\the\dimexpr\p_maxheight }\fi
+ \ifx\p_lines \empty\else \edef\p_height {\the\dimexpr\p_lines\lineheight}\fi
+ \csname\??scalegrid\scaleparameter\c!grid\endcsname}
+
+\def\grph_scale_by_nature % where ! ! ! ! !
+ {\ifx\p_width \empty\else \global\d_grph_scale_used_x_size\p_width \fi
+ \ifx\p_height\empty\else \global\d_grph_scale_used_y_size\p_height\fi
+ \ifx\p_scale \empty\else \c_grph_scale_used_x_scale\p_scale
+ \c_grph_scale_used_y_scale\p_scale \fi
+ \ifx\p_xscale\empty\else \c_grph_scale_used_x_scale\p_xscale\fi
+ \ifx\p_yscale\empty\else \c_grph_scale_used_y_scale\p_yscale\fi}
+
+% \defineexternalfigure[width-6][factor=auto,maxwidth=\textheight,maxheight=\textwidth]
+% \defineexternalfigure[width-7][factor=auto,maxwidth=\textwidth,maxheight=\textheight]
+% \placefigure{none}{\rotate[frame=on,offset=overlay]{\externalfigure[t:/sources/cow.pdf][width-6]}} \page
+% \placefigure{none}{\framed[frame=on,offset=overlay]{\externalfigure[t:/sources/cow.pdf][width-7]}}
+
+\def\m_grph_scale_factor_set{\v!max,\v!fit,\v!broad,\v!auto} % can be an \edef
+
+\def\grph_scale_by_factor
+ {\doifelseinset\p_factor\m_grph_scale_factor_set
+ \grph_scale_by_factor_a
+ {\doifelseinset\p_hfactor\m_grph_scale_factor_set
+ \grph_scale_by_factor_b
+ {\doifelseinset\p_wfactor\m_grph_scale_factor_set
+ \grph_scale_by_factor_c
+ \grph_scale_by_factor_d}}}
+
+% \def\grph_scale_by_factor_a
+% {\grph_scale_apply_size
+% \ifdim\d_grph_scale_x_size>\d_grph_scale_y_size
+% \grph_scale_calculate_norm \d_grph_scale_used_x_size\p_factor\p_maxwidth\hsize\d_grph_scale_h_size
+% \grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size
+% \else
+% \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
+% \grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size
+% \fi
+% \grph_scale_by_factor_indeed}
+%
+% \def\grph_scale_by_factor_b
+% {\grph_scale_apply_size
+% \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
+% \grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size
+% \grph_scale_by_factor_indeed}
+%
+% \def\grph_scale_by_factor_c
+% {\grph_scale_apply_size
+% \grph_scale_calculate_norm \d_grph_scale_used_x_size\p_wfactor\p_maxwidth\hsize\d_grph_scale_h_size
+% \grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size
+% \grph_scale_by_factor_indeed}
+%
+% \def\grph_scale_by_factor_d
+% {\grph_scale_calculate_norm\d_grph_scale_used_y_size\p_factor \p_height \textheight\d_grph_scale_v_size
+% \grph_scale_calculate_norm\d_grph_scale_used_y_size\p_hfactor\p_height \textheight\d_grph_scale_v_size
+% \grph_scale_calculate_norm\d_grph_scale_used_x_size\p_wfactor\p_width \hsize \hsize}
+
+\def\grph_scale_by_factor_a
+ {\grph_scale_apply_size
+ \ifdim\d_grph_scale_x_size>\d_grph_scale_y_size
+ \grph_scale_calculate_norm \d_grph_scale_used_x_size\p_factor\p_maxwidth\hsize\d_grph_scale_h_size
+ \grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size
+ \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size
+ \else
+ \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
+ \grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size
+ \fi
+ \grph_scale_by_factor_indeed}
+
+\def\grph_scale_by_factor_b
+ {\grph_scale_apply_size
+ \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
+ \grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size
+ \grph_scale_by_factor_indeed}
+
+\def\grph_scale_by_factor_c
+ {\grph_scale_apply_size
+ \grph_scale_calculate_norm \d_grph_scale_used_x_size\p_wfactor\p_maxwidth\hsize\d_grph_scale_h_size
+ \grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size
+ \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size
+ \grph_scale_by_factor_indeed}
+
+\def\grph_scale_by_factor_d
+ {\grph_scale_calculate_norm\d_grph_scale_used_y_size\p_factor \p_height \textheight\d_grph_scale_v_size
+ \grph_scale_calculate_norm\d_grph_scale_used_y_size\p_hfactor\p_height \textheight\d_grph_scale_v_size
+ \grph_scale_calculate_norm\d_grph_scale_used_x_size\p_wfactor\p_width \hsize \hsize}
+
+\def\grph_scale_by_factor_indeed
+ {\settrue\c_grph_scale_scaling_done
+ \ifconditional\c_grph_scale_limit_factors
+ \ifdim\d_grph_scale_used_x_size>\d_grph_scale_h_size
+ \global\d_grph_scale_used_y_size\zeropoint
+ \global\d_grph_scale_used_x_size\d_grph_scale_h_size
+ \else\ifdim\d_grph_scale_used_y_size>\d_grph_scale_v_size
+ \global\d_grph_scale_used_x_size\zeropoint
+ \global\d_grph_scale_used_y_size\d_grph_scale_v_size
+ \fi\fi
+ \fi
+ \grph_scale_by_dimension}
+
+% \def\grph_scale_by_scale
+% {\edef\m_grph_scale_temp{\p_scale\p_xscale\p_yscale}%
+% \ifx\m_grph_scale_temp\empty \else
+% \grph_scale_apply_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale\p_xscale
+% \grph_scale_apply_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale\p_yscale
+% \global\d_grph_scale_used_x_size\zeropoint
+% \global\d_grph_scale_used_y_size\zeropoint
+% \ifx\p_maxwidth\empty
+% \ifx\p_maxheight\empty
+% \else
+% \ifdim\d_grph_scale_y_size>\p_maxheight\relax
+% \global\d_grph_scale_used_y_size\p_maxheight
+% \fi
+% \fi
+% \else
+% \ifdim\d_grph_scale_x_size>\p_maxwidth\relax
+% \global\d_grph_scale_used_x_size\p_maxwidth
+% \fi
+% \fi
+% \fi}
+
+\def\grph_scale_by_scale
+ {\edef\m_grph_scale_temp{\p_scale\p_xscale\p_yscale}%
+ \ifx\m_grph_scale_temp\empty \else
+ \grph_scale_apply_scale\m_grph_scale_used_x_scale\p_xscale
+ \grph_scale_apply_scale\m_grph_scale_used_y_scale\p_yscale
+ % \global\d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size\relax % no global needed here
+ % \global\d_grph_scale_used_y_size\m_grph_scale_used_y_scale\d_grph_scale_y_size\relax % no global needed here
+ % wrong: we need to recalculate the scale
+ \global\d_grph_scale_used_x_size\zeropoint
+ \global\d_grph_scale_used_y_size\zeropoint
+ %
+ \ifx\p_maxwidth\empty
+ \ifx\p_maxheight\empty
+ \else
+ \ifdim\d_grph_scale_y_size>\p_maxheight\relax
+ \global\d_grph_scale_used_y_size\p_maxheight
+ \fi
+ \fi
+ \else
+ \ifdim\d_grph_scale_x_size>\p_maxwidth\relax
+ \global\d_grph_scale_used_x_size\p_maxwidth
+ \fi
+ \fi
+ \fi}
+
+\def\grph_scale_by_dimension
+ {\ifdim\d_grph_scale_used_x_size>\zeropoint
+ \ifdim\d_grph_scale_used_y_size>\zeropoint
+ \grph_scale_by_dimension_a
+ \else
+ \grph_scale_by_dimension_b
+ \fi
+ \else
+ \ifdim\d_grph_scale_used_y_size>\zeropoint
+ \grph_scale_by_dimension_c
+ \else
+ \grph_scale_by_dimension_d
+ \fi
+ \fi}
+
+% \def\grph_scale_by_dimension_a
+% {\grph_scale_by_dimension_indeed
+% {\grph_scale_calculate_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale
+% \grph_scale_calculate_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale}%
+% {\grph_scale_calculate_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale
+% \grph_scale_calculate_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale}%
+% {\grph_scale_calculate_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale
+% \grph_scale_calculate_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale}}
+%
+% \def\grph_scale_by_dimension_b
+% {\grph_scale_by_dimension_indeed
+% {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size}%
+% {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size}%
+% {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size}}
+%
+% \def\grph_scale_by_dimension_c
+% {\grph_scale_by_dimension_indeed
+% {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size}%
+% {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size}%
+% {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size}}
+%
+% \def\grph_scale_by_dimension_d
+% {\grph_scale_by_dimension_indeed
+% {\grph_scale_apply_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale\p_xscale
+% \grph_scale_apply_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale\p_yscale}%
+% {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size}%
+% {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size}}
+
+\def\grph_scale_by_dimension_a
+ {\grph_scale_by_dimension_indeed
+ {\grph_scale_calculate_scale\m_grph_scale_used_y_scale\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \grph_scale_calculate_scale\m_grph_scale_used_x_scale\d_grph_scale_used_x_size\d_grph_scale_x_size}%
+ {\grph_scale_calculate_scale\m_grph_scale_used_y_scale\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \grph_scale_calculate_scale\m_grph_scale_used_x_scale\d_grph_scale_used_x_size\d_grph_scale_x_size}%
+ {\grph_scale_calculate_scale\m_grph_scale_used_y_scale\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \grph_scale_calculate_scale\m_grph_scale_used_x_scale\d_grph_scale_used_x_size\d_grph_scale_x_size}}
+
+\def\grph_scale_by_dimension_b
+ {\grph_scale_by_dimension_indeed
+ {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size
+ \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size}%
+ {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size
+ \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size}%
+ {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size
+ \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size}}
+
+\def\grph_scale_by_dimension_c
+ {\grph_scale_by_dimension_indeed % weird .. three same cases
+ {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size}%
+ {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size}%
+ {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size}}
+
+\def\grph_scale_by_dimension_d
+ {\grph_scale_by_dimension_indeed
+ {\grph_scale_apply_scale\m_grph_scale_used_x_scale\p_xscale
+ \grph_scale_apply_scale\m_grph_scale_used_y_scale\p_yscale
+ \global\d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size
+ \global\d_grph_scale_used_y_size\m_grph_scale_used_y_scale\d_grph_scale_y_size}%
+ {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size
+ \d_grph_scale_used_y_size\m_grph_scale_used_x_scale\d_grph_scale_y_size}%
+ {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \d_grph_scale_used_x_size\m_grph_scale_used_x_scale\d_grph_scale_x_size}}
+
+\def\grph_scale_by_dimension_indeed#1#2#3%
+ {#1\relax
+ \ifx\p_maxwidth\empty \else
+ \ifdim\d_grph_scale_used_x_size>\p_maxwidth\relax
+ \global\d_grph_scale_used_x_size\p_maxwidth
+ #2\relax
+ \fi
+ \fi
+ \ifx\p_maxheight\empty \else
+ \ifdim\d_grph_scale_used_y_size>\p_maxheight\relax
+ \global\d_grph_scale_used_y_size\p_maxheight
+ #3\relax
+ \fi
+ \fi}
+
+\def\grph_scale_calculate_norm#1#2% todo: swap 1 and 2 and pass one less
+ {\csname\??scalenorm\ifcsname\??scalenorm#2\endcsname#2\else\s!unknown\fi\endcsname#1#2}
+
+\setvalue{\??scalenorm\v!max }#1#2#3#4#5{\global#1#4}
+\setvalue{\??scalenorm\v!fit }#1#2#3#4#5{\global#1#5}
+\setvalue{\??scalenorm\v!broad }#1#2#3#4#5{\global#1\dimexpr#5-4\externalfigureparameter\c!bodyfont\relax}
+\setvalue{\??scalenorm\s!unknown}#1#2#3#4#5{\global#1\dimexpr#2\dimexpr\externalfigureparameter\c!bodyfont/10\relax\relax} % brr ex
+\setvalue{\??scalenorm\v!auto }#1#2#3#4#5{\ifx#3\empty\else\global#1#3\fi}
+\setvalue{\??scalenorm\empty }#1#2#3#4#5{\ifx#3\empty\else\global#1#3\fi}
+\setvalue{\??scalenorm\s!default}#1#2#3#4#5{\ifx#3\empty\else\global#1#3\fi}
+
+% \def\grph_scale_calculate_scales#1#2#3#4%
+% {\scratchdimen\dimexpr#1/\dimexpr#2/\plusthousand\relax\relax
+% \c_grph_scale_used_x_scale\scratchdimen
+% \c_grph_scale_used_y_scale\scratchdimen
+% %\writestatus{!!!!}{\the#3/\luaexpr{\number\dimexpr#1\relax/\number\dimexpr#2/1000}}%
+% #3\dimexpr\c_grph_scale_used_x_scale\dimexpr#4/\plusthousand\relax\relax}
+%
+% \def\grph_scale_calculate_scale#1#2#3%
+% {#3\dimexpr#1/\dimexpr#2/\plusthousand\relax\relax}
+%
+% \def\grph_scale_apply_scale#1#2#3#4% #4 = parameter / scale can be empty
+% {\ifcase0#4\relax
+% \ifcase0\p_scale\relax
+% #3=\plusthousand
+% \else
+% #3=\p_scale
+% \fi
+% \else
+% #3=#4%
+% \fi
+% \relax % important ! still ?
+% \global#1\ifnum#3=\plusthousand#2\else\dimexpr#3\dimexpr#2/\plusthousand\relax\relax\fi
+% \relax}
+
+\def\grph_scale_calculate_scales#1#2%
+ {\edef\m_grph_scale_used_x_scale{\luaexpr{\number#1/\number#2}}%
+ \let\m_grph_scale_used_y_scale\m_grph_scale_used_x_scale}
+
+% we could inline this:
+%
+% \grph_scale_calculate_scale\m_grph_scale_used_x_scale#1#2
+% \let\m_grph_scale_used_y_scale\m_grph_scale_used_x_scale
+
+\def\grph_scale_calculate_scale#1#2#3%
+ {\edef#1{\luaexpr{\number#2/\number#3}}}
+
+\def\grph_scale_apply_scale#1#2% #1 = parameter / scale can be empty
+ {\edef#1{\luaexpr
+ {\number
+ \ifx#2\empty
+ \ifx \p_scale \empty \plusthousand \else
+ \ifnum\p_scale=\zerocount \plusthousand \else
+ \p_scale \fi\fi
+ \else\ifnum#2=\zerocount
+ \ifx \p_scale \empty \plusthousand \else
+ \ifnum\p_scale=\zerocount \plusthousand \else
+ \p_scale \fi\fi
+ \else
+ #2%
+ \fi\fi
+ /1000}}}
+
+\def\grph_scale_apply_size
+ {\ifx\p_maxheight\empty
+ \d_grph_scale_outer_v_size\textheight
+ \ifinner
+ \d_grph_scale_outer_v_size \vsize % \textheight =\vsize
+ \scratchdimen\vsize % \scratchdimen=\textheight
+ \else\ifinsidefloat
+ \d_grph_scale_outer_v_size \vsize % \textheight =\vsize
+ \scratchdimen\vsize % \scratchdimen=\textheight
+ \else\ifinpagebody
+ \d_grph_scale_outer_v_size \vsize % \textheight =\vsize
+ \scratchdimen\vsize % \scratchdimen=\textheight
+ \else % hm, there should be an option to force this
+ \ifdim\pagegoal<\maxdimen
+ \ifdim\pagetotal<\pagegoal
+ \scratchdimen\dimexpr\pagegoal-\pagetotal\relax
+ \else
+ \scratchdimen\d_grph_scale_outer_v_size % \textheight
+ \fi
+ \else
+ \scratchdimen\d_grph_scale_outer_v_size % \textheight
+ \fi
+ \fi\fi\fi
+ \else
+ \scratchdimen\p_maxheight
+ \d_grph_scale_outer_v_size\scratchdimen
+ \fi
+ \ifx\p_height\empty
+ \d_grph_scale_v_size\scratchdimen
+ \else
+ \d_grph_scale_v_size\p_height
+ \fi
+ \ifx\p_width\empty
+ \d_grph_scale_h_size\hsize
+ \else
+ \d_grph_scale_h_size\p_width
+ \fi}
+
+%\def\grph_scale_convert_large_scale#1#2#3#4%
+% {\scratchdimen#1\relax
+% \ifnum#3=\plusthousand
+% % == scale 1
+% \else
+% % better 1000 100 10 ranges, evt round 2sp
+% \divide\scratchdimen \plusthousand
+% \multiply\scratchdimen #3\relax
+% \fi
+% \scratchdimen-\scratchdimen % beter hier - dan in driver
+% \edef#2{\the\scratchdimen}%
+% \scratchcounter#3\relax
+% \ifnum\scratchcounter>\plustenthousand
+% \divide\scratchcounter\plusten
+% \scratchdimen\the\scratchcounter\points % \the ?
+% \else
+% \scratchdimen\the\scratchcounter\points % \the ?
+% \divide\scratchdimen\plusten
+% \fi
+% \edef#4{\withoutpt\the\scratchdimen}}
+%
+% \def\grph_scale_convert_large_scale#1#2#3#4% less overflow
+% {\edef#2{\ifnum#3=\plusthousand-\the\dimexpr#1\else\luaexpr{-\number#3*\number\dimexpr#1/1000}sp\fi}%
+% \edef#4{\luaexpr{\number#3/10}}}
+
+% \startcombination
+% {\externalfigure[cow.pdf] [frame=on,height=3cm,equalwidth=6cm]} {a cow}
+% {\externalfigure[mill.png][frame=on,height=3cm,equalwidth=6cm]} {a mill}
+% \stopcombination
+
+\def\grph_scale_position
+ {\ifx\p_equalwidth\empty \else
+ \scratchdimen\p_equalwidth\relax
+ \ifdim\d_grph_scale_wd<\scratchdimen
+ \setbox\nextbox\hpack to \scratchdimen{\hss\box\nextbox\hss}%
+ \fi
+ \fi
+ \ifx\p_equalheight\empty \else
+ \scratchdimen\p_equalheight\relax
+ \ifdim\d_grph_scale_ht<\scratchdimen
+ \setbox\nextbox\vpack to \scratchdimen{\vss\box\nextbox\vss}%
+ \fi
+ \fi}
+
+\unexpanded\def\fastscale#1%
+ {\ifnum#1=1000\relax
+ \expandafter\grph_scale_fast_nop
+ \else
+ \expandafter\grph_scale_fast_yes
+ \fi{#1}}
+
+\def\grph_scale_fast_nop#1%
+ {\hbox}
+
+\def\grph_scale_fast_yes#1%
+ {\edef\finalscaleboxxscale{\withoutpt\the\dimexpr#1\onepoint/1000\relax}% brrr
+ \let\finalscaleboxyscale\finalscaleboxxscale
+ \dowithnextboxcs\grph_scale_fast_finish\hbox}
+
+\def\grph_scale_fast_finish
+ {\grph_scale_apply
+ \box\nextbox
+ \endgroup}
+
+\unexpanded\def\fastsxsy#1#2%
+ {\bgroup
+ \edef\p_sx{#1}%
+ \edef\p_sy{#2}%
+ \dowithnextboxcs\grph_scale_fast_sx_xy_finish\hbox}
+
+\def\grph_scale_fast_sx_xy_finish
+ {\grph_scale_check_sx_sy
+ \grph_scale_calculations_nop
+ \grph_scale_apply
+ \box\nextbox
+ \egroup}
+
+%D \macros
+%D {clip, setupclipping}
+%D
+%D Although related to figures, clipping can be applied to
+%D arbitrary content. We can use \METAPOST\ to provide a non
+%D rectangular clipping path.
+%D
+%D \starttyping
+%D \startMPclip{fun}
+%D clip currentpicture to fullcircle
+%D shifted (.5,.5) xscaled \width yscaled \height ;
+%D \stopMPclip
+%D \stoptyping
+%D
+%D We get a rectangular piece of the figure when we say:
+%D
+%D \starttyping
+%D \clip[x=2,y=1]{\externalfigure[photo]}
+%D \stoptyping
+%D
+%D When we want to clip to the oval we defined a few lines ago,
+%D we say:
+%D
+%D \starttyping
+%D \clip[nx=1,ny=1,x=1,y=1,mp=fun]{\externalfigure[photo]}
+%D \stoptyping
+%D
+%D The general characteristics of clipping can be set up with
+%D
+%D \showsetup{setupclipping}
+
+\installcorenamespace{clipping}
+
+\installdirectcommandhandler \??clipping {clipping}
+
+\unexpanded\def\clip
+ {\dosingleempty\grph_clip}
+
+\def\grph_clip[#1]% nb top->bottom left->right
+ {\bgroup
+ \iffirstargument
+ \setupcurrentclipping[#1]%
+ \fi
+ \dowithnextboxcs\grph_clip_finish\hbox}
+
+\def\grph_clip_finish
+ {\doifelse{\clippingparameter\c!state}\v!start
+ \grph_clip_yes_finish
+ \grph_clip_nop_finish}
+
+% \def\grph_clip_yes_finish
+% {\ifdim\@@cpwidth>\zeropoint
+% \!!dimena\@@cpwidth
+% \!!dimenc\@@cphoffset
+% \else
+% \!!dimena\wd\nextbox
+% \divide\!!dimena \@@cpnx
+% \!!dimenc\@@cpx\!!dimena
+% \advance\!!dimenc -\!!dimena
+% \!!dimena\@@cpsx\!!dimena
+% \fi
+% \relax % sure
+% \ifdim\@@cpheight>\zeropoint
+% \!!dimenb\@@cpheight
+% \!!dimend\ht\nextbox
+% \advance\!!dimend -\@@cpvoffset
+% \advance\!!dimend -\!!dimenb
+% \else
+% \!!dimenb\ht\nextbox
+% \divide\!!dimenb \@@cpny
+% \!!dimend-\@@cpy\!!dimenb
+% \advance\!!dimend -\@@cpsy\!!dimenb
+% \advance\!!dimend \!!dimenb
+% \!!dimenb\@@cpsy\!!dimenb
+% \advance\!!dimend \ht\nextbox % dimend !
+% \fi
+% \setbox\nextbox\hbox % old
+% {\advance\!!dimenc -\@@cpleftoffset % new !
+% \advance\!!dimend -\@@cpbottomoffset % new ! % - added
+% \hskip-\!!dimenc\lower\!!dimend\box\nextbox}% old
+% \wd\nextbox\zeropoint
+% \ht\nextbox\zeropoint
+% \dp\nextbox\zeropoint
+% \setbox\nextbox\hbox
+% {\advance\!!dimena \@@cpleftoffset % new !
+% \advance\!!dimena \@@cprightoffset % new !
+% \advance\!!dimenb \@@cpbottomoffset % new !
+% \advance\!!dimenb \@@cptopoffset % new !
+% \dostartclipping\@@cpmp\!!dimena\!!dimenb % old
+% \box\nextbox
+% \dostopclipping}%
+% \setbox\nextbox\hbox % new !
+% {\!!dimena-\@@cpleftoffset % new !
+% \!!dimenb \@@cpbottomoffset % new ! % - removed
+% \hskip\!!dimena\lower\!!dimenb\box\nextbox}% new !
+% \wd\nextbox\!!dimena
+% \ht\nextbox\!!dimenb
+% \dp\nextbox\zeropoint
+% \box\nextbox
+% \egroup}
+
+\def\grph_clip_yes_finish
+ {\ifdim\clippingparameter\c!width>\zeropoint
+ \scratchwidth \clippingparameter\c!width
+ \scratchxoffset\clippingparameter\c!hoffset
+ \else
+ \scratchwidth\dimexpr\wd\nextbox/\clippingparameter\c!nx\relax
+ \scratchxoffset\dimexpr\clippingparameter\c!x\scratchwidth-\scratchwidth\relax
+ \scratchwidth\clippingparameter\c!sx\scratchwidth
+ \fi
+ \relax % sure
+ \ifdim\clippingparameter\c!height>\zeropoint
+ \scratchheight\clippingparameter\c!height
+ \scratchyoffset\dimexpr\ht\nextbox-\clippingparameter\c!voffset-\scratchheight\relax
+ \else
+ \scratchheight\dimexpr\ht\nextbox/\clippingparameter\c!ny\relax
+ \scratchyoffset\dimexpr-\clippingparameter\c!y\scratchheight-\clippingparameter\c!sy\scratchheight+\scratchheight\relax
+ \scratchheight\clippingparameter\c!sy\scratchheight
+ \advance\scratchyoffset \ht\nextbox
+ \fi
+ \setbox\nextbox\hpack
+ {\advance\scratchxoffset -\clippingparameter\c!leftoffset \relax
+ \advance\scratchyoffset -\clippingparameter\c!bottomoffset\relax
+ \hskip-\scratchxoffset
+ \lower\scratchyoffset
+ \box\nextbox}%
+ \wd\nextbox\zeropoint
+ \ht\nextbox\zeropoint
+ \dp\nextbox\zeropoint
+ \setbox\nextbox\hpack
+ {\advance\scratchwidth \dimexpr\clippingparameter\c!leftoffset +\clippingparameter\c!rightoffset\relax
+ \advance\scratchheight\dimexpr\clippingparameter\c!bottomoffset+\clippingparameter\c!topoffset \relax
+ \dostartclipping{\clippingparameter\c!mp}\scratchwidth\scratchheight
+ \box\nextbox
+ \dostopclipping}%
+ \setbox\nextbox\hpack
+ {\hskip-\clippingparameter\c!leftoffset
+ \lower \clippingparameter\c!bottomoffset
+ \box\nextbox}%
+ \wd\nextbox\scratchwidth
+ \ht\nextbox\scratchheight
+ \dp\nextbox\zeropoint
+ \box\nextbox
+ \egroup}
+
+\def\grph_clip_nop_finish
+ {\box\nextbox
+ \egroup}
+
+\setupclipping
+ [\c!state=\v!start,
+ \c!n=\plusone, % was \plustwo
+ \c!nx=\clippingparameter\c!n,\c!x=\plusone,\c!sx=\plusone,
+ \c!ny=\clippingparameter\c!n,\c!y=\plusone,\c!sy=\plusone,
+ \c!width=\zeropoint,
+ \c!height=\zeropoint,
+ \c!hoffset=\zeropoint,
+ \c!voffset=\zeropoint,
+ \c!offset=\zeropoint,
+ \c!leftoffset=\clippingparameter\c!offset,
+ \c!rightoffset=\clippingparameter\c!offset,
+ \c!topoffset=\clippingparameter\c!offset,
+ \c!bottomoffset=\clippingparameter\c!offset,
+ \c!mp=]
+
+%D \startbuffer
+%D \startuseMPgraphic{test}
+%D path p ; p := fullcircle scaled 4cm ;
+%D draw p withpen pencircle scaled 1cm ;
+%D setbounds currentpicture to boundingbox p ;
+%D \stopuseMPgraphic
+%D
+%D \hbox to \hsize \bgroup
+%D \hss
+%D \ruledhbox{\useMPgraphic{test}}%
+%D \hss
+%D \ruledhbox{\clip{\useMPgraphic{test}}}%
+%D \hss
+%D \egroup
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D Mirroring.
+
+\unexpanded\def\mirror
+ {\bgroup
+ \dowithnextboxcs\grph_mirror_finish\hbox}
+
+\def\grph_mirror_finish
+ {\scratchdimen\wd\nextbox
+ % better use an hbox (if no \forgetall, leftskip etc may creep in)
+ %\setbox\nextbox\vbox{\forgetall\dostartmirroring\hskip-\wd\nextbox\box\nextbox\dostopmirroring}%
+ \setbox\nextbox\hpack{\dostartmirroring\hskip-\wd\nextbox\box\nextbox\dostopmirroring}%
+ \wd\nextbox\scratchdimen
+ \box\nextbox
+ \egroup}
+
+%D A couple of examples, demonstrating how the depth is
+%D taken care of:
+%D
+%D \startbuffer
+%D test\rotate[frame=on, rotation=0] {gans}%
+%D test\rotate[frame=on, rotation=90] {gans}%
+%D test\rotate[frame=on, rotation=180]{gans}%
+%D test\rotate[frame=on, rotation=270]{gans}%
+%D test
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+% When we rotate over arbitrary angles, we need to relocate the
+% resulting box because rotation brings that box onto the negative
+% axis. The calculations (mostly sin and cosine) need to be tuned for
+% the way a box is packages (i.e. the refence point). A typical example
+% of drawing, scribbling, and going back to the days of school math.
+%
+% We do a bit more calculations than needed, simply because that way
+% it's easier to debug the code.
+
+% Cleanup in progress ... todo: less boxing
+
+\installcorenamespace {rotate}
+\installcorenamespace {rotatelocation}
+\installcorenamespace {rotatepreset}
+
+% we can alias these to \d_layers-* to save some dimens or maybe have a generic
+% set of scratch variables
+
+% maybe just \rotation_...
+
+\newdimen\d_grph_rotate_x_size
+\newdimen\d_grph_rotate_y_size
+\newdimen\d_grph_rotate_x_offset
+\newdimen\d_grph_rotate_y_offset
+\newdimen\d_grph_rotate_x_position
+\newdimen\d_grph_rotate_y_position
+
+\newdimen\d_grph_rotate_used_height
+
+\let\d_grph_rotate_width \!!widtha
+\let\d_grph_rotate_height\!!heighta
+\let\d_grph_rotate_depth \!!deptha
+
+\let\d_grph_rotate_saved_width \!!widthb
+\let\d_grph_rotate_saved_height\!!heightb
+\let\d_grph_rotate_saved_depth \!!depthb
+
+\newconditional\c_grph_rotate_obey_depth
+\newconditional\c_grph_rotate_not_fit
+\newconditional\c_grph_rotate_center
+
+\installframedcommandhandler \??rotate {rotate} \??rotate
+
+\setuprotate
+ [\c!rotation=90,
+ \c!location=\v!normal,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off]
+
+\let\p_rotation_location\empty
+\let\p_rotation_rotation\empty
+
+\unexpanded\def\rotate % \bgroup: \rotate kan argument zijn
+ {\bgroup
+ \dosingleempty\grph_rotate}
+
+\def\grph_rotate[#1]%
+ {\iffirstargument
+ \setupcurrentrotate[#1]%
+ \fi
+ \edef\p_rotation_location{\rotateparameter\c!location}%
+ \edef\p_rotation_rotation{\rotateparameter\c!rotation}%
+ \csname\??rotatelocation
+ \ifcsname\??rotatelocation\p_rotation_location\endcsname\p_rotation_location\else\v!default\fi
+ \endcsname}
+
+\def\grph_rotate_framed
+ {\resetrotateparameter\c!location
+ \dowithnextboxcs\grph_rotate_finish\vbox
+ \inheritedrotateframed}
+
+\def\grph_rotate_normal
+ {\dowithnextboxcs\grph_rotate_finish\vbox}
+
+\def\grph_rotate_finish
+ {\grph_rotate_finish_indeed
+ \egroup}
+
+\setvalue{\??rotatelocation\v!depth}%
+ {\setfalse\c_grph_rotate_not_fit
+ \setfalse\c_grph_rotate_center
+ \settrue \c_grph_rotate_obey_depth
+ \grph_rotate_normal}
+
+\setvalue{\??rotatelocation\v!fit}%
+ {\settrue \c_grph_rotate_not_fit
+ \setfalse\c_grph_rotate_center
+ \settrue \c_grph_rotate_obey_depth
+ \grph_rotate_normal}
+
+\setvalue{\??rotatelocation\v!broad}%
+ {\setfalse\c_grph_rotate_not_fit
+ \setfalse\c_grph_rotate_center
+ \setfalse\c_grph_rotate_obey_depth
+ \grph_rotate_normal}
+
+\setvalue{\??rotatelocation\v!high}%
+ {\setfalse\c_grph_rotate_not_fit
+ \setfalse\c_grph_rotate_center
+ \setfalse\c_grph_rotate_obey_depth
+ \grph_rotate_framed}
+
+\setvalue{\??rotatelocation\v!middle}%
+ {\setfalse\c_grph_rotate_not_fit
+ \settrue \c_grph_rotate_center
+ \setfalse\c_grph_rotate_obey_depth % hm, depth ?
+ \grph_rotate_normal}
+
+\setvalue{\??rotatelocation\v!default}%
+ {\setfalse\c_grph_rotate_not_fit
+ \setfalse\c_grph_rotate_center
+ \settrue \c_grph_rotate_obey_depth
+ \grph_rotate_framed}
+
+\unexpanded\def\dorotatebox#1% {angle} \hbox/\vbox/\vtop % a fast low level one
+ {\ifcase#1\relax
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\grph_rotate_box
+ \fi{#1}}
+
+\def\grph_rotate_box#1% {angle} \hbox/\vbox/\vtop
+ {\bgroup
+ \hbox\bgroup % compatibility hack
+ \edef\p_rotation_rotation{#1}%
+ \dowithnextboxcs\grph_rotate_finish_box}
+
+\def\grph_rotate_finish_box
+ {\setfalse\c_grph_rotate_not_fit % this is the same as broad but
+ \setfalse\c_grph_rotate_center % without the following grab as
+ \setfalse\c_grph_rotate_obey_depth % we call finish directly
+ \grph_rotate_finish_indeed
+ \egroup
+ \egroup}
+
+\def\grph_rotate_finish_indeed
+ {\hbox\bgroup
+ \ifx\p_rotation_rotation\empty
+ \grph_rotate_finish_nop
+ \else
+ \grph_rotate_finish_yes
+ \fi
+ \egroup}
+
+\def\grph_rotate_finish_nop
+ {\boxcursor\box\nextbox}
+
+\setvalue{\??rotatepreset\v!left}%
+ {\edef\p_rotation_rotation{\doifelseoddpage{90}{270}}}
+
+\setvalue{\??rotatepreset\v!right}%
+ {\edef\p_rotation_rotation{\doifelseoddpage{270}{90}}}
+
+\setvalue{\??rotatepreset\v!inner}%
+ {\signalrightpage
+ \doifelserightpage{\def\p_rotation_rotation{270}}{\def\p_rotation_rotation{90}}}
+
+\setvalue{\??rotatepreset\v!outer}%
+ {\signalrightpage
+ \doifelserightpage{\def\p_rotation_rotation{90}}{\def\p_rotation_rotation{270}}}
+
+\setvalue{\??rotatepreset\v!default}%
+ {\edef\p_rotation_rotation{\realnumber{\p_rotation_rotation}}}% get rid of leading zeros and spaces
+
+\def\grph_rotate_finish_yes
+ {\csname\??rotatepreset
+ \ifcsname\??rotatepreset\p_rotation_rotation\endcsname\p_rotation_rotation\else\v!default\fi
+ \endcsname
+ \setbox\nextbox\vpack{\box\nextbox}% not really needed
+ \dontcomplain
+ \ifconditional\c_grph_rotate_center
+ \d_grph_rotate_saved_width \wd\nextbox
+ \d_grph_rotate_saved_height\ht\nextbox
+ \d_grph_rotate_saved_depth \dp\nextbox
+ \setbox\nextbox\vpack{\vskip.5\ht\nextbox\hskip-.5\wd\nextbox\box\nextbox}%
+ \smashbox\nextbox
+ \fi
+ \d_grph_rotate_width \wd\nextbox
+ \d_grph_rotate_height\ht\nextbox
+ \d_grph_rotate_depth \dp\nextbox
+ \setbox\nextbox\vpack{\hpack{\raise\dp\nextbox\box\nextbox}}%
+ \d_grph_rotate_used_height \ht\nextbox
+ % much of the next happens in lua (all the sin and cos) so we can do that in
+ % one go if needed
+ \setcalculatedcos\cos\p_rotation_rotation
+ \setcalculatedsin\sin\p_rotation_rotation
+ \ifdim\sin\points>\zeropoint
+ \ifdim\cos\points>\zeropoint
+ \grph_rotate_calculate_a
+ \grph_rotate_apply
+ \else
+ \grph_rotate_calculate_b
+ \grph_rotate_apply
+ \wd\nextbox\ifconditional\c_grph_rotate_not_fit\sin\d_grph_rotate_depth\else\d_grph_rotate_x_size\fi
+ \fi
+ \else
+ \ifdim\cos\points<\zeropoint
+ \grph_rotate_calculate_c
+ \grph_rotate_apply
+ \wd\nextbox\ifconditional\c_grph_rotate_not_fit\negated\sin\d_grph_rotate_height\else\d_grph_rotate_x_size\fi
+ \else\ifdim\sin\points=\zeropoint
+ \grph_rotate_calculate_d
+ \grph_rotate_apply
+ % no wd ?
+ \else
+ \grph_rotate_calculate_e
+ \grph_rotate_apply
+ \wd\nextbox\ifconditional\c_grph_rotate_not_fit\negated\sin\d_grph_rotate_height\else\d_grph_rotate_x_size\fi
+ \fi\fi
+ \fi
+ \ifconditional\c_grph_rotate_center
+ \setbox\nextbox\vpack{\vskip-.5\d_grph_rotate_saved_height\hskip.5\d_grph_rotate_saved_height\box\nextbox}%
+ \wd\nextbox\d_grph_rotate_saved_width
+ \ht\nextbox\d_grph_rotate_saved_height
+ \dp\nextbox\d_grph_rotate_saved_depth
+ \fi
+ \boxcursor\box\nextbox}
+
+\def\grph_rotate_calculate_a
+ {\d_grph_rotate_x_size\dimexpr\cos\d_grph_rotate_width+\sin\d_grph_rotate_used_height\relax
+ \d_grph_rotate_y_size\dimexpr\sin\d_grph_rotate_width+\cos\d_grph_rotate_used_height\relax
+ \d_grph_rotate_x_position\zeropoint
+ \d_grph_rotate_y_position\cos\d_grph_rotate_used_height
+ \ifconditional\c_grph_rotate_not_fit
+ \d_grph_rotate_x_offset\dimexpr\negated\sin\d_grph_rotate_used_height+\sin\d_grph_rotate_depth\relax
+ \fi
+ \ifconditional\c_grph_rotate_obey_depth
+ \d_grph_rotate_y_offset\cos\d_grph_rotate_depth
+ \fi}
+
+\def\grph_rotate_calculate_b
+ {\d_grph_rotate_x_size\dimexpr\negated\cos\d_grph_rotate_width+\sin\d_grph_rotate_used_height\relax
+ \d_grph_rotate_y_size\dimexpr\sin\d_grph_rotate_width+\negated\cos\d_grph_rotate_used_height\relax
+ \d_grph_rotate_x_position\negated\cos\d_grph_rotate_width
+ \d_grph_rotate_y_position\zeropoint
+ \ifconditional\c_grph_rotate_not_fit
+ \d_grph_rotate_x_offset\dimexpr-\d_grph_rotate_x_size+\sin\d_grph_rotate_depth\relax
+ \fi
+ \ifconditional\c_grph_rotate_obey_depth
+ \d_grph_rotate_y_offset\negated\cos\d_grph_rotate_height
+ \fi}
+
+\def\grph_rotate_calculate_c
+ {\d_grph_rotate_x_size\dimexpr\negated\cos\d_grph_rotate_width+\negated\sin\d_grph_rotate_used_height\relax
+ \d_grph_rotate_y_size\dimexpr\negated\sin\d_grph_rotate_width+\negated\cos\d_grph_rotate_used_height\relax
+ \d_grph_rotate_x_position\d_grph_rotate_x_size
+ \d_grph_rotate_y_position\negated\sin\d_grph_rotate_width
+ \ifconditional\c_grph_rotate_not_fit
+ \d_grph_rotate_x_offset\dimexpr-\d_grph_rotate_x_size+\negated\sin\d_grph_rotate_height\relax
+ \fi
+ \ifconditional\c_grph_rotate_obey_depth
+ \d_grph_rotate_y_offset\dimexpr\d_grph_rotate_y_size+\cos\d_grph_rotate_depth\relax
+ \fi}
+
+\def\grph_rotate_calculate_d
+ {\d_grph_rotate_x_size\dimexpr\cos\d_grph_rotate_width+\negated\sin\d_grph_rotate_used_height\relax
+ \d_grph_rotate_y_size\dimexpr\negated\sin\d_grph_rotate_width+\cos\d_grph_rotate_used_height\relax
+ \d_grph_rotate_x_position\zeropoint
+ \d_grph_rotate_y_position\d_grph_rotate_y_size
+ \d_grph_rotate_x_offset\zeropoint
+ \ifconditional\c_grph_rotate_obey_depth
+ \d_grph_rotate_y_offset\d_grph_rotate_depth
+ \fi}
+
+\def\grph_rotate_calculate_e
+ {\d_grph_rotate_x_size\dimexpr\cos\d_grph_rotate_width+\negated\sin\d_grph_rotate_used_height\relax
+ \d_grph_rotate_y_size\dimexpr\negated\sin\d_grph_rotate_width+\cos\d_grph_rotate_used_height\relax
+ \d_grph_rotate_x_position\negated\sin\d_grph_rotate_used_height
+ \d_grph_rotate_y_position\d_grph_rotate_y_size
+ \ifconditional\c_grph_rotate_not_fit
+ \d_grph_rotate_x_offset\dimexpr-\d_grph_rotate_x_size+\negated\sin\d_grph_rotate_height\relax
+ \fi
+ \ifconditional\c_grph_rotate_obey_depth
+ \d_grph_rotate_y_offset\negated\sin\d_grph_rotate_depth
+ \fi}
+
+\def\grph_rotate_apply
+ {\setbox\nextbox\vpack to \d_grph_rotate_y_size
+ {\vfill
+ \hpack to \d_grph_rotate_x_size
+ {\dostartrotation\p_rotation_rotation
+ \wd\nextbox\zeropoint
+ \ht\nextbox\zeropoint
+ \box\nextbox
+ \dostoprotation
+ \hfill}%
+ \kern\d_grph_rotate_y_position}%
+ \setbox\nextbox\hpack
+ {\kern\dimexpr\d_grph_rotate_x_position+\d_grph_rotate_x_offset\relax
+ \lower\d_grph_rotate_y_offset\box\nextbox}}
+
+% \dostepwiserecurse{0}{360}{10}
+% {\startlinecorrection[blank]
+% \hbox
+% {\expanded{\setuprotate[rotation=\recurselevel]}%
+% \traceboxplacementtrue
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=depth] {\ruledhbox{\bfb (depth)}}}}%
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=fit] {\ruledhbox{\bfb (fit)}}}}%
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=broad] {\ruledhbox{\bfb (broad)}}}}%
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=normal]{\ruledhbox{\bfb (normal)}}}}%
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=high] {\ruledhbox{\bfb (high)}}}}}
+% \stoplinecorrection}
+
+\protect \endinput