gradient 0.4.0 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2b086f81d5d8bc9667fd9ecf8272f154f882402d
4
- data.tar.gz: 2ddcd6b8f68940d5dca3f7b6b18809cdc0a73416
3
+ metadata.gz: 16b46fdf7f784862a6e05230f8717e4485c5794c
4
+ data.tar.gz: c677d43ca0e4cb0a3df7e28811ec9a442b8b7dce
5
5
  SHA512:
6
- metadata.gz: 7487c077ae4393109c689ea7ffef938108059d6965e8e04e47747fa8be7d97444f444f3364571de9ad813f604169371b542810c71ef669889cd238bec15675e5
7
- data.tar.gz: 46c68629d2e91dfa0432a230886a28c68e60450ab2eef160d8ff2434b91fef2cf68b04c16c2dcf31ae43d92f0c82d6bb4282549e91c880cf5cbae63a9a3b5449
6
+ metadata.gz: 040beeb18b21d234a733d1790d37f8c0508255cc6f44dcaa5dfaad1a08445736a0ffb0b771beb633b349c808b69e71bb8535788d82b4ef8497c9eadfcd06fa5c
7
+ data.tar.gz: a6b6060794a681c72d6609af073c0b2f2fde4ec9c247de2c6f65f07ac60bfcabbf449a6810d08257d28aaf6d1a7e52edb39bddaf71c8ce90d3525f92da0251dc
@@ -1,6 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.0.0
4
3
  - 2.1.6
5
4
  - 2.2.2
6
5
  before_install: gem install bundler -v 1.10.6
6
+ script: bundle exec rspec
data/README.md CHANGED
@@ -1,4 +1,7 @@
1
1
  # Gradient
2
+ [![Gem Version](https://badge.fury.io/rb/gradient.svg)](https://badge.fury.io/rb/gradient)
3
+ [![Build Status](https://travis-ci.org/zeeraw/gradient.svg?branch=master)](https://travis-ci.org/zeeraw/gradient)
4
+
2
5
  Library for dealing with color gradients in ruby
3
6
 
4
7
  ## Usage
@@ -40,8 +43,28 @@ printer.radial(shape: :circle)
40
43
  # => "radial-gradient(circle, rgba(30,87,153,1.0) 0%, rgba(41,137,216,0.02) 49%, rgba(37,131,209,0.0) 50%, rgba(32,124,202,0.02) 51%, rgba(125,185,232,1.0) 100%)"
41
44
  ```
42
45
 
43
- ### Import Adobe Photoshop Gradient (`.grd`) files
44
- For many artists a preferred way of creating gradients is through Photoshop.
46
+ ### Serialize & deserialize gradients
47
+ To store your gradients in something like a document database,
48
+ you're able to convert a gradient to primitives using `Gradient::Map#serialize`.
49
+
50
+ ```ruby
51
+ Gradient::Map.new(
52
+ Gradient::Point.new(0, Color::RGB.new(221, 189, 82), 1.0),
53
+ Gradient::Point.new(1, Color::RGB.new(89, 12, 72), 0.3)
54
+ ).serialize
55
+ # => [[0, "rgb", [221, 189, 82], 1.0], [1, "rgb", [89, 12, 72], 0.3]]
56
+
57
+ ```
58
+
59
+ You can easily turn them back in to ruby objects by using `Gradient::Map.deserialize`.
60
+
61
+ ```ruby
62
+ Gradient::Map.deserialize([[0, "rgb", [221, 189, 82], 1.0], [1, "rgb", [89, 12, 72], 0.3]])
63
+ # => #<Gradient Map #<Point 0 #ddbd52ff> #<Point 100 #590c484d>>
64
+ ```
65
+
66
+ ### Import Adobe Photoshop gradient (`.grd`) files
67
+ For many artists, a preferred way of creating gradients is through Photoshop.
45
68
  You are able to parse `.grd` files and turn them in to a hash of `Gradient::Map` objects.
46
69
 
47
70
  ```ruby
@@ -51,6 +74,17 @@ Gradient::GRD.read("./kiwi.grd")
51
74
  # }
52
75
  ```
53
76
 
77
+ ### Import SVG gradients
78
+ SVG images can contain multiple gradients, and these can be extracted in the same
79
+ way as for [`.grd`](#import-adobe-photoshop-gradient-grd-files) files.
80
+
81
+ ```ruby
82
+ Gradient::SVG.read("./lemon-lime.svg")
83
+ # => {
84
+ # "Lemon-Lime"=> #<Gradient Map #<Point 0.0 #ffff00ff> #<Point 20.0 #ffff00ff> #<Point 50.0 #00ff00ff> #<Point 80.0 #ffff00ff> #<Point 100.0 #ffff00ff>>}"
85
+ # }
86
+ ```
87
+
54
88
  ### Separate point vectors for opacity and color
55
89
  You're able to control the point vectors for color and opacity separately by using a point merger.
56
90
 
@@ -74,6 +108,18 @@ gradient = Gradient::Map.new(points)
74
108
  # => #<Gradient Map #<Point 0 #1e5799ff> #<Point 49.0 #2989d805> #<Point 50.0 #2583d100> #<Point 51.0 #207cca05> #<Point 100 #7db9e8ff>>
75
109
  ```
76
110
 
111
+ ### Interpolation
112
+ One can find the color and opacity at an arbitrary location using the `#at` method, which returns a new `Gradient::Point`.
113
+
114
+ ```ruby
115
+ map = Gradient::Map.new(
116
+ Gradient::Point.new(0, Color::RGB.new(0, 128, 255), 1.0),
117
+ Gradient::Point.new(1, Color::RGB.new(255, 128, 0), 0.0)
118
+ )
119
+ map.at(0.5)
120
+ # => #<Point 50.0 #80808080>
121
+ ```
122
+
77
123
  ## Installation
78
124
  Add this line to your application's Gemfile:
79
125
 
@@ -98,7 +144,7 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
98
144
  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).
99
145
 
100
146
  ## Contributing
101
- Bug reports and pull requests are welcome on GitHub at https://github.com/zeeraw/gradient. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
147
+ Bug reports and pull requests are welcome on GitHub at https://github.com/zeeraw/gradient. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
102
148
 
103
149
  ## License
104
150
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -1,5 +1,5 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
@@ -20,7 +20,8 @@ Gem::Specification.new do |spec|
20
20
  spec.require_paths = ["lib"]
21
21
 
22
22
  spec.add_dependency "color", "~> 1.8"
23
- spec.add_development_dependency "bundler", "~> 1.10"
23
+ spec.add_dependency 'nokogiri', '~> 1.6'
24
+ spec.add_development_dependency "bundler", "~> 1.7"
24
25
  spec.add_development_dependency "rake", "~> 10.0"
25
26
  spec.add_development_dependency "rspec"
26
27
  spec.add_development_dependency "pry"
@@ -5,8 +5,9 @@ require "gradient/point"
5
5
  require "gradient/point_merger"
6
6
  require "gradient/map"
7
7
  require "gradient/grd"
8
+ require "gradient/svg"
8
9
  require "gradient/css_printer"
9
10
 
10
11
  module Gradient
11
12
  require "color"
12
- end
13
+ end
@@ -18,6 +18,26 @@ module Gradient
18
18
  "#<Gradient Map #{points.map(&:inspect).join(" ")}>"
19
19
  end
20
20
 
21
+ def range
22
+ @range ||=
23
+ begin
24
+ ends = [:first, :last]
25
+ .map { |method| points.send(method) }
26
+ .map(&:location)
27
+ Range.new(*ends)
28
+ end
29
+ end
30
+
31
+ def at(location, opts = {})
32
+ if range.include? location then
33
+ if 0 == (i = points.find_index { |p| p.location >= location }) then
34
+ points[0].dup
35
+ else
36
+ interpolate_points(points[i-1], points[i], location)
37
+ end
38
+ end
39
+ end
40
+
21
41
  def to_css(**args)
22
42
  @css_printer ||= Gradient::CSSPrinter.new(self)
23
43
  @css_printer.css(**args)
@@ -31,5 +51,32 @@ module Gradient
31
51
  serialize
32
52
  end
33
53
 
54
+ private
55
+
56
+ def interpolate_points(point_left, point_right, location)
57
+ points = [point_left, point_right]
58
+ color_left, color_right = points.map(&:color)
59
+ location_left, location_right = points.map(&:location)
60
+ separation = location_right - location_left
61
+ if separation == 0.0 then
62
+ point_right.dup
63
+ else
64
+ weight = (location - location_left)/separation
65
+ r, g, b = [:r, :g, :b].map do |channel|
66
+ interpolate_floats(color_left.send(channel),
67
+ color_right.send(channel),
68
+ weight)
69
+ end
70
+ color = Color::RGB.from_fraction(r, g, b)
71
+ opacity = interpolate_floats(point_left.opacity,
72
+ point_right.opacity,
73
+ weight)
74
+ Point.new(location, color, opacity)
75
+ end
76
+ end
77
+
78
+ def interpolate_floats(x0, x1, weight)
79
+ x0 * (1.0 - weight) + x1 * weight
80
+ end
34
81
  end
35
- end
82
+ end
@@ -0,0 +1,118 @@
1
+ require 'scanf'
2
+ require 'nokogiri'
3
+
4
+ module Gradient
5
+
6
+ class SVGError < StandardError ; end
7
+
8
+ class SVG
9
+
10
+ attr_reader :maps
11
+
12
+ class << self
13
+
14
+ def parse(string_buffer)
15
+ new.tap do |parser|
16
+ parser.parse(string_buffer)
17
+ end.maps
18
+ end
19
+
20
+ def read(file)
21
+ new.tap do |parser|
22
+ File.open(file, 'r') do |file|
23
+ parser.parse(file.read)
24
+ end
25
+ end.maps
26
+ end
27
+
28
+ def open(file)
29
+ read(file)
30
+ end
31
+
32
+ end
33
+
34
+ def initialize
35
+ @maps = {}
36
+ end
37
+
38
+ SVGNS = 'http://www.w3.org/2000/svg'
39
+
40
+ def parse(buffer)
41
+ xml = Nokogiri::XML(buffer)
42
+ (
43
+ xml.xpath('//linearGradient') +
44
+ xml.xpath('//xmlns:linearGradient', 'xmlns' => SVGNS)
45
+ ).each do |linear_gradient|
46
+ unless (id = linear_gradient['id']) then
47
+ raise SVGError, 'linearGradient has no id'
48
+ end
49
+ unless (map = parse_linear_gradient(linear_gradient)).points.empty?
50
+ @maps[id] = map
51
+ end
52
+ end
53
+ end
54
+
55
+ private def parse_linear_gradient(linear_gradient)
56
+ map = Gradient::Map.new
57
+ linear_gradient.children.each do |node|
58
+ next unless node.name == 'stop'
59
+ map.points << parse_stop(node)
60
+ end
61
+ map
62
+ end
63
+
64
+ private def parse_stop(stop)
65
+ unless (offset = stop['offset']) then
66
+ raise SVGError, 'stop has no offset'
67
+ end
68
+ location = parse_location(offset)
69
+ if (style = stop['style']) then
70
+ point_from_style(location, style)
71
+ else
72
+ point_from_stop(location, stop)
73
+ end
74
+ end
75
+
76
+ private def point_from_style(location, style)
77
+ stop = Hash[ style.split(/;/).map { |item| item.split(/:/) } ]
78
+ point_from_stop(location, stop)
79
+ end
80
+
81
+ private def point_from_stop(location, stop)
82
+ unless (stop_color = stop['stop-color']) then
83
+ raise SVGError, 'stop has no stop-color'
84
+ end
85
+ color, opacity = parse_stop_color(stop_color)
86
+ if (stop_opacity = stop['stop-opacity']) then
87
+ opacity = parse_stop_opacity(stop_opacity)
88
+ end
89
+ Gradient::Point.new(location, color, opacity)
90
+ end
91
+
92
+ private def parse_location(offset)
93
+ unless (location = offset.scanf('%f%%')).count == 1 then
94
+ raise SVGError, "failed parse of offset #{offset}"
95
+ end
96
+ location.first / 100.0
97
+ end
98
+
99
+ private def parse_stop_color(stop_color)
100
+ parts =
101
+ if (r, g, b = stop_color.scanf('rgb(%d,%d,%d)')).count == 3 then
102
+ [Color::RGB.new(r, g, b), 1.0]
103
+ elsif (r, g, b, a = stop_color.scanf('rgba(%d,%d,%d,%f)')).count == 4 then
104
+ [Color::RGB.new(r, g, b), a]
105
+ elsif (color = Color::RGB.by_css(stop_color)) then
106
+ [color, 1.0]
107
+ end
108
+ unless parts then
109
+ raise SVGError, "failed parse of stop-color #{stop_color}"
110
+ end
111
+ parts
112
+ end
113
+
114
+ private def parse_stop_opacity(stop_opacity)
115
+ stop_opacity.scanf('%f').first
116
+ end
117
+ end
118
+ end
@@ -1,3 +1,3 @@
1
1
  module Gradient
2
- VERSION = "0.4.0"
2
+ VERSION = "0.5.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gradient
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Philip Vieira
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-11-22 00:00:00.000000000 Z
11
+ date: 2016-01-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: color
@@ -24,20 +24,34 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.6'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - "~>"
32
46
  - !ruby/object:Gem::Version
33
- version: '1.10'
47
+ version: '1.7'
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
- version: '1.10'
54
+ version: '1.7'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rake
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -119,6 +133,7 @@ files:
119
133
  - lib/gradient/opacity_point.rb
120
134
  - lib/gradient/point.rb
121
135
  - lib/gradient/point_merger.rb
136
+ - lib/gradient/svg.rb
122
137
  - lib/gradient/version.rb
123
138
  homepage: https://github.com/zeeraw/gradient
124
139
  licenses: