diff options
author | Karl Berry <karl@freefriends.org> | 2011-11-25 00:14:23 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2011-11-25 00:14:23 +0000 |
commit | 4796116f06de1574987757c8945f6678d21f0a40 (patch) | |
tree | b6d95196b38ef31d6021471ecbf7c4d48fcaa730 /Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx | |
parent | 27ecf3bfa131e03a530396ff6c0016cf6dffacd0 (diff) |
l3kernel 2966 (19nov11)
git-svn-id: svn://tug.org/texlive/trunk@24657 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx | 285 |
1 files changed, 195 insertions, 90 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx b/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx index 47b21713513..5159746f515 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx @@ -36,7 +36,7 @@ % %<*driver|package> \RequirePackage{l3names} -\GetIdInfo$Id: l3drivers.dtx 2862 2011-09-27 21:14:27Z joseph $ +\GetIdInfo$Id: l3drivers.dtx 2959 2011-11-14 21:47:18Z joseph $ {L3 Experimental drivers} %</driver|package> %<*driver> @@ -86,6 +86,18 @@ % functions here are closely tied to the immediate level \enquote{up}: % several variable values must be in the correct locations for the driver % code to function. +% +% \section{Box clipping} +% +% \begin{function}[added = 2011-11-11]{\driver_box_use_clip:N} +% \begin{syntax} +% \cs{driver_box_use_clip:N} \meta{box} +% \end{syntax} +% Inserts the content of the \meta{box} at the current insertion point +% such that any material outside of the bounding box will not be displayed +% by the driver. The material in the \meta{box} is still places in the +% output stream: the clipping takes place at a driver level. +% \end{function} % % \section{Box rotation and scaling} % @@ -193,78 +205,201 @@ %</pdfmode> %</initex> % \end{macrocode} +% +% \subsection{Driver utility functions} +% +% \begin{macro}{\driver_graphic_state_save:} +% \begin{macro}{\driver_graphic_state_restore:} +% All of the drivers have a stack for saving the graphic state. These +% have slightly different interfaces. As \texttt{dvips} does not +% automatically save the current location, this is set up here. +% \begin{macrocode} +\cs_new_protected:Npn \driver_graphic_state_save: +%<*dvips> + { \tex_special:D { ps:gsave } } +%</dvips> +%<*pdfmode> + { \pdftex_pdfsave:D } +%</pdfmode> +%<*xdvipdfmx> + { \tex_special:D { pdf:bcontent } } +%</xdvipdfmx> +\cs_new_protected:Npn \driver_graphic_state_restore: +%<*dvips> + { \tex_special:D { ps:grestore } } +%</dvips> +%<*pdfmode> + { \pdftex_pdfrestore:D } +%</pdfmode> +%<*xdvipdfmx> + { \tex_special:D { pdf:econtent } } +%</xdvipdfmx> +% \end{macrocode} +% \end{macro} +% \end{macro} % -% \subsection{Box rotation and scaling} -% -% \begin{variable}{\l_driver_box_matrix_tl} -% A token list for the affine transformation matrix. +% \begin{macro}{\driver_pdf_literal:n, \driver_pdf_literal_direct:n} +% Both direct PDF mode and \texttt{xdvipdfmx} make use of direct PDF +% special insertion. These are slightly different in the two cases. +% The |direct| versions do not save the current matrix. % \begin{macrocode} +%<*pdfmode|xdvipdfmx> +\cs_new_protected:Npn \driver_pdf_literal:n #1 +%<*pdfmode> + { \pdftex_pdfliteral:D {#1} } +%</pdfmode> +%<*xdvipdfmx> + { \tex_special:D { pdf:content~ #1 } } +%</xdvipdfmx> +\cs_new_protected:Npn \driver_pdf_literal_direct:n #1 %<*pdfmode> -\tl_new:N \l_driver_box_matrix_tl + { \pdftex_pdfliteral:D direct~{#1} } %</pdfmode> +%<*xdvipdfmx> + { \tex_special:D { pdf:literal~direct~ #1 } } +%</xdvipdfmx> +%</pdfmode|xdvipdfmx> % \end{macrocode} -% \end{variable} +% \end{macro} +% +% \begin{macro}{\driver_ps_literal:n} +% The same concept for PostScript: these are \enquote{direct} by default, +% but by keeping the same name life should be a little clearer. +% \begin{macrocode} +%<*dvips> +\cs_new_protected:Npn \driver_ps_literal:n #1 + { \tex_special:D { ps: #1 } } +%</dvips> +% \end{macrocode} +% \end{macro} +% +% \subsection{Box clipping} +% +% \begin{macro}{\driver_box_use_clip:N} +% The overall logic to clipping a box is the same in all cases. The general +% method is to save the current location, define a clipping path equivalent +% to the bounding box, then insert the content at the current position +% and in a zero width box. The \enquote{real} width is then made up using +% a horizontal skip before tidying up. There are other approaches that +% can be taken (for example using XForm objects), but the logic here shares +% as much code as possible and uses the same conversions (and so same +% rounding errors) in all three cases. +% \begin{macrocode} +\cs_new_protected:Npn \driver_box_use_clip:N #1 + { + \driver_graphic_state_save: +% \end{macrocode} +% The business end of the code sets up the clip box, using the higher-level +% rectangle operators rather than the lower level direct line drawing. This +% makes sense for a simple rectangular clip. There are a couple of approaches +% for \texttt{dvips}. The approach here is to save the current matrix, +% then translate to the current \TeX{} position and switch to big point +% measurement. The clip box can then be set up using the same conversion +% as for direct PDF output: notice that here the $y$-axis is upside down. +% The original matrix is then restored, so that \TeX{} inserts material +% in the correct place (there is an offset between the PostScript and +% \TeX{} current positions). +% \begin{macrocode} +%<*dvips> + \driver_ps_literal:n + { + /savedmatrix~matrix~currentmatrix~def~ + currentpoint~translate~ + Resolution~72~div~VResolution~72~div~scale + } + \driver_ps_literal:n + { + 0~ + -\dim_strip_bp:n { \box_dp:N #1 } ~neg~ + \dim_strip_bp:n { \box_wd:N #1 } ~ + \dim_strip_bp:n { \box_ht:N #1 + \box_dp:N #1 } ~neg~ + rectclip + } + \driver_ps_literal:n { savedmatrix~setmatrix } +%</dvips> +% \end{macrocode} +% The PDF box is easier to define as it is automatically in big points and +% as the driver deals with the relationship between the \TeX{} and graphics +% locations automatically. +% \begin{macrocode} +%<*pdfmode|xdvipdfmx> + \driver_pdf_literal_direct:n + { + 0 ~ + -\dim_strip_bp:n { \box_dp:N #1 } ~ + \dim_strip_bp:n { \box_wd:N #1 } ~ + \dim_strip_bp:n { \box_ht:N #1 + \box_dp:N #1 } ~ + re~W~n + } +%</pdfmode|xdvipdfmx> +% \end{macrocode} +% Insert the material in a box of no width, restore the graphic state +% and then insert the necessary width. +% \begin{macrocode} + \hbox_overlap_right:n { \box_use:N #1 } + \driver_graphic_state_restore: + \skip_horizontal:n { \box_wd:N #1 } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Box rotation and scaling} % % \begin{variable}{\l_driver_tmp_fp} % Needed for a safe sign inversion in PDF mode. % \begin{macrocode} -%<*pdfmode> +%<*pdfmode|xdvipdfmx> \fp_new:N \l_driver_tmp_fp -%</pdfmode> +%</pdfmode|xdvipdfmx> % \end{macrocode} % \end{variable} % % \begin{macro}{\driver_box_rotate_begin:, \driver_box_rotate_end:} -% Systems which require only the rotation angle have simple drivers. -% On the other hand, in PDF mode the affine transformation matrix is -% needed, which has to be set up. This also requires that the sine -% value does not have two |-| tokens at the start, hence having to -% work out the negative sine carefully. This driver also requires -% that the width of the box in use for the output is set to zero, hence -% needing to know where the output is actually stored. +% The driver for \texttt{dvips} works with a simple rotation angle. +% In PDF mode, an affine matrix is used instead. The transformation for +% \texttt{xdvipdfmx} can be done either way: to have some code sharing, +% the choice here is to use an affine approach (at least some code is +% shared in this way). For the \texttt{dvips}, that odd-looking +% |currentpoint| at the beginning is used to put this data onto the +% stack for |neg exch neg exch translate| to pick up. % \begin{macrocode} -\cs_new_protected_nopar:Npn \driver_box_rotate_begin: +\cs_new_protected:Npn \driver_box_rotate_begin: { + \driver_graphic_state_save: %<*dvips> - \tex_special:D + \driver_ps_literal:n { - ps:~gsave~currentpoint~ - currentpoint~translate~ \fp_use:N \l_box_angle_fp \c_space_tl - neg~rotate~neg~exch~neg~exch~translate + currentpoint~ + currentpoint~translate~ + \fp_use:N \l_box_angle_fp \c_space_tl neg~rotate~ + neg~exch~neg~exch~translate } %</dvips> -%<*pdfmode> +%<*pdfmode|xdvipdfmx> + \box_set_wd:Nn \l_box_tmp_box \c_zero_dim \fp_set_eq:NN \l_driver_tmp_fp \l_box_sin_fp \fp_neg:N \l_driver_tmp_fp - \tl_set:Nx \l_driver_box_matrix_tl +%<*pdfmode> + \pdftex_pdfsetmatrix:D +%</pdfmode> +%<*xdvipdfmx> + \driver_pdf_literal_direct:n +%</xdvipdfmx> { \fp_use:N \l_box_cos_fp \c_space_tl \fp_use:N \l_box_sin_fp \c_space_tl \fp_use:N \l_driver_tmp_fp \c_space_tl \fp_use:N \l_box_cos_fp - } - \pdftex_pdfsave:D - \pdftex_pdfsetmatrix:D { \l_driver_box_matrix_tl } - \box_set_wd:Nn \l_box_tmp_box \c_zero_dim -%</pdfmode> %<*xdvipdfmx> - \tex_special:D { x:gsave } - \tex_special:D { x:rotate~ \fp_use:N \l_box_angle_fp } + \c_space_tl 0~0~cm %</xdvipdfmx> + } +%</pdfmode|xdvipdfmx> } % \end{macrocode} % The end of a rotation means tidying up the output grouping. % \begin{macrocode} -\cs_new_protected_nopar:Npn \driver_box_rotate_end: -%<*dvips> - { \tex_special:D { ps:~currentpoint~grestore~moveto } } -%</dvips> -%<*pdfmode> - { \pdftex_pdfrestore:D } -%</pdfmode> -%<*xdvipdfmx> - { \tex_special:D { x:grestore } } -%</xdvipdfmx> +\cs_new_eq:NN \driver_box_rotate_end: \driver_graphic_state_restore: % \end{macrocode} % \end{macro} % @@ -272,61 +407,37 @@ % Scaling is not dissimilar to rotation, but the calculations are somewhat % less complex. % \begin{macrocode} -\cs_new_protected_nopar:Npn \driver_box_scale_begin: +\cs_new_protected:Npn \driver_box_scale_begin: { + \driver_graphic_state_save: %<*dvips> - \tex_special:D + \driver_ps_literal:n { - ps:~currentpoint~ + currentpoint~ currentpoint~translate~ \fp_use:N \l_box_scale_x_fp \c_space_tl - \fp_use:N \l_box_scale_y_fp \c_space_tl - scale~neg~exch~neg~exch~ - translate + \fp_use:N \l_box_scale_y_fp \c_space_tl scale~ + neg~exch~neg~exch~translate } %</dvips> +%<*pdfmode|xdvipdfmx> %<*pdfmode> - \tl_set:Nx \l_driver_box_matrix_tl - { - \fp_use:N \l_box_scale_x_fp \c_space_tl - 0 ~ 0 ~ - \fp_use:N \l_box_scale_y_fp - } - \pdftex_pdfsave:D - \pdftex_pdfsetmatrix:D { \l_driver_box_matrix_tl } + \pdftex_pdfsetmatrix:D %</pdfmode> %<*xdvipdfmx> - \tex_special:D { x:gsave } - \tex_special:D + \driver_pdf_literal_direct:n +%</xdvipdfmx> { - x:scale ~ \fp_use:N \l_box_scale_x_fp \c_space_tl + 0~0~ \fp_use:N \l_box_scale_y_fp - } -%</xdvipdfmx> - } -% \end{macrocode} -% \begin{macrocode} -\cs_new_protected_nopar:Npn \driver_box_scale_end: -%<*dvips> - { - \tex_special:D - { - ps:~currentpoint~ - currentpoint~translate~ - 1~\fp_use:N \l_box_scale_x_fp \c_space_tl div~ - 1~\fp_use:N \l_box_scale_y_fp \c_space_tl div~ - scale~neg~exch~neg~exch~ - translate - } - } -%</dvips> -%<*pdfmode> - { \pdftex_pdfrestore:D } -%</pdfmode> %<*xdvipdfmx> - { \tex_special:D { x:grestore } } + \c_space_tl 0~0~cm %</xdvipdfmx> + } +%</pdfmode|xdvipdfmx> + } +\cs_new_eq:NN \driver_box_scale_end: \driver_graphic_state_restore: % \end{macrocode} % \end{macro} % @@ -354,24 +465,18 @@ % stack therefore needs a number. % \begin{macrocode} %<*pdfmode> -\int_new:N \l_driver_color_stack_int +\int_new:N \l_driver_color_stack_int %</pdfmode> % \end{macrocode} % \end{variable} % -% \begin{macro}{\driver_color_group_begin:, \driver_color_group_end:} -% \begin{macrocode} - -% \end{macrocode} -% \end{macro} -% % \begin{macro}{\driver_color_ensure_current:} % \begin{macro}[aux]{\driver_color_reset:} % Setting the current colour depends on the nature of the colour stack % available. In all cases there is a need to reset the colour after % the current group. % \begin{macrocode} -\cs_new_protected_nopar:Npn \driver_color_ensure_current: +\cs_new_protected:Npn \driver_color_ensure_current: { %<*dvips|xdvipdfmx> \tex_special:D { color~push~\l_driver_current_color_tl } @@ -382,12 +487,12 @@ %</pdfmode> \group_insert_after:N \driver_color_reset: } -\cs_new_protected_nopar:Npn \driver_color_reset: +\cs_new_protected:Npn \driver_color_reset: %<*dvips|xdvipdfmx> { \tex_special:D { color~pop } } %</dvips|xdvipdfmx> %<*pdfmode> - { \pdftex_pdfcolorstack:D \l_driver_color_stack_int pop \scan_stop: } + { \pdftex_pdfcolorstack:D \l_driver_color_stack_int pop } %</pdfmode> % \end{macrocode} % \end{macro} |