mathtype_to_mathml_plus 0.0.13 → 0.0.14
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/convert.rb +1 -1
- data/lib/mathtype-0.0.7.5/.gitignore +17 -0
- data/lib/mathtype-0.0.7.5/.rspec +2 -0
- data/lib/mathtype-0.0.7.5/Gemfile +4 -0
- data/lib/mathtype-0.0.7.5/LICENSE.txt +22 -0
- data/lib/mathtype-0.0.7.5/README.md +40 -0
- data/lib/mathtype-0.0.7.5/Rakefile +2 -0
- data/lib/mathtype-0.0.7.5/lib/file_parser/eps.rb +30 -0
- data/lib/mathtype-0.0.7.5/lib/file_parser/ole.rb +15 -0
- data/lib/mathtype-0.0.7.5/lib/file_parser/parser.rb +102 -0
- data/lib/mathtype-0.0.7.5/lib/file_parser/wmf.rb +28 -0
- data/lib/mathtype-0.0.7.5/lib/mathtype/version.rb +3 -0
- data/lib/mathtype-0.0.7.5/lib/mathtype.rb +86 -0
- data/lib/mathtype-0.0.7.5/lib/records/bintypes.rb +37 -0
- data/lib/mathtype-0.0.7.5/lib/records/end.rb +8 -0
- data/lib/mathtype-0.0.7.5/lib/records/mtef.rb +36 -0
- data/lib/mathtype-0.0.7.5/lib/records/nudge.rb +38 -0
- data/lib/mathtype-0.0.7.5/lib/records/ruler.rb +22 -0
- data/lib/mathtype-0.0.7.5/lib/records/snapshot.rb +19 -0
- data/lib/mathtype-0.0.7.5/lib/records/tmp.rb +7 -0
- data/lib/mathtype-0.0.7.5/lib/records/typesizes.rb +19 -0
- data/lib/mathtype-0.0.7.5/lib/records3/char.rb +53 -0
- data/lib/mathtype-0.0.7.5/lib/records3/embell.rb +109 -0
- data/lib/mathtype-0.0.7.5/lib/records3/end.rb +8 -0
- data/lib/mathtype-0.0.7.5/lib/records3/font.rb +27 -0
- data/lib/mathtype-0.0.7.5/lib/records3/line.rb +47 -0
- data/lib/mathtype-0.0.7.5/lib/records3/matrix.rb +80 -0
- data/lib/mathtype-0.0.7.5/lib/records3/mtef.rb +97 -0
- data/lib/mathtype-0.0.7.5/lib/records3/nudge.rb +38 -0
- data/lib/mathtype-0.0.7.5/lib/records3/options.rb +5 -0
- data/lib/mathtype-0.0.7.5/lib/records3/pile.rb +43 -0
- data/lib/mathtype-0.0.7.5/lib/records3/ruler.rb +22 -0
- data/lib/mathtype-0.0.7.5/lib/records3/size.rb +75 -0
- data/lib/mathtype-0.0.7.5/lib/records3/snapshot.rb +19 -0
- data/lib/mathtype-0.0.7.5/lib/records3/tmpl.rb +751 -0
- data/lib/mathtype-0.0.7.5/lib/records3/typesizes.rb +24 -0
- data/lib/mathtype-0.0.7.5/lib/records5/char.rb +84 -0
- data/lib/mathtype-0.0.7.5/lib/records5/color.rb +13 -0
- data/lib/mathtype-0.0.7.5/lib/records5/color_def.rb +37 -0
- data/lib/mathtype-0.0.7.5/lib/records5/comment.rb +15 -0
- data/lib/mathtype-0.0.7.5/lib/records5/embell.rb +103 -0
- data/lib/mathtype-0.0.7.5/lib/records5/encoding_def.rb +22 -0
- data/lib/mathtype-0.0.7.5/lib/records5/end.rb +8 -0
- data/lib/mathtype-0.0.7.5/lib/records5/eqn_prefs.rb +44 -0
- data/lib/mathtype-0.0.7.5/lib/records5/font_def.rb +14 -0
- data/lib/mathtype-0.0.7.5/lib/records5/font_style_def.rb +14 -0
- data/lib/mathtype-0.0.7.5/lib/records5/future.rb +14 -0
- data/lib/mathtype-0.0.7.5/lib/records5/line.rb +36 -0
- data/lib/mathtype-0.0.7.5/lib/records5/matrix.rb +77 -0
- data/lib/mathtype-0.0.7.5/lib/records5/mtef.rb +134 -0
- data/lib/mathtype-0.0.7.5/lib/records5/mtuint.rb +14 -0
- data/lib/mathtype-0.0.7.5/lib/records5/nudge.rb +38 -0
- data/lib/mathtype-0.0.7.5/lib/records5/pile.rb +41 -0
- data/lib/mathtype-0.0.7.5/lib/records5/ruler.rb +22 -0
- data/lib/mathtype-0.0.7.5/lib/records5/size.rb +72 -0
- data/lib/mathtype-0.0.7.5/lib/records5/snapshot.rb +19 -0
- data/lib/mathtype-0.0.7.5/lib/records5/tmpl.rb +498 -0
- data/lib/mathtype-0.0.7.5/lib/records5/typesizes.rb +24 -0
- data/lib/mathtype-0.0.7.5/mathtype.gemspec +28 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/ceil.xml +38 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/fence.xml +77 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/floor.xml +38 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/frac.xml +136 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/large_nudge.xml +135 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/lim_embell.xml +247 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/matrix_2x1.xml +500 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/pile.xml +188 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/sigma_subsup.xml +46 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/small_nudge.xml +90 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/sqrt.xml +132 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/299.xml +1082 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/arrows.xml +1762 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/embedded.xml +350 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/embellishments.xml +911 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation1.xml +508 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation10.xml +373 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation11.xml +376 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation12.xml +445 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation13.xml +719 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation2.xml +437 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation3.xml +1437 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation4.xml +359 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation5.xml +380 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation6.xml +366 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation7.xml +373 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation8.xml +365 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation9.xml +357 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/fences.xml +1538 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/integrals.xml +1751 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/matrix-border.xml +350 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/matrix.xml +367 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/sizes.xml +386 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/ceil.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/fence.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/floor.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/frac.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/large_nudge.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/lim_embell.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/matrix_2x1.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/pile.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/sigma_subsup.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/small_nudge.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/sqrt.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/299.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/arrows.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/embedded.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/embellishments.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation1.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation10.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation11.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation12.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation13.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation2.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation3.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation4.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation5.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation6.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation7.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation8.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation9.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/fences.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/integrals.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/matrix-border.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/matrix.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/sizes.bin +0 -0
- data/lib/mathtype-0.0.7.5/spec/mathtype_spec.rb +18 -0
- data/lib/mathtype-0.0.7.5/spec/spec_helper.rb +59 -0
- data/lib/mathtype_to_mathml_plus/version.rb +1 -1
- data/lib/mathtype_to_mathml_plus.rb +1 -2
- data/oleObject11.bin +0 -0
- metadata +128 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fc4579dd069903f70cc783ad324cfc1c01a09573b07a334e0b5892a7087fcdb2
|
|
4
|
+
data.tar.gz: 4fc036e1f2bd673c07eaca8c2693645894b500e543ca885e4dcd5fbb6eb8e890
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b04c47298c11e02caccdb240cda47cadf566bc1b1d125f6d24de712a2e20002bd382aa55c601be5538d1ababa7f1e4075374b58055388f6afa35786b43a5ff21
|
|
7
|
+
data.tar.gz: da962421affc24aec5f71b1ea57df6a8a46d7446890e204a5a5fdf121fb8d8c1dc7ac1c016902e46b33515637a10f5a2ebe9dc70a79dd3dc22bb6746547c2ffb
|
data/convert.rb
CHANGED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2015 Jure Triglav
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Mathtype
|
|
2
|
+
|
|
3
|
+
This gem can read proprietary MathType binary equations that are usually embedded in Word documents and convert these equations into an XML form. This XML form can then be used for further processing, e.g. to convert the equation to MathML.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add this line to your application's Gemfile:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem 'mathtype'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
And then execute:
|
|
14
|
+
|
|
15
|
+
$ bundle
|
|
16
|
+
|
|
17
|
+
Or install it yourself as:
|
|
18
|
+
|
|
19
|
+
$ gem install mathtype
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
To convert a MathType binary equation (e.g. extracted from a Word document) to an XML form:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
xml = Mathtype::Converter.new("equation1.bin") # to get the Nokogiri XML object
|
|
27
|
+
puts xml.to_xml # to get the string XML representation
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
# Testing
|
|
31
|
+
|
|
32
|
+
Run `bundle exec rspec` to run specs.
|
|
33
|
+
|
|
34
|
+
## Contributing
|
|
35
|
+
|
|
36
|
+
1. Fork it ( https://github.com/[my-github-username]/mathtype/fork )
|
|
37
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
38
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
39
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
40
|
+
5. Create a new Pull Request
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Mathtype
|
|
2
|
+
class EpsFileParser < FileParser
|
|
3
|
+
def initialize(path)
|
|
4
|
+
super(path)
|
|
5
|
+
extract_mtef_from_epscomment(@raw)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def extract_mtef_from_epscomment(comment)
|
|
9
|
+
string64 = @raw.gsub /\r/, ""
|
|
10
|
+
# d for delimiter
|
|
11
|
+
d = string64[(/MathType(.)MTEF\1/ =~ string64) + 8]
|
|
12
|
+
matches = string64.match /.*MathType#{d}MTEF#{d}(.)#{d}(.)#{d}(.)(.)(.*)#{d}([0-9A-F]{4})#{d}.*/m
|
|
13
|
+
leading_chrs = matches[1].to_i
|
|
14
|
+
trailing_chrs = matches[2].to_i - 1
|
|
15
|
+
a64_chr1 = matches[3]
|
|
16
|
+
a64_chr2 = matches[4]
|
|
17
|
+
A64[a64_chr1] = 62
|
|
18
|
+
A64[a64_chr2] = 63
|
|
19
|
+
A64[62] = a64_chr1
|
|
20
|
+
A64[63] = a64_chr2
|
|
21
|
+
string64 = matches[5]
|
|
22
|
+
mtchecksum = matches[6]
|
|
23
|
+
string64.gsub! /.{#{trailing_chrs}}(\n).{#{leading_chrs}}/m, ""
|
|
24
|
+
@equation = decode string64
|
|
25
|
+
unless checksum == mtchecksum
|
|
26
|
+
raise ArgumentError, "Checksums do not match, expected #{mtchecksum} but got #{checksum}"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require "bindata"
|
|
2
|
+
require "ole/storage"
|
|
3
|
+
|
|
4
|
+
module Mathtype
|
|
5
|
+
class OleFileParser < FileParser
|
|
6
|
+
def initialize(path)
|
|
7
|
+
read_from_file(path)
|
|
8
|
+
end
|
|
9
|
+
def read_from_file(path)
|
|
10
|
+
ole = Ole::Storage.open(path, "rb+")
|
|
11
|
+
@equation = ole.file.read("Equation Native")[28..-1]
|
|
12
|
+
ole.close
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
module Mathtype
|
|
2
|
+
class FileParser
|
|
3
|
+
attr_reader :raw
|
|
4
|
+
attr_reader :equation
|
|
5
|
+
def initialize(path)
|
|
6
|
+
read_from_file(path)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def checksum
|
|
10
|
+
(@equation.bytes.reduce(:+) & 0xFFFF).to_s(16).upcase
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def read_from_file(path)
|
|
14
|
+
f = File.open(path, "rb")
|
|
15
|
+
@raw = f.read
|
|
16
|
+
f.close
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
A64 =
|
|
20
|
+
{
|
|
21
|
+
"a" => 0, "b" => 1, "c" => 2, "d" => 3, "e" => 4,
|
|
22
|
+
"f" => 5, "g" => 6, "h" => 7, "i" => 8, "j" => 9,
|
|
23
|
+
"k" => 10, "l" => 11, "m" => 12, "n" => 13, "o" => 14, "p" => 15,
|
|
24
|
+
"q" => 16, "r" => 17, "s" => 18, "t" => 19, "u" => 20, "v" => 21,
|
|
25
|
+
"w" => 22, "x" => 23, "y" => 24, "z" => 25, "A" => 26, "B" => 27,
|
|
26
|
+
"C" => 28, "D" => 29, "E" => 30, "F" => 31, "G" => 32, "H" => 33,
|
|
27
|
+
"I" => 34, "J" => 35, "K" => 36, "L" => 37, "M" => 38, "N" => 39,
|
|
28
|
+
"O" => 40, "P" => 41, "Q" => 42, "R" => 43, "S" => 44, "T" => 45,
|
|
29
|
+
"U" => 46, "V" => 47, "W" => 48, "X" => 49, "Y" => 50, "Z" => 51,
|
|
30
|
+
"0" => 52, "1" => 53, "2" => 54, "3" => 55, "4" => 56, "5" => 57,
|
|
31
|
+
"6" => 58, "7" => 59, "8" => 60, "9" => 61, "+" => 62, "-" => 63,
|
|
32
|
+
0 => "a", 1 => "b", 2 => "c", 3 => "d", 4 => "e",
|
|
33
|
+
5 => "f", 6 => "g", 7 => "h", 8 => "i", 9 => "j",
|
|
34
|
+
10 => "k", 11 => "l", 12 => "m", 13 => "n", 14 => "o", 15 => "p",
|
|
35
|
+
16 => "q", 17 => "r", 18 => "s", 19 => "t", 20 => "u", 21 => "v",
|
|
36
|
+
22 => "w", 23 => "x", 24 => "y", 25 => "z", 26 => "A", 27 => "B",
|
|
37
|
+
28 => "C", 29 => "D", 30 => "E", 31 => "F", 32 => "G", 33 => "H",
|
|
38
|
+
34 => "I", 35 => "J", 36 => "K", 37 => "L", 38 => "M", 39 => "N",
|
|
39
|
+
40 => "O", 41 => "P", 42 => "Q", 43 => "R", 44 => "S", 45 => "T",
|
|
40
|
+
46 => "U", 47 => "V", 48 => "W", 49 => "X", 50 => "Y", 51 => "Z",
|
|
41
|
+
52 => "0", 53 => "1", 54 => "2", 55 => "3", 56 => "4", 57 => "5",
|
|
42
|
+
58 => "6", 59 => "7", 60 => "8", 61 => "9", 62 => "+", 63 => "-"
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
def decode(string64)
|
|
46
|
+
#decode from base64 mtef to binary mtef
|
|
47
|
+
l = string64.length
|
|
48
|
+
i = b0 = b1 = carry = 0
|
|
49
|
+
out = []
|
|
50
|
+
while i < l
|
|
51
|
+
chr = A64[string64[i]]
|
|
52
|
+
case i % 4
|
|
53
|
+
when 0
|
|
54
|
+
b0 = chr
|
|
55
|
+
b1 = 0
|
|
56
|
+
when 1
|
|
57
|
+
b0 += ((chr & 3) << 6)
|
|
58
|
+
b1 = ((chr & 0xfc) >> 2)
|
|
59
|
+
out << b0
|
|
60
|
+
when 2
|
|
61
|
+
b0 = ((chr & 0x30) >> 4)
|
|
62
|
+
b1 += ((chr & 0xf) << 4)
|
|
63
|
+
when 3
|
|
64
|
+
b0 += chr << 2
|
|
65
|
+
out << b1 << b0
|
|
66
|
+
b0=b1=0
|
|
67
|
+
end
|
|
68
|
+
i += 1
|
|
69
|
+
end
|
|
70
|
+
out << b0 if i % 2 == 1
|
|
71
|
+
return out.pack("C*")
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def encode(mtef)
|
|
75
|
+
#encode from binary mtef to base64 mtef
|
|
76
|
+
out = ""
|
|
77
|
+
bytes = mtef.bytes
|
|
78
|
+
i = shft = 0
|
|
79
|
+
l = bytes.length
|
|
80
|
+
carry = 0
|
|
81
|
+
while i < l
|
|
82
|
+
chr = bytes[i] << shft
|
|
83
|
+
chr = chr | carry
|
|
84
|
+
out << A64[chr & 0x3f]
|
|
85
|
+
carry = chr >> 6
|
|
86
|
+
i += 1
|
|
87
|
+
shft = (i % 3) * 2
|
|
88
|
+
if shft == 0
|
|
89
|
+
out << A64[carry]
|
|
90
|
+
carry = 0
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
return out
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
require_relative "ole.rb"
|
|
100
|
+
require_relative "wmf.rb"
|
|
101
|
+
require_relative "eps.rb"
|
|
102
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Mathtype
|
|
2
|
+
class WmfFileParser < FileParser
|
|
3
|
+
def initialize(path)
|
|
4
|
+
super(path)
|
|
5
|
+
extract_mtef_from_mfcomment(@raw)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def extract_mtef_from_mfcomment(comment)
|
|
9
|
+
match = comment.match("MathTypeUU")
|
|
10
|
+
if match
|
|
11
|
+
lenpos = match.end(0)
|
|
12
|
+
len = comment[lenpos..lenpos+1].unpack("H*")[0].to_i 16
|
|
13
|
+
start = lenpos + 2
|
|
14
|
+
else
|
|
15
|
+
match = comment.match("AppsMFCC\x01")
|
|
16
|
+
raise ::NotImplementedError, "No MathType Equation found in wmf" unless match
|
|
17
|
+
len_start = match.end(0)
|
|
18
|
+
totallen = comment[len_start..len_start + 3].reverse.chars.rotate(-1).join.unpack("H*")[0].to_i 16
|
|
19
|
+
datalen = comment[len_start + 4 .. len_start + 7].reverse.chars.rotate(-1).join.unpack("H*")[0].to_i 16
|
|
20
|
+
signature = comment[len_start + 8.. -1].match(/.+?\x00/)
|
|
21
|
+
raise ::NotImplementedError, "Equation split over multiple comments" unless totallen == datalen
|
|
22
|
+
start = len_start + 8 + signature.end(0)
|
|
23
|
+
len = datalen
|
|
24
|
+
end
|
|
25
|
+
@equation = comment[start..(start + len)]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
require "mathtype/version"
|
|
2
|
+
require "nokogiri"
|
|
3
|
+
require_relative "file_parser/parser.rb"
|
|
4
|
+
require_relative "records/mtef.rb"
|
|
5
|
+
require_relative "records3/mtef.rb"
|
|
6
|
+
require_relative "records5/mtef.rb"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
module Mathtype
|
|
10
|
+
class Converter
|
|
11
|
+
attr_reader :parser
|
|
12
|
+
attr_reader :xml
|
|
13
|
+
attr_reader :builder
|
|
14
|
+
attr_reader :version
|
|
15
|
+
def initialize(equation)
|
|
16
|
+
set_parser(equation)
|
|
17
|
+
raise ::NotImplementedError, "Equation format not supported. Only .eps, .wmf and .bin (OLE-Object) currently supported, supplied was: #{equation}" unless @parser.equation
|
|
18
|
+
@version = @parser.equation[0].unpack('C')[0].to_i
|
|
19
|
+
raise ::NotImplementedError, "Only MTEF Version 3 and 5 currently supported, version is #{version}" unless (version==3 or version==5)
|
|
20
|
+
case @version
|
|
21
|
+
when 3
|
|
22
|
+
data = Mathtype3::Equation.read(@parser.equation).snapshot
|
|
23
|
+
when 5
|
|
24
|
+
data = Mathtype5::Equation.read(@parser.equation).snapshot
|
|
25
|
+
end
|
|
26
|
+
@builder = Nokogiri::XML::Builder.new do |xml|
|
|
27
|
+
@xml = xml
|
|
28
|
+
xml.root do
|
|
29
|
+
process(object: data)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def set_parser(equation)
|
|
35
|
+
if equation.end_with?(".bin")
|
|
36
|
+
@parser = Mathtype::OleFileParser.new equation
|
|
37
|
+
elsif equation.end_with?(".wmf")
|
|
38
|
+
@parser = Mathtype::WmfFileParser.new equation
|
|
39
|
+
else
|
|
40
|
+
@parser = Mathtype::EpsFileParser.new equation
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def to_xml
|
|
45
|
+
@builder.to_xml
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def process(element: "mtef", object:)
|
|
49
|
+
if object.is_a? Hash
|
|
50
|
+
case @version
|
|
51
|
+
when 3
|
|
52
|
+
name = Mathtype3::RECORD_NAMES[object[:record_type]]
|
|
53
|
+
else
|
|
54
|
+
name = Mathtype5::RECORD_NAMES[object[:record_type]]
|
|
55
|
+
end
|
|
56
|
+
if name
|
|
57
|
+
xml.send(name) do
|
|
58
|
+
(object[:payload] || {}).each do |k, v|
|
|
59
|
+
process(element: k, object: v)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
else
|
|
63
|
+
xml.send(element) do
|
|
64
|
+
object.each do |k, v|
|
|
65
|
+
process(element: k, object: v)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
elsif object.is_a? Array
|
|
70
|
+
object.each do |a|
|
|
71
|
+
process(element: element, object: a)
|
|
72
|
+
end
|
|
73
|
+
else
|
|
74
|
+
process_final_element(element, object)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def process_final_element(element, object)
|
|
79
|
+
if object.is_a? Hash
|
|
80
|
+
xml.send(element, object)
|
|
81
|
+
else
|
|
82
|
+
xml.send(element) { xml.text object }
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Mathtype
|
|
2
|
+
class Mtef16 < BinData::Primitive
|
|
3
|
+
uint8 :low, :initial_value => 0
|
|
4
|
+
uint8 :high, :initial_value => 0
|
|
5
|
+
|
|
6
|
+
def get; (high << 8) + low end
|
|
7
|
+
def getlow
|
|
8
|
+
self.low
|
|
9
|
+
end
|
|
10
|
+
def gethigh
|
|
11
|
+
self.high
|
|
12
|
+
end
|
|
13
|
+
def set(v)
|
|
14
|
+
self.low = v & 0xFF
|
|
15
|
+
self.high = (v & 0xFF00) >> 8
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class MatrixLineByte < BinData::Primitive
|
|
20
|
+
# row/columlines are represented as 2-bit values in a full byte, in reverse
|
|
21
|
+
# see MATRIX RECORD (5)
|
|
22
|
+
# a 3x3 matrix with rows "solid none dashed solid" would be represented as
|
|
23
|
+
# 01 10 00 01 = reverse 01 00 10 01
|
|
24
|
+
# a 4x4 matrix with "solid none dashed solid solid " accordingly does
|
|
25
|
+
# 01100001 00000001 = 01 00 10 01 01 00 00 00
|
|
26
|
+
uint8 :_byte
|
|
27
|
+
|
|
28
|
+
def get
|
|
29
|
+
[
|
|
30
|
+
(self._byte & 0x03),
|
|
31
|
+
(self._byte & 0x0C) >> 2,
|
|
32
|
+
(self._byte & 0x30) >> 4,
|
|
33
|
+
(self._byte & 0xC0) >> 6
|
|
34
|
+
]
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require_relative 'snapshot'
|
|
2
|
+
require_relative 'bintypes'
|
|
3
|
+
require_relative 'end'
|
|
4
|
+
require_relative 'nudge'
|
|
5
|
+
require_relative 'ruler'
|
|
6
|
+
require_relative 'typesizes'
|
|
7
|
+
|
|
8
|
+
module Mathtype
|
|
9
|
+
|
|
10
|
+
HALIGN = {
|
|
11
|
+
1 => "left",
|
|
12
|
+
2 => "center",
|
|
13
|
+
3 => "right",
|
|
14
|
+
4 => "al", # relational
|
|
15
|
+
5 => "dec" # decimal
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
VALIGN = {
|
|
19
|
+
0 => "top_baseline",
|
|
20
|
+
1 => "center_baseline",
|
|
21
|
+
2 => "bottom_baseline",
|
|
22
|
+
3 => "center", # vertical centering
|
|
23
|
+
4 => "axis" # math axis (center of +,-, brace points, etc.)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
class Equation < BinData::Record
|
|
27
|
+
endian :little
|
|
28
|
+
uint8 :mtef_version
|
|
29
|
+
uint8 :platform
|
|
30
|
+
uint8 :product
|
|
31
|
+
uint8 :product_version
|
|
32
|
+
uint8 :product_subversion
|
|
33
|
+
include Snapshot
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Nudge values:
|
|
2
|
+
# LINE, CHAR, TMPL, PILE, MATRIX, and EMBELL records may store the result of
|
|
3
|
+
# nudging (small offsets applied by the user). A nudged record has the
|
|
4
|
+
# mtefOPT_NUDGE option (0x8) and the option byte is followed immediately by
|
|
5
|
+
# the nudge offset. The nudge offset consists of either two bytes or six,
|
|
6
|
+
# depending on the amount of offset. If -128 <= dx < +128 and
|
|
7
|
+
# -128 <= dy < +128, then the offsets are stored as two bytes, dx followed
|
|
8
|
+
# by dy, where each value has 128 added to it before it is written. Otherwise,
|
|
9
|
+
# two bytes of 128 are stored, followed by the offsets, dx and dy, stored as
|
|
10
|
+
# 16-bit values, low byte followed by high byte.
|
|
11
|
+
|
|
12
|
+
require_relative "snapshot"
|
|
13
|
+
|
|
14
|
+
module Mathtype
|
|
15
|
+
class RecordNudge < BinData::Record
|
|
16
|
+
include Snapshot
|
|
17
|
+
EXPOSED_IN_SNAPSHOT = %i(dx dy)
|
|
18
|
+
|
|
19
|
+
endian :little
|
|
20
|
+
|
|
21
|
+
int8 :_small_dx
|
|
22
|
+
int8 :_small_dy
|
|
23
|
+
mtef16 :_large_dx, :onlyif => lambda { has_large_offset }
|
|
24
|
+
mtef16 :_large_dy, :onlyif => lambda { has_large_offset }
|
|
25
|
+
|
|
26
|
+
def dx
|
|
27
|
+
has_large_offset ? _large_dx : (_small_dx - 128)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def dy
|
|
31
|
+
has_large_offset ? _large_dy : (_small_dy - 128)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def has_large_offset
|
|
35
|
+
_small_dx == -128 and _small_dy == -128
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# RULER record (7):
|
|
2
|
+
# Consists of:
|
|
3
|
+
# record type (7)
|
|
4
|
+
# [n_stops] number of tab-stops
|
|
5
|
+
# [tab-stop list] tab-stops in order from left-to-right
|
|
6
|
+
# Each tab stop is described by a tab-stop type
|
|
7
|
+
# (0 for left, 1 for center, 2 for right, 3 for equal, 4 for decimal),
|
|
8
|
+
# followed by a 16-bit integer offset from the left end of the slot or pile
|
|
9
|
+
# with which it is associated.
|
|
10
|
+
|
|
11
|
+
module Mathtype
|
|
12
|
+
class RecordRuler < BinData::Record
|
|
13
|
+
endian :little
|
|
14
|
+
|
|
15
|
+
int8 :n_stops
|
|
16
|
+
|
|
17
|
+
array :tab_stops, initial_length: :n_stops do
|
|
18
|
+
int8 :tab_stop_type
|
|
19
|
+
mtef16 :tab_stop
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require "bindata"
|
|
2
|
+
|
|
3
|
+
module Mathtype
|
|
4
|
+
module Snapshot
|
|
5
|
+
def snapshot
|
|
6
|
+
snapshot = BinData::Record::Snapshot.new
|
|
7
|
+
exposed = self.class.const_get(:EXPOSED_IN_SNAPSHOT)
|
|
8
|
+
exposed.each do |name|
|
|
9
|
+
obj = find_obj_for_name(name)
|
|
10
|
+
if obj
|
|
11
|
+
snapshot[name] = obj.snapshot if include_obj?(obj)
|
|
12
|
+
else
|
|
13
|
+
snapshot[name] = self.send(name)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
snapshot
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Typesize records (10-14):
|
|
2
|
+
# Consists of:
|
|
3
|
+
# record type (10-14)
|
|
4
|
+
# These records are just short ways of specifying a simple typesize where dsize
|
|
5
|
+
# is zero. The tag value represents an lsize + 10. So if the tag value is 10,
|
|
6
|
+
# it means equation content following it will be Full size (szFULL), tag value
|
|
7
|
+
# 11 means szSUB, and so on. See typesize.
|
|
8
|
+
|
|
9
|
+
module Mathtype
|
|
10
|
+
class RecordFull < BinData::Record; end
|
|
11
|
+
|
|
12
|
+
class RecordSub < BinData::Record; end
|
|
13
|
+
|
|
14
|
+
class RecordSub2 < BinData::Record; end
|
|
15
|
+
|
|
16
|
+
class RecordSym < BinData::Record; end
|
|
17
|
+
|
|
18
|
+
class RecordSubsym < BinData::Record; end
|
|
19
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# CHAR record (2):
|
|
2
|
+
# Consists of:
|
|
3
|
+
# record type (2)
|
|
4
|
+
# options
|
|
5
|
+
# [nudge] if mtefOPT_NUDGE is set
|
|
6
|
+
# [typeface] typeface value (signed integer; see FONT_STYLE_DEF record below)
|
|
7
|
+
# [character] character value (see below)
|
|
8
|
+
# [embellishment list] if mtefOPT_CHAR_EMBELL is set (embellishments)
|
|
9
|
+
# The character value itself is represented by one or more values. The presence or absence of these value is indicated by options and appear in this order:
|
|
10
|
+
# 16-bit integer MTCode value present unless the mtefOPT_CHAR_ENC_NO_MTCODE option is set
|
|
11
|
+
# 8-bit font position present if the mtefOPT_CHAR_ENC_CHAR_8 option is set
|
|
12
|
+
# 16-bit integer font position present if the mtefOPT_CHAR_ENC_CHAR_16 option is set
|
|
13
|
+
# The MTCode value defines the character independent of its font. MTCode is a superset of Unicode and is described in MTCode Encoding Tables. The 8-bit and 16-bit font positions are mutually exclusive but may both be absent. This is the position of the character within its font. Some of the common font encodings are given in Font Encoding Tables.
|
|
14
|
+
|
|
15
|
+
require_relative "snapshot"
|
|
16
|
+
|
|
17
|
+
module Mathtype3
|
|
18
|
+
class RecordEmbell < BinData::Record; end
|
|
19
|
+
class RecordChar < BinData::Record
|
|
20
|
+
include Snapshot
|
|
21
|
+
EXPOSED_IN_SNAPSHOT = %i(options nudge typeface mt_code_value embellishment_list)
|
|
22
|
+
|
|
23
|
+
endian :little
|
|
24
|
+
|
|
25
|
+
mandatory_parameter :_options
|
|
26
|
+
|
|
27
|
+
virtual :_tag_options, :value => lambda{ _options }
|
|
28
|
+
|
|
29
|
+
record_nudge :nudge, onlyif: lambda { _options & OPTIONS["xfLMOVE"] > 0 }
|
|
30
|
+
|
|
31
|
+
int8 :_typeface
|
|
32
|
+
|
|
33
|
+
mtef16 :_mt_code_value
|
|
34
|
+
|
|
35
|
+
array :embellishment_list,
|
|
36
|
+
onlyif: lambda { _options & OPTIONS["xfEMBELL"] > 0 },
|
|
37
|
+
read_until: lambda { element.record_type == 0 } do
|
|
38
|
+
named_record
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def mt_code_value
|
|
42
|
+
sprintf("0x%04X", _mt_code_value)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def typeface
|
|
46
|
+
_typeface + 128
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def options
|
|
50
|
+
_tag_options
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|