ios_icon_generator 0.1 → 0.1.1

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: 2f852400e4c7991cb98356bac374aaf2b94c47af
4
- data.tar.gz: d0d52e7ba57b37506f51412a54a1868f9709561f
3
+ metadata.gz: 0b46b6ba358fea7257956c5b604814fab0e6357d
4
+ data.tar.gz: ff34cdecebb146b1a0bd77785a42128181587d44
5
5
  SHA512:
6
- metadata.gz: 485b9f3d19409c684ffa7062dc3a81ba0aa25331dc20475dc3aa6ecdb09393379c7c997ff2fed94cc9240b5a058607ed74c036b1343710b26ef9496abb5482b8
7
- data.tar.gz: ab152df1fe540e28a284c45be891cf67c9e9c9113f5b3381773799e6ae69ff680483d160bf17b3aff39d26af4467a7153a30fdb07217e2be64b969fa4a608120
6
+ metadata.gz: 4ee3aa9f28014df742b90153ab9920f47d92c0f5eefbb90ff33a27e13a5774feed4a769c8ec17e67ab58487ca52096b8546479c2ce3a2184a19688b4c4527782
7
+ data.tar.gz: 592077858ad24fff1f632c2aab47022f55e86d9ec97e660021f8be11d60af33811aafd95d7dd55e773afc2971f9d834bedb227e648cce71d43b6b1e224221ae2
data/.yardopts ADDED
@@ -0,0 +1,4 @@
1
+ --output-dir docs
2
+ --readme README.md
3
+ --no-private
4
+ lib/ios_icon_generator/version.rb lib/ios_icon_generator.rb lib/ios_icon_generator/helpers/**/*.rb
data/README.md CHANGED
@@ -33,7 +33,7 @@ For now, the CLI supports generating app icon sets for all supported platforms:
33
33
  - Mac
34
34
  - Carplay
35
35
 
36
- > Please note that the Display P3 is not supported yet
36
+ > Please note that the Display P3 color space is not supported yet
37
37
 
38
38
  And supports generating sticker packs icons for iMessage apps.
39
39
 
@@ -33,7 +33,7 @@ module IOSIconGenerator
33
33
  option :parallel_processes, type: :integer, default: -1, desc: 'Number of processes to use to process the files. Defaults to -1, meaning the number of cores the machine. \
34
34
  Set to 0 to disable parallel processing.'
35
35
  def call(icon_path:, xcasset_folder:, type:, **options)
36
- raise "#{'ImageMagick'.blue.bold} is required. It can be installed via #{'homebrew'.bold.underlined} using #{'brew install imagemagick'.blue.bold.underlined}" unless Library.which('magick')
36
+ raise "#{'ImageMagick'.blue.bold} is required. It can be installed via #{'homebrew'.bold.underlined} using #{'brew install imagemagick'.blue.bold.underlined}" unless Helpers.which('magick')
37
37
 
38
38
  types = type.map(&:to_sym)
39
39
 
@@ -39,8 +39,8 @@ module IOSIconGenerator
39
39
  option :symbol_color, default: '#7F0000', desc: 'The color of the symbol to use to generate the mask.'
40
40
  option :font, default: 'Helvetica', desc: 'The font to use to generate the symbol.'
41
41
  option :file, default: nil, desc: 'The path to an image representing the symbol to use to generate the mask.'
42
- option :x_size_ratio, type: :float, default: 0.46, desc: 'The x offset of the size of the mask.'
43
- option :y_size_ratio, type: :float, default: 0.46, desc: 'The y offset of the size of the mask.'
42
+ option :x_size_ratio, type: :float, default: 0.54, desc: 'The x offset of the size of the mask.'
43
+ option :y_size_ratio, type: :float, default: 0.54, desc: 'The y offset of the size of the mask.'
44
44
  option :size_offset, type: :float, default: 0.12, desc: 'The size offset to use when applying the symbol. 0.0 means it\'s scale to the full image, 1.0 means the symbol has the full size of the logo.'
45
45
  option :x_offset, type: :float, default: 0.11, desc: 'The x offset to use when applying the symbol. 0.0 means bottom, 1.0 means top.'
46
46
  option :y_offset, type: :float, default: 0.11, desc: 'The y offset to use when applying the symbol. 0.0 means left, 1.0 means top.'
@@ -48,7 +48,7 @@ module IOSIconGenerator
48
48
  option :parallel_processes, type: :integer, default: -1, desc: 'Number of processes to use to process the files. Defaults to -1, meaning the number of cores the machine. \
49
49
  Set to 0 to disable parallel processing.'
50
50
  def call(appiconset_path:, output_path:, **options)
51
- raise "#{'ImageMagick'.blue.bold} is required. It can be installed via #{'homebrew'.bold.underlined} using #{'brew install imagemagick'.blue.bold.underlined}" unless Library.which('magick')
51
+ raise "#{'ImageMagick'.blue.bold} is required. It can be installed via #{'homebrew'.bold.underlined} using #{'brew install imagemagick'.blue.bold.underlined}" unless Helpers.which('magick')
52
52
 
53
53
  raise 'There is no App icon set at the path specified.' unless Dir.exist?(appiconset_path)
54
54
 
@@ -34,15 +34,15 @@ module IOSIconGenerator
34
34
  option :font, default: 'Helvetica', desc: 'The font to use to generate the symbol.'
35
35
  option :symbol_color, default: '#7F0000', desc: 'The color of the symbol to use to generate the mask.'
36
36
  option :stroke_color, default: '#000000', desc: 'The stroke color of the mask'
37
- option :stroke_width_offset, type: :float, default: 0.1, desc: 'The width of the stroke used when generating the symbol.'
37
+ option :stroke_width_offset, type: :float, default: 0.0, desc: 'The width of the stroke used when generating the symbol.'
38
38
  option :size_offset, type: :float, default: 0.5, desc: 'The point size used for the symbol, relative to the height of the icon. Values over 0.5 are not recommended.'
39
39
  option :x_offset, type: :float, default: 0.0, desc: 'The x offset to use when applying the symbol. 0.0 means bottom, 1.0 means top.'
40
- option :y_offset, type: :float, default: 0.0, desc: 'The y offset to use when applying the symbol. 0.0 means left, 1.0 means top.'
40
+ option :y_offset, type: :float, default: -0.05, desc: 'The y offset to use when applying the symbol. 0.0 means left, 1.0 means top.'
41
41
  option :type, type: :array, default: %w[iphone], desc: 'Which target to generate the icons for. Can be "iphone", "ipad", "watch", "mac" or "carplay" or a combination of any of them, or "imessage"'
42
42
  option :parallel_processes, type: :integer, default: -1, desc: 'Number of processes to use to process the files. Defaults to -1, meaning the number of cores the machine. \
43
43
  Set to 0 to disable parallel processing.'
44
44
  def call(text:, xcasset_folder:, type:, **options)
45
- raise "#{'ImageMagick'.blue.bold} is required. It can be installed via #{'homebrew'.bold.underlined} using #{'brew install imagemagick'.blue.bold.underlined}" unless Library.which('magick')
45
+ raise "#{'ImageMagick'.blue.bold} is required. It can be installed via #{'homebrew'.bold.underlined} using #{'brew install imagemagick'.blue.bold.underlined}" unless Helpers.which('magick')
46
46
 
47
47
  types = type.map(&:to_sym)
48
48
 
@@ -16,23 +16,51 @@
16
16
 
17
17
  require 'json'
18
18
  require 'fileutils'
19
- require 'ios_icon_generator/helpers/images_sets_definition'
19
+ require 'ios_icon_generator/helpers/image_sets_definition'
20
20
 
21
21
  module IOSIconGenerator
22
22
  module Helpers
23
+ ##
24
+ # Generate an icon using the base icon provided.
25
+ #
26
+ # If +icon_path+ is set to +nil+, the function expects +generate_icon+ to be set or the function will raise.
27
+ #
28
+ # @param [String, #read] icon_path The path to the icon to use as the base icon.
29
+ # If specified, it must point to a valid pdf file (with a .pdf extension), with a resolution over 1024x1024.
30
+ # If not specified, +generate_icon+ must be specified.
31
+ # @param [String, #read] output_folder The folder to create the app icon set in.
32
+ # @param [Array<Symbol>, #read] types The types to generate the sets of images for. Each type must be one of +:iphone+, +:ipad+, +:watch+, +mac+ or +carplay+, or it can be an array of just +:imessage+.
33
+ # @param [Symbol, #read] parallel_processes The number of processes to use when generating the icons.
34
+ # +nil+ means it'll use as many processes as they are cores on the machine.
35
+ # +0+ will disables spawning any processes.
36
+ # @param [Lambda(base_path [String], target_path [String], width [Float], height [Float]), #read] generate_icon The lambda that actually generates the icon.
37
+ # If none is specified, and default one will be used.
38
+ # It should take four parameters:
39
+ # - +base_path+: The base path to the reference image to use to generate the new icon. If +icon_path+ is set to +nil+, the +base_path+ parameter will +nil+ as well.
40
+ # - +target_path+: The path to generate the icon at.
41
+ # - +width+: The width of the icon to generate.
42
+ # - +height+: The height of the icon to generate.
43
+ # @param [Lambda(progress [Int], total [Int]), #read] progress An optional progress block called when progress has been made generating the icons.
44
+ # It should take two parameters:
45
+ # - +progress+: An integer indicating the current progress out of +total+
46
+ # - +total+: An integer indicating the total progress
47
+ #
48
+ # @return [String] Return the path to the generated app icon set.
23
49
  def self.generate_icon(icon_path:, output_folder:, types:, parallel_processes: nil, generate_icon: nil, progress: nil)
24
50
  if icon_path
25
- matches = /(\d+)x(\d+)/.match(`magick identify "#{icon_path}"`)
26
51
  raise 'There is no icon at the path specified.' unless File.exist?(icon_path)
27
52
 
28
53
  raise 'The icon specified must be .pdf.' if File.extname(icon_path) != '.pdf'
29
54
 
55
+ matches = /(\d+)x(\d+)/.match(`magick identify "#{icon_path}"`)
30
56
  raise 'Unable to verify icon. Please make sure it\'s a valid pdf file and try again.' if matches.nil?
31
57
 
32
58
  width, height = matches.captures
33
59
  raise 'Invalid pdf specified.' if width.nil? || height.nil?
34
60
 
35
61
  raise "The icon must at least be 1024x1024, it currently is #{width}x#{height}." unless width.to_i >= 1024 && height.to_i >= 1024
62
+ elsif generate_icon.nil?
63
+ raise 'icon_path has been set to nil, generate_icon must be specified'
36
64
  end
37
65
  appiconset_path = File.join(output_folder, "#{types.include?(:imessage) ? 'iMessage App Icon' : 'AppIcon'}.#{types.include?(:imessage) ? 'stickersiconset' : 'appiconset'}")
38
66
 
@@ -70,7 +98,7 @@ module IOSIconGenerator
70
98
  end
71
99
  end
72
100
 
73
- images_sets = Helpers.images_sets(types)
101
+ images_sets = Helpers.image_sets(types)
74
102
 
75
103
  smaller_sizes = []
76
104
  images_sets.each do |image|
@@ -130,9 +158,11 @@ module IOSIconGenerator
130
158
  },
131
159
  }
132
160
 
133
- File.write(File.join(appiconset_path, 'Contents.json'), JSON.generate(contents_json))
161
+ File.write(File.join(appiconset_path, 'Contents.json'), JSON.pretty_generate(contents_json))
134
162
 
135
163
  progress&.call(total - 1, total)
164
+
165
+ appiconset_path
136
166
  end
137
167
  end
138
168
  end
@@ -18,7 +18,15 @@ require 'json'
18
18
 
19
19
  module IOSIconGenerator
20
20
  module Helpers
21
- def self.images_sets(types)
21
+ ##
22
+ # Get the image sets for the given types.
23
+ #
24
+ # @param [Symbol, #read] types The types to return the sets of image for.
25
+ # This method won't fail if the types aren't compatible as defined by +type_incompatible?+
26
+ #
27
+ # @return [Array<Hash<String, String>>] The sets of image for the given types.
28
+ # Each hash will at least contain a +size+ [String] key, that has the format +<width>x<height>+
29
+ def self.image_sets(types)
22
30
  types.flat_map do |type|
23
31
  contents_path = File.expand_path(File.join(File.dirname(__FILE__), "../../../vendor/Contents-#{type}.json"))
24
32
  raise "Unknown type #{type}" unless File.exist?(contents_path)
@@ -28,8 +36,15 @@ module IOSIconGenerator
28
36
  end
29
37
  end
30
38
 
39
+ ##
40
+ # Check if the given types are compatible (if they can be used in the same set)
41
+ #
42
+ # @param [Symbol, #read] lhs The first type to check against the second type.
43
+ # @param [Symbol, #read] rhs The second type to check against the first type.
44
+ #
45
+ # @return [Boolean] +true+ if the given are compatible together, +false+ otherwise
31
46
  def self.type_incompatible?(lhs, rhs)
32
- (lhs == :imessage && rhs != :imessage || lhs != :imessage && rhs == :imessage)
47
+ (lhs == :imessage && rhs != :imessage) || (lhs != :imessage && rhs == :imessage)
33
48
  end
34
49
  end
35
50
  end
@@ -20,6 +20,39 @@ require 'fileutils'
20
20
 
21
21
  module IOSIconGenerator
22
22
  module Helpers
23
+ ##
24
+ # Mask an icon using the parameters provided.
25
+ #
26
+ # The mask is for now always generated in the bottom left corner of the image.
27
+ #
28
+ # @param [String, #read] appiconset_path The path of the original app icon set to use to generate the new one.
29
+ # @param [String, #read] output_folder The folder to create the new app icon set in.
30
+ # @param [Hash<String, Object>, #read] mask A hash representing parameters for creating the mask.
31
+ # The Hash may contain the following values:
32
+ # - +background_color+: The background color to use when generating the mask
33
+ # - +stroke_color+: The stroke color to use when generating the mask. Used for the outline of the mask.
34
+ # - +stroke_width_offset+: The stroke width of the mask, offset to the image's minimum dimension (width or height).
35
+ # 1.0 means the stroke will have the full width/height of the image
36
+ # - +suffix+: The suffix to use when generating the new mask
37
+ # - +file+: The file to use when generating the new mask. This file should be an image, and it will be overlayed over the background.
38
+ # - +symbol+: The symbol to use when generating the new mask
39
+ # - +symbol_color+: The color to use for the symbol
40
+ # - +font+: The font to use for the symbol
41
+ # - +x_size_ratio+: The size ratio (of the width of the image) to use when generating the mask. 1.0 means the full width, 0.5 means half-width.
42
+ # - +y_size_ratio+: The size ratio (of the height of the image) to use when generating the mask. 1.0 means the full height, 0.5 means half-height.
43
+ # - +size_offset+: The size ratio (of the width and height) to use when generating the symbol or file. 1.0 means the full width and height, 0.5 means half-width and half-height.
44
+ # - +x_offset+: The X offset (of the width of the image) to use when generating the symbol or file. 1.0 means the full width, 0.5 means half-width.
45
+ # - +y_offset+: The Y offset (of the width of the image) to use when generating the symbol or file. 1.0 means the full height, 0.5 means half-height.
46
+ # - +shape+: The shape to use when generating the mask. Can be either +:triangle+ or +:square+.
47
+ # @param [Symbol, #read] parallel_processes The number of processes to use when generating the icons.
48
+ # +nil+ means it'll use as many processes as they are cores on the machine.
49
+ # +0+ will disables spawning any processes.
50
+ # @param [Lambda(progress [Int], total [Int]), #read] progress An optional progress block called when progress has been made generating the icons.
51
+ # It should take two parameters:
52
+ # - +progress+: An integer indicating the current progress out of +total+
53
+ # - +total+: An integer indicating the total progress
54
+ #
55
+ # @return [String] Return the path to the generated app icon set.
23
56
  def self.mask_icon(
24
57
  appiconset_path:,
25
58
  output_folder:,
@@ -31,8 +64,8 @@ module IOSIconGenerator
31
64
  symbol: 'b',
32
65
  symbol_color: '#7F0000',
33
66
  font: 'Helvetica',
34
- x_size_ratio: 0.5478515625,
35
- y_size_ratio: 0.5478515625,
67
+ x_size_ratio: 0.54,
68
+ y_size_ratio: 0.54,
36
69
  size_offset: 0.0,
37
70
  x_offset: 0.0,
38
71
  y_offset: 0.0,
@@ -54,7 +87,8 @@ module IOSIconGenerator
54
87
  Parallel.each(
55
88
  json_content['images'],
56
89
  in_processes: parallel_processes,
57
- finish: lambda do |_item, i, _result|
90
+ finish: lambda do |_item, i, result|
91
+ json_content['images'][i]['filename'] = result
58
92
  progress&.call(i, json_content['images'].count)
59
93
  end
60
94
  ) do |image|
@@ -73,11 +107,13 @@ module IOSIconGenerator
73
107
  icon_output = "#{File.basename(image['filename'], extension)}-#{mask[:suffix]}#{extension}"
74
108
  icon_output_path = File.join(output_folder, icon_output)
75
109
 
76
- draw_shape_parameters = "-strokewidth '#{(mask[:stroke_width_offset] || 0) * [width, height].min}' -stroke '#{mask[:stroke_width_offset].zero? ? 'none' : (mask[:stroke_color] || '#000000')}' -fill '#{mask[:background_color] || '#FFFFFF'}'"
110
+ draw_shape_parameters = "-strokewidth '#{(mask[:stroke_width_offset] || 0) * [width, height].min}' \
111
+ -stroke '#{mask[:stroke_width_offset].zero? ? 'none' : (mask[:stroke_color] || '#000000')}' \
112
+ -fill '#{mask[:background_color] || '#FFFFFF'}'"
77
113
  draw_shape =
78
114
  case mask[:shape]
79
115
  when :triangle
80
- "-draw \"polyline 0,#{mask_size_height} 0,#{height} #{width - mask_size_width},#{height}\""
116
+ "-draw \"polyline -#{width},#{height - mask_size_height} 0,#{height - mask_size_height} #{mask_size_width},#{height} #{mask_size_width},#{height * 2.0} -#{width},#{height * 2.0}\""
81
117
  when :square
82
118
  "-draw \"rectangle -#{width},#{height * 2.0} #{mask_size_height},#{width - mask_size_width}\""
83
119
  else
@@ -86,16 +122,29 @@ module IOSIconGenerator
86
122
 
87
123
  draw_symbol =
88
124
  if mask[:file]
89
- "\\( -background none -density 1536 -resize #{width * mask[:size_offset]}x#{height} \"#{mask[:file]}\" -geometry +#{width * mask[:x_offset]}+#{height * mask[:y_offset]} \\) -gravity southwest -composite"
125
+ "\\( -background none \
126
+ -density 1536 \
127
+ -resize #{width * mask[:size_offset]}x#{height} \
128
+ \"#{mask[:file]}\" \
129
+ -geometry +#{width * mask[:x_offset]}+#{height * mask[:y_offset]} \\) \
130
+ -gravity southwest \
131
+ -composite"
90
132
  else
91
- "-strokewidth 0 -stroke none -fill '#{mask[:symbol_color] || '#7F0000'}' -font '#{mask[:font]}' -pointsize #{height * mask[:size_offset] * 2.0} -annotate +#{width * mask[:x_offset]}+#{height - height * mask[:y_offset]} '#{mask[:symbol]}'"
133
+ "-strokewidth 0 \
134
+ -stroke none \
135
+ -fill '#{mask[:symbol_color] || '#7F0000'}' \
136
+ -font '#{mask[:font]}' \
137
+ -pointsize #{height * mask[:size_offset] * 2.0} \
138
+ -annotate +#{width * mask[:x_offset]}+#{height - height * mask[:y_offset]} '#{mask[:symbol]}'"
92
139
  end
93
140
  system("convert '#{File.join(appiconset_path, image['filename'])}' #{draw_shape_parameters} #{draw_shape} #{draw_symbol} '#{icon_output_path}'")
94
141
 
95
- image['filename'] = icon_output
142
+ next icon_output
96
143
  end
97
144
 
98
- File.write(File.join(output_folder, 'Contents.json'), JSON.generate(json_content))
145
+ File.write(File.join(output_folder, 'Contents.json'), JSON.pretty_generate(json_content))
146
+
147
+ output_folder
99
148
  end
100
149
  end
101
150
  end
@@ -15,18 +15,15 @@
15
15
  # limitations under the License.
16
16
 
17
17
  module IOSIconGenerator
18
- module Library
18
+ module Helpers
19
19
  ##
20
20
  # Cross-platform way of finding an executable in the +$PATH+.
21
21
  #
22
22
  # From http://stackoverflow.com/questions/2108727/which-in-ruby-checking-if-program-exists-in-path-from-ruby
23
23
  #
24
- # == Parameters:
25
- # +cmd+::
26
- # The name of the command to search the path for.
24
+ # @param cmd [String] The name of the command to search the path for.
27
25
  #
28
- # == Returns:
29
- # The full path to the command if found, and +nil+ otherwise.
26
+ # @return [String] The full path to the command if found, and +nil+ otherwise.
30
27
  def self.which(cmd)
31
28
  exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
32
29
  ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
@@ -15,5 +15,8 @@
15
15
  # limitations under the License.
16
16
 
17
17
  module IOSIconGenerator
18
- VERSION = '0.1'
18
+ ##
19
+ # The current version of the gem.
20
+ #
21
+ VERSION = '0.1.1'
19
22
  end
@@ -21,8 +21,10 @@ require 'hanami/cli'
21
21
 
22
22
  # The IOSIconGenerator module
23
23
  module IOSIconGenerator
24
+ # @private
24
25
  # :nodoc:
25
26
  module CLI
27
+ # @private
26
28
  # :nodoc:
27
29
  module Commands
28
30
  extend Hanami::CLI::Registry
@@ -38,3 +40,4 @@ end
38
40
  require 'ios_icon_generator/cli/commands/generate'
39
41
  require 'ios_icon_generator/cli/commands/mask'
40
42
  require 'ios_icon_generator/cli/commands/stub'
43
+ require 'ios_icon_generator/cli/commands/version'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ios_icon_generator
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.1'
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stéphane Copin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-20 00:00:00.000000000 Z
11
+ date: 2019-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colored2
@@ -200,6 +200,7 @@ executables:
200
200
  extensions: []
201
201
  extra_rdoc_files: []
202
202
  files:
203
+ - ".yardopts"
203
204
  - LICENSE
204
205
  - README.md
205
206
  - bin/icongen
@@ -209,7 +210,7 @@ files:
209
210
  - lib/ios_icon_generator/cli/commands/stub.rb
210
211
  - lib/ios_icon_generator/cli/commands/version.rb
211
212
  - lib/ios_icon_generator/helpers/generate_icon.rb
212
- - lib/ios_icon_generator/helpers/images_sets_definition.rb
213
+ - lib/ios_icon_generator/helpers/image_sets_definition.rb
213
214
  - lib/ios_icon_generator/helpers/mask_icon.rb
214
215
  - lib/ios_icon_generator/helpers/which.rb
215
216
  - lib/ios_icon_generator/version.rb
@@ -222,7 +223,8 @@ files:
222
223
  homepage: https://github.com/Fueled/ios-icon-generator
223
224
  licenses:
224
225
  - Apache-2.0
225
- metadata: {}
226
+ metadata:
227
+ yard.run: yri
226
228
  post_install_message:
227
229
  rdoc_options: []
228
230
  require_paths: