spittle 0.9.1.3 → 0.9.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/{README → README.rdoc} +36 -31
- data/VERSION +1 -1
- data/bin/{spittle → sprite} +0 -0
- data/examples/sprites/.mtimes +24 -0
- data/examples/sprites/apple/.mtimes +9 -0
- data/examples/sprites/apple/fragment.css +14 -14
- data/examples/sprites/many_sized_cats/.mtimes +3 -0
- data/examples/sprites/many_sized_cats/sprite.png +0 -0
- data/examples/sprites/sprite.css +14 -14
- data/examples/sprites/words/.mtimes +5 -0
- data/lib/spittle/directory_spriter.rb +5 -0
- data/lib/spittle/filters.rb +36 -13
- data/lib/spittle/image.rb +41 -16
- data/lib/spittle/mtime_tracker.rb +76 -0
- data/lib/spittle.rb +1 -0
- data/spec/integration_spec.rb +2 -2
- data/spec/mtime_tracking_spec.rb +69 -0
- data/spittle.gemspec +13 -6
- metadata +13 -6
data/{README → README.rdoc}
RENAMED
@@ -1,72 +1,77 @@
|
|
1
|
-
|
2
|
-
[ PNG, PNG, PNG ] (° )
|
3
|
-
[ PNG, PNG, PNG ] )°)
|
4
|
-
[ PNG, PNG, )°)
|
5
|
-
[ PNG, )°)
|
6
|
-
[ )°)
|
1
|
+
= Spittle, a sprite generator
|
7
2
|
|
8
|
-
|
3
|
+
[ PNG, PNG, PNG ] (°_°)
|
4
|
+
[ PNG, PNG, PNG ] (° )
|
5
|
+
[ PNG, PNG, PNG ] )°)
|
6
|
+
[ PNG, PNG, )°)
|
7
|
+
[ PNG, )°)
|
8
|
+
[ )°)
|
9
9
|
|
10
|
+
\(°_°)/ -> SPRITES!!!
|
11
|
+
|
12
|
+
== Description
|
10
13
|
|
11
14
|
It takes your PNG's, chews them up and spits out sprites!
|
12
15
|
|
13
16
|
point bin/spittle at a directory, and watch it sprite away!
|
14
17
|
|
15
|
-
|
18
|
+
== Installation - standalone
|
16
19
|
|
17
20
|
We're hosted at gemcutter. I believe 'sudo gem install gemcutter' then 'gem tumble'.
|
18
|
-
Then you can run:
|
21
|
+
Then you can run:
|
22
|
+
|
23
|
+
sudo gem install spittle
|
19
24
|
|
20
|
-
|
25
|
+
=== Usage - standalone
|
21
26
|
|
22
|
-
|
27
|
+
sprite <directory>
|
23
28
|
|
24
|
-
|
29
|
+
If you point the sprite command at a directory tree by default it will construct sprites for each of the sub directories and generate a single css to access all of the sprites which is placed in the root of the directory tree
|
25
30
|
|
26
31
|
For a full list of options:
|
27
32
|
|
28
|
-
|
33
|
+
sprite -h
|
29
34
|
|
30
|
-
|
35
|
+
== Installation - Rails plugin
|
31
36
|
|
32
|
-
|
37
|
+
script/plugin install git://github.com/aberant/spittle.git
|
33
38
|
|
34
|
-
|
39
|
+
=== Usage - Rails plugin
|
35
40
|
|
36
|
-
Spittle assumes all of your sprites are located in the directory public/images/sprites. This directory should
|
41
|
+
Spittle assumes all of your sprites are located in the directory public/images/sprites. This directory should contain sub-directories for each sprite you wish to create. The css class names for an image in a sprite will take the form <directory_name>_<image_name>. Here is an example:
|
37
42
|
|
38
|
-
sprites /
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
43
|
+
sprites /
|
44
|
+
cars /
|
45
|
+
ford.png
|
46
|
+
chevy.png
|
47
|
+
planes /
|
48
|
+
boeing.png
|
49
|
+
cesna.png
|
45
50
|
|
46
51
|
Running spittle:generate does all the work. Each sprite directory (cars, planes) will now contain a sprite.png. Spittle will also generate a sprites.css stylesheet in public/stylesheets/ that you should include in your layout. If you wished to use the ford image from the cars sprite you would give the 'cars_ford' class to the desired element in the view. That's it!
|
47
52
|
|
48
53
|
Check out examples/sprites if you want to see what spittle can do without doing any work.
|
49
54
|
|
50
|
-
|
55
|
+
== Limitations
|
51
56
|
|
52
57
|
- only supports RGB and RGBA color types (and they must be the same for all images in a sprite)
|
53
58
|
- does not support color profiles (can cause a slight change in color from the source image)
|
54
59
|
|
55
|
-
|
60
|
+
== Features
|
56
61
|
|
57
62
|
- automatically generates sprites from a set of PNG images
|
58
63
|
- automatically generates css classes to access images within the sprite
|
59
|
-
-
|
64
|
+
- customizable css templates
|
60
65
|
- Rails plugin & rake tasks (sprite:generate & sprite:cleanup)
|
61
66
|
- Supports varying dimensions in source images
|
62
67
|
|
63
|
-
|
68
|
+
== Roadmap - by priority
|
64
69
|
|
65
70
|
- Use mtime tracking to prevent regeneration of sprites that have not changed
|
66
71
|
- Support global css template override
|
67
72
|
- Improve image compression
|
68
73
|
|
69
|
-
|
74
|
+
== Authors
|
70
75
|
|
71
|
-
aberant - Colin Harris
|
72
|
-
tjennings - Tyler Jennings
|
76
|
+
- aberant - Colin Harris
|
77
|
+
- tjennings - Tyler Jennings
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.9.1.
|
1
|
+
0.9.1.4
|
data/bin/{spittle → sprite}
RENAMED
File without changes
|
@@ -0,0 +1,24 @@
|
|
1
|
+
./apple/iphone.png 1258678989
|
2
|
+
./apple/apple.png 1258157162
|
3
|
+
./many_sized_cats/music-keyboard-cat.png 1258479430
|
4
|
+
./words/set.png 1258120615
|
5
|
+
./many_sized_cats/cat-on-keyboard.png 1258479384
|
6
|
+
./apple/support.png 1258157107
|
7
|
+
./many_sized_cats 1258678265
|
8
|
+
./words/sprite.css 1258397039
|
9
|
+
./words/latitude.png 1258120615
|
10
|
+
./sprite.css 1258679016
|
11
|
+
./words/specified.png 1258120615
|
12
|
+
./server.rb 1258120560
|
13
|
+
./many_sized_cats/darth_cat.png 1258678472
|
14
|
+
./words/of.png 1258120615
|
15
|
+
./apple/search.png 1258157118
|
16
|
+
./apple/itunes.png 1258157145
|
17
|
+
./apple/downloads.png 1258157123
|
18
|
+
./apple 1258678259
|
19
|
+
./README 1258164457
|
20
|
+
./apple/mac.png 1258157151
|
21
|
+
./words 1258678265
|
22
|
+
./index.html 1258503160
|
23
|
+
./apple/store.png 1258157157
|
24
|
+
./apple/divider.png 1258158522
|
@@ -0,0 +1,9 @@
|
|
1
|
+
./apple/iphone.png 1258678989
|
2
|
+
./apple/apple.png 1258157162
|
3
|
+
./apple/support.png 1258157107
|
4
|
+
./apple/search.png 1258157118
|
5
|
+
./apple/itunes.png 1258157145
|
6
|
+
./apple/downloads.png 1258157123
|
7
|
+
./apple/mac.png 1258157151
|
8
|
+
./apple/store.png 1258157157
|
9
|
+
./apple/divider.png 1258158522
|
@@ -1,3 +1,10 @@
|
|
1
|
+
.apple_itunes {
|
2
|
+
background: transparent url(/apple/sprite.png) -350px 0px no-repeat;
|
3
|
+
width:116;
|
4
|
+
height:38;
|
5
|
+
text-indent:-5000px;
|
6
|
+
}
|
7
|
+
|
1
8
|
.apple_mac {
|
2
9
|
background: transparent url(/apple/sprite.png) -466px 0px no-repeat;
|
3
10
|
width:116;
|
@@ -26,13 +33,6 @@
|
|
26
33
|
text-indent:-5000px;
|
27
34
|
}
|
28
35
|
|
29
|
-
.apple_search {
|
30
|
-
background: transparent url(/apple/sprite.png) -582px 0px no-repeat;
|
31
|
-
width:162;
|
32
|
-
height:38;
|
33
|
-
text-indent:-5000px;
|
34
|
-
}
|
35
|
-
|
36
36
|
.apple_downloads {
|
37
37
|
background: transparent url(/apple/sprite.png) -118px 0px no-repeat;
|
38
38
|
width:116;
|
@@ -40,22 +40,22 @@
|
|
40
40
|
text-indent:-5000px;
|
41
41
|
}
|
42
42
|
|
43
|
-
.
|
44
|
-
background: transparent url(/apple/sprite.png) -
|
43
|
+
.apple_store {
|
44
|
+
background: transparent url(/apple/sprite.png) -744px 0px no-repeat;
|
45
45
|
width:116;
|
46
46
|
height:38;
|
47
47
|
text-indent:-5000px;
|
48
48
|
}
|
49
49
|
|
50
|
-
.
|
51
|
-
background: transparent url(/apple/sprite.png) -
|
52
|
-
width:
|
50
|
+
.apple_search {
|
51
|
+
background: transparent url(/apple/sprite.png) -582px 0px no-repeat;
|
52
|
+
width:162;
|
53
53
|
height:38;
|
54
54
|
text-indent:-5000px;
|
55
55
|
}
|
56
56
|
|
57
|
-
.
|
58
|
-
background: transparent url(/apple/sprite.png) -
|
57
|
+
.apple_iphone {
|
58
|
+
background: transparent url(/apple/sprite.png) -234px 0px no-repeat;
|
59
59
|
width:116;
|
60
60
|
height:38;
|
61
61
|
text-indent:-5000px;
|
Binary file
|
data/examples/sprites/sprite.css
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
.apple_itunes {
|
2
|
+
background: transparent url(/apple/sprite.png) -350px 0px no-repeat;
|
3
|
+
width:116;
|
4
|
+
height:38;
|
5
|
+
text-indent:-5000px;
|
6
|
+
}
|
7
|
+
|
1
8
|
.apple_mac {
|
2
9
|
background: transparent url(/apple/sprite.png) -466px 0px no-repeat;
|
3
10
|
width:116;
|
@@ -26,13 +33,6 @@
|
|
26
33
|
text-indent:-5000px;
|
27
34
|
}
|
28
35
|
|
29
|
-
.apple_search {
|
30
|
-
background: transparent url(/apple/sprite.png) -582px 0px no-repeat;
|
31
|
-
width:162;
|
32
|
-
height:38;
|
33
|
-
text-indent:-5000px;
|
34
|
-
}
|
35
|
-
|
36
36
|
.apple_downloads {
|
37
37
|
background: transparent url(/apple/sprite.png) -118px 0px no-repeat;
|
38
38
|
width:116;
|
@@ -40,22 +40,22 @@
|
|
40
40
|
text-indent:-5000px;
|
41
41
|
}
|
42
42
|
|
43
|
-
.
|
44
|
-
background: transparent url(/apple/sprite.png) -
|
43
|
+
.apple_store {
|
44
|
+
background: transparent url(/apple/sprite.png) -744px 0px no-repeat;
|
45
45
|
width:116;
|
46
46
|
height:38;
|
47
47
|
text-indent:-5000px;
|
48
48
|
}
|
49
49
|
|
50
|
-
.
|
51
|
-
background: transparent url(/apple/sprite.png) -
|
52
|
-
width:
|
50
|
+
.apple_search {
|
51
|
+
background: transparent url(/apple/sprite.png) -582px 0px no-repeat;
|
52
|
+
width:162;
|
53
53
|
height:38;
|
54
54
|
text-indent:-5000px;
|
55
55
|
}
|
56
56
|
|
57
|
-
.
|
58
|
-
background: transparent url(/apple/sprite.png) -
|
57
|
+
.apple_iphone {
|
58
|
+
background: transparent url(/apple/sprite.png) -234px 0px no-repeat;
|
59
59
|
width:116;
|
60
60
|
height:38;
|
61
61
|
text-indent:-5000px;
|
@@ -17,6 +17,8 @@ class DirectoryProcessor
|
|
17
17
|
@sprite = PNG::Sprite.new
|
18
18
|
files.each {|f| @sprite.append(PNG::Image.open(f))}
|
19
19
|
#puts "#{@dir} #{files.size} files"
|
20
|
+
@tracker = MtimeTracker.new(@dir,
|
21
|
+
:exclude => ['fragment.css', 'sprite.png'])
|
20
22
|
end
|
21
23
|
|
22
24
|
def images
|
@@ -24,15 +26,18 @@ class DirectoryProcessor
|
|
24
26
|
end
|
25
27
|
|
26
28
|
def write
|
29
|
+
return unless @tracker.has_changes?
|
27
30
|
@sprite.write(sprite_file)
|
28
31
|
File.open(css_file, 'w') do |f|
|
29
32
|
f.write(css)
|
30
33
|
end
|
34
|
+
@tracker.update
|
31
35
|
end
|
32
36
|
|
33
37
|
def cleanup
|
34
38
|
File.delete(sprite_file) rescue {}
|
35
39
|
File.delete(css_file) rescue {}
|
40
|
+
@tracker.cleanup
|
36
41
|
end
|
37
42
|
|
38
43
|
def sprite_file
|
data/lib/spittle/filters.rb
CHANGED
@@ -22,25 +22,48 @@ module PNG
|
|
22
22
|
(value + ( (fetch_pixel(index - record_width, row) + fetch_pixel(index, last_row)) / 2 ).floor) % 256
|
23
23
|
when 4
|
24
24
|
#paeth
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
pb = (p - b).abs
|
31
|
-
pc = (p - c).abs
|
25
|
+
left = fetch_pixel(index - record_width, row)
|
26
|
+
above = fetch_pixel(index, last_row)
|
27
|
+
upper_left = fetch_pixel(index - record_width, last_row)
|
28
|
+
|
29
|
+
pr = paeth_predictor( left, above, upper_left )
|
32
30
|
|
33
|
-
pr = c
|
34
|
-
if ( pa <= pb and pa <= pc)
|
35
|
-
pr = a
|
36
|
-
elsif (pb <= pc)
|
37
|
-
pr = b
|
38
|
-
end
|
39
31
|
(value + pr) % 256
|
40
32
|
else
|
41
33
|
raise "Invalid filter type (#{filter_type})"
|
42
34
|
end
|
43
35
|
end
|
36
|
+
def encode( filter_type, value, index, row, last_row, record_width )
|
37
|
+
case filter_type
|
38
|
+
when 4
|
39
|
+
#paeth
|
40
|
+
left = fetch_pixel(index - record_width, row)
|
41
|
+
above = fetch_pixel(index, last_row)
|
42
|
+
upper_left = fetch_pixel(index - record_width, last_row)
|
43
|
+
|
44
|
+
pr = paeth_predictor( left, above, upper_left )
|
45
|
+
(value - pr) % 256
|
46
|
+
else
|
47
|
+
raise "We can currently only encode to PAETH. Filter type (#{filter_type}) is not supported"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def paeth_predictor( left, above, upper_left )
|
54
|
+
p = left + above - upper_left
|
55
|
+
pa = (p - left).abs
|
56
|
+
pb = (p - above).abs
|
57
|
+
pc = (p - upper_left).abs
|
58
|
+
|
59
|
+
pr = upper_left
|
60
|
+
if ( pa <= pb and pa <= pc)
|
61
|
+
pr = left
|
62
|
+
elsif (pb <= pc)
|
63
|
+
pr = above
|
64
|
+
end
|
65
|
+
pr
|
66
|
+
end
|
44
67
|
end
|
45
68
|
end
|
46
69
|
end
|
data/lib/spittle/image.rb
CHANGED
@@ -30,9 +30,10 @@ module PNG
|
|
30
30
|
self.depth == image.depth
|
31
31
|
end
|
32
32
|
|
33
|
-
def write(file_name)
|
33
|
+
def write(file_name, options={})
|
34
|
+
filter_type = options[:filter_type] || 4
|
34
35
|
File.open(file_name, 'w') do |f|
|
35
|
-
f.write(generate_png)
|
36
|
+
f.write(generate_png( filter_type ))
|
36
37
|
end
|
37
38
|
end
|
38
39
|
|
@@ -56,10 +57,11 @@ module PNG
|
|
56
57
|
end
|
57
58
|
|
58
59
|
def to_s
|
59
|
-
|
60
|
+
inspect
|
60
61
|
end
|
61
62
|
|
62
63
|
def merge_left( other )
|
64
|
+
#puts "merging #{self.name} into #{other.name}"
|
63
65
|
l = other.rows
|
64
66
|
r = self.rows
|
65
67
|
|
@@ -91,24 +93,35 @@ module PNG
|
|
91
93
|
end
|
92
94
|
|
93
95
|
def rows
|
94
|
-
|
95
|
-
|
96
|
-
|
96
|
+
each_row( @idat.uncompressed ) do |scanline, row, out, pixel_width|
|
97
|
+
decode(scanline, row, out, pixel_width)
|
98
|
+
end
|
99
|
+
end
|
97
100
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
offset = end_row
|
103
|
-
end
|
104
|
-
out
|
101
|
+
def encoded_rows(data, filter_type)
|
102
|
+
each_row( data ) do |scanline, row, out, pixel_width|
|
103
|
+
encode(scanline, row, out, pixel_width, filter_type)
|
104
|
+
end
|
105
105
|
end
|
106
106
|
|
107
107
|
def inspect
|
108
|
-
"
|
108
|
+
"#{@name} (#{height} x #{width}) [color type: #{color_type}, depth: #{depth}]"
|
109
109
|
end
|
110
110
|
private
|
111
111
|
|
112
|
+
def each_row( data )
|
113
|
+
out = Array.new(height)
|
114
|
+
offset = 0
|
115
|
+
|
116
|
+
height.times do |scanline|
|
117
|
+
end_row = scanline_width + offset
|
118
|
+
row = data.slice(offset, scanline_width)
|
119
|
+
out[scanline] = yield( scanline, row, out, pixel_width)
|
120
|
+
offset = end_row
|
121
|
+
end
|
122
|
+
out
|
123
|
+
end
|
124
|
+
|
112
125
|
def last_scanline(current, data)
|
113
126
|
(current - 1 < 0 ? [] : data[current - 1])
|
114
127
|
end
|
@@ -119,6 +132,10 @@ module PNG
|
|
119
132
|
process_row(row, last_scanline(current, data), filter_type, pixel_width)
|
120
133
|
end
|
121
134
|
|
135
|
+
def encode(current, row, data, pixel_width, filter_type)
|
136
|
+
process_row(row, last_scanline(current, data), filter_type, pixel_width)
|
137
|
+
end
|
138
|
+
|
122
139
|
def process_row(row, last_scanline, filter_type, pixel_width)
|
123
140
|
o = Array.new(row.size)
|
124
141
|
row.each_with_index do |e, i|
|
@@ -127,9 +144,17 @@ module PNG
|
|
127
144
|
o
|
128
145
|
end
|
129
146
|
|
130
|
-
def
|
147
|
+
def encode_row(row, last_scanline, filter_type, pixel_width)
|
148
|
+
o = Array.new(row.size)
|
149
|
+
row.each_with_index do |e, i|
|
150
|
+
o[i] = Filters.encode(filter_type, e, i, o, last_scanline, pixel_width)
|
151
|
+
end
|
152
|
+
o
|
153
|
+
end
|
154
|
+
|
155
|
+
def generate_png( filter_type )
|
131
156
|
file_header = PNG::FileHeader.new.encode
|
132
|
-
raw_data = @idat.uncompressed
|
157
|
+
raw_data = encoded_rows( @idat.uncompressed, filter_type ).flatten
|
133
158
|
|
134
159
|
ihdr = PNG::IHDR.new( width, height, depth, color_type ).to_chunk
|
135
160
|
idat = PNG::IDAT.new( raw_data ).to_chunk
|
@@ -0,0 +1,76 @@
|
|
1
|
+
class MtimeTracker
|
2
|
+
def initialize(dir, options = {})
|
3
|
+
@dir = dir
|
4
|
+
@options = options
|
5
|
+
end
|
6
|
+
|
7
|
+
def cleanup
|
8
|
+
File.delete(mtime_file) rescue {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def fresh?
|
12
|
+
not File.exists?(mtime_file)
|
13
|
+
end
|
14
|
+
|
15
|
+
def files
|
16
|
+
return @files if @files
|
17
|
+
@files = without_exclusions(Dir.glob(@dir + "/**/*"))
|
18
|
+
end
|
19
|
+
|
20
|
+
def without_exclusions(files)
|
21
|
+
return files unless @options[:exclude]
|
22
|
+
exclusions = [@options[:exclude]].flatten
|
23
|
+
files.select{|f| exclusions.none?{|e| f.match e}}
|
24
|
+
end
|
25
|
+
|
26
|
+
def current_mtimes
|
27
|
+
@current ||= files.inject({}) do |map, f|
|
28
|
+
map[f] = File.mtime(f).to_i; map
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def file_changed?(file)
|
33
|
+
#puts "#{file} #{mtimes[file]} != #{current_mtimes[file]}"
|
34
|
+
mtimes[file] != current_mtimes[file]
|
35
|
+
end
|
36
|
+
|
37
|
+
def mtimes
|
38
|
+
return @mtimes if @mtimes
|
39
|
+
return {} unless File.exists?(mtime_file)
|
40
|
+
@mtimes = {}
|
41
|
+
File.open(mtime_file) do |f|
|
42
|
+
f.each do |line|
|
43
|
+
parts = line.split("\t")
|
44
|
+
@mtimes[parts[0]] = parts[1].to_i
|
45
|
+
end
|
46
|
+
end
|
47
|
+
@mtimes
|
48
|
+
end
|
49
|
+
|
50
|
+
def changeset
|
51
|
+
files.select{|f| file_changed?(f)}
|
52
|
+
end
|
53
|
+
|
54
|
+
def has_changes?
|
55
|
+
not changeset.empty?
|
56
|
+
end
|
57
|
+
|
58
|
+
def mtime_file
|
59
|
+
@dir + "/.mtimes"
|
60
|
+
end
|
61
|
+
|
62
|
+
def update
|
63
|
+
File.open(mtime_file, 'w') do |f|
|
64
|
+
current = current_mtimes
|
65
|
+
flat = current.map{|k, v| "#{k}\t#{v}\n"}.join
|
66
|
+
f.write flat
|
67
|
+
end
|
68
|
+
reset
|
69
|
+
end
|
70
|
+
|
71
|
+
def reset
|
72
|
+
@mtimes = nil
|
73
|
+
@current = nil
|
74
|
+
@files = nil
|
75
|
+
end
|
76
|
+
end
|
data/lib/spittle.rb
CHANGED
data/spec/integration_spec.rb
CHANGED
@@ -10,7 +10,7 @@ describe 'PNG' do
|
|
10
10
|
|
11
11
|
it 'can read and write a PNG' do
|
12
12
|
img = PNG::Image.open("#{@img_dir}/lightening.png")
|
13
|
-
img.write("#{@tmp_dir}/write_test.png")
|
13
|
+
img.write("#{@tmp_dir}/write_test.png", :filter_type => 0)
|
14
14
|
read("#{@expected_dir}/write_test.png").should == read("#{@tmp_dir}/write_test.png")
|
15
15
|
end
|
16
16
|
|
@@ -18,7 +18,7 @@ describe 'PNG' do
|
|
18
18
|
one = PNG::Image.open("#{@img_dir}/lightening.png")
|
19
19
|
two = PNG::Image.open("#{@img_dir}/lightening.png")
|
20
20
|
merged = one.merge_left two
|
21
|
-
merged.write("#{@tmp_dir}/merge_right_test.png")
|
21
|
+
merged.write("#{@tmp_dir}/merge_right_test.png", :filter_type => 0)
|
22
22
|
read("#{@expected_dir}/merge_right_test.png").should == read("#{@tmp_dir}/merge_right_test.png")
|
23
23
|
end
|
24
24
|
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require 'fileutils'
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
4
|
+
|
5
|
+
describe MtimeTracker do
|
6
|
+
describe "on a new directory" do
|
7
|
+
before do
|
8
|
+
@img_dir = File.dirname(__FILE__) + '/images'
|
9
|
+
@tracker = MtimeTracker.new(@img_dir)
|
10
|
+
end
|
11
|
+
|
12
|
+
after do
|
13
|
+
File.delete(@img_dir + "/.mtimes") rescue {}
|
14
|
+
end
|
15
|
+
|
16
|
+
it "tells me there are changes" do
|
17
|
+
@tracker.has_changes?.should be_true
|
18
|
+
end
|
19
|
+
|
20
|
+
it "tells me things have not changed after I update the tracking" do
|
21
|
+
@tracker.update
|
22
|
+
@tracker.has_changes?.should be_false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "on an existing directory" do
|
27
|
+
before do
|
28
|
+
@img_dir = File.dirname(__FILE__) + '/images'
|
29
|
+
MtimeTracker.new(@img_dir).update
|
30
|
+
@tracker = MtimeTracker.new(@img_dir)
|
31
|
+
end
|
32
|
+
|
33
|
+
after do
|
34
|
+
File.delete(@img_dir + "/.mtimes") rescue {}
|
35
|
+
end
|
36
|
+
|
37
|
+
it "tells me nothing has changed" do
|
38
|
+
@tracker.has_changes?.should be_false
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "when a file has changed" do
|
42
|
+
before do
|
43
|
+
FileUtils.touch(@img_dir + "/lightening.png")
|
44
|
+
@tracker.reset
|
45
|
+
end
|
46
|
+
|
47
|
+
it "returns true from has_changes" do
|
48
|
+
@tracker.has_changes?.should be_true
|
49
|
+
@tracker.changeset.first.should == "./spec/images/lightening.png"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "file exclustions" do
|
54
|
+
before do
|
55
|
+
@img_dir = File.dirname(__FILE__) + '/images'
|
56
|
+
@tracker = MtimeTracker.new(@img_dir, :exclude => [/lightening/, "tacos"])
|
57
|
+
end
|
58
|
+
|
59
|
+
after do
|
60
|
+
File.delete(@img_dir + "/.mtimes") rescue {}
|
61
|
+
end
|
62
|
+
|
63
|
+
it "does not report excluded files as changed" do
|
64
|
+
FileUtils.touch(@img_dir + "/lightening.png")
|
65
|
+
@tracker.has_changes?.should be_false
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/spittle.gemspec
CHANGED
@@ -5,26 +5,28 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{spittle}
|
8
|
-
s.version = "0.9.1.
|
8
|
+
s.version = "0.9.1.4"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["aberant", "tjennings"]
|
12
|
-
s.date = %q{2009-11-
|
12
|
+
s.date = %q{2009-11-20}
|
13
13
|
s.description = %q{pure ruby PNG}
|
14
14
|
s.email = ["qzzzq1@gmail.com", "tyler.jennings@gmail.com"]
|
15
|
-
s.executables = ["png_info", "
|
15
|
+
s.executables = ["png_info", "sprite"]
|
16
16
|
s.extra_rdoc_files = [
|
17
|
-
"README"
|
17
|
+
"README.rdoc"
|
18
18
|
]
|
19
19
|
s.files = [
|
20
20
|
".gitignore",
|
21
21
|
"MIT-LICENSE",
|
22
|
-
"README",
|
22
|
+
"README.rdoc",
|
23
23
|
"Rakefile",
|
24
24
|
"VERSION",
|
25
25
|
"bin/png_info",
|
26
|
-
"bin/
|
26
|
+
"bin/sprite",
|
27
|
+
"examples/sprites/.mtimes",
|
27
28
|
"examples/sprites/README",
|
29
|
+
"examples/sprites/apple/.mtimes",
|
28
30
|
"examples/sprites/apple/apple.png",
|
29
31
|
"examples/sprites/apple/divider.png",
|
30
32
|
"examples/sprites/apple/downloads.png",
|
@@ -38,6 +40,7 @@ Gem::Specification.new do |s|
|
|
38
40
|
"examples/sprites/apple/support.png",
|
39
41
|
"examples/sprites/fragment.css",
|
40
42
|
"examples/sprites/index.html",
|
43
|
+
"examples/sprites/many_sized_cats/.mtimes",
|
41
44
|
"examples/sprites/many_sized_cats/cat-on-keyboard.png",
|
42
45
|
"examples/sprites/many_sized_cats/darth_cat.png",
|
43
46
|
"examples/sprites/many_sized_cats/fragment.css",
|
@@ -45,6 +48,7 @@ Gem::Specification.new do |s|
|
|
45
48
|
"examples/sprites/many_sized_cats/sprite.png",
|
46
49
|
"examples/sprites/server.rb",
|
47
50
|
"examples/sprites/sprite.css",
|
51
|
+
"examples/sprites/words/.mtimes",
|
48
52
|
"examples/sprites/words/fragment.css",
|
49
53
|
"examples/sprites/words/latitude.png",
|
50
54
|
"examples/sprites/words/of.png",
|
@@ -62,6 +66,7 @@ Gem::Specification.new do |s|
|
|
62
66
|
"lib/spittle/iend.rb",
|
63
67
|
"lib/spittle/ihdr.rb",
|
64
68
|
"lib/spittle/image.rb",
|
69
|
+
"lib/spittle/mtime_tracker.rb",
|
65
70
|
"lib/spittle/parser.rb",
|
66
71
|
"lib/spittle/processor.rb",
|
67
72
|
"lib/spittle/sprite.rb",
|
@@ -79,6 +84,7 @@ Gem::Specification.new do |s|
|
|
79
84
|
"spec/lib/image_spec.rb",
|
80
85
|
"spec/lib/parser_spec.rb",
|
81
86
|
"spec/lib/sprite_spec.rb",
|
87
|
+
"spec/mtime_tracking_spec.rb",
|
82
88
|
"spec/spec.opts",
|
83
89
|
"spec/spec_helper.rb",
|
84
90
|
"spec/sprite_dirs/words/latitude.png",
|
@@ -104,6 +110,7 @@ Gem::Specification.new do |s|
|
|
104
110
|
"spec/lib/image_spec.rb",
|
105
111
|
"spec/lib/parser_spec.rb",
|
106
112
|
"spec/lib/sprite_spec.rb",
|
113
|
+
"spec/mtime_tracking_spec.rb",
|
107
114
|
"spec/spec_helper.rb",
|
108
115
|
"examples/sprites/server.rb"
|
109
116
|
]
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spittle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.1.
|
4
|
+
version: 0.9.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- aberant
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2009-11-
|
13
|
+
date: 2009-11-20 00:00:00 -06:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -29,20 +29,22 @@ email:
|
|
29
29
|
- tyler.jennings@gmail.com
|
30
30
|
executables:
|
31
31
|
- png_info
|
32
|
-
-
|
32
|
+
- sprite
|
33
33
|
extensions: []
|
34
34
|
|
35
35
|
extra_rdoc_files:
|
36
|
-
- README
|
36
|
+
- README.rdoc
|
37
37
|
files:
|
38
38
|
- .gitignore
|
39
39
|
- MIT-LICENSE
|
40
|
-
- README
|
40
|
+
- README.rdoc
|
41
41
|
- Rakefile
|
42
42
|
- VERSION
|
43
43
|
- bin/png_info
|
44
|
-
- bin/
|
44
|
+
- bin/sprite
|
45
|
+
- examples/sprites/.mtimes
|
45
46
|
- examples/sprites/README
|
47
|
+
- examples/sprites/apple/.mtimes
|
46
48
|
- examples/sprites/apple/apple.png
|
47
49
|
- examples/sprites/apple/divider.png
|
48
50
|
- examples/sprites/apple/downloads.png
|
@@ -56,6 +58,7 @@ files:
|
|
56
58
|
- examples/sprites/apple/support.png
|
57
59
|
- examples/sprites/fragment.css
|
58
60
|
- examples/sprites/index.html
|
61
|
+
- examples/sprites/many_sized_cats/.mtimes
|
59
62
|
- examples/sprites/many_sized_cats/cat-on-keyboard.png
|
60
63
|
- examples/sprites/many_sized_cats/darth_cat.png
|
61
64
|
- examples/sprites/many_sized_cats/fragment.css
|
@@ -63,6 +66,7 @@ files:
|
|
63
66
|
- examples/sprites/many_sized_cats/sprite.png
|
64
67
|
- examples/sprites/server.rb
|
65
68
|
- examples/sprites/sprite.css
|
69
|
+
- examples/sprites/words/.mtimes
|
66
70
|
- examples/sprites/words/fragment.css
|
67
71
|
- examples/sprites/words/latitude.png
|
68
72
|
- examples/sprites/words/of.png
|
@@ -80,6 +84,7 @@ files:
|
|
80
84
|
- lib/spittle/iend.rb
|
81
85
|
- lib/spittle/ihdr.rb
|
82
86
|
- lib/spittle/image.rb
|
87
|
+
- lib/spittle/mtime_tracker.rb
|
83
88
|
- lib/spittle/parser.rb
|
84
89
|
- lib/spittle/processor.rb
|
85
90
|
- lib/spittle/sprite.rb
|
@@ -97,6 +102,7 @@ files:
|
|
97
102
|
- spec/lib/image_spec.rb
|
98
103
|
- spec/lib/parser_spec.rb
|
99
104
|
- spec/lib/sprite_spec.rb
|
105
|
+
- spec/mtime_tracking_spec.rb
|
100
106
|
- spec/spec.opts
|
101
107
|
- spec/spec_helper.rb
|
102
108
|
- spec/sprite_dirs/words/latitude.png
|
@@ -144,5 +150,6 @@ test_files:
|
|
144
150
|
- spec/lib/image_spec.rb
|
145
151
|
- spec/lib/parser_spec.rb
|
146
152
|
- spec/lib/sprite_spec.rb
|
153
|
+
- spec/mtime_tracking_spec.rb
|
147
154
|
- spec/spec_helper.rb
|
148
155
|
- examples/sprites/server.rb
|