根据 pdf 扩展的绝对页面高度进行排序

根据 pdf 扩展的绝对页面高度进行排序

我不确定如何提出这个问题,因此如果有必要的话我只会进行一些编辑。

PDF 扩展目前至少使用以下三个宏扩展了基本的 TeX 宏

  1. \pdfsavepos
  2. \pdflastxpos
  3. \pdflastypos

允许用户提取当前页面定位出货时。TUG 文章对此进行了详细讨论:https://www.tug.org/TUGboat/tb30-1/tb94zyka.pdf

我正在尝试根据 对计数器进行排序\pdfsavepos。我的想法是,我有几个宏,比如说,\csname macro-1-savedposition\endcsname一直到,比如说\csname macro-4-savedposition\endcsname(在宏的四个实例的情况下),并且扩展的值保持\the\pdflastypos。然后我希望对这些宏进行排序,以便另一个宏,比如说\csname macro-3\endcsname,根据 savedposition 实例的值正确扩展。

举一个具体的例子,假设我有四个宏(箭头后的值是宏的(一次)扩展定义):

  1. \csname macro-1-savedposition\endcsname -> 12345
  2. \csname macro-2-savedposition\endcsname -> 1234
  3. \csname macro-3-savedposition\endcsname -> 123456
  4. \csname macro-4-savedposition\endcsname -> 1234567

由于页面定位是从底部到顶部进行的,我希望按“最大优先”的顺序对它们进行排序,因此在这种情况下顺序应该是。4-3-1-2相应的宏应该具有扩展值\csname macro-4\endcsname=1\csname macro-3\endcsname=2和。\csname macro-1\endcsname=3\csname macro-2\endcsname=4

我已经思考了一段时间如何完成这项工作,但感觉自己陷入了困境。在最简单的情况下,我可以在宏调用时而不是在页面输出时提取绝对页面定位,但显然该机制不是以这种方式编码的,我不确定是否支持此功能。

深入挖掘,这意味着必须追溯添加与保存的位置相对应的标识符,因为(据我所知)计数器通常不会在页面输出时增加。这种对定位计算和计数器值的异步处理使生活变得更加困难。一种选择是生成这些定位命令的链,这也是我在另一个问题中使用的方法:使用 pdfsavepos 重新排版 marginpars,但我在本网站或有关 TeX 语言的国外网站上没有找到任何可以循环这些链的内容。

继续进行排序部分,我发现一个有用但无法适应这种用例的(字母)数字排序的初步实现如下:如何对字母数字列表进行排序(我可能在这方面搞乱了扩展控制。)

下面的例子很好地说明了这个问题:

\documentclass{article}
\usepackage{lipsum}
\makeatletter
\def\@oddfoot{\hskip\textwidth\smash{\raise\footskip\vbox to .9\textheight{\hsize\marginparwidth%
  \hrule\@height\z@%
  \box123
  \vskip\z@\@plus\textheight}}}
\def\mymacroX{\setbox123\hbox{Here is my macro X \mymacro}}
\def\saveposition#1{%
\pdfsavepos\write\@auxout{%
  \noexpand\savedpos%
    {#1}{\the\c@page}{\the\pdflastxpos}{\the\pdflastypos}}}
\def\savedpos#1#2#3#4{%
\begingroup
  \let\@positions\relax
  \expandafter\xdef\csname sp@#1-#2\endcsname{%
    \expandafter\ifx\csname sp@#1-#2\endcsname\relax
    \else
      \csname sp@#1-#2\endcsname
    \fi
  \@positions{#3}{#4}}%
  \endgroup}%
\newcount\mymacrocounter
\newcount\mymacrohelper
\def\mymacro{%
\saveposition{mymacro}
}
\makeatother
\begin{document}
\lipsum[1]
\mymacro
\mymacroX
\lipsum[1]
\mymacro
\lipsum[1]
\mymacro
\lipsum[1]
\mymacro
\end{document}

如果我们查看该aux文件,我们会发现由 创建的第四个实例\mymacroX的 值\pdflastypos比前一个实例更高,尽管它被调用第二并排版最后的

当我最终成功编译一个时,我会添加更多示例。

编辑我能想到的最具体的例子是实际用例。代码可以在以下位置找到:gist.github.com/TobiasBouma/de4fa02c4e7fa12141cagist.github.com/TobiasBouma/798444f698dd637cafa2,这说明了为什么我要要求基于位置解决方案。(为了完整性,我不建议将该代码用作 MWE。)

答案1

这里我做了一个冒泡排序(带有可以注释的诊断)。然后我采用了 OP 请求的间接寻址。

已编辑以自动化必要的初始化。

\documentclass{article}
\usepackage{ifthen}

    \expandafter\def\csname macro-1-savedposition\endcsname{12345}
    \expandafter\def\csname macro-2-savedposition\endcsname{1234}
    \expandafter\def\csname macro-3-savedposition\endcsname{123456}
    \expandafter\def\csname macro-4-savedposition\endcsname{1234567}
%    \expandafter\def\csname macro-5-savedposition\endcsname{12}

\def\npos{4}
%\def\npos{5}

\newcounter{outer}
\newcounter{inner}
\newcounter{cntA}
\newcounter{cntB}
\newcommand\sortpos[1]{%
% FIRST DO A BUBBLE SORT
  \setcounter{outer}{0}%
  \whiledo{\value{outer}<#1}{%
    \stepcounter{outer}%
    \expandafter\edef\csname macro--\theouter\endcsname{\theouter}%
    \bubblesort{\theouter}%
    \listorder{#1}\par% CAN COMMENT THIS WHEN SATISFIED WITH OUTPUT
  }%
% THEN ACHIEVE THE INDIRECT ADDRESSING
  \setcounter{outer}{0}%
  \whiledo{\value{outer}<#1}{%
    \stepcounter{outer}%
    \expandafter\edef%
      \csname macro-\csname macro--\theouter\endcsname\endcsname{\theouter}%
  }%
}
\newcommand\bubblesort[1]{%
  \setcounter{inner}{#1}%
  \whiledo{\value{inner} > 1}{%
    \setcounter{cntA}{\theinner}%
    \edef\entryA{%
      \csname macro-\csname macro--\thecntA\endcsname-savedposition\endcsname}%
    \setcounter{cntB}{\numexpr\theinner-1}%
    \edef\entryB{%
      \csname macro-\csname macro--\thecntB\endcsname-savedposition\endcsname}%
    \ifthenelse{\entryB<\entryA}{%
      \edef\tmp{\csname macro--\thecntB\endcsname}%
      \expandafter\edef\csname macro--\thecntB\endcsname{%
        \csname macro--\thecntA\endcsname}%
      \expandafter\edef\csname macro--\thecntA\endcsname{\tmp}%
    }{}%
    \addtocounter{inner}{-1}%
  }%
}
% CAN REMOVE THE FOLLOWING DIAGNOSTIC MACROS AND INITIALIZATIONS 
% WHEN HAPPY WITH ALGORITHM
\newcounter{diag}
\newcommand\init[1]{%
  \setcounter{diag}{0}%
  \whiledo{\value{diag}<#1}{%
    \stepcounter{diag}%
    \expandafter\def\csname macro--\thediag\endcsname{0}%
  }%
}
\init{\npos}
\newcommand\listorder[1]{(%
  \setcounter{diag}{0}%
  \whiledo{\value{diag}<#1}{%
    \stepcounter{diag}%
    \csname macro--\thediag\endcsname%
    \ifthenelse{\value{diag}=#1}{}{-}%
  }%
  )
}
%%%%% END DIAGNOSTICS
\begin{document}

\sortpos{\npos}

\noindent\hrulefill

\verb|\csname macro-1\endcsname|: \csname macro-1\endcsname

\verb|\csname macro-2\endcsname|: \csname macro-2\endcsname

\verb|\csname macro-3\endcsname|: \csname macro-3\endcsname

\verb|\csname macro-4\endcsname|: \csname macro-4\endcsname

%\verb|\csname macro-5\endcsname|: \csname macro-5\endcsname

\end{document}

在此处输入图片描述


只是为了证明一个更大的情况,

\expandafter\def\csname macro-1-savedposition\endcsname{12345}
\expandafter\def\csname macro-2-savedposition\endcsname{1234}
\expandafter\def\csname macro-3-savedposition\endcsname{123456}
\expandafter\def\csname macro-4-savedposition\endcsname{1234567}
\expandafter\def\csname macro-5-savedposition\endcsname{12}
\expandafter\def\csname macro-6-savedposition\endcsname{123}

\def\npos{6}

结果是

在此处输入图片描述

应该(4,3,1,2,6,5)解释为 savedposition 4 中的最大数字、savedposition 3 中第二大数字等,以及 savedposition 5 中的最小数字。

间接寻址是这样的

\csname macros-1\endcsname: 3
\csname macros-2\endcsname: 4
\csname macros-3\endcsname: 2
\csname macros-4\endcsname: 1
\csname macros-5\endcsname: 6
\csname macros-6\endcsname: 5

意味着 savedposition 1 是第三大,savedposition 2 是第四大,savedposition 3 是第二大,等等。

答案2

我认为您\pdfsavepos根本不想要。您对打印时图形的坐标并不真正感兴趣,您只想使用基于排版顺序的编号,因此您应该记录该顺序,而不是位置。

请注意,仅当您使用非浮动浮点数时,图形编号才会乱序,因为浮动机制在保持顺序方面会遇到一些麻烦。

然而,这里有一份标题顺序可疑的文件:

在此处输入图片描述

由。。。生产

\documentclass{article}


\usepackage{capt-of}
\raggedright
\setlength\textheight{.5\textheight}

\begin{document}

\begin{minipage}{\textwidth}\centering
\fbox{HHHHH}
\captionof{figure}{zzzzz}
\end{minipage}

text text text

\begin{figure}[t]\centering
\fbox{TTTT}
\caption{ttttttttt}
\end{figure}

\begin{minipage}{\textwidth}\centering
\fbox{HHHHH}
\captionof{figure}{zzzzz}
\end{minipage}

\begin{figure}[b]\centering
\fbox{BBBB}
\caption{bbbb}
\end{figure}

\begin{minipage}{\textwidth}\centering
\fbox{HHHHH}
\captionof{figure}{z2z2z2z2z2z}
\end{minipage}

text tetx text 
\end{document}

如果您记录了标题命令的顺序,您可以定义\thefigure使用修改后的编号方案:

在此处输入图片描述

\documentclass{article}

\let\oldcaption\caption
\makeatletter
\newcount\realfig
\def\caption{%
\protected@write\@auxout{}{\string\real@fig{\the\value{figure}}}%
\expandafter\csname real@@fig@\the\value{figure}\endcsname
\oldcaption}
\def\real@fig#1{%
\global\advance\realfig\@ne
\expandafter\xdef\csname real@@fig@#1\endcsname{%
\def\noexpand\thefigure{\the\realfig}%
}}
\makeatletter

\usepackage{capt-of}
\raggedright
\setlength\textheight{.5\textheight}

\begin{document}

\begin{minipage}{\textwidth}\centering
\fbox{HHHHH}
\captionof{figure}{zzzzz}
\end{minipage}

text text text

\begin{figure}[t]\centering
\fbox{TTTT}
\caption{ttttttttt}
\end{figure}

\begin{minipage}{\textwidth}\centering
\fbox{HHHHH}
\captionof{figure}{zzzzz}
\end{minipage}

\begin{figure}[b]\centering
\fbox{BBBB}
\caption{bbbb}
\end{figure}

\begin{minipage}{\textwidth}\centering
\fbox{HHHHH}
\captionof{figure}{z2z2z2z2z2z}
\end{minipage}

text tetx text 
\end{document}

答案3

这是我的初步解决方案,它整合了所有内容。它尚未完全发挥作用,但一旦发挥作用,我就会更新它。

\documentclass{classnofonts}

\usepackage[demo]{graphicx}
\usepackage{letltxmacro}
\usepackage{atbegshi}
\usepackage{ifthen}
\usepackage{everypage}

\makeatletter
\newcount\caption@counter@i \caption@counter@i\z@
\newcount\caption@counter@ii \caption@counter@ii\z@
\newcount\caption@counter@iii \caption@counter@iii\z@

\def\savecaptionposition{%
\pdfsavepos
\global\advance\caption@counter@i\@ne
\divide\caption@counter@i\tw@
\expandafter\write
\expandafter\@auxout
\expandafter{%
\expandafter\string
\expandafter\expandafter
\expandafter\string
\expandafter\gdef
\expandafter\noexpand
\expandafter\csname
\expandafter m%
\expandafter a%
\expandafter c%
\expandafter r%
\expandafter o%
\expandafter-\the\caption@counter@i-savedposition-page-\thepage
\string\endcsname
{\the\pdflastypos}}}

\LetLtxMacro{\oldcaption}{\caption}

\def\caption[#1]#2{%
\global\advance\caption@counter@ii\@ne
\expandafter\ifx\csname macro-\the\caption@counter@ii\endcsname\relax
  \def\thefigure{\textbf{??}}%
\else
  \advance\caption@counter@iii\csname macro-\the\caption@counter@ii\endcsname
  \def\thefigure{\the\caption@counter@iii}%
\fi
\oldcaption[#1]{#2\protect\savecaptionposition}}

\newcounter{outer}
\newcounter{inner}
\newcounter{cntA}
\newcounter{cntB}
\newcommand\sortpos[1]{%
  \setcounter{outer}{0}%
  \whiledo{\value{outer}<#1}{%
    \stepcounter{outer}%
    \expandafter\edef\csname macro--\theouter\endcsname{\theouter}%
    \bubblesort{\theouter}%
  }%
  \setcounter{outer}{0}%
  \whiledo{\value{outer}<#1}{%
    \stepcounter{outer}%
    \expandafter\xdef
      \csname macro-\csname macro--\theouter\endcsname\endcsname{\theouter}%
  }%
}
\newcommand\bubblesort[1]{%
  \setcounter{inner}{#1}%
  \whiledo{\value{inner} > 1}{%
    \setcounter{cntA}{\theinner}%
    \edef\entryA{%
      \csname macro-\csname macro--\thecntA\endcsname-savedposition-page-\thepage\endcsname}%
    \setcounter{cntB}{\numexpr\theinner-1}%
    \edef\entryB{%
      \csname macro-\csname macro--\thecntB\endcsname-savedposition-page-\thepage\endcsname}%
    \ifthenelse{\entryB<\entryA}{%
      \edef\tmp{\csname macro--\thecntB\endcsname}%
      \expandafter\edef\csname macro--\thecntB\endcsname{%
        \csname macro--\thecntA\endcsname}%
      \expandafter\edef\csname macro--\thecntA\endcsname{\tmp}%
    }{}%
    \addtocounter{inner}{-1}}}


\AtBeginDocument{%
\ifdefined\runNo
  \ifnum\the\runNo>\tw@
    \ifnum\csname npos-page-\thepage\endcsname>\z@
      \sortpos{\csname npos-page-\thepage\endcsname}%
\fi\fi\fi}

\AtBeginDocument{%
  \ifx\runNo\@undefined
    \newcount\runNo \runNo\@ne
  \else
    \ifnum\the\runNo<\thr@@
      \advance\runNo\@ne
  \fi\fi
  \write\@auxout{%
    \string\newcount\string\runNo ^^J
    \string\global\runNo=\the\runNo}}

\AtBeginShipout{%
\immediate\write\@auxout{\string\expandafter\string\gdef\noexpand\csname npos-page-\thepage\string\endcsname{\the\caption@counter@ii}}%
\ifdefined\runNo
  \ifnum\the\runNo>\tw@
    \ifnum\csname npos-page-\thepage\endcsname>\z@
      \global\advance\caption@counter@iii\csname npos-page-\thepage\endcsname
      \sortpos{\csname npos-page-\thepage\endcsname}%
\fi\fi\fi
\global\caption@counter@i\z@
\global\caption@counter@ii\z@}
\makeatother

\begin{document}

stuff

% doesnt work if this is commented ?!?!?!
\begin{figure*}[b]
\includegraphics[width=.99\linewidth]{example-image-a}%
\caption{fafqfaf}%
\end{figure*}

\begin{marginfigure}%
\includegraphics[width=\linewidth,height=2\linewidth]{example-image-a}%
\caption{a4a4a4a4a4}%
\end{marginfigure}

stuff

\newpage

\begin{figure*}[b]
\includegraphics[width=.99\linewidth]{example-image-a}%
\caption{A really long caption. A really long caption. A really long caption. A really long caption. A really long caption. A really long caption. A really long caption. A really long caption.}%
\end{figure*}

\begin{marginfigure}%
\includegraphics[width=\linewidth]{example-image-a}%
\caption{A really long caption}%
\end{marginfigure}

some more stuff

\newpage

\begin{figure*}[b]
\includegraphics[width=.99\linewidth]{example-image-a}%
\caption{A really long caption. A really long caption. A really long caption. A really long caption. A really long caption. A really long caption. A really long caption. A really long caption.}%
\end{figure*}

\begin{marginfigure}%
\includegraphics[width=\linewidth]{example-image-a}%
\caption{A really long caption}%
\end{marginfigure}

some more stuff

\end{document}

相关内容