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 +7 -0
- data/README.md +26 -0
- data/lib/svg_pathify/shape.rb +55 -0
- data/lib/svg_pathify/shapes/circle.rb +22 -0
- data/lib/svg_pathify/shapes/ellipse.rb +20 -0
- data/lib/svg_pathify/shapes/line.rb +21 -0
- data/lib/svg_pathify/shapes/polygon.rb +31 -0
- data/lib/svg_pathify/shapes/rect.rb +16 -0
- data/lib/svg_pathify/to_short_f.rb +12 -0
- data/lib/svg_pathify.rb +53 -0
- data/test/svg_pathify_test.rb +94 -0
- metadata +53 -0
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
|
data/lib/svg_pathify.rb
ADDED
@@ -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: []
|