我不确定如何提出这个问题,因此如果有必要的话我只会进行一些编辑。
PDF 扩展目前至少使用以下三个宏扩展了基本的 TeX 宏
\pdfsavepos
,\pdflastxpos
和\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 实例的值正确扩展。
举一个具体的例子,假设我有四个宏(箭头后的值是宏的(一次)扩展定义):
\csname macro-1-savedposition\endcsname -> 12345
\csname macro-2-savedposition\endcsname -> 1234
\csname macro-3-savedposition\endcsname -> 123456
\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/de4fa02c4e7fa12141ca和gist.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}