rmagick 2.15.3 → 2.15.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rmagick might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.editorconfig +14 -0
- data/.rubocop.yml +27 -3
- data/.travis.yml +9 -6
- data/CHANGELOG.md +4 -0
- data/CONTRIBUTING.md +10 -0
- data/README.textile +4 -0
- data/before_install_linux.sh +4 -4
- data/doc/ex/gravity.rb +2 -1
- data/ext/RMagick/extconf.rb +60 -17
- data/lib/rmagick/version.rb +1 -1
- data/lib/rvg/clippath.rb +37 -36
- data/lib/rvg/container.rb +106 -107
- data/lib/rvg/deep_equal.rb +46 -48
- data/lib/rvg/describable.rb +35 -36
- data/lib/rvg/embellishable.rb +384 -380
- data/lib/rvg/misc.rb +705 -690
- data/lib/rvg/paint.rb +39 -40
- data/lib/rvg/pathdata.rb +120 -121
- data/lib/rvg/rvg.rb +212 -209
- data/lib/rvg/stretchable.rb +159 -158
- data/lib/rvg/stylable.rb +99 -100
- data/lib/rvg/text.rb +0 -1
- data/lib/rvg/transformable.rb +110 -110
- data/lib/rvg/units.rb +58 -58
- data/rmagick.gemspec +1 -1
- data/spec/rmagick/image/blue_shift_spec.rb +16 -0
- data/spec/rmagick/image/composite_spec.rb +140 -0
- data/spec/rmagick/image/constitute_spec.rb +15 -0
- data/spec/rmagick/image/dispatch_spec.rb +18 -0
- data/spec/rmagick/image/from_blob_spec.rb +14 -0
- data/spec/rmagick/image/ping_spec.rb +14 -0
- data/spec/rmagick/image/properties_spec.rb +29 -0
- data/spec/spec_helper.rb +3 -0
- data/test/Image1.rb +524 -718
- data/test/Image2.rb +1262 -1262
- data/test/Image3.rb +973 -973
- data/test/ImageList2.rb +341 -341
- data/test/Image_attributes.rb +678 -678
- data/test/Info.rb +336 -336
- data/test/Magick.rb +245 -242
- data/test/Pixel.rb +105 -105
- data/test/Preview.rb +42 -42
- metadata +21 -6
data/lib/rvg/paint.rb
CHANGED
@@ -4,48 +4,47 @@
|
|
4
4
|
#++
|
5
5
|
# Defines paint server classes.
|
6
6
|
# Eventually this will include gradients.
|
7
|
-
|
8
7
|
module Magick
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
8
|
+
class RVG
|
9
|
+
class Pattern
|
10
|
+
include StructureConstructors
|
11
|
+
include UseConstructors
|
12
|
+
include ShapeConstructors
|
13
|
+
include TextConstructors
|
14
|
+
include ImageConstructors
|
15
|
+
include Stretchable
|
16
|
+
include Duplicatable
|
17
|
+
include Stylable
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
# Return upper-left corner, width, height of viewport in user coordinates.
|
20
|
+
# Usually these are the values specified when the Pattern object is
|
21
|
+
# created, but they can be changed by a call to the viewbox method.
|
22
|
+
attr_reader :x, :y, :width, :height
|
24
23
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
24
|
+
# Create a pattern that can be used with the :fill or :stroke styles.
|
25
|
+
# The +width+ and +height+ arguments define the viewport.
|
26
|
+
# The pattern will be repeated at <tt>x+m*width</tt> and <tt>y+n*height</tt>
|
27
|
+
# offsets.
|
28
|
+
#
|
29
|
+
# Define the pattern in the block.
|
30
|
+
# The pattern can be composed of shapes (rectangle, circles, etc.), text,
|
31
|
+
# raster images and container objects. You can include graphic objects by
|
32
|
+
# referring to them with #use.
|
33
|
+
def initialize(width = 0, height = 0, x = 0, y = 0)
|
34
|
+
super()
|
35
|
+
@width, @height, @x, @y = Magick::RVG.convert_to_float(width, height, x, y)
|
36
|
+
@content = Content.new
|
37
|
+
yield(self) if block_given?
|
38
|
+
end
|
40
39
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
40
|
+
def add_primitives(gc, style) #:nodoc:
|
41
|
+
name = __id__.to_s
|
42
|
+
gc.pattern(name, @x, @y, @width, @height) do
|
43
|
+
add_viewbox_primitives(@width, @height, gc)
|
44
|
+
@content.each { |element| element.add_primitives(gc) }
|
45
|
+
end
|
46
|
+
gc.__send__(style, name)
|
47
|
+
end
|
48
|
+
end # class Pattern
|
49
|
+
end # class RVG
|
51
50
|
end # module Magick
|
data/lib/rvg/pathdata.rb
CHANGED
@@ -2,126 +2,125 @@
|
|
2
2
|
# $Id: pathdata.rb,v 1.5 2009/02/28 23:52:28 rmagick Exp $
|
3
3
|
# Copyright (C) 2009 Timothy P. Hunter
|
4
4
|
#++
|
5
|
-
|
6
5
|
module Magick
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
6
|
+
class RVG
|
7
|
+
# The PathData class provides an object-oriented way to produce an SVG
|
8
|
+
# path. Each of the methods corresponds to a path command. Construct a
|
9
|
+
# path by calling one or more methods. The path object can be passed
|
10
|
+
# as an argument to the RVG::ShapeConstructors#path method.
|
11
|
+
class PathData
|
12
|
+
private
|
13
|
+
|
14
|
+
def add_points(req, *coords)
|
15
|
+
if coords
|
16
|
+
if coords.length % req != 0
|
17
|
+
fail ArgumentError, "wrong number of coordinates specified. A multiple of #{req} required, #{req+coords.length} given."
|
18
|
+
end
|
19
|
+
coords.each {|c| @path << ('%g' % c)}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
public
|
24
|
+
|
25
|
+
# Construct an empty path
|
26
|
+
def initialize
|
27
|
+
@path = ''
|
28
|
+
end
|
29
|
+
|
30
|
+
# Convert the path to its string equivalent.
|
31
|
+
def to_s
|
32
|
+
@path
|
33
|
+
end
|
34
|
+
|
35
|
+
def deep_copy(h = nil) #:nodoc:
|
36
|
+
@path.dup
|
37
|
+
end
|
38
|
+
|
39
|
+
# Add a <tt>moveto</tt> command. If <tt>abs</tt> is
|
40
|
+
# <tt>true</tt> the coordinates are absolute, otherwise
|
41
|
+
# the coordinates are relative.
|
42
|
+
def moveto(abs, x, y, *coords)
|
43
|
+
@path << sprintf('%s%g,%g ', (abs ? 'M' : 'm'), x, y)
|
44
|
+
# "subsequent pairs are treated as implicit lineto commands"
|
45
|
+
add_points(2, *coords)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Add a <tt>closepath</tt> command. The <tt>abs</tt> argument
|
49
|
+
# is ignored.
|
50
|
+
def closepath(abs = true)
|
51
|
+
@path << 'Z' # ignore `abs'
|
52
|
+
end
|
53
|
+
|
54
|
+
# Add a <tt>lineto</tt> command. Any number of x,y coordinate
|
55
|
+
# pairs may be specified. If <tt>abs</tt> is
|
56
|
+
# <tt>true</tt> the coordinates are absolute, otherwise
|
57
|
+
# the coordinates are relative.
|
58
|
+
def lineto(abs, x, y, *coords)
|
59
|
+
@path << sprintf('%s%g,%g ', (abs ? 'L' : 'l'), x, y)
|
60
|
+
# "a number of coordinate pairs may be specified to draw a polyline"
|
61
|
+
add_points(2, *coords)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Add a <tt>horizontal lineto</tt> command. If <tt>abs</tt> is
|
65
|
+
# <tt>true</tt> the coordinates are absolute, otherwise
|
66
|
+
# the coordinates are relative.
|
67
|
+
def hlineto(abs, x)
|
68
|
+
@path << sprintf('%s%g ', (abs ? 'H' : 'h'), x)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Add a <tt>vertical lineto</tt> command. If <tt>abs</tt> is
|
72
|
+
# <tt>true</tt> the coordinates are absolute, otherwise
|
73
|
+
# the coordinates are relative.
|
74
|
+
def vlineto(abs, y)
|
75
|
+
@path << sprintf('%s%g ', (abs ? 'V' : 'v'), y)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Add a <tt>curveto</tt> (<em>cubic Bezier</em>) command.
|
79
|
+
# If <tt>abs</tt> is
|
80
|
+
# <tt>true</tt> the coordinates are absolute, otherwise
|
81
|
+
# the coordinates are relative.
|
82
|
+
def curveto(abs, x1, y1, x2, y2, x, y, *coords)
|
83
|
+
@path << sprintf('%s%g,%g %g,%g %g,%g ', (abs ? 'C' : 'c'), x1, y1, x2, y2, x, y)
|
84
|
+
# "multiple sets of coordinates may be specified to draw a polybezier"
|
85
|
+
add_points(6, *coords)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Add a <tt>smooth curveto</tt> (<em>cubic Bezier</em>) command.
|
89
|
+
# If <tt>abs</tt> is
|
90
|
+
# <tt>true</tt> the coordinates are absolute, otherwise
|
91
|
+
# the coordinates are relative.
|
92
|
+
def smooth_curveto(abs, x2, y2, x, y, *coords)
|
93
|
+
@path << sprintf('%s%g,%g %g,%g ', (abs ? 'S' : 's'), x2, y2, x, y)
|
94
|
+
# "multiple sets of coordinates may be specified to draw a polybezier"
|
95
|
+
add_points(4, *coords)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Add a <tt>quadratic Bezier curveto</tt> command.
|
99
|
+
# If <tt>abs</tt> is
|
100
|
+
# <tt>true</tt> the coordinates are absolute, otherwise
|
101
|
+
# the coordinates are relative.
|
102
|
+
def quadratic_curveto(abs, x1, y1, x, y, *coords)
|
103
|
+
@path << sprintf('%s%g,%g %g,%g ', (abs ? 'Q' : 'q'), x1, y1, x, y)
|
104
|
+
add_points(4, *coords)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Add a <tt>smooth quadratic Bezier curveto</tt> command.
|
108
|
+
# If <tt>abs</tt> is
|
109
|
+
# <tt>true</tt> the coordinates are absolute, otherwise
|
110
|
+
# the coordinates are relative.
|
111
|
+
def smooth_quadratic_curveto(abs, x, y, *coords)
|
112
|
+
@path << sprintf('%s%g,%g ', (abs ? 'T' : 't'), x, y)
|
113
|
+
add_points(2, *coords)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Add an <tt>arc</tt> command.
|
117
|
+
# If <tt>abs</tt> is
|
118
|
+
# <tt>true</tt> the coordinates are absolute, otherwise
|
119
|
+
# the coordinates are relative.
|
120
|
+
|
121
|
+
def arc(abs, rx, ry, x_axis_rotation, large_arc_flag, sweep_flag, x, y)
|
122
|
+
@path << sprintf('%s%g,%g %g %d %d %g,%g ', (abs ? 'A' : 'a'), rx, ry, x_axis_rotation, large_arc_flag, sweep_flag, x, y)
|
123
|
+
end
|
124
|
+
end # class PathData
|
125
|
+
end # class RVG
|
127
126
|
end # module Magick
|
data/lib/rvg/rvg.rb
CHANGED
@@ -27,7 +27,6 @@
|
|
27
27
|
# OSI Certified is a certification mark of the Open Source Initiative.
|
28
28
|
#
|
29
29
|
#++############################################################################
|
30
|
-
|
31
30
|
require 'rmagick'
|
32
31
|
require 'rvg/misc'
|
33
32
|
require 'rvg/describable'
|
@@ -47,234 +46,238 @@ require 'pp' if ENV['debug_rvg']
|
|
47
46
|
# RVG is the main class in this library. All graphic elements
|
48
47
|
# must be contained within an RVG object.
|
49
48
|
module Magick
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
49
|
+
class RVG
|
50
|
+
include Stylable
|
51
|
+
include Transformable
|
52
|
+
include Stretchable
|
53
|
+
include Embellishable
|
54
|
+
include Describable
|
55
|
+
include Duplicatable
|
57
56
|
|
58
|
-
|
57
|
+
private
|
59
58
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
59
|
+
# background_fill defaults to 'none'. If background_fill has been set to something
|
60
|
+
# else, combine it with the background_fill_opacity.
|
61
|
+
def bgfill
|
62
|
+
if @background_fill.nil?
|
63
|
+
color = Magick::Pixel.new(0,0,0,Magick::TransparentOpacity)
|
64
|
+
else
|
65
|
+
color = @background_fill
|
66
|
+
color.opacity = (1.0 - @background_fill_opacity) * Magick::TransparentOpacity
|
67
|
+
end
|
68
|
+
color
|
69
|
+
end
|
71
70
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
bg_image
|
92
|
-
end
|
93
|
-
end
|
94
|
-
else
|
95
|
-
canvas = @background_image.copy
|
71
|
+
def new_canvas
|
72
|
+
if @background_pattern
|
73
|
+
canvas = Magick::Image.new(@width, @height, @background_pattern)
|
74
|
+
elsif @background_image
|
75
|
+
if @width != @background_image.columns || @height != @background_image.rows
|
76
|
+
canvas = case @background_position
|
77
|
+
when :scaled
|
78
|
+
@background_image.resize(@width, @height)
|
79
|
+
when :tiled
|
80
|
+
Magick::Image.new(@width, @height, Magick::TextureFill.new(@background_image))
|
81
|
+
when :fit
|
82
|
+
width = @width
|
83
|
+
height = @height
|
84
|
+
bgcolor = bgfill
|
85
|
+
@background_image.change_geometry(Magick::Geometry.new(width, height)) do |new_cols, new_rows|
|
86
|
+
bg_image = @background_image.resize(new_cols, new_rows)
|
87
|
+
if bg_image.columns != width || bg_image.rows != height
|
88
|
+
bg = Magick::Image.new(width, height) { self.background_color = bgcolor }
|
89
|
+
bg_image = bg.composite!(bg_image, Magick::CenterGravity, Magick::OverCompositeOp)
|
96
90
|
end
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
canvas[:title] = @title if @title
|
103
|
-
canvas[:metadata] = @metadata if @metadata
|
104
|
-
canvas
|
91
|
+
bg_image
|
92
|
+
end
|
93
|
+
end
|
94
|
+
else
|
95
|
+
canvas = @background_image.copy
|
105
96
|
end
|
97
|
+
else
|
98
|
+
bgcolor = bgfill
|
99
|
+
canvas = Magick::Image.new(Integer(@width), Integer(@height)) { self.background_color = bgcolor }
|
100
|
+
end
|
101
|
+
canvas[:desc] = @desc if @desc
|
102
|
+
canvas[:title] = @title if @title
|
103
|
+
canvas[:metadata] = @metadata if @metadata
|
104
|
+
canvas
|
105
|
+
end
|
106
106
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
end
|
116
|
-
end
|
107
|
+
if ENV['debug_prim']
|
108
|
+
def print_gc(gc)
|
109
|
+
primitives = gc.inspect.split(/\n/)
|
110
|
+
indent = 0
|
111
|
+
primitives.each do |cmd|
|
112
|
+
indent -= 1 if cmd['pop ']
|
113
|
+
print((' '*indent), cmd, "\n")
|
114
|
+
indent += 1 if cmd['push ']
|
117
115
|
end
|
116
|
+
end
|
117
|
+
end
|
118
118
|
|
119
|
-
|
119
|
+
public
|
120
120
|
|
121
|
-
|
121
|
+
WORD_SEP = / / # Regexp to separate words
|
122
122
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
123
|
+
# The background image specified by background_image=
|
124
|
+
attr_reader :background_image
|
125
|
+
# The background image layout specified by background_position=
|
126
|
+
attr_reader :background_position
|
127
|
+
# The background fill color specified by background_fill=
|
128
|
+
attr_reader :background_fill
|
129
|
+
# The background fill color opacity specified by background_fill_opacity=
|
130
|
+
attr_reader :background_fill_opacity
|
131
|
+
# The image after drawing has completed
|
132
|
+
attr_reader :canvas
|
133
|
+
# For embedded RVG objects, the x-axis coordinate of the upper-left corner
|
134
|
+
attr_reader :x
|
135
|
+
# For embedded RVG objects, the x-axis coordinate of the upper-left corner
|
136
|
+
attr_reader :y
|
137
|
+
attr_reader :width, :height
|
138
138
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
139
|
+
# Sets an image to use as the canvas background. See background_position= for layout options.
|
140
|
+
def background_image=(bg_image)
|
141
|
+
warn 'background_image= has no effect in nested RVG objects' if @nested
|
142
|
+
if bg_image && !bg_image.is_a?(Magick::Image)
|
143
|
+
fail ArgumentError, "background image must be an Image (got #{bg_image.class})"
|
144
|
+
end
|
145
|
+
@background_image = bg_image
|
146
|
+
end
|
147
147
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
148
|
+
# Sets an object to use to fill the canvas background.
|
149
|
+
# The object must have a <tt>fill</tt> method. See the <b>Fill Classes</b>
|
150
|
+
# section in the RMagick doc for more information.
|
151
|
+
def background_pattern=(filler)
|
152
|
+
warn 'background_pattern= has no effect in nested RVG objects' if @nested
|
153
|
+
@background_pattern = filler
|
154
|
+
end
|
155
155
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
156
|
+
# How to position the background image on the canvas. One of the following symbols:
|
157
|
+
# [:scaled] Scale the image to the canvas width and height.
|
158
|
+
# [:tiled] Tile the image across the canvas.
|
159
|
+
# [:fit] Scale the image to fit within the canvas while retaining the
|
160
|
+
# image proportions. Center the image on the canvas. Color any part of
|
161
|
+
# the canvas not covered by the image with the background color.
|
162
|
+
def background_position=(pos)
|
163
|
+
warn 'background_position= has no effect in nested RVG objects' if @nested
|
164
|
+
bg_pos = pos.to_s.downcase
|
165
|
+
unless ['scaled', 'tiled', 'fit'].include?(bg_pos)
|
166
|
+
fail ArgumentError, "background position must be `scaled', `tiled', or `fit' (#{pos} given)"
|
167
|
+
end
|
168
|
+
@background_position = bg_pos.to_sym
|
169
|
+
end
|
170
170
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
end
|
185
|
-
else
|
186
|
-
@background_fill = color
|
187
|
-
end
|
171
|
+
# Sets the canvas background color. Either a Magick::Pixel or a color name.
|
172
|
+
# The default fill is "none", that is, transparent black.
|
173
|
+
def background_fill=(color)
|
174
|
+
warn 'background_fill= has no effect in nested RVG objects' if @nested
|
175
|
+
if !color.is_a?(Magick::Pixel)
|
176
|
+
begin
|
177
|
+
@background_fill = Magick::Pixel.from_color(color)
|
178
|
+
rescue Magick::ImageMagickError
|
179
|
+
raise ArgumentError, "unknown color `#{color}'"
|
180
|
+
rescue TypeError
|
181
|
+
raise TypeError, "cannot convert #{color.class} into Pixel"
|
182
|
+
rescue
|
183
|
+
raise ArgumentError, "argument must be a color name or a Pixel (got #{color.class})"
|
188
184
|
end
|
185
|
+
else
|
186
|
+
@background_fill = color
|
187
|
+
end
|
188
|
+
end
|
189
189
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
190
|
+
# Opacity of the background fill color, a number between 0.0 (transparent) and
|
191
|
+
# 1.0 (opaque). The default is 1.0 when the background_fill= attribute has been set.
|
192
|
+
def background_fill_opacity=(opacity)
|
193
|
+
warn 'background_fill_opacity= has no effect in nested RVG objects' if @nested
|
194
|
+
begin
|
195
|
+
@background_fill_opacity = Float(opacity)
|
196
|
+
rescue ArgumentError
|
197
|
+
raise ArgumentError, "background_fill_opacity must be a number between 0 and 1 (#{opacity} given)"
|
198
|
+
end
|
199
|
+
end
|
200
200
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
201
|
+
# Draw a +width+ x +height+ image. The image is specified by calling
|
202
|
+
# one or more drawing methods on the RVG object.
|
203
|
+
# You can group the drawing method calls in the optional associated block.
|
204
|
+
# The +x+ and +y+ arguments have no meaning for the outermost RVG object.
|
205
|
+
# On nested RVG objects [+x+, +y+] is the coordinate of the upper-left
|
206
|
+
# corner in the containing canvas on which the nested RVG object is placed.
|
207
|
+
#
|
208
|
+
# Drawing occurs on a +canvas+ created by the #draw method. By default the
|
209
|
+
# canvas is transparent. You can specify a different canvas with the
|
210
|
+
# #background_fill= or #background_image= methods.
|
211
|
+
#
|
212
|
+
# RVG objects are _containers_. That is, styles and transforms defined
|
213
|
+
# on the object are used by contained objects such as shapes, text, and
|
214
|
+
# groups unless overridden by an inner container or the object itself.
|
215
|
+
def initialize(width = nil, height = nil)
|
216
|
+
super
|
217
|
+
@width = width
|
218
|
+
@height = height
|
219
|
+
@content = Content.new
|
220
|
+
@canvas = nil
|
221
|
+
@background_fill = nil
|
222
|
+
@background_fill_opacity = 1.0 # applies only if background_fill= is used
|
223
|
+
@background_position = :scaled
|
224
|
+
@background_pattern, @background_image, @desc, @title, @metadata = nil
|
225
|
+
@x = 0.0
|
226
|
+
@y = 0.0
|
227
|
+
@nested = false
|
228
|
+
yield(self) if block_given?
|
229
|
+
end
|
228
230
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
231
|
+
# Construct a canvas or reuse an existing canvas.
|
232
|
+
# Execute drawing commands. Return the canvas.
|
233
|
+
def draw
|
234
|
+
fail StandardError, 'draw not permitted in nested RVG objects' if @nested
|
235
|
+
@canvas ||= new_canvas # allow drawing over existing canvas
|
236
|
+
gc = Utility::GraphicContext.new
|
237
|
+
add_outermost_primitives(gc)
|
238
|
+
pp(self) if ENV['debug_rvg']
|
239
|
+
print_gc(gc) if ENV['debug_prim']
|
240
|
+
gc.draw(@canvas)
|
241
|
+
@canvas
|
242
|
+
end
|
241
243
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
244
|
+
# Accept #use arguments. Use (x,y) to generate an additional translate.
|
245
|
+
# Override @width and @height if new values are supplied.
|
246
|
+
def ref(x, y, rw, rh) #:nodoc:
|
247
|
+
translate(x, y) if x != 0 || y != 0
|
248
|
+
@width = rw if rw
|
249
|
+
@height = rh if rh
|
250
|
+
end
|
249
251
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
252
|
+
# Used by Magick::Embellishable.rvg to set non-0 x- and y-coordinates
|
253
|
+
def corner(x, y) #:nodoc:
|
254
|
+
@nested = true
|
255
|
+
@x = Float(x)
|
256
|
+
@y = Float(y)
|
257
|
+
translate(@x, @y) if @x != 0.0 || @y != 0.0
|
258
|
+
end
|
256
259
|
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
260
|
+
# Primitives for the outermost RVG object
|
261
|
+
def add_outermost_primitives(gc) #:nodoc:
|
262
|
+
add_transform_primitives(gc)
|
263
|
+
gc.push
|
264
|
+
add_viewbox_primitives(@width, @height, gc)
|
265
|
+
add_style_primitives(gc)
|
266
|
+
@content.each { |element| element.add_primitives(gc) }
|
267
|
+
gc.pop
|
268
|
+
self
|
269
|
+
end
|
267
270
|
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
271
|
+
# Primitives for nested RVG objects
|
272
|
+
def add_primitives(gc) #:nodoc:
|
273
|
+
if @width.nil? || @height.nil?
|
274
|
+
fail ArgumentError, 'RVG width or height undefined'
|
275
|
+
elsif @width == 0 || @height == 0
|
276
|
+
return self
|
277
|
+
end
|
278
|
+
gc.push
|
279
|
+
add_outermost_primitives(gc)
|
280
|
+
gc.pop
|
281
|
+
end
|
282
|
+
end # end class RVG
|
280
283
|
end # end module Magick
|