我尝试制作一个非浮动的图形环境。
问题
当两个图形足够接近时,第二个图形会被 TeX 分页机制推到下一页,而第一个图形则会被忽略。
图片列表
这里我们看到了我自制的图形列表的输出,其命名恰当,\mylistoffigures
:
缺少图片
代码
我的代码编写方式使得 image.jpg 不是必需的。我调整了标签参考系统以使用我的运行计数器。这是因为我需要从打印计数器中抽象出一个唯一的数字,因为我\thefigure
在每个语言版本中重置了打印,由 模拟\setcurrentlanguage
。
\documentclass{article}
\usepackage{fontspec}% xelatex
\usepackage{xparse}
\usepackage{environ}
\usepackage{lipsum}
\usepackage{tikz}
\usepackage{hyperref}
\makeatletter
% Define counter
\newcounter{runningfigurecounter}% latex counter, equiv of \global\newcount\runningfigurecounter\runningfigurecounter=0
% Redefine hyperref unique label
\renewcommand*{\theHfigure}{runningfigurecounter.\the\value{runningfigurecounter}} % Sets fifth field in second component of \newlabel to provide unique labels independent of what gets printed i.e. the counter \c@figure etc.
% https://tex.stackexchange.com/questions/273098/mimicking-latexs-table-of-contents-functionality?noredirect=1&lq=1
\long\def\myfigure@addtocontents#1#2{%
\protected@write\@auxout%
{\let\label\@gobble \let\index\@gobble \let\glossary\@gobble}%
{\string\myfigure@writefile{#1}{#2}}}%use our own version of \@writefile
\long\def\myfigure@writefile#1#2{% Redefine our own file handler. This gets called by aux file macros.
\@ifundefined{#1}\relax%
{\@temptokena{#2}%
\immediate\write\csname #1\endcsname{\the\@temptokena}% open file handler
}%
}
\NewDocumentEnvironment{myfigure}{ O{} m O{build:fig:\therunningfigurecounter} }{% \therunningfigurecounter instead \the\runningfigurecounter because it was defined using latex and not tex
% 1: optional graphicx arg
% 2: file
% 3: label
\myfigure@getBODY%
}%
{%
\endmyfigure@getBODY%
\refstepcounter{runningfigurecounter}% global backend figure counter
\@temptokena{\protect\contentsline{figure}{\protect\numberline{\thefigure}\protect{\ignorespaces\myfigurecaption\relax\protect}}{\thepage}{figure.runningfigurecounter.\therunningfigurecounter}}% Contents Line (hyperref format)
\myfigure@addtocontents{lof_\mylanguage}{\the\@temptokena}% Adds \@writefile{lof_en-US}{expanded contents of \@temptokena} to aux
\def\@captype{figure}% see source2e for using caption outside of float
\medbreak% adds \medskip but only if preceding space is less than what \medbreak would insert
\centering% ensure figure and caption is centered within environment
\vbox{% keep stuff on the same page
\IfFileExists{#2}%
{% ensure graphic exists in filesystem
\caption{\myfigurecaption}% handles printed counter logic
\label{#3}% requires redef of \label \ref \autoref \nameref to include build\mylanguage suffix
\includegraphics[width=.8\linewidth,#1]{#2}%
}% True
{%
\caption{\myfigurecaption}% handles printed counter logic
\label{#3}% \requires redef of \label \ref \autoref \nameref to include build:\mylanguage suffix
\tikz \draw [fill=red!15] (0,0) rectangle node [align=center] {Missing Image\\#2} (.8\linewidth, 50mm);
\typeout{Error: Missing figure file #2.}%
}% False
}% end vbox
\medbreak% adds \medskip but only if preceding space is less than what \medbreak would insert
}%
\NewEnviron{myfigure@getBODY}% The goal of collecting \BODY of myfigure is to separate translated text from LaTeX code.
{\global\let\myfigurecaption\BODY}%
\NewDocumentCommand{\mylistoffigures}{}{% Provides list of figures local, works with \@mystarttoc
% to a language
\newpage\section{\listfigurename
\@mkboth{%
\MakeUppercase\listfigurename}{\MakeUppercase\listfigurename}}%
\@mystarttoc{lof_\mylanguage}\newpage% Language-specific lof file is only made if \mylistoffigures called. %\vfill% \vspace*{glue} fill vertical space below line in which is appears %\vfill ends graf immediately ad add vertical space
}
\def\@mystarttoc#1{% imitates latex \@starttoc, except removes tf@ prefix to file handle
\begingroup
\makeatletter
\@input{\jobname.#1}%
\if@filesw% Controls whether writing is enabled. Controls whether writing is enabled. Conditional returns false if \nofiles is issued and no writing to aux has been performed.
\expandafter\newwrite\csname #1\endcsname% make file handle
\immediate\openout \csname #1\endcsname \jobname.#1\relax% open file handle
\fi
\@nobreakfalse
\endgroup}
\makeatother
\NewDocumentCommand\setcurrentlanguage{ m }{\edef\mylanguage{#1}}
\begin{document}
\setcurrentlanguage{en-US}
\mylistoffigures
\newpage
\begin{myfigure}{image.jpg}[fig:label]
Apples.
\end{myfigure}
\lipsum[1-3]
filler
filler
\begin{myfigure}{image.jpg}[fig:label]
Bananas.
\end{myfigure}
\lipsum[1-3]
\newpage
\begin{myfigure}{image.jpg}[fig:label]
Pears.
\end{myfigure}
\end{document}
答案1
你得到
\contentsline {figure}{\numberline {2}{\ignorespaces Bananas.\relax }}{2}{figure.runningfigurecounter.2}
\contentsline {figure}{\numberline {2}{\ignorespaces Bananas.\relax }}{2}{figure.runningfigurecounter.2}
\contentsline {figure}{\numberline {3}{\ignorespaces Pears.\relax }}{4}{figure.runningfigurecounter.3}
在您的 .lof 文件中,因为您只是在页面发走时写入令牌寄存器的值,所以如果一页上有多个图形,那么您得到的最后一个图形的重复次数与图形的数量一样多。
您可以使用
\myfigure@addtocontents{lof_\mylanguage}{\protect\contentsline{figure}{\protect\numberline{\thefigure}\protect{\ignorespaces\myfigurecaption\relax\protect}}{\thepage}{figure.runningfigurecounter.\therunningfigurecounter}}% Adds \@writefile{lof_en-US}{expanded contents of \@temptokena} to aux
因此只需将您的\@temptokena
设置移动到 addtocontents 然后你就会得到
\contentsline {figure}{\numberline {0}{\ignorespaces Apples.\relax }}{2}{figure.runningfigurecounter.1}
\contentsline {figure}{\numberline {1}{\ignorespaces Bananas.\relax }}{2}{figure.runningfigurecounter.2}
\contentsline {figure}{\numberline {2}{\ignorespaces Pears.\relax }}{4}{figure.runningfigurecounter.3}
它获得三个不同的条目,但编号为 0,1,2 而不是 1,2,3,因为您在增加计数器之前进行了写入。
因此将其移至\caption
获取之后:
\documentclass{article}
\usepackage{fontspec}% xelatex
\usepackage{xparse}
\usepackage{environ}
\usepackage{lipsum}
\usepackage{tikz}
\usepackage{hyperref}
\makeatletter
% Define counter
\newcounter{runningfigurecounter}% latex counter, equiv of \global\newcount\runningfigurecounter\runningfigurecounter=0
% Redefine hyperref unique label
\renewcommand*{\theHfigure}{runningfigurecounter.\the\value{runningfigurecounter}} % Sets fifth field in second component of \newlabel to provide unique labels independent of what gets printed i.e. the counter \c@figure etc.
% https://tex.stackexchange.com/questions/273098/mimicking-latexs-table-of-contents-functionality?noredirect=1&lq=1
\long\def\myfigure@addtocontents#1#2{%
\protected@write\@auxout%
{\let\label\@gobble \let\index\@gobble \let\glossary\@gobble}%
{\string\myfigure@writefile{#1}{#2}}}%use our own version of \@writefile
\long\def\myfigure@writefile#1#2{% Redefine our own file handler. This gets called by aux file macros.
\@ifundefined{#1}\relax%
{\@temptokena{#2}%
\immediate\write\csname #1\endcsname{\the\@temptokena}% open file handler
}%
}
\NewDocumentEnvironment{myfigure}{ O{} m O{build:fig:\therunningfigurecounter} }{% \therunningfigurecounter instead \the\runningfigurecounter because it was defined using latex and not tex
% 1: optional graphicx arg
% 2: file
% 3: label
\myfigure@getBODY%
}%
{%
\endmyfigure@getBODY%
\refstepcounter{runningfigurecounter}% global backend figure counter
\def\@captype{figure}% see source2e for using caption outside of float
\medbreak% adds \medskip but only if preceding space is less than what \medbreak would insert
\centering% ensure figure and caption is centered within environment
\vbox{% keep stuff on the same page
\IfFileExists{#2}%
{% ensure graphic exists in filesystem
\caption{\myfigurecaption}% handles printed counter logic
\label{#3}% requires redef of \label \ref \autoref \nameref to include build\mylanguage suffix
\includegraphics[width=.8\linewidth,#1]{#2}%
}% True
{%
\caption{\myfigurecaption}% handles printed counter logic
\label{#3}% \requires redef of \label \ref \autoref \nameref to include build:\mylanguage suffix
\tikz \draw [fill=red!15] (0,0) rectangle node [align=center] {Missing Image\\#2} (.8\linewidth, 50mm);
\typeout{Error: Missing figure file #2.}%
}% False
\myfigure@addtocontents{lof_\mylanguage}{\protect\contentsline{figure}{\protect\numberline{\thefigure}\protect{\ignorespaces\myfigurecaption\relax\protect}}{\thepage}{figure.runningfigurecounter.\therunningfigurecounter}}% Adds \@writefile{lof_en-US}{expanded contents of \@temptokena} to aux
}% end vbox
\medbreak% adds \medskip but only if preceding space is less than what \medbreak would insert
}%
\NewEnviron{myfigure@getBODY}% The goal of collecting \BODY of myfigure is to separate translated text from LaTeX code.
{\global\let\myfigurecaption\BODY}%
\NewDocumentCommand{\mylistoffigures}{}{% Provides list of figures local, works with \@mystarttoc
% to a language
\newpage\section{\listfigurename
\@mkboth{%
\MakeUppercase\listfigurename}{\MakeUppercase\listfigurename}}%
\@mystarttoc{lof_\mylanguage}\newpage% Language-specific lof file is only made if \mylistoffigures called. %\vfill% \vspace*{glue} fill vertical space below line in which is appears %\vfill ends graf immediately ad add vertical space
}
\def\@mystarttoc#1{% imitates latex \@starttoc, except removes tf@ prefix to file handle
\begingroup
\makeatletter
\@input{\jobname.#1}%
\if@filesw% Controls whether writing is enabled. Controls whether writing is enabled. Conditional returns false if \nofiles is issued and no writing to aux has been performed.
\expandafter\newwrite\csname #1\endcsname% make file handle
\immediate\openout \csname #1\endcsname \jobname.#1\relax% open file handle
\fi
\@nobreakfalse
\endgroup}
\makeatother
\NewDocumentCommand\setcurrentlanguage{ m }{\edef\mylanguage{#1}}
\begin{document}
\setcurrentlanguage{en-US}
\mylistoffigures
\newpage
\begin{myfigure}{image.jpg}[fig:label]
Apples.
\end{myfigure}
\lipsum[1-3]
filler
filler
\begin{myfigure}{image.jpg}[fig:label]
Bananas.
\end{myfigure}
\lipsum[1-3]
\newpage
\begin{myfigure}{image.jpg}[fig:label]
Pears.
\end{myfigure}
\end{document}