mathematical 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +20 -9
  3. data/Rakefile +5 -24
  4. data/ext/mathematical/extconf.rb +8 -3
  5. data/ext/mathematical/lasem/src/lsmdomparser.c +7 -7
  6. data/ext/mathematical/lasem/src/lsmdomparser.h +2 -2
  7. data/ext/mathematical/lasem/src/lsmitex.c +8 -5
  8. data/ext/mathematical/lasem/src/lsmitex.h +1 -1
  9. data/ext/mathematical/lasem/src/lsmmathmldocument.c +2 -2
  10. data/ext/mathematical/lasem/src/lsmmathmldocument.h +1 -1
  11. data/ext/mathematical/lasem/tests/lsmtest.c +2 -2
  12. data/ext/mathematical/mathematical.c +119 -10
  13. data/ext/mathematical/mtex2MML/ext/extconf.rb +4 -0
  14. data/ext/mathematical/mtex2MML/src/lex.yy.c +6791 -0
  15. data/ext/mathematical/mtex2MML/src/mtex2MML.h +59 -0
  16. data/ext/mathematical/mtex2MML/src/parse_extras.c +306 -0
  17. data/ext/mathematical/mtex2MML/src/parse_extras.h +78 -0
  18. data/ext/mathematical/mtex2MML/src/stack.c +80 -0
  19. data/ext/mathematical/mtex2MML/src/stack.h +101 -0
  20. data/ext/mathematical/mtex2MML/src/string_extras.c +211 -0
  21. data/ext/mathematical/mtex2MML/src/string_extras.h +46 -0
  22. data/ext/mathematical/mtex2MML/src/y.tab.c +7090 -0
  23. data/ext/mathematical/mtex2MML/src/y.tab.h +393 -0
  24. data/lib/mathematical.rb +1 -0
  25. data/lib/mathematical/corrections.rb +34 -0
  26. data/lib/mathematical/render.rb +21 -12
  27. data/lib/mathematical/version.rb +1 -1
  28. data/mathematical.gemspec +2 -2
  29. data/test/mathematical/corrections_test.rb +56 -0
  30. data/test/mathematical/fixtures/png/pmatrix.png +0 -0
  31. data/test/mathematical/fixtures_test.rb +11 -1
  32. data/test/mathematical/maliciousness_test.rb +10 -2
  33. data/test/mathematical/mathml_test.rb +22 -0
  34. data/test/mathematical/png_test.rb +26 -0
  35. data/test/test_helper.rb +13 -0
  36. metadata +150 -134
  37. data/ext/mathematical/itexToMML/itex2MML.h +0 -63
  38. data/ext/mathematical/itexToMML/lex.yy.c +0 -6548
  39. data/ext/mathematical/itexToMML/y.tab.c +0 -6179
  40. data/ext/mathematical/itexToMML/y.tab.h +0 -389
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7f786243252000f0ce7053c49e288c8024edc860
4
- data.tar.gz: 8958c2259c707f27a9cddb5655b8ac1e9dd6d76c
3
+ metadata.gz: 03f0731bd32ba0f8f1f6f8a3c83ce1ee89ece70d
4
+ data.tar.gz: e0ca46a7d69b7943645b8bb4bd64c2f6e780b8fa
5
5
  SHA512:
6
- metadata.gz: 623fa07b26e1693d761561ac91305a50d5e87da002a472e2a7a5b42342eb2ce6c8a69dcc43b0986f0195e8f9038dcd62add881e43407b44d72f7b637f1649a49
7
- data.tar.gz: 716e5e0ca88f633957d322dae909b1d5efc23ef2aedb7278d936ad0af6f09f54a646fef3fcf0cc01235c0d69eba938e5902b8a274683f63621fef615e9d49675
6
+ metadata.gz: 33098207ab043b4b6452b0b35eb332bf731abfedc2fb29ddb14f446e5dab94edc2fefaf51b8f4bc75b3877c69e3fb72c06dbfe3dda4350a3e561ae7516e18ffc
7
+ data.tar.gz: 2341104e60ea0d51019912c607bf8d81ddd48e46b41aaa2d789e11026eb28d5bde6af0c500754ff9d329431bb11f0d80e4f6a122128b5a8e1e95c42468ae52b4
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Mathematical
2
2
 
3
- Quickly convert math equations into beautiful SVGs.
3
+ Quickly convert math equations into beautiful SVGs (or PNGs/MathML).
4
4
 
5
5
  [![Build Status](https://travis-ci.org/gjtorikian/mathematical.svg?branch=master)](https://travis-ci.org/gjtorikian/mathematical)
6
6
 
@@ -25,16 +25,25 @@ Or install it yourself as:
25
25
  The simplest way to do this is
26
26
 
27
27
  ``` ruby
28
+ require 'mathematical'
29
+
28
30
  Mathematical::Render.new.render(string_with_math)
29
31
  ```
30
32
 
31
33
  `string_with_math` should just be a string of itex inline (`$..$`) or display (`$$..$$`) style math.
32
34
 
33
- The output will be a hash, with the following data:
35
+ The output will be a hash, with keys that depend on the format you want:
34
36
 
35
- * `width`: the width of the resulting SVG file
36
- * `height`: the height of the resulting SVG file
37
- * `svg`: the actual string of SVG
37
+ * If you asked for an SVG, you'll get:
38
+ * `width`: the width of the resulting image
39
+ * `height`: the height of the resulting image
40
+ * `svg`: the actual string of SVG
41
+ * If you asked for a PNG, you'll get:
42
+ * `width`: the width of the resulting image
43
+ * `height`: the height of the resulting image
44
+ * `png`: the PNG data
45
+ * If you asked for MathML, you'll get:
46
+ * `mathml`: the MathML data
38
47
 
39
48
  ### Options
40
49
 
@@ -43,6 +52,8 @@ The output will be a hash, with the following data:
43
52
  * `:ppi` - A double determining the pixels per inch of the resulting SVG (default: `72.0`).
44
53
  * `:zoom` - A double determining the zoom level of the resulting SVG (default: `1.0`).
45
54
  * `:base64` - A boolean determining whether Mathematical's output should be a base64-encoded SVG string (default: `false`).
55
+ * `:maxsize` - A numeral indicating the `MAXSIZE` the output string can be. (default: `unsigned long`).
56
+ * `:format` - A string indicating whether you want an "svg", "png", or "mathml" output. (default: `svg`).
46
57
 
47
58
  Pass these in as an options hash:
48
59
 
@@ -56,6 +67,8 @@ renderer.render('$a \ne b$')
56
67
 
57
68
  Literally everything on the [itex2MML homepage for version 1.5.1](http://golem.ph.utexas.edu/~distler/blog/itex2MMLcommands.html) is supported, because it acts as the interpretation engine for Mathematical.
58
69
 
70
+ **Note**: This library makes few assumptions about the strings that you pass in. It assumes that `$..$` is inline math, `$$..$$` is display math, and that slashes like `\\` are escaped (`\\\\`).
71
+
59
72
  ## Dependencies
60
73
 
61
74
  Before using this gem, you must install the following libraries:
@@ -98,11 +111,9 @@ curl -LO http://mirrors.ctan.org/fonts/cm/ps-type1/bakoma/ttf/cmex10.ttf \
98
111
  To install these dependencies on a *nix machine, fetch the packages through your package manager. For example:
99
112
 
100
113
  ```
101
- sudo apt-get -qq -y install libxml2-dev libcairo2-dev libpango1.0-dev ttf-lyx
114
+ sudo apt-get -qq -y install libglib2.0-dev libxml2-dev libcairo2-dev libpango1.0-dev ttf-lyx libgdk-pixbuf2.0-dev
102
115
  ```
103
116
 
104
- `glib` and `gdk-pixbuf` should be on your machine.
105
-
106
117
  ### Windows install
107
118
 
108
119
  On a Windows machine, I have no idea. Pull requests welcome!
@@ -121,7 +132,7 @@ Rendering... 9.470000 0.750000 10.220000 ( 13.9
121
132
 
122
133
  After cloning the repo:
123
134
 
124
- ```
135
+ ```
125
136
  script/bootstrap
126
137
  bundle exec rake compile
127
138
  ```
data/Rakefile CHANGED
@@ -28,34 +28,14 @@ Rake::Task[:test].prerequisites << :compile
28
28
 
29
29
  task :default => [:test]
30
30
 
31
- desc "Generate and publish to gh-pages"
32
- task :publish do
31
+ desc "Copy samples to gh-pages"
32
+ task :copy_samples do
33
33
  Dir.mktmpdir do |tmp|
34
- system "cp test/mathematical/fixtures/after/* #{tmp}"
35
- titles_to_content = {}
36
- Dir.glob("#{tmp}/compliance_*.html") do |item|
37
- titles_to_content[File.basename(item)] = File.read(item)
38
- end
34
+ system "cp -r samples #{tmp}"
39
35
 
40
36
  system "git checkout gh-pages"
41
37
 
42
- li_listing = titles_to_content.keys.map { |title| "<li><a href='#{title}'>#{File.basename(title, File.extname(title))}</a></li>" }
43
- index = File.read("index.html")
44
- File.open("index.html", 'w') { |file| file.write(index.sub(/<!-- LIST_GOES_HERE -->/, li_listing.join("\n"))) }
45
-
46
- layout = File.read("layout_shell.text")
47
- titles_to_content.each do |title, content|
48
- new_layout = layout.sub(/<!-- TITLE_GOES_HERE -->/, title)
49
- new_layout = new_layout.sub(/<!-- CONTENT_GOES_HERE -->/, content)
50
- File.open("#{title}", 'w') { |file| file.write(new_layout) }
51
- end
52
-
53
- message = "Site updated at #{Time.now.utc}"
54
- system "git add ."
55
- system "git commit -am #{message.shellescape}"
56
- system "git push origin gh-pages --force"
57
- system "git checkout master"
58
- system "echo yolo"
38
+ system "cp -r #{tmp}/samples ."
59
39
  end
60
40
  end
61
41
 
@@ -65,4 +45,5 @@ task :destroy_copies do
65
45
  next if f =~ /extconf.rb/ || f =~ /mathematical.c/
66
46
  File.delete(f)
67
47
  end
48
+ Dir.glob("#{ext_dir}/{lib,src,test,ext}").select { |d| FileUtils.rm_rf d }
68
49
  end
@@ -3,7 +3,7 @@ require 'rbconfig'
3
3
  host_os = RbConfig::CONFIG['host_os']
4
4
 
5
5
  LASEM_DIR = File.join(File.dirname(__FILE__), "lasem", "src")
6
- ITEX_DIR = File.join(File.dirname(__FILE__), "itexToMML")
6
+ MTEX_DIR = File.join(File.dirname(__FILE__), "mtex2MML", "src")
7
7
 
8
8
  if host_os =~ /darwin|mac os/
9
9
  ENV['PKG_CONFIG_PATH'] = "/opt/X11/lib/pkgconfig:#{ENV['PKG_CONFIG_PATH']}"
@@ -20,11 +20,16 @@ find_header("libxml/xpathInternals.h", "/usr/include/libxml2", "/usr/local/inclu
20
20
  FileUtils.cp_r(Dir.glob("#{LASEM_DIR}/*"), File.dirname(__FILE__))
21
21
  File.delete(File.join(File.dirname(__FILE__), "lasemrender.c"))
22
22
 
23
- FileUtils.cp_r(Dir.glob("#{ITEX_DIR}/*"), File.dirname(__FILE__))
23
+ # build mtex2MML Bison files
24
+ Dir.chdir(MTEX_DIR) do
25
+ system "make"
26
+ end
27
+
28
+ FileUtils.cp_r(Dir.glob("#{MTEX_DIR}/*.{c,h,cc}"), File.dirname(__FILE__))
24
29
 
25
30
  have_library("pangocairo-1.0")
26
31
 
27
32
  $LDFLAGS += " #{`pkg-config --static --libs glib-2.0 gdk-pixbuf-2.0 cairo pango`.chomp}"
28
- $CFLAGS += " #{`pkg-config --cflags glib-2.0 gdk-pixbuf-2.0 cairo pango`.chomp} -I#{LASEM_DIR} -I#{ITEX_DIR}"
33
+ $CFLAGS += " #{`pkg-config --cflags glib-2.0 gdk-pixbuf-2.0 cairo pango`.chomp} -DFLIP_OFFSET_VAL -I#{LASEM_DIR} -I#{MTEX_DIR}"
29
34
 
30
35
  create_makefile("mathematical/mathematical")
@@ -259,7 +259,7 @@ typedef enum {
259
259
 
260
260
  static LsmDomDocument *
261
261
  _parse_memory (LsmDomDocument *document, LsmDomNode *node,
262
- const void *buffer, gsize size, GError **error)
262
+ const void *buffer, gssize size, GError **error)
263
263
  {
264
264
  static LsmDomSaxParserState state;
265
265
 
@@ -269,7 +269,7 @@ _parse_memory (LsmDomDocument *document, LsmDomNode *node,
269
269
  else
270
270
  state.current_node = LSM_DOM_NODE (document);
271
271
 
272
- if (size < 1)
272
+ if (size < 0)
273
273
  size = strlen (buffer);
274
274
 
275
275
  if (xmlSAXUserParseMemory (&sax_handler, &state, buffer, size) < 0) {
@@ -293,18 +293,18 @@ _parse_memory (LsmDomDocument *document, LsmDomNode *node,
293
293
  * @document: a #LsmDomDocument
294
294
  * @node: a #LsmDomNode
295
295
  * @buffer: a memory buffer holding xml data
296
- * @size: size of the xml data, in bytes, 0 if unknown
296
+ * @size: size of the xml data, in bytes, -1 if NULL terminated
297
297
  * @error: an error placeholder
298
298
  *
299
299
  * Append a chunk of xml tree to an existing document. The resulting nodes will be appended to
300
300
  * @node, or to @document if @node == NULL.
301
301
  *
302
- * Size set to 0 indicates an unknow xml data size.
302
+ * Size set to -1 indicates the buffer is NULL terminated.
303
303
  */
304
304
 
305
305
  void
306
306
  lsm_dom_document_append_from_memory (LsmDomDocument *document, LsmDomNode *node,
307
- const void *buffer, gsize size, GError **error)
307
+ const void *buffer, gssize size, GError **error)
308
308
  {
309
309
  g_return_if_fail (LSM_IS_DOM_DOCUMENT (document));
310
310
  g_return_if_fail (LSM_IS_DOM_NODE (node) || node == NULL);
@@ -316,14 +316,14 @@ lsm_dom_document_append_from_memory (LsmDomDocument *document, LsmDomNode *node,
316
316
  /**
317
317
  * lsm_dom_document_new_from_memory:
318
318
  * @buffer: xml data
319
- * @size: size of the data, in bytes, 0 if unknown
319
+ * @size: size of the data, in bytes, -1 if NULL terminated
320
320
  * @error: an error placeholder
321
321
  *
322
322
  * Create a new document from a memory data buffer.
323
323
  */
324
324
 
325
325
  LsmDomDocument *
326
- lsm_dom_document_new_from_memory (const void *buffer, gsize size, GError **error)
326
+ lsm_dom_document_new_from_memory (const void *buffer, gssize size, GError **error)
327
327
  {
328
328
  g_return_val_if_fail (buffer != NULL, NULL);
329
329
 
@@ -30,8 +30,8 @@
30
30
  G_BEGIN_DECLS
31
31
 
32
32
  void lsm_dom_document_append_from_memory (LsmDomDocument *document, LsmDomNode *node,
33
- const void *buffer, gsize size, GError **error);
34
- LsmDomDocument * lsm_dom_document_new_from_memory (const void *buffer, gsize size, GError **error);
33
+ const void *buffer, gssize size, GError **error);
34
+ LsmDomDocument * lsm_dom_document_new_from_memory (const void *buffer, gssize size, GError **error);
35
35
  LsmDomDocument * lsm_dom_document_new_from_path (const char *path, GError **error);
36
36
  LsmDomDocument * lsm_dom_document_new_from_url (const char *url, GError **error);
37
37
 
@@ -28,7 +28,7 @@
28
28
  /**
29
29
  * lsm_itex_to_mathml:
30
30
  * @itex: (allow-none): an itex string
31
- * @size: itex string length, 0 if unknown
31
+ * @size: itex string length, -1 if NULL terminated
32
32
  *
33
33
  * Converts an itex string to a Mathml representation.
34
34
  *
@@ -36,17 +36,20 @@
36
36
  */
37
37
 
38
38
  char *
39
- lsm_itex_to_mathml (const char *itex, gsize size)
39
+ lsm_itex_to_mathml (const char *itex, gssize size)
40
40
  {
41
+ gsize usize;
41
42
  char *mathml;
42
43
 
43
44
  if (itex == NULL)
44
45
  return NULL;
45
46
 
46
- if (size < 1)
47
- size = strlen (itex);
47
+ if (size < 0)
48
+ usize = strlen (itex);
49
+ else
50
+ usize = size;
48
51
 
49
- mathml = itex2MML_parse (itex, size);
52
+ mathml = itex2MML_parse (itex, usize);
50
53
  if (mathml == NULL)
51
54
  return NULL;
52
55
 
@@ -28,7 +28,7 @@
28
28
 
29
29
  G_BEGIN_DECLS
30
30
 
31
- char * lsm_itex_to_mathml (const char *itex, gsize size);
31
+ char * lsm_itex_to_mathml (const char *itex, gssize size);
32
32
  void lsm_itex_free_mathml_buffer (char *mathml);
33
33
 
34
34
  G_END_DECLS
@@ -213,7 +213,7 @@ typedef enum {
213
213
  } LsmMathmlDocumentError;
214
214
 
215
215
  LsmMathmlDocument *
216
- lsm_mathml_document_new_from_itex (const char *itex, gsize size, GError **error)
216
+ lsm_mathml_document_new_from_itex (const char *itex, gssize size, GError **error)
217
217
  {
218
218
  LsmDomDocument *document;
219
219
  char *mathml;
@@ -250,7 +250,7 @@ static LsmMathmlDocument *
250
250
  lsm_mathml_document_new_from_itex_file (GFile *file, GError **error)
251
251
  {
252
252
  LsmMathmlDocument *document;
253
- gsize size = 0;
253
+ gssize size = 0;
254
254
  char *contents = NULL;
255
255
 
256
256
  if (!g_file_load_contents (file, NULL, &contents, &size, NULL, error))
@@ -51,7 +51,7 @@ GType lsm_mathml_document_get_type (void);
51
51
  LsmDomDocument * lsm_mathml_document_new (void);
52
52
  LsmMathmlMathElement * lsm_mathml_document_get_root_element (const LsmMathmlDocument *document);
53
53
 
54
- LsmMathmlDocument * lsm_mathml_document_new_from_itex (const char *itex, gsize size, GError **error);
54
+ LsmMathmlDocument * lsm_mathml_document_new_from_itex (const char *itex, gssize size, GError **error);
55
55
  LsmMathmlDocument * lsm_mathml_document_new_from_itex_path (const char *url, GError **error);
56
56
  LsmMathmlDocument * lsm_mathml_document_new_from_itex_url (const char *url, GError **error);
57
57
 
@@ -254,7 +254,7 @@ lasem_test_render (char const *filename, gboolean compare, gboolean dry_run, Sta
254
254
  cairo_t *cairo;
255
255
  cairo_surface_t *surface;
256
256
  char *buffer = NULL;
257
- gsize size;
257
+ gssize size;
258
258
  char *png_filename;
259
259
  char *reference_png_filename;
260
260
  char *test_name;
@@ -300,7 +300,7 @@ lasem_test_render (char const *filename, gboolean compare, gboolean dry_run, Sta
300
300
  xml = buffer;
301
301
  else {
302
302
  xml = itex2MML_parse (buffer, size);
303
- size = 0;
303
+ size = -1;
304
304
  }
305
305
 
306
306
  timer = g_timer_new ();
@@ -33,7 +33,7 @@
33
33
  #include <cairo-pdf.h>
34
34
  #include <cairo-svg.h>
35
35
  #include <cairo-ps.h>
36
- #include "itex2MML.h"
36
+ #include "mtex2MML.h"
37
37
 
38
38
  #define CSTR2SYM(str) ID2SYM(rb_intern(str))
39
39
 
@@ -49,6 +49,64 @@ static VALUE rb_eDocumentCreationError;
49
49
  // Raised when the SVG document could not be read
50
50
  static VALUE rb_eDocumentReadError;
51
51
 
52
+ typedef enum {
53
+ FORMAT_SVG,
54
+ FORMAT_PNG,
55
+ FORMAT_MATHML
56
+ } FileFormat;
57
+
58
+ /**
59
+ * lsm_mtex_to_mathml:
60
+ * @mtex: (allow-none): an mtex string
61
+ * @size: mtex string length, -1 if NULL terminated
62
+ *
63
+ * Converts an mtex string to a Mathml representation.
64
+ *
65
+ * Return value: a newly allocated string, NULL on parse error. The returned data must be freed using @lsm_mtex_free_mathml_buffer.
66
+ */
67
+
68
+ char *
69
+ lsm_mtex_to_mathml (const char *mtex, gssize size)
70
+ {
71
+ gsize usize;
72
+ char *mathml;
73
+
74
+ if (mtex == NULL)
75
+ return NULL;
76
+
77
+ if (size < 0)
78
+ usize = strlen (mtex);
79
+ else
80
+ usize = size;
81
+
82
+ mathml = mtex2MML_parse (mtex, usize);
83
+ if (mathml == NULL)
84
+ return NULL;
85
+
86
+ if (mathml[0] == '\0') {
87
+ mtex2MML_free_string (mathml);
88
+ return NULL;
89
+ }
90
+
91
+ return mathml;
92
+ }
93
+
94
+ /**
95
+ * lsm_mtex_free_mathml_buffer:
96
+ * @mathml: (allow-none): a mathml buffer
97
+ *
98
+ * Free the buffer returned by @lsm_mtex_to_mathml.
99
+ */
100
+
101
+ void
102
+ lsm_mtex_free_mathml_buffer (char *mathml)
103
+ {
104
+ if (mathml == NULL)
105
+ return;
106
+
107
+ mtex2MML_free_string (mathml);
108
+ }
109
+
52
110
  cairo_status_t cairoSvgSurfaceCallback (void *closure, const unsigned char *data, unsigned int length) {
53
111
  VALUE self = (VALUE) closure;
54
112
  if (rb_iv_get(self, "@svg") == Qnil) {
@@ -60,21 +118,37 @@ cairo_status_t cairoSvgSurfaceCallback (void *closure, const unsigned char *data
60
118
  return CAIRO_STATUS_SUCCESS;
61
119
  }
62
120
 
121
+ cairo_status_t cairoPngSurfaceCallback (void *closure, const unsigned char *data, unsigned int length) {
122
+ VALUE self = (VALUE) closure;
123
+ if (rb_iv_get(self, "@png") == Qnil) {
124
+ rb_iv_set(self, "@png", rb_str_new2(""));
125
+ }
126
+
127
+ rb_str_cat(rb_iv_get(self, "@png"), data, length);
128
+
129
+ return CAIRO_STATUS_SUCCESS;
130
+ }
131
+
63
132
  static VALUE MATHEMATICAL_init(VALUE self, VALUE rb_Options) {
64
133
  Check_Type (rb_Options, T_HASH);
65
- VALUE rb_ppi, rb_zoom, rb_maxsize;
134
+ VALUE rb_ppi, rb_zoom, rb_maxsize, rb_format;
66
135
 
67
136
  rb_ppi = rb_hash_aref(rb_Options, CSTR2SYM("ppi"));
68
137
  rb_zoom = rb_hash_aref(rb_Options, CSTR2SYM("zoom"));
69
138
  rb_maxsize = rb_hash_aref(rb_Options, CSTR2SYM("maxsize"));
139
+ rb_format = rb_hash_aref(rb_Options, CSTR2SYM("format"));
70
140
 
71
141
  Check_Type(rb_ppi, T_FLOAT);
72
142
  Check_Type(rb_zoom, T_FLOAT);
73
143
  Check_Type(rb_maxsize, T_FIXNUM);
144
+ Check_Type(rb_format, T_STRING);
74
145
 
75
146
  rb_iv_set(self, "@ppi", rb_ppi);
76
147
  rb_iv_set(self, "@zoom", rb_zoom);
77
148
  rb_iv_set(self, "@maxsize", rb_maxsize);
149
+ rb_iv_set(self, "@format", rb_format);
150
+
151
+ rb_iv_set(self, "@png", Qnil);
78
152
  rb_iv_set(self, "@svg", Qnil);
79
153
 
80
154
  return self;
@@ -99,20 +173,30 @@ static VALUE MATHEMATICAL_process(VALUE self, VALUE rb_LatexCode) {
99
173
  g_type_init ();
100
174
  #endif
101
175
 
176
+ VALUE result_hash = rb_hash_new();
177
+ const char* rb_format = RSTRING_PTR(rb_iv_get(self, "@format"));
178
+
102
179
  // convert the TeX math to MathML
103
- char * mathml = lsm_itex_to_mathml(latex_code, latex_size);
104
- if (mathml == NULL) rb_raise(rb_eParseError, "Failed to parse itex");
180
+ char * mathml = mtex2MML_parse(latex_code, latex_size);
181
+ if (mathml == NULL) rb_raise(rb_eParseError, "Failed to parse mtex");
182
+
183
+ if (strncmp(rb_format, "mathml", 6) == 0) {
184
+ rb_hash_aset (result_hash, rb_tainted_str_new2 ("mathml"), rb_str_new2(mathml));
185
+ mtex2MML_free_string(mathml);
186
+ return result_hash;
187
+ }
105
188
 
106
189
  int mathml_size = strlen(mathml);
107
190
 
108
191
  LsmDomDocument *document;
109
192
  document = lsm_dom_document_new_from_memory(mathml, mathml_size, NULL);
110
193
 
111
- lsm_itex_free_mathml_buffer (mathml);
194
+ mtex2MML_free_string(mathml);
112
195
 
113
196
  if (document == NULL) rb_raise(rb_eDocumentCreationError, "Failed to create document");
114
197
 
115
198
  LsmDomView *view;
199
+ FileFormat format;
116
200
 
117
201
  double ppi = NUM2DBL(rb_iv_get(self, "@ppi"));
118
202
  double zoom = NUM2DBL(rb_iv_get(self, "@zoom"));
@@ -132,26 +216,51 @@ static VALUE MATHEMATICAL_process(VALUE self, VALUE rb_LatexCode) {
132
216
  cairo_t *cairo;
133
217
  cairo_surface_t *surface;
134
218
 
135
- surface = cairo_svg_surface_create_for_stream (cairoSvgSurfaceCallback, self, width_pt, height_pt);
219
+ if (strncmp(rb_format, "svg", 3) == 0) {
220
+ format = FORMAT_SVG;
221
+ surface = cairo_svg_surface_create_for_stream (cairoSvgSurfaceCallback, self, width_pt, height_pt);
222
+ }
223
+ else if (strncmp(rb_format, "png", 3) == 0) {
224
+ format = FORMAT_PNG;
225
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
226
+ }
227
+
136
228
  cairo = cairo_create (surface);
137
229
  cairo_surface_destroy (surface);
138
230
  cairo_scale (cairo, zoom, zoom);
139
231
  lsm_dom_view_render (view, cairo, 0, 0);
140
232
 
233
+ switch (format) {
234
+ case FORMAT_PNG:
235
+ cairo_surface_write_to_png_stream (cairo_get_target (cairo), cairoPngSurfaceCallback, self);
236
+ break;
237
+ default:
238
+ break;
239
+ }
240
+
141
241
  cairo_destroy (cairo);
142
242
  g_object_unref (view);
143
243
  g_object_unref (document);
144
244
 
145
- if (rb_iv_get(self, "@svg") == Qnil) rb_raise(rb_eDocumentReadError, "Failed to read SVG contents");
146
-
147
- VALUE result_hash = rb_hash_new();
245
+ switch (format) {
246
+ case FORMAT_SVG:
247
+ if (rb_iv_get(self, "@svg") == Qnil) rb_raise(rb_eDocumentReadError, "Failed to read SVG contents");
248
+ rb_hash_aset (result_hash, rb_tainted_str_new2 ("svg"), rb_iv_get(self, "@svg"));
249
+ break;
250
+ case FORMAT_PNG:
251
+ if (rb_iv_get(self, "@png") == Qnil) rb_raise(rb_eDocumentReadError, "Failed to read PNG contents");
252
+ rb_hash_aset (result_hash, rb_tainted_str_new2 ("png"), rb_iv_get(self, "@png"));
253
+ break;
254
+ default:
255
+ break;
256
+ }
148
257
 
149
258
  rb_hash_aset (result_hash, rb_tainted_str_new2 ("width"), INT2FIX(width_pt));
150
259
  rb_hash_aset (result_hash, rb_tainted_str_new2 ("height"), INT2FIX(height_pt));
151
- rb_hash_aset (result_hash, rb_tainted_str_new2 ("svg"), rb_iv_get(self, "@svg"));
152
260
 
153
261
  // we need to clear out this key when attempting multiple calls. See http://git.io/i1hblQ
154
262
  rb_iv_set(self, "@svg", Qnil);
263
+ rb_iv_set(self, "@png", Qnil);
155
264
 
156
265
  return result_hash;
157
266
  }