aslakhellesoy-png 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.
Binary file
@@ -0,0 +1,73 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ require 'png/reader'
4
+
5
+ ##
6
+ # Implements a simple bitmap font by extracting letters from a PNG.
7
+
8
+ class PNG::Font
9
+ LETTERS = (('A'..'Z').to_a +
10
+ ('a'..'z').to_a +
11
+ ('0'..'9').to_a + [" "] * 16 +
12
+ '({[<!@#$%^&*?_+-=;,"/~>]})'.split(//))
13
+
14
+ attr_reader :height, :width, :canvas
15
+
16
+ def self.default
17
+ @@default ||= new(File.join(File.dirname(__FILE__), "default_font.png"))
18
+ end
19
+
20
+ def initialize(png_file)
21
+ @canvas = PNG.load_file png_file
22
+ @height, @width = canvas.height / 4, canvas.width / 26
23
+ @cache = {}
24
+ end
25
+
26
+ def coordinates c
27
+ i = LETTERS.index c
28
+
29
+ raise ArgumentError, "Can't find #{c.inspect}" unless i
30
+
31
+ x = (i % 26) * width
32
+ y = (3 - (i / 26)) * height # start from the top (3rd row)
33
+
34
+ return x, y, x+width-1, y+height-1
35
+ end
36
+
37
+ def [] c
38
+ c = c.chr unless String === c
39
+ x0, y0, x1, y1 = coordinates c
40
+
41
+ @cache[c] ||= @canvas.extract(x0, y0, x1, y1)
42
+ end
43
+ end
44
+
45
+ class PNG::Canvas
46
+ ##
47
+ # Write a string at [x, y] with font, optionally specifying a font,
48
+ # an alignment of :left, :center, or :right and the style to draw
49
+ # the annotation (see #composite).
50
+ #
51
+ # require 'png/font'
52
+
53
+ def annotate(string, x, y,
54
+ font = PNG::Font.default, align = :left, style = :overwrite)
55
+ case align
56
+ when :left then
57
+ # do nothing
58
+ when :center then
59
+ x -= string.length * font.width / 2
60
+ when :right then
61
+ x -= string.length * font.width
62
+ else
63
+ raise ArgumentError, "Unknown align: #{align.inspect}"
64
+ end
65
+
66
+ x_offset, width = 0, font.width
67
+
68
+ string.split(//).each do |char|
69
+ self.composite font[char], x + x_offset, y
70
+ x_offset += width
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,47 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ require 'png'
4
+
5
+ class PNG
6
+ FULL = 360.0
7
+ HALF = FULL / 2
8
+
9
+ def self.angle(x, y)
10
+ return 0 if x == 0 and y == 0
11
+ rad_to_deg = 180.0 / Math::PI
12
+ (Math.atan2(-y, x) * rad_to_deg + 90) % 360
13
+ end
14
+
15
+ ##
16
+ # Makes a pie chart you can pass to PNG.new:
17
+ #
18
+ # png = PNG.new pie_chart(250, 0.30)
19
+ # png.save "pie.png"
20
+ # system 'open pie.png'
21
+
22
+ def self.pie_chart(diameter, pct_green,
23
+ good_color=PNG::Color::Green, bad_color=PNG::Color::Red)
24
+ diameter += 1 if diameter % 2 == 0
25
+ radius = (diameter / 2.0).to_i
26
+ pct_in_deg = FULL * pct_green
27
+ rad_to_deg = HALF / Math::PI
28
+
29
+ canvas = PNG::Canvas.new(diameter, diameter)
30
+
31
+ (-radius..radius).each do |x|
32
+ (-radius..radius).each do |y|
33
+ magnitude = Math.sqrt(x*x + y*y)
34
+ if magnitude <= radius then
35
+ angle = PNG.angle(x, y)
36
+ color = ((angle <= pct_in_deg) ? good_color : bad_color)
37
+
38
+ rx, ry = x+radius, y+radius
39
+
40
+ canvas[ rx, ry ] = color
41
+ end
42
+ end
43
+ end
44
+
45
+ canvas
46
+ end
47
+ end
@@ -0,0 +1,139 @@
1
+ require 'png'
2
+ require 'enumerator'
3
+
4
+ class PNG
5
+ def self.load_file path, metadata_only = false
6
+ self.load File.read(path), metadata_only
7
+ end
8
+
9
+ def self.load png, metadata_only = false
10
+ png = png.dup
11
+ signature = png.slice! 0, 8
12
+ raise ArgumentError, 'Invalid PNG signature' unless signature == SIGNATURE
13
+
14
+ ihdr = read_chunk 'IHDR', png
15
+
16
+ bit_depth, color_type, width, height = read_IHDR ihdr, metadata_only
17
+
18
+ return [width, height, bit_depth] if metadata_only
19
+
20
+ canvas = PNG::Canvas.new width, height
21
+
22
+ type = png.slice(4, 4).unpack('a4').first
23
+ read_chunk type, png if type == 'iCCP' # Ignore color profile
24
+
25
+ read_IDAT read_chunk('IDAT', png), bit_depth, color_type, canvas
26
+ read_chunk 'IEND', png
27
+
28
+ canvas
29
+ end
30
+
31
+ def self.read_chunk expected_type, png
32
+ size, type = png.slice!(0, 8).unpack 'Na4'
33
+ data, crc = png.slice!(0, size + 4).unpack "a#{size}N"
34
+
35
+ check_crc type, data, crc
36
+
37
+ raise ArgumentError, "Expected #{expected_type} chunk, not #{type}" unless
38
+ type == expected_type
39
+
40
+ return data
41
+ end
42
+
43
+ def self.check_crc type, data, crc
44
+ return true if (type + data).png_crc == crc
45
+ raise ArgumentError, "Invalid CRC encountered in #{type} chunk"
46
+ end
47
+
48
+ def self.read_IHDR data, metadata_only = false
49
+ width, height, bit_depth, color_type, *rest = data.unpack 'N2C5'
50
+
51
+ unless metadata_only then
52
+ raise ArgumentError, "Wrong bit depth: #{bit_depth}" unless
53
+ bit_depth == 8
54
+ raise ArgumentError, "Wrong color type: #{color_type}" unless
55
+ color_type == RGBA or color_type = RGB
56
+ raise ArgumentError, "Unsupported options: #{rest.inspect}" unless
57
+ rest == [0, 0, 0]
58
+ end
59
+
60
+ return bit_depth, color_type, width, height
61
+ end
62
+
63
+ def self.read_IDAT data, bit_depth, color_type, canvas
64
+ data = Zlib::Inflate.inflate(data).unpack 'C*'
65
+
66
+ pixel_size = color_type == RGBA ? 4 : 3
67
+
68
+ height = canvas.height
69
+ scanline_length = pixel_size * canvas.width + 1 # for filter
70
+
71
+ row = canvas.height - 1
72
+ until data.empty? do
73
+ row_data = data.slice! 0, scanline_length
74
+
75
+ filter = row_data.shift
76
+ case filter
77
+ when NONE then
78
+ when SUB then
79
+ row_data.each_with_index do |byte, index|
80
+ left = index < pixel_size ? 0 : row_data[index - pixel_size]
81
+ row_data[index] = (byte + left) % 256
82
+ end
83
+ when UP then
84
+ row_data.each_with_index do |byte, index|
85
+ col = index / pixel_size
86
+ upper = row == 0 ? 0 : canvas[col, row + 1].values[index % pixel_size]
87
+ row_data[index] = (upper + byte) % 256
88
+ end
89
+ when AVG then
90
+ row_data.each_with_index do |byte, index|
91
+ col = index / pixel_size
92
+ upper = row == 0 ? 0 : canvas[col, row + 1].values[index % pixel_size]
93
+ left = index < pixel_size ? 0 : row_data[index - pixel_size]
94
+
95
+ row_data[index] = (byte + ((left + upper)/2).floor) % 256
96
+ end
97
+ when PAETH then
98
+ left = upper = upper_left = nil
99
+ row_data.each_with_index do |byte, index|
100
+ col = index / pixel_size
101
+
102
+ left = index < pixel_size ? 0 : row_data[index - pixel_size]
103
+ if row == height then
104
+ upper = upper_left = 0
105
+ else
106
+ upper = canvas[col, row + 1].values[index % pixel_size]
107
+ upper_left = col == 0 ? 0 :
108
+ canvas[col - 1, row + 1].values[index % pixel_size]
109
+ end
110
+
111
+ paeth = paeth left, upper, upper_left
112
+ row_data[index] = (byte + paeth) % 256
113
+ end
114
+ else
115
+ raise ArgumentError, "invalid filter algorithm #{filter}"
116
+ end
117
+
118
+ col = 0
119
+ row_data.each_slice pixel_size do |slice|
120
+ slice << 0xFF if pixel_size == 3
121
+ canvas[col, row] = PNG::Color.new(*slice)
122
+ col += 1
123
+ end
124
+
125
+ row -= 1
126
+ end
127
+ end
128
+
129
+ def self.paeth a, b, c # left, above, upper left
130
+ p = a + b - c
131
+ pa = (p - a).abs
132
+ pb = (p - b).abs
133
+ pc = (p - c).abs
134
+
135
+ return a if pa <= pb && pa <= pc
136
+ return b if pb <= pc
137
+ c
138
+ end
139
+ end
@@ -0,0 +1,529 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'png'
4
+ require 'png/reader'
5
+ require 'png/pie'
6
+
7
+ class TestPng < Test::Unit::TestCase
8
+
9
+ def setup
10
+ @canvas = PNG::Canvas.new 5, 10, PNG::Color::White
11
+ @png = PNG.new @canvas
12
+
13
+ @blob = <<-EOF.unpack('m*').first
14
+ iVBORw0KGgoAAAANSUhEUgAAAAUAAAAKCAYAAAB8OZQwAAAAD0lEQVR4nGP4
15
+ jwUwDGVBALuJxzlQugpEAAAAAElFTkSuQmCC
16
+ EOF
17
+ end
18
+
19
+ def test_class_chunk
20
+ chunk = PNG.chunk 'IHDR', [10, 10, 8, 6, 0, 0, 0 ].pack('N2C5')
21
+
22
+ header_crc = "\2152\317\275"
23
+ header_data = "\000\000\000\n\000\000\000\n\b\006\000\000\000"
24
+ header_length = "\000\000\000\r"
25
+ header_chunk = "#{header_length}IHDR#{header_data}#{header_crc}"
26
+
27
+ assert_equal header_chunk, chunk
28
+ end
29
+
30
+ def test_class_chunk_empty
31
+ chunk = PNG.chunk 'IHDR'
32
+ expected = "#{0.chr * 4}IHDR#{["IHDR".png_crc].pack 'N'}"
33
+ assert_equal expected, chunk
34
+ end
35
+
36
+ def test_to_blob
37
+ assert_equal @blob, @png.to_blob
38
+ end
39
+
40
+ def test_save
41
+ path = "blah.png"
42
+ @png.save(path)
43
+ assert_equal @blob, File.read(path)
44
+ ensure
45
+ assert_equal 1, File.unlink(path)
46
+ end
47
+
48
+ end
49
+
50
+ class TestCanvas < Test::Unit::TestCase
51
+
52
+ def setup
53
+ @canvas = PNG::Canvas.new 5, 10, PNG::Color::White
54
+ end
55
+
56
+ def test_composite_default
57
+ canvas1, canvas2 = util_composite_canvases
58
+
59
+ canvas1.composite canvas2, 1, 1
60
+
61
+ expected = " xxxxxxxx
62
+ xxxxxxxx
63
+ xx..xxxx
64
+ ..xxxxxx
65
+ ".gsub(/ /, '')
66
+
67
+ assert_equal expected, canvas1.to_s.gsub(/ /, 'x')
68
+ end
69
+
70
+ def test_composite_underlay
71
+ canvas1, canvas2 = util_composite_canvases
72
+
73
+ canvas1.composite canvas2, 1, 1, :add
74
+
75
+ expected = " xxxxxxxx
76
+ xxxx..xx
77
+ xx00xxxx
78
+ ..xxxxxx
79
+ ".gsub(/ /, '')
80
+
81
+ assert_equal expected, canvas1.to_s.gsub(/ /, 'x')
82
+ end
83
+
84
+ def test_composite_overlay
85
+ canvas1, canvas2 = util_composite_canvases
86
+
87
+ canvas1.composite canvas2, 1, 1, :overlay
88
+
89
+ expected = " xxxxxxxx
90
+ xxxx..xx
91
+ xx..xxxx
92
+ ..xxxxxx
93
+ ".gsub(/ /, '')
94
+
95
+ assert_equal expected, canvas1.to_s.gsub(/ /, 'x')
96
+ end
97
+
98
+ def test_composite_blend
99
+ canvas1, canvas2 = util_composite_canvases
100
+
101
+ canvas1.composite canvas2, 1, 1, :blend
102
+
103
+ expected = " xxxxxxxx
104
+ xxxx..xx
105
+ xx,,xxxx
106
+ ..xxxxxx
107
+ ".gsub(/ /, '')
108
+
109
+ assert_equal expected, canvas1.to_s.gsub(/ /, 'x')
110
+ end
111
+
112
+ def test_composite_bad_style
113
+ canvas1, canvas2 = util_composite_canvases
114
+
115
+ assert_raises RuntimeError do
116
+ canvas1.composite canvas2, 1, 1, :bad
117
+ end
118
+ end
119
+
120
+ def test_extract
121
+ canvas1, _ = util_composite_canvases
122
+
123
+ expected = " xxxxxxxx
124
+ xxxx..xx
125
+ xx00xxxx
126
+ ..xxxxxx
127
+ ".gsub(/ /, '')
128
+
129
+ assert_equal expected, canvas1.to_s.gsub(/ /, 'x')
130
+
131
+ canvas2 = canvas1.extract(1, 1, 2, 2)
132
+
133
+ expected = " xx..
134
+ 00xx
135
+ ".gsub(/ /, '')
136
+
137
+ assert_equal expected, canvas2.to_s.gsub(/ /, 'x')
138
+ end
139
+
140
+ def test_index
141
+ assert_equal PNG::Color::White, @canvas[1, 2]
142
+ assert_same @canvas[1, 2], @canvas.data[1][2]
143
+ end
144
+
145
+ def test_index_tall
146
+ @canvas = PNG::Canvas.new 2, 4, PNG::Color::White
147
+ @canvas[ 0, 0] = PNG::Color::Black
148
+ @canvas[ 0, 3] = PNG::Color::Background
149
+ @canvas[ 1, 0] = PNG::Color::Yellow
150
+ @canvas[ 1, 3] = PNG::Color::Blue
151
+
152
+ expected = " ,,\n0000\n0000\n..++\n"
153
+
154
+ assert_equal expected, @canvas.to_s
155
+ end
156
+
157
+ def test_index_wide
158
+ @canvas = PNG::Canvas.new 4, 2, PNG::Color::White
159
+ @canvas[ 0, 0] = PNG::Color::Black
160
+ @canvas[ 3, 0] = PNG::Color::Background
161
+ @canvas[ 0, 1] = PNG::Color::Yellow
162
+ @canvas[ 3, 1] = PNG::Color::Blue
163
+
164
+ expected = "++0000,,\n..0000 \n"
165
+
166
+ assert_equal expected, @canvas.to_s
167
+ end
168
+
169
+ def test_index_bad_x
170
+ begin
171
+ @canvas[6, 1]
172
+ rescue => e
173
+ assert_equal "bad x value 6 >= 5", e.message
174
+ else
175
+ flunk "didn't raise"
176
+ end
177
+ end
178
+
179
+ def test_index_bad_y
180
+ begin
181
+ @canvas[1, 11]
182
+ rescue => e
183
+ assert_equal "bad y value 11 >= 10", e.message
184
+ else
185
+ flunk "didn't raise"
186
+ end
187
+ end
188
+
189
+ def test_index_equals
190
+ @canvas[1, 2] = PNG::Color::Red
191
+ assert_equal PNG::Color::Red, @canvas[1, 2]
192
+ assert_same @canvas[1, 2], @canvas.data[7][1]
193
+
194
+ expected = "
195
+ 0000000000
196
+ 0000000000
197
+ 0000000000
198
+ 0000000000
199
+ 0000000000
200
+ 0000000000
201
+ 0000000000
202
+ 00,,000000
203
+ 0000000000
204
+ 0000000000".strip + "\n"
205
+ actual = @canvas.to_s
206
+ assert_equal expected, actual
207
+ end
208
+
209
+ def test_index_equals_bad_x
210
+ begin
211
+ @canvas[6, 1] = PNG::Color::Red
212
+ rescue => e
213
+ assert_equal "bad x value 6 >= 5", e.message
214
+ else
215
+ flunk "didn't raise"
216
+ end
217
+ end
218
+
219
+ def test_index_equals_bad_y
220
+ begin
221
+ @canvas[1, 11] = PNG::Color::Red
222
+ rescue => e
223
+ assert_equal "bad y value 11 >= 10", e.message
224
+ else
225
+ flunk "didn't raise"
226
+ end
227
+ end
228
+
229
+ # def test_point
230
+ # raise NotImplementedError, 'Need to write test_point'
231
+ # end
232
+
233
+ def test_inspect
234
+ assert_equal "#<PNG::Canvas 5x10>", @canvas.inspect
235
+ end
236
+
237
+ def test_point
238
+ assert_equal PNG::Color.new(0xff, 0x7f, 0xff, 0xff),
239
+ @canvas.point(0, 0, PNG::Color::Magenta)
240
+ # flunk "this doesn't test ANYTHING"
241
+ end
242
+
243
+ def test_line
244
+ @canvas.line 0, 9, 4, 0, PNG::Color::Black
245
+
246
+ expected = <<-EOF
247
+ ,,00000000
248
+ ,,00000000
249
+ ,,,,000000
250
+ 00..000000
251
+ 00,,,,0000
252
+ 0000..0000
253
+ 0000,,,,00
254
+ 000000..00
255
+ 000000,,,,
256
+ 00000000..
257
+ EOF
258
+
259
+ assert_equal expected, @canvas.to_s
260
+ end
261
+
262
+ def test_positive_slope_line
263
+ @canvas.line 0, 0, 4, 9, PNG::Color::Black
264
+
265
+ expected = <<-EOF
266
+ 00000000,,
267
+ 00000000,,
268
+ 000000,,,,
269
+ 000000..00
270
+ 0000,,,,00
271
+ 0000..0000
272
+ 00,,,,0000
273
+ 00..000000
274
+ ,,,,000000
275
+ ..00000000
276
+ EOF
277
+
278
+ assert_equal expected, @canvas.to_s
279
+ end
280
+
281
+ def test_to_s_normal
282
+ @canvas = PNG::Canvas.new 5, 10, PNG::Color::White
283
+ expected = util_ascii_art(5, 10)
284
+ assert_equal expected, @canvas.to_s
285
+ end
286
+
287
+ def test_to_s_wide
288
+ @canvas = PNG::Canvas.new 250, 10, PNG::Color::White
289
+ expected = util_ascii_art(36, 2) # scaled
290
+ assert_equal expected, @canvas.to_s
291
+ end
292
+
293
+ def test_to_s_tall
294
+ @canvas = PNG::Canvas.new 10, 250, PNG::Color::White
295
+ expected = util_ascii_art(10, 250)
296
+ assert_equal expected, @canvas.to_s
297
+ end
298
+
299
+ def test_to_s_huge
300
+ @canvas = PNG::Canvas.new 250, 250, PNG::Color::White
301
+ expected = util_ascii_art(36, 36) # scaled
302
+ assert_equal expected, @canvas.to_s
303
+ end
304
+
305
+ def util_composite_canvases
306
+ canvas1 = PNG::Canvas.new 4, 4
307
+ canvas1[0, 0] = PNG::Color::Black
308
+ canvas1[1, 1] = PNG::Color::White
309
+ canvas1[2, 2] = PNG::Color::Black
310
+
311
+ expected = " xxxxxxxx
312
+ xxxx..xx
313
+ xx00xxxx
314
+ ..xxxxxx
315
+ ".gsub(/ /, '')
316
+
317
+ assert_equal expected, canvas1.to_s.gsub(/ /, 'x')
318
+
319
+
320
+ canvas2 = PNG::Canvas.new 2, 2
321
+ canvas2[0, 0] = PNG::Color::Black
322
+
323
+ expected = " xxxx
324
+ ..xx
325
+ ".gsub(/ /, '')
326
+
327
+ assert_equal expected, canvas2.to_s.gsub(/ /, 'x')
328
+
329
+ return canvas1, canvas2
330
+ end
331
+
332
+ def util_ascii_art(width, height)
333
+ (("0" * width * 2) + "\n") * height
334
+ end
335
+ end
336
+
337
+ class TestPng::TestColor < Test::Unit::TestCase
338
+ def setup
339
+ @color = PNG::Color.new 0x01, 0x02, 0x03, 0x04
340
+ end
341
+
342
+ def test_class_from_str
343
+ @color = PNG::Color.from "0x01020304"
344
+ test_r
345
+ test_g
346
+ test_b
347
+ test_a
348
+ end
349
+
350
+ def test_class_from_int
351
+ @color = PNG::Color.from 0x01020304
352
+ test_r
353
+ test_g
354
+ test_b
355
+ test_a
356
+ end
357
+
358
+ def test_r
359
+ assert_equal 0x01, @color.r
360
+ end
361
+
362
+ def test_g
363
+ assert_equal 0x02, @color.g
364
+ end
365
+
366
+ def test_b
367
+ assert_equal 0x03, @color.b
368
+ end
369
+
370
+ def test_a
371
+ assert_equal 0x04, @color.a
372
+ end
373
+
374
+ def test_blend
375
+ # c1 = @color
376
+ # c2 = PNG::Color.new 0xFF, 0xFE, 0xFD, 0xFC
377
+
378
+ # assert_equal PNG::Color.new(0xFB, 0xFA, 0xF9, 0xF8), c1.blend(c2)
379
+
380
+ c1 = PNG::Color::White
381
+ c2 = PNG::Color::Black
382
+
383
+ assert_equal PNG::Color::Gray, c2.blend(c1)
384
+ assert_equal PNG::Color::Gray, c1.blend(c2)
385
+ end
386
+
387
+ def test_intensity
388
+ assert_equal PNG::Color.new(0x01, 0x02, 0x03, 0x3c), @color.intensity(0xf00)
389
+ end
390
+
391
+ def test_inspect
392
+ assert_equal "#<PNG::Color 01 02 03 04>", @color.inspect
393
+ end
394
+
395
+ def test_inspect_name
396
+ assert_equal "#<PNG::Color Red>", PNG::Color::Red.inspect
397
+ end
398
+
399
+ def test_pipe
400
+ b = PNG::Color::Black
401
+ w = PNG::Color::White
402
+ t = PNG::Color::Background
403
+
404
+ # first non-transparent
405
+ assert_equal b, b | t
406
+ assert_equal b, t | b
407
+
408
+ assert_equal b, b | w
409
+ assert_equal w, w | b
410
+
411
+ assert_equal t, t | t
412
+ end
413
+
414
+ def test_to_ascii
415
+ assert_equal '00', PNG::Color::White.to_ascii, "white"
416
+ assert_equal '++', PNG::Color::Yellow.to_ascii, "yellow"
417
+ assert_equal ',,', PNG::Color::Red.to_ascii, "red"
418
+ assert_equal '..', PNG::Color::Black.to_ascii, "black"
419
+ assert_equal ' ', PNG::Color::Background.to_ascii, "background"
420
+ end
421
+
422
+ def test_to_ascii_alpha
423
+ assert_equal '00', PNG::Color.new(255,255,255,255).to_ascii
424
+ assert_equal '00', PNG::Color.new(255,255,255,192).to_ascii
425
+ assert_equal '++', PNG::Color.new(255,255,255,191).to_ascii
426
+ assert_equal ',,', PNG::Color.new(255,255,255,127).to_ascii
427
+ assert_equal ',,', PNG::Color.new(255,255,255,126).to_ascii
428
+ assert_equal ',,', PNG::Color.new(255,255,255, 64).to_ascii
429
+ assert_equal '..', PNG::Color.new(255,255,255, 63).to_ascii
430
+ assert_equal '..', PNG::Color.new(255,255,255, 1).to_ascii
431
+ assert_equal ' ', PNG::Color.new(255,255,255, 0).to_ascii
432
+ end
433
+
434
+ def test_to_s_name
435
+ assert_equal 'Red', PNG::Color::Red.to_s
436
+ end
437
+
438
+ def test_to_s
439
+ obj = PNG::Color.new(255,255,255, 0)
440
+ assert_equal '#<PNG::Color:0xXXXXXX>', obj.to_s.sub(/0x[0-9a-f]+/, '0xXXXXXX')
441
+ end
442
+
443
+ def test_equals2
444
+ assert_equal PNG::Color.new(255,255,255, 0), PNG::Color.new(255,255,255, 0)
445
+ end
446
+
447
+ def test_hash
448
+ a = PNG::Color.new(255,255,255, 0)
449
+ b = PNG::Color.new(255,255,255, 0)
450
+ assert_equal a.hash, b.hash
451
+ end
452
+
453
+ # def test_values
454
+ # raise NotImplementedError, 'Need to write test_values'
455
+ # end
456
+ end
457
+
458
+ class TestPng::TestPie < Test::Unit::TestCase
459
+ def setup
460
+
461
+ end
462
+
463
+ def test_pie_chart_odd
464
+ expected =
465
+ [" .. ",
466
+ " ,,,,,,........ ",
467
+ " ,,,,,,,,.......... ",
468
+ " ,,,,,,,,.......... ",
469
+ " ,,,,,,,,.......... ",
470
+ ",,,,,,,,,,............",
471
+ " ,,,,,,,,,,,,,,,,,, ",
472
+ " ,,,,,,,,,,,,,,,,,, ",
473
+ " ,,,,,,,,,,,,,,,,,, ",
474
+ " ,,,,,,,,,,,,,, ",
475
+ " ,, ",
476
+ nil].join("\n")
477
+
478
+ actual = PNG::pie_chart(11, 0.25, PNG::Color::Black, PNG::Color::Green)
479
+ assert_equal expected, actual.to_s
480
+ end
481
+
482
+ def test_pie_chart_even
483
+ expected =
484
+ [" .. ",
485
+ " ,,,,,,........ ",
486
+ " ,,,,,,,,.......... ",
487
+ " ,,,,,,,,.......... ",
488
+ " ,,,,,,,,.......... ",
489
+ ",,,,,,,,,,............",
490
+ " ,,,,,,,,,,,,,,,,,, ",
491
+ " ,,,,,,,,,,,,,,,,,, ",
492
+ " ,,,,,,,,,,,,,,,,,, ",
493
+ " ,,,,,,,,,,,,,, ",
494
+ " ,, ",
495
+ nil].join("\n")
496
+
497
+ actual = PNG::pie_chart(10, 0.25, PNG::Color::Black, PNG::Color::Green)
498
+ assert_equal expected, actual.to_s
499
+ end
500
+
501
+ def util_angle(expect, x, y)
502
+ actual = PNG.angle(x, y)
503
+ case expect
504
+ when Integer then
505
+ assert_equal(expect, actual,
506
+ "[#{x}, #{y}] should be == #{expect}, was #{actual}")
507
+ else
508
+ assert_in_delta(expect, actual, 0.5)
509
+ end
510
+ end
511
+
512
+ def test_math_is_hard_lets_go_shopping
513
+ util_angle 0, 0, 0
514
+ (25..500).step(25) do |n|
515
+ util_angle 0, 0, n
516
+ util_angle 90, n, 0
517
+ util_angle 180, 0, -n
518
+ util_angle 270, -n, 0
519
+ end
520
+
521
+ util_angle 359.5, -1, 250
522
+ util_angle 0.0, 0, 250
523
+ util_angle 0.5, 1, 250
524
+
525
+ util_angle 89.5, 250, 1
526
+ util_angle 90.0, 250, 0
527
+ util_angle 90.5, 250, -1
528
+ end
529
+ end