如何使用 expl3 语法在零宽度和指定高度的框中设置内容(可选择旋转)?

如何使用 expl3 语法在零宽度和指定高度的框中设置内容(可选择旋转)?

使用Steven B. Segletes 的回答,我可以将某个东西水平居中,也可以选择旋转它,使用

\centering
\makebox[0pt]{\rotatebox{<angle>}{<contents>}}
\par

但是,我还想指定框具有指定的高度。此外,由于我使用已经使用 expl3 语法的命令执行此操作,因此我认为尝试使用 expl3 函数可能有意义。(但是,我并不坚持这个想法 - 我的宏已经是 TeX、LaTeX2e 和 expl3 语法的混合体,因此再多一点实际上不会损害我还没有违反的任何东西。)

我可以使用以下命令获得我想要的效果:

\documentclass[a4paper]{article}
\usepackage{expl3,xparse,geometry}
\geometry{margin=20mm}
\ExplSyntaxOn
\tl_new:N \l_cfr_troibocs_tl
\bool_new:N \l_cfr_bocs_bool
\keys_define:nn { mycommand }
{
  hfit .bool_set:N = \l_cfr_hfit_bool,
  hfit .default:n = true,
  vfit .bool_set:N = \l_cfr_vfit_bool,
  vfit .default:n = true,
  rotate .code:n = {
    \tl_set:Nn \l_cfr_troibocs_tl {#1}
    \bool_set_true:N \l_cfr_troi_bool },
  troi .bool_set:N = \l_cfr_troi_bool,
  troi .default:n = true,
  troibocs .tl_set:N = \l_cfr_troibocs_tl,
  troibocs .initial:n = 0,
}
\NewDocumentCommand\mycommand { o m }{
  \group_begin:
  \IfValueT{#1}{ \keys_set:nn { mycommand } { #1 } }
  % from Steven B. Segletes's answer at https://tex.stackexchange.com/a/162202/
    \bool_if:NTF \l_cfr_troi_bool
    {
      \hbox_set:Nn \g_tmpa_box {\rotatebox[]{\l_cfr_troibocs_tl}{\file_input:n {#2}}}
    }
    {
      \hbox_set:Nn \g_tmpa_box {\file_input:n {#2}}
    }
    \bool_if:NT \l_cfr_vfit_bool
    {
      \box_set_ht:Nn \g_tmpa_box {.8\textheight}
    }
    \centering
    \bool_if:NTF \l_cfr_hfit_bool
    {
      \makebox[0pt]{\box_use:N \g_tmpa_box}
    }{
      \box_use:N \g_tmpa_box
    }
    \par
  \group_end:
}
\ExplSyntaxOff
\usepackage{filecontents,tikz}
\begin{filecontents}{mytikz.tex}
  \begin{tikzpicture}
    \path [draw, fill] (0,0) rectangle +(265mm,175mm);
  \end{tikzpicture}
\end{filecontents}

\begin{document}
\mycommand[
  rotate=90,
  vfit,
  hfit
  ]{mytikz}
\end{document}

有没有更好/更干净的方法来做到这一点?

我尝试将更多的定义翻译成 expl3 语法,但迄今为止都遭遇了彻底的失败。我怀疑我的困难与egreg 的回答但我不确定,而且无论如何我也不确定如何修改代码。

如果我使用\hbox_to_zero:n,那么框就不会水平居中,但\leavemode在这种情况下我不能直接将它放在前面,因为那样会完全破坏一切。我也不能在改变高度时改变框的宽度,因为\box_set_wd:Nn \g_tmpa_box {0pt}没有效果。

[我也尝试过\rotatebox用新的实验扩展来替换它\box_rotate:Nn,但是相对于我的预期,它的行为很奇怪,所以我放弃了这个想法。]

答案1

如果我理解您的要求,标准方法就足够了:

\documentclass{article}
\usepackage{graphicx,lipsum,color}

\newcommand\rotbox[3][\dimexpr\height+\depth\relax]{%
  % #1 is the final height, #2 is the angle, #3 the contents
  \raisebox{\depth}[#1][0pt]{%
    \makebox[0pt]{%
      \rotatebox{#2}{\color{red}#3}%
    }%
  }%
}

\begin{document}

\lipsum[3]
\begin{center}
XX\rotbox{45}{This text is rotated}XX
\end{center}
\lipsum*[2]
\begin{center}
XX\rotbox[4cm]{45}{This text is rotated}XX
\end{center}
\lipsum[2]

\end{document}

我添加了红色只是为了更清晰。如果你想要自然宽度(旋转后),请删除\makebox[0pt]

在此处输入图片描述

可能的expl3版本:

\documentclass{article}
\usepackage{graphicx,lipsum,color,xparse}

\ExplSyntaxOn
\NewDocumentCommand{\xrotbox}{O{}m}
 {
  \group_begin:
  \keys_set:nn { cfr/rotbox } { #1 }
  \cfr_xrotbox:n { #2 }
  \group_end:
 }

\keys_define:nn { cfr/rotbox }
 {
  hfit .bool_set:N = \l_cfr_hfit_bool,
  hfit .default:n = true,
  vfit .bool_set:N = \l_cfr_vfit_bool,
  vfit .default:n = true,
  rotate .fp_set:N = \l_cfr_rotate_fp,
  rotate .initial:n = 0,
  %troi .bool_set:N = \l_cfr_troi_bool,
  %troi .default:n = true,
  %troibocs .tl_set:N = \l_cfr_troibocs_tl,
  %troibocs .initial:n = 0,
 }

\box_new:N \l_cfr_xrotbox_box

\cs_new_protected:Npn \cfr_xrotbox:n #1
 {
  \hbox_set:Nn \l_cfr_xrotbox_box { #1 }
  \fp_compare:nF { \l_cfr_rotate_fp = \c_zero_fp }
   {
    \box_rotate:Nn \l_cfr_xrotbox_box { \l_cfr_rotate_fp }
   }
  \hbox_set:Nn \l_cfr_xrotbox_box
   {
    \box_move_up:nn { \box_dp:N \l_cfr_xrotbox_box } { \box_use:N \l_cfr_xrotbox_box }
   }
  \bool_if:NF \l_cfr_hfit_bool
   {
    \hbox_set_to_wd:Nnn \l_cfr_xrotbox_box { 0pt }
     {
      \hss \box_use:N \l_cfr_xrotbox_box \hss
     }
   }
  \bool_if:NF \l_cfr_vfit_bool
   {
    \box_set_ht:Nn \l_cfr_xrotbox_box { 0pt }
   }
  \leavevmode\box_use:N \l_cfr_xrotbox_box
 }
\ExplSyntaxOn

\begin{document}

\lipsum[3]
\begin{center}
XX\xrotbox[rotate=45]{This text is rotated}XX
\end{center}
\lipsum*[2]
\begin{center}
XX\xrotbox[rotate=45,hfit,vfit]{This text is rotated}XX
\end{center}
\lipsum[2]

\end{document}

在此处输入图片描述

答案2

这是基于egreg 的回答但适合我实际想要做的事情。恐怕我最初的问题没有充分解释上下文,因此不清楚。因此,我认为 egreg 的答案非常好。但是,如果它对其他人有用,我也会发布我通过调整该答案得出的代码。

代码的目的是排版一个对于可用空间来说确实太大但从人(非 TeX)的角度来看又适合的图像。例如,思维导图可以稍微溢出页面区域而不会“看起来”太大,因为它包含合理数量的空白空间。

我实际使用的命令是输入一个文件,并可选地排版标题和副标题、目录条目和参考书目。通常,输入的内容主要是文本。但是,我想使用相同的命令排版带有标题的单页图像,以便确保格式的一致性等。在这种情况下,文件的内容被放入一个框中并进一步处理,而在标准情况下,它只是正常输入。

下面的代码只涉及图像情况。也就是说,它不区分常规情况和图像情况,也不担心标题、目录或参考书目。

\mycommand[]{}接受由 0 到 3 个键组成的可选参数:

  • rotate=<angle>内容是否需要轮换;
  • hfit如果必须将内容置于宽度为的盒子中央,以使其水平放置0pt
  • vfit如果要强制内容物垂直放置,请将其放置在一个高度为.8\textheight盒子的自然高度和高度之差的一半的盒子中.8\textheight

tikzpicture强制参数是要输入的文件的名称,例如包含思维导图的文件的名称。

示例图片比 稍宽,\textheight稍高\textwidth。因此,即使旋转,就 TeX 而言,它也太大了。(由于它是一个黑色的盒子,所以对人类来说它也太大了。但关键是它的尺寸与我所关注的图像种类足够相似。)

我不确定这是否正确,但到目前为止它的完整版本似乎有效......

\documentclass[a4paper]{article}
\usepackage{expl3,xparse,geometry}
\geometry{margin=20mm}
\ExplSyntaxOn
\fp_new:N \l_cfr_troibocs_fp
\bool_new:N \l_cfr_bocs_bool
\dim_zero_new:N \l_cfr_width_dim
\box_new:N \l_cfr_bocs_box
\NewDocumentCommand\mycommand{O{}m}
 {
  \group_begin:
  \centering
  \keys_set:nn { cfr/rotbox } { #1 }
  \cfr_troibocs:n { 0pt } { .8\textheight } { #2 }
  \par
  \group_end:
 }

\keys_define:nn { cfr/rotbox }
 {
  hfit .bool_set:N = \l_cfr_hfit_bool,
  hfit .default:n = true,
  vfit .bool_set:N = \l_cfr_vfit_bool,
  vfit .default:n = true,
  rotate .fp_set:N = \l_cfr_troibocs_fp,
  rotate .initial:n = 0,
 }
\cs_new_protected:Npn \cfr_troibocs:n #1 #2 #3
 {
  \hbox_set:Nn \l_cfr_bocs_box { #3 }
  \fp_compare:nF { \l_cfr_troibocs_fp = \c_zero_fp }
   {
    \box_rotate:Nn \l_cfr_bocs_box { \l_cfr_troibocs_fp }
   }
  \hbox_set:Nn \l_cfr_bocs_box
   {
    \box_move_up:nn { \box_dp:N \l_cfr_bocs_box } { \box_use:N \l_cfr_bocs_box }
   }
  \bool_if:NT \l_cfr_hfit_bool
   {
    \hbox_set_to_wd:Nnn \l_cfr_bocs_box { #1 }
     {
      \hss \box_use:N \l_cfr_bocs_box \hss
     }
   }
  \bool_if:NT \l_cfr_vfit_bool
   {
     \dim_set:Nn \l_cfr_width_dim { \box_ht:N \l_cfr_bocs_box }
     \dim_sub:Nn \l_cfr_width_dim { #2 }
     \dim_compare:nNnT {0pt} < \l_cfr_width_dim
     {
       \vbox_set_to_ht:Nnn \l_cfr_bocs_box { #2 + .5\l_cfr_width_dim }
         {
           \vss \box_use:N \l_cfr_bocs_box \vss
         }
     }
   }
  \leavevmode\box_use:N \l_cfr_bocs_box
 }
\ExplSyntaxOff
\usepackage{filecontents,tikz}
\begin{filecontents}{mytikz.tex}
  \begin{tikzpicture}
    \path [draw, fill] (0,0) rectangle +(265mm,175mm);
  \end{tikzpicture}
\end{filecontents}

\begin{document}
\mycommand[
  rotate=90,
  hfit,
  vfit
  ]{\input{mytikz}}
\end{document}

虚拟输出

相关内容