原始答案

原始答案

正如今天的另一个问题wrapfig,我正在尝试寻找一种比标准解决方案(如或手动使用)更灵活的方式来让文本环绕图形\parshape,我目前专注于实验性的 expl3 包xgalley

其中一个问题是如何将图形放在文本的右侧。我的第一次尝试(如下所示)使用了不太纯粹的普通 TeX 命令和 expl3 的混合。是否有一种更“正确”和“纯粹”的、最好是基于 expl3 的方法来将图形放在右边?

当前构造还存在一些问题,包括它使用了\vadjust,这可能会扰乱 的机制xgalley。另外,我无法使 的内容\putright顶部对齐(\vtop搞乱了一切),因此 的第一个参数\putright(降低数字的行数)必须高于传递给 的参数\cutright

\documentclass{article}

\usepackage{lipsum,xgalley,graphicx}

\ExplSyntaxOn
\cs_new_eq:NN \cutright \galley_cutout_right:nn
\ExplSyntaxOff

\newcommand\putright[2]{% #1 = number of lines to lower the figure, #2 = content
    \leavevmode
    \vadjust{%
        \hfill
        \smash{%
            \lower\dimexpr#1\baselineskip-2.5\lineskip\relax\llap{#2}%
        }%
    }\ignorespaces
}

\begin{document}


\cutright{4}{.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth}
\putright{12}{\includegraphics[width=.3\textwidth]{duck}}
\lipsum

\end{document}

在此处输入图片描述

答案1

如果您确实想要问题中显示的语法,请参阅下面我的原始答案。

\cutright这次编辑修改了用户界面,消除了之前使用的需要\putright。这个版本还产生了更整洁的结果,我认为,比我第一次尝试的错误更少。

新版本定义仅有的以下命令:

\putright[<options>]{<content for cut-out>}
\putleft[<options>]{<content for cut-out>}
\resetindents
\xwrapfigsetup{<options>}

<options>是使用键值接口定义的。\xwrapfigsetup{}只知道一个键,该键本身采用使用和cutout创建的切口的默认选项列表。并且知道更多键:\putright\putleft\putright\putleft

hmargin=<dimension>

指定切口内容左侧和右侧的总水平空间(默认为 2ex);

skip lines=<integer>

指定除了适合内容所需的行数之外还允许剪切的行数(默认值为 1);

top lines=<integer>

指定剪切之前段落顶部保留的未改变的行数(默认为 2)。

其余部分都将自动处理或根本不处理,但有一个相当大的例外,即在剪切排版后恢复标准段落形状。

\putright/\putleft计算适当的缩进行数和缩进所需的宽度。然后他们将剪切部分添加到当前段落,最后排版剪切部分的内容。

这意味着简单地说

\putright{\includegraphics[width=.3\textwidth]{duck}}
\lipsum

生产

向右躲避

相似地,

\putleft[top lines=3]{\includegraphics[width=.3\textwidth]{duck}}
\kant[3]

鸭子左

跳过的额外线为鸭子的头部和尾部留出了一点空间。显然,如果您喜欢更紧或更松的配合,可以修改这一点。

完整代码(早期版本我的答案在这里

\documentclass{article}
\usepackage{kantlipsum,xgalley,tikz}
\ExplSyntaxOn
\box_new:N \l_xwrapfig_fig_box
\box_new:N \l_xwrapfig_vfig_box
\box_new:N \l_xwrapfig_hfig_box
\dim_new:N \l_xwrapfig_wd_dim
\dim_new:N \l_xwrapfig_totalht_dim
\clist_new:N \l_xwrapfig_indents_clist
\int_new:N \l_xwrapfig_lines_int
\int_new:N \l_xwrapfig_totallines_int
\fp_new:N \l_xwrapfig_adjfig_fp
\keys_define:nn { xwrapfig }
{
  cutout .code:n = {
    \keys_set:nn { xwrapfig / cutout } { #1 }
  }
}
\keys_define:nn { xwrapfig / cutout }
{
  hmargin .dim_set:N = \l_xwrapfig_adjwd_dim,
  hmargin .initial:n = { 2ex },
  skip~lines .int_set:N = \l_xwrapfig_adjlines_int,
  skip~lines .initial:n = { 1 },
  top~lines .int_set:N = \l_xwrapfig_toplines_int,
  top~lines .initial:n = { 2 },
}
\cs_generate_variant:Nn \galley_cutout_right:nn { nV }
\cs_generate_variant:Nn \galley_cutout_left:nn { nV }
\cs_new_protected:Nn \xwrapfig_prewrap:n
{
  \clist_clear:N \l_xwrapfig_indents_clist
  \clist_clear:N \l_xwrapfig_zindents_clist
  \vbox_set:Nn \l_xwrapfig_vfig_box { #1 }
  \dim_set:Nn \l_xwrapfig_totalht_dim { \box_ht:N \l_xwrapfig_vfig_box + \box_dp:N \l_xwrapfig_vfig_box }
  \hbox_set:Nn \l_xwrapfig_hfig_box { #1 }
  \dim_set:Nn \l_xwrapfig_wd_dim { \box_wd:N \l_xwrapfig_hfig_box + \l_xwrapfig_adjwd_dim }
  \int_set:Nn \l_xwrapfig_totallines_int { ( \l_xwrapfig_totalht_dim / \baselineskip ) + \l_xwrapfig_adjlines_int }
  \int_zero:N \l_xwrapfig_lines_int
  \int_do_while:nn { \l_xwrapfig_lines_int < \l_xwrapfig_totallines_int }
  {
    \int_incr:N \l_xwrapfig_lines_int
    \clist_put_right:Nn \l_xwrapfig_indents_clist { \l_xwrapfig_wd_dim }
  }
}
\cs_new_protected:Nn \xwrapfig_postwrap:
{
  \box_set_ht:Nn \l_xwrapfig_fig_box { 0pt }
  \box_set_dp:Nn \l_xwrapfig_fig_box { 0pt }
  \skip_vertical:n { -\baselineskip }
  \box_use:N \l_xwrapfig_fig_box
}
\cs_new_protected:Nn \xwrapfig_putright:nn
{
  \xwrapfig_prewrap:n { #2 }
  \galley_cutout_right:nV { #1 } \l_xwrapfig_indents_clist
  \vbox_set:Nn \l_xwrapfig_fig_box
  {
    \fp_set:Nn \l_xwrapfig_adjfig_fp { ( #1 + .5\l_xwrapfig_adjlines_int ) * \baselineskip }
    \skip_vertical:n  { \fp_to_dim:N \l_xwrapfig_adjfig_fp }
    \hbox_to_wd:nn { \linewidth } { \skip_horizontal:n { \linewidth - \l_xwrapfig_wd_dim + .5\l_xwrapfig_adjwd_dim } #2 }
  }
  \xwrapfig_postwrap:
}
\cs_new_protected:Nn \xwrapfig_putleft:nn
{
  \xwrapfig_prewrap:n { #2 }
  \galley_cutout_left:nV { #1 } \l_xwrapfig_indents_clist
  \vbox_set:Nn \l_xwrapfig_fig_box
  {
    \fp_set:Nn \l_xwrapfig_adjfig_fp { ( #1 + .5\l_xwrapfig_adjlines_int ) * \baselineskip }
    \skip_vertical:n  { \fp_to_dim:N \l_xwrapfig_adjfig_fp }
    \hbox_to_wd:nn { \l_xwrapfig_wd_dim } { \skip_horizontal:n { .5\l_xwrapfig_adjwd_dim } #2 }
  }
  \xwrapfig_postwrap:
}
\cs_generate_variant:Nn \xwrapfig_putleft:nn { Vn }
\cs_generate_variant:Nn \xwrapfig_putright:nn { Vn }
\NewDocumentCommand\putright { O { } +m }
{
  \keys_set:nn { xwrapfig / cutout } { #1 }
  \xwrapfig_putright:Vn \l_xwrapfig_toplines_int { #2 }
}
\NewDocumentCommand\putleft { O { } +m }
{
  \keys_set:nn { xwrapfig / cutout } { #1 }
  \xwrapfig_putleft:Vn \l_xwrapfig_toplines_int { #2 }
}
\NewDocumentCommand\resetindents { }
{
  \galley_parshape_set_multi:nnnN { 0 } { 0pt } { 0pt } \c_true_bool
}
\NewDocumentCommand\xwrapfigsetup { m }
{
  \keys_set:nn { xwrapfig } { #1 }
}
\ExplSyntaxOff

\begin{document}
\kant[1]

\putright[top lines=0]{%
  \begin{tikzpicture}
    \newcommand*\len{1.5}
    \draw [thick] (0,0,\len) coordinate (a) \foreach \i/\j in {(\len,0,\len)/b,(\len,0,0)/c,(\len,\len,0)/g,(0,\len,0)/h,(0,\len,\len)/e,(\len,\len,\len)/f} {-- \i coordinate (\j)} -- (g) (f) -- (b) (a) -- (e);
    \coordinate (d) at (0,0,0);
    \draw [gray] (a) -- (d) edge (c) -- (h);
    \foreach \i/\j in {a/left,b/right,c/right,d/left,e/left,f/right,g/above,h/above} \node at (\i) [\j] {\i};
  \end{tikzpicture}}
Let $G S_8$ and $X = \{\{a,g\},\{b,h\},\{c,e\},\{d,f\}\}$
\kant[1-2]

\kant[3]
\clearpage

\putright[top lines=0]{%
  \begin{tikzpicture}
    \newcommand*\len{1.5}
    \draw [thick] (0,0,\len) coordinate (a) \foreach \i/\j in {(\len,0,\len)/b,(\len,0,0)/c,(\len,\len,0)/g,(0,\len,0)/h,(0,\len,\len)/e,(\len,\len,\len)/f} {-- \i coordinate (\j)} -- (g) (f) -- (b) (a) -- (e);
    \coordinate (d) at (0,0,0);
    \draw [gray] (a) -- (d) edge (c) -- (h);
    \foreach \i/\j in {a/left,b/right,c/right,d/left,e/left,f/right,g/above,h/above} \node at (\i) [\j] {\i};
  \end{tikzpicture}}
Let $G S_8$ and $X = \{\{a,g\},\{b,h\},\{c,e\},\{d,f\}\}$
\kant[1-2]

\putleft[top lines=3]{\includegraphics[width=.3\textwidth]{duck}}
\kant[3]
\clearpage

\putleft[top lines=0]{%
  \begin{tikzpicture}
    \newcommand*\len{1.5}
    \draw [thick] (0,0,\len) coordinate (a) \foreach \i/\j in {(\len,0,\len)/b,(\len,0,0)/c,(\len,\len,0)/g,(0,\len,0)/h,(0,\len,\len)/e,(\len,\len,\len)/f} {-- \i coordinate (\j)} -- (g) (f) -- (b) (a) -- (e);
    \coordinate (d) at (0,0,0);
    \draw [gray] (a) -- (d) edge (c) -- (h);
    \foreach \i/\j in {a/left,b/right,c/right,d/left,e/left,f/right,g/above,h/above} \node at (\i) [\j] {\i};
  \end{tikzpicture}}
Let $G S_8$ and $X = \{\{a,g\},\{b,h\},\{c,e\},\{d,f\}\}$\par
\kant[4]

\putright{\includegraphics[width=.3\textwidth]{duck}}
\kant[5]
\resetindents

\xwrapfigsetup{%
  cutout={%
    skip lines=3,
    hmargin=5ex,
    top lines=1,
  }
}

\kant[6]

\kant[7]

\putright{\includegraphics[width=.3\textwidth]{duck}}
\kant[5]


\end{document}

鸭子和方块

请注意,我不清楚如何将其仅应用于当前文本块。它的工作方式非常奇怪。我尝试使用,\galley_parshape_set_single:nVVN但只能让它正常工作\putleft

\resetindents因此,提供用于重置段落缩进。这需要在\putleft或之后\putright使用。

我不明白的是,为什么第二段\kant[1-2]不受影响,而后面的一段\kant[3]却受影响(如wipet 指出) 或者为什么左侧剪切空间在最后一次使用后几个段落中重复出现。

我怀疑关于如何做到这一点存在一些根本性的问题,但我现在还不明白。

原始答案

你想要这样的东西吗?

\documentclass{article}
\usepackage{lipsum,xgalley,graphicx}
\ExplSyntaxOn
% don't use \cs_new_eq for document-level macros (which necessarily fail to conform to expl3 syntax) - use xparse
\NewDocumentCommand\cutright { m m }
{
  \galley_cutout_right:nn { #1 } { #2 }
}
\coffin_new:N \l_gaussler_fig_coffin
\box_new:N \l_gaussler_fig_box
\NewDocumentCommand\putright { m m }
{
  \vbox_set:Nn \l_tmpa_box { #2 }
  \dim_set:Nn \l_tmpa_dim { \box_dp:N \l_tmpa_box + \box_ht:N \l_tmpa_box }
  \int_set:Nn \l_tmpa_int { ( #1 - ( \l_tmpa_dim / \baselineskip ) ) /2 }
  \skip_vertical:n { #1\baselineskip - \l_tmpa_dim +\l_tmpa_int\baselineskip }
  \skip_horizontal:N \linewidth
  \vbox_to_zero:n
  {
    \hbox_overlap_left:n { #2 }
  }
  \skip_vertical:n { -#1\baselineskip + \l_tmpa_dim - \l_tmpa_int\baselineskip  }
}
\ExplSyntaxOff

\begin{document}


\cutright{4}{.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth,.35\textwidth}
\putright{9}{\includegraphics[width=.3\textwidth]{duck}}
\lipsum

\end{document}

糊涂鸭

答案2

我不明白两件事。当基于 TeX 基元的解决方案更简单、更直接时,为什么需要显式 expl3 解决方案。为什么在\cutright和中使用不同的数据\putright。第一个参数 (4) 表示未触及的行数,但第二个参数 (12)——我不知道它是什么。

我可以帮你做第二件事。定义:

\def\putright#1#2{\vskip\parskip
   \hbox to\hsize{\hss
      \vbox to0pt{\kern#1\baselineskip\kern-.8\baselineskip \hbox{#2}\vss}}
   \nobreak\vskip-\parskip\vskip-\baselineskip
}

然后您可以对两者使用相同的数据:\cutright{4}{...}\putright{4}{...}

相关内容