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.
@@ -16,7 +16,11 @@ Gem::Specification.new do |s|
16
16
  s.add_development_dependency 'rmagick'
17
17
  s.add_development_dependency 'chunky_png'
18
18
 
19
- s.files = `git ls-files`.split("\n")
19
+ s.has_rdoc = false
20
+ s.extra_rdoc_files = ["README.md"]
21
+ s.rdoc_options = ["--charset=UTF-8"]
22
+
23
+ s.files = `git ls-files `.split("\n")
20
24
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
25
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
26
  s.require_paths = ["lib"]
@@ -6,12 +6,14 @@
6
6
  <link href='regular.css' rel='stylesheet' type='text/css' media='screen'></link>
7
7
  <link href='regular.horizontal.css' rel='stylesheet' type='text/css' media='screen'></link>
8
8
  <link href='regular.vertical.css' rel='stylesheet' type='text/css' media='screen'></link>
9
+ <link href='regular.packed.css' rel='stylesheet' type='text/css' media='screen'></link>
9
10
  <link href='regular.padded.css' rel='stylesheet' type='text/css' media='screen'></link>
10
11
  <link href='regular.fixed.css' rel='stylesheet' type='text/css' media='screen'></link>
11
12
  <link href='regular.sassy.css' rel='stylesheet' type='text/css' media='screen'></link>
12
13
  <link href='irregular.css' rel='stylesheet' type='text/css' media='screen'></link>
13
14
  <link href='irregular.horizontal.css' rel='stylesheet' type='text/css' media='screen'></link>
14
15
  <link href='irregular.vertical.css' rel='stylesheet' type='text/css' media='screen'></link>
16
+ <link href='irregular.packed.css' rel='stylesheet' type='text/css' media='screen'></link>
15
17
  <link href='irregular.padded.css' rel='stylesheet' type='text/css' media='screen'></link>
16
18
  <link href='irregular.fixed.css' rel='stylesheet' type='text/css' media='screen'></link>
17
19
  <link href='irregular.sassy.css' rel='stylesheet' type='text/css' media='screen'></link>
@@ -44,6 +46,13 @@
44
46
  <img src='s.gif' class='vertical_regular4'><br>
45
47
  <img src='s.gif' class='vertical_regular5'><br>
46
48
 
49
+ <h1>Regular (packed)</h1>
50
+ <img src='s.gif' class='packed_regular1'>
51
+ <img src='s.gif' class='packed_regular2'>
52
+ <img src='s.gif' class='packed_regular3'>
53
+ <img src='s.gif' class='packed_regular4'>
54
+ <img src='s.gif' class='packed_regular5'>
55
+
47
56
  <h1>Regular (padded)</h1>
48
57
  <img src='s.gif' class='padded_regular1'>
49
58
  <img src='s.gif' class='padded_regular2'>
@@ -86,6 +95,13 @@
86
95
  <img src='s.gif' class='vertical_irregular4'><br>
87
96
  <img src='s.gif' class='vertical_irregular5'><br>
88
97
 
98
+ <h1>Irregular (packed)</h1>
99
+ <img src='s.gif' class='packed_irregular1'>
100
+ <img src='s.gif' class='packed_irregular2'>
101
+ <img src='s.gif' class='packed_irregular3'>
102
+ <img src='s.gif' class='packed_irregular4'>
103
+ <img src='s.gif' class='packed_irregular5'>
104
+
89
105
  <h1>Irregular (padded)</h1>
90
106
  <img src='s.gif' class='padded_irregular1'>
91
107
  <img src='s.gif' class='padded_irregular2'>
@@ -0,0 +1,24 @@
1
+ /*
2
+
3
+ Creating a sprite from following images:
4
+
5
+ test/images/irregular/irregular1.png (60x60)
6
+ test/images/irregular/irregular3.png (48x48)
7
+ test/images/irregular/irregular5.png (46x25)
8
+ test/images/irregular/irregular4.png (34x14)
9
+ test/images/irregular/irregular2.png (16x16)
10
+
11
+ Output files:
12
+ test/images/irregular.packed.png
13
+ test/images/irregular.packed.css
14
+
15
+ Output size:
16
+ 108x101
17
+
18
+
19
+ */
20
+ img.packed_irregular1 { width: 60px; height: 60px; background: url(irregular.packed.png) 0px 0px no-repeat; }
21
+ img.packed_irregular3 { width: 48px; height: 48px; background: url(irregular.packed.png) -60px 0px no-repeat; }
22
+ img.packed_irregular5 { width: 46px; height: 25px; background: url(irregular.packed.png) 0px -60px no-repeat; }
23
+ img.packed_irregular4 { width: 34px; height: 14px; background: url(irregular.packed.png) -46px -60px no-repeat; }
24
+ img.packed_irregular2 { width: 16px; height: 16px; background: url(irregular.packed.png) 0px -85px no-repeat; }
@@ -0,0 +1,24 @@
1
+ /*
2
+
3
+ Creating a sprite from following images:
4
+
5
+ test/images/regular/regular1.png (64x64)
6
+ test/images/regular/regular2.png (64x64)
7
+ test/images/regular/regular3.png (64x64)
8
+ test/images/regular/regular4.png (64x64)
9
+ test/images/regular/regular5.png (64x64)
10
+
11
+ Output files:
12
+ test/images/regular.packed.png
13
+ test/images/regular.packed.css
14
+
15
+ Output size:
16
+ 192x128
17
+
18
+
19
+ */
20
+ img.packed_regular1 { width: 64px; height: 64px; background: url(regular.packed.png) 0px 0px no-repeat; }
21
+ img.packed_regular2 { width: 64px; height: 64px; background: url(regular.packed.png) -64px 0px no-repeat; }
22
+ img.packed_regular3 { width: 64px; height: 64px; background: url(regular.packed.png) 0px -64px no-repeat; }
23
+ img.packed_regular4 { width: 64px; height: 64px; background: url(regular.packed.png) -64px -64px no-repeat; }
24
+ img.packed_regular5 { width: 64px; height: 64px; background: url(regular.packed.png) -128px 0px no-repeat; }
@@ -21,6 +21,12 @@ module SpriteFactory
21
21
  :layout => :vertical)
22
22
  end
23
23
 
24
+ def test_generate_packed_regular_sprite
25
+ integration_test(REGULAR_PATH, :output => output_path('regular.packed'),
26
+ :selector => 'img.packed_',
27
+ :layout => :packed)
28
+ end
29
+
24
30
  def test_generate_regular_sprite_with_padding
25
31
  integration_test(REGULAR_PATH, :output => output_path('regular.padded'),
26
32
  :selector => 'img.padded_',
@@ -58,6 +64,12 @@ module SpriteFactory
58
64
  :layout => :vertical)
59
65
  end
60
66
 
67
+ def test_generate_packed_irregular_sprite
68
+ integration_test(IRREGULAR_PATH, :output => output_path('irregular.packed'),
69
+ :selector => 'img.packed_',
70
+ :layout => :packed)
71
+ end
72
+
61
73
  def test_generate_irregular_sprite_with_padding
62
74
  integration_test(IRREGULAR_PATH, :output => output_path('irregular.padded'),
63
75
  :selector => 'img.padded_',
@@ -0,0 +1,100 @@
1
+ require File.expand_path('test_case', File.dirname(__FILE__))
2
+
3
+ module SpriteFactory
4
+ module Layout
5
+ class HorizontalTest < SpriteFactory::Layout::TestCase
6
+
7
+ #==========================================================================
8
+ # test REGULAR images
9
+ #==========================================================================
10
+
11
+ def test_horizontal_layout_of_regular_images
12
+ images = get_regular_images
13
+ expected = [
14
+ { :x => 0, :y => 0 },
15
+ { :x => 20, :y => 0 },
16
+ { :x => 40, :y => 0 },
17
+ { :x => 60, :y => 0 },
18
+ { :x => 80, :y => 0 }
19
+ ]
20
+ verify_layout(100, 10, expected, images, :layout => :horizontal)
21
+ end
22
+
23
+ #--------------------------------------------------------------------------
24
+
25
+ def test_padded_horizontal_layout_of_regular_images
26
+ images = get_regular_images
27
+ expected = [
28
+ { :cssx => 0, :cssy => 0, :cssw => 40, :cssh => 50, :x => 10, :y => 20 },
29
+ { :cssx => 40, :cssy => 0, :cssw => 40, :cssh => 50, :x => 50, :y => 20 },
30
+ { :cssx => 80, :cssy => 0, :cssw => 40, :cssh => 50, :x => 90, :y => 20 },
31
+ { :cssx => 120, :cssy => 0, :cssw => 40, :cssh => 50, :x => 130, :y => 20 },
32
+ { :cssx => 160, :cssy => 0, :cssw => 40, :cssh => 50, :x => 170, :y => 20 }
33
+ ]
34
+ verify_layout(200, 50, expected, images, :layout => :horizontal, :hpadding => 10, :vpadding => 20)
35
+ end
36
+
37
+ #--------------------------------------------------------------------------
38
+
39
+ def test_fixed_horizontal_layout_of_regular_images
40
+ images = get_regular_images
41
+ expected = [
42
+ { :cssx => 0, :cssy => 0, :cssw => 50, :cssh => 50, :x => 15, :y => 20 },
43
+ { :cssx => 50, :cssy => 0, :cssw => 50, :cssh => 50, :x => 65, :y => 20 },
44
+ { :cssx => 100, :cssy => 0, :cssw => 50, :cssh => 50, :x => 115, :y => 20 },
45
+ { :cssx => 150, :cssy => 0, :cssw => 50, :cssh => 50, :x => 165, :y => 20 },
46
+ { :cssx => 200, :cssy => 0, :cssw => 50, :cssh => 50, :x => 215, :y => 20 }
47
+ ]
48
+ verify_layout(250, 50, expected, images, :layout => :horizontal, :width => 50, :height => 50)
49
+ end
50
+
51
+ #==========================================================================
52
+ # test IRREGULAR images
53
+ #==========================================================================
54
+
55
+ def test_horizontal_layout_of_irregular_images
56
+ images = get_irregular_images
57
+ expected = [
58
+ { :x => 0, :y => 0 },
59
+ { :x => 20, :y => 5 },
60
+ { :x => 60, :y => 10 },
61
+ { :x => 120, :y => 15 },
62
+ { :x => 200, :y => 20 }
63
+ ]
64
+ verify_layout(300, 50, expected, images, :layout => :horizontal)
65
+ end
66
+
67
+ #--------------------------------------------------------------------------
68
+
69
+ def test_padded_horizontal_layout_of_irregular_images
70
+ images = get_irregular_images
71
+ expected = [
72
+ { :cssx => 0, :cssy => 0, :cssw => 40, :cssh => 90, :x => 10, :y => 20 },
73
+ { :cssx => 40, :cssy => 5, :cssw => 60, :cssh => 80, :x => 50, :y => 25 },
74
+ { :cssx => 100, :cssy => 10, :cssw => 80, :cssh => 70, :x => 110, :y => 30 },
75
+ { :cssx => 180, :cssy => 15, :cssw => 100, :cssh => 60, :x => 190, :y => 35 },
76
+ { :cssx => 280, :cssy => 20, :cssw => 120, :cssh => 50, :x => 290, :y => 40 }
77
+ ]
78
+ verify_layout(400, 90, expected, images, :layout => :horizontal, :hpadding => 10, :vpadding => 20)
79
+ end
80
+
81
+ #--------------------------------------------------------------------------
82
+
83
+ def test_fixed_horizontal_layout_of_irregular_images
84
+ images = get_irregular_images
85
+ expected = [
86
+ { :cssx => 0, :cssy => 0, :cssw => 100, :cssh => 100, :x => 40, :y => 25 },
87
+ { :cssx => 100, :cssy => 0, :cssw => 100, :cssh => 100, :x => 130, :y => 30 },
88
+ { :cssx => 200, :cssy => 0, :cssw => 100, :cssh => 100, :x => 220, :y => 35 },
89
+ { :cssx => 300, :cssy => 0, :cssw => 100, :cssh => 100, :x => 310, :y => 40 },
90
+ { :cssx => 400, :cssy => 0, :cssw => 100, :cssh => 100, :x => 400, :y => 45 }
91
+ ]
92
+ verify_layout(500, 100, expected, images, :layout => :horizontal, :width => 100, :height => 100)
93
+ end
94
+
95
+ #--------------------------------------------------------------------------
96
+
97
+ end # class HorizontalTest
98
+ end # module Layout
99
+ end # module SpriteFactory
100
+
@@ -0,0 +1,221 @@
1
+ require File.expand_path('test_case', File.dirname(__FILE__))
2
+
3
+ module SpriteFactory
4
+ module Layout
5
+ class PackedTest < SpriteFactory::Layout::TestCase
6
+
7
+ #==========================================================================
8
+ # test REGULAR images
9
+ #==========================================================================
10
+
11
+ def test_packed_layout_of_regular_images
12
+ images = get_regular_images
13
+ expected = [ # expected: ---------
14
+ { :x => 0, :y => 0 }, # |111|333|
15
+ { :x => 0, :y => 10 }, # ---------
16
+ { :x => 20, :y => 0 }, # |222|444|
17
+ { :x => 20, :y => 10 }, # ---------
18
+ { :x => 0, :y => 20 } # |555| |
19
+ ] # ---------
20
+ verify_layout(40, 30, expected, images, :layout => :packed)
21
+ end
22
+
23
+ #--------------------------------------------------------------------------
24
+
25
+ def test_padded_packed_layout_of_regular_images
26
+ assert_not_implemented ":packed layout does not support the :padding option" do
27
+ Layout::Packed.layout(get_regular_images, :padding => 10)
28
+ end
29
+ end
30
+
31
+ #--------------------------------------------------------------------------
32
+
33
+ def test_fixed_packed_layout_of_regular_images
34
+ assert_not_implemented ":packed layout does not support fixed :width/:height option" do
35
+ Layout::Packed.layout(get_regular_images, :width => 50, :height => 50)
36
+ end
37
+ end
38
+
39
+ #==========================================================================
40
+ # test IRREGULAR images
41
+ #==========================================================================
42
+
43
+ def test_packed_layout_of_irregular_images
44
+ images = get_irregular_images
45
+ # expected: -----------------
46
+ expected = [ # |11111111111|444|
47
+ { :x => 0, :y => 0 }, # ------------|444|
48
+ { :x => 0, :y => 10 }, # |2222222| |444|
49
+ { :x => 0, :y => 30 }, # ------------|444|
50
+ { :x => 100, :y => 0 }, # |3333| -----
51
+ { :x => 0, :y => 60 } # -----------------
52
+ ] # |555| |
53
+ # -----------------
54
+ verify_layout(120, 100, expected, images, :layout => :packed)
55
+ end
56
+
57
+ #==========================================================================
58
+ # other packed algorithm test
59
+ #==========================================================================
60
+
61
+ def test_single_image_is_100_percent_packed
62
+ images = [
63
+ { :width => 100, :height => 100 },
64
+ { :width => 100, :height => 50 },
65
+ { :width => 50, :height => 100 }
66
+ ]
67
+ images.each do |image|
68
+ verify_layout(image[:width], image[:height], [{:x => 0, :y => 0}], [image], :layout => :packed)
69
+ end
70
+ end
71
+
72
+ #==========================================================================
73
+ # some test cases from original bin packing demonstration
74
+ # (see http://codeincomplete.com/posts/2011/5/7/bin_packing/example/)
75
+ #==========================================================================
76
+
77
+ def test_packed_simple
78
+ images = expanded_images([
79
+ { :width => 500, :height => 200 },
80
+ { :width => 250, :height => 200 },
81
+ { :width => 50, :height => 50, :num => 20 }
82
+ ])
83
+ expected = [
84
+ { :x => 0, :y => 0 },
85
+ { :x => 0, :y => 200 },
86
+ { :x => 250, :y => 200 },
87
+ { :x => 300, :y => 200 },
88
+ { :x => 350, :y => 200 },
89
+ { :x => 400, :y => 200 },
90
+ { :x => 450, :y => 200 },
91
+ { :x => 250, :y => 250 },
92
+ { :x => 300, :y => 250 },
93
+ { :x => 350, :y => 250 },
94
+ { :x => 400, :y => 250 },
95
+ { :x => 450, :y => 250 },
96
+ { :x => 250, :y => 300 },
97
+ { :x => 300, :y => 300 },
98
+ { :x => 350, :y => 300 },
99
+ { :x => 400, :y => 300 },
100
+ { :x => 450, :y => 300 },
101
+ { :x => 250, :y => 350 },
102
+ { :x => 300, :y => 350 },
103
+ { :x => 350, :y => 350 },
104
+ { :x => 400, :y => 350 },
105
+ { :x => 450, :y => 350 }
106
+ ]
107
+ verify_layout(500, 400, expected, images, :layout => :packed)
108
+ end
109
+
110
+ #--------------------------------------------------------------------------
111
+
112
+ def test_packed_square
113
+ images = expanded_images([{ :width => 50, :height => 50, :num => 16 }])
114
+ expected = [
115
+ { :x => 0, :y => 0 },
116
+ { :x => 50, :y => 0 },
117
+ { :x => 0, :y => 50 },
118
+ { :x => 50, :y => 50 },
119
+ { :x => 100, :y => 0 },
120
+ { :x => 100, :y => 50 },
121
+ { :x => 0, :y => 100 },
122
+ { :x => 50, :y => 100 },
123
+ { :x => 100, :y => 100 },
124
+ { :x => 150, :y => 0 },
125
+ { :x => 150, :y => 50 },
126
+ { :x => 150, :y => 100 },
127
+ { :x => 0, :y => 150 },
128
+ { :x => 50, :y => 150 },
129
+ { :x => 100, :y => 150 },
130
+ { :x => 150, :y => 150 }
131
+ ]
132
+ verify_layout(200, 200, expected, images, :layout => :packed)
133
+ end
134
+
135
+ #--------------------------------------------------------------------------
136
+
137
+ def test_packed_tall
138
+ images = expanded_images([{ :width => 50, :height => 500, :num => 5 }])
139
+ expected = [
140
+ { :x => 0, :y => 0 },
141
+ { :x => 50, :y => 0 },
142
+ { :x => 100, :y => 0 },
143
+ { :x => 150, :y => 0 },
144
+ { :x => 200, :y => 0 }
145
+ ]
146
+ verify_layout(250, 500, expected, images, :layout => :packed)
147
+ end
148
+
149
+ #--------------------------------------------------------------------------
150
+
151
+ def test_packed_wide
152
+ images = expanded_images([{ :width => 500, :height => 50, :num => 5 }])
153
+ expected = [
154
+ { :x => 0, :y => 0 },
155
+ { :x => 0, :y => 50 },
156
+ { :x => 0, :y => 100 },
157
+ { :x => 0, :y => 150 },
158
+ { :x => 0, :y => 200 }
159
+ ]
160
+ verify_layout(500, 250, expected, images, :layout => :packed)
161
+ end
162
+
163
+ #--------------------------------------------------------------------------
164
+
165
+ def test_packed_tall_and_wide
166
+ images = expanded_images([
167
+ { :width => 50, :height => 500, :num => 3 },
168
+ { :width => 500, :height => 50, :num => 3 }
169
+ ])
170
+ expected = [
171
+ { :x => 0, :y => 0 },
172
+ { :x => 50, :y => 0 },
173
+ { :x => 100, :y => 0 },
174
+ { :x => 150, :y => 0 },
175
+ { :x => 150, :y => 50 },
176
+ { :x => 150, :y => 100 }
177
+ ]
178
+ verify_layout(650, 500, expected, images, :layout => :packed)
179
+ end
180
+
181
+ #--------------------------------------------------------------------------
182
+
183
+ def test_packed_powers_of_2
184
+ images = expanded_images([
185
+ { :width => 64, :height => 64, :num => 2 },
186
+ { :width => 32, :height => 32, :num => 4 },
187
+ { :width => 16, :height => 16, :num => 8 }
188
+ ])
189
+ expected = [
190
+ { :x => 0, :y => 0 },
191
+ { :x => 64, :y => 0 },
192
+ { :x => 0, :y => 64 },
193
+ { :x => 32, :y => 64 },
194
+ { :x => 64, :y => 64 },
195
+ { :x => 96, :y => 64 },
196
+ { :x => 0, :y => 96 },
197
+ { :x => 16, :y => 96 },
198
+ { :x => 32, :y => 96 },
199
+ { :x => 48, :y => 96 },
200
+ { :x => 64, :y => 96 },
201
+ { :x => 80, :y => 96 },
202
+ { :x => 96, :y => 96 },
203
+ { :x => 112, :y => 96 }
204
+ ]
205
+ verify_layout(128, 112, expected, images, :layout => :packed)
206
+ end
207
+
208
+ #--------------------------------------------------------------------------
209
+
210
+ protected
211
+
212
+ def expanded_images(images)
213
+ result = images.map do |i|
214
+ (1..(i[:num] || 1)).map{{:width => i[:width], :height => i[:height]}}
215
+ end.flatten
216
+ end
217
+
218
+ end # class PackedTest
219
+ end # module Layout
220
+ end # module SpriteFactory
221
+