# frozen_string_literal: true
require 'appiconset'
require 'json'
require 'rbconfig'
# Appiconset
module Appiconset
# Generator
class Generator
def initialize; end
def config(input, output)
raise 'no input file.' unless File.exist?(input)
raise 'no output
.' if output == ''
size = FastImage.size(input)
raise 'Unsupported file.' if size.nil?
@width = size[0]
@height = size[1]
output += '/' unless output.end_with?('/')
FileUtils.mkdir_p(output) unless FileTest.exist?(output)
@input = input
@output = output
end
# 正方形アイコン
def square_platforms
return unless size_match?([1024, 1024])
show_info('square')
json_dir = "#{__dir__}/settings/*.json"
Dir.glob(json_dir).each do |path|
json_data = File.open(path) do |f|
JSON.parse(f.read)
end
# プラットフォームごとのディレクトリ
platform = File.basename(path).gsub('-Contents.json', '')
output_dir = "#{@output}#{platform}/"
FileUtils.mkdir_p(output_dir)
json_data['images'].each do |image|
size = image['size'].match(/(.*?)x/)[1].to_f
scale = image['scale'].gsub('x', '').to_i
# 実際のサイズ
real_size = size * scale
name = image['filename']
image = Magick::ImageList.new(@input)
new_image = image.resize_to_fit(real_size, real_size)
new_image.format = 'PNG'
new_image.write(output_dir + name)
end
# Xcode用にファイルをコピーする
begin
FileUtils.cp(path, "#{output_dir}/Contents.json") if json_data['info']['author'] == 'xcode'
rescue StandardError
# none
end
end
end
# rubocop:todo Metrics/PerceivedComplexity
# rubocop:todo Metrics/AbcSize
def any_platforms # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/PerceivedComplexity
platforms = [
{
name: 'universal',
size: [0, 0],
contents: [
{ width: @width, height: @height, name: 'Icon@3x.png' },
{ width: @width / 3 * 2, height: @height / 3 * 2, name: 'Icon@2x.png' },
{ width: @width / 3, height: @height / 3, name: 'Icon@1x.png' }
]
},
{
name: 'tv',
size: [4640, 1440],
contents: [
{ width: 800, height: 480, name: 'Icon@2x.png' },
{ width: 400, height: 240, name: 'Icon@1x.png' }
]
},
{
name: 'tv-top-shelf',
size: [4640, 1440],
contents: [
{ width: 3840, height: 1440, name: 'Icon@2x.png' },
{ width: 1920, height: 720, name: 'Icon@1x.png' }
]
},
{
name: 'tv-top-shelf-wide',
size: [4640, 1440],
contents: [
{ width: 4640, height: 1440, name: 'Icon@2x.png' },
{ width: 2320, height: 720, name: 'Icon@1x.png' }
]
},
{
name: 'icns.iconset',
size: [1024, 1024],
contents: [
{ width: 1024, height: 1024, name: 'icon_512x512@2x.png' },
{ width: 512, height: 512, name: 'icon_512x512.png' },
{ width: 512, height: 512, name: 'icon_256x256@2x.png' },
{ width: 256, height: 256, name: 'icon_256x256.png' },
{ width: 256, height: 256, name: 'icon_128x128@2x.png' },
{ width: 128, height: 128, name: 'icon_128x128.png' },
{ width: 128, height: 128, name: 'icon_64x64@2x.png' },
{ width: 64, height: 64, name: 'icon_64x64.png' },
{ width: 64, height: 64, name: 'icon_32x32@2x.png' },
{ width: 32, height: 32, name: 'icon_32x32.png' },
{ width: 32, height: 32, name: 'icon_16x16@2x.png' },
{ width: 16, height: 16, name: 'icon_16x16.png' }
]
},
{
name: 'favicon',
size: [1024, 1024],
contents: [
{ width: 256, height: 256, name: 'icon_256x256.png' },
{ width: 128, height: 128, name: 'icon_128x128.png' },
{ width: 64, height: 64, name: 'icon_64x64.png' },
{ width: 48, height: 48, name: 'icon_48x48.png' },
{ width: 32, height: 32, name: 'icon_32x32.png' },
{ width: 24, height: 24, name: 'icon_24x24.png' },
{ width: 16, height: 16, name: 'icon_16x16.png' }
]
}
]
platforms.each do |platform|
platform_name = platform[:name]
next unless size_match?(platform[:size])
show_info(platform_name)
output_dir = "#{@output}#{platform_name}/"
FileUtils.mkdir_p(output_dir)
platform[:contents].each do |content|
width = content[:width].to_f
height = content[:height].to_f
name = content[:name]
image = Magick::ImageList.new(@input)
if platform_name.start_with?('tv')
image = image.scale(height / 1440.0)
image = image.crop(Magick::CenterGravity, width, height)
else
image = image.resize_to_fit(width, height)
end
image.format = 'PNG'
image.write(output_dir + name)
end
if platform_name == 'icns.iconset' && RbConfig::CONFIG['host_os'].match(/darwin|mac os/)
# macOSで実行可能
show_info('icns')
system("iconutil -c icns --output #{@output}Icon.icns #{@output}icns.iconset/")
elsif platform_name == 'favicon'
images = platforms.find do |x|
x[:name] == 'favicon'
end[:contents].map do |x| # rubocop:disable Style/MultilineBlockChain
"#{output_dir}#{x[:name]}"
end
image = Magick::ImageList.new(*images)
image.format = 'ICO'
image.write("#{@output}favicon/favicon.ico")
end
end
end
# rubocop:enable Metrics/AbcSize
# rubocop:enable Metrics/PerceivedComplexity
private
# 入力画像のサイズが条件に一致したときtrueを返す
def size_match?(size)
size == [0, 0] || (@width == size[0] && @height == size[1])
end
def show_info(platform_name)
puts "Created #{platform_name} icon(s) from #{@width} x #{@height} image."
end
end
end