chunky_png 1.3.11 → 1.3.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ruby.yml +35 -0
  3. data/.standard.yml +16 -0
  4. data/.yardopts +1 -1
  5. data/CHANGELOG.rdoc +8 -4
  6. data/CONTRIBUTING.rdoc +17 -8
  7. data/Gemfile +15 -3
  8. data/LICENSE +1 -1
  9. data/README.md +15 -9
  10. data/Rakefile +5 -3
  11. data/benchmarks/decoding_benchmark.rb +17 -17
  12. data/benchmarks/encoding_benchmark.rb +22 -19
  13. data/benchmarks/filesize_benchmark.rb +6 -6
  14. data/bin/rake +29 -0
  15. data/bin/standardrb +29 -0
  16. data/chunky_png.gemspec +17 -15
  17. data/docs/.gitignore +3 -0
  18. data/docs/CNAME +1 -0
  19. data/docs/_config.yml +9 -0
  20. data/docs/_posts/2010-01-14-memory-efficiency-when-using-ruby.md +136 -0
  21. data/docs/_posts/2010-01-17-ode-to-array-pack-and-string-unpack.md +82 -0
  22. data/docs/_posts/2014-11-07-the-value-of-a-pure-ruby-library.md +61 -0
  23. data/docs/index.md +88 -0
  24. data/lib/chunky_png.rb +17 -30
  25. data/lib/chunky_png/canvas.rb +31 -28
  26. data/lib/chunky_png/canvas/adam7_interlacing.rb +16 -10
  27. data/lib/chunky_png/canvas/data_url_exporting.rb +3 -3
  28. data/lib/chunky_png/canvas/data_url_importing.rb +3 -3
  29. data/lib/chunky_png/canvas/drawing.rb +30 -43
  30. data/lib/chunky_png/canvas/masking.rb +14 -14
  31. data/lib/chunky_png/canvas/operations.rb +28 -24
  32. data/lib/chunky_png/canvas/png_decoding.rb +39 -33
  33. data/lib/chunky_png/canvas/png_encoding.rb +111 -103
  34. data/lib/chunky_png/canvas/resampling.rb +27 -32
  35. data/lib/chunky_png/canvas/stream_exporting.rb +8 -8
  36. data/lib/chunky_png/canvas/stream_importing.rb +8 -8
  37. data/lib/chunky_png/chunk.rb +101 -66
  38. data/lib/chunky_png/color.rb +218 -212
  39. data/lib/chunky_png/datastream.rb +22 -28
  40. data/lib/chunky_png/dimension.rb +18 -11
  41. data/lib/chunky_png/image.rb +11 -11
  42. data/lib/chunky_png/palette.rb +6 -9
  43. data/lib/chunky_png/point.rb +27 -26
  44. data/lib/chunky_png/rmagick.rb +10 -10
  45. data/lib/chunky_png/vector.rb +28 -29
  46. data/lib/chunky_png/version.rb +3 -1
  47. data/spec/chunky_png/canvas/adam7_interlacing_spec.rb +20 -21
  48. data/spec/chunky_png/canvas/data_url_exporting_spec.rb +8 -5
  49. data/spec/chunky_png/canvas/data_url_importing_spec.rb +5 -6
  50. data/spec/chunky_png/canvas/drawing_spec.rb +46 -38
  51. data/spec/chunky_png/canvas/masking_spec.rb +15 -16
  52. data/spec/chunky_png/canvas/operations_spec.rb +68 -67
  53. data/spec/chunky_png/canvas/png_decoding_spec.rb +37 -38
  54. data/spec/chunky_png/canvas/png_encoding_spec.rb +59 -50
  55. data/spec/chunky_png/canvas/resampling_spec.rb +19 -21
  56. data/spec/chunky_png/canvas/stream_exporting_spec.rb +47 -27
  57. data/spec/chunky_png/canvas/stream_importing_spec.rb +10 -11
  58. data/spec/chunky_png/canvas_spec.rb +63 -52
  59. data/spec/chunky_png/color_spec.rb +115 -114
  60. data/spec/chunky_png/datastream_spec.rb +49 -51
  61. data/spec/chunky_png/dimension_spec.rb +10 -10
  62. data/spec/chunky_png/image_spec.rb +11 -14
  63. data/spec/chunky_png/point_spec.rb +21 -23
  64. data/spec/chunky_png/rmagick_spec.rb +7 -8
  65. data/spec/chunky_png/vector_spec.rb +21 -17
  66. data/spec/chunky_png_spec.rb +2 -2
  67. data/spec/png_suite_spec.rb +35 -40
  68. data/spec/spec_helper.rb +6 -10
  69. data/tasks/benchmarks.rake +7 -8
  70. metadata +46 -10
  71. data/.travis.yml +0 -18
  72. data/lib/chunky_png/compatibility.rb +0 -15
@@ -1,33 +1,33 @@
1
- require 'rmagick'
1
+ # frozen-string-literal: true
2
+
3
+ require "rmagick"
2
4
 
3
5
  module ChunkyPNG
4
-
5
6
  # Methods for importing and exporting RMagick image objects.
6
7
  #
7
8
  # By default, this module is disabled because of the dependency on RMagick.
8
- # You need to include this module yourself if you want to use it.
9
+ # You need to include this module yourself if you want to use it.
9
10
  #
10
11
  # @example
11
12
  #
12
13
  # require 'rmagick'
13
14
  # require 'chunky_png/rmagick'
14
- #
15
+ #
15
16
  # canvas = ChunkyPNG::Canvas.from_file('filename.png')
16
17
  # image = ChunkyPNG::RMagick.export(canvas)
17
- #
18
+ #
18
19
  # # do something with the image using RMagick
19
- #
20
+ #
20
21
  # updated_canvas = ChunkyPNG::RMagick.import(image)
21
22
  #
22
23
  module RMagick
23
-
24
24
  extend self
25
-
25
+
26
26
  # Imports an RMagick image as Canvas object.
27
27
  # @param [Magick::Image] image The image to import
28
28
  # @return [ChunkyPNG::Canvas] The canvas, constructed from the RMagick image.
29
29
  def import(image)
30
- pixels = image.export_pixels_to_str(0, 0, image.columns, image.rows, 'RGBA')
30
+ pixels = image.export_pixels_to_str(0, 0, image.columns, image.rows, "RGBA")
31
31
  ChunkyPNG::Canvas.from_rgba_stream(image.columns, image.rows, pixels)
32
32
  end
33
33
 
@@ -36,7 +36,7 @@ module ChunkyPNG
36
36
  # @return [Magick::Image] The RMagick image constructed from the Canvas instance.
37
37
  def export(canvas)
38
38
  image = Magick::Image.new(canvas.width, canvas.height)
39
- image.import_pixels(0,0, canvas.width, canvas.height, 'RGBA', canvas.pixels.pack('N*'))
39
+ image.import_pixels(0, 0, canvas.width, canvas.height, "RGBA", canvas.pixels.pack("N*"))
40
40
  image
41
41
  end
42
42
  end
@@ -1,9 +1,10 @@
1
- module ChunkyPNG
1
+ # frozen-string-literal: true
2
2
 
3
+ module ChunkyPNG
3
4
  # Factory method for {ChunkyPNG::Vector} instances.
4
5
  #
5
6
  # @overload Vector(x0, y0, x1, y1, x2, y2, ...)
6
- # Creates a vector by parsing two subsequent values in the argument list
7
+ # Creates a vector by parsing two subsequent values in the argument list
7
8
  # as x- and y-coordinate of a point.
8
9
  # @return [ChunkyPNG::Vector] The instantiated vector.
9
10
  # @overload Vector(string)
@@ -17,27 +18,25 @@ module ChunkyPNG
17
18
  # @raise [ArgumentError] If the given arguments could not be understood as a vector.
18
19
  # @see ChunkyPNG::Vector
19
20
  def self.Vector(*args)
20
-
21
- return args.first if args.length == 1 && args.first.kind_of?(ChunkyPNG::Vector)
22
-
21
+ return args.first if args.length == 1 && args.first.is_a?(ChunkyPNG::Vector)
22
+
23
23
  if args.length == 1 && args.first.respond_to?(:scan)
24
24
  ChunkyPNG::Vector.new(ChunkyPNG::Vector.multiple_from_string(args.first)) # e.g. ['1,1 2,2 3,3']
25
25
  else
26
26
  ChunkyPNG::Vector.new(ChunkyPNG::Vector.multiple_from_array(args)) # e.g. [[1,1], [2,2], [3,3]] or [1,1,2,2,3,3]
27
27
  end
28
28
  end
29
-
29
+
30
30
  # Class that represents a vector of points, i.e. a list of {ChunkyPNG::Point} instances.
31
31
  #
32
- # Vectors can be created quite flexibly. See the {ChunkyPNG.Vector} factory methods for
32
+ # Vectors can be created quite flexibly. See the {ChunkyPNG.Vector} factory methods for
33
33
  # more information on how to construct vectors.
34
34
  class Vector
35
-
36
35
  include Enumerable
37
-
36
+
38
37
  # @return [Array<ChunkyPNG::Point>] The array that holds all the points in this vector.
39
38
  attr_reader :points
40
-
39
+
41
40
  # Initializes a vector based on a list of Point instances.
42
41
  #
43
42
  # You usually do not want to use this method directly, but call {ChunkyPNG.Vector} instead.
@@ -47,7 +46,7 @@ module ChunkyPNG
47
46
  def initialize(points = [])
48
47
  @points = points
49
48
  end
50
-
49
+
51
50
  # Iterates over all the edges in this vector.
52
51
  #
53
52
  # An edge is a combination of two subsequent points in the vector. Together, they will form
@@ -63,14 +62,14 @@ module ChunkyPNG
63
62
  points.each_cons(2) { |a, b| yield(a, b) }
64
63
  yield(points.last, points.first) if close
65
64
  end
66
-
65
+
67
66
  # Returns the point with the given indexof this vector.
68
67
  # @param [Integer] index The 0-based index of the point in this vector.
69
- # @param [ChunkyPNG::Point] The point instance.
68
+ # @return [ChunkyPNG::Point] The point instance.
70
69
  def [](index)
71
70
  points[index]
72
71
  end
73
-
72
+
74
73
  # Returns an enumerator that will iterate over all the edges in this vector.
75
74
  # @param (see #each_edge)
76
75
  # @return [Enumerator] The enumerator that iterates over the edges.
@@ -79,28 +78,28 @@ module ChunkyPNG
79
78
  def edges(close = true)
80
79
  to_enum(:each_edge, close)
81
80
  end
82
-
81
+
83
82
  # Returns the number of points in this vector.
84
83
  # @return [Integer] The length of the points array.
85
84
  def length
86
85
  points.length
87
86
  end
88
-
87
+
89
88
  # Iterates over all the points in this vector
90
89
  # @yield [ChunkyPNG::Point] The points in the correct order.
91
90
  # @return [void]
92
91
  def each(&block)
93
92
  points.each(&block)
94
93
  end
95
-
94
+
96
95
  # Comparison between two vectors for quality.
97
96
  # @param [ChunkyPNG::Vector] other The vector to compare with.
98
97
  # @return [true, false] true if the list of points are identical
99
98
  def eql?(other)
100
99
  other.points == points
101
100
  end
102
-
103
- alias_method :==, :eql?
101
+
102
+ alias == eql?
104
103
 
105
104
  # Returns the range in x-coordinates for all the points in this vector.
106
105
  # @return [Range] The (inclusive) range of x-coordinates.
@@ -113,13 +112,13 @@ module ChunkyPNG
113
112
  def y_range
114
113
  Range.new(*points.map { |p| p.y }.minmax)
115
114
  end
116
-
115
+
117
116
  # Finds the lowest x-coordinate in this vector.
118
117
  # @return [Integer] The lowest x-coordinate of all the points in the vector.
119
118
  def min_x
120
119
  x_range.first
121
120
  end
122
-
121
+
123
122
  # Finds the highest x-coordinate in this vector.
124
123
  # @return [Integer] The highest x-coordinate of all the points in the vector.
125
124
  def max_x
@@ -131,13 +130,13 @@ module ChunkyPNG
131
130
  def min_y
132
131
  y_range.first
133
132
  end
134
-
133
+
135
134
  # Finds the highest y-coordinate in this vector.
136
135
  # @return [Integer] The highest y-coordinate of all the points in the vector.
137
136
  def max_y
138
137
  y_range.last
139
138
  end
140
-
139
+
141
140
  # Returns the offset from (0,0) of the minimal bounding box of all the
142
141
  # points in this vector
143
142
  # @return [ChunkyPNG::Point] A point that describes the top left corner if a
@@ -145,7 +144,7 @@ module ChunkyPNG
145
144
  def offset
146
145
  ChunkyPNG::Point.new(min_x, min_y)
147
146
  end
148
-
147
+
149
148
  # Returns the width of the minimal bounding box of all the points in this vector.
150
149
  # @return [Integer] The x-distance between the points that are farthest from each other.
151
150
  def width
@@ -157,17 +156,17 @@ module ChunkyPNG
157
156
  def height
158
157
  1 + (max_y - min_y)
159
158
  end
160
-
159
+
161
160
  # Returns the dimension of the minimal bounding rectangle of the points in this vector.
162
- # @return [ChunkyPNG::Dimension] The dimension instance with the width and height
161
+ # @return [ChunkyPNG::Dimension] The dimension instance with the width and height
163
162
  def dimension
164
163
  ChunkyPNG::Dimension.new(width, height)
165
164
  end
166
-
165
+
167
166
  # @return [Array<ChunkyPNG::Point>] The list of points interpreted from the input array.
168
167
  def self.multiple_from_array(source)
169
168
  return [] if source.empty?
170
- if source.first.kind_of?(Numeric) || source.first =~ /^\d+$/
169
+ if source.first.is_a?(Numeric) || source.first =~ /^\d+$/
171
170
  raise ArgumentError, "The points array is expected to have an even number of items!" if source.length % 2 != 0
172
171
 
173
172
  points = []
@@ -177,7 +176,7 @@ module ChunkyPNG
177
176
  source.map { |p| ChunkyPNG::Point(p) }
178
177
  end
179
178
  end
180
-
179
+
181
180
  # @return [Array<ChunkyPNG::Point>] The list of points parsed from the string.
182
181
  def self.multiple_from_string(source_str)
183
182
  multiple_from_array(source_str.scan(/[\(\[\{]?(\d+)\s*[,x]?\s*(\d+)[\)\]\}]?/))
@@ -1,5 +1,7 @@
1
+ # frozen-string-literal: true
2
+
1
3
  module ChunkyPNG
2
4
  # The current version of ChunkyPNG.
3
5
  # Set it and commit the change this before running rake release.
4
- VERSION = "1.3.11"
6
+ VERSION = "1.3.14"
5
7
  end
@@ -1,48 +1,48 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
2
 
3
3
  describe ChunkyPNG::Canvas::Adam7Interlacing do
4
4
  include ChunkyPNG::Canvas::Adam7Interlacing
5
5
 
6
- describe '#adam7_pass_sizes' do
6
+ describe "#adam7_pass_sizes" do
7
7
  it "should get the pass sizes for a 8x8 image correctly" do
8
8
  expect(adam7_pass_sizes(8, 8)).to eql [
9
- [1, 1], [1, 1], [2, 1], [2, 2], [4, 2], [4, 4], [8, 4]
10
- ]
9
+ [1, 1], [1, 1], [2, 1], [2, 2], [4, 2], [4, 4], [8, 4],
10
+ ]
11
11
  end
12
12
 
13
13
  it "should get the pass sizes for a 12x12 image correctly" do
14
14
  expect(adam7_pass_sizes(12, 12)).to eql [
15
- [2, 2], [1, 2], [3, 1], [3, 3], [6, 3], [6, 6], [12, 6]
16
- ]
15
+ [2, 2], [1, 2], [3, 1], [3, 3], [6, 3], [6, 6], [12, 6],
16
+ ]
17
17
  end
18
18
 
19
19
  it "should get the pass sizes for a 33x47 image correctly" do
20
20
  expect(adam7_pass_sizes(33, 47)).to eql [
21
- [5, 6], [4, 6], [9, 6], [8, 12], [17, 12], [16, 24], [33, 23]
22
- ]
21
+ [5, 6], [4, 6], [9, 6], [8, 12], [17, 12], [16, 24], [33, 23],
22
+ ]
23
23
  end
24
24
 
25
25
  it "should get the pass sizes for a 1x1 image correctly" do
26
26
  expect(adam7_pass_sizes(1, 1)).to eql [
27
- [1, 1], [0, 1], [1, 0], [0, 1], [1, 0], [0, 1], [1, 0]
28
- ]
27
+ [1, 1], [0, 1], [1, 0], [0, 1], [1, 0], [0, 1], [1, 0],
28
+ ]
29
29
  end
30
30
 
31
31
  it "should get the pass sizes for a 0x0 image correctly" do
32
32
  expect(adam7_pass_sizes(0, 0)).to eql [
33
- [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]
34
- ]
33
+ [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0],
34
+ ]
35
35
  end
36
36
 
37
37
  it "should always maintain the same amount of pixels in total" do
38
38
  [[8, 8], [12, 12], [33, 47], [1, 1], [0, 0]].each do |(width, height)|
39
39
  pass_sizes = adam7_pass_sizes(width, height)
40
- expect(pass_sizes.inject(0) { |sum, (w, h)| sum + (w*h) }).to eql width * height
40
+ expect(pass_sizes.inject(0) { |sum, (w, h)| sum + (w * h) }).to eql width * height
41
41
  end
42
42
  end
43
43
  end
44
44
 
45
- describe '#adam7_multiplier_offset' do
45
+ describe "#adam7_multiplier_offset" do
46
46
  it "should get the multiplier and offset values for pass 1 correctly" do
47
47
  expect(adam7_multiplier_offset(0)).to eql [3, 0, 3, 0]
48
48
  end
@@ -72,7 +72,7 @@ describe ChunkyPNG::Canvas::Adam7Interlacing do
72
72
  end
73
73
  end
74
74
 
75
- describe '#adam7_merge_pass' do
75
+ describe "#adam7_merge_pass" do
76
76
  it "should merge the submatrices correctly" do
77
77
  submatrices = [
78
78
  ChunkyPNG::Canvas.new(1, 1, 168430335), # r = 10
@@ -84,23 +84,22 @@ describe ChunkyPNG::Canvas::Adam7Interlacing do
84
84
  ChunkyPNG::Canvas.new(8, 4, 1175063295), # r = 70
85
85
  ]
86
86
 
87
- canvas = ChunkyPNG::Image.new(8,8)
87
+ canvas = ChunkyPNG::Image.new(8, 8)
88
88
  submatrices.each_with_index { |m, pass| adam7_merge_pass(pass, canvas, m) }
89
- expect(canvas).to eql reference_image('adam7')
89
+ expect(canvas).to eql reference_image("adam7")
90
90
  end
91
91
  end
92
92
 
93
- describe '#adam7_extract_pass' do
94
- before(:each) { @canvas = reference_canvas('adam7') }
93
+ describe "#adam7_extract_pass" do
94
+ before(:each) { @canvas = reference_canvas("adam7") }
95
95
 
96
96
  1.upto(7) do |pass|
97
97
  it "should extract pass #{pass} correctly" do
98
98
  sm = adam7_extract_pass(pass - 1, @canvas)
99
99
  expect(sm.pixels.length).to eql sm.width * sm.height
100
100
  expect(sm.pixels.uniq.length).to eql 1
101
- expect(ChunkyPNG::Color.r(sm[0,0])).to eql pass * 10
101
+ expect(ChunkyPNG::Color.r(sm[0, 0])).to eql pass * 10
102
102
  end
103
103
  end
104
104
  end
105
-
106
105
  end
@@ -1,11 +1,14 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
2
 
3
3
  describe ChunkyPNG::Canvas do
4
-
5
- describe '#to_data_url' do
4
+ describe "#to_data_url" do
6
5
  it "should export a sample canvas to an RGBA stream correctly" do
7
- canvas = ChunkyPNG::Canvas.new(2, 2, [ChunkyPNG::Color.rgba(1,2,3,4), ChunkyPNG::Color.rgba(5,6,7,8),
8
- ChunkyPNG::Color.rgba(4,3,2,1), ChunkyPNG::Color.rgba(8,7,6,5)])
6
+ canvas = ChunkyPNG::Canvas.new(2, 2, [
7
+ ChunkyPNG::Color.rgba(1, 2, 3, 4),
8
+ ChunkyPNG::Color.rgba(5, 6, 7, 8),
9
+ ChunkyPNG::Color.rgba(4, 3, 2, 1),
10
+ ChunkyPNG::Color.rgba(8, 7, 6, 5),
11
+ ])
9
12
 
10
13
  expect(canvas.to_data_url).to eql "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAgMAAAAP2OW3AAAADFBMVEUBAgMEAwIFBgcIBwazgAAdAAAABHRSTlMEAQgFhYDlfQAAAAxJREFUeJxjUmAKAAAAwAB1GNhIEwAAAABJRU5ErkJggg=="
11
14
  end
@@ -1,15 +1,14 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
2
 
3
3
  describe ChunkyPNG::Canvas do
4
-
5
- describe '.from_data_url' do
4
+ describe ".from_data_url" do
6
5
  it "should import an image from a data URL" do
7
- data_url = reference_canvas('operations').to_data_url
8
- expect(ChunkyPNG::Canvas.from_data_url(data_url)).to eql reference_canvas('operations')
6
+ data_url = reference_canvas("operations").to_data_url
7
+ expect(ChunkyPNG::Canvas.from_data_url(data_url)).to eql reference_canvas("operations")
9
8
  end
10
9
 
11
10
  it "should raise an exception if the string is not a proper data URL" do
12
- expect { ChunkyPNG::Canvas.from_data_url('whatever') }.to raise_error(ChunkyPNG::SignatureMismatch)
11
+ expect { ChunkyPNG::Canvas.from_data_url("whatever") }.to raise_error(ChunkyPNG::SignatureMismatch)
13
12
  end
14
13
  end
15
14
  end
@@ -1,12 +1,11 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
2
 
3
3
  describe ChunkyPNG::Canvas::Drawing do
4
-
5
- describe '#compose_pixel' do
4
+ describe "#compose_pixel" do
6
5
  subject { ChunkyPNG::Canvas.new(1, 1, ChunkyPNG::Color.rgb(200, 150, 100)) }
7
6
 
8
7
  it "should compose colors correctly" do
9
- subject.compose_pixel(0,0, ChunkyPNG::Color(100, 150, 200, 128))
8
+ subject.compose_pixel(0, 0, ChunkyPNG::Color(100, 150, 200, 128))
10
9
  expect(subject[0, 0]).to eql ChunkyPNG::Color(150, 150, 150)
11
10
  end
12
11
 
@@ -20,11 +19,11 @@ describe ChunkyPNG::Canvas::Drawing do
20
19
  end
21
20
  end
22
21
 
23
- describe '#line' do
22
+ describe "#line" do
24
23
  it "should draw lines correctly with anti-aliasing" do
25
-
26
24
  canvas = ChunkyPNG::Canvas.new(31, 31, ChunkyPNG::Color::WHITE)
27
25
 
26
+ # rubocop:disable Layout/SpaceInsideParens # for improved readability
28
27
  canvas.line( 0, 0, 30, 30, ChunkyPNG::Color::BLACK)
29
28
  canvas.line( 0, 30, 30, 0, ChunkyPNG::Color::BLACK)
30
29
  canvas.line(15, 30, 15, 0, ChunkyPNG::Color.rgba(200, 0, 0, 128))
@@ -33,13 +32,14 @@ describe ChunkyPNG::Canvas::Drawing do
33
32
  canvas.line( 0, 15, 30, 0, ChunkyPNG::Color.rgba( 0, 200, 0, 128))
34
33
  canvas.line( 0, 30, 15, 0, ChunkyPNG::Color.rgba( 0, 0, 200, 128), false)
35
34
  canvas.line(15, 0, 30, 30, ChunkyPNG::Color.rgba( 0, 0, 200, 128))
35
+ # rubocop:enable Layout/SpaceInsideParens
36
36
 
37
- expect(canvas).to eql reference_canvas('lines')
37
+ expect(canvas).to eql reference_canvas("lines")
38
38
  end
39
39
 
40
40
  it "should draw partial lines if the coordinates are partially out of bounds" do
41
41
  canvas = ChunkyPNG::Canvas.new(1, 2, ChunkyPNG::Color::WHITE)
42
- canvas.line(-5, -5, 0, 0, '#000000')
42
+ canvas.line(-5, -5, 0, 0, "#000000")
43
43
  expect(canvas.pixels).to eql [ChunkyPNG::Color::BLACK, ChunkyPNG::Color::WHITE]
44
44
  end
45
45
 
@@ -47,15 +47,23 @@ describe ChunkyPNG::Canvas::Drawing do
47
47
  canvas = ChunkyPNG::Canvas.new(16, 16, ChunkyPNG::Color::WHITE)
48
48
  expect(canvas.line(1, 1, 10, 10, :black)).to equal(canvas)
49
49
  end
50
+
51
+ it "should draw a single pixel when the start and end point are the same" do
52
+ canvas = ChunkyPNG::Canvas.new(5, 5, ChunkyPNG::Color::WHITE)
53
+ canvas.line(2, 2, 2, 2, ChunkyPNG::Color::BLACK)
54
+
55
+ non_white_pixels = canvas.pixels.count { |pixel| pixel != ChunkyPNG::Color::WHITE }
56
+ expect(non_white_pixels).to eql 1
57
+ end
50
58
  end
51
59
 
52
- describe '#rect' do
53
- subject { ChunkyPNG::Canvas.new(16, 16, '#ffffff') }
60
+ describe "#rect" do
61
+ subject { ChunkyPNG::Canvas.new(16, 16, "#ffffff") }
54
62
 
55
63
  it "should draw a rectangle with the correct colors" do
56
- subject.rect(1, 1, 10, 10, ChunkyPNG::Color.rgba(0, 255, 0, 80), ChunkyPNG::Color.rgba(255, 0, 0, 100))
64
+ subject.rect(1, 1, 10, 10, ChunkyPNG::Color.rgba(0, 255, 0, 80), ChunkyPNG::Color.rgba(255, 0, 0, 100))
57
65
  subject.rect(5, 5, 14, 14, ChunkyPNG::Color.rgba(0, 0, 255, 160), ChunkyPNG::Color.rgba(255, 255, 0, 100))
58
- expect(subject).to eql reference_canvas('rect')
66
+ expect(subject).to eql reference_canvas("rect")
59
67
  end
60
68
 
61
69
  it "should return itself to allow chaining" do
@@ -73,19 +81,19 @@ describe ChunkyPNG::Canvas::Drawing do
73
81
  end
74
82
  end
75
83
 
76
- describe '#circle' do
84
+ describe "#circle" do
77
85
  subject { ChunkyPNG::Canvas.new(32, 32, ChunkyPNG::Color.rgba(0, 0, 255, 128)) }
78
86
 
79
87
  it "should draw circles" do
80
- subject.circle(11, 11, 10, ChunkyPNG::Color('red @ 0.5'), ChunkyPNG::Color('white @ 0.2'))
81
- subject.circle(21, 21, 10, ChunkyPNG::Color('green @ 0.5'))
82
- expect(subject).to eql reference_canvas('circles')
88
+ subject.circle(11, 11, 10, ChunkyPNG::Color("red @ 0.5"), ChunkyPNG::Color("white @ 0.2"))
89
+ subject.circle(21, 21, 10, ChunkyPNG::Color("green @ 0.5"))
90
+ expect(subject).to eql reference_canvas("circles")
83
91
  end
84
92
 
85
93
  it "should draw partial circles when going of the canvas bounds" do
86
94
  subject.circle(0, 0, 10, ChunkyPNG::Color(:red))
87
95
  subject.circle(31, 16, 10, ChunkyPNG::Color(:black), ChunkyPNG::Color(:white, 0xaa))
88
- expect(subject).to eql reference_canvas('partial_circles')
96
+ expect(subject).to eql reference_canvas("partial_circles")
89
97
  end
90
98
 
91
99
  it "should return itself to allow chaining" do
@@ -93,78 +101,78 @@ describe ChunkyPNG::Canvas::Drawing do
93
101
  end
94
102
  end
95
103
 
96
- describe '#polygon' do
104
+ describe "#polygon" do
97
105
  subject { ChunkyPNG::Canvas.new(22, 22) }
98
106
 
99
107
  it "should draw an filled triangle when using 3 control points" do
100
- subject.polygon('(2,2) (20,5) (5,20)', ChunkyPNG::Color(:black, 0xaa), ChunkyPNG::Color(:red, 0x44))
101
- expect(subject).to eql reference_canvas('polygon_triangle_filled')
108
+ subject.polygon("(2,2) (20,5) (5,20)", ChunkyPNG::Color(:black, 0xaa), ChunkyPNG::Color(:red, 0x44))
109
+ expect(subject).to eql reference_canvas("polygon_triangle_filled")
102
110
  end
103
111
 
104
112
  it "should draw a unfilled polygon with 6 control points" do
105
- subject.polygon('(2,2) (12, 1) (20,5) (18,18) (5,20) (1,12)', ChunkyPNG::Color(:black))
106
- expect(subject).to eql reference_canvas('polygon_unfilled')
113
+ subject.polygon("(2,2) (12, 1) (20,5) (18,18) (5,20) (1,12)", ChunkyPNG::Color(:black))
114
+ expect(subject).to eql reference_canvas("polygon_unfilled")
107
115
  end
108
116
 
109
117
  it "should draw a vertically crossed filled polygon with 4 control points" do
110
- subject.polygon('(2,2) (21,2) (2,21) (21,21)', ChunkyPNG::Color(:black), ChunkyPNG::Color(:red))
111
- expect(subject).to eql reference_canvas('polygon_filled_vertical')
118
+ subject.polygon("(2,2) (21,2) (2,21) (21,21)", ChunkyPNG::Color(:black), ChunkyPNG::Color(:red))
119
+ expect(subject).to eql reference_canvas("polygon_filled_vertical")
112
120
  end
113
121
 
114
122
  it "should draw a vertically crossed filled polygon with 4 control points" do
115
- subject.polygon('(2,2) (2,21) (21,2) (21,21)', ChunkyPNG::Color(:black), ChunkyPNG::Color(:red))
116
- expect(subject).to eql reference_canvas('polygon_filled_horizontal')
123
+ subject.polygon("(2,2) (2,21) (21,2) (21,21)", ChunkyPNG::Color(:black), ChunkyPNG::Color(:red))
124
+ expect(subject).to eql reference_canvas("polygon_filled_horizontal")
117
125
  end
118
126
 
119
127
  it "should return itself to allow chaining" do
120
- expect(subject.polygon('(2,2) (20,5) (5,20)')).to equal(subject)
128
+ expect(subject.polygon("(2,2) (20,5) (5,20)")).to equal(subject)
121
129
  end
122
130
  end
123
131
 
124
- describe '#bezier_curve' do
132
+ describe "#bezier_curve" do
125
133
  subject { ChunkyPNG::Canvas.new(24, 24, ChunkyPNG::Color::WHITE) }
126
134
 
127
135
  it "should draw a bezier curve starting at the first point" do
128
- subject.bezier_curve('3,20 10,10, 20,20')
136
+ subject.bezier_curve("3,20 10,10, 20,20")
129
137
  expect(subject[3, 20]).to eql ChunkyPNG::Color::BLACK
130
138
  end
131
139
 
132
140
  it "should draw a bezier curve ending at the last point" do
133
- subject.bezier_curve('3,20 10,10, 20,20')
141
+ subject.bezier_curve("3,20 10,10, 20,20")
134
142
  expect(subject[20, 20]).to eql ChunkyPNG::Color::BLACK
135
143
  end
136
144
 
137
145
  it "should draw a bezier curve with a color of green" do
138
- subject.bezier_curve('3,20 10,10, 20,20', :green)
146
+ subject.bezier_curve("3,20 10,10, 20,20", :green)
139
147
  expect(subject[3, 20]).to eql ChunkyPNG::Color(:green)
140
148
  end
141
149
 
142
150
  it "should draw a three point bezier curve" do
143
- expect(subject.bezier_curve('1,23 12,10 23,23')).to eql reference_canvas('bezier_three_point')
151
+ expect(subject.bezier_curve("1,23 12,10 23,23")).to eql reference_canvas("bezier_three_point")
144
152
  end
145
153
 
146
154
  it "should draw a three point bezier curve flipped" do
147
- expect(subject.bezier_curve('1,1 12,15 23,1')).to eql reference_canvas('bezier_three_point_flipped')
155
+ expect(subject.bezier_curve("1,1 12,15 23,1")).to eql reference_canvas("bezier_three_point_flipped")
148
156
  end
149
157
 
150
158
  it "should draw a four point bezier curve" do
151
- expect(subject.bezier_curve('1,23 1,5 22,5 22,23')).to eql reference_canvas('bezier_four_point')
159
+ expect(subject.bezier_curve("1,23 1,5 22,5 22,23")).to eql reference_canvas("bezier_four_point")
152
160
  end
153
161
 
154
162
  it "should draw a four point bezier curve flipped" do
155
- expect(subject.bezier_curve('1,1 1,19 22,19 22,1')).to eql reference_canvas('bezier_four_point_flipped')
163
+ expect(subject.bezier_curve("1,1 1,19 22,19 22,1")).to eql reference_canvas("bezier_four_point_flipped")
156
164
  end
157
165
 
158
166
  it "should draw a four point bezier curve with a shape of an s" do
159
- expect(subject.bezier_curve('1,23 1,5 22,23 22,5')).to eql reference_canvas('bezier_four_point_s')
167
+ expect(subject.bezier_curve("1,23 1,5 22,23 22,5")).to eql reference_canvas("bezier_four_point_s")
160
168
  end
161
169
 
162
170
  it "should draw a five point bezier curve" do
163
- expect(subject.bezier_curve('10,23 1,10 12,5 23,10 14,23')).to eql reference_canvas('bezier_five_point')
171
+ expect(subject.bezier_curve("10,23 1,10 12,5 23,10 14,23")).to eql reference_canvas("bezier_five_point")
164
172
  end
165
173
 
166
174
  it "should draw a six point bezier curve" do
167
- expect(subject.bezier_curve('1,23 4,15 8,20 2,2 23,15 23,1')).to eql reference_canvas('bezier_six_point')
175
+ expect(subject.bezier_curve("1,23 4,15 8,20 2,2 23,15 23,1")).to eql reference_canvas("bezier_six_point")
168
176
  end
169
177
  end
170
178
  end