Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'm looking for a way to calculate the ascent and descent of a character glyph after it has been scaled and then drawn into a MetaPost figure.

With TikZ, I can do this fairly easily by performing calculations on the bounding box of a node containing the character:

\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

Note that these example use ConTeXt. The latest version of PGF from TLcontrib may be required in order to use TikZ with ConTeXt MKIV

This gives the following output:

Font metrics in TikZ

I can also shortcut this by using the width and depth functions inside \pgfmathparse and multiplying the result by the scaling factor applied to the node.


Here is my attempt to reproduce the above figure using 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

This gives the following output:

MetaPost metric calculation attempt

Now, I have two problems:

  1. I am only calculating the total height of the glyph because I cannot find a MetaPost equivalent to the TikZ base anchor that gives me the position of the baseline.

  2. My measurement is not being returned in units of points as the double arrow has been right-shifted by 10pt and that is a far smaller distance than the overall height of the character.

Could anyone suggest an appropriate method of calculating ascent and descent inside a MetaPost graphic?


Update

Here's part of egreg's first example, re-worked to compile with 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

The output is exactly what I am looking for:

Font metrics in MetaPost

A key insight was using the eTeX primitives \fontcharht and \fontchardp to access the font metrics. These numbers can be assigned to variables in the MetaPost code when prefixed with \the. Another neat trick was using the ability of MetaPost to solve linear systems to calculate the coordinates of the baseline.

share|improve this question
add comment

1 Answer

up vote 6 down vote accepted

With the gmp package one is able to use in the Metapost file dimensions computed by TeX (e-TeX, in this case, as we use the \fontcharht and \fontchardp primitives)

\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}

Compile with the --shell-escape option. One should be able to use similar methods in ConTeXt.

--- Improvement ---

The following code draws also a small line in order to denote the italic correction and prints the width and italic correction of the character. I've added more examples to show how it can be used with different fonts, via a new optional argument.

\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}

The documentation of gmp explains the difference between \btex and btex and why it's necessary \unexpanded in a few places.

share|improve this answer
1  
Thanks for the pointer to fontcharht and fontchardp---they look promising! –  Sharpie Apr 22 '11 at 10:16
1  
Thanks for such an excellent example! I was able to figure out how to access the results of \fontcharht and \fontchardp when using ConTeXt. Your second example is full of all sorts of interesting information as well. Thanks for posting! –  Sharpie Apr 23 '11 at 22:26
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.