计算 MetaPost 图形中字形的字体指标

计算 MetaPost 图形中字形的字体指标

我正在寻找一种方法来计算字符字形在缩放并绘制成 MetaPost 图形后的上升和下降。

使用 TikZ,我可以通过对包含字符的节点的边界框执行计算来轻松完成此操作:

\usemodule[tikz]
\usetikzlibrary[calc,positioning]   
\newdimen\yone
\newdimen\ytwo
\def\tikzmetriccalc#1#2#3{
  \pgfextracty{\yone}{\pgfpointanchor{#1}{#2}}
  \pgfextracty{\ytwo}{\pgfpointanchor{#1}{#3}}
  \pgfmathparse{ \yone - \ytwo }
  \yone=\pgfmathresult pt
}

\starttext    
\starttikzpicture[char node/.style={
  scale=10,text=black!40,inner sep=0pt,outer sep=0pt}]

\node[char node] at (0,0) (char) {g};

\draw[ultra thick] (char.base west) -- (char.base east)
  (char.north west) -- (char.north east)
  (char.south west) -- (char.south east);
\draw[color=red,ultra thick,<->,>=stealth] ([xshift=10pt]char.base west) --
  ([xshift=10pt]char.north west);
\draw[color=red,ultra thick,<->,>=stealth] ([xshift=-10pt]char.base east) --
  ([xshift=-10pt]char.south east);

\tikzmetriccalc{char}{north}{base}
\node[above=0.25em of char.north] {\bf Ascent = \the\yone};

\tikzmetriccalc{char}{base}{south}
\node[below=0.25em of char.south] {\bf Descent = \the\yone};

\stoptikzpicture
\stoptext

请注意,这些示例使用 ConTeXt。最新版本的 PGF 来自TL贡献可能需要使用 TikZ 和 ConTeXt MKIV

输出结果如下:

TikZ 中的字体指标

我还可以通过使用里面的widthdepth函数\pgfmathparse并将结果乘以应用于节点的缩放因子来简化这一过程。


以下是我使用 MetaPost 重现上图的尝试:

\starttext    
\startMPpage

  picture c;
  c := thelabel(btex g etex scaled 10, origin); draw c;

  pickup pensquare scaled 1pt;
  draw (ulcorner c -- urcorner c) withcolor red;
  draw (llcorner c -- lrcorner c) withcolor red;
  drawdblarrow (llcorner c -- ulcorner c) xshifted 10pt withcolor red;

  h := (ypart ulcorner c) - (ypart llcorner c);
  label("Height = " & (decimal h), up * (ypart ulcorner c + 10pt));

  setbounds currentpicture to boundingbox currentpicture enlarged 2mm;

\stopMPpage   
\stoptext

输出结果如下:

MetaPost 指标计算尝试

现在,我有两个问题:

  1. 我只计算字形的总高度,因为我找不到与 TikZ 锚点等效的 MetaPostbase来提供基线的位置。

  2. 我的测量结果没有以点为单位返回,因为双箭头已右移 10pt,并且该距离比字符的整体高度小得多。

有人可以建议一种在 MetaPost 图形中计算上升和下降的适当方法吗?


更新

这是 egreg 的第一个示例的一部分,经过重新设计以使用 ConTeXt MKIV 进行编译:

\starttext
\startMPpage
  picture c;
  c := thelabel(btex g etex scaled 10, origin); draw c;

  h := \the\fontcharht\font`g;
  d := \the\fontchardp\font`g;

  % Solve a linear equation to find coordinates of the baseline.
  z1+(0,10h)=ulcorner c;
  z2+(0,10h)=urcorner c;

  pickup pensquare scaled 1pt;
  draw (ulcorner c -- urcorner c) withcolor red;
  draw (llcorner c -- lrcorner c) withcolor red;
  draw (z1 -- z2) withcolor red;
  drawdblarrow (z1 -- ulcorner c) xshifted 10pt withcolor red;
  drawdblarrow (lrcorner c -- z2) xshifted -10pt withcolor red;

  label("Ascent = " & (decimal 10h) & " pt", up * (ypart ulcorner c + 10pt));
  label("Descent = " & (decimal 10d) & " pt", up * (ypart llcorner c - 10pt));

  setbounds currentpicture to boundingbox currentpicture enlarged 2mm;
\stopMPpage

\stoptext

输出正是我想要的:

MetaPost 中的字体规格

一个关键的见解是使用 eTeX 基元\fontcharht\fontchardp访问字体度量。当以 为前缀时,这些数字可以分配给 MetaPost 代码中的变量\the。另一个巧妙的技巧是使用 MetaPost 解决线性系统的能力来计算基线的坐标。

答案1

使用 gmp 包,可以在 Metapost 文件中使用 TeX 计算的尺寸(在本例中为 e-TeX,因为我们使用\fontcharht\fontchardp原语)

\documentclass[a4paper]{article}
\usepackage[shellescape]{gmp}

\newcommand{\drawchar}[1]{%
\begin{mpost}[mpmem=metafun]
h:=\mpdim{\fontcharht\font`#1};
d:=\mpdim{\fontchardp\font`#1};

picture c;
c := thelabel(\btex #1 etex scaled 10,origin); draw c;

z1+(0,10h)=ulcorner c;
z2+(0,10h)=urcorner c;

pickup pensquare scaled 1pt;
draw (ulcorner c -- urcorner c) withcolor red;
draw (llcorner c -- lrcorner c) withcolor red;
draw (z1 -- z2) withcolor red;
drawdblarrow (ulcorner c -- z1) xshifted 10pt withcolor red;
drawdblarrow (llcorner c -- z1) xshifted 10pt withcolor red;

label(btex Height = {\the\fontcharht\font`#1} etex, up * (ypart ulcorner c + 10pt));
label(btex Depth = {\the\fontchardp\font`#1} etex, up * (ypart llcorner c - 10pt));

setbounds currentpicture to boundingbox currentpicture enlarged 2mm;
\end{mpost}}

\begin{document}
\drawchar{g}

\drawchar{a}
\end{document}

使用该--shell-escape选项进行编译。应该能够在 ConTeXt 中使用类似的方法。

---改进---

以下代码还绘制了一条小线以表示斜体校正并打印字符的宽度和斜体校正。我添加了更多示例来展示如何通过新的可选参数将其用于不同的字体。

\documentclass[a4paper]{article}
\usepackage[shellescape,latex]{gmp}

\newcommand{\drawchar}[2][]{{#1%
  \edef\dcharht{\the\fontcharht\font`#2}%
  \edef\dchardp{\the\fontchardp\font`#2}%
  \edef\dcharwd{\the\fontcharwd\font`#2}%
  \edef\dcharic{\the\fontcharic\font`#2}%
\begin{mpost}[mpmem=metafun]
h:=\mpdim{\fontcharht\font`#2};
d:=\mpdim{\fontchardp\font`#2};
w:=\mpdim{\fontcharwd\font`#2};
icorr:=\mpdim{\fontcharic\font`#2};

picture c;
c := thelabel(\btex #1#2 etex scaled 10,origin); draw c;

z1+(0,10h)=ulcorner c;
z2+(0,10h)=urcorner c;
z3=urcorner c + 10*(icorr,0);
z4=z3+10pt*down;

%pickup pensquare scaled 1pt;
draw (ulcorner c -- urcorner c) withcolor red;
draw (llcorner c -- lrcorner c) withcolor red;
draw (z3 -- z4) withcolor red;
draw (z1 -- z2) withcolor red;
drawdblarrow (ulcorner c -- z1) xshifted 1pt withcolor red;
drawdblarrow (llcorner c -- z1) xshifted 1pt withcolor red;

label(btex \unexpanded{\footnotesize} Height = {\dcharht} etex, up * (ypart ulcorner c + 10pt));
label(btex \unexpanded{\footnotesize} Depth = {\dchardp} etex, up * (ypart llcorner c - 10pt));
label.rt(btex \unexpanded{\footnotesize} Width = {\dcharwd} etex, (x3+2pt)*right-(0,6pt));
label.rt(btex \unexpanded{\footnotesize} Italic correction = {\dcharic} etex, (x3+2pt)*right+(0,6pt));
setbounds currentpicture to boundingbox currentpicture enlarged 2mm;
\end{mpost}}}

\begin{document}
\drawchar{g}

\drawchar{a}

\drawchar[\itshape]{f}

\drawchar[\fontfamily{ppl}\itshape]{f}

\drawchar[\fontencoding{OMX}\fontfamily{cmex}\selectfont]{p}
\end{document}

gmp 的文档在几个地方解释了\btex和之间的区别btex以及为什么它是必要的。\unexpanded

相关内容