假设我有一个 LaTeX 文档,其全部内容如下:
$\frac{a+b}{c}$
现在,假设我想要为 $a$、$b$ 和 $c$ 设置边界矩形。有没有办法定义一个函数“bbox”,以便我可以将我的 LaTeX 代码更改为:
$\frac{\bbox{id_a}{a} + \bbox{id_b}{b}}{\bbox{id_c}{c}}$
然后,作为输出的一部分,我得到:
id_a: BBOX INFO
id_b: BBOX INFO
id_c: BBOX INFO
谢谢!
== 回复评论:
评论 1:BBOX INFO 应该输出到哪里? 答案:将 BBOX INFO 输出到任何地点,只要它 (1) 一致且 (2) 机器可解析,就可以了。
评论 2:BBOX INFO 从何而来? 答案:TeX 运行时,每个字符/子表达式都会卡在一个 BBOX 中。这就是我想要输出的 BBOX,即相对于页面的 x_min、x_max、y_min、y_max。
答案1
盒子尺寸
的材料\bbox
可以放入盒子中,然后可以输出盒子的尺寸。但是,数学模式特别困难,因为数学样式未知。这可以通过\mathpalette
( )部分解决,其中盒子设置为所有四种数学样式,然后 TeX 选择正确的一种。然后必须在发货时\mathchoice
通过延迟完成输出,将输出所有四种数学样式的结果。\write
\immediate\write
有一些限制:
数学原子的性质发生变化,因此
\bbox
必须按照框内内容被\mathbin
、 、... 所包围。\mathrel
未检测到狭窄的样式(它对分母或根的上标很重要)。
位置
pdfTeX(LuaTeX、XeTeX)具有记住当前位置的功能\pdfsavepos
。它在 DVI 和 PDF 两种模式下都有效。由于在页面输出时已知位置,因此只能使用它来将位置写入辅助文件。
限制:
该位置适用于相对位置,当有一个参考点时,可以测量到该点的距离。位置以缩放点(
sp
)输出,无单位。据我所知,该功能不适用于混合了左右和左右模式的 XeTeX。它会打乱位置。
例子
以下示例将盒子尺寸和位置写入文件中.aux
,以便可以进一步评估它们:
\documentclass{article}
\usepackage{zref-savepos}
\makeatletter
\DeclareRobustCommand{\bbox}[2]{%
\ifmmode
\mathpalette{\bbox@math{#1}}{#2}%
\else
\@bbox{#1}{#2}%
\fi
}
\newcommand{\bbox@math}[3]{%
% #1: id
% #2: math style
% #3: box contents
\@bbox{#1}{$#2#3\m@th$}%
}
\newcommand{\@bbox}[2]{%
\begingroup
\sbox0{\zsavepos{bbox-#1}#2}%
\usebox{0}%
\if@filesw
\protected@write\@auxout{}{%
\string\bboxaux{#1}{\the\wd0}{\the\ht0}{\the\dp0}%
}%
\fi
\endgroup
}
\usepackage{auxhook}
\AddLineBeginAux{%
\string\providecommand\string\bboxaux[4]{}%
}
\makeatother
\begin{document}
\bbox{id_hello}{Hello}
$\bbox{id_frac}{%
\frac{
\bbox{id_a}{a}
\mathbin{\bbox{id_plus}{+}}
\bbox{id_b}{b}
}{
\bbox{id_c}{c}
}
}$
\end{document}
文件.aux
:
\relax
\providecommand\zref@newlabel[2]{}
\providecommand\bboxaux[4]{}
\zref@newlabel{bbox-id_hello}{\posx{9782558}\posy{46515936}}
\bboxaux{id_hello}{22.50005pt}{6.94444pt}{0.0pt}
\zref@newlabel{bbox-id_frac}{\posx{11475574}\posy{46515936}}
\zref@newlabel{bbox-id_a}{\posx{11554217}\posy{46773972}}
\bboxaux{id_a}{4.33765pt}{3.01389pt}{0.0pt}
\zref@newlabel{bbox-id_plus}{\posx{11838489}\posy{46773972}}
\bboxaux{id_plus}{6.13892pt}{4.33334pt}{0.83334pt}
\zref@newlabel{bbox-id_b}{\posx{12240809}\posy{46773972}}
\bboxaux{id_b}{3.51666pt}{4.8611pt}{0.0pt}
\zref@newlabel{bbox-id_c}{\posx{11895643}\posy{46289942}}
\bboxaux{id_c}{3.57375pt}{3.01389pt}{0.0pt}
\bboxaux{id_frac}{16.39322pt}{8.79842pt}{3.44841pt}
答案2
您可以尝试以下宏:
\newwrite\fbbox
\immediate\openout\fbbox=\jobname.box
\def\bbox#1#2{#2\def\bboxid{#1}%
\ifmmode \mathpalette\bboxM{#2}\else \bboxA{#2}\fi
}
\def\bboxA#1{\setbox0=\hbox{#1}\pdfsavepos\bboxB}
\def\bboxM#1#2{\setbox0=\hbox{$#1#2$}\pdfsavepos\bboxB}
\def\bboxB{\edef\tmp{\write\fbbox
{\bboxid: (\noexpand\the\pdflastxpos, \noexpand\the\pdflastypos)
[\number\wd0, \number\ht0, \number\dp0]}}\tmp}
%% tests:
Normal text: \bbox{id_g}{g}
${a+b \over c} = d + e$
${\bbox{id_a}{a}+ \bbox{id_b}{b} \over \bbox{id_c}{c}} =
\bbox{id_d}{d} + \bbox{id_e}{e}$
使用 pdfTeX 原语打印绝对位置\pdfsavepos
。输出文件document.box
包含以下形式的数据:
id1: (8577430, 49989344) [327681, 282168, 127431]
id_a: (6409921, 48592804) [284272, 197518, 0]
id_b: (7042709, 48592804) [230468, 318577, 0]
id_c: (6701284, 48108774) [234209, 197518, 0]
id_d: (8336264, 48334768) [341106, 455111, 0]
id_e: (9442407, 48334768) [305153, 282168, 0]
正式名称为:box_id: (posx, posy) [wd, ht, dp]
,其中(posx, posy)
是字母或方框打印后的位置,[wd, ht, dp]
是字母或方框的宽度、高度和深度。使用的单位是 sp = 1/2^16 pt。
我假设你会用另一个程序读取这些数据。它可以计算边界框,如下所示:
Left-bottom corner: (posx - wd, posy - dp)
Top-right corner: (posx, posy + ht)
我必须指出,结果在数学模式下不可能完全正确,因为
$$ {a\over e^2}, {a\over \hbox{$e^2$}} $$
对于 e^2 给出的结果略有不同,但如果您要测量 e^2,那么宏会测量第二个但打印第一个。