mathematical 0.4.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +20 -9
- data/Rakefile +5 -24
- data/ext/mathematical/extconf.rb +8 -3
- data/ext/mathematical/lasem/src/lsmdomparser.c +7 -7
- data/ext/mathematical/lasem/src/lsmdomparser.h +2 -2
- data/ext/mathematical/lasem/src/lsmitex.c +8 -5
- data/ext/mathematical/lasem/src/lsmitex.h +1 -1
- data/ext/mathematical/lasem/src/lsmmathmldocument.c +2 -2
- data/ext/mathematical/lasem/src/lsmmathmldocument.h +1 -1
- data/ext/mathematical/lasem/tests/lsmtest.c +2 -2
- data/ext/mathematical/mathematical.c +119 -10
- data/ext/mathematical/mtex2MML/ext/extconf.rb +4 -0
- data/ext/mathematical/mtex2MML/src/lex.yy.c +6791 -0
- data/ext/mathematical/mtex2MML/src/mtex2MML.h +59 -0
- data/ext/mathematical/mtex2MML/src/parse_extras.c +306 -0
- data/ext/mathematical/mtex2MML/src/parse_extras.h +78 -0
- data/ext/mathematical/mtex2MML/src/stack.c +80 -0
- data/ext/mathematical/mtex2MML/src/stack.h +101 -0
- data/ext/mathematical/mtex2MML/src/string_extras.c +211 -0
- data/ext/mathematical/mtex2MML/src/string_extras.h +46 -0
- data/ext/mathematical/mtex2MML/src/y.tab.c +7090 -0
- data/ext/mathematical/mtex2MML/src/y.tab.h +393 -0
- data/lib/mathematical.rb +1 -0
- data/lib/mathematical/corrections.rb +34 -0
- data/lib/mathematical/render.rb +21 -12
- data/lib/mathematical/version.rb +1 -1
- data/mathematical.gemspec +2 -2
- data/test/mathematical/corrections_test.rb +56 -0
- data/test/mathematical/fixtures/png/pmatrix.png +0 -0
- data/test/mathematical/fixtures_test.rb +11 -1
- data/test/mathematical/maliciousness_test.rb +10 -2
- data/test/mathematical/mathml_test.rb +22 -0
- data/test/mathematical/png_test.rb +26 -0
- data/test/test_helper.rb +13 -0
- metadata +150 -134
- data/ext/mathematical/itexToMML/itex2MML.h +0 -63
- data/ext/mathematical/itexToMML/lex.yy.c +0 -6548
- data/ext/mathematical/itexToMML/y.tab.c +0 -6179
- data/ext/mathematical/itexToMML/y.tab.h +0 -389
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03f0731bd32ba0f8f1f6f8a3c83ce1ee89ece70d
|
4
|
+
data.tar.gz: e0ca46a7d69b7943645b8bb4bd64c2f6e780b8fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
35
|
+
The output will be a hash, with keys that depend on the format you want:
|
34
36
|
|
35
|
-
*
|
36
|
-
* `
|
37
|
-
* `
|
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 "
|
32
|
-
task :
|
31
|
+
desc "Copy samples to gh-pages"
|
32
|
+
task :copy_samples do
|
33
33
|
Dir.mktmpdir do |tmp|
|
34
|
-
system "cp
|
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
|
-
|
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
|
data/ext/mathematical/extconf.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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#{
|
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,
|
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 <
|
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,
|
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
|
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,
|
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,
|
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,
|
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,
|
34
|
-
LsmDomDocument * lsm_dom_document_new_from_memory (const void *buffer,
|
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,
|
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,
|
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 <
|
47
|
-
|
47
|
+
if (size < 0)
|
48
|
+
usize = strlen (itex);
|
49
|
+
else
|
50
|
+
usize = size;
|
48
51
|
|
49
|
-
mathml = itex2MML_parse (itex,
|
52
|
+
mathml = itex2MML_parse (itex, usize);
|
50
53
|
if (mathml == NULL)
|
51
54
|
return NULL;
|
52
55
|
|
@@ -213,7 +213,7 @@ typedef enum {
|
|
213
213
|
} LsmMathmlDocumentError;
|
214
214
|
|
215
215
|
LsmMathmlDocument *
|
216
|
-
lsm_mathml_document_new_from_itex (const char *itex,
|
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
|
-
|
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,
|
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
|
-
|
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 =
|
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 "
|
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 =
|
104
|
-
if (mathml == NULL) rb_raise(rb_eParseError, "Failed to parse
|
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
|
-
|
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
|
-
|
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
|
-
|
146
|
-
|
147
|
-
|
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
|
}
|