vector_be_winding 0.9.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: 8d63331bdde70ece16ad946c86b40d16651ff6e3
4
+ data.tar.gz: 757ea390d934c45d3dfb2461d05182955bfafaf3
5
+ SHA512:
6
+ metadata.gz: 349d180848c2a3a0cda2fdab934c4cf6bacd599c629fcafaaa66e74073b2f8e9cce6553cca95df1fc78d3e15abad77ada9647450724ceab32dffae7c56a8194a
7
+ data.tar.gz: 02deb594f43de821830d565aa5c5db4d4ac9bae726b6d8b9875624f0f5febaab80f0eaa2c0a5b77708276693f932e90882985bc4553ce566774f3f1382c4780f
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.3
5
+ before_install: gem install bundler -v 1.13.7
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in vector_be_winding.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,37 @@
1
+ # VectorBeWinding ![Travis](https://travis-ci.org/dagezi/vector_be_winding.svg?branch=master)
2
+
3
+ Android Vector Drawable is very combinent, but sometimes it missing holes in the shape generated by some tools. `vector_be_winding` will massage such Vector Drawalbes so that the shape will be rendered as expectd!
4
+
5
+ ## Example
6
+
7
+ TODO: Describe some pipeline which might generate "wrong" Vector Drawable.
8
+
9
+ 1. Skecth + vdtool
10
+
11
+ TODO: Describe why it happens and how this tool resolve it.
12
+
13
+ ## Installation
14
+
15
+ just with Gem.
16
+
17
+
18
+ ## Usage
19
+
20
+ TODO: Write usage instructions here
21
+
22
+ ## Development
23
+
24
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
25
+
26
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
27
+
28
+ ## Contributing
29
+
30
+ Bug reports and pull requests are welcome on GitHub at https://github.com/dagezi/vector_be_winding.
31
+
32
+ ## Lisense
33
+
34
+ MIT License.
35
+
36
+
37
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/exe/vbw ADDED
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env ruby
2
+ require 'optparse'
3
+ require 'vector_be_winding'
4
+
5
+ opt = OptionParser.new
6
+
7
+ @dry_run = false
8
+ @verbose = false
9
+ @debug = false
10
+ @backup_template = '%{p}.bak'
11
+
12
+ opt.on('-n', 'Dry run') { @dry_run = true }
13
+ opt.on('-v', 'Verbose') { @verbose = true }
14
+ opt.on('-d', 'Debug') { @debug = true }
15
+ opt.on('-i TEMP', 'Template of back-up filename. Default; ".bak"') { |temp|
16
+ @backup_template = if temp.index('%')
17
+ temp
18
+ else
19
+ '%{p}' + temp
20
+ end
21
+ }
22
+
23
+ opt.parse!(ARGV)
24
+
25
+ ARGV.each { |file|
26
+ drawable = VectorBeWinding::Drawable.new
27
+ drawable.read_from_file(file)
28
+ if !drawable.is_winding
29
+ print "Not winding: #{file}\n" if @verbose
30
+ drawable.dump if @debug
31
+
32
+ if !@dry_run
33
+ args = {
34
+ d: File.dirname(file),
35
+ p: file,
36
+ r: File.basename(file, File.extname(file)),
37
+ e: File.extname(file)
38
+ }
39
+
40
+ File.rename(file, @backup_template % args)
41
+ drawable.be_winding
42
+ drawable.dump if @debug
43
+ drawable.write_to_file(file)
44
+ end
45
+ end
46
+ }
@@ -0,0 +1,61 @@
1
+ require "rexml/document"
2
+
3
+ module VectorBeWinding
4
+ class Drawable
5
+ # A class to handle Android's vector drawable
6
+
7
+ def read_from_file(filename)
8
+ open(filename) { |inio|
9
+ read(inio)
10
+ }
11
+ end
12
+
13
+ def read(inio)
14
+ @document = REXML::Document.new inio
15
+ end
16
+
17
+ def write_to_file(filename)
18
+ open(filename, 'w') {|outio|
19
+ write(outio)
20
+ }
21
+ end
22
+
23
+ def write(outio)
24
+ @document.write outio
25
+ end
26
+
27
+ def be_winding
28
+ @document.each_recursive {|node|
29
+ if node.name == 'path'
30
+ pathString = node.attributes['android:pathData']
31
+ path = Path.with_string(pathString)
32
+ newPath = path.be_winding
33
+
34
+ node.add_attribute('android:pathData', newPath.to_command)
35
+ end
36
+ }
37
+ end
38
+
39
+ def is_winding
40
+ @document.each_recursive {|node|
41
+ if node.name == 'path'
42
+ pathString = node.attributes['android:pathData']
43
+ path = Path.with_string(pathString)
44
+ return false if !path.is_winding
45
+ end
46
+ }
47
+ true
48
+ end
49
+
50
+ def dump
51
+ @document.each_recursive {|node|
52
+ if node.name == 'path'
53
+ pathString = node.attributes['android:pathData']
54
+ path = Path.with_string(pathString)
55
+ puts "Path"
56
+ path.dump(1)
57
+ end
58
+ }
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,52 @@
1
+ module VectorBeWinding
2
+ class Path < Shape
3
+ include SpatialTree
4
+
5
+ attr_reader :sub_paths
6
+
7
+ def self.with_string(path_string)
8
+ begin
9
+ svg_path = Savage::Parser.parse(path_string)
10
+ rescue => e
11
+ raise ArgumentError, "Possibly wrong path string \"#{path_string}\""
12
+ end
13
+ Path.new(svg_path.subpaths.map { |svg_subpath| SubPath.with_svg(svg_subpath) })
14
+ end
15
+
16
+ def initialize(sub_paths, is_tree = false)
17
+ if is_tree
18
+ @children = sub_paths
19
+ @sub_paths = []
20
+ children.each {|root| root.each { |subpath| @sub_paths << subpath }}
21
+ else
22
+ @sub_paths = sub_paths
23
+ sub_paths.each {|p| insert_to_tree(p)}
24
+ end
25
+ end
26
+
27
+ def bounding_rect
28
+ @bounding_rect ||= @sub_paths.map(&:bounding_rect).reduce(:|)
29
+ end
30
+
31
+ def area
32
+ sub_paths.map(&:area).reduce(:+)
33
+ end
34
+
35
+ def inspect
36
+ "#<Path>"
37
+ end
38
+
39
+ def is_winding(sign = 1)
40
+ children.all? { |c| c.is_winding }
41
+ end
42
+
43
+ def be_winding()
44
+ wounds = children.map(&:be_winding)
45
+ Path.new(wounds, true)
46
+ end
47
+
48
+ def to_command
49
+ sub_paths.map(&:to_command).join
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,77 @@
1
+ module VectorBeWinding
2
+ class Rect < Shape
3
+ attr_reader :left, :top, :right, :bottom
4
+
5
+ def initialize(left, top, right, bottom)
6
+ @left, @right = if left <= right then [left, right] else [right, left] end
7
+ @top, @bottom = if top <= bottom then [top, bottom] else [bottom, top] end
8
+ end
9
+
10
+ def self.with_vectors(v0, v1)
11
+ self.new(v0.x, v0.y, v1.x, v1.y)
12
+ end
13
+
14
+ def bounding_rect
15
+ self
16
+ end
17
+
18
+ def ==(rect1)
19
+ left == rect1.left && top == rect1.top &&
20
+ right == rect1.right && bottom == rect1.bottom
21
+ end
22
+
23
+ def empty?
24
+ left == right || top == bottom
25
+ end
26
+
27
+ def |(rect1)
28
+ Rect.new([left, rect1.left].min, [top, rect1.top].min,
29
+ [right, rect1.right].max, [bottom, rect1.bottom].max)
30
+ end
31
+
32
+ def &(rect1)
33
+ newLeft = [left, rect1.left].max
34
+ newTop = [top, rect1.top].max
35
+ newRight = [right, rect1.right].min
36
+ newBottom = [bottom, rect1.bottom].min
37
+
38
+ if (newLeft <= newRight && newTop <= newBottom)
39
+ Rect.new(newLeft, newTop, newRight, newBottom)
40
+ else
41
+ nil
42
+ end
43
+ end
44
+
45
+ def intersectedness(shape1)
46
+ if shape1.class == Rect
47
+ [Rect.range_intersectedness(left, right, shape1.left, shape1.right),
48
+ Rect.range_intersectedness(top, bottom, shape1.top, shape1.bottom)].min
49
+ else
50
+ shape1.intersectedness(self)
51
+ end
52
+ end
53
+
54
+ def self.range_intersectedness(a0, a1, b0, b1)
55
+ if a0 < b0
56
+ a1 - b0
57
+ else
58
+ b1 - a0
59
+ end
60
+ end
61
+
62
+ def containingness(shape1)
63
+ b = shape1.bounding_rect
64
+ [Rect.range_containingness(left, right, b.left, b.right),
65
+ Rect.range_containingness(top, bottom, b.top, b.bottom)].min
66
+ end
67
+
68
+ # check [a0, a0] contains [b0, b1]
69
+ def self.range_containingness(a0, a1, b0, b1)
70
+ if a0 <= b0 && b1 <= a1
71
+ (b0 - a0) * (a1 - b1)
72
+ else
73
+ -1
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,101 @@
1
+ module VectorBeWinding
2
+ class Segment < Shape
3
+ attr_reader :start_point, :direction, :end_point,
4
+ :control, :control_1
5
+
6
+ def initialize(direction, start_point, end_point_hint, prev_segment = nil)
7
+ @direction = direction
8
+ @start_point = start_point
9
+ @end_point =
10
+ if @direction.kind_of?(::Savage::Directions::PointTarget)
11
+ create_vector(@direction.target.x, @direction.target.y, @direction.absolute?)
12
+ elsif @direction.kind_of?(::Savage::Directions::HorizontalTo)
13
+ create_vector(@direction.target, nil, @direction.absolute?)
14
+ elsif @direction.kind_of?(::Savage::Directions::VerticalTo)
15
+ create_vector(nil, @direction.target, @direction.absolute?)
16
+ elsif @direction.kind_of?(::Savage::Directions::ClosePath)
17
+ end_point_hint
18
+ else
19
+ raise "Unknown direction: #{@direction}"
20
+ end
21
+
22
+ if @direction.instance_of?(::Savage::Directions::QuadraticCurveTo)
23
+ control = @direction.control ||
24
+ prev_segment.control&.reflect(start_point) ||
25
+ start_point
26
+ @control = create_vector(control.x, control.y, @direction.absolute?)
27
+ elsif @direction.instance_of?(::Savage::Directions::CubicCurveTo)
28
+ control = @direction.control
29
+ control_1 = @direction.control_1 ||
30
+ prev_segment.control&.reflect(start_point) ||
31
+ start_point
32
+ @control = create_vector(control.x, control.y, @direction.absolute?)
33
+ @control_1 = create_vector(control_1.x, control_1.y, @direction.absolute?)
34
+ end
35
+
36
+ # TODO: Support 'A'
37
+ end
38
+
39
+ def control_2
40
+ control
41
+ end
42
+
43
+ def create_vector(x, y, absolute)
44
+ if absolute
45
+ Vector.new(x || start_point.x, y || start_point.y)
46
+ else
47
+ start_point + Vector.new(x || 0, y || 0)
48
+ end
49
+ end
50
+
51
+ def bounding_rect
52
+ @bounding_rect ||=
53
+ Rect.new(start_point.x, start_point.y, end_point.x, end_point.y)
54
+ end
55
+
56
+ # Calculate direction area of the triangle (p, start_point, end_point)
57
+ # It must be positive iff the three points forms clockwise order.
58
+ def area(p)
59
+ if @direction.kind_of?(::Savage::Directions::QuadraticCurveTo)
60
+ # Approximate with triangle
61
+ (start_point - p).cross(control - start_point) +
62
+ (control - p).cross(end_point - control)
63
+ elsif @direction.kind_of?(::Savage::Directions::CubicCurveTo)
64
+ # Approximate with quadrangle
65
+ (start_point - p).cross(control_1 - start_point) +
66
+ (control_1 - p).cross(control_2 - control_1) +
67
+ (control_2 - p).cross(end_point - control_2)
68
+ else
69
+ # TODO: Support arc
70
+ (start_point - p).cross(end_point - start_point) / 2.0
71
+ end
72
+ end
73
+
74
+ def reverse
75
+ Segment.new(reverse_dir, end_point, start_point)
76
+ end
77
+
78
+ def reverse_dir
79
+ case @direction.command_code.upcase
80
+ when 'Z', 'L'
81
+ ::Savage::Directions::LineTo.new(start_point.x, start_point.y, true)
82
+ when 'M'
83
+ nil # Unable to reverse
84
+ when 'H'
85
+ ::Savage::Directions::HorizontalTo.new(start_point.x, true)
86
+ when 'V'
87
+ ::Savage::Directions::VerticalTo.new(start_point.y, true)
88
+ when 'Q', 'T'
89
+ ::Savage::Directions::QuadraticCurveTo.new(
90
+ control.x, control.y, start_point.x, start_point.y, true)
91
+ when 'C', 'S'
92
+ ::Savage::Directions::CubicCurveTo.new(
93
+ control.x, control.y, control_1.x, control_1.y,
94
+ start_point.x, start_point.y, true)
95
+ else
96
+ # TODO: Support 'A'
97
+ raise "Unknown direction: #{@direction}"
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,28 @@
1
+ module VectorBeWinding
2
+ class Shape
3
+ # Each subclass must override it
4
+ def bounding_rect
5
+ raise 'implment this'
6
+ end
7
+
8
+ def intersects?(shape1)
9
+ intersectedness(shape1) >= 0
10
+ end
11
+
12
+ # Very naive definition. Each subclass is expected to override it
13
+ # negative: no intersected, 0: touched, positive: intersected
14
+ def intersectedness(shape1)
15
+ bounding_rect.intersectedness(shape1.bounding_rect)
16
+ end
17
+
18
+ def contains?(shape1)
19
+ containingness(shape1) >= 0
20
+ end
21
+
22
+ # Very naive definition. Each subclass is expected to override it
23
+ # negative: no containing, 0: containing with border, positive: inside
24
+ def containingness(shape1)
25
+ bounding_rect.containingness(shape1.bounding_rect)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,39 @@
1
+ module VectorBeWinding
2
+ module SpatialTree
3
+ def children
4
+ @children ||= []
5
+ end
6
+
7
+ def insert_to_tree(node)
8
+ raise "#{node} is same node: " if equal?(node)
9
+
10
+ containers = children.select {|n1| n1.contains?(node)}
11
+ if containers.empty?
12
+ components = children.select {|n1| node.contains?(n1)}
13
+ components.each{|n1| children.delete(n1)}
14
+ node.children.concat(components)
15
+ children << node
16
+ else
17
+ containers.first.insert_to_tree(node)
18
+ end
19
+ end
20
+
21
+ def depth
22
+ if children.empty?
23
+ 1
24
+ else
25
+ children.map(&:depth).max + 1
26
+ end
27
+ end
28
+
29
+ def each &pr
30
+ pr.call(self)
31
+ children.each {|node| node.each(&pr) }
32
+ end
33
+
34
+ def dump(indent = 0)
35
+ puts ' ' * (indent * 2) + (area < 0 ? '-' : '+') + inspect
36
+ children.each {|node| node.dump(indent + 1)}
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,93 @@
1
+ module VectorBeWinding
2
+ class SubPath < Shape
3
+ include SpatialTree
4
+
5
+ attr_reader :start_point, :svg_subpath, :segments
6
+
7
+ def self.with_segments(segments)
8
+ SubPath.new.init_with_segment(segments)
9
+ end
10
+
11
+ # Suppose all segments are connected
12
+ def init_with_segment(segments)
13
+ raise "No segments" if segments.empty?
14
+ @segments = segments
15
+ @start_point = segments.first.start_point
16
+ @svg_subpath = Savage::SubPath.new(start_point.x, start_point.y)
17
+ @svg_subpath.directions.concat(segments.map(&:direction))
18
+ self
19
+ end
20
+
21
+ def self.with_string(path_string)
22
+ path = Savage::Parser.parse(path_string)
23
+ raise "No subpaths: ${path_string}" if path.subpaths.empty?
24
+ SubPath.with_svg(path.subpaths.last)
25
+ end
26
+
27
+ def self.with_svg(svg_subpath, start_point = nil)
28
+ SubPath.new.init_with_svg(svg_subpath, start_point)
29
+ end
30
+
31
+ def init_with_svg(svg_subpath, start_point = nil)
32
+ start_point ||= Vector.new(0,0)
33
+ @svg_subpath = svg_subpath
34
+ @segments = []
35
+
36
+ point = start_point
37
+ @svg_subpath.directions.each { |dir|
38
+ segment = Segment.new(dir, point, start_point, segments.last)
39
+ point = segment.end_point
40
+ if segment.direction.kind_of?(Savage::Directions::MoveTo)
41
+ start_point = point
42
+ else
43
+ @segments << segment
44
+ end
45
+ }
46
+ @start_point = start_point
47
+ self
48
+ end
49
+
50
+ def bounding_rect
51
+ unless @bounding_rect
52
+ rect = Rect.with_vectors(start_point, start_point)
53
+ segments.each { |segment|
54
+ rect |= segment.bounding_rect
55
+ }
56
+ @bounding_rect = rect
57
+ end
58
+ @bounding_rect
59
+ end
60
+
61
+ # Calculate direction area of this path.
62
+ # It's positive iff the path forms clockwise.
63
+ def area()
64
+ segments.map { |seg| seg.area(start_point) }.reduce(:+)
65
+ end
66
+
67
+ def reverse
68
+ SubPath.with_segments(segments.map(&:reverse).reverse)
69
+ end
70
+
71
+ def be_winding(sign = 1)
72
+ wound = if area * sign >= 0
73
+ SubPath.with_svg(svg_subpath)
74
+ else
75
+ reverse
76
+ end
77
+ wound.children.concat(children.map { |c| c.be_winding(-sign) })
78
+ wound
79
+ end
80
+
81
+ def is_winding
82
+ children.all? { |c| c.is_winding && c.area * area < 0}
83
+ end
84
+
85
+ def inspect
86
+ "#<SubPath \"#{svg_subpath.to_command}\">"
87
+ end
88
+
89
+ def to_command
90
+ @svg_subpath.to_command
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,47 @@
1
+ module VectorBeWinding
2
+ class Vector
3
+ attr_accessor :x, :y
4
+
5
+ def initialize(x, y)
6
+ @x = x
7
+ @y = y
8
+ end
9
+
10
+ def ==(v)
11
+ x == v.x && y == v.y
12
+ end
13
+
14
+ def -@()
15
+ Vector.new(-x, -y)
16
+ end
17
+
18
+ def +(v)
19
+ Vector.new(x + v.x, y + v.y)
20
+ end
21
+
22
+ def -(v)
23
+ Vector.new(x - v.x, y - v.y)
24
+ end
25
+
26
+ def *(s)
27
+ Vector.new(x * s, y * s)
28
+ end
29
+
30
+ def dot(v)
31
+ x * v.x + y * v.y
32
+ end
33
+
34
+ def norm
35
+ dot(self)
36
+ end
37
+
38
+ def cross(v)
39
+ x * v.y - y * v.x
40
+ end
41
+
42
+ # Create reflection point of self
43
+ def reflect(v)
44
+ v + (v - self)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ module VectorBeWinding
2
+ VERSION = "0.9.0"
3
+ end
@@ -0,0 +1,10 @@
1
+ require "savage"
2
+ require "vector_be_winding/version"
3
+ require "vector_be_winding/shape"
4
+ require "vector_be_winding/vector"
5
+ require "vector_be_winding/rect"
6
+ require "vector_be_winding/segment"
7
+ require "vector_be_winding/spatial_tree"
8
+ require "vector_be_winding/sub_path"
9
+ require "vector_be_winding/path"
10
+ require "vector_be_winding/drawable"
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'vector_be_winding/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "vector_be_winding"
8
+ spec.version = VectorBeWinding::VERSION
9
+ spec.authors = ["Takeshi SASAKI"]
10
+ spec.email = ["dagezi@gmail.com"]
11
+
12
+ spec.summary = %q{Let Android vector drawable follow winding-rule.}
13
+ spec.description = %q{Let Android vector drawable follow winding-rule.}
14
+ spec.homepage = "http://github.com/dagezi/vector-be-winding"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features|bin|sampleApp)/})
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_dependency "savage"
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.13"
27
+ spec.add_development_dependency "rake", "~> 10.0"
28
+ spec.add_development_dependency "rspec", "~> 3.0"
29
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vector_be_winding
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ platform: ruby
6
+ authors:
7
+ - Takeshi SASAKI
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-04-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: savage
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.13'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.13'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ description: Let Android vector drawable follow winding-rule.
70
+ email:
71
+ - dagezi@gmail.com
72
+ executables:
73
+ - vbw
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - ".rspec"
79
+ - ".travis.yml"
80
+ - Gemfile
81
+ - README.md
82
+ - Rakefile
83
+ - exe/vbw
84
+ - lib/vector_be_winding.rb
85
+ - lib/vector_be_winding/drawable.rb
86
+ - lib/vector_be_winding/path.rb
87
+ - lib/vector_be_winding/rect.rb
88
+ - lib/vector_be_winding/segment.rb
89
+ - lib/vector_be_winding/shape.rb
90
+ - lib/vector_be_winding/spatial_tree.rb
91
+ - lib/vector_be_winding/sub_path.rb
92
+ - lib/vector_be_winding/vector.rb
93
+ - lib/vector_be_winding/version.rb
94
+ - vector_be_winding.gemspec
95
+ homepage: http://github.com/dagezi/vector-be-winding
96
+ licenses:
97
+ - MIT
98
+ metadata: {}
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubyforge_project:
115
+ rubygems_version: 2.6.10
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: Let Android vector drawable follow winding-rule.
119
+ test_files: []
120
+ has_rdoc: