图文混排的一种新的实现方式

发布于 2022-02-03 17:13:34

各位大佬,我在网上找到一段图文混排新的实现方式,但是它不能配合caption宏包给图片加标题,请各位大佬帮忙修改一下,使其能给配合caption宏包使用。

\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
\usepackage{caption}
\usepackage{varwidth}
\begin{document}
\kant[1]

\putleft[top lines=3]{\includegraphics[width=.3\textwidth]{example-image-a}}
\kant[3]

\putright{
\includegraphics[scale=0.2]{example-image-a}
\captionof*{figure}{ABCD}
}
\kant[5]
\resetindents

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

\kant[7]

\putright{\includegraphics[width=.3\textwidth]{example-image-a}}
\kant[5]


\end{document}

查看更多

关注者
1
被浏览
1.3k
2 个回答
寄存器
寄存器 2022-02-03
这家伙很懒,什么也没写!

可以用xcoffins宏包的垂直盒子实现包装一下插图,不过会不会有其它问题我不能确定,你自己再试试。同样的处理方法,也许可以将列表环境丢在盒子里,然后看成一个图片用wrapfig2排版,可能能解决你的问题。

\documentclass{article}

\usepackage{kantlipsum,xgalley,tikz}

\usepackage{caption}
\usepackage{varwidth}
\usepackage{xcoffins}

\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]

  \putleft[top lines=3]{\includegraphics[width=.3\textwidth]{example-image-a}}
  \kant[3]

  \NewCoffin \ImgCoffin
  \SetVerticalCoffin\ImgCoffin{0.2\textwidth}{
    \includegraphics[scale=0.2]{example-image-a}
    \captionof*{figure}{ABCD}
  }

  \putright{
    \TypesetCoffin\ImgCoffin
  }
  \kant[5]

  \SetVerticalCoffin\ImgCoffin{0.4\textwidth}{
    \includegraphics[scale=0.4]{example-image-a}
    \captionof{figure}{ABCD}\label{fig-test}
  }

  In figure \ref{fig-test}:
  \putleft{
    \TypesetCoffin\ImgCoffin
  }

  \resetindents

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

  \kant[7]

  \putright{\includegraphics[width=.3\textwidth]{example-image-a}}
  \kant[5]

\end{document}

以下是用wrapfig2结合xcoffins垂直盒子实现的带列表环境的图文混排,不知是不是合乎需求,如果是,则可能这个方案更为简洁。

\documentclass{ctexart}

\usepackage{xcoffins}
\usepackage{wrapfig2}
\usepackage{zhlipsum}

\begin{document}

\begin{wrapfigure}{r}{0.3\textwidth}
  \centering
  \includegraphics[scale=0.2]{example-image-a}
  \caption{示例图A}\label{fig:figure-a}
\end{wrapfigure}
\zhlipsum[1]

\NewCoffin \ImgCoffin
\SetVerticalCoffin\ImgCoffin{0.3\textwidth}{
  \begin{itemize}
    \item \LaTeX item A
    \item \LaTeX item B
    \item \LaTeX item C
  \end{itemize}
}

\begin{wrapfigure}{l}{0.4\textwidth}
  \centering
  \TypesetCoffin\ImgCoffin
  \caption{示例图B}\label{fig:figure-b}
\end{wrapfigure}
\zhlipsum[2]

\end{document}

image.png

还可以在原代码再添加captionlabel两个key,然后用coffin实现:

% https://tex.stackexchange.com/questions/309302/best-way-to-wrap-text-around-figures-in-expl3
\documentclass{article}

\usepackage{kantlipsum,tikz}

\usepackage{caption}
\usepackage{varwidth}
\usepackage{xcoffins}

\usepackage{xgalley}
\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
\bool_new:N   \l_xwrapfig_caption_num_bool
\tl_new:N     \l_xwrapfig_caption_tl
\tl_new:N     \l_xwrapfig_label_tl
\coffin_new:N \l_xwrapfig_output_coffin

\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 },
    caption .tl_set:N = \l_xwrapfig_caption_tl,
    caption .initial:n = {},
    label .tl_set:N = \l_xwrapfig_label_tl,
    label .initial:n = {},
  }

\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
      {
        \tl_if_empty:VTF \l_xwrapfig_caption_tl
          {
            #1
          }{
            #1
            \captionof*{figure}{\l_xwrapfig_caption_tl}
          }
      }
    \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 }

    \vcoffin_set:Nnn \l_xwrapfig_output_coffin { \l_xwrapfig_wd_dim }
      {
        \centering
        \bool_if:NTF \l_xwrapfig_caption_num_bool
          {
            \tl_if_empty:VTF \l_xwrapfig_caption_tl
              {
                #1
              }{
                #1
                \captionof{figure}{\l_xwrapfig_caption_tl}
                \tl_if_empty:VF \l_xwrapfig_label_tl
                  {
                    \label{\l_xwrapfig_label_tl}
                  }
              }
          }{
            \tl_if_empty:VTF \l_xwrapfig_caption_tl
              {
                #1
              }{
                #1
                \captionof*{figure}{\l_xwrapfig_caption_tl}
              }
          }
      }
    \tl_clear:N \l_xwrapfig_caption_tl
    \tl_clear:N \l_xwrapfig_label_tl

    \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 }
          \coffin_typeset:Nnnnn \l_xwrapfig_output_coffin
            {l} {vc} {0pt} {0pt}
          % #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 }
            \coffin_typeset:Nnnnn \l_xwrapfig_output_coffin
              {l} {vc} {0pt} {0pt}
            % #2
          }
      }
      \xwrapfig_postwrap:
  }
\cs_generate_variant:Nn \xwrapfig_putleft:nn { Vn }
\cs_generate_variant:Nn \xwrapfig_putright:nn { Vn }

\NewDocumentCommand\putright { s O { } +m }
  {
    \IfBooleanTF{#1}
      {
        \bool_set_false:N \l_xwrapfig_caption_num_bool
      }{
        \bool_set_true:N  \l_xwrapfig_caption_num_bool
      }
    \keys_set:nn { xwrapfig / cutout } { #2 }
    \xwrapfig_putright:Vn \l_xwrapfig_toplines_int { #3 }
  }
\NewDocumentCommand\putleft { s O { } +m }
  {
    \IfBooleanTF{#1}
      {
        \bool_set_false:N \l_xwrapfig_caption_num_bool
      }{
        \bool_set_true:N  \l_xwrapfig_caption_num_bool
      }
    \keys_set:nn { xwrapfig / cutout } { #2 }
    \xwrapfig_putleft:Vn \l_xwrapfig_toplines_int { #3 }
  }
\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]

  \putleft[top lines=3]{\includegraphics[width=.3\textwidth]{example-image-a}}
  \kant[3]

  \putright[caption=ABCD,label=fig-abcd]
  {
    \includegraphics[scale=0.2]{example-image-a}
  }
  \kant[5]

  \resetindents

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

  \putright{\includegraphics[width=.3\textwidth]{example-image-a}}
  \kant[1]

  \putleft*[caption=EFGH,label=fig-efgh]
  {
    \includegraphics[scale=0.3]{example-image-a}
  }
  \kant[5]

  \kant[7]

  In figure \ref{fig-kkkk}:

  \xwrapfigsetup{%
    cutout={%
      skip lines=1,
      hmargin=2ex,
      top lines=3,
    }
  }
  \putleft[caption=KKKK,label=fig-kkkk]
  {
    \includegraphics[scale=0.3]{example-image-a}
  }
  \kant[5]

\end{document}
雾月
雾月 2022-02-03
这家伙很懒,什么也没写!

这个实现比较简易,想要完全兼容 caption 宏包不是那么容易,你可以试试新的 wrapfig2 宏包,它兼容 wrapfig 宏包的接口,并且兼容 caption 宏包,也提供了的一些新的东西。

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览