Mathematical

Convert mathematical equations to base64 encoded images.

Installation

Add this line to your application's Gemfile:

gem 'mathematical'

And then execute:

$ bundle

Or install it yourself as:

$ gem install mathematical

Usage

The simplest way to do this is

Mathematical::Render.new.render(string_with_math)

string_with_math should just be a string, containing inline or display style math. The output will be all the math equations, as SVGs, converted into base64 encoded images. They look something like this:

<img class="type-inline" data-math-type="type-inline" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0..."/>

Inline math will have class="type-inline" data-math-type="type-inline" set, and display math will have class="type-display" data-math-type="type-display".

Matched math notations

Currently, the following formats are supported:

inline formulas displayed equations
$...$ [...]
(...) \begin{equation}...\end{equation}

Options

Mathematical::Render.new can take a few options:

  • :ppi, the pixels per inch of the resulting SVG (default: 72.0)
  • :zoom, the zoome level of the resulting SVG (default: 1.0)

Pass these in as an options hash; these must be Float values! For example:

opts = { :ppi => 200.0, :zoom => 5.0 }
renderer = Mathematical::Render.new(opts)

Dependencies

This package depends on the following libraries:

  • glib-2.0
  • gdk-pixbuf-2.0
  • xml2
  • cairo
  • pango
  • pangocairo

  • On a Mac, pretty much everything can be installed via Homebrew.

  • On a *nix machine, I'm sure it's possible via package managers to install all of these.

  • On a Windows machine, I have no idea.

History

There are a smattering of libraries written in various languages to convert math into a variety of formats. But there needs to be a sane way to show math equations in the browser. With browser support for MathML under attack, it's unfortunately not a sustainable solution. A PNG or SVG representation of the equation is the safest way to go.

Most advice suggests using MathJax. While extremely popular I dislike the "stuttering" effect caused by pages loading math. JavaScript shouldn't be used in situations where server-rendering is a possibility, in my opinion.

To that end, I obsessed over the problem of server-side math rendering for over a week. Here was my journey:

  • I started out with blahtexml, which takes TeX equations and converts them to PNG. This wasn't a bad idea, but it took too long; for twelve equations, it took eight seconds. It was slow because it shelled out to LaTeX, then dvipng. In fact, as I discovered, most projects on the 'Net shell out to LaTeX, then something else, which makes performance absolutely horrid. I had to find something better, with no preferably dependency on LaTeX.

  • mimetex was my next attempt. It looked great: a pure C implementation that turned TeX equations into a rasterized representation, and then into a PNG. The speed was there, but the output image was pretty jagged. I tweaked the program to output BMPs, and tried to sharpen those with potrace, but the results were less then pleasant. The "update" to mimetex is mathtex, but it, too, depend on LaTeX and dvipng binaries to produce images.

  • pmml2svg had potential. It's a set of XSLT stylesheets to convert MathML to SVG. Unfortunately, it relies on XSLT 2.0, of which there are no Ruby bindings (at the time of this writing, April '14). It had to rely on Saxon and Java.

  • tth converts TeX to HTML, but the output is aesthetically unpleasing, so I passed.

  • Wikipedia uses texvc, which is written in OCaml, a language I am utterly unfamiliar with. In any event, I could not get the code to compile on my machine.

  • It took me forever to finally compile gtkmathview, and when it did, I got a bunch of SVG images with screwed up fonts.

  • dvisvgm worked well, but still depended on two external binaries (LaTeX to convert the text to dvi, and dvisvgm to turn it into SVG)

  • At one point, I began to try and convert the MathJax code to Ruby to figure out how it accomplished its toSVG methods. The MathJax codebase, while written by geniuses, is absoloutely incomprehnsible, due in part to JavaScript's inability to possess a coherent structure.

  • Near the end of my wits, I mimicked the behavior of mathrender2, which uses PhantomJS to embed MathJax onto a fake HTML page. This produced exactly what I needed: a bunch of accurate SVG files with no intermediate binaries. It was, unfortunately, a bit slow: for an arbitrary composition of 880 equations, it took about eight seconds to complete. Could I do better?

  • I came across Lasem, which meet every need. It has no external binary dependencies (only library packages), can convert directly to SVG, and it's fast. The same arbitrary 880 equations were rendered in less than three seconds.

And thus a wrapper was born.