元素的输出位置

元素的输出位置

假设我有一个 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,那么宏会测量第二个但打印第一个。

相关内容