spittle 0.9.1.3 → 0.9.1.4
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/{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
|