mathematical 0.4.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
[](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
|
}
|