在宏中,我需要知道我是否位于页面顶部(不包括顶部浮动)。因此,我使用的长度\pagetotal
来确定我是否位于页面顶部。如果\pagetotal
为零,则表示我位于页面顶部。但是,我注意到这\pagetotal
并不总是“最新的”,并且会扭曲我的宏的使用。
我该如何强制\pagetotal
更新?还是我误解了 的意思\pagetotal
?
您会在下面看到一个示例,其中\pagetotal
宏位于页面顶部,尺寸约为 552 pt。
\documentclass{article}
\usepackage{lipsum}
\newcommand{\test}{%
\par
\ifdim\pagetotal=0pt
TRUE%
\else
FALSE : \textbackslash pagetotal = \the\pagetotal
\fi}
\begin{document}
\lipsum[1]
\lipsum[1]
\lipsum[1]
\lipsum[3]
\test
\the\pagetotal\lipsum[1]
\the\pagetotal
\end{document}
语境
这个问题与我之前的两个问题相关:如何从文档主体判断页面是否有顶部浮动?和在使用时,如何确保 a 之前或之后的间距\vbox
正确\addvspace?
。
我正在尝试创建一个宏,根据上下文添加不同的垂直空间。
通常,我想\myLength
在宏的开头和结尾插入一个值的空间。
如果宏位于页面顶部,在分页符之后(\pagetotal=0pt
如果我理解正确的话,其中),则忽略 \vspace{\myLength} 并且不添加垂直空间,这正是我想要的。
但是问题出现在,如前一种情况一样,宏位于页面顶部,但前面有一个或多个顶部浮动(它不再是严格意义上的“页面顶部”,但如果我理解正确的话,我们仍然有\pagetotal=0pt
)。在这种情况下,我希望宏插入垂直\vspace*{\dimexpr\myLength-\textfloatsep}
以保持一致性。
举个例子来说明一下:
这里,宏的行为正确:当它位于页面顶部时,宏的开头不会插入空格;当它不在页面顶部时,\vspace{\myLength}
会正确插入。
然而,当宏位于页面顶部并且前面有一个顶部浮动时,空间就完全不平衡了。
这是一个不起作用的最小示例:
\documentclass{article}
\usepackage{lipsum, mwe, refcount}
\makeatletter
%From : https://tex.stackexchange.com/questions/712713/how-to-determine-from-the-document-body-whether-or-not-a-page-has-a-top-float
\def \@combinefloats {%
\ifx \@toplist\@empty%
\else%
\@cflt%
\immediate\write\@auxout{\string\global\string\@namedef{pageWithTopFloat-\thepage}{1}}%
\fi%
\ifx \@botlist\@empty \else \@cflb \fi%
}
\newcounter{ifTopFloatCnt}
\def\iftopfloat#1#2{%
\global\advance\c@ifTopFloatCnt\@ne%
\label{\the\c@ifTopFloatCnt @ifTopFloat}%
\ifcsname pageWithTopFloat-\getpagerefnumber{\the\c@ifTopFloatCnt @ifTopFloat}\endcsname%
#1%
\else%
#2%
\fi%
}
\makeatother
\newlength{\myLength}
\setlength{\myLength}{30pt}% exaggerated value to illustrate
\newcommand{\mycommand}{\par%
\iftopfloat{%
\ifdim\pagetotal=0pt% If there's a top float AND you're right after it
\vspace*{\dimexpr\myLength-\textfloatsep}
\else% If there is a top float BUT you are not right after it
\vspace{\myLength}
\fi
}{% If there is no top float
\vspace{\myLength}
}
{\centering\LARGE * * *\par}
\vspace{\myLength}
}
\begin{document}
\lipsum[1]
\lipsum[1]
\lipsum[1]
\lipsum[3]
\begin{figure}[t]
\centering
\includegraphics{example-image}
\end{figure}
\mycommand
\lipsum[1]
\lipsum[2]
\mycommand
\lipsum[1]
\mycommand
\lipsum[1]
\end{document}
测试\pdfsavepos
正如评论中所建议的,我尝试使用\pdfsavepos
和\pdflastypos
原语。这似乎比使用效果更好\pagetotal
,但我在使用我的命令时仍然遇到了一些“错误”。
在某些情况下,\pdfsavepos
给出命令位于页面顶部(\pdflastypos
= 0)的信息,但实际上并非如此(请参阅下面的 MWE)。另一方面,有时当命令位于页面顶部时,页面顶部浮动之后,\pdflastypos
不为零,这表明\pdflastypos
实际上指的是上一页的底部。
示例:\pdflastypos
尽管命令位于页面顶部,但这里我得到的结果却是 ≠ 0。
\documentclass{article}
\usepackage{lipsum, mwe, refcount, iftex}
\ifluatex% For compatibility with LuaTeX, which I generally use.
\let\pdfsavepos\savepos
\let\pdflastypos\lastypos
\fi
\makeatletter
%From : https://tex.stackexchange.com/questions/712713/how-to-determine-from-the-document-body-whether-or-not-a-page-has-a-top-float
\def \@combinefloats {%
\ifx \@toplist\@empty%
\else%
\@cflt%
\immediate\write\@auxout{\string\global\string\@namedef{pageWithTopFloat-\thepage}{1}}%
\fi%
\ifx \@botlist\@empty \else \@cflb \fi%
}
\newcounter{ifTopFloatCnt}
\long\def\ifTopFloat#1#2{%
\global\advance\c@ifTopFloatCnt\@ne%
\label{\the\c@ifTopFloatCnt @ifTopFloat}\nopagebreak%
\ifcsname pageWithTopFloat-\getpagerefnumber{\the\c@ifTopFloatCnt @ifTopFloat}\endcsname%
#1%
\else%
#2%
\fi%
}
\newlength{\myLength}
\setlength{\myLength}{30pt}% exaggerated value to illustrate
\newcounter{myCommandCnt}
\newcounter{myCommandCntAux}
\newcommand{\myCommand}{\par%
\stepcounter{myCommandCnt}%
\pdfsavepos%
\write\@auxout{%
\string\global\string\stepcounter{myCommandCntAux}%
\string\global\string\@namedef{myCommand-\string\themyCommandCntAux}{\the\pdflastypos}%
}%
\ifTopFloat{%
\ifnum\@nameuse{myCommand-\themyCommandCnt}=0% If there's a top float AND you're right after it
\vspace*{\dimexpr\myLength-\textfloatsep}
{\centering\LARGE * * * (a, \textbackslash lastypos: \@nameuse{myCommand-\themyCommandCnt} )\par}
\else% If there is a top float BUT you are not right after it
\vspace{\myLength}
{\centering\LARGE * * * (b, \textbackslash lastypos: \@nameuse{myCommand-\themyCommandCnt} )\par}
\fi
}{% If there is no top float
\vspace{\myLength}
{\centering\LARGE * * * (c, \textbackslash lastypos: \@nameuse{myCommand-\themyCommandCnt} )\par}
}
\vspace{\myLength}
}
\makeatother
\begin{document}
\lipsum[1]
\lipsum[1]
\lipsum[1]
\lipsum[2]
\begin{figure}[t]
\centering
\includegraphics{example-image}
\end{figure}
\myCommand
\lipsum[1]
\lipsum[2]
\begin{figure}[t]
\centering
\includegraphics{example-image-9x16}
\end{figure}
\myCommand
\lipsum[2]
\myCommand
\lipsum[1]
\myCommand
\lipsum[1]
\end{document}