sprite-factory 1.0.0 → 1.2.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.
- data/.gitignore +10 -0
- data/README.md +39 -31
- data/Rakefile +2 -0
- data/bin/sf +3 -2
- data/lib/sprite_factory.rb +25 -3
- data/lib/sprite_factory/layout/horizontal.rb +42 -0
- data/lib/sprite_factory/layout/packed.rb +107 -0
- data/lib/sprite_factory/layout/vertical.rb +42 -0
- data/lib/sprite_factory/runner.rb +20 -1
- data/sprite_factory.gemspec +5 -1
- data/test/images/reference/index.html +16 -0
- data/test/images/reference/irregular.packed.css +24 -0
- data/test/images/reference/irregular.packed.png +0 -0
- data/test/images/reference/regular.packed.css +24 -0
- data/test/images/reference/regular.packed.png +0 -0
- data/test/integration_test.rb +12 -0
- data/test/layout/horizontal_test.rb +100 -0
- data/test/layout/packed_test.rb +221 -0
- data/test/layout/test_case.rb +56 -0
- data/test/layout/vertical_test.rb +100 -0
- data/test/test_case.rb +7 -0
- metadata +19 -9
- data/lib/sprite_factory/layout.rb +0 -89
- data/test/layout_test.rb +0 -228
data/.gitignore
ADDED
data/README.md
CHANGED
@@ -12,6 +12,7 @@ The library provides:
|
|
12
12
|
* many customizable options
|
13
13
|
* support for any stylesheet syntax, including [CSS](http://www.w3.org/Style/CSS/) and [Sass](http://sass-lang.com/).
|
14
14
|
* support for any image library, including [RMagick](http://rmagick.rubyforge.org/) and [ChunkyPNG](https://github.com/wvanbergen/chunky_png).
|
15
|
+
* support for pngcrush'n the generated image file
|
15
16
|
|
16
17
|
|
17
18
|
Installation
|
@@ -20,11 +21,18 @@ Installation
|
|
20
21
|
$ gem install sprite-factory
|
21
22
|
|
22
23
|
An image library is also required. SpriteFactory comes with built in support for
|
23
|
-
[RMagick](http://rmagick.rubyforge.org/) or
|
24
|
-
[ChunkyPng](https://github.com/wvanbergen/chunky_png) and is easily extensible to
|
25
|
-
use any image library of your choice.
|
24
|
+
[RMagick](http://rmagick.rubyforge.org/) or [ChunkyPng](https://github.com/wvanbergen/chunky_png).
|
26
25
|
|
27
|
-
|
26
|
+
RMagick is the most common image libary to use, installation instructions for ubuntu:
|
27
|
+
|
28
|
+
$ sudo aptitude install imageMagick libMagickWand-dev
|
29
|
+
$ sudo gem install rmagick
|
30
|
+
|
31
|
+
ChunkyPng is lighter weight but only supports .png format:
|
32
|
+
|
33
|
+
$ gem install chunky_png
|
34
|
+
|
35
|
+
SpriteFactory can also be easily extended to use the image library of your choice.
|
28
36
|
|
29
37
|
Usage
|
30
38
|
=====
|
@@ -62,7 +70,7 @@ Customization
|
|
62
70
|
Much of the behavior can be customized by overriding the following options:
|
63
71
|
|
64
72
|
- `:output` - specify output location for generated files
|
65
|
-
- `:layout` - specify layout algorithm (horizontal or
|
73
|
+
- `:layout` - specify layout algorithm (horizontal, vertical or packed)
|
66
74
|
- `:style` - specify output style (css or sass)
|
67
75
|
- `:library` - specify image library to use (rmagick or chunkypng)
|
68
76
|
- `:selector` - specify custom css selector (see below)
|
@@ -70,18 +78,32 @@ Much of the behavior can be customized by overriding the following options:
|
|
70
78
|
- `:padding` - add padding to each sprite
|
71
79
|
- `:width` - fix width of each sprite to a specific size
|
72
80
|
- `:height` - fix height of each sprite to a specific size
|
81
|
+
- `:pngcrush` - pngcrush the generated output image (if pngcrush is available)
|
73
82
|
|
74
83
|
Options can be passed as command line arguments to the `sf` script:
|
75
84
|
|
76
|
-
$ sf images/icons --style sass --layout
|
85
|
+
$ sf images/icons --style sass --layout packed
|
77
86
|
|
78
87
|
Options can also be passed as the 2nd argument to the `#run!` method:
|
79
88
|
|
80
|
-
SpriteFactory.run!('images/icons', :style => :sass, :layout => :
|
89
|
+
SpriteFactory.run!('images/icons', :style => :sass, :layout => :packed)
|
81
90
|
|
82
91
|
You can see the results of many of these options by viewing the sample page that
|
83
92
|
comes with the gem in `test/images/reference/index.html`.
|
84
93
|
|
94
|
+
Layout
|
95
|
+
======
|
96
|
+
|
97
|
+
The generated image can be laid out in a horizontal or a vertical strip by
|
98
|
+
providing a `:layout` option (defaults to horizontal). A **new option in v1.2.0** is
|
99
|
+
to use a **:packed** layout which will attempt to generate an optimized packed
|
100
|
+
square-ish layout.
|
101
|
+
|
102
|
+
For more details on the bin-packing algorithm used:
|
103
|
+
|
104
|
+
* You can find a [description here](http://codeincomplete.com/posts/2011/5/7/bin_packing/)
|
105
|
+
* You can find a [demo here](http://codeincomplete.com/posts/2011/5/7/bin_packing/example/)
|
106
|
+
|
85
107
|
Customizing the CSS Selector
|
86
108
|
============================
|
87
109
|
|
@@ -113,7 +135,7 @@ building a Ruby on Rails application you might need to generate URL's using the
|
|
113
135
|
helper method to ensure it gets the appopriate cache-busting query parameter.
|
114
136
|
|
115
137
|
By default, the SpriteFactory generates simple url's that contain only the basename of the
|
116
|
-
unified sprite image, but you can control the generation of these url's using the
|
138
|
+
unified sprite image, but you can control the generation of these url's using the `:csspath`
|
117
139
|
option:
|
118
140
|
|
119
141
|
For most CDN's, you can prepend a simple string to the image name:
|
@@ -171,37 +193,23 @@ The sprite factory library can also be extended in a number of other ways.
|
|
171
193
|
|
172
194
|
_(see existing code for examples of each)._
|
173
195
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
SpriteFactory comes with built in support for
|
178
|
-
[RMagick](http://rmagick.rubyforge.org/) or
|
179
|
-
[ChunkyPng](https://github.com/wvanbergen/chunky_png)
|
180
|
-
|
181
|
-
RMagick is the most flexible image libary to use, but requires ImageMagick
|
182
|
-
binaries, installation instructions for ubuntu:
|
183
|
-
|
184
|
-
$ sudo aptitude install imageMagick libMagickWand-dev
|
185
|
-
$ sudo gem install rmagick
|
186
|
-
|
187
|
-
ChunkyPng is lighter weight and has no binary requirements, but only supports
|
188
|
-
.png format. Installation is a simple gem install:
|
189
|
-
|
190
|
-
$ gem install chunky_png
|
196
|
+
License
|
197
|
+
=======
|
191
198
|
|
192
|
-
|
199
|
+
See [LICENSE](https://github.com/jakesgordon/sprite-factory/blob/master/LICENSE) file.
|
193
200
|
|
194
|
-
|
201
|
+
Credits
|
195
202
|
=======
|
196
203
|
|
197
|
-
|
204
|
+
Thanks to my employer, [LiquidPlanner](http://liquidplanner.com) for allowing me to take this idea from our
|
205
|
+
online project management web application and release it into the wild.
|
198
206
|
|
199
207
|
Contact
|
200
208
|
=======
|
201
209
|
|
202
|
-
|
203
|
-
|
204
|
-
|
210
|
+
If you have any ideas, feedback, requests or bug reports, you can reach me at
|
211
|
+
[jake@codeincomplete.com](mailto:jake@codeincomplete.com), or via
|
212
|
+
my website: [Code inComplete](http://codeincomplete.com/posts/2011/4/29/sprite_factory/).
|
205
213
|
|
206
214
|
|
207
215
|
|
data/Rakefile
CHANGED
@@ -31,6 +31,7 @@ task :reference do
|
|
31
31
|
regenerate.call('test/images/regular')
|
32
32
|
regenerate.call('test/images/regular', :output => 'test/images/regular.horizontal', :selector => 'img.horizontal_', :layout => :horizontal)
|
33
33
|
regenerate.call('test/images/regular', :output => 'test/images/regular.vertical', :selector => 'img.vertical_', :layout => :vertical)
|
34
|
+
regenerate.call('test/images/regular', :output => 'test/images/regular.packed', :selector => 'img.packed_', :layout => :packed)
|
34
35
|
regenerate.call('test/images/regular', :output => 'test/images/regular.padded', :selector => 'img.padded_', :padding => 10)
|
35
36
|
regenerate.call('test/images/regular', :output => 'test/images/regular.fixed', :selector => 'img.fixed_', :width => 100, :height => 100)
|
36
37
|
regenerate.call('test/images/regular', :output => 'test/images/regular.sassy', :selector => 'img.sassy_', :style => :sass)
|
@@ -38,6 +39,7 @@ task :reference do
|
|
38
39
|
regenerate.call('test/images/irregular')
|
39
40
|
regenerate.call('test/images/irregular', :output => 'test/images/irregular.horizontal', :selector => 'img.horizontal_', :layout => :horizontal)
|
40
41
|
regenerate.call('test/images/irregular', :output => 'test/images/irregular.vertical', :selector => 'img.vertical_', :layout => :vertical)
|
42
|
+
regenerate.call('test/images/irregular', :output => 'test/images/irregular.packed', :selector => 'img.packed_', :layout => :packed)
|
41
43
|
regenerate.call('test/images/irregular', :output => 'test/images/irregular.padded', :selector => 'img.padded_', :padding => 10)
|
42
44
|
regenerate.call('test/images/irregular', :output => 'test/images/irregular.fixed', :selector => 'img.fixed_', :width => 100, :height => 100)
|
43
45
|
regenerate.call('test/images/irregular', :output => 'test/images/irregular.sassy', :selector => 'img.sassy_', :style => :sass)
|
data/bin/sf
CHANGED
@@ -20,11 +20,12 @@ op.on("-v", "--version") do
|
|
20
20
|
end
|
21
21
|
|
22
22
|
output_help = "specify output location, without any extension"
|
23
|
-
layout_help = "specify layout orientation ( horizontal, vertical )"
|
23
|
+
layout_help = "specify layout orientation ( horizontal, vertical, packed )"
|
24
24
|
style_help = "specify output style format ( css, sass )"
|
25
25
|
library_help = "specify image library to use ( rmagic, chunkypng )"
|
26
26
|
selector_help = "specify custom selector to use for each css rule ( default: 'img.' )"
|
27
27
|
csspath_help = "specify custom path to use for css image urls ( default: output file's basename )"
|
28
|
+
pngcrush_help = "use pngcrush to optimize generated image"
|
28
29
|
|
29
30
|
op.on("--output [PATH]", output_help) {|value| options[:output] = value }
|
30
31
|
op.on("--layout [ORIENTATION]", layout_help) {|value| options[:layout] = value }
|
@@ -32,6 +33,7 @@ op.on("--style [STYLE]", style_help) {|value| options[:style] = v
|
|
32
33
|
op.on("--library [LIBRARY]", library_help) {|value| options[:library] = value }
|
33
34
|
op.on("--selector [SELECTOR]", selector_help) {|value| options[:selector] = value }
|
34
35
|
op.on("--csspath [CSSPATH]", csspath_help) {|value| options[:csspath] = value }
|
36
|
+
op.on("--pngcrush", pngcrush_help) {|value| options[:pngcrush] = value }
|
35
37
|
|
36
38
|
begin
|
37
39
|
op.parse!(ARGV)
|
@@ -39,7 +41,6 @@ begin
|
|
39
41
|
SpriteFactory.run!(ARGV[0], options)
|
40
42
|
rescue Exception => ex
|
41
43
|
puts ex.message
|
42
|
-
puts op.to_s
|
43
44
|
exit
|
44
45
|
end
|
45
46
|
|
data/lib/sprite_factory.rb
CHANGED
@@ -2,14 +2,13 @@ module SpriteFactory
|
|
2
2
|
|
3
3
|
#----------------------------------------------------------------------------
|
4
4
|
|
5
|
-
VERSION = "1.
|
5
|
+
VERSION = "1.2.0"
|
6
6
|
SUMMARY = "Automatic CSS sprite generator"
|
7
7
|
DESCRIPTION = "Combines individual images from a directory into a single sprite image file and creates an appropriate CSS stylesheet"
|
8
8
|
LIB = File.dirname(__FILE__)
|
9
9
|
|
10
10
|
autoload :Runner, File.join(LIB, 'sprite_factory/runner') # controller that glues everything together
|
11
|
-
autoload :
|
12
|
-
autoload :Style, File.join(LIB, 'sprite_factory/style') # style generators
|
11
|
+
autoload :Style, File.join(LIB, 'sprite_factory/style') # style generators all live in a single module (for now)
|
13
12
|
|
14
13
|
def self.run!(input, config = {}, &block)
|
15
14
|
Runner.new(input, config).run!(&block)
|
@@ -26,6 +25,29 @@ module SpriteFactory
|
|
26
25
|
attr_accessor :library
|
27
26
|
attr_accessor :selector
|
28
27
|
attr_accessor :csspath
|
28
|
+
attr_accessor :pngcrush
|
29
|
+
end
|
30
|
+
|
31
|
+
#----------------------------------------------------------------------------
|
32
|
+
|
33
|
+
module Layout # abstract module for various layout strategies
|
34
|
+
|
35
|
+
autoload :Horizontal, File.join(LIB, 'sprite_factory/layout/horizontal') # concrete module for layout in a single horizontal strip
|
36
|
+
autoload :Vertical, File.join(LIB, 'sprite_factory/layout/vertical') # concrete module for layout in a single vertical strip
|
37
|
+
autoload :Packed, File.join(LIB, 'sprite_factory/layout/packed') # concrete module for layout in a bin-packed square
|
38
|
+
|
39
|
+
def self.horizontal
|
40
|
+
Horizontal
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.vertical
|
44
|
+
Vertical
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.packed
|
48
|
+
Packed
|
49
|
+
end
|
50
|
+
|
29
51
|
end
|
30
52
|
|
31
53
|
#----------------------------------------------------------------------------
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module SpriteFactory
|
2
|
+
module Layout
|
3
|
+
module Horizontal
|
4
|
+
|
5
|
+
def self.layout(images, options = {})
|
6
|
+
width = options[:width]
|
7
|
+
height = options[:height]
|
8
|
+
hpadding = options[:hpadding] || 0
|
9
|
+
vpadding = options[:vpadding] || 0
|
10
|
+
max_height = height || ((2 * vpadding) + images.map{|i| i[:height]}.max)
|
11
|
+
x = 0
|
12
|
+
images.each do |i|
|
13
|
+
|
14
|
+
if width
|
15
|
+
i[:cssw] = width
|
16
|
+
i[:cssx] = x
|
17
|
+
i[:x] = x + (width - i[:width]) / 2
|
18
|
+
else
|
19
|
+
i[:cssw] = i[:width] + (2 * hpadding) # image width plus padding
|
20
|
+
i[:cssx] = x # anchored at x
|
21
|
+
i[:x] = i[:cssx] + hpadding # image drawn offset to account for padding
|
22
|
+
end
|
23
|
+
|
24
|
+
if height
|
25
|
+
i[:cssh] = height
|
26
|
+
i[:cssy] = 0
|
27
|
+
i[:y] = 0 + (height - i[:height]) / 2
|
28
|
+
else
|
29
|
+
i[:cssh] = i[:height] + (2 * vpadding) # image height plus padding
|
30
|
+
i[:cssy] = (max_height - i[:cssh]) / 2 # centered vertically
|
31
|
+
i[:y] = i[:cssy] + vpadding # image drawn offset to account for padding
|
32
|
+
end
|
33
|
+
|
34
|
+
x = x + i[:cssw]
|
35
|
+
|
36
|
+
end
|
37
|
+
{ :width => x, :height => max_height }
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module SpriteFactory
|
2
|
+
module Layout
|
3
|
+
module Packed
|
4
|
+
|
5
|
+
#------------------------------------------------------------------------
|
6
|
+
|
7
|
+
def self.layout(images, options = {})
|
8
|
+
|
9
|
+
raise NotImplementedError, ":packed layout does not support the :padding option" if (options[:padding].to_i > 0) || (options[:hpadding].to_i > 0) || (options[:vpadding].to_i > 0)
|
10
|
+
raise NotImplementedError, ":packed layout does not support fixed :width/:height option" if options[:width] || options[:height]
|
11
|
+
|
12
|
+
return { :width => 0, :height => 0 } if images.empty?
|
13
|
+
|
14
|
+
images.sort! do |a,b|
|
15
|
+
diff = [b[:width], b[:height]].max <=> [a[:width], a[:height]].max
|
16
|
+
diff = [b[:width], b[:height]].min <=> [a[:width], a[:height]].min if diff.zero?
|
17
|
+
diff = b[:height] <=> a[:height] if diff.zero?
|
18
|
+
diff = b[:width] <=> a[:width] if diff.zero?
|
19
|
+
diff
|
20
|
+
end
|
21
|
+
|
22
|
+
root = { :x => 0, :y => 0, :w => images[0][:width], :h => images[0][:height] }
|
23
|
+
|
24
|
+
images.each do |i|
|
25
|
+
if (node = findNode(root, i[:width], i[:height]))
|
26
|
+
placeImage(i, node)
|
27
|
+
splitNode(node, i[:width], i[:height])
|
28
|
+
else
|
29
|
+
root = grow(root, i[:width], i[:height])
|
30
|
+
redo
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
{ :width => root[:w], :height => root[:h] }
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.placeImage(image, node)
|
39
|
+
image[:cssx] = image[:x] = node[:x] # TODO
|
40
|
+
image[:cssy] = image[:y] = node[:y] # * support for :padding option
|
41
|
+
image[:cssw] = image[:width] # * support for fixed :width/:height option
|
42
|
+
image[:cssh] = image[:height]
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.findNode(root, w, h)
|
46
|
+
if root[:used]
|
47
|
+
findNode(root[:right], w, h) || findNode(root[:down], w, h)
|
48
|
+
elsif (w <= root[:w]) && (h <= root[:h])
|
49
|
+
root
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.splitNode(node, w, h)
|
54
|
+
node[:used] = true
|
55
|
+
node[:down] = { :x => node[:x], :y => node[:y] + h, :w => node[:w], :h => node[:h] - h }
|
56
|
+
node[:right] = { :x => node[:x] + w, :y => node[:y], :w => node[:w] - w, :h => h }
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.grow(root, w, h)
|
60
|
+
|
61
|
+
canGrowDown = (w <= root[:w])
|
62
|
+
canGrowRight = (h <= root[:h])
|
63
|
+
|
64
|
+
shouldGrowRight = canGrowRight && (root[:h] >= (root[:w] + w))
|
65
|
+
shouldGrowDown = canGrowDown && (root[:w] >= (root[:h] + h))
|
66
|
+
|
67
|
+
if shouldGrowRight
|
68
|
+
growRight(root, w, h)
|
69
|
+
elsif shouldGrowDown
|
70
|
+
growDown(root, w, h)
|
71
|
+
elsif canGrowRight
|
72
|
+
growRight(root, w, h)
|
73
|
+
elsif canGrowDown
|
74
|
+
growDown(root, w, h)
|
75
|
+
else
|
76
|
+
raise RuntimeError, "can't fit #{w}x#{h} block into root #{root[:w]}x#{root[:h]} - this should not happen if images are pre-sorted correctly"
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.growRight(root, w, h)
|
82
|
+
return {
|
83
|
+
:used => true,
|
84
|
+
:x => 0,
|
85
|
+
:y => 0,
|
86
|
+
:w => root[:w] + w,
|
87
|
+
:h => root[:h],
|
88
|
+
:down => root,
|
89
|
+
:right => { :x => root[:w], :y => 0, :w => w, :h => root[:h] }
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.growDown(root, w, h)
|
94
|
+
return {
|
95
|
+
:used => true,
|
96
|
+
:x => 0,
|
97
|
+
:y => 0,
|
98
|
+
:w => root[:w],
|
99
|
+
:h => root[:h] + h,
|
100
|
+
:down => { :x => 0, :y => root[:h], :w => root[:w], :h => h },
|
101
|
+
:right => root
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
end # module Packed
|
106
|
+
end # module Layout
|
107
|
+
end # module SpriteFactory
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module SpriteFactory
|
2
|
+
module Layout
|
3
|
+
module Vertical
|
4
|
+
|
5
|
+
def self.layout(images, options = {})
|
6
|
+
width = options[:width]
|
7
|
+
height = options[:height]
|
8
|
+
hpadding = options[:hpadding] || 0
|
9
|
+
vpadding = options[:vpadding] || 0
|
10
|
+
max_width = width || ((2 * hpadding) + images.map{|i| i[:width]}.max)
|
11
|
+
y = 0
|
12
|
+
images.each do |i|
|
13
|
+
|
14
|
+
if width
|
15
|
+
i[:cssw] = width
|
16
|
+
i[:cssx] = 0
|
17
|
+
i[:x] = 0 + (width - i[:width]) / 2
|
18
|
+
else
|
19
|
+
i[:cssw] = i[:width] + (2 * hpadding) # image width plus padding
|
20
|
+
i[:cssx] = (max_width - i[:cssw]) / 2 # centered horizontally
|
21
|
+
i[:x] = i[:cssx] + hpadding # image drawn offset to account for padding
|
22
|
+
end
|
23
|
+
|
24
|
+
if height
|
25
|
+
i[:cssh] = height
|
26
|
+
i[:cssy] = y
|
27
|
+
i[:y] = y + (height - i[:height]) / 2
|
28
|
+
else
|
29
|
+
i[:cssh] = i[:height] + (2 * vpadding) # image height plus padding
|
30
|
+
i[:cssy] = y # anchored at y
|
31
|
+
i[:y] = i[:cssy] + vpadding # image drawn offset to account for padding
|
32
|
+
end
|
33
|
+
|
34
|
+
y = y + i[:cssh]
|
35
|
+
|
36
|
+
end
|
37
|
+
{ :width => max_width, :height => y }
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'pathname'
|
2
|
+
require 'fileutils'
|
2
3
|
|
3
4
|
module SpriteFactory
|
4
5
|
class Runner
|
@@ -17,6 +18,7 @@ module SpriteFactory
|
|
17
18
|
@config[:selector] ||= SpriteFactory.selector || 'img.'
|
18
19
|
@config[:csspath] ||= SpriteFactory.csspath
|
19
20
|
@config[:report] ||= SpriteFactory.report
|
21
|
+
@config[:pngcrush] ||= SpriteFactory.pngcrush
|
20
22
|
end
|
21
23
|
|
22
24
|
#----------------------------------------------------------------------------
|
@@ -146,12 +148,17 @@ module SpriteFactory
|
|
146
148
|
|
147
149
|
def create_sprite(images, width, height)
|
148
150
|
library.create(output_image_file, images, width, height)
|
151
|
+
pngcrush(output_image_file)
|
149
152
|
end
|
150
153
|
|
151
154
|
#----------------------------------------------------------------------------
|
152
155
|
|
156
|
+
def layout_strategy
|
157
|
+
@layout_strategy ||= Layout.send(layout_name)
|
158
|
+
end
|
159
|
+
|
153
160
|
def layout_images(images)
|
154
|
-
|
161
|
+
layout_strategy.layout(images, :width => width, :height => height, :hpadding => hpadding, :vpadding => vpadding)
|
155
162
|
end
|
156
163
|
|
157
164
|
#----------------------------------------------------------------------------
|
@@ -171,6 +178,18 @@ module SpriteFactory
|
|
171
178
|
|
172
179
|
#----------------------------------------------------------------------------
|
173
180
|
|
181
|
+
SUPPORTS_PNGCRUSH = !`which pngcrush`.empty?
|
182
|
+
|
183
|
+
def pngcrush(image)
|
184
|
+
if SUPPORTS_PNGCRUSH && config[:pngcrush]
|
185
|
+
crushed = "#{image}.crushed"
|
186
|
+
`pngcrush -rem alla -reduce -brute #{image} #{crushed}`
|
187
|
+
FileUtils.mv(crushed, image)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
#----------------------------------------------------------------------------
|
192
|
+
|
174
193
|
def summary(images, max)
|
175
194
|
return <<-EOF
|
176
195
|
|