chunky_png 1.0.0.rc1 → 1.0.0.rc2
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/.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
|
|