| Class | Webgen::Tag::TikZ |
| In: |
lib/webgen/tag/tikz.rb
|
| Parent: | Object |
This tag allows the creation and inclusion of complex graphics using the PGF/TikZ library of LaTeX. You will need a current LaTeX distribution and the convert utility from ImageMagick.
| LATEX_TEMPLATE | = | <<EOF \\nonstopmode \\documentclass{article} \\usepackage{tikz} \\pagestyle{empty} <% if param('tag.tikz.libraries') %> \\usetikzlibrary{<%= param('tag.tikz.libraries').join(',') %>} <% end %> \\begin{document} <% if param('tag.tikz.opts') %> \\begin{tikzpicture}[<%= param('tag.tikz.opts') %>] <% else %> \\begin{tikzpicture} <% end %> <%= body %> \\end{tikzpicture} \\end{document} EOF |
Create a graphic from the commands in the body of the tag.
# File lib/webgen/tag/tikz.rb, line 34
34: def call(tag, body, context)
35: path = param('tag.tikz.path')
36: path = Webgen::Path.make_absolute(context.ref_node.parent.alcn, path)
37:
38: mem_handler = website.cache.instance('Webgen::SourceHandler::Memory')
39: src_path = context.ref_node.node_info[:src]
40: parent = website.blackboard.invoke(:create_directories, context.ref_node.tree.root, File.dirname(path), src_path)
41: params = @params
42:
43: node = website.blackboard.invoke(:create_nodes, Webgen::Path.new(path, src_path), mem_handler) do |node_path|
44: mem_handler.create_node(node_path, context.ref_node.alcn) do |pic_node|
45: set_params(params)
46: document = ERB.new(LATEX_TEMPLATE).result(binding)
47: pic_path = compile(document, File.extname(path), context)
48: set_params(nil)
49: if pic_path
50: io = Webgen::Path::SourceIO.new { File.open(pic_path, 'rb') }
51: else
52: pic_node.flag(:dirty)
53: nil
54: end
55: end
56: end.first
57: attrs = {'alt' => ''}.merge(param('tag.tikz.img_attr')).collect {|name,value| "#{name.to_s}=\"#{value}\"" }.sort.unshift('').join(' ')
58: "<img src=\"#{context.dest_node.route_to(node)}\"#{attrs} />"
59: end
Compile the LaTeX document and convert the resulting PDF to the correct output image format specified by ext (the extension needs to include the dot).
# File lib/webgen/tag/tikz.rb, line 67
67: def compile(document, ext, context)
68: file = Tempfile.new('webgen-tikz')
69: file.write(document)
70: file.close
71:
72: FileUtils.mv(file.path, file.path + '.tex')
73: cmd_prefix = "cd #{File.dirname(file.path)}; "
74: output = `#{cmd_prefix} pdflatex --shell-escape -interaction=batchmode #{File.basename(file.path)}.tex`
75: if $?.exitstatus != 0
76: errors = output.scan(/^!(.*\n.*)/).join("\n")
77: raise Webgen::RenderError.new("Error while creating a TikZ picture: #{errors}",
78: self.class.name, context.dest_node, context.ref_node)
79: else
80: cmd = cmd_prefix + "pdfcrop #{File.basename(file.path)}.pdf #{File.basename(file.path)}.pdf; "
81: return unless run_command(cmd, context)
82:
83: render_res, output_res = param('tag.tikz.resolution').split(' ')
84: if param('tag.tikz.transparent') && ext =~ /\.png/i
85: cmd = cmd_prefix +
86: "gs -dSAFER -dBATCH -dNOPAUSE -r#{render_res} -sDEVICE=pngalpha -dGraphicsAlphaBits=4 -dTextAlphaBits=4 " +
87: "-sOutputFile=#{File.basename(file.path)}#{ext} #{File.basename(file.path)}.pdf"
88: else
89: cmd = cmd_prefix + "convert -density #{render_res} #{File.basename(file.path)}.pdf #{File.basename(file.path)}#{ext}"
90: end
91: return unless run_command(cmd, context)
92:
93: if render_res != output_res
94: cmd = cmd_prefix + "identify #{File.basename(file.path)}#{ext}"
95: return unless (output = run_command(cmd, context))
96: width, height = output.scan(/\s\d+x\d+\s/).first.strip.split('x').collect {|s| s.to_f * output_res.to_f / render_res.to_f }
97: cmd = cmd_prefix + "convert -resize #{width}x#{height} #{File.basename(file.path)}#{ext} #{File.basename(file.path)}#{ext}"
98: return unless run_command(cmd, context)
99: end
100: file.path + ext
101: end
102: end
Runs the command cmd and returns it‘s output if successful or nil otherwise.
# File lib/webgen/tag/tikz.rb, line 105
105: def run_command(cmd, context)
106: output = `#{cmd}`
107: if $?.exitstatus != 0
108: raise Webgen::RenderError.new("Error while running a command for a TikZ picture: #{output}",
109: self.class.name, context.dest_node, context.ref_node)
110: else
111: output
112: end
113: end