# File lib/lilygraph.rb, line 110
  def render
    output = ""
    xml = Builder::XmlMarkup.new(:target => output, :indent => @options[:indent])

    # Output headers unless we specified otherwise
    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|

        # Outline
        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|

          # Title
          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]

          # Lines
          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

              # Smaller Line
              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
            # Smaller Line
            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

          # Labels
          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

          # Bars
          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

              # Rectangles
              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

              # Text
              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

          # Legend
          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 in case they want to do some custom drawing and have a block ready
          yield(xml, @options) if block_given?

        end
      end
    end

    output
  end