gradient 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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: