chunky_png 1.0.0.rc1 → 1.0.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +2 -0
- data/chunky_png.gemspec +2 -2
- data/lib/chunky_png.rb +94 -28
- data/lib/chunky_png/canvas.rb +10 -7
- data/lib/chunky_png/canvas/drawing.rb +15 -2
- data/lib/chunky_png/canvas/operations.rb +44 -24
- data/lib/chunky_png/canvas/png_decoding.rb +6 -6
- data/lib/chunky_png/canvas/png_encoding.rb +7 -5
- data/lib/chunky_png/canvas/resampling.rb +9 -3
- data/lib/chunky_png/color.rb +19 -19
- data/lib/chunky_png/dimension.rb +10 -3
- data/lib/chunky_png/point.rb +9 -4
- data/lib/chunky_png/vector.rb +95 -8
- data/spec/chunky_png/canvas/drawing_spec.rb +17 -19
- data/spec/chunky_png/canvas/operations_spec.rb +46 -0
- data/spec/chunky_png/canvas/resampling_spec.rb +33 -0
- data/spec/chunky_png/dimension_spec.rb +10 -5
- data/spec/chunky_png/point_spec.rb +7 -2
- data/spec/chunky_png/vector_spec.rb +59 -13
- metadata +3 -3
@@ -14,13 +14,14 @@ module ChunkyPNG
|
|
14
14
|
# @param [Integer] new_width The width of the resamples canvas.
|
15
15
|
# @param [Integer] new_height The height of the resamples canvas.
|
16
16
|
# @param [ChunkyPNG::Canvas] A new canvas instance with the resamples pixels.
|
17
|
-
def resample_nearest_neighbor(new_width, new_height)
|
17
|
+
def resample_nearest_neighbor!(new_width, new_height)
|
18
18
|
|
19
19
|
resampled_image = self.class.new(new_width.to_i, new_height.to_i)
|
20
20
|
|
21
21
|
width_ratio = width.to_f / new_width.to_f
|
22
22
|
height_ratio = height.to_f / new_height.to_f
|
23
23
|
|
24
|
+
pixels = []
|
24
25
|
for y in 1..new_height do
|
25
26
|
source_y = (y - 0.5) * height_ratio + 0.5
|
26
27
|
input_y = source_y.to_i
|
@@ -29,14 +30,19 @@ module ChunkyPNG
|
|
29
30
|
source_x = (x - 0.5) * width_ratio + 0.5
|
30
31
|
input_x = source_x.to_i
|
31
32
|
|
32
|
-
|
33
|
+
pixels << get_pixel([input_x - 1, 0].max, [input_y - 1, 0].max)
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
36
|
-
|
37
|
+
replace_canvas!(new_width.to_i, new_height.to_i, pixels)
|
38
|
+
end
|
39
|
+
|
40
|
+
def resample_nearest_neighbor(new_width, new_height)
|
41
|
+
dup.resample_nearest_neighbor!(new_width, new_height)
|
37
42
|
end
|
38
43
|
|
39
44
|
alias_method :resample, :resample_nearest_neighbor
|
45
|
+
alias_method :resize, :resample
|
40
46
|
end
|
41
47
|
end
|
42
48
|
end
|
data/lib/chunky_png/color.rb
CHANGED
@@ -2,11 +2,6 @@ module ChunkyPNG
|
|
2
2
|
|
3
3
|
# Factory method to return a color value, based on the arguments given.
|
4
4
|
#
|
5
|
-
# - When given 1 argument, it can either be a color integer, which is returned as is,
|
6
|
-
# or it can be a HTML named color or a color in hex notation.
|
7
|
-
# - When given 2 arguments, the 1st argument is parsed as color value and the second
|
8
|
-
# argument is used as opacity value (range: 0-255)
|
9
|
-
#
|
10
5
|
# @overload Color(r, g, b, a)
|
11
6
|
# @param (see ChunkyPNG::Color.rgba)
|
12
7
|
# @return [Integer] The rgba color value.
|
@@ -27,7 +22,9 @@ module ChunkyPNG
|
|
27
22
|
# @param [Integer, :to_i] The color value.
|
28
23
|
# @return [Integer] The color value, with the opacity applied if one was given.
|
29
24
|
#
|
30
|
-
# @
|
25
|
+
# @return [Integer] The determined color value as RGBA integer.
|
26
|
+
# @raise [ArgumentError] if the arguments weren't understood as a color.
|
27
|
+
# @see ChunkyPNG::Color
|
31
28
|
def self.Color(*args)
|
32
29
|
case args.length
|
33
30
|
when 4; ChunkyPNG::Color.rgba(*args)
|
@@ -38,9 +35,9 @@ module ChunkyPNG
|
|
38
35
|
when Integer, /^\d+$/; source.to_i
|
39
36
|
when ChunkyPNG::Color::HEX_COLOR_REGEXP; ChunkyPNG::Color.from_hex(source)
|
40
37
|
when ChunkyPNG::Color::HTML_COLOR_REGEXP; ChunkyPNG::Color.html_color(source)
|
41
|
-
else raise
|
38
|
+
else raise ArgumentError, "Don't know how to create a color from #{source.inspect}!"
|
42
39
|
end
|
43
|
-
else raise
|
40
|
+
else raise ArgumentError, "Don't know how to create a color from #{args.inspect}!"
|
44
41
|
end
|
45
42
|
end
|
46
43
|
|
@@ -63,9 +60,11 @@ module ChunkyPNG
|
|
63
60
|
# @return [Integer] The maximum value of each color component.
|
64
61
|
MAX = 0xff
|
65
62
|
|
63
|
+
# @private
|
66
64
|
# @return [Regexp] The regexp to parse hex color values.
|
67
65
|
HEX_COLOR_REGEXP = /^(?:#|0x)?([0-9a-f]{6})([0-9a-f]{2})?$/i
|
68
|
-
|
66
|
+
|
67
|
+
# @private
|
69
68
|
# @return [Regexp] The regexp to parse named color values.
|
70
69
|
HTML_COLOR_REGEXP = /^([a-z][a-z_ ]+[a-z])(?:\ ?\@\ ?(1\.0|0\.\d+))?$/i
|
71
70
|
|
@@ -75,8 +74,8 @@ module ChunkyPNG
|
|
75
74
|
|
76
75
|
# Creates a new color using an r, g, b triple and an alpha value.
|
77
76
|
# @param [Integer] r The r-component (0-255)
|
78
|
-
# @param [Integer] g The
|
79
|
-
# @param [Integer] b The
|
77
|
+
# @param [Integer] g The g-component (0-255)
|
78
|
+
# @param [Integer] b The b-component (0-255)
|
80
79
|
# @param [Integer] a The opacity (0-255)
|
81
80
|
# @return [Integer] The newly constructed color value.
|
82
81
|
def rgba(r, g, b, a)
|
@@ -85,8 +84,8 @@ module ChunkyPNG
|
|
85
84
|
|
86
85
|
# Creates a new color using an r, g, b triple.
|
87
86
|
# @param [Integer] r The r-component (0-255)
|
88
|
-
# @param [Integer] g The
|
89
|
-
# @param [Integer] b The
|
87
|
+
# @param [Integer] g The g-component (0-255)
|
88
|
+
# @param [Integer] b The b-component (0-255)
|
90
89
|
# @return [Integer] The newly constructed color value.
|
91
90
|
def rgb(r, g, b)
|
92
91
|
r << 24 | g << 16 | b << 8 | 0xff
|
@@ -94,7 +93,7 @@ module ChunkyPNG
|
|
94
93
|
|
95
94
|
# Creates a new color using a grayscale teint.
|
96
95
|
# @param [Integer] teint The grayscale teint (0-255), will be used as r, g, and b value.
|
97
|
-
# @return [
|
96
|
+
# @return [Integer] The newly constructed color value.
|
98
97
|
def grayscale(teint)
|
99
98
|
teint << 24 | teint << 16 | teint << 8 | 0xff
|
100
99
|
end
|
@@ -141,13 +140,14 @@ module ChunkyPNG
|
|
141
140
|
# @param [Integer] opacity The opacity value for the color. Overrides any
|
142
141
|
# opacity value given in the hex value if given.
|
143
142
|
# @return [Integer] The color value.
|
143
|
+
# @raise [ArgumentError] if the value given is not a hex color notation.
|
144
144
|
def from_hex(hex_value, opacity = nil)
|
145
145
|
if HEX_COLOR_REGEXP =~ hex_value
|
146
146
|
base_color = $1.hex << 8
|
147
147
|
opacity ||= $2 ? $2.hex : 0xff
|
148
148
|
base_color | opacity
|
149
149
|
else
|
150
|
-
raise
|
150
|
+
raise ArgumentError, "Not a valid hex color notation: #{hex_value.inspect}!"
|
151
151
|
end
|
152
152
|
end
|
153
153
|
|
@@ -333,7 +333,7 @@ module ChunkyPNG
|
|
333
333
|
# @param [Integer] mask The opauqe variant of the color that was being composed
|
334
334
|
# @param [Integer] bg The background color on which the color was composed.
|
335
335
|
# @param [Integer] tolerance The decomposition tolerance level, a value between 0 and 255.
|
336
|
-
# @return [
|
336
|
+
# @return [Boolean] True if the alpha component can be decomposed successfully.
|
337
337
|
# @see #decompose_alpha
|
338
338
|
def alpha_decomposable?(color, mask, bg, tolerance = 1)
|
339
339
|
components = decompose_alpha_components(color, mask, bg)
|
@@ -360,11 +360,11 @@ module ChunkyPNG
|
|
360
360
|
end
|
361
361
|
|
362
362
|
# Decomposes an alpha channel for either the r, g or b color channel.
|
363
|
-
# @param [:r, :g, :b] The channel to decompose the alpha channel from.
|
363
|
+
# @param [:r, :g, :b] channel The channel to decompose the alpha channel from.
|
364
364
|
# @param [Integer] color The color that was the result of compositing.
|
365
|
-
# @param [Integer] mask The
|
365
|
+
# @param [Integer] mask The opaqe variant of the color that was being composed
|
366
366
|
# @param [Integer] bg The background color on which the color was composed.
|
367
|
-
# @
|
367
|
+
# @return [Integer] The decomposed alpha value for the channel.
|
368
368
|
def decompose_alpha_component(channel, color, mask, bg)
|
369
369
|
((send(channel, bg) - send(channel, color)).to_f /
|
370
370
|
(send(channel, bg) - send(channel, mask)).to_f * MAX).round
|
data/lib/chunky_png/dimension.rb
CHANGED
@@ -24,6 +24,8 @@ module ChunkyPNG
|
|
24
24
|
# width.
|
25
25
|
# @return [ChunkyPNG::Dimension] The instantiated dimension.
|
26
26
|
#
|
27
|
+
# @return [ChunkyPNG::Dimension] The dimension created by this factory method.
|
28
|
+
# @raise [ArgumentError] If the argument(s) given where not understood as a dimension.
|
27
29
|
# @see ChunkyPNG::Dimension
|
28
30
|
def self.Dimension(*args)
|
29
31
|
|
@@ -34,15 +36,15 @@ module ChunkyPNG
|
|
34
36
|
when ChunkyPNG::Point; ChunkyPNG::Dimension.new(source.x, source.y)
|
35
37
|
when Array; ChunkyPNG::Dimension.new(source[0], source[1])
|
36
38
|
when Hash; ChunkyPNG::Dimension.new(source[:width] || source['width'], source[:height] || source['height'])
|
37
|
-
when
|
39
|
+
when ChunkyPNG::Dimension::DIMENSION_REGEXP; ChunkyPNG::Dimension.new($1, $2)
|
38
40
|
else
|
39
41
|
if source.respond_to?(:width) && source.respond_to?(:height)
|
40
42
|
ChunkyPNG::Dimension.new(source.width, source.height)
|
41
43
|
else
|
42
|
-
raise
|
44
|
+
raise ArgumentError, "Don't know how to construct a point from #{source.inspect}!"
|
43
45
|
end
|
44
46
|
end
|
45
|
-
else raise
|
47
|
+
else raise ArgumentError, "Don't know how to construct a point from #{args.inspect}!"
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
@@ -51,6 +53,10 @@ module ChunkyPNG
|
|
51
53
|
# This class contains some methods to simplify performing dimension related checks.
|
52
54
|
class Dimension
|
53
55
|
|
56
|
+
# @return [Regexp] The regexp to parse dimensions from a string.
|
57
|
+
# @private
|
58
|
+
DIMENSION_REGEXP = /^[\(\[\{]?(\d+)\s*[x,]?\s*(\d+)[\)\]\}]?$/
|
59
|
+
|
54
60
|
# @return [Integer] The width-compontent of this dimension.
|
55
61
|
attr_accessor :width
|
56
62
|
|
@@ -73,6 +79,7 @@ module ChunkyPNG
|
|
73
79
|
# Checks whether a point is within bounds of this dimension.
|
74
80
|
# @param [ChunkyPNG::Point, ...] A point-like to bounds-check.
|
75
81
|
# @return [true, false] True iff the the x and y coordinate fall in this dimension.
|
82
|
+
# @see ChunkyPNG.Point
|
76
83
|
def include?(*point_like)
|
77
84
|
point = ChunkyPNG::Point(*point_like)
|
78
85
|
point.x >= 0 && point.x < width && point.y >= 0 && point.y < height
|
data/lib/chunky_png/point.rb
CHANGED
@@ -25,7 +25,8 @@ module ChunkyPNG
|
|
25
25
|
# <tt>'(0 4)'</tt>, <tt>[0,4}'</tt>, etc.
|
26
26
|
# @return [ChunkyPNG::Point] The instantiated point.
|
27
27
|
#
|
28
|
-
# @
|
28
|
+
# @return [ChunkyPNG::Point]
|
29
|
+
# @raise [ArgumentError] if the arguments weren't understood.
|
29
30
|
# @see ChunkyPNG::Point
|
30
31
|
def self.Point(*args)
|
31
32
|
case args.length
|
@@ -35,15 +36,15 @@ module ChunkyPNG
|
|
35
36
|
when ChunkyPNG::Dimension; ChunkyPNG::Point.new(source.width, source.height)
|
36
37
|
when Array; ChunkyPNG::Point.new(source[0], source[1])
|
37
38
|
when Hash; ChunkyPNG::Point.new(source[:x] || source['x'], source[:y] || source['y'])
|
38
|
-
when
|
39
|
+
when ChunkyPNG::Point::POINT_REGEXP; ChunkyPNG::Point.new($1.to_i, $2.to_i)
|
39
40
|
else
|
40
41
|
if source.respond_to?(:x) && source.respond_to?(:y)
|
41
42
|
ChunkyPNG::Point.new(source.x, source.y)
|
42
43
|
else
|
43
|
-
raise
|
44
|
+
raise ArgumentError, "Don't know how to construct a point from #{source.inspect}!"
|
44
45
|
end
|
45
46
|
end
|
46
|
-
else raise
|
47
|
+
else raise ArgumentError, "Don't know how to construct a point from #{args.inspect}!"
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
@@ -54,6 +55,10 @@ module ChunkyPNG
|
|
54
55
|
#
|
55
56
|
# @see ChunkyPNG.Point
|
56
57
|
class Point
|
58
|
+
|
59
|
+
# @return [Regexp] The regexp to parse points from a string.
|
60
|
+
# @private
|
61
|
+
POINT_REGEXP = /^[\(\[\{]?(\d+)\s*[,]?\s*(\d+)[\)\]\}]?$/
|
57
62
|
|
58
63
|
# @return [Integer] The x-coordinate of the point.
|
59
64
|
attr_accessor :x
|
data/lib/chunky_png/vector.rb
CHANGED
@@ -12,6 +12,10 @@ module ChunkyPNG
|
|
12
12
|
# @overload Vector(pointlike, pointlike, pointlike, ...)
|
13
13
|
# Creates a vector by converting every argument to a point using {ChunkyPNG.Point}.
|
14
14
|
# @return [ChunkyPNG::Vector] The instantiated vector.
|
15
|
+
#
|
16
|
+
# @return [ChunkyPNG::Vector] The vector created by this factory method.
|
17
|
+
# @raise [ArgumentError] If the given arguments could not be understood as a vector.
|
18
|
+
# @see ChunkyPNG::Vector
|
15
19
|
def self.Vector(*args)
|
16
20
|
|
17
21
|
return args.first if args.length == 1 && args.first.kind_of?(ChunkyPNG::Vector)
|
@@ -24,58 +28,140 @@ module ChunkyPNG
|
|
24
28
|
end
|
25
29
|
|
26
30
|
# Class that represents a vector of points, i.e. a list of {ChunkyPNG::Point} instances.
|
31
|
+
#
|
32
|
+
# Vectors can be created quite flexibly. See the {ChunkyPNG.Vector} factory methods for
|
33
|
+
# more information on how to construct vectors.
|
27
34
|
class Vector
|
28
35
|
|
29
36
|
include Enumerable
|
30
37
|
|
38
|
+
# @return [Array<ChunkyPNG::Point>] The array that holds all the points in this vector.
|
31
39
|
attr_reader :points
|
32
40
|
|
41
|
+
# Initializes a vector based on a list of Point instances.
|
42
|
+
#
|
43
|
+
# You usually do not want to use this method directy, but call {ChunkyPNG.Vector} instead.
|
44
|
+
#
|
45
|
+
# @param [Array<ChunkyPNG::Point>] points
|
46
|
+
# @see ChunkyPNG.Vector
|
33
47
|
def initialize(points = [])
|
34
48
|
@points = points
|
35
49
|
end
|
36
50
|
|
51
|
+
# Iterates over all the edges in this vector.
|
52
|
+
#
|
53
|
+
# An edge is a combination of two subsequent points in the vector. Together, they will form
|
54
|
+
# a path from the first point to the last point
|
55
|
+
#
|
56
|
+
# @param [true, false] close Whether to close the path, i.e. return an edge that connects the last
|
57
|
+
# point in the vector back to the first point.
|
58
|
+
# @return [void]
|
59
|
+
# @raise [ChunkyPNG::ExpectationFailed] if the vector contains less than two points.
|
60
|
+
# @see #edges
|
37
61
|
def each_edge(close = true)
|
38
62
|
raise ChunkyPNG::ExpectationFailed, "Not enough points in this path to draw an edge!" if length < 2
|
39
63
|
points.each_cons(2) { |a, b| yield(a, b) }
|
40
64
|
yield(points.last, points.first) if close
|
41
65
|
end
|
42
66
|
|
67
|
+
# Returns an enumerator that will iterate over all the edges in this vector.
|
68
|
+
# @param (see #each_edge)
|
69
|
+
# @return [Enumerator] The enumerator that iterates over the edges.
|
70
|
+
# @raise [ChunkyPNG::ExpectationFailed] if the vector contains less than two points.
|
71
|
+
# @see #each_edge
|
43
72
|
def edges(close = true)
|
44
73
|
Enumerator.new(self, :each_edge, close)
|
45
74
|
end
|
46
75
|
|
76
|
+
# Returns the number of points in this vector.
|
77
|
+
# @return [Integer] The length of the points array.
|
47
78
|
def length
|
48
79
|
points.length
|
49
80
|
end
|
50
81
|
|
82
|
+
# Iterates over all the points in this vector
|
83
|
+
# @yield [ChunkyPNG::Point] The points in the correct order.
|
84
|
+
# @return [void]
|
51
85
|
def each(&block)
|
52
86
|
points.each(&block)
|
53
87
|
end
|
54
88
|
|
89
|
+
# Comparison between two vectors for quality.
|
90
|
+
# @param [ChunkyPNG::Vector] other The vector to compare with.
|
91
|
+
# @return [true, false] true if the list of points are identical
|
55
92
|
def eql?(other)
|
56
93
|
other.points == points
|
57
94
|
end
|
58
95
|
|
59
96
|
alias_method :==, :eql?
|
60
|
-
|
61
|
-
def to_a
|
62
|
-
edges
|
63
|
-
end
|
64
|
-
|
65
|
-
alias_method :to_ary, :to_a
|
66
97
|
|
98
|
+
# Returns the range in x-coordinates for all the points in this vector.
|
99
|
+
# @return [Range] The (inclusive) range of x-coordinates.
|
67
100
|
def x_range
|
68
101
|
Range.new(*points.map { |p| p.x }.minmax)
|
69
102
|
end
|
70
|
-
|
103
|
+
|
104
|
+
# Returns the range in y-coordinates for all the points in this vector.
|
105
|
+
# @return [Range] The (inclusive) range of y-coordinates.
|
71
106
|
def y_range
|
72
107
|
Range.new(*points.map { |p| p.y }.minmax)
|
73
108
|
end
|
74
109
|
|
110
|
+
# Finds the lowest x-coordinate in this vector.
|
111
|
+
# @return [Integer] The lowest x-coordinate of all the points in the vector.
|
112
|
+
def min_x
|
113
|
+
x_range.first
|
114
|
+
end
|
115
|
+
|
116
|
+
# Finds the highest x-coordinate in this vector.
|
117
|
+
# @return [Integer] The highest x-coordinate of all the points in the vector.
|
118
|
+
def max_x
|
119
|
+
x_range.last
|
120
|
+
end
|
121
|
+
|
122
|
+
# Finds the lowest y-coordinate in this vector.
|
123
|
+
# @return [Integer] The lowest y-coordinate of all the points in the vector.
|
124
|
+
def min_y
|
125
|
+
y_range.first
|
126
|
+
end
|
127
|
+
|
128
|
+
# Finds the highest y-coordinate in this vector.
|
129
|
+
# @return [Integer] The highest y-coordinate of all the points in the vector.
|
130
|
+
def max_y
|
131
|
+
y_range.last
|
132
|
+
end
|
133
|
+
|
134
|
+
# Returns the offset from (0,0) of the minimal bounding box of all the
|
135
|
+
# points in this vector
|
136
|
+
# @return [ChunkyPNG::Point] A point that describes the top left corner if a
|
137
|
+
# minimal bounding box would be drawn around all the points in the vector.
|
138
|
+
def offset
|
139
|
+
ChunkyPNG::Point.new(min_x, min_y)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Returns the width of the minimal bounding box of all the points in this vector.
|
143
|
+
# @return [Integer] The x-distance between the points that are farthest from each other.
|
144
|
+
def width
|
145
|
+
1 + (max_x - min_x)
|
146
|
+
end
|
147
|
+
|
148
|
+
# Returns the height of the minimal bounding box of all the points in this vector.
|
149
|
+
# @return [Integer] The y-distance between the points that are farthest from each other.
|
150
|
+
def height
|
151
|
+
1 + (max_y - min_y)
|
152
|
+
end
|
153
|
+
|
154
|
+
# Returns the dimension of the minimal bounding rectangle of the points in this vector.
|
155
|
+
# @return [ChunkyPNG::Dimension] The dimension instance with the width and height
|
156
|
+
def dimension
|
157
|
+
ChunkyPNG::Dimension.new(width, height)
|
158
|
+
end
|
159
|
+
|
160
|
+
# @return [Array<ChunkyPNG::Point>] The list of points interpreted from the input array.
|
75
161
|
def self.multiple_from_array(source)
|
76
162
|
return [] if source.empty?
|
77
163
|
if source.first.kind_of?(Numeric) || source.first =~ /^\d+$/
|
78
|
-
raise
|
164
|
+
raise ArgumentError, "The points array is expected to have an even number of items!" if source.length % 2 != 0
|
79
165
|
|
80
166
|
points = []
|
81
167
|
source.each_slice(2) { |x, y| points << ChunkyPNG::Point.new(x, y) }
|
@@ -85,6 +171,7 @@ module ChunkyPNG
|
|
85
171
|
end
|
86
172
|
end
|
87
173
|
|
174
|
+
# @return [Array<ChunkyPNG::Point>] The list of points parsed from the string.
|
88
175
|
def self.multiple_from_string(source_str)
|
89
176
|
multiple_from_array(source_str.scan(/[\(\[\{]?(\d+)\s*[,x]?\s*(\d+)[\)\]\}]?/))
|
90
177
|
end
|
@@ -6,8 +6,8 @@ describe ChunkyPNG::Canvas::Drawing do
|
|
6
6
|
subject { ChunkyPNG::Canvas.new(1, 1, ChunkyPNG::Color.rgb(200, 150, 100)) }
|
7
7
|
|
8
8
|
it "should compose colors correctly" do
|
9
|
-
subject.compose_pixel(0,0, ChunkyPNG::Color
|
10
|
-
subject['0,0'].should == ChunkyPNG::Color
|
9
|
+
subject.compose_pixel(0,0, ChunkyPNG::Color(100, 150, 200, 128))
|
10
|
+
subject['0,0'].should == ChunkyPNG::Color(150, 150, 150)
|
11
11
|
end
|
12
12
|
|
13
13
|
it "should return the composed color" do
|
@@ -21,8 +21,8 @@ describe ChunkyPNG::Canvas::Drawing do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
it "should do nothing when the coordinates are out of bounds" do
|
24
|
-
subject.compose_pixel(1, -1,
|
25
|
-
lambda { subject.compose_pixel(1, -1,
|
24
|
+
subject.compose_pixel(1, -1, :black).should be_nil
|
25
|
+
lambda { subject.compose_pixel(1, -1, :black) }.should_not change { subject['0,0'] }
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -45,39 +45,37 @@ describe ChunkyPNG::Canvas::Drawing do
|
|
45
45
|
|
46
46
|
it "should draw partial lines if the coordinates are partially out of bounds" do
|
47
47
|
canvas = ChunkyPNG::Canvas.new(1, 2, ChunkyPNG::Color::WHITE)
|
48
|
-
canvas.line(-5, -5, 0, 0,
|
48
|
+
canvas.line(-5, -5, 0, 0, '#000000')
|
49
49
|
canvas.pixels.should == [ChunkyPNG::Color::BLACK, ChunkyPNG::Color::WHITE]
|
50
50
|
end
|
51
51
|
|
52
52
|
it "should return itself to allow chaining" do
|
53
53
|
canvas = ChunkyPNG::Canvas.new(16, 16, ChunkyPNG::Color::WHITE)
|
54
|
-
canvas.line(1, 1, 10, 10,
|
54
|
+
canvas.line(1, 1, 10, 10, :black).should equal(canvas)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
58
|
describe '#rect' do
|
59
|
+
subject { ChunkyPNG::Canvas.new(16, 16, '#ffffff') }
|
60
|
+
|
59
61
|
it "should draw a rectangle with the correct colors" do
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
canvas.should == reference_canvas('rect')
|
62
|
+
subject.rect(1, 1, 10, 10, ChunkyPNG::Color.rgba(0, 255, 0, 80), ChunkyPNG::Color.rgba(255, 0, 0, 100))
|
63
|
+
subject.rect(5, 5, 14, 14, ChunkyPNG::Color.rgba(0, 0, 255, 160), ChunkyPNG::Color.rgba(255, 255, 0, 100))
|
64
|
+
subject.should == reference_canvas('rect')
|
64
65
|
end
|
65
66
|
|
66
67
|
it "should return itself to allow chaining" do
|
67
|
-
|
68
|
-
canvas.rect(1, 1, 10, 10).should equal(canvas)
|
68
|
+
subject.rect(1, 1, 10, 10).should equal(subject)
|
69
69
|
end
|
70
70
|
|
71
71
|
it "should draw partial rectangles if the coordinates are partially out of bounds" do
|
72
|
-
|
73
|
-
|
74
|
-
canvas[0, 0].should == ChunkyPNG::Color::BLACK
|
72
|
+
subject.rect(0, 0, 20, 20, :black, :white)
|
73
|
+
subject[0, 0].should == ChunkyPNG::Color::BLACK
|
75
74
|
end
|
76
75
|
|
77
76
|
it "should draw the rectangle fill only if the coordinates are fully out of bounds" do
|
78
|
-
|
79
|
-
|
80
|
-
canvas[0, 0].should == ChunkyPNG::Color::WHITE
|
77
|
+
subject.rect(-1, -1, 20, 20, :black, :white)
|
78
|
+
subject[0, 0].should == ChunkyPNG::Color::WHITE
|
81
79
|
end
|
82
80
|
end
|
83
81
|
|
@@ -97,7 +95,7 @@ describe ChunkyPNG::Canvas::Drawing do
|
|
97
95
|
end
|
98
96
|
|
99
97
|
it "should return itself to allow chaining" do
|
100
|
-
subject.circle(10, 10, 5).should equal(subject)
|
98
|
+
subject.circle(10, 10, 5, :red).should equal(subject)
|
101
99
|
end
|
102
100
|
end
|
103
101
|
|