Skip to content

Instantly share code, notes, and snippets.

@codeslinger
Created July 25, 2010 23:13
Show Gist options
  • Save codeslinger/489980 to your computer and use it in GitHub Desktop.
Save codeslinger/489980 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
# vim:set ts=4 sw=4 et ai:
#############################################################################
# Copyright (c) 2007, Toby DiPasquale
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the Toby DiPasquale nor the names of his
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#############################################################################
#
# Fancy Pants Formula Generator
#
# Web-based wrapper around LaTeX tools for easy creation of images with
# mathematical equations in them for use with any app that supports images
# but does not natively have an equation editor (e.g. Apple Pages,
# SocialText, etc).
#
# Last Modified: 2007.04.01
#
# Requires:
# Ruby >= 1.8.2
# Ghostscript >= 6.52
# NetPBM >= 9.24
# teTeX >= 3.0
#
# Inspired by John Walker's textogif
# <http://www.fourmilab.ch/webtools/textogif/textogif.html>
#
require 'webrick'
require 'cgi'
CLEANUP = "rm -f *.png"
P = { :dpi => 150, :res => 1.0, :background => '', :transparent => 'ff/ff/ff' }
CONVERT = [
"echo x | latex %s",
"dvips -f %s > %s",
"echo quit | gs -q -dNOPAUSE -r%dx%d -sOutputFile=- -sDEVICE=pbmraw %s | pnmcrop -white | pnmdepth 255 | %s pnmscale %.3f | pnmtopng -interlace -transparent rgb:%s > %s",
"rm -f *.tex *.dvi *.aux *.log *.ps",
"pngtopnm %s | pnmfile"
]
TEX_TEMPLATE = <<EOF
\\documentclass[12pt]{article}
\\pagestyle{empty}
\\begin{document}
\\begin{displaymath}
%s
\\end{displaymath}
\\end{document}
EOF
FORM_TEMPLATE = <<EOF
<html><head></head><body>
<h2>Fancy Pants Formula Generator</h2>
%s
<form method="POST" action="/formula">
<span>Enter LaTeX to convert to image of equation. <a href="http://cs.wlu.edu/~necaise/refs/latex2e/" target="_blank">LaTeX? Huh?</a></span><br/>
<textarea id="formula" name="formula" cols="60" rows="10" />%s</textarea>
<br/>
<label for="dpi">DPI</label>
%s
<input id="submit" name="submit" type="submit" value="Generate" />
</form>
</body></html>
EOF
class FormulaService < WEBrick::HTTPServlet::AbstractServlet
private
def run_system cmd
r = `#{cmd}`
raise "command failed with status #{$?.exitstatus}: #{cmd}" unless $?.exitstatus.zero?
r
end
def tempnam
"#{Time.now.to_i}#{rand(1000000)}"
end
def generate_dpi_select default
str = "<select id=\"dpi\" name=\"dpi\">\n"
(50..1000).step(25) { |x|
str << "<option value=\"%d\" %s>%d</option>\n" % [x, (x == default) ? "selected" : "", x]
}
str << "</select>\n"
str
end
def generate_image formula, dpi=P[:dpi]
tmp = tempnam
ps = tmp + ".ps"
imgfile = tmp + ".png"
File.open(tmp + ".tex", 'w') { |f| f.write(TEX_TEMPLATE % [formula]) }
scale = (dpi / P[:res]).to_i
run_system(CONVERT[0] % tmp)
run_system(CONVERT[1] % [tmp, ps])
run_system(CONVERT[2] % [scale, scale, ps, P[:background], P[:res], P[:transparent], imgfile])
run_system(CONVERT[3])
rv = run_system(CONVERT[4] % [imgfile])
rv =~ /(\d+) by (\d+)/m
width, height = $1, $2
"<img src=\"%s\" height=\"%d\" width=\"%d\"/><br/><br/>" % [imgfile, height, width]
end
def generate_page dpi=P[:dpi], formula='', img=''
FORM_TEMPLATE % [img, formula, generate_dpi_select(dpi)]
end
public
def do_GET req, resp
resp.body = generate_page
end
def do_POST req, resp
if req.body.nil?
resp.body = generate_page
else
parts = CGI.parse req.body
formula, dpi = parts['formula'][0], parts['dpi'][0].to_i
unless formula and dpi
raise "invalid form submission; missing parameter!"
end
img = generate_image formula, dpi
resp.body = generate_page dpi, formula, img
end
end
end
def start_webrick config={}
config.update :Port => 10000
server = WEBrick::HTTPServer.new config
yield server if block_given?
[ 'INT', 'TERM' ].each { |signal|
trap(signal) {
server.shutdown
system(CLEANUP)
}
}
server.start
end
start_webrick do |server|
server.mount '/', WEBrick::HTTPServlet::FileHandler, Dir.pwd
server.mount '/formula', FormulaService
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment