在排版之前测量/获取标题的大小?

在排版之前测量/获取标题的大小?

为了解决部分这个问题,我想在排版之前测量标题的大小,然后用它来计算节点矩阵的大小。

我能看到的第一个问题是它\caption有一个不同的定义,取决于(至少)是否{caption}使用了包,或者只是普通的 Latex:

$ texdef -t latex \@caption

\@caption:
\long macro:#1[#2]#3->\par \addcontentsline {\csname ext@#1\endcsname }{#1}{\protect \numberline {\csname the#1\endcsname }{\ignorespaces #2}}\begingroup \@parboxrestore \if@minipage \@setminipage \fi \normalsize \@makecaption {\csname fnum@#1\endcsname }{\ignorespaces #3}\par \endgroup 

$ texdef -t latex -p caption \@caption

\@caption:
\long macro:#1[#2]#3->\ifcaption@star \else \caption@prepareanchor {#1}{#2}\memcaptioninfo {#1}{\csname the#1\endcsname }{#2}{#3}\@nameuse {nag@hascaptiontrue}\fi \par \caption@beginex {#1}{#2}{#3}\caption@setfloatcapt {\caption@boxrestore \if@minipage \@setminipage \fi \caption@normalsize \ifcaption@star \let \caption@makeanchor \@firstofone \fi \@makecaption {\csname fnum@#1\endcsname }{\ignorespaces \caption@makeanchor {#3}}\par \caption@if@minipage \@minipagetrue \@minipagefalse }\caption@end 

更糟糕的是,我想要旋转标题后的尺寸;下面是基于另一个问题

% modified from: https://tex.stackexchange.com/questions/44427/rotate-picture-with-caption

\documentclass{article}
\usepackage[demo]{graphicx}
\usepackage{adjustbox}
\usepackage{lipsum}


\begin{document}
\lipsum[1]

\begin{figure}[ht]
  \begin{adjustbox}{addcode={\begin{minipage}{\width}}{%
      \caption{%
        Here is a caption of the figure which is so long that
        it has to be wrapped over multiple lines, but should
        not exceed the width (height after the rotation) of the image.
      }%
      \makeatletter%
      \ifx\caption@@make\undefined%
        \typeout{\string\caption@@make is undefined, prob. not using \{caption\}}%
      \else%
        \typeout{\string\caption@@make is defined, prob. using \{caption\}}%
        \typeout{\string\caption@box is: \meaning\caption@box}%
      \fi%
      \typeout{\string\@makecaption is: \meaning\@makecaption}%
      \makeatother%
      \end{minipage}},rotate=90,center}
    \includegraphics[width=0.6\textwidth,height=0.4\textwidth]{demo}%
  \end{adjustbox}
\end{figure}

\lipsum[2]
\end{document}

我基本上希望通过阅读的定义\caption,找到一个排版标题的框,并测量其宽度/高度/深度;但不幸的是,这取决于是否加载{caption},以及标题的样式(例如,使用什么大小的字体) - 并且在排版标题后它仍然是信息。

顺便说一下,MWE 输出以下内容:

测试.png

...并打印出:

\caption@@make is defined, prob. using \{caption\}
\caption@box is: macro:->\ifx \@captype \@undefined \@latex@error {\noexpand \caption outside float}\@ehd \expandafter \@gobble \else \refstepcounter \@captype \expandafter \@firstofone \fi {\@dblarg {\@caption \@captype }}@box
\@makecaption is: macro:->\spacefactor \@m makecaption

...这似乎表明该{caption}包被使用,即使没有明确指定错误,请参见在下面评论(此外,我在这里得到的定义与提供的定义有点不同texdef,但没关系)。

所以我的问题是 - 如何从 MWE 获取图像上旋转标题的大小,以便我可以使用它进行计算(例如,旋转图像的高度=原始图像的宽度)?

答案1

好的,我想我明白了一些,但不确定它是否正确。本质上:

  • 我们可以使用\savebox预先将标题排版到框中;但是:
    • \caption\savebox)必须位于 内{figure};并且:
    • 必须有一个\parbox{minipage}包装\caption在里面\savebox- 否则不会应用换行

事实证明,需要使用某种换行符( \break\linebreak或)来将 定位在图像下方,就像正常情况一样 - 否则,由于某种原因,它会粘在图像的右侧。以下 MWE 结果具有此输出(单击可查看完整分辨率):\\\newline\usebox\caption

测试.png

第一个图是OP中的正常用法。

第二幅图使用\savebox{ \parbox{ ... \caption...\break \usebox{...,只是为了确认它相对于第一幅图是否正确。一般来说是正确的,除了标题有点偏离,我用红色虚线(放置在gimp)来表示。

第三个图是预先计算标题的大小,并用它来调整图像大小(新高度 = 原始高度 - 标题高度的一半)。现在这里有一些技巧,需要小心:

  • addcode=实际上\adjustbox由两部分组成;代码前(或precode=)和代码后(或appcode=);我在用空格标记的地方标明了 - 对于最后一个图,我明确使用了precode=appcode=
  • 有了这个,人们可能会认为最终的构造将是这样的:

    from \adjustbox:precode -> \begin{minipage}{\width}
    inside -> \includegraphics{...}
    from \adjustbox:appcode -> \end{minipage}
    

    ...这通常是正确的 - 除了在执行方面,“内部”的代码首先执行,甚至在之前precode=!它是:

    inside -> \includegraphics{...}
    from \adjustbox:precode -> \begin{minipage}{\width}
    from \adjustbox:appcode -> \end{minipage}
    
  • 类似地,该\width参数仅存在于 pre/appcode 中 - 不存在于“内部”代码中

  • 因此,即使你可以在预编码中,并在应用程序代码中\savebox使用它 - 也没关系,到那时图像已经排版,并且其大小已固定 - 所以我们无法根据这些点的标题大小修改其大小\caption\usebox

因此,唯一的解决方案是预先知道/设置图像的至少一个维度 - 此处为宽度(未旋转),该维度由图像和标题共享(无论如何都需要它来打破文本行)。如果人们接受这是不可避免的,那么人们可以:

  • 将 排版\caption在 中\savebox,在 内{figure},但在{adjustbox}之前
  • 然后,在“内部”代码中,当\includegraphics排版时,保存的框和它的先验尺寸都是已知的 - 因此可以及时计算出修改后的尺寸;
  • 最后,\usebox可以在这里 - 或者像下面的 MWE 一样,在的appcode=\adjustboxprecode\adjustbox需要打开\begin{minipage}{\width}

MWE 代码:

% modified from: http://tex.stackexchange.com/questions/44427/rotate-picture-with-caption

\documentclass{article}
\usepackage[demo]{graphicx}
\usepackage{adjustbox}
%\usepackage{lipsum}

\usepackage{lua-visual-debug} % compile with lualatex test.tex, for visual indication of margins

% "The text in a \savebox is typeset all on one line. You need to use a \parbox inside \savebox."
% http://tex.stackexchange.com/questions/194811/how-to-measure-the-height-and-width-of-several-lines-paragraph
% "'Missing \endgroup inserted' errors - a horizontal (LR) box which can not directly contain vertical (par) mode display material, you need a minipage to get into vertical mode"
% http://tex.stackexchange.com/questions/74896/using-align-within-savebox

% http://tex.stackexchange.com/questions/60491/latex-tracing
\def\tracingboxes{\showboxbreadth = \maxdimen
  \showboxdepth = \maxdimen}%
% must have \tracingboxes here before \tracingoutput,
% else nothing will be printed
\tracingboxes
\tracingoutput1

\begin{document}
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit,
vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur dictum ...

\begin{figure}[ht]
  \begin{adjustbox}{addcode={\begin{minipage}{\width}} {%
      \caption{%
        Here is a caption of the figure which is so long that
        it has to be wrapped over multiple lines, but should
        not exceed the width (height after the rotation) of the image.
      }%
      \end{minipage}},rotate=90,center}
    \includegraphics[width=0.4\textwidth,height=0.3\textwidth]{demo}%
  \end{adjustbox}
\end{figure}

\begin{figure}[ht]
  \newsavebox{\boxcapt}% is allocated (though not set) globally now, http://tex.stackexchange.com/questions/7134/making-register-declarations-local-undef
  \begin{adjustbox}{addcode={\begin{minipage}{\width}} {%
      \savebox{\boxcapt}{%
      \parbox{\width}{%
        \caption{%
          Here is a caption of the figure which is so long that
          it has to be wrapped over multiple lines, but should
          not exceed the width (height after the rotation) of the image.
        }%
      }% %end \parbox%
      }% %end \savebox%
      \typeout{boxcapt:  wd is: \the\wd\boxcapt, ht is: \the\ht\boxcapt, dp is: \the\dp\boxcapt}%
      %\break\fbox{\usebox{\boxcapt}}% fbox will mess up spacing
      \break% same w/ \linebreak, \\ or \newline
      \usebox{\boxcapt}%
      \end{minipage}},rotate=90,center}
    \includegraphics[width=0.4\textwidth,height=0.3\textwidth]{demo}%
  \end{adjustbox}
\end{figure}

Nam dui ligula, fringilla a, euismod sodales, sollicitudin vel, wisi. Morbi auctor lorem non justo. Nam lacus libero, pretium at, lobortis vitae, ...

% http://tex.stackexchange.com/questions/45396/is-it-possible-to-remove-length-counter-dim-etc-that-have-been-declared
% No, it's not possible: \newlength allocates a register and this allocation is permanent. If you do the \newlength inside a group, you'll lose the register name at group end, but the register will not be reusable.
\newlength{\globimw}
\newlength{\globimh}

% %%%%%%%%%%%%% nowork like this: %%%%%%%%%%%%%
% \begin{figure}[!h]
%   \begin{adjustbox}{addcode={\begin{minipage}{\width}%
%       \savebox{\boxcapt}{%
%       \parbox{\width}{%
%         \caption{%
%           Here is a caption of the figure which is so long that
%           it has to be wrapped over multiple lines, but should
%           not exceed the width (height after the rotation) of the image.
%         }%
%       }% %end \parbox%
%       }% %end \savebox%
%       \setlength{\skip0}{\ht\boxcapt}%
%       \global\setlength{\skip1}{\ht\boxcapt}% nope
%       \global\skip1=\skip0% nope
%       \global\setlength{\globimw}{\ht\boxcapt}% nope
%       \global\globimw=\globimw%
%       \typeout{boxcapt in:  wd is: \the\wd\boxcapt, ht is: \the\ht\boxcapt, dp is: \the\dp\boxcapt ; skip0: \the\skip0; skip1: \the\skip1; glp: \the\globimw}% ok here! but runs after boxcapt out?
%   } {% addcode= code after:
%       \break% same w/ \linebreak, \\ or \newline
%       \usebox{\boxcapt}%
%       \end{minipage}},rotate=90,center}
%     % use temp "scratch" register to calculate new height (rotated: width) of image, to its original height minus half height of caption
%       \typeout{boxcapt out:  wd is: \the\wd\boxcapt, ht is: \the\ht\boxcapt, dp is: \the\dp\boxcapt ; skip0: \the\skip0; skip1: \the\skip1; glp: \the\globimw}% all are zeroes!
%     \setlength{\skip0}{\dimexpr 0.3\textwidth-\expandafter\ht\boxcapt}
%     \includegraphics[width=0.4\textwidth,height=\skip0]{demo}%
%   \end{adjustbox}
% \end{figure}


\begin{figure}[!h]
  \setlength{\globimw}{0.4\textwidth}%
  \setlength{\globimh}{0.3\textwidth}%
  \global\globimw=\globimw% % must have, to propagate
  \global\globimh=\globimh%
  \savebox{\boxcapt}{%
  \parbox{\globimw}{% \width here is undefined (\adjustbox is below)
    \caption{%
      Here is a caption of the figure which is so long that
      it has to be wrapped over multiple lines, but should
      not exceed the width (height after the rotation) of the image.
    }%
  }% %end \parbox%
  }% %end \savebox%
  \begin{adjustbox}{
    precode={\begin{minipage}{\width}},
    appcode={% addcode= code after:
      \typeout{boxcapt out:  wd is: \the\wd\boxcapt, ht is: \the\ht\boxcapt, dp is: \the\dp\boxcapt ; skip1: \the\skip1; skip3: \the\skip3; glw,h: \the\globimw, \the\globimh; tw \the\textwidth}% all are here
      \break% same w/ \linebreak, \\ or \newline
      \usebox{\boxcapt}% place the caption, finally
      \vspace{\skip3}% this just to push everything "up" (i.e. left in rotated perspective), so "top" (left) edge of this figure aligns with the others - since \adjustbox does the rotation centered.
      \end{minipage}%
    },
    rotate=90,center%
  }% %closing of \begin{adjustbox}%
    %\includegraphics[width=\globimw,height=\globimh]{demo}% ok
    %\includegraphics[width=0.4\textwidth,height=0.3\textwidth]{demo}% ok
    % use temp "scratch" register to calculate new height (rotated: width) of image, to its original height minus half height of caption
    % skip1, 3 should be \global % http://tex.stackexchange.com/questions/29950/is-there-a-way-of-limiting-the-scope-of-newlength
    %\typeout{\width} % \width ! Undefined control sequence.
    \setlength{\skip3}{\dimexpr 0.5\dimexpr(\ht\boxcapt+\dp\boxcapt)}%
    \setlength{\skip1}{\dimexpr 0.3\textwidth-\skip3}%
    \global\skip1=\skip1% w. \global keeps val until next step
    \global\skip3=\skip3%
    \typeout{boxcapt inside:  wd is: \the\wd\boxcapt, ht is: \the\ht\boxcapt, dp is: \the\dp\boxcapt ; skip1: \the\skip1; skip3: \the\skip3; glw: \the\globimw}% boxcapt is now known
    \includegraphics[width=0.4\textwidth,height=\skip1]{demo}%
  \end{adjustbox}
\end{figure}

\end{document}

相关内容