# File temp/Graph/Bar.rb, line 216 def gen_svg d = Document.new d << XMLDecl.new d << DocType.new( %{svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"} ) if style_sheet && style_sheet != '' d << ProcessingInstruction.new( "xml-stylesheet", %{href="#{style_sheet}" type="text/css"} ) end root = d.add_element( "svg", { "width" => width, "height" => height, "viewBox" => "0 0 #{width} #{height}", "xmlns" => "http://www.w3.org/2000/svg", "xmlns:xlink" => "http://www.w3.org/1999/xlink" }) root << Comment.new( " "+"\\"*66 ) root << Comment.new( " Created with SVG::Graph " ) root << Comment.new( " Sean Russell " ) root << Comment.new( " Based on SVG::TT::Graph for Perl by"+ " Leo Lapworth & Stephan Morgan " ) root << Comment.new( " "+"/"*66 ) if not(style_sheet && style_sheet != '') root << Comment.new(" include default stylesheet if none specified ") defs = root.add_element( "defs" ) style = defs.add_element( "style", {"type"=>"text/css"} ) style << CData.new( CSS ) end root << Comment.new( "SVG Background" ) root.add_element( "rect", { "width" => width, "height" => height, "x" => "0", "y" => "0", "class" => "svgBackground" }) # Calculate graph area and boundries x = 0 y = 0 char_width = 9 half_char_height = 2.5 min_value = 9e20 max_value = 0 max_key_size = 0 max_x_label_size = @config[:fields].max{ |a,b| a.length <=> b.length }.length for data in @data dataset = data[:data] title = data[:title] dm = dataset.min min_value = dm < min_value ? dm : min_value dm = dataset.max max_value = dm > max_value ? dm : max_value max_key_size = title.length if title.length > max_key_size end h = height w = width h -= 20 if show_x_labels max_x_label_length = 0 if rotate_x_labels max_x_label_length = max_x_label_size * char_width h -= max_x_label_length end stagger = 0 if stagger_x_labels stagger = 17 h -= stagger end h = h - 25 - stagger if show_x_title if show_y_labels h -= 10 y += 10 end if show_graph_title h -= 25 y += 25 end if show_graph_subtitle h -= 10 y += 10 end key_box_size = 12 key_padding = 5 if key && key_position == :right w = w - (max_key_size * (char_width - 1)) - (key_box_size * 3 ) elsif key && key_position == :bottom if data.size > 4 h -= (data.size + 1) * (key_box_size + key_padding) else h -= 4 * (key_box_size + key_padding) end end minvalue = min_value minvalue = min_scale_value if min_scale_value base_line = h + y temp = max_value - minvalue top_pad = temp == 0 ? 10 : temp / 20.0 scale_range = (max_value + top_pad) - minvalue scale_division = scale_divisions || (scale_range / 10.0) if scale_integers scale_division = scale_division < 1 ? 1 : scale_division.round end dx = @config[:fields].size data_widths_x = w / dx dw = data_widths_x half_label_width = @config[:fields][0].length/2 * char_width space_b4_y_axis = 0 if half_label_width > (dw / 2) space_b4_y_axis = half_label_width - (dw / 2) if key && key_position == :right w = w - space_b4_y_axis else w = w - (space_b4_y_axis * 2) end x = x + space_b4_y_axis end max_value_length = max_value.to_s.length max_value_length_px = max_value_length * char_width if show_y_labels && space_b4_y_axis < max_value_length_px if max_value_length < 2 w = w - (max_value_length * (char_width * 2)) - char_width x = x + (max_value_length * (char_width * 2)) + char_width else w = w - max_value_length_px + char_width x = x + max_value_length_px + char_width end end if show_y_title && space_b4_y_axis < max_value_length_px w = w - 25 x = x + 25 end # Background root.add_element( "rect", { "x" => x, "y" => y, "width" => w, "height" => h, "class" => "graphBackground" }) # Axis root.add_element( "path", { "d" => "M #{x} #{y} v#{h}", "class" => "axis", "id" => "xAxis" }) root.add_element( "path", { "d" => "M #{x} #{base_line} h#{w}", "class" => "axis", "id" => "yAxis" }) dx = @config[:fields].size data_widths_x = w / dx dw = (data_widths_x*100).truncate / 100.0 i = dw count = 0 if bar_gap bargap = 10 bargap = dw / 2 if dw < bargap else bargap = 0 end stagger_count = 0 if show_x_labels for field in @config[:fields] text = root.add_element( "text" ) text.attributes["class"] = "xAxisLabels" text.text = field tx = x + (dw / 2) - (bargap / 2) ty = base_line + 15 tt = x + ( dw / 2 ) - ( bargap / 2 ) - half_char_height if count == 0 i -= dw else tx += i tt += i if stagger_count == 2 stagger_count = 0 else ty += stagger root.add_element( "path", { "d" => "M#{tx} #{base_line}, v#{stagger}", "class" => "staggerGuideLine" }) end end text.attributes["x"] = tx text.attributes["y"] = ty if rotate_x_labels text.attributes["transform"] = "rotate( 90 #{tt} #{ty} )" text.attributes["style"] = "text-anchor: start" end i += dw count += 1 stagger_count += 1 end end dy = scale_range / scale_division y_marker_height = h.to_f / dy dy = y_marker_height.to_i count = 0 y_value = min_scale_value if show_y_labels while (dy * count) < h root.add_element( "text", { "x" => x - 5, "y" => base_line - (dy * count), "class" => "yAxisLabels" }).text = y_value if count != 0 root.add_element( "path", { "d" => "M#{x} #{base_line - (dy * count)} h#{w}", "class" => "guideLines" }) end y_value = y_value + scale_division count += 1 end end if show_x_title y_xtitle = show_x_labels ? 35 : 15 root.add_element( "text", { "x" => (w / 2) + x, "y" => h + y + y_xtitle + stagger + max_x_label_length, "class" => "xAxisTitle" }).text = x_title end if show_y_title text = root.add_element( "text", { "class" => "yAxisTitle" } ) text.text = y_title if y_title_text_direction == :tb text.attributes["x"] = 12 text.attributes["y"] = (h / 2) + y text.attributes["style"] = "writing-mode: tb;" else text.attributes["transform"]="translate(15, #{(h/2)+y}) rotate(270)" end end bar_width = dw - bargap divider = dy / scale_division xcount = 0 subbar_width = bar_width subbar_width /= @data.length if stack == :side @config[:fields].each_index { |i| dcount = 1 for dataset in @data # X1 p1 = (dw * xcount) + x # Y1 p2 = base_line # to Y2 p3 = base_line - (dataset[:data][i] * divider) # to X2 p4 = subbar_width case stack when :side p1 += (dcount-1) * subbar_width when :top else end root.add_element( "path", { "class" => "fill#{dcount}", "d" => "M#{p1} #{p2} V#{p3} h#{p4} V#{p2} Z" }) if show_data_values root.add_element( "text", { "x" => p1 + ((dw-bargap)/2)-(stack==:side ? subbar_width/2 : 0), "y" => p3 - 6, "class" => "dataPointLabel" } ).text = dataset[:data][i].to_s end dcount += 1 end xcount += 1 } key_count = 1 key_padding = 5 if key && key_position == :right for dataset in @data yval = y + (key_box_size * key_count) + (key_count * key_padding) root.add_element( "rect", { "x" => x + w + 20, "y" => yval, "width" => key_box_size, "height" => key_box_size, "class" => "key#{key_count}" }) root.add_element( "text", { "x" => x + w + 20 + key_box_size + key_padding, "y" => yval + key_box_size, "class" => "keyText" }).text = dataset[:title] key_count += 1 end elsif key && key_position == :bottom y_key = base_line y_key += 25 if show_x_title if rotate_x_labels && show_x_labels y_key = y_key + max_x_label_length elsif show_x_labels && stagger < 1 y_key = y_key + 20 end y_key_start = y_key x_key = x for dataset in @data if key_count == 4 || key_count == 7 || key_count == 10 x_key += 200 y_key -= (key_box_size * 4) - 2 end wh = key_box_size bs = y_key + (key_box_size * key_count) + (key_count * key_padding) + stagger cl = "key#{key_count}" root.add_element( "rect", { "x" => x_key, "y" => bs, "width" => wh, "height" => wh, "class" => cl }) root.add_element( "text", { "x" => x_key + key_box_size + key_padding, "y" => bs + key_box_size, "width" => wh, "height" => wh, "class" => cl }).text = dataset[:title] key_count += 1 end end if show_graph_title root.add_element( "text", { "x" => width / 2, "y" => "15", "class" => "mainTitle" }).text = graph_title end if show_graph_subtitle y_subtitle = show_graph_title ? 30 : 15 root.add_element("text", { "x" => width / 2, "y" => y_subtitle, "class" => "subTitle" }).text = graph_subtitle end return d end