svg_pathify 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3b85d9b461f4ce5d4cd3653458bee1c601ee1791
4
+ data.tar.gz: 05ec30b4bbb13c0546b9e13e2375db1c5fc96b15
5
+ SHA512:
6
+ metadata.gz: 4c58f24294519ad59fcbf51e72cf2a86913d5e330349163dc4dbcd087082330462f12343256697f888cd368d97dbbbd15a0199b2026a83e30dee485c33f2e233
7
+ data.tar.gz: 367deaf9db8dc2cec4d183d54f199d1631264324f91c483d88472fa34a63cffb0d77aa8fd0e0e93d6b458acad1e1991efecd9f033fdc907b56690ec9ea122dd4
data/README.md ADDED
@@ -0,0 +1,26 @@
1
+ **svg_pathify** turns svg [basic shapes](http://www.w3.org/TR/SVG/shapes.html) into path svg elements.
2
+
3
+ ## install
4
+
5
+ ~~~
6
+ gem install svg_pathify
7
+ ~~~
8
+
9
+ or in your Gemfile:
10
+
11
+ ~~~
12
+ gem 'svg_pathify'
13
+ ~~~
14
+
15
+ ## usage
16
+
17
+
18
+ ~~~ruby
19
+ input = %Q{<polyline points="350,75 379,161 469,161 397,215
20
+ 423,301 350,250 277,301 303,215
21
+ 231,161 321,161" />}
22
+
23
+ output = SvgPathify.convert( input )
24
+ #=> '<path d="M350,75L379,161L469,161L397,215L423,301L350,250L277,301L303,215L231,161L321,161Z" />'
25
+ ~~~
26
+
@@ -0,0 +1,55 @@
1
+ module SvgPathify
2
+
3
+ class Shape
4
+
5
+ attr_accessor :node, :path, :special_attrs
6
+
7
+ def initialize( node )
8
+ @node = node
9
+ special_attrs && special_attrs.each do |attr|
10
+ self.send "#{attr}=", node[attr]
11
+ end
12
+ end
13
+
14
+ def to_path_element
15
+ node.document.create_element 'path', clean_attributes.merge( d: path_commands )
16
+ end
17
+
18
+ def path_commands
19
+ nil
20
+ end
21
+
22
+ def clean_attributes
23
+ node.attributes.reject {|k,v| attributes_to_delete.include?(k) }
24
+ end
25
+
26
+ def attributes_to_delete
27
+ []
28
+ end
29
+
30
+ def self.inherited( clz )
31
+ def clz.special_attr( *attrs )
32
+ class_eval do
33
+ attr_accessor *attrs
34
+
35
+ define_method :attributes_to_delete do
36
+ attrs.map &:to_s
37
+ end
38
+
39
+ define_method :special_attrs do
40
+ attrs
41
+ end
42
+
43
+ attrs.each do |the_attr|
44
+ define_method the_attr do
45
+ instance_variable_get( "@#{the_attr}" ).to_short_f
46
+ end
47
+ end
48
+
49
+ end
50
+ end
51
+ end
52
+
53
+ end
54
+
55
+ end
@@ -0,0 +1,22 @@
1
+ module SvgPathify
2
+
3
+ module Shapes
4
+
5
+ class Circle < ::SvgPathify::Shape
6
+
7
+ special_attr :cx, :cy, :r
8
+
9
+ def path_commands
10
+ [
11
+ "M#{cx} #{cy}",
12
+ "m#{-r} 0",
13
+ "a#{r},#{r} 0 1,0 #{r * 2},0",
14
+ "a#{r},#{r} 0 1,0 -#{r * 2},0",
15
+ "Z"
16
+ ].join
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,20 @@
1
+ module SvgPathify
2
+
3
+ module Shapes
4
+
5
+ class Ellipse < ::SvgPathify::Shape
6
+
7
+ special_attr :cx, :cy, :rx, :ry
8
+
9
+ def path_commands
10
+ [
11
+ "M#{cx-rx} #{cy}",
12
+ "a#{rx},#{ry},0,1,1,#{cx-rx},#{cy+1}",
13
+ "Z"
14
+ ].join
15
+ end
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,21 @@
1
+ module SvgPathify
2
+
3
+ module Shapes
4
+
5
+ class Line < ::SvgPathify::Shape
6
+
7
+ special_attr :x1, :y1, :x2, :y2
8
+
9
+ def path_commands
10
+ [
11
+ "M#{x1} #{y1}",
12
+ "L#{x2} #{y2}",
13
+ "L#{x1} #{y1}",
14
+ "Z"
15
+ ].join
16
+ end
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,31 @@
1
+ module SvgPathify
2
+
3
+ module Shapes
4
+
5
+ # Example:
6
+ # <polygon fill="#ED1C24" points="68.793,3.148 51.865,19 86.795,19 "/>
7
+ class Polygon < ::SvgPathify::Shape
8
+
9
+ def path_commands
10
+ pts = node['points'].split.map {|pos| pos.split(',').map(&:to_short_f) }
11
+
12
+ paths = []
13
+ pts.each_with_index do |dot, i|
14
+ if i.zero?
15
+ paths << "M#{dot.join ?,}"
16
+ else
17
+ paths << "L#{dot.join ?,}"
18
+ end
19
+ end
20
+ paths << "Z"
21
+ paths.join
22
+ end
23
+
24
+ def attributes_to_delete
25
+ "points"
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,16 @@
1
+ module SvgPathify
2
+
3
+ module Shapes
4
+
5
+ class Rect < ::SvgPathify::Shape
6
+
7
+ special_attr :width, :height
8
+
9
+ def path_commands
10
+ "M0 0l#{width} 0l0 #{height}l#{-width} 0l0 #{-height}Z"
11
+ end
12
+
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ unless Object.instance_methods.include? :to_short_f
2
+ class ::Object
3
+
4
+ def to_short_f( precision=4 )
5
+ factor = 10 ** precision
6
+ rnd = (to_f * factor).round.to_f / factor
7
+ f, i = rnd, rnd.to_i
8
+ f == i ? i : f
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,53 @@
1
+ require 'nokogiri'
2
+ require_relative 'svg_pathify/to_short_f'
3
+ require_relative 'svg_pathify/shape'
4
+
5
+ Dir.glob( File.expand_path( "svg_pathify/shapes/*.rb", File.dirname(__FILE__) ) ) do |shape|
6
+ require shape
7
+ end
8
+
9
+ module SvgPathify
10
+
11
+ class << self
12
+ def convert svg_xml
13
+ Converter.new(svg_xml).output
14
+ end
15
+ end
16
+
17
+ class Converter
18
+
19
+ attr_reader :input
20
+
21
+ def initialize( svg )
22
+ @xml = Nokogiri::XML( svg, &:noblanks )
23
+ @converted_root = convert_node @xml.root
24
+ end
25
+
26
+ def output
27
+ @converted_root.to_s
28
+ end
29
+
30
+ protected
31
+
32
+
33
+ CONVERTING_MAP = {
34
+ :rect => ::SvgPathify::Shapes::Rect,
35
+ :circle => ::SvgPathify::Shapes::Circle,
36
+ :polygon => ::SvgPathify::Shapes::Polygon,
37
+ :polyline => ::SvgPathify::Shapes::Polygon,
38
+ :line => ::SvgPathify::Shapes::Line,
39
+ :ellipse => ::SvgPathify::Shapes::Ellipse
40
+ }
41
+
42
+ def convert_node( node )
43
+ return node if node.text?
44
+
45
+ type = CONVERTING_MAP[node.name.to_sym]
46
+ return node if type.nil?
47
+
48
+ type.new( node ).to_path_element
49
+ end
50
+
51
+ end
52
+
53
+ end
@@ -0,0 +1,94 @@
1
+ require 'test/unit'
2
+ $: << File.expand_path( '../lib/', File.basename(__FILE__) )
3
+
4
+ require 'svg_pathify'
5
+
6
+ class SvgPathifyTest < Test::Unit::TestCase
7
+
8
+ def test_nothing_changed_if_no_shape_available
9
+ input = %Q{<path d="M93.992 83.676m-67.244 0a67.244,67.244 0 1,0 134.488,0a67.244,67.244 0 1,0 -134.488,0Z" />}
10
+
11
+ assert_xml_equal input, SvgPathify.convert( input )
12
+ end
13
+
14
+ def test_rect_changes_to_path_tag
15
+ input = %Q{<rect x="100" y="300" width="50" height="200" />}
16
+ output = %Q{<path x="100" y="300" d="M0 0l50 0l0 200l-50 0l0 -200Z" />}
17
+
18
+ assert_xml_equal output, SvgPathify.convert( input )
19
+ end
20
+
21
+ def test_circle_changes_to_path_tag
22
+ input = %Q{<circle x="100" y="300" r="50" cx="100" cy="200" />}
23
+ output = %Q{<path x="100" y="300" d="M100 200m-50 0a50,50 0 1,0 100,0a50,50 0 1,0 -100,0Z" />}
24
+
25
+ assert_xml_equal output, SvgPathify.convert( input )
26
+ end
27
+
28
+ def test_polygon_changes_to_path_tag
29
+ input = %Q{<polygon points="350,75 379,161 469,161 397,215
30
+ 423,301 350,250 277,301 303,215
31
+ 231,161 321,161" />}
32
+ output = %Q{<path d="M350,75L379,161L469,161L397,215L423,301L350,250L277,301L303,215L231,161L321,161Z" />}
33
+
34
+ assert_xml_equal output, SvgPathify.convert( input )
35
+ end
36
+
37
+ def test_polyline_changes_to_path_tag
38
+ input = %Q{<polyline points="350,75 379,161 469,161 397,215
39
+ 423,301 350,250 277,301 303,215
40
+ 231,161 321,161" />}
41
+ output = %Q{<path d="M350,75L379,161L469,161L397,215L423,301L350,250L277,301L303,215L231,161L321,161Z" />}
42
+
43
+ assert_xml_equal output, SvgPathify.convert( input )
44
+ end
45
+
46
+ def test_line_changes_to_path_tag
47
+ input = %Q{<line x1="900" y1="300" x2="1100" y2="100" stroke-width="25" />}
48
+ output = %Q{<path d="M900 300L1100 100L900 300Z" stroke-width="25" />}
49
+
50
+ assert_xml_equal output, SvgPathify.convert( input )
51
+ end
52
+
53
+ def test_ellipse_changes_to_path_tag
54
+ input = %Q{<ellipse
55
+ rx="250" ry="100"
56
+ fill="none" stroke="blue" stroke-width="20" />}
57
+ output = %Q{<path d="M-250 0a250,100,0,1,1,-250,1Z"
58
+ stroke-width="20"
59
+ fill="none"
60
+ stroke="blue" />}
61
+
62
+ assert_xml_equal output, SvgPathify.convert( input )
63
+ end
64
+
65
+ #-----> helper
66
+
67
+ def assert_xml_equal( expect, other, msg=nil )
68
+ assert_equal Nokogiri.parse( expect ).root, Nokogiri.parse( other ).root
69
+ end
70
+
71
+ end
72
+
73
+ class Nokogiri::XML::Node
74
+ # Return true if this node is content-equivalent to other, false otherwise
75
+ def == (other)
76
+ return true if self.object_id == other.object_id
77
+ return false if other.nil?
78
+ return false unless name == other.name
79
+ stype = node_type; otype = other.node_type
80
+ return false unless stype == otype
81
+ sa = attributes; oa = other.attributes
82
+ return false unless sa.length == oa.length
83
+ sa = sa.sort.map{ |n,a| [n,a.value,a.namespace && a.namespace.href] }
84
+ oa = oa.sort.map{ |n,a| [n,a.value,a.namespace && a.namespace.href] }
85
+ return false unless sa == oa
86
+ skids = children; okids = other.children
87
+ return false unless skids.length == okids.length
88
+ return false if stype == TEXT_NODE && (content != other.content)
89
+ sns = namespace; ons = other.namespace
90
+ return false if !sns ^ !ons
91
+ return false if sns && (sns.href != ons.href)
92
+ skids.to_enum.with_index.all?{ |ski,i| ski =~ okids[i] }
93
+ end
94
+ end
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: svg_pathify
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - qhwa
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-11-12 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email: qhwa@163.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - README.md
20
+ - lib/svg_pathify.rb
21
+ - lib/svg_pathify/to_short_f.rb
22
+ - lib/svg_pathify/shapes/rect.rb
23
+ - lib/svg_pathify/shapes/polygon.rb
24
+ - lib/svg_pathify/shapes/line.rb
25
+ - lib/svg_pathify/shapes/circle.rb
26
+ - lib/svg_pathify/shapes/ellipse.rb
27
+ - lib/svg_pathify/shape.rb
28
+ - test/svg_pathify_test.rb
29
+ homepage: https://github.com/qhwa/svg_pathify
30
+ licenses:
31
+ - MIT
32
+ metadata: {}
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ requirements: []
48
+ rubyforge_project:
49
+ rubygems_version: 2.0.3
50
+ signing_key:
51
+ specification_version: 4
52
+ summary: turn svg shape tags into <path> tag.
53
+ test_files: []