class DYI::Formatter::SvgReader

@since 0.0.0

Public Class Methods

read(file_name) click to toggle source
# File lib/dyi/formatter/svg_reader.rb, line 30
def read(file_name)
  doc = REXML::Document.new(open(file_name))
  container = DYI::Shape::ShapeGroup.new
  doc.root.elements.each do |element|
    container.child_elements.push(create_shape(element))
  end
  container
end

Private Class Methods

create_path(element) click to toggle source
# File lib/dyi/formatter/svg_reader.rb, line 72
def create_path(element)
  color = DYI::Color.new(element.attributes['fill']) if element.attributes['fill'] != 'none'
  paths = element.attributes['d'].scan(/([MmZzLlHhVvCcSsQqTtAa])\s*([+-]?(?:\d+\.?\d*|\.\d+)(?:\s*,?\s*[+-]?(?:\d+\.?\d*|\.\d+))*)?/)
  enumerator = paths.each
  path_element = enumerator.next
  if path_element.first.upcase == 'M'
    lengths = path_element[1].scan(/[+-]?(?:\d+\.?\d*|\.\d+)/).map{|n| DYI::Length.new(n)}
    return if lengths.count % 2 == 1
    points = lengths.each_slice(2).map{|x, y| DYI::Coordinate.new(x, y)}
    path_data = DYI::Shape::Path::PathData.new(*points)
    loop do
      path_element = enumerator.next
      case path_element.first
      when 'M', 'm', 'L', 'l', 'C', 'c', 'S', 's', 'Q', 'q', 'T', 't'
        lengths = path_element[1].scan(/[+-]?(?:\d+\.?\d*|\.\d+)/).map{|n| DYI::Length.new(n)}
        return unless lengths.size % 2 == 0
        command_type = case path_element.first
                         when 'M' then :move_to
                         when 'm' then :rmove_to
                         when 'L' then :line_to
                         when 'l' then :rline_to
                         when 'C' then :curve_to
                         when 'c' then :rcurve_to
                         when 'S' then :shorthand_curve_to
                         when 's' then :rshorthand_curve_to
                         when 'Q' then :quadratic_curve_to
                         when 'q' then :rquadratic_curve_to
                         when 'T' then :shorthand_quadratic_curve_to
                         when 't' then :rshorthand_quadratic_curve_to
                       end
        points = lengths.each_slice(2).map{|x, y| DYI::Coordinate.new(x, y)}
        path_data.push_command(command_type, *points)
      when 'Z', 'z'
        path_data.push_command(:close_path, *lengths)
      when 'H', 'h', 'V', 'v'
        lengths = path_element[1].scan(/[+-]?(?:\d+\.?\d*|\.\d+)/).map{|n| DYI::Length.new(n)}
        command_type = case path_element.first
                         when 'H' then :horizontal_lineto_to
                         when 'h' then :rhorizontal_lineto_to
                         when 'V' then :vertical_lineto_to
                         when 'v' then :rvertical_lineto_to
                       end
        path_data.push_command(command_type, *lengths)
      when 'A', 'a'
        params = []
        enumerator = path_element[1].scan(/[+-]?(?:\d+\.?\d*|\.\d+)/).each
        return unless enumerator.count % 7 == 0
        loop do
          rx = enumerator.next
          ry = enumerator.next
          rotation = enumerator.next
          is_large_arc = enumerator.next
          is_clockwise = enumerator.next
          cx = enumerator.next
          cy = enumerator.next
          params << DYI::Length.new(rx) << DYI::Length.new(ry)
          params << rotation.to_f
          [is_large_arc, is_clockwise].each do |flg|
            case flg
              when '0' then params << false
              when '1' then params << true
              else return
            end
          end
          params << Coordinate.new(cx, cy)
        end
        path_data.push_command(path_element.first == 'A' ? :arc_to : :rarc_to, *params)
      end
    end
  end
  DYI::Shape::Path.new(path_data, :painting => {:fill => color})
end
create_polygon(element) click to toggle source
# File lib/dyi/formatter/svg_reader.rb, line 58
def create_polygon(element)
  color = DYI::Color.new(element.attributes['fill']) if element.attributes['fill'] != 'none'
  points = element.attributes['points'].split(/\s+/).map {|pt| pt.scan(/-?[\.0-9]+/).map {|s| s.to_f}}
  path = nil
  points.each do |pt|
    if path
      path.line_to(pt)
    else
      path = DYI::Shape::Polygon.new(pt, :painting => {:fill => color})
    end
  end
  path
end
create_shape(element) click to toggle source
# File lib/dyi/formatter/svg_reader.rb, line 41
def create_shape(element)
  case element.name
    when 'g' then create_shape_group(element)
    when 'polygon' then create_polygon(element)
    when 'path' then create_path(element)
  end
end
create_shape_group(element) click to toggle source
# File lib/dyi/formatter/svg_reader.rb, line 49
def create_shape_group(element)
  group = DYI::Shape::ShapeGroup.new
  element.elements.each do |child|
    child_element = create_shape(child)
    group.child_elements.push(child_element) if child_element
  end
  group
end