Skip to content

Commit

Permalink
improve imgmath function. Closes #868
Browse files Browse the repository at this point in the history
  • Loading branch information
kmuto committed Oct 13, 2018
1 parent 9d74ecf commit 084a186
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 10 deletions.
9 changes: 9 additions & 0 deletions lib/review/configure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,15 @@ def self.values
'makeindex_dic' => nil,
'makeindex_mecab' => true,
'makeindex_mecab_opts' => '-Oyomi'
},
'imgmath_options' => {
'format' => 'png',
'converter' => 'pdfcrop', # dvipng | pdfcrop
'pdfcrop_cmd' => 'pdfcrop --hires %i %o',
'preamble_file' => nil,
'fontsize' => 12,
'lineheight' => 12 * 1.2,
'pdfcrop_pixelize_cmd' => 'pdftocairo -png -f %p -l %p %i %o'
}
]
conf.maker = nil
Expand Down
141 changes: 141 additions & 0 deletions lib/review/epubmaker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
require 'rexml/streamlistener'
require 'epubmaker'
require 'review/epubmaker/reviewheaderlistener'
require 'shellwords'

module ReVIEW
class EPUBMaker
Expand Down Expand Up @@ -125,6 +126,9 @@ def produce(yamlfile, bookname = nil)
call_hook('hook_afterbody', basetmpdir)

copy_backmatter(basetmpdir)
if @config['imgmath'] && File.exist?("#{math_dir}/__IMGMATH_BODY__.tex")
make_math_images(math_dir)
end
call_hook('hook_afterbackmatter', basetmpdir)

## push contents in basetmpdir into @producer
Expand Down Expand Up @@ -267,6 +271,7 @@ def build_body(basetmpdir, yamlfile)
book.config = @config
@converter = ReVIEW::Converter.new(book, ReVIEW::HTMLBuilder.new)
@compile_errors = nil

book.parts.each do |part|
if part.name.present?
if part.file?
Expand Down Expand Up @@ -602,5 +607,141 @@ def check_image_size(basetmpdir, maxpixels, allow_exts = nil)

true
end

def default_imgmath_preamble
<<-EOB
\\documentclass[uplatex]{jsarticle}
\\usepackage[deluxe,uplatex]{otf}
\\usepackage[T1]{fontenc}
\\usepackage{textcomp}
\\usepackage{lmodern}
\\usepackage[dvipdfmx]{graphicx}
\\usepackage[dvipdfmx,table]{xcolor}
\\usepackage[utf8]{inputenc}
\\usepackage{ascmac}
\\usepackage{float}
\\usepackage{alltt}
\\usepackage{amsmath}
\\usepackage{amssymb}
\\usepackage{amsfonts}
\\usepackage{anyfontsize}
\\usepackage{bm}
\\pagestyle{empty}
EOB
end

def make_math_images(math_dir)
fontsize = @config['imgmath_options']['fontsize'].to_f
lineheight = @config['imgmath_options']['lineheight'].to_f

texsrc = default_imgmath_preamble
if @config['imgmath_options']['preamble_file'] && File.readable?(@config['imgmath_options']['preamble_file'])
texsrc = File.read(@config['imgmath_options']['preamble_file'])
end

texsrc << <<-EOB
\\begin{document}
\\fontsize{#{fontsize}}{#{lineheight}}\\selectfont
\\input{__IMGMATH_BODY__}
\\end{document}
EOB

math_dir = File.realpath(math_dir)
Dir.mktmpdir do |tmpdir|
FileUtils.cp([File.join(math_dir, '__IMGMATH_BODY__.tex'),
File.join(math_dir, '__IMGMATH_BODY__.map')],
tmpdir)
tex_path = File.join(tmpdir, '__IMGMATH__.tex')
File.write(tex_path, texsrc)

begin
case @config['imgmath_options']['converter']
when 'pdfcrop'
make_math_images_pdfcrop(tmpdir, tex_path, math_dir)
when 'dvipng'
make_math_images_dvipng(tmpdir, tex_path, math_dir)
end
rescue CompileError
FileUtils.cp([tex_path,
File.join(File.dirname(tex_path), '__IMGMATH__.log')],
math_dir)
error "LaTeX math compile error. See #{math_dir}/__IMGMATH__.log for details."
end
end
FileUtils.rm_f([File.join(math_dir, '__IMGMATH_BODY__.tex'),
File.join(math_dir, '__IMGMATH_BODY__.map')])
end

def make_math_images_pdfcrop(dir, tex_path, math_dir)
Dir.chdir(dir) do
dvi_path = '__IMGMATH__.dvi'
pdf_path = '__IMGMATH__.pdf'
out, status = Open3.capture2e(*[@config['texcommand'], @config['texoptions'].shellsplit, tex_path].flatten.compact)
if !status.success? || (!File.exist?(dvi_path) && !File.exist?(pdf_path))
raise CompileError
end
if File.exist?(dvi_path)
out, status = Open3.capture2e(*[@config['dvicommand'], @config['dvioptions'].shellsplit, dvi_path].flatten.compact)
if !status.success? || !File.exist?(pdf_path)
warn "error in #{@config['dvicommand']}. Error log:\n#{out}"
raise CompileError
end
end

File.open('__IMGMATH_BODY__.map') do |f|
page = 0
f.each_line do |key|
page += 1
key.chomp!
args = @config['imgmath_options']['pdfcrop_cmd'].shellsplit
args.map! do |m|
m.sub('%i', pdf_path).
sub('%o', '__IMGMATH__pdfcrop.pdf')
end
out, status = Open3.capture2e(*args)
unless status.success?
warn "error in pdfcrop. Error log:\n#{out}"
raise CompileError
end

args = @config['imgmath_options']['pdfcrop_pixelize_cmd'].shellsplit
args.map! do |m|
m.sub('%i', '__IMGMATH__pdfcrop.pdf').
sub('%o', File.join(math_dir, "_gen_#{key}.#{@config['imgmath_options']['format']}")).
sub('%O', File.join(math_dir, "_gen_#{key}")).
sub('%p', page.to_s)
end
out, status = Open3.capture2e(*args)
unless status.success?
warn "error in pdf pixelizing. Error log:\n#{out}"
raise CompileError
end
end
end
end
end

def make_math_images_dvipng(dir, tex_path, math_dir)
Dir.chdir(dir) do
dvi_path = '__IMGMATH__.dvi'
out, status = Open3.capture2e(*[@config['texcommand'], @config['texoptions'].shellsplit, tex_path].flatten.compact)
if !status.success? || !File.exist?(dvi_path)
raise CompileError
end

File.open('__IMGMATH_BODY__.map') do |f|
page = 0
f.each_line do |key|
page += 1
key.chomp!
out, status = Open3.capture2e('dvipng', '-T', 'tight', '-z', '9', '-p', page.to_s, '-l', page.to_s, '-o', File.join(math_dir, "_gen_#{key}.png"), dvi_path)
unless status.success?
warn "error in dvipng. Error log:\n#{out}"
raise CompileError
end
end
end
end
end
end
end
40 changes: 31 additions & 9 deletions lib/review/htmlbuilder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -549,14 +549,19 @@ def texequation(lines)
elsif @book.config['imgmath']
math_str = "\\begin{equation*}\n" + unescape(lines.join("\n")) + "\n\\end{equation*}\n"
key = Digest::SHA256.hexdigest(math_str)
math_dir = "./#{@book.config['imagedir']}/_review_math"
math_dir = File.join(@book.config['imagedir'], '_review_math')
Dir.mkdir(math_dir) unless Dir.exist?(math_dir)
img_path = "./#{math_dir}/_gen_#{key}.png"
make_math_image(math_str, img_path)
puts %Q(<img src="#{img_path}" />)
img_path = File.join(math_dir, "_gen_#{key}.#{@book.config['imgmath_options']['format']}")
if @book.config.check_version('2', exception: false)
make_math_image(math_str, img_path)
puts %Q(<img src="#{img_path}" />)
else
defer_math_image(math_str, img_path, key)
puts %Q(<img src="#{img_path}" alt="#{escape(lines.join(' '))}" />)
end
else
print '<pre>'
puts lines.join("\n")
puts escape(lines.join("\n"))
puts '</pre>'
end
puts '</div>'
Expand Down Expand Up @@ -924,11 +929,16 @@ def inline_m(str)
elsif @book.config['imgmath']
math_str = '$' + str + '$'
key = Digest::SHA256.hexdigest(str)
math_dir = "./#{@book.config['imagedir']}/_review_math"
math_dir = File.join(@book.config['imagedir'], '_review_math')
Dir.mkdir(math_dir) unless Dir.exist?(math_dir)
img_path = "./#{math_dir}/_gen_#{key}.png"
make_math_image(math_str, img_path)
%Q(<span class="equation"><img src="#{img_path}" /></span>)
img_path = File.join(math_dir, "_gen_#{key}.#{@book.config['imgmath_options']['format']}")
if @book.config.check_version('2', exception: false)
make_math_image(math_str, img_path)
%Q(<span class="equation"><img src="#{img_path}" /></span>)
else
defer_math_image(math_str, img_path, key)
%Q(<span class="equation"><img src="#{img_path}" alt="#{escape(str)}" /></span>)
end
else
%Q(<span class="equation">#{escape(str)}</span>)
end
Expand Down Expand Up @@ -1192,7 +1202,19 @@ def olnum(num)
@ol_num = num.to_i
end

def defer_math_image(str, path, key)
# for Re:VIEW >3
File.open(File.join(File.dirname(path), '__IMGMATH_BODY__.tex'), 'a+') do |f|
f.puts str
f.puts '\\clearpage'
end
File.open(File.join(File.dirname(path), '__IMGMATH_BODY__.map'), 'a+') do |f|
f.puts key
end
end

def make_math_image(str, path, fontsize = 12)
# Re:VIEW 2 compatibility
fontsize2 = (fontsize * 1.2).round.to_i
texsrc = <<-EOB
\\documentclass[12pt]{article}
Expand Down
7 changes: 7 additions & 0 deletions lib/review/webmaker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,17 @@ def generate_html_files(yamlfile)
copy_resources(@config['fontdir'], "#{@path}/fonts", @config['font_ext'])
end

def clean_mathdir
if @config['imgmath'] && File.exist?("#{@config['imagedir']}/_review_math")
FileUtils.rm_rf("#{@config['imagedir']}/_review_math")
end
end

def build_body(basetmpdir, _yamlfile)
base_path = Pathname.new(@basedir)
builder = ReVIEW::HTMLBuilder.new
@converter = ReVIEW::Converter.new(@book, builder)
clean_mathdir
@book.parts.each do |part|
if part.name.present?
if part.file?
Expand Down
4 changes: 3 additions & 1 deletion test/test_htmlbuilder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1080,7 +1080,7 @@ def test_texequation
FileUtils.mkdir_p(File.join(dir, 'images'))
expected = <<-EOB
<div class=\"equation\">
<img src=\"././images/_review_math/_gen_XXX.png\" />
<img src=\"images/_review_math/_gen_XXX.png\" alt="p \\land \\bm{P} q" />
</div>
EOB
tmpio = $stderr
Expand All @@ -1096,12 +1096,14 @@ def test_texequation
end

def test_texequation_fail
# Re:VIEW 3 never fail on defer mode. This test is only for Re:VIEW 2.
return true if /mswin|mingw|cygwin/ =~ RUBY_PLATFORM
return true unless system('latex -version 1>/dev/null 2>/dev/null')
mktmpbookdir('catalog.yml' => "CHAPS:\n - ch01.re\n",
'ch01.re' => "= test\n\n//texequation{\np \\land \\bm{P}} q\n//}\n") do |dir, book, _files|
@book = book
@book.config = @config
@config['review_version'] = 2
@config['imgmath'] = true
@chapter = Book::Chapter.new(@book, 1, '-', nil, StringIO.new)
location = Location.new(nil, nil)
Expand Down

0 comments on commit 084a186

Please sign in to comment.