gradient 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: f318a955895204681e1ee985f8decfb009557eb4
4
+ data.tar.gz: 9af5a313c38bf4824dc53c4f1f2346c25cef0f60
5
+ SHA512:
6
+ metadata.gz: 6ca6cd175607983e38b4ca60d30a7a1d16edb94b245408498bddeac41165c4e0dba507ad33919aaad0bed8fdd03038b9f63e6d2b90868ee050f1a9f13c6e3644
7
+ data.tar.gz: eb7551719748b8361fb6db2bf8a3195ffa0e322d9b9d435873f9dd82d052aee6a91618eae87493e80dbd847d88eb182fd0cc5db00e8285a925332cb7732c651a
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,4 @@
1
+ --require helper
2
+ --format documentation
3
+ --color
4
+ --tty
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - 2.1.6
5
+ - 2.2.2
6
+ before_install: gem install bundler -v 1.10.6
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Philip Vieira
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # Gradient
2
+ Library for dealing with color gradients in ruby
3
+
4
+ ## Usage
5
+
6
+ ### Import Adobe Photoshop Gradient (`.grd`) files
7
+ For many artists a preferred way of creating gradients is through Photoshop.
8
+ You are able to parse `.grd` files and turn them in to a hash of `Gradient::Map` objects.
9
+
10
+ ```ruby
11
+ Gradient::GRD.parse("./kiwi.grd")
12
+ # => {"Kiwi" => <Gradient::Map:0x00000000000000
13
+ # @points=[
14
+ # #<Gradient::Point:0x007fae248a9358 @color=RGB [#3d1103], @location=0.0>,
15
+ # #<Gradient::Point:0x007fae248a9308 @color=RGB [#29860d], @location=0.386>,
16
+ # #<Gradient::Point:0x007fae248a92b8 @color=RGB [#a0cb1b], @location=0.84>,
17
+ # #<Gradient::Point:0x007fae248a9268 @color=RGB [#f3f56e], @location=0.927>,
18
+ # #<Gradient::Point:0x007fae248a9218 @color=RGB [#ffffff], @location=1.0>
19
+ # ]>
20
+ # }
21
+ ```
22
+
23
+ ## Installation
24
+ Add this line to your application's Gemfile:
25
+
26
+ ```ruby
27
+ gem "gradient"
28
+ ```
29
+
30
+ And then execute:
31
+
32
+ ```bash
33
+ $ bundle
34
+ ```
35
+
36
+ Or install it yourself as:
37
+
38
+ ```bash
39
+ $ gem install gradient
40
+ ```
41
+
42
+ ## Development
43
+ 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.
44
+ 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).
45
+
46
+ ## Contributing
47
+ 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.
48
+
49
+ ## License
50
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
51
+
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/bin/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "gradient"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ require "pry"
10
+ Pry.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
data/gradient.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "gradient/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "gradient"
8
+ spec.version = Gradient::VERSION
9
+ spec.authors = ["Philip Vieira"]
10
+ spec.email = ["zee@vall.in"]
11
+
12
+ spec.summary = %q{Library for dealing with color gradients in ruby}
13
+ spec.description = spec.summary
14
+ spec.homepage = "https://github.com/zeeraw/gradient"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_dependency "color", "~> 1.8"
23
+ spec.add_development_dependency "bundler", "~> 1.10"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "rspec"
26
+ spec.add_development_dependency "pry"
27
+ end
data/lib/gradient.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "gradient/version"
2
+ require "gradient/point"
3
+ require "gradient/map"
4
+ require "gradient/grd"
5
+
6
+ module Gradient
7
+ require "color"
8
+ end
@@ -0,0 +1,315 @@
1
+ module Gradient
2
+ class GRD
3
+
4
+ SHIFT_BUFFER = " "
5
+ COLOR_TERMS = %w(Cyn Mgnt Ylw Blck Rd Grn Bl H Strt Brgh)
6
+ PARSE_METHODS = {
7
+ "patt" => :parse_patt,
8
+ "desc" => :parse_desc,
9
+ "VlLs" => :parse_vlls,
10
+ "TEXT" => :parse_text,
11
+ "Objc" => :parse_objc,
12
+ "UntF" => :parse_untf,
13
+ "bool" => :parse_bool,
14
+ "long" => :parse_long,
15
+ "doub" => :parse_doub,
16
+ "enum" => :parse_enum,
17
+ "tdta" => :parse_tdta,
18
+ }
19
+
20
+ attr_reader :maps
21
+
22
+ class << self
23
+
24
+ def parse(file)
25
+ new(file).maps
26
+ end
27
+
28
+ end
29
+
30
+ def initialize(file)
31
+ @maps = {}
32
+ @gradients = []
33
+ @gradient_names = []
34
+ @current_object_name = ""
35
+ @current_gradient = []
36
+ @current_color = {}
37
+ @shift = 0
38
+
39
+ File.open(file, "r") do |file|
40
+ parse while (@buffer = file.gets)
41
+ end
42
+ end
43
+
44
+ private def parse
45
+ @offset = 28
46
+ parse_entry while @offset < @buffer.length
47
+ flush_current_gradient
48
+
49
+ gradients = @gradients.map do |gradient|
50
+ points = clean_gradient(gradient).map do |point_data|
51
+ Gradient::Point.new(*point_data)
52
+ end
53
+
54
+ Gradient::Map.new(*points)
55
+ end
56
+
57
+ @maps = Hash[ @gradient_names.zip(gradients) ]
58
+ end
59
+
60
+ private def clean_gradient(color_steps)
61
+ locations = color_steps.map { |g| g["Lctn"] }
62
+ min_location = locations.min
63
+ max_location = locations.max
64
+ locations = locations.map do |location|
65
+ ((location - min_location) * (1.0 / (max_location - min_location))).round(3)
66
+ end
67
+
68
+ colors = color_steps.map do |color_step|
69
+ convert_to_color(color_step)
70
+ end
71
+
72
+ color_locations = locations.zip(colors)
73
+ end
74
+
75
+ private def convert_to_color(color_data)
76
+ case format = color_data["palette"]
77
+ when "CMYC" then Color::CMYK.from_percent(*color_data.values_at("Cyn", "Mgnt", "Ylw", "Blck").map(&:round))
78
+ when "RGBC" then Color::RGB.new(*color_data.values_at("Rd", "Grn", "Bl").map(&:round))
79
+ when "HSBC"
80
+ h = color_data.fetch("H")
81
+ s = color_data.fetch("Strt") / 100.0
82
+ l = color_data.fetch("Brgh") / 100.0
83
+ Color::HSL.from_fraction(h, s, l)
84
+ else
85
+ raise NotImplementedError.new("The color #{format} is not supported")
86
+ end
87
+ end
88
+
89
+ # Unpack 8 bytes IEEE 754 value to floating point number
90
+ private def current_float_slice
91
+ @buffer.slice(@offset, 8).unpack("G").first
92
+ end
93
+
94
+ private def current_slice_length
95
+ current_slice.unpack("L>").first
96
+ end
97
+
98
+ private def current_slice(length=4)
99
+ @buffer.slice(@offset, length)
100
+ end
101
+
102
+ private def continue!(steps=4)
103
+ @offset += steps
104
+ end
105
+
106
+ private def upshift!
107
+ @shift += 4
108
+ end
109
+
110
+ private def downshift!
111
+ @shift -= 4
112
+ end
113
+
114
+ private def log(name, type, *args)
115
+ puts "#{Array.new(@shift, " ").join}#{name}(#{type}) #{ Array(args).join(", ") }" if ENV["ENABLE_LOG"]
116
+ end
117
+
118
+ private def send_parse_method(type, name)
119
+ if parse_method = PARSE_METHODS.fetch(type, nil)
120
+ send(parse_method, name)
121
+ else
122
+ parse_unknown(name)
123
+ end
124
+ end
125
+
126
+ private def parse_entry
127
+ length = current_slice_length
128
+ length = 4 if length.zero?
129
+ continue!
130
+
131
+ name = current_slice
132
+ continue!(length)
133
+
134
+ type = current_slice
135
+ continue!
136
+
137
+ send_parse_method(type, name)
138
+ end
139
+
140
+ private def flush_current_gradient
141
+ flush_current_color
142
+ @gradients << @current_gradient if @current_gradient.any?
143
+ @current_gradient = []
144
+ end
145
+
146
+ private def flush_current_color
147
+ @current_gradient << @current_color if @current_color.any?
148
+ @current_color = {}
149
+ end
150
+
151
+ private def parse_patt(name)
152
+ # TODO: Figure out exactly what this is and implement it.
153
+ log(name, "patt")
154
+ end
155
+
156
+ private def parse_desc(name)
157
+ size = current_slice_length
158
+ log(name, "desc", size)
159
+ continue!(26)
160
+ end
161
+
162
+ private def parse_vlls(name)
163
+ size = current_slice_length
164
+ continue!
165
+ log(name, "vlls", size)
166
+ upshift!
167
+
168
+ size.times do
169
+ type = current_slice
170
+ continue!
171
+ send_parse_method(type, name)
172
+ end
173
+
174
+ downshift!
175
+ end
176
+
177
+ private def parse_text(name)
178
+ size = current_slice_length
179
+ characters = []
180
+
181
+ (0..size).each_with_index do |string, idx|
182
+ a = @offset + 4 + idx * 2 + 1
183
+ b = @offset + 4 + idx * 2 + 2
184
+ characters << @buffer[a...b]
185
+ end
186
+
187
+ text = characters.join
188
+
189
+ log(name, "text", size, text)
190
+
191
+ if @current_object_name == "Grad" && name.strip == "Nm"
192
+ @gradient_names << text.strip
193
+ end
194
+
195
+ continue!(4 + size * 2)
196
+ end
197
+
198
+ private def parse_objc(name)
199
+ object_name_length = current_slice_length
200
+ continue!
201
+
202
+ object_name = current_slice(object_name_length * 2)
203
+ continue!(object_name_length * 2)
204
+
205
+ object_type_length = current_slice_length
206
+ object_type_length = 4 if object_type_length.zero?
207
+ continue!
208
+
209
+ object_type = current_slice(object_type_length)
210
+ continue!(object_type_length)
211
+
212
+ object_size = current_slice_length
213
+ continue!
214
+
215
+ log(name, "objc", object_size, object_type, object_name)
216
+
217
+ @current_object_name = name.strip
218
+ case @current_object_name
219
+ when "Grad"
220
+ flush_current_gradient
221
+ when "Clr"
222
+ flush_current_color
223
+ @current_color = { "palette" => object_type.strip }
224
+ end
225
+
226
+ upshift!
227
+ object_size.times { parse_entry }
228
+ downshift!
229
+ end
230
+
231
+ private def parse_untf(name)
232
+ type = current_slice
233
+ value = @buffer.slice(@offset + 4, 8).unpack("G").first
234
+ log(name, "untf", type, value)
235
+
236
+ if @current_object_name == "Clr" && COLOR_TERMS.include?(name.strip)
237
+ @current_color[name.strip] = value
238
+ end
239
+
240
+ continue!(12)
241
+ end
242
+
243
+ private def parse_bool(name)
244
+ value = @buffer.slice(@offset, 1).ord
245
+ log(name, "bool", value)
246
+ continue!(1)
247
+ end
248
+
249
+ private def parse_long(name)
250
+ size = current_slice_length
251
+ log(name, "long", size)
252
+
253
+ if @current_object_name == "Clr" && name == "Lctn"
254
+ @current_color[name.strip] = size
255
+ end
256
+
257
+ continue!
258
+ end
259
+
260
+ private def parse_doub(name)
261
+ value = current_float_slice
262
+ log(name, "doub", value)
263
+
264
+ if @current_object_name == "Clr" && COLOR_TERMS.include?(name.strip)
265
+ @current_color[name.strip] = value
266
+ end
267
+
268
+ continue!(8)
269
+ end
270
+
271
+ private def parse_enum(name)
272
+ size_a = current_slice_length
273
+ continue!
274
+ size_a = 4 if size_a.zero?
275
+ name_a = current_slice(size_a)
276
+ continue!(size_a)
277
+
278
+ size_b = current_slice_length
279
+ continue!
280
+ size_b = 4 if size_b.zero?
281
+ name_b = current_slice(size_b)
282
+ continue!(size_b)
283
+
284
+ log(name, "enum", name_a, name_b)
285
+ end
286
+
287
+ private def parse_tdta(name)
288
+ log(name, "tdta")
289
+ parse_unknown(name)
290
+ end
291
+
292
+ private def parse_unknown(name)
293
+ name = @buffer.slice(@offset + 8, 4)
294
+ log(name, "unknown", "Failed with simple case")
295
+
296
+ hex = []
297
+ ascii = []
298
+
299
+ (0...15).times do |i|
300
+ begin
301
+ ord = @buffer[@offset + i].ord
302
+ hex << "%02x" % ord
303
+ ascii << (ord < 32 || 126 < ord) ? "." : ord
304
+ rescue
305
+ log(name, "unknown", "Something failed")
306
+ end
307
+ end
308
+
309
+ fail [hex.join(" "), ascii.join].join("\n")
310
+ end
311
+
312
+ end
313
+ end
314
+
315
+
@@ -0,0 +1,8 @@
1
+ module Gradient
2
+ class Map
3
+ attr_reader :points
4
+ def initialize(*points)
5
+ @points = Array(points).sort { |a, b| a.location <=> b.location }
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module Gradient
2
+ class Point
3
+ attr_reader :color, :location
4
+ def initialize(location, color)
5
+ @color, @location = color, location
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ module Gradient
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gradient
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Philip Vieira
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-11-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: color
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.8'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.8'
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.10'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.10'
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: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Library for dealing with color gradients in ruby
84
+ email:
85
+ - zee@vall.in
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - ".travis.yml"
93
+ - Gemfile
94
+ - LICENSE.txt
95
+ - README.md
96
+ - Rakefile
97
+ - bin/console
98
+ - bin/setup
99
+ - gradient.gemspec
100
+ - lib/gradient.rb
101
+ - lib/gradient/grd.rb
102
+ - lib/gradient/map.rb
103
+ - lib/gradient/point.rb
104
+ - lib/gradient/version.rb
105
+ homepage: https://github.com/zeeraw/gradient
106
+ licenses:
107
+ - MIT
108
+ metadata: {}
109
+ post_install_message:
110
+ rdoc_options: []
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 2.4.5
126
+ signing_key:
127
+ specification_version: 4
128
+ summary: Library for dealing with color gradients in ruby
129
+ test_files: []