[metapost] accessing letters in picture (for...within loop)

Stephan Hennig mailing_list at arcor.de
Tue Nov 21 01:21:20 CET 2006


the for...within loop provides access to text inside a picture
variable together with properties such as the font name, coordinates,
scale, color etc.  The loop doesn't always return text letter by letter,
but very often returns arbitrary bunches of letters at once (whose
length depends on the font in use).  This is very unfortunate, since I
want to access the coordinates of single letters.  Is there any way to
tell MetaPost to process pictures letter by letter?

Background:  I want to typeset text along a free path (actually, just a
circle segment).  The idea is to let TeX typeset the text horizontally
to get a reference and then inspect the resulting picture letter by
letter to get the coordinates, transform them to the desired location on
the path and then typeset the single letters there using TeX again.

I've appended example code demonstrating the problem.  All strings
returned in the loop are output on the console together with their
coordinates.  In the output red dots indicate string boundaries.
(Unfortunately, there are only few.)  The black text is the original
picture that is inspected and re-typeset in the for...within loop.[1]
The blue text is the resulting copy (just shifted vertically).

I know the txp package, but that works only with MetaPost strings which
ignore kerning information and ligatures.  Moreover I'm dealing with 8
bit characters.  Any ideas?

Best regards,
Stephan Hennig

[1]  The \strut\smash construct is just to keep sure all letters line up
correctly, since the coordinates (xpart item, ypart item) refer to the
base line of the glyphs/strings---ignoring descenders---and in the copy
descenders are relevant.  The resulting copy comes out a little bit too
high, but I can correct for that.

string package; package := "";
% package := "\usepackage{mathpazo}";
% package := "\usepackage{mathptmx}";
% package := "\usepackage{charter}";
% package := "\usepackage{utopia}";

input TEX
TEXPRE("%&latex" & char(10) & "\documentclass{article}" &
  package & "\begin{document}");

prologues := 1;
labeloffset := 0bp;

vardef copyItems(expr pic)=
save t,f,col,item;
string t,f;
color col;
  for item within pic:
    if textual item:
      t := textpart item;
      f := fontpart item;
      x := xpart item;
      y := ypart item;
      col := (redpart item, greenpart item, bluepart item);
      show t;
%       show f;
      show z;
%       show xxpart item, xypart item, yxpart item, yypart item;
%       show col;
      drawdot z withpen pencircle scaled 1bp withcolor red;
      label.urt(TEX("\strut\smash{" & t & "}"), z shifted (0,20bp))
withcolor blue;
      drawdot z shifted (0,20bp) withpen pencircle scaled 1bp withcolor red;

picture pic;
path p;
  pic := thelabel.rt(TEX("abcdefghijklmnopqrstuvwxyz"), (0,0));
  draw pic;
  pic := thelabel.rt(TEX("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), (0,70));
  draw pic;
  pic := thelabel.rt(TEX("Greetings from MetaPost!"), (0,140));
  draw pic;

More information about the metapost mailing list