summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2011-11-25 00:14:23 +0000
committerKarl Berry <karl@freefriends.org>2011-11-25 00:14:23 +0000
commit4796116f06de1574987757c8945f6678d21f0a40 (patch)
treeb6d95196b38ef31d6021471ecbf7c4d48fcaa730 /Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx
parent27ecf3bfa131e03a530396ff6c0016cf6dffacd0 (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.dtx285
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}