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.
Files changed (132) hide show
  1. checksums.yaml +4 -4
  2. data/convert.rb +1 -1
  3. data/lib/mathtype-0.0.7.5/.gitignore +17 -0
  4. data/lib/mathtype-0.0.7.5/.rspec +2 -0
  5. data/lib/mathtype-0.0.7.5/Gemfile +4 -0
  6. data/lib/mathtype-0.0.7.5/LICENSE.txt +22 -0
  7. data/lib/mathtype-0.0.7.5/README.md +40 -0
  8. data/lib/mathtype-0.0.7.5/Rakefile +2 -0
  9. data/lib/mathtype-0.0.7.5/lib/file_parser/eps.rb +30 -0
  10. data/lib/mathtype-0.0.7.5/lib/file_parser/ole.rb +15 -0
  11. data/lib/mathtype-0.0.7.5/lib/file_parser/parser.rb +102 -0
  12. data/lib/mathtype-0.0.7.5/lib/file_parser/wmf.rb +28 -0
  13. data/lib/mathtype-0.0.7.5/lib/mathtype/version.rb +3 -0
  14. data/lib/mathtype-0.0.7.5/lib/mathtype.rb +86 -0
  15. data/lib/mathtype-0.0.7.5/lib/records/bintypes.rb +37 -0
  16. data/lib/mathtype-0.0.7.5/lib/records/end.rb +8 -0
  17. data/lib/mathtype-0.0.7.5/lib/records/mtef.rb +36 -0
  18. data/lib/mathtype-0.0.7.5/lib/records/nudge.rb +38 -0
  19. data/lib/mathtype-0.0.7.5/lib/records/ruler.rb +22 -0
  20. data/lib/mathtype-0.0.7.5/lib/records/snapshot.rb +19 -0
  21. data/lib/mathtype-0.0.7.5/lib/records/tmp.rb +7 -0
  22. data/lib/mathtype-0.0.7.5/lib/records/typesizes.rb +19 -0
  23. data/lib/mathtype-0.0.7.5/lib/records3/char.rb +53 -0
  24. data/lib/mathtype-0.0.7.5/lib/records3/embell.rb +109 -0
  25. data/lib/mathtype-0.0.7.5/lib/records3/end.rb +8 -0
  26. data/lib/mathtype-0.0.7.5/lib/records3/font.rb +27 -0
  27. data/lib/mathtype-0.0.7.5/lib/records3/line.rb +47 -0
  28. data/lib/mathtype-0.0.7.5/lib/records3/matrix.rb +80 -0
  29. data/lib/mathtype-0.0.7.5/lib/records3/mtef.rb +97 -0
  30. data/lib/mathtype-0.0.7.5/lib/records3/nudge.rb +38 -0
  31. data/lib/mathtype-0.0.7.5/lib/records3/options.rb +5 -0
  32. data/lib/mathtype-0.0.7.5/lib/records3/pile.rb +43 -0
  33. data/lib/mathtype-0.0.7.5/lib/records3/ruler.rb +22 -0
  34. data/lib/mathtype-0.0.7.5/lib/records3/size.rb +75 -0
  35. data/lib/mathtype-0.0.7.5/lib/records3/snapshot.rb +19 -0
  36. data/lib/mathtype-0.0.7.5/lib/records3/tmpl.rb +751 -0
  37. data/lib/mathtype-0.0.7.5/lib/records3/typesizes.rb +24 -0
  38. data/lib/mathtype-0.0.7.5/lib/records5/char.rb +84 -0
  39. data/lib/mathtype-0.0.7.5/lib/records5/color.rb +13 -0
  40. data/lib/mathtype-0.0.7.5/lib/records5/color_def.rb +37 -0
  41. data/lib/mathtype-0.0.7.5/lib/records5/comment.rb +15 -0
  42. data/lib/mathtype-0.0.7.5/lib/records5/embell.rb +103 -0
  43. data/lib/mathtype-0.0.7.5/lib/records5/encoding_def.rb +22 -0
  44. data/lib/mathtype-0.0.7.5/lib/records5/end.rb +8 -0
  45. data/lib/mathtype-0.0.7.5/lib/records5/eqn_prefs.rb +44 -0
  46. data/lib/mathtype-0.0.7.5/lib/records5/font_def.rb +14 -0
  47. data/lib/mathtype-0.0.7.5/lib/records5/font_style_def.rb +14 -0
  48. data/lib/mathtype-0.0.7.5/lib/records5/future.rb +14 -0
  49. data/lib/mathtype-0.0.7.5/lib/records5/line.rb +36 -0
  50. data/lib/mathtype-0.0.7.5/lib/records5/matrix.rb +77 -0
  51. data/lib/mathtype-0.0.7.5/lib/records5/mtef.rb +134 -0
  52. data/lib/mathtype-0.0.7.5/lib/records5/mtuint.rb +14 -0
  53. data/lib/mathtype-0.0.7.5/lib/records5/nudge.rb +38 -0
  54. data/lib/mathtype-0.0.7.5/lib/records5/pile.rb +41 -0
  55. data/lib/mathtype-0.0.7.5/lib/records5/ruler.rb +22 -0
  56. data/lib/mathtype-0.0.7.5/lib/records5/size.rb +72 -0
  57. data/lib/mathtype-0.0.7.5/lib/records5/snapshot.rb +19 -0
  58. data/lib/mathtype-0.0.7.5/lib/records5/tmpl.rb +498 -0
  59. data/lib/mathtype-0.0.7.5/lib/records5/typesizes.rb +24 -0
  60. data/lib/mathtype-0.0.7.5/mathtype.gemspec +28 -0
  61. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/ceil.xml +38 -0
  62. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/fence.xml +77 -0
  63. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/floor.xml +38 -0
  64. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/frac.xml +136 -0
  65. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/large_nudge.xml +135 -0
  66. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/lim_embell.xml +247 -0
  67. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/matrix_2x1.xml +500 -0
  68. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/pile.xml +188 -0
  69. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/sigma_subsup.xml +46 -0
  70. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/small_nudge.xml +90 -0
  71. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype3/sqrt.xml +132 -0
  72. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/299.xml +1082 -0
  73. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/arrows.xml +1762 -0
  74. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/embedded.xml +350 -0
  75. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/embellishments.xml +911 -0
  76. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation1.xml +508 -0
  77. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation10.xml +373 -0
  78. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation11.xml +376 -0
  79. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation12.xml +445 -0
  80. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation13.xml +719 -0
  81. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation2.xml +437 -0
  82. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation3.xml +1437 -0
  83. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation4.xml +359 -0
  84. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation5.xml +380 -0
  85. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation6.xml +366 -0
  86. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation7.xml +373 -0
  87. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation8.xml +365 -0
  88. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/equation9.xml +357 -0
  89. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/fences.xml +1538 -0
  90. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/integrals.xml +1751 -0
  91. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/matrix-border.xml +350 -0
  92. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/matrix.xml +367 -0
  93. data/lib/mathtype-0.0.7.5/spec/fixtures/expected/mathtype5/sizes.xml +386 -0
  94. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/ceil.bin +0 -0
  95. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/fence.bin +0 -0
  96. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/floor.bin +0 -0
  97. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/frac.bin +0 -0
  98. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/large_nudge.bin +0 -0
  99. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/lim_embell.bin +0 -0
  100. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/matrix_2x1.bin +0 -0
  101. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/pile.bin +0 -0
  102. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/sigma_subsup.bin +0 -0
  103. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/small_nudge.bin +0 -0
  104. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype3/sqrt.bin +0 -0
  105. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/299.bin +0 -0
  106. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/arrows.bin +0 -0
  107. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/embedded.bin +0 -0
  108. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/embellishments.bin +0 -0
  109. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation1.bin +0 -0
  110. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation10.bin +0 -0
  111. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation11.bin +0 -0
  112. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation12.bin +0 -0
  113. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation13.bin +0 -0
  114. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation2.bin +0 -0
  115. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation3.bin +0 -0
  116. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation4.bin +0 -0
  117. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation5.bin +0 -0
  118. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation6.bin +0 -0
  119. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation7.bin +0 -0
  120. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation8.bin +0 -0
  121. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/equation9.bin +0 -0
  122. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/fences.bin +0 -0
  123. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/integrals.bin +0 -0
  124. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/matrix-border.bin +0 -0
  125. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/matrix.bin +0 -0
  126. data/lib/mathtype-0.0.7.5/spec/fixtures/input/mathtype5/sizes.bin +0 -0
  127. data/lib/mathtype-0.0.7.5/spec/mathtype_spec.rb +18 -0
  128. data/lib/mathtype-0.0.7.5/spec/spec_helper.rb +59 -0
  129. data/lib/mathtype_to_mathml_plus/version.rb +1 -1
  130. data/lib/mathtype_to_mathml_plus.rb +1 -2
  131. data/oleObject11.bin +0 -0
  132. metadata +128 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 61dc01300451c4b4e4f50e41d021d3f5293fb5c8b49c3c839fec068f4801e8d9
4
- data.tar.gz: 7dc1af9c3dffe93fe102540692a26829bcecafebe6f56277831f103c5df0127d
3
+ metadata.gz: fc4579dd069903f70cc783ad324cfc1c01a09573b07a334e0b5892a7087fcdb2
4
+ data.tar.gz: 4fc036e1f2bd673c07eaca8c2693645894b500e543ca885e4dcd5fbb6eb8e890
5
5
  SHA512:
6
- metadata.gz: 98aff52b51c1a132f6e39e6aff9b63f9f6a9c1c97faf30f38fb9549413d8a5af3e74c7edc96b903f62ea2bee8902c15e2e0d251e9d6c4578e95a0a46a422fdb8
7
- data.tar.gz: 8e0473bf44c72f733b26433b11959dfa0ed5021732cce538ffe1133df9d89f7fb189a48be33d6aaf549e2ea3398bde2ede38193d21fa4c7e77dab0891b12e98b
6
+ metadata.gz: b04c47298c11e02caccdb240cda47cadf566bc1b1d125f6d24de712a2e20002bd382aa55c601be5538d1ababa7f1e4075374b58055388f6afa35786b43a5ff21
7
+ data.tar.gz: da962421affc24aec5f71b1ea57df6a8a46d7446890e204a5a5fdf121fb8d8c1dc7ac1c016902e46b33515637a10f5a2ebe9dc70a79dd3dc22bb6746547c2ffb
data/convert.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require_relative 'lib/mathtype_to_mathml_plus'
2
2
 
3
- converter = MathTypeToMathMLPlus::Converter.new("oleObject2.bin")
3
+ converter = MathTypeToMathMLPlus::Converter.new("oleObject1.bin")
4
4
  xml = converter.convert
5
5
 
6
6
  puts xml
@@ -0,0 +1,17 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ *.gem
15
+ mkmf.log
16
+ *~
17
+ #*#
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mathtype.gemspec
4
+ gemspec
@@ -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,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -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,3 @@
1
+ module Mathtype
2
+ VERSION = "0.2.0"
3
+ 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,8 @@
1
+ module Mathtype
2
+ class RecordEnd < BinData::Primitive
3
+ def get; ""; end
4
+ def set(v); end
5
+
6
+ def to_formatted_s(indent = 0); to_s; end
7
+ end
8
+ 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,7 @@
1
+ module Mathtype
2
+ class RecordChar < BinData::Record; end
3
+ class RecordLine < BinData::Record; end
4
+ class RecordMatrix < BinData::Record; end
5
+ class RecordPile < BinData::Record; end
6
+ class RecordSize < BinData::Record; end
7
+ 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