def render
output = ""
xml = Builder::XmlMarkup.new(:target => output, :indent => @options[:indent])
xml.instruct!
xml.declare! :DOCTYPE, :svg, :PUBLIC, "-//W3C//DTD SVG 1.1//EN", "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"
xml.svg(:viewBox => "0 0 #{@options[:viewbox][:width]} #{@options[:viewbox][:height]}",
:width => @options[:width], :height => @options[:height],
:xmlns => 'http://www.w3.org/2000/svg', :version => '1.1') do |xml|
xml.g(:fill => 'black', :stroke => 'black', 'stroke-width' => '2',
'font-family' => 'Helvetica, Arial, sans-serif', 'font-size' => '10px', 'font-weight' => 'medium') do |xml|
xml.rect(:x => @options[:margin][:left], :y => @options[:margin][:top],
:width => graph_width,
:height => graph_height,
:fill => 'lightgray')
xml.g 'stroke-width' => '1' do |xml|
xml.text(@options[:title], 'font-size' => '24px', :x => (@options[:viewbox][:width] / 2.0).round, :y => (@options[:subtitle] ? 24 : 32), 'text-anchor' => 'middle') if @options[:title]
xml.text(@options[:subtitle], 'font-size' => '18px', :x => (@options[:viewbox][:width] / 2.0).round, :y => 34, 'text-anchor' => 'middle') if @options[:subtitle]
xml.g 'font-size' => '10px' do |xml|
line_x1 = @options[:margin][:left] + 1
line_x2 = @options[:viewbox][:width] - @options[:margin][:right] - 1
text_x = @options[:margin][:left] - 25
xml.text 0, :x => text_x, :y => (@options[:viewbox][:height] - @options[:margin][:bottom] + 4), 'stroke-width' => 0.5
1.upto((max / 10) - 1) do |line_number|
y = (@options[:margin][:top] + (line_number * dy)).round
xml.line :x1 => line_x1, :y1 => y, :x2 => line_x2, :y2 => y, :stroke => '#666666'
xml.text max - line_number * 10, :x => text_x, :y => y + 4, 'stroke-width' => 0.5
xml.line(:x1 => line_x1, :y1 => y + (0.5 * dy), :x2 => line_x2, :y2 => y + (0.5 * dy), :stroke => '#999999') if max < 55
end
xml.text max, :x => text_x, :y => @options[:margin][:top] + 4, 'stroke-width' => 0.5
xml.line(:x1 => line_x1, :y1 => @options[:margin][:top] + (0.5 * dy), :x2 => line_x2, :y2 => @options[:margin][:top] + (0.5 * dy), :stroke => '#999999') if max < 55
end
xml.g 'text-anchor' => 'end', 'font-size' => '12px', 'stroke-width' => 0.3 do |xml|
@labels.each_with_index do |label, index|
x = (@options[:margin][:left] + (dx * index) + (dx / 2.0)).round
y = @options[:viewbox][:height] - @options[:margin][:bottom] + 15
xml.text label, :x => x, :y => y, :transform => "rotate(-45 #{x} #{y})"
end
end
xml.g 'font-size' => '8px', 'stroke-width' => 0.3 do |xml|
@data.each_with_index do |data, data_index|
data = Array(data)
width = dx - @options[:padding]
bar_width = (width / Float(data.size)).round
x = (@options[:margin][:left] + (dx * data_index)).round
data.each_with_index do |number, number_index|
color = if @colors.respond_to? :call
@colors.call(data_index, number_index, @data.size, data.size)
elsif @colors.class == Array
first = @colors[data_index % (@colors.size)]
if first.class == Array
first[number_index % (first.size)]
else
first
end
else
@colors
end
height = ((dy / 10.0) * number).round
bar_x = (x + ((dx - width) / 2.0) + (number_index * bar_width)).round
bar_y = @options[:viewbox][:height] - @options[:margin][:bottom] - height
xml.rect :fill => color, :stroke => color, 'stroke-width' => 0, :x => bar_x, :width => bar_width, :y => bar_y, :height => height - 1
end
if @options[:bar_text]
data.each_with_index do |number, number_index|
height = ((dy / 10.0) * number).round
bar_x = (x + ((dx - width) / 2.0) + (number_index * bar_width)).round
text_x = (bar_x + (bar_width / 2.0)).round
bar_y = @options[:viewbox][:height] - @options[:margin][:bottom] - height
text_y = bar_y - 3
xml.text number, :x => text_x, :y => text_y, 'text-anchor' => 'middle'
end
end
end
end
if @legend
legend_x = @options[:viewbox][:width] - (3 * @options[:margin][:right])
legend_y = @options[:margin][:top] / 2
xml.rect :fill => '#ffffff', :stroke => '#000000', 'stroke-width' => 2, :x => legend_x, :y => legend_y, :width => (2.5 * @options[:margin][:right]), :height => (@legend.size * 15) + 16
@legend.sort.each_with_index do |data, index|
color, label = data
xml.rect :fill => color, :stroke => color, 'stroke-width' => 0, :x => legend_x + 10, :y => legend_y + 10 + (index * 15), :width => 35, :height => 10
xml.text label, :x => legend_x + 70, :y => legend_y + 18 + (index * 15), 'text-anchor' => 'left'
end
end
yield(xml, @options) if block_given?
end
end
end
output
end