svg_pathify 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []