%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 go away. Some of %D this is an inheritance of limited backends (some supported fractions, some %D 1000's, some dimentions) so we calculate all of them. Nowadays scaling is always %D available so we could simplify the code. On the other hand, we now get some extra %D values for free. %D %D We could move the calculations to \LUA\ and clean up this lot anyway. On the %D other hand, there is some danger of messing up so it has a real low priority. \registerctxluafile{grph-trf}{autosuffix} % See below \newdimension\d_grph_rotate_x_size \newdimension\d_grph_rotate_y_size \newdimension\d_grph_rotate_x_offset \newdimension\d_grph_rotate_y_offset \newdimension\d_grph_rotate_x_position \newdimension\d_grph_rotate_y_position \newdimension\d_grph_rotate_new_width \newdimension\d_grph_rotate_new_height \newdimension\d_grph_rotate_new_depth % local: \newdimension\d_grph_scale_x_size \newdimension\d_grph_scale_y_size \newdimension\d_grph_scale_x_offset \newdimension\d_grph_scale_y_offset \newdimension\d_grph_scale_h_size \newdimension\d_grph_scale_v_size \newconditional\c_grph_scale_done \newconditional\c_grph_scale_scaling_done \newconditional\c_grph_scale_limit_factors \c_grph_scale_limit_factors\conditionaltrue \newdimension\d_grph_scale_wd \newdimension\d_grph_scale_ht \newdimension\d_grph_scale_dp \newconditional\c_grph_scale_swap_factor % global \newdimension\d_grph_scale_used_x_size % global \newdimension\d_grph_scale_used_y_size % global \newinteger\c_grph_scale_used_x_scale \newinteger\c_grph_scale_used_y_scale \let\m_grph_scale_used_x_scale\!!plusone \let\m_grph_scale_used_y_scale\!!plusone \newdimension\d_grph_scale_outer_v_size % we cannot manipulate any global vsize ! % scratch: \lettonothing\m_grph_scale_temp \lettonothing\m_grph_scale_temp_x \lettonothing\m_grph_scale_temp_y % public: \mutable\let\finalscaleboxxscale \!!plusone \mutable\let\finalscaleboxyscale \!!plusone \mutable\let\finalscaleboxwidth \!!zeropoint \mutable\let\finalscaleboxheight \!!zeropoint % we can let sx/sy win (first check) \installcorenamespace{scale} \installcorenamespace{scalegrid} \installcorenamespace{scalenorm} \installcorenamespace{scalefact} \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] % \permanent\tolerant\protected\def\scale[#1]#*[#2]% % {\bgroup % % this is quite common so we might make this a helper % \ifarguments % \lettonothing\currentscale % \or % \ifhastok={#1}% % \lettonothing\currentscale % \setupcurrentscale[#1]% % \else % \cdef\currentscale{#1}% % \fi % \or % \cdef\currentscale{#1}% % \setupcurrentscale[#2]% % \fi % % % \dowithnextboxcs\grph_scale_finish\naturalhbox} % intercept direction \newinteger\c_grph_scale_nesting \def\grph_scale_set_nesting {\advanceby\c_grph_scale_nesting\plusone \letcsname\??scale>\the\c_grph_scale_nesting:\s!parent\endcsname\??scale \cdef\currentscale{>\the\c_grph_scale_nesting}} \permanent\tolerant\protected\def\scale[#S#1]#*[#S#2]% {\bgroup \ifarguments \grph_scale_set_nesting \or \ifhastok={#1}% \grph_scale_set_nesting \setupcurrentscale[#1]% \else \cdef\currentscale{#1}% \ifempty\currentscale \grph_scale_set_nesting \fi \fi \or \cdef\currentscale{#1}% \ifempty\currentscale \grph_scale_set_nesting \fi \setupcurrentscale[#2]% \fi % \dowithnextboxcs\grph_scale_finish\naturalhbox} % intercept direction \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\naturalhpack{\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 % \glet\finalscaleboxxscale \!!plusone \glet\finalscaleboxyscale \!!plusone \xdef\finalscaleboxwidth {\the\d_grph_scale_wd}% \xdef\finalscaleboxheight{\the\d_grph_scale_ht}% % \forgetall \dontcomplain % \c_grph_scale_done\conditionalfalse \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 \ifdim\d_grph_scale_wd=\wd\nextbox \ifdim\d_grph_scale_ht=\ht\nextbox \ifdim\d_grph_scale_dp=\dp\nextbox % \grph_scale_apply_nop \else \grph_scale_apply_yes \fi \else \grph_scale_apply_yes \fi \else \grph_scale_apply_yes \fi} \def\grph_scale_apply_yes {\setbox\nextbox\hcontainer {\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}% \ifempty\m_grph_scale_stamp_a \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 \ifempty\m_grph_scale_stamp_b % 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% {\thewithoutunit\dimexpr#1\points*100+32768\scaledpoint\relax} \def\grph_scale_calculations_nop {\c_grph_scale_done\conditionaltrue \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 \ifempty\finalscaleboxxscale\let\finalscaleboxxscale\!!plusone\fi \ifempty\finalscaleboxyscale\let\finalscaleboxyscale\!!plusone\fi} \let\grph_scale_calculations_report\relax \def\grph_scale_calculations_yes {\c_grph_scale_done\conditionaltrue % 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 \c_grph_scale_scaling_done\conditionalfalse \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} \defcsname\??scalegrid\v!yes \endcsname{\getnoflines \d_grph_scale_used_y_size\edef\p_height{\the\noflines\lineheight}} \defcsname\??scalegrid\v!height \endcsname{\getrawnoflines\d_grph_scale_used_y_size\edef\p_height{\the\dimexpr\noflines\lineheight+\strutdepth}} \defcsname\??scalegrid\v!depth \endcsname{\getrawnoflines\d_grph_scale_used_y_size\edef\p_height{\the\dimexpr\noflines\lineheight-\strutdepth}} \defcsname\??scalegrid\v!halfline\endcsname{\getrawnoflines\d_grph_scale_used_y_size\edef\p_height{\the\dimexpr\noflines\lineheight+.5\lineheight}} \defcsname\??scalegrid\v!fit \endcsname{\getrawnoflines\d_grph_scale_used_y_size\edef\p_height{\the\noflines\lineheight}} \letcsname\??scalegrid\empty \endcsname\donothing \def\grph_scale_check_parameters % resolve self referencing loops {\ifempty\p_maxwidth \else \edef\p_maxwidth {\the\dimexpr\p_maxwidth }\fi \ifempty\p_maxheight\else \edef\p_maxheight{\the\dimexpr\p_maxheight }\fi \ifempty\p_lines \else \edef\p_height {\the\dimexpr\p_lines\lineheight}\fi \begincsname\??scalegrid\scaleparameter\c!grid\endcsname} \def\grph_scale_by_nature % where ! ! ! ! ! {\ifempty\p_width \else \global\d_grph_scale_used_x_size\p_width \fi \ifempty\p_height\else \global\d_grph_scale_used_y_size\p_height\fi \ifempty\p_scale \else \c_grph_scale_used_x_scale\p_scale \c_grph_scale_used_y_scale\p_scale \fi \ifempty\p_xscale\else \c_grph_scale_used_x_scale\p_xscale\fi \ifempty\p_yscale\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]}} %D The \type {min} option makes sure that the smallest available space determines %D the max size (so we can get a bleed on the other axis): %D %D \startlinecorrection %D \startcombination[nx=2,ny=2,distance=4cm] %D {\externalfigure[hacker][factor=max,maxwidth=6cm,maxheight=6cm]} {} %D {\externalfigure[mill] [factor=max,maxwidth=6cm,maxheight=6cm]} {} %D {\externalfigure[hacker][factor=min,maxwidth=6cm,maxheight=6cm]} {} %D {\externalfigure[mill] [factor=min,maxwidth=6cm,maxheight=6cm]} {} %D \stopcombination %D \stoplinecorrection \def\m_grph_scale_factor_set{\v!min,\v!max,\v!fit,\v!broad,\v!auto} % can be an \edef \def\grph_scale_by_factor {\ifinset\p_factor\m_grph_scale_factor_set \grph_scale_by_factor_a \orelse\ifinset\p_hfactor\m_grph_scale_factor_set \grph_scale_by_factor_b \orelse\ifinset\p_wfactor\m_grph_scale_factor_set \grph_scale_by_factor_c \else \grph_scale_by_factor_d \fi} \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 {\grph_scale_calculate_fact\p_factor \c_grph_scale_scaling_done\conditionaltrue \ifconditional\c_grph_scale_limit_factors \ifdim\d_grph_scale_used_x_size\ifconditional\c_grph_scale_swap_factor<\else>\fi\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 \orelse\ifdim\d_grph_scale_used_y_size\ifconditional\c_grph_scale_swap_factor<\else>\fi\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 \grph_scale_by_dimension} \def\grph_scale_by_scale {\edef\m_grph_scale_temp{\p_scale\p_xscale\p_yscale}% \ifempty\m_grph_scale_temp \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 % \ifempty\p_maxwidth \ifempty\p_maxheight\orelse\ifdim\d_grph_scale_y_size>\p_maxheight\relax \global\d_grph_scale_used_y_size\p_maxheight \fi \orelse\ifdim\d_grph_scale_x_size>\p_maxwidth\relax \global\d_grph_scale_used_x_size\p_maxwidth \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\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 \ifempty\p_maxwidth\orelse\ifdim\d_grph_scale_used_x_size>\p_maxwidth\relax \global\d_grph_scale_used_x_size\p_maxwidth #2\relax \fi \ifempty\p_maxheight\orelse\ifdim\d_grph_scale_used_y_size>\p_maxheight\relax \global\d_grph_scale_used_y_size\p_maxheight #3\relax \fi} % we can use \lastnamedcs if we want to squeeze out some more \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} \def\grph_scale_calculate_fact#1% {\csname\??scalefact\ifcsname\??scalefact#1\endcsname#1\else\s!unknown\fi\endcsname} \defcsname\??scalenorm\v!max \endcsname#1#-#-#2#-{\global#1#2} \defcsname\??scalenorm\v!fit \endcsname#1#-#-#-#2{\global#1#2} \defcsname\??scalenorm\v!broad \endcsname#1#-#-#-#2{\global#1\dimexpr#2-4\externalfigureparameter\c!bodyfont\relax} \defcsname\??scalenorm\s!unknown\endcsname#1#2#-#-#-{\global#1\dimexpr#2\dimexpr\externalfigureparameter\c!bodyfont/10\relax\relax} % brr ex \defcsname\??scalenorm\v!auto \endcsname#1#-#2#-#-{\ifempty#2\else\global#1#2\fi} \defcsname\??scalenorm\empty \endcsname#1#-#2#-#-{\ifempty#2\else\global#1#2\fi} \defcsname\??scalenorm\s!default\endcsname#1#-#2#-#-{\ifempty#2\else\global#1#2\fi} \defcsname\??scalefact\v!min \endcsname{\global\c_grph_scale_swap_factor\conditionaltrue} \defcsname\??scalefact\s!unknown\endcsname{\global\c_grph_scale_swap_factor\conditionalfalse} \defcsname\??scalenorm\v!min\endcsname#-#-#-#-#-% an ugly hack {\d_grph_scale_used_x_size\hsize \d_grph_scale_used_y_size\vsize} \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} \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 {% no overflow \edef#1{\luaexpr {\number \ifempty#2% \ifempty\p_scale \plusthousand \else \ifnum \p_scale=\zerocount \plusthousand \else \p_scale \fi\fi \orelse\ifnum#2=\zerocount \ifempty\p_scale \plusthousand \else \ifnum \p_scale=\zerocount \plusthousand \else \p_scale \fi\fi \else #2% \fi /1000}}} \def\grph_scale_apply_size {\ifempty\p_maxheight \d_grph_scale_outer_v_size\textheight \ifinner \d_grph_scale_outer_v_size \vsize % \textheight =\vsize \scratchdimen\vsize % \scratchdimen=\textheight \orelse\ifinsidefloat \d_grph_scale_outer_v_size \vsize % \textheight =\vsize \scratchdimen\vsize % \scratchdimen=\textheight \orelse\ifinpagebody \d_grph_scale_outer_v_size \vsize % \textheight =\vsize \scratchdimen\vsize % \scratchdimen=\textheight \orelse\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 \else \scratchdimen\p_maxheight \d_grph_scale_outer_v_size\scratchdimen \fi \ifempty\p_height \d_grph_scale_v_size\scratchdimen \else \d_grph_scale_v_size\p_height \fi \ifempty\p_width \d_grph_scale_h_size\hsize \else \d_grph_scale_h_size\p_width \fi} % \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 {\ifempty\p_equalwidth \else \scratchdimen\p_equalwidth\relax \ifdim\d_grph_scale_wd<\scratchdimen \setbox\nextbox\naturalhpack to \scratchdimen{\hss\box\nextbox\hss}% \fi \fi \ifempty\p_equalheight \else \scratchdimen\p_equalheight\relax \ifdim\d_grph_scale_ht<\scratchdimen \setbox\nextbox\naturalvpack to \scratchdimen{\vss\box\nextbox\vss}% \fi \fi} \permanent\protected\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{\toscaled\dimexpr#1\onepoint/1000\relax}% brrr \let\finalscaleboxyscale\finalscaleboxxscale \dowithnextboxcs\grph_scale_fast_finish\hbox} % container ? \def\grph_scale_fast_finish {\grph_scale_apply \box\nextbox \endgroup} \permanent\protected\def\fastsxsy#1#2% {\bgroup \edef\p_sx{#1}% \edef\p_sy{#2}% \dowithnextboxcs\grph_scale_fast_sx_xy_finish\hbox} % container? \def\grph_scale_fast_sx_xy_finish {\grph_scale_check_sx_sy \d_grph_scale_wd\wd\nextbox \d_grph_scale_ht\ht\nextbox \d_grph_scale_dp\dp\nextbox \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 arbitrary content. We can %D use \METAPOST\ to provide a non 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, 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} \permanent\tolerant\protected\def\clip[#S#1]% nb top->bottom left->right {\bgroup \ifparameter#1\or \setupcurrentclipping[#1]% \fi \dowithnextboxcs\grph_clip_finish\hbox} \def\grph_clip_finish {\ifcstok{\clippingparameter\c!state}\v!start \grph_clip_yes_finish \else \grph_clip_nop_finish \fi} \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 \advanceby\scratchyoffset \ht\nextbox \fi \setbox\nextbox\naturalhpack {\advanceby\scratchxoffset -\clippingparameter\c!leftoffset \relax \advanceby\scratchyoffset -\clippingparameter\c!bottomoffset\relax \hskip-\scratchxoffset \lower\scratchyoffset \box\nextbox}% \wd\nextbox\zeropoint \ht\nextbox\zeropoint \dp\nextbox\zeropoint \setbox\nextbox\naturalhpack {\advanceby\scratchwidth \dimexpr\clippingparameter\c!leftoffset +\clippingparameter\c!rightoffset\relax \advanceby\scratchheight\dimexpr\clippingparameter\c!bottomoffset+\clippingparameter\c!topoffset \relax \dostartclipping{\clippingparameter\c!mp}\scratchwidth\scratchheight \box\nextbox \dostopclipping}% \setbox\nextbox\hcontainer {\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. \permanent\protected\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\naturalhpack {\dostartmirroring \hskip-\wd\nextbox \box\nextbox \dostopmirroring}% \wd\nextbox\scratchdimen \box\nextbox \egroup} %D A couple of examples, demonstrating how the depth is 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 %D %D When we rotate over arbitrary angles, we need to relocate the resulting box %D because rotation brings that box onto the negative axis. The calculations (mostly %D sin and cosine) need to be tuned for the way a box is packages (i.e. the refence %D point). A typical example of drawing, scribbling, and going back to the days of %D school math. %D %D We do a bit more calculations than needed, simply because that way it's easier to %D debug the code. \installcorenamespace {rotate} \installcorenamespace {rotatelocation} \installcorenamespace {rotatepreset} %D These are set at the \LUA\ end (it's a cheaper operation than setting a dimen %D register and these are actually kind of constants not used in further %D calculations): % mutable\dimendef\d_grph_rotate_x_size \zeropoint % mutable\dimendef\d_grph_rotate_y_size \zeropoint % mutable\dimendef\d_grph_rotate_x_offset \zeropoint % mutable\dimendef\d_grph_rotate_y_offset \zeropoint % mutable\dimendef\d_grph_rotate_x_position\zeropoint % mutable\dimendef\d_grph_rotate_y_position\zeropoint % % mutable\dimendef\d_grph_rotate_new_width \zeropoint % mutable\dimendef\d_grph_rotate_new_height\zeropoint % mutable\dimendef\d_grph_rotate_new_depth \zeropoint %D These aren't: \newdimension\d_grph_rotate_used_height \newdimension\d_grph_rotate_width \newdimension\d_grph_rotate_height \newdimension\d_grph_rotate_depth \newdimension\d_grph_rotate_saved_width \newdimension\d_grph_rotate_saved_height \newdimension\d_grph_rotate_saved_depth \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] \lettonothing\p_rotation_location \lettonothing\p_rotation_rotation \permanent\tolerant\protected\def\rotate[#S#1]% \bgroup: \rotate kan argument zijn {\bgroup \ifparameter#1\or \setupcurrentrotate[#1]% \fi \edef\p_rotation_location{\rotateparameter\c!location}% \edef\p_rotation_rotation{\rotateparameter\c!rotation}% \ifcsname\??rotatelocation\p_rotation_location\endcsname \expandafter\lastnamedcs \else \expandafter\grph_rotate_default \fi} \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} \def\grph_rotate_default {\c_grph_rotate_not_fit\conditionalfalse \c_grph_rotate_center\conditionalfalse \c_grph_rotate_obey_depth\conditionaltrue \grph_rotate_framed} \letcsname\??rotatelocation\v!default\endcsname\grph_rotate_default \defcsname\??rotatelocation\v!depth\endcsname {\c_grph_rotate_not_fit\conditionalfalse \c_grph_rotate_center\conditionalfalse \c_grph_rotate_obey_depth\conditionaltrue \grph_rotate_normal} \defcsname\??rotatelocation\v!fit\endcsname {\c_grph_rotate_not_fit\conditionaltrue \c_grph_rotate_center\conditionalfalse \c_grph_rotate_obey_depth\conditionaltrue \grph_rotate_normal} \defcsname\??rotatelocation\v!broad\endcsname {\c_grph_rotate_not_fit\conditionalfalse \c_grph_rotate_center\conditionalfalse \c_grph_rotate_obey_depth\conditionalfalse \grph_rotate_normal} \defcsname\??rotatelocation\v!high\endcsname {\c_grph_rotate_not_fit\conditionalfalse \c_grph_rotate_center\conditionalfalse \c_grph_rotate_obey_depth\conditionalfalse \grph_rotate_framed} \defcsname\??rotatelocation\v!middle\endcsname {\c_grph_rotate_not_fit\conditionalfalse \c_grph_rotate_center\conditionaltrue \c_grph_rotate_obey_depth\conditionalfalse % hm, depth ? \grph_rotate_normal} \permanent\protected\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 {\c_grph_rotate_not_fit\conditionalfalse % this is the same as broad but \c_grph_rotate_center\conditionalfalse % without the following grab as \c_grph_rotate_obey_depth\conditionalfalse % we call finish directly \grph_rotate_finish_indeed \egroup \egroup} \def\grph_rotate_finish_indeed {\naturalhpack\bgroup \ifempty\p_rotation_rotation \grph_rotate_finish_nop \else \grph_rotate_finish_yes \fi \egroup} \def\grph_rotate_finish_nop {\boxcursor\box\nextbox} \defcsname\??rotatepreset\v!left\endcsname {\edef\p_rotation_rotation{90}} \defcsname\??rotatepreset\v!right\endcsname {\edef\p_rotation_rotation{270}} \defcsname\??rotatepreset\v!inner\endcsname {\signalrightpage \doifelserightpage{\def\p_rotation_rotation{270}}{\def\p_rotation_rotation{90}}} \defcsname\??rotatepreset\v!outer\endcsname {\signalrightpage \doifelserightpage{\def\p_rotation_rotation{90}}{\def\p_rotation_rotation{270}}} \letcsname\??rotatepreset\v!default\endcsname\empty \def\grph_rotate_finish_yes {\begincsname\??rotatepreset\p_rotation_rotation\endcsname \setbox\nextbox\naturalvpack{\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\naturalhpack{\hskip-.5\wd\nextbox\lower.5\ht\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\naturalvpack{\naturalhpack{\raise\dp\nextbox\box\nextbox}}% can we do without % \d_grph_rotate_used_height\ht\nextbox % \clf_analyzerotate % rather accurate \p_rotation_rotation\space \d_grph_rotate_width \d_grph_rotate_height \d_grph_rotate_depth \d_grph_rotate_used_height \c_grph_rotate_not_fit \c_grph_rotate_obey_depth \relax % \setbox\nextbox\naturalvpack to \d_grph_rotate_y_size {\vfilll \hcontainer 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\naturalhpack {\kern\dimexpr\d_grph_rotate_x_position+\d_grph_rotate_x_offset\relax \lower\d_grph_rotate_y_offset \box\nextbox}% % \ifconditional\c_grph_rotate_center \setbox\nextbox\naturalhpack{\hskip.5\d_grph_rotate_saved_width\lower-.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 \else \wd\nextbox\d_grph_rotate_new_width \ht\nextbox\d_grph_rotate_new_height \dp\nextbox\d_grph_rotate_new_depth \fi % \boxcursor\box\nextbox} % \dostepwiserecurse{0}{360}{10} % {\startlinecorrection[blank] % \hbox % {\setuprotate[rotation=#1]% % \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} % \def\Test{\ruledhbox{% % \def\DemoX{\vl\kern.5\emwidth\vl}% % \kern\emwidth\ruledhpack{\green\rotate[rotation=20] {\ruledhpack{\DemoX}}}% % \kern\emwidth\ruledhpack{\blue \rotate[rotation=0] {\ruledhpack{\DemoX}}}% % \kern\emwidth\ruledhpack{\red \rotate[rotation=-20] {\ruledhpack{\DemoX}}}% % \kern\emwidth\ruledhpack{\green\rotate[rotation=200] {\ruledhpack{\DemoX}}}% % \kern\emwidth\ruledhpack{\blue \rotate[rotation=180] {\ruledhpack{\DemoX}}}% % \kern\emwidth\ruledhpack{\red \rotate[rotation=-200]{\ruledhpack{\DemoX}}}% % \kern\emwidth}} % \startTEXpage[offset=10pt,align=middle] % \setuprotate[location=fit] \Test \par {\infofont\setstrut\strut fit} \par % \setuprotate[location=depth] \Test \par {\infofont\setstrut\strut depth} \par % \setuprotate[location=broad] \Test \par {\infofont\setstrut\strut broad} \par % \setuprotate[location=high] \Test \par {\infofont\setstrut\strut high} \par % \setuprotate[location=middle] \Test \par {\infofont\setstrut\strut middle} \par % \setuprotate[location=default] \Test \par {\infofont\setstrut\strut default} \par % \stopTEXpage \protect \endinput