require 'rubygems' require 'nokogiri' require 'pp' anim_name = 'vaxgen' ## Make base document structure be the axes_boxes class OriginalDoc attr_reader :doc, :unique_clip_paths, :unique_symbols, :surface, :svg def initialize(doc) @doc = doc @unique_clip_paths = {} @uclip_id = 1 @unique_symbols = {} @usymbol_id=0 normalize_self @surface = doc.xpath('//xmlns:g[@id = "surface0"]')[0] @svg = doc.xpath('/xmlns:svg')[0] self end def normalize_self clip_path_map = {} @doc.xpath('/xmlns:svg/xmlns:defs/xmlns:clipPath').each do |clip_path| clip_id = clip_path.attribute("id").value clip_str = clip_path.children.to_s uid, junk = unique_clip_paths.detect{ |id, path| path == clip_str } if uid.nil? new_clip_id = "clip#{@uclip_id}" @uclip_id += 1 unique_clip_paths[new_clip_id] = clip_str clip_path_map[clip_id] = new_clip_id clip_path['id'] = new_clip_id else clip_path_map[clip_id] = uid clip_path.unlink end end @doc.xpath('//xmlns:g/@clip-path').each do |node| node.value =~ /^url\(#(.+)\)$/ node.value = "url(##{clip_path_map[$1]})" end symbol_map = {} @doc.child.xpath('/xmlns:svg/xmlns:defs/xmlns:g/xmlns:symbol').each do |symbol| comp_sym = symbol.dup symbol_id = comp_sym.remove_attribute('id').value comp_str = comp_sym.to_s uid,junk = unique_symbols.detect{ |id, str| comp_str == str} if uid.nil? new_symbol_id = "glyph#{@usymbol_id}" @usymbol_id += 1 unique_symbols[new_symbol_id] = comp_str symbol_map[symbol_id] = new_symbol_id symbol['id'] = new_symbol_id else symbol_map[symbol_id] = uid symbol.unlink end end @doc.xpath('//xmlns:use').each do |node| if(node['href'] =~ /^#(glyph\d+-\d+)$/) node['xlink:href'] = "##{symbol_map[$1]}" end end end def normalize_refs!(new_doc) ## read clipPaths clip_path_map = {} new_doc.xpath('/xmlns:svg/xmlns:defs/xmlns:clipPath').each do |clip_path| clip_id = clip_path.attribute("id").value clip_str = clip_path.children.to_s uid, junk = unique_clip_paths.detect{ |id, path| path == clip_str } if uid.nil? new_clip_id = "clip#{@uclip_id}" @uclip_id += 1 unique_clip_paths[new_clip_id] = clip_str clip_path_map[clip_id] = new_clip_id clip_path['id'] = new_clip_id clip_path.unlink @doc.xpath('/xmlns:svg/xmlns:defs')[0].add_child(clip_path) else clip_path_map[clip_id] = uid end end new_doc.xpath('//xmlns:g/@clip-path').each do |node| node.value =~ /^url\(#(.+)\)$/ node.value = "url(##{clip_path_map[$1]})" end symbol_map = {} new_doc.child.xpath('/xmlns:svg/xmlns:defs/xmlns:g/xmlns:symbol').each do |symbol| comp_sym = symbol.dup symbol_id = comp_sym.remove_attribute('id').value comp_str = comp_sym.to_s uid,junk = unique_symbols.detect{ |id, str| comp_str == str} if uid.nil? new_symbol_id = "glyph#{@usymbol_id}" @usymbol_id += 1 unique_symbols[new_symbol_id] = comp_str symbol_map[symbol_id] = new_symbol_id symbol['id'] = new_symbol_id symbol.unlink @doc.child.xpath('/xmlns:svg/xmlns:defs/xmlns:g')[0].add_child(symbol) else symbol_map[symbol_id] = uid end end new_doc.xpath('//xmlns:use').each do |node| if(node['href'] =~ /^#(glyph\d+-\d+)$/) node['xlink:href'] = "##{symbol_map[$1]}" end end end end axis_doc = Nokogiri::XML(File.read("#{anim_name}_axes_boxes.svg"),nil,nil,Nokogiri::XML::ParseOptions::NOBLANKS) base = axis_doc.dup base.xpath('/xmlns:svg/xmlns:defs/xmlns:clipPath | /xmlns:svg/xmlns:defs/xmlns:g/xmlns:symbol | /xmlns:svg/xmlns:g[@id = "surface0"]/xmlns:g').unlink doc = OriginalDoc.new(base) button_js = { "rewind" => "ShowFrame(-2)", "rstep" => "ShowFrame(-1)", "play" => "StartAnimation()", "pause" => "StopAnimation()", "fstep" => "ShowFrame(1)", "fforward" => "ShowFrame(2)", } anim_frames = Dir.glob("#{anim_name}_animframe*.svg").sort anim_frames.each do |anim_frame| frame_doc = Nokogiri::XML(File.read(anim_frame),nil,nil,Nokogiri::XML::ParseOptions::NOBLANKS) unless(anim_frame =~ /#{anim_name}_animframe(\d+).svg/) raise end frame_num = $1.to_i doc.normalize_refs!(frame_doc) frame = frame_doc.xpath('//xmlns:g[@id = "surface0"]')[0] frame_doc.xpath('//xmlns:g[@id = "surface0"]/xmlns:rect[1]').unlink frame['id'] = "anim_frame#{frame_num}" frame['name'] = 'anim_frame' frame['style'] ||= "" frame['style'] += "display:none;" doc.surface.add_child(frame) end doc.normalize_refs!(axis_doc) axis_doc.xpath('/xmlns:svg/xmlns:g[@id = "surface0"]/xmlns:g').each do |axes_box| doc.surface.add_child(axes_box) end ## Now load the button things %w{rewind rstep play pause fstep fforward}.each do |button_name| button_doc = Nokogiri::XML(File.read("#{anim_name}_button_#{button_name}.svg"),nil,nil,Nokogiri::XML::ParseOptions::NOBLANKS) doc.normalize_refs!(button_doc) button = button_doc.xpath('//xmlns:g[@id = "surface0"]/xmlns:g')[0] button['id'] = "#{button_name}_button" if button_name == 'pause' button['style'] ||= "" button['style'] += "display:none;" end doc.surface.add_child(button) end doc.svg['onload'] = "InitializeAnimation(evt)" anim_script =<