Metapost and TeX labels

Default Metapost has the concept of two types of labels, postscript labels and TeX labels. Postscript labels are created using

label("text", location);

while TeX labels are created using

label(btex text etex, location);

In the latter case, Metapost collects everything between btex and etex in a separate file, processes that file through TeX, and includes the resulting postscript code at an appropriate location. Such a Golberg-esque mechanism is needed to propertly typeset mathematics, get proper kerning, etc.; tasks that TeX can do but Postscript cannot.

ConTeXt has always been tightly integrated with Metapost, but in the pdftex days typesetting labels was slow. ConTeXt (i.e. pdftex) calls Metapost (to draw a figure, say), and then Metapost calls pdftex (to typeset a label), and imports the result to the postscript; this postscript file is passed to ConTeXt and translated into PDF code using TeX macros and the result in inserted in the PDF file that pdftex is generating. Phew!

Six or seven years ago, Hans Hagen and Mojca Miklavec had an idea to speed up this process by collecting all the labels at the ConTeXt end, typesetting them in boxes, and pass on the dimension of the boxes to Metapost. See Mojca’s My Way describing this mechanism. To use this feature, one had to type:

label(\sometxt{text}, location);

With luatex, Metapost can be called as a library, and the basic idea of preprocessing the labels at the TeX end and passing the resulting dimensions to Metapost has been implemented more robustly in Lua. (The conversion of the PS generated by Metapost to PDF is also done in Lua). So one could just type

label(btex text etex, location);

and ConTeXt would parse the Metapost environment and do all the book-keeping at the back.

However, I had always been unstastified with the user interface. There are very few situations where I as a user want postscript labels. So, why not redefine the label macro so that

label("text", location);

is equivalent to the btexetex version. I had made such a suggestion back in 2007, and for some years had been using a private macro for such purposes.

Today, while answering a question at TEX.SX, I noticed that now there is no difference between the postscript and the TeX labels!. For example


  draw "$w$" infont defaultfont scaled defaultscale;
  draw btex $p$ etex shifted (1cm,0);



Notice that both w and p are in the Times Math font. So, there is no need for those pesky btex ... etex tags anymore.

I really don’t know when this change was implemented. As far as I can tell, nothing has changed at the ConTeXt end, so it appears that MetaPost is now directly parsing the postscript labels using TeX. Nonetheless, this means that there is one less thing to worry about while learning and using Metapost. Yay!

Announcing the visualcounter module

It has been almost two years since I posted about the main idea of the visualcounter module. I am happy to announce the official release of the module. I have been using this module in my presentations for almost two years without any problems, so I believe that it is stable enough to be released.

At present, the module is available on github and it should be available through ConTeXt garden soon. Look at the documentation to see some of the features of the module (in particular, the "star rating" example based on Jim Hefferon’s article in the Practex Journal).

The module provides six counters. Two of these were created for proof of concept and are not well tested; the remaining four—scratchcounter, mayanumbers, markers, and countdown—are well tested and, hopefully, their interface will not change.

This was my first module that uses the ConTeXt namespace macros. If you peek into the module, you’ll notice that I only define one macro; everything else is handled by the ConTeXt namespace macro \definenamespace.

The other interesting feature of this module is that I use a separate metapost instance for displaying the counters. This avoids conflict with user definitions. For example, if a user decides to change the metapost definition of fill for whatever reason,

let fill = draw;

such a change will not affect the visual counter module!

Any feedback is appreciated.

Introducing the visual counter module

A typical document usually contains many contains many counters: page numbers, section numbers, enumerations, theorems, and so on. Displaying all these numbers gets boring quickly. Do you want to spice up the document a bit? Enter the visual counter module.

The idea is simple. Each counter already keeps track of its current and maximum value. So, we can just pass that information to MetaPost and display the counter in a visually attractive manner. For example, to display page numbers, I use:




The options are pretty self explanatory. counter sets the name of the counter that we want to display (the module figures out its current and maximum (last) value) The alternative selects the type of visual counter that you want to use. The \usevisualcounter macro displays the counter. Currently, I have only implemented two alternatives: countdown and pulseline. (Here is an example showing both of them). I plan to add others in the future. Suggestions are welcome!

At the moment, there is no documentation. I am still playing around with the API and the code is in a state of flux. Nonetheless, you can take a look in the tests directory to see a few examples of how things work. Stay tuned for more posts on this module.

I am also using the new name space code in the module. It is very very elegant. The entire module has just three macros (two of them are just for convenience). Everything else is just a matter of setting the values for different options. A big advantage of the name space code is that the macros to access the value of a particular option are fully expandable. This means that they can be used directly inside Metapost. No need to have an extra \setMPvariables to pass values to Metapost. Yipee!

Note: It appears that github is down at the moment. Hopefully, it will come back up soon.

Imitating Metapost using Haskell

Brent Yorgey has released a Haskell EDSL for creating diagrams. Here is my first impression of the library, comparing it with another DSL for creating diagrams — Metapost.

lineLets start with the simplest example: drawing a straight line between two points. First the metapost code

draw (0,0)--(100,100)
withpen pencircle scaled 4bp withcolor red;

Now the same code in Haskell (this needs to be wrapped around in a function and rendered to a png or pdf, but I’ll leave that part out).

lineColor red . lineWidth 4 .
  straight $ pathFromVectors [(0,0),(100,-100)]

I like the Metapost style better (since I have been using that for ages). One minor annoyance with diagrams is that positive values of y goes downwards rather than upwards. But the main trouble for me is prefix versus infix style. For diagrams, I find the infix style much easier to read. In this post, I will try to persuade Haskell to follow that style. The transforms in the diagram package have the signature Something -> Diagram -> Diagram, while I want Diagram -> Something -> Diagram. That is easy to fix

linecolor  = flip lineColor
linewidth  = flip lineWidth
fillcolor  = flip fillColor

Now we can use

straight (pathFromVectors [(0,0),(100,-100)])
  `linewidth` 4 `linecolor` red

circleNow lets try the next simplest example: drawing a circle. Again, the metapost code first

fill fullcircle scaled 100
withcolor 0.5green ;

draw fullcircle scaled 100
withpen pencircle scaled 3 withcolor 0.5blue ;

Now using the above flipped functions, we can draw this by (there is a minor difference in metapost and diagrams. Metapost draws a circle of  a given diameter while diagrams draws a circle of a given radius).

circle 50
  `linewidth` 3 `linecolor` lightblue `fillcolor` lightgreen

Ah, much better than the metapost version.

I need to figure out two more things to be able to use the diagrams package in my publications.

  • How to define the infix equivalents of metapost’s --, ---, .., and ... in Haskell.
  • Write a Metapost/ConTeXt backend to render text using TeX.

Here is the complete code

import Graphics.Rendering.Diagrams

linecolor  = flip lineColor
linewidth  = flip lineWidth
fillcolor  = flip fillColor

example1 =
straight (pathFromVectors [(0,0),(100,-100)]) `linewidth` 4 `linecolor` red

example2 =
circle 50 `linewidth` 3 `linecolor` lightblue `fillcolor` lightgreen

main = do
renderAs PNG "line.png" (Width 100) example1
renderAs PNG "circle.png" (Width 100) example2