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