rmagick 1.7.4 → 1.8.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.

Files changed (130) hide show
  1. data/ChangeLog +10 -2
  2. data/README.html +284 -290
  3. data/README.txt +298 -307
  4. data/configure +180 -11
  5. data/configure.ac +18 -2
  6. data/doc/comtasks.html +1 -1
  7. data/doc/constants.html +15 -10
  8. data/doc/css/ref.css +67 -0
  9. data/doc/draw.html +1 -1
  10. data/doc/ex/InitialCoords.rb +24 -0
  11. data/doc/ex/NewCoordSys.rb +33 -0
  12. data/doc/ex/OrigCoordSys.rb +19 -0
  13. data/doc/ex/PreserveAspectRatio.rb +206 -0
  14. data/doc/ex/RotateScale.rb +38 -0
  15. data/doc/ex/Skew.rb +39 -0
  16. data/doc/ex/Use01.rb +17 -0
  17. data/doc/ex/Use02.rb +22 -0
  18. data/doc/ex/Use03.rb +17 -0
  19. data/doc/ex/ViewBox.rb +34 -0
  20. data/doc/ex/arcs01.rb +29 -0
  21. data/doc/ex/arcs02.rb +62 -0
  22. data/doc/ex/baseline_shift01.rb +19 -0
  23. data/doc/ex/bounding_box.rb +31 -37
  24. data/doc/ex/circle01.rb +18 -0
  25. data/doc/ex/cubic01.rb +46 -0
  26. data/doc/ex/cubic02.rb +95 -0
  27. data/doc/ex/drop_shadow.rb +1 -1
  28. data/doc/ex/ellipse01.rb +23 -0
  29. data/doc/ex/evenodd.rb +44 -0
  30. data/doc/ex/font_styles.rb +29 -0
  31. data/doc/ex/group.rb +27 -0
  32. data/doc/ex/image.rb +47 -0
  33. data/doc/ex/images/big-duck.gif +0 -0
  34. data/doc/ex/images/duck.gif +0 -0
  35. data/doc/ex/images/duck0.gif +0 -0
  36. data/doc/ex/images/duck1.gif +0 -0
  37. data/doc/ex/images/duck10.gif +0 -0
  38. data/doc/ex/images/duck11.gif +0 -0
  39. data/doc/ex/images/duck12.gif +0 -0
  40. data/doc/ex/images/duck13.gif +0 -0
  41. data/doc/ex/images/duck14.gif +0 -0
  42. data/doc/ex/images/duck15.gif +0 -0
  43. data/doc/ex/images/duck2.gif +0 -0
  44. data/doc/ex/images/duck3.gif +0 -0
  45. data/doc/ex/images/duck4.gif +0 -0
  46. data/doc/ex/images/duck5.gif +0 -0
  47. data/doc/ex/images/duck6.gif +0 -0
  48. data/doc/ex/images/duck7.gif +0 -0
  49. data/doc/ex/images/duck8.gif +0 -0
  50. data/doc/ex/images/duck9.gif +0 -0
  51. data/doc/ex/line01.rb +24 -0
  52. data/doc/ex/nested_rvg.rb +22 -0
  53. data/doc/ex/nonzero.rb +44 -0
  54. data/doc/ex/polygon01.rb +24 -0
  55. data/doc/ex/polyline01.rb +24 -0
  56. data/doc/ex/quad01.rb +37 -0
  57. data/doc/ex/rect01.rb +16 -0
  58. data/doc/ex/rect02.rb +23 -0
  59. data/doc/ex/rvg_clippath.rb +15 -0
  60. data/doc/ex/rvg_linecap.rb +44 -0
  61. data/doc/ex/rvg_linejoin.rb +42 -0
  62. data/doc/ex/rvg_opacity.rb +20 -0
  63. data/doc/ex/rvg_pattern.rb +27 -0
  64. data/doc/ex/rvg_stroke_dasharray.rb +13 -0
  65. data/doc/ex/sepiatone.rb +15 -0
  66. data/doc/ex/shadow.rb +37 -0
  67. data/doc/ex/smile.rb +9 -9
  68. data/doc/ex/stroke_fill.rb +12 -0
  69. data/doc/ex/text01.rb +18 -0
  70. data/doc/ex/text_styles.rb +22 -0
  71. data/doc/ex/texture_fill_to_border.rb +3 -3
  72. data/doc/ex/texture_floodfill.rb +3 -2
  73. data/doc/ex/tref01.rb +26 -0
  74. data/doc/ex/triangle01.rb +17 -0
  75. data/doc/ex/tspan01.rb +19 -0
  76. data/doc/ex/tspan02.rb +20 -0
  77. data/doc/ex/tspan03.rb +22 -0
  78. data/doc/ex/writing_mode01.rb +28 -0
  79. data/doc/ex/writing_mode02.rb +27 -0
  80. data/doc/ilist.html +1 -1
  81. data/doc/image1.html +66 -30
  82. data/doc/image2.html +1 -1
  83. data/doc/image3.html +274 -49
  84. data/doc/imageattrs.html +87 -10
  85. data/doc/imusage.html +1 -1
  86. data/doc/index.html +80 -39
  87. data/doc/info.html +149 -13
  88. data/doc/magick.html +1 -1
  89. data/doc/rvg.html +890 -0
  90. data/doc/rvgclip.html +249 -0
  91. data/doc/rvggroup.html +305 -0
  92. data/doc/rvgimage.html +288 -0
  93. data/doc/rvgpattern.html +456 -0
  94. data/doc/rvgshape.html +376 -0
  95. data/doc/rvgstyle.html +269 -0
  96. data/doc/rvgtext.html +464 -0
  97. data/doc/rvgtspan.html +237 -0
  98. data/doc/rvgtut.html +512 -0
  99. data/doc/rvguse.html +145 -0
  100. data/doc/rvgxform.html +294 -0
  101. data/doc/struct.html +9 -71
  102. data/doc/usage.html +22 -7
  103. data/ext/RMagick/MANIFEST +94 -2
  104. data/ext/RMagick/rmagick.h +10 -4
  105. data/ext/RMagick/rmagick_config.h.in +8 -2
  106. data/ext/RMagick/rmdraw.c +2 -2
  107. data/ext/RMagick/rmfill.c +2 -2
  108. data/ext/RMagick/rmilist.c +3 -3
  109. data/ext/RMagick/rmimage.c +152 -5
  110. data/ext/RMagick/rminfo.c +208 -2
  111. data/ext/RMagick/rmmain.c +14 -5
  112. data/ext/RMagick/rmutil.c +83 -22
  113. data/lib/RMagick.rb +2 -2
  114. data/lib/rvg/clippath.rb +46 -0
  115. data/lib/rvg/container.rb +129 -0
  116. data/lib/rvg/deep_equal.rb +54 -0
  117. data/lib/rvg/describable.rb +51 -0
  118. data/lib/rvg/embellishable.rb +395 -0
  119. data/lib/rvg/misc.rb +729 -0
  120. data/lib/rvg/paint.rb +48 -0
  121. data/lib/rvg/pathdata.rb +129 -0
  122. data/lib/rvg/rvg.rb +279 -0
  123. data/lib/rvg/stretchable.rb +150 -0
  124. data/lib/rvg/stylable.rb +116 -0
  125. data/lib/rvg/text.rb +185 -0
  126. data/lib/rvg/transformable.rb +131 -0
  127. data/lib/rvg/units.rb +64 -0
  128. data/rmagick.gemspec +1 -1
  129. data/uninstall.rb +3 -2
  130. metadata +96 -3
@@ -1,6 +1,6 @@
1
- # $Id: RMagick.rb,v 1.22 2004/10/06 22:23:49 rmagick Exp $
1
+ # $Id: RMagick.rb,v 1.23 2005/03/05 16:19:10 rmagick Exp $
2
2
  #==============================================================================
3
- # Copyright (C) 2004 by Timothy P. Hunter
3
+ # Copyright (C) 2005 by Timothy P. Hunter
4
4
  # Name: RMagick.rb
5
5
  # Author: Tim Hunter
6
6
  # Purpose: Extend Ruby to interface with ImageMagick.
@@ -0,0 +1,46 @@
1
+ #--
2
+ # $Id: clippath.rb,v 1.1 2005/03/12 17:02:00 rmagick Exp $
3
+ # Copyright (C) 2005 Timothy P. Hunter
4
+ #++
5
+ class Magick::RVG
6
+
7
+ class ClipPath
8
+ include ShapeConstructors
9
+ include UseConstructors
10
+ include TextConstructors
11
+ include Describable
12
+ include Stylable
13
+ include Duplicatable
14
+
15
+ # Create a clipping path. Within the block create an outline
16
+ # from one or more paths, basic shapes, text objects, or +use+.
17
+ # Everything drawn within the outline will be displayed.
18
+ # Anything drawn outside the outline will not.
19
+ #
20
+ # If the clipping path contains a +use+, it
21
+ # must directly reference path, basic shape, or text objects.
22
+ #
23
+ # Attach the clipping path to an object with the :clip_path style.
24
+ def initialize(clip_path_units='userSpaceOnUse')
25
+ super()
26
+ if ! ['userSpaceOnUse', 'objectBoundingBox'].include?(clip_path_units)
27
+ raise ArgumentError, "undefined value for clip path units: #{clip_path_units}"
28
+ end
29
+ @clip_path_units = clip_path_units
30
+ @content = Content.new
31
+ yield(self) if block_given?
32
+ end
33
+
34
+ def add_primitives(gc, style) #:nodoc:
35
+ name = __id__.to_s
36
+ gc.define_clip_path(name) do
37
+ gc.clip_units(@clip_path_units)
38
+ @content.each { |element| element.add_primitives(gc) }
39
+ end
40
+ gc.clip_path(name)
41
+ end
42
+
43
+ end # class ClipPath
44
+
45
+ end # class Magick::RVG
46
+
@@ -0,0 +1,129 @@
1
+ #--
2
+ # $Id: container.rb,v 1.1 2005/03/12 17:02:00 rmagick Exp $
3
+ # Copyright (C) 2005 Timothy P. Hunter
4
+ #++
5
+
6
+ class Magick::RVG
7
+
8
+ # Content is simply an Array with a deep_copy method.
9
+ # When unit-testing, it also has a deep_equal method.
10
+ class Content < Array #:nodoc:
11
+
12
+ def deep_copy(h = {})
13
+ me = self.__id__
14
+ copy = h[me]
15
+ unless copy
16
+ copy = self.class.new
17
+ each do |c|
18
+ copy << case
19
+ when c.nil?
20
+ nil
21
+ when c.respond_to?(:deep_copy)
22
+ c.deep_copy(h)
23
+ when c.respond_to?(:dup)
24
+ c.dup rescue c
25
+ else
26
+ c
27
+ end
28
+ end
29
+ copy.freeze if frozen?
30
+ h[me] = copy
31
+ end
32
+ return copy
33
+ end
34
+
35
+ end # class Content
36
+
37
+ # Define a collection of shapes, text, etc. that can be reused.
38
+ # Group objects are _containers_. That is, styles and transforms defined
39
+ # on the group are used by contained objects such as shapes, text, and
40
+ # nested groups unless overridden by a nested container or the object itself.
41
+ # Groups can be reused with the RVG::UseConstructors#use method.
42
+ # Create groups within
43
+ # containers with the RVG::StructureConstructors#g method.
44
+ #
45
+ # Example:
46
+ # # All elements in the group will be translated by 50 in the
47
+ # # x-direction and 10 in the y-direction.
48
+ # rvg.g.translate(50, 10).styles(:stroke=>'red',:fill=>'none') do |grp|
49
+ # # The line will be red.
50
+ # grp.line(10,10, 20,20)
51
+ # # The circle will be blue.
52
+ # grp.circle(10, 20, 20).styles(:stroke=>'blue')
53
+ # end
54
+ class Group
55
+ include Stylable
56
+ include Transformable
57
+ include Embellishable
58
+ include Describable
59
+ include Duplicatable
60
+
61
+ def initialize
62
+ super
63
+ @content = Content.new
64
+ yield(self) if block_given?
65
+ end
66
+
67
+ def add_primitives(gc) #:nodoc:
68
+ gc.push
69
+ add_transform_primitives(gc)
70
+ add_style_primitives(gc)
71
+ @content.each { |element| element.add_primitives(gc) }
72
+ gc.pop
73
+ end
74
+
75
+ # Translate container according to #use arguments
76
+ def ref(x, y, width, height) #:nodoc:
77
+ translate(x, y) if (x != 0 || y != 0)
78
+ end
79
+
80
+ # Append an arbitrary object to the group's content. Called
81
+ # by #use to insert a non-container object into a group.
82
+ def <<(obj) #:nodoc:
83
+ @content << obj
84
+ end
85
+
86
+ end # class Group
87
+
88
+
89
+ # A Use object allows the re-use of RVG and RVG::Group
90
+ # objects within a container. Create a Use object with the
91
+ # RVG::UseConstructors#use method.
92
+ class Use
93
+ include Stylable
94
+ include Transformable
95
+ include Duplicatable
96
+
97
+ # In a container, Use objects are created indirectly via the
98
+ # RVG::UseConstructors#use method.
99
+ # The +x+ and +y+ arguments
100
+ # can be used to specify an additional translation for
101
+ # the group. The +width+ and +height+ arguments specify
102
+ # a width and height for referenced RVG objects.
103
+ def initialize(element, x=0, y=0, width=nil, height=nil)
104
+ super()
105
+
106
+ # If the element is not a group, defs, symbol, or rvg,
107
+ # wrap a group around it so it can get a transform and
108
+ # possibly a new viewport.
109
+ if ! element.respond_to?(:ref)
110
+ @element = Group.new
111
+ @element << element.deep_copy
112
+ else
113
+ @element = element.deep_copy
114
+ end
115
+ @element.ref(x, y, width, height)
116
+ end
117
+
118
+ def add_primitives(gc) #:nodoc:
119
+ gc.push
120
+ add_transform_primitives(gc)
121
+ add_style_primitives(gc)
122
+ @element.add_primitives(gc)
123
+ gc.pop
124
+ end
125
+
126
+ end # class Use
127
+
128
+ end # class Magick::RVG
129
+
@@ -0,0 +1,54 @@
1
+ class Magick::RVG
2
+
3
+ [PathData, Styles, Transforms].each do |c|
4
+ c.class_eval do
5
+ def deep_equal(other)
6
+ if self != other
7
+ puts "#{c.inspect} not equal.\nself:#{self} != other:#{other}"
8
+ return false
9
+ end
10
+ return true
11
+ end
12
+ end
13
+ end
14
+
15
+ [Shape, TextBase, Image, Group, Content, Use, ClipPath, Pattern, self].each do |c|
16
+ c.class_eval do
17
+ def deep_equal(other)
18
+ ivs = self.instance_variables
19
+
20
+ ivs.each do |iv|
21
+ itv = self.instance_variable_get(iv)
22
+ otv = other.instance_variable_get(iv)
23
+ if itv.respond_to?(:deep_equal)
24
+ if itv.equal?(otv)
25
+ puts "#{iv} has deep_equal but self.#{iv} and other.#{iv} are the same object."
26
+ return false
27
+ end
28
+ if !itv.deep_equal(otv)
29
+ puts "Not equal.\nself.#{iv}=#{itv.inspect}\nother.#{iv}=#{otv.inspect}"
30
+ return false
31
+ end
32
+ else
33
+ case itv
34
+ when Float, Symbol, TrueClass, FalseClass, Fixnum, NilClass
35
+ return false if itv != otv
36
+ else
37
+ if itv.equal?(otv)
38
+ puts "#{iv} is dup-able but self.#{iv} and other.#{iv} are the same object."
39
+ return false
40
+ end
41
+ if itv != otv
42
+ puts "Not equal.\nself.#{iv}=#{itv.inspect}\nother.#{iv}=#{otv.inspect}"
43
+ return false
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ return true
50
+ end
51
+ end
52
+ end
53
+
54
+ end # class Magick::RVG
@@ -0,0 +1,51 @@
1
+ #--
2
+ # $Id: describable.rb,v 1.1 2005/03/12 17:02:00 rmagick Exp $
3
+ # Copyright (C) 2005 Timothy P. Hunter
4
+ #++
5
+
6
+ class Magick::RVG
7
+
8
+ #--
9
+ # Corresponds to SVG's Description.class
10
+ #++
11
+ # This module defines a number of metadata attributes.
12
+ module Describable
13
+
14
+ private
15
+
16
+ def initialize(*args, &block) #:nodoc:
17
+ super
18
+ @title, @desc, @metadata = nil
19
+ end
20
+
21
+ public
22
+
23
+ # Sets the object description
24
+ attr_writer :desc
25
+ # Sets the object title
26
+ attr_writer :title
27
+ # Sets the object metadata
28
+ attr_writer :metadata
29
+
30
+ # Returns the title of this object. The RVG object title is stored as
31
+ # the 'title' property on the image
32
+ def title
33
+ @title.to_s
34
+ end
35
+
36
+ # Returns the description of this object. The RVG object description is
37
+ # stored as the 'desc' property on the image
38
+ def desc
39
+ @desc.to_s
40
+ end
41
+
42
+ # Returns additional metadata of this object. The RVG object metadata
43
+ # are stored as the 'metadata' property on the image
44
+ def metadata
45
+ @metadata.to_s
46
+ end
47
+
48
+ end # module Describable
49
+
50
+ end # class Magick::RVG
51
+
@@ -0,0 +1,395 @@
1
+ #--
2
+ # $Id: embellishable.rb,v 1.3 2005/04/10 15:12:45 rmagick Exp $
3
+ # Copyright (C) 2005 Timothy P. Hunter
4
+ #++
5
+
6
+ class Magick::RVG
7
+
8
+ # Parent class of Circle, Ellipse, Text, etc.
9
+ class Shape #:nodoc:
10
+ include Stylable
11
+ include Transformable
12
+ include Duplicatable
13
+
14
+ # Each shape can have its own set of transforms and styles.
15
+ def add_primitives(gc)
16
+ gc.push
17
+ add_transform_primitives(gc)
18
+ add_style_primitives(gc)
19
+ gc.__send__(@primitive, *@args)
20
+ gc.pop
21
+ end
22
+
23
+ end # class Shape
24
+
25
+ class Circle < Shape
26
+
27
+ # Define a circle with radius +r+ and centered at [<tt>cx</tt>, <tt>cy</tt>].
28
+ # Use the RVG::ShapeConstructors#circle method to create Circle objects in a container.
29
+ def initialize(r, cx=0, cy=0)
30
+ super()
31
+ r, cx, cy = RVG.convert_to_float(r, cx, cy)
32
+ if r < 0
33
+ raise ArgumentError, "radius must be >= 0 (#{r} given)"
34
+ end
35
+ @primitive = :circle
36
+ @args = [cx, cy, cx+r, cy]
37
+ self
38
+ end
39
+
40
+ end # class Circle
41
+
42
+ class Ellipse < Shape
43
+
44
+ # Define an ellipse with a center at [<tt>cx</tt>, <tt>cy</tt>], a horizontal radius +rx+
45
+ # and a vertical radius +ry+.
46
+ # Use the RVG::ShapeConstructors#ellipse method to create Ellipse objects in a container.
47
+ def initialize(rx, ry, cx=0, cy=0)
48
+ super()
49
+ rx, ry, cx, cy = RVG.convert_to_float(rx, ry, cx, cy)
50
+ if rx < 0 || ry < 0
51
+ raise ArgumentError, "radii must be >= 0 (#{rx}, #{ry} given)"
52
+ end
53
+ @primitive = :ellipse
54
+ # Ellipses are always complete.
55
+ @args = [cx, cy, rx, ry, 0, 360]
56
+ end
57
+
58
+ end # class Ellipse
59
+
60
+ class Line < Shape
61
+
62
+ # Define a line from [<tt>x1</tt>, <tt>y1</tt>] to [<tt>x2</tt>, <tt>y2</tt>].
63
+ # Use the RVG::ShapeConstructors#line method to create Line objects in a container.
64
+ def initialize(x1=0, y1=0, x2=0, y2=0)
65
+ super()
66
+ @primitive = :line
67
+ @args = [x1, y1, x2, y2]
68
+ end
69
+
70
+ end # class Line
71
+
72
+ class Path < Shape
73
+
74
+ # Define an SVG path. The argument can be either a path string
75
+ # or a PathData object.
76
+ # Use the RVG::ShapeConstructors#path method to create Path objects in a container.
77
+ def initialize(path)
78
+ super()
79
+ @primitive = :path
80
+ @args = [path.to_s]
81
+ end
82
+
83
+ end # class Path
84
+
85
+ class Rect < Shape
86
+
87
+ # Define a width x height rectangle. The upper-left corner is at [<tt>x</tt>, <tt>y</tt>].
88
+ # If either <tt>width</tt> or <tt>height</tt> is 0, the rectangle is not rendered.
89
+ # Use the RVG::ShapeConstructors#rect method to create Rect objects in a container.
90
+ def initialize(width, height, x=0, y=0)
91
+ super()
92
+ width, height, x, y = RVG.convert_to_float(width, height, x, y)
93
+ if width < 0 || height < 0
94
+ raise ArgumentError, "width, height must be >= 0 (#{width}, #{height} given)"
95
+ end
96
+ @args = [x, y, x+width, y+height]
97
+ @primitive = :rectangle
98
+ end
99
+
100
+ # Specify optional rounded corners for a rectangle. The arguments
101
+ # are the x- and y-axis radii. If y is omitted it defaults to x.
102
+ def round(rx, ry=nil)
103
+ rx, ry = RVG.convert_to_float(rx, ry || rx)
104
+ if rx < 0 || ry < 0
105
+ raise ArgumentError, "rx, ry must be >= 0 (#{rx}, #{ry} given)"
106
+ end
107
+ @args << rx << ry
108
+ @primitive = :roundrectangle
109
+ self
110
+ end
111
+
112
+ end # class Rect
113
+
114
+ class Polygon < Shape
115
+
116
+ # Draws a polygon. The arguments are [<tt>x</tt>, <tt>y</tt>] pairs that
117
+ # define the points that make up the polygon. At least two
118
+ # points must be specified. If the last point is not the
119
+ # same as the first, adds an additional point to close
120
+ # the polygon.
121
+ # Use the RVG::ShapeConstructors#polygon method to create Polygon objects in a container.
122
+ def initialize(*points)
123
+ super()
124
+ n = points.length
125
+ if n < 4 || n % 2 != 0
126
+ raise ArgumentError, "insufficient/odd number of points specified: #{n}"
127
+ end
128
+ @primitive = :polygon
129
+ @args = RVG.convert_to_float(*points)
130
+ end
131
+
132
+ end # class Polygon
133
+
134
+ class Polyline < Shape
135
+
136
+ # Draws a polyline. The arguments are [<tt>x</tt>, <tt>y</tt>] pairs that
137
+ # define the points that make up the polyline. At least two
138
+ # points must be specified.
139
+ # Use the RVG::ShapeConstructors#polyline method to create Polyline objects in a container.
140
+ def initialize(*points)
141
+ super()
142
+ n = points.length
143
+ if n < 4 || n % 2 != 0
144
+ raise ArgumentError, "insufficient/odd number of points specified: #{n}"
145
+ end
146
+ @primitive = :polyline
147
+ @args = RVG.convert_to_float(*points)
148
+ end
149
+
150
+ end # class Polyline
151
+
152
+
153
+ class Image
154
+ include Stylable
155
+ include Transformable
156
+ include Describable
157
+ include PreserveAspectRatio
158
+ include Duplicatable
159
+
160
+ private
161
+ def align_to_viewport(scale)
162
+ tx = case @align
163
+ when 'none', /\AxMin/
164
+ 0
165
+ when NilClass, /\AxMid/
166
+ (@width - @image.columns*scale) / 2.0
167
+ when /\AxMax/
168
+ @width - @image.columns*scale
169
+ end
170
+
171
+ ty = case @align
172
+ when 'none', /YMin\z/
173
+ 0
174
+ when NilClass, /YMid\z/
175
+ (@height - @image.rows*scale) / 2.0
176
+ when /YMax\z/
177
+ @height - @image.rows*scale
178
+ end
179
+ return [tx, ty]
180
+ end
181
+
182
+ def add_composite_primitive(gc)
183
+ if @align == 'none'
184
+ # Let RMagick do the scaling
185
+ scale = 1.0
186
+ width, height = @width, @height
187
+ elsif @meet_or_slice == 'meet'
188
+ scale = [@width/@image.columns, @height/@image.rows].min
189
+ width, height = @image.columns, @image.rows
190
+ else
191
+ # Establish clipping path around the current viewport
192
+ name = __id__.to_s
193
+ gc.define_clip_path(name) do
194
+ gc.path("M#{@x},#{@y} l#{@width},0 l0,#{@height} l-#{@width},0 l0,-#{@height}z")
195
+ end
196
+
197
+ gc.clip_path(name)
198
+ scale = [@width/@image.columns, @height/@image.rows].max
199
+ width, height = @image.columns, @image.rows
200
+ end
201
+ tx, ty = align_to_viewport(scale)
202
+ gc.composite(@x+tx, @y+ty, width*scale, height*scale, @image)
203
+ end
204
+
205
+ def init_viewbox()
206
+ @align = nil
207
+ @vbx_width, @vbx_height = @image.columns, @image.rows
208
+ @meet_or_slice = 'meet'
209
+ end
210
+
211
+ public
212
+
213
+ # Composite a raster image in the viewport defined by [x,y] and
214
+ # +width+ and +height+.
215
+ # Use the RVG::ImageConstructors#image method to create Text objects in a container.
216
+ def initialize(image, width=nil, height=nil, x=0, y=0)
217
+ super() # run module initializers
218
+ @image = image.copy # use a copy of the image in case app. re-uses the argument
219
+ @x, @y, @width, @height = RVG.convert_to_float(x, y, width || @image.columns, height || @image.rows)
220
+ if @width < 0 || @height < 0
221
+ raise ArgumentError, "width, height must be >= 0"
222
+ end
223
+ init_viewbox()
224
+ end
225
+
226
+ def add_primitives(gc) #:nodoc:
227
+ # Do not render if width or height is 0
228
+ return if @width == 0 || @height == 0
229
+ gc.push
230
+ add_transform_primitives(gc)
231
+ add_style_primitives(gc)
232
+ add_composite_primitive(gc)
233
+ gc.pop
234
+ end
235
+
236
+ end # class Image
237
+
238
+
239
+ # Methods that construct basic shapes within a container
240
+ module ShapeConstructors
241
+
242
+ # Draws a circle whose center is [<tt>cx</tt>, <tt>cy</tt>] and radius is +r+.
243
+ def circle(r, cx=0, cy=0)
244
+ circle = Circle.new(r, cx, cy)
245
+ @content << circle
246
+ return circle
247
+ end
248
+
249
+ # Draws an ellipse whose center is [<tt>cx</tt>, <tt>cy</tt>] and having
250
+ # a horizontal radius +rx+ and vertical radius +ry+.
251
+ def ellipse(rx, ry, cx=0, cy=0)
252
+ ellipse = Ellipse.new(rx, ry, cx, cy)
253
+ @content << ellipse
254
+ return ellipse
255
+ end
256
+
257
+ # Draws a line from [<tt>x1</tt>, <tt>y1</tt>] to [<tt>x2</tt>, <tt>y2</tt>].
258
+ def line(x1=0, y1=0, x2=0, y2=0)
259
+ line = Line.new(x1, y1, x2, y2)
260
+ @content << line
261
+ return line
262
+ end
263
+
264
+ # Draws a path defined by an SVG path string or a PathData
265
+ # object.
266
+ def path(path)
267
+ path = Path.new(path)
268
+ @content << path
269
+ return path
270
+ end
271
+
272
+ # Draws a rectangle whose upper-left corner is [<tt>x</tt>, <tt>y</tt>] and
273
+ # with the specified +width+ and +height+. Unless otherwise
274
+ # specified the rectangle has square corners. Returns a
275
+ # Rectangle object.
276
+ #
277
+ # Draw a rectangle with rounded corners by calling the #round
278
+ # method on the Rectangle object. <tt>rx</tt> and <tt>ry</tt> are
279
+ # the corner radii in the x- and y-directions. For example:
280
+ # canvas.rect(width, height, x, y).round(8, 6)
281
+ # If <tt>ry</tt> is omitted it defaults to <tt>rx</tt>.
282
+ def rect(width, height, x=0, y=0)
283
+ rect = Rect.new(width, height, x, y)
284
+ @content << rect
285
+ return rect
286
+ end
287
+
288
+ # Draws a polygon. The arguments are [<tt>x</tt>, <tt>y</tt>] pairs that
289
+ # define the points that make up the polygon. At least two
290
+ # points must be specified. If the last point is not the
291
+ # same as the first, adds an additional point to close
292
+ # the polygon.
293
+ def polygon(*points)
294
+ polygon = Polygon.new(*points)
295
+ @content << polygon
296
+ return polygon
297
+ end
298
+
299
+ # Draws a polyline. The arguments are [<tt>x</tt>, <tt>y</tt>] pairs that
300
+ # define the points that make up the polyline. At least two
301
+ # points must be specified.
302
+ def polyline(*points)
303
+ polyline = Polyline.new(*points)
304
+ @content << polyline
305
+ return polyline
306
+ end
307
+
308
+ end # module ShapeContent
309
+
310
+ # Methods that reference ("use") other drawable objects within a container
311
+ module UseConstructors
312
+
313
+ # Reference an object to be inserted into the container's
314
+ # content. [<tt>x</tt>,<tt>y</tt>] is the offset from the upper-left
315
+ # corner. If the argument is an RVG or Image object and +width+ and +height+
316
+ # are specified, these values will override the +width+ and +height+
317
+ # attributes on the argument.
318
+ def use(obj, x=0, y=0, width=nil, height=nil)
319
+ use = Use.new(obj, x, y, width, height)
320
+ @content << use
321
+ return use
322
+ end
323
+
324
+ end # module UseConstructors
325
+
326
+ # Methods that construct container objects within a container
327
+ module StructureConstructors
328
+
329
+ # Establishes a new viewport. [<tt>x</tt>, <tt>y</tt>] is the coordinate of the
330
+ # upper-left corner within the containing viewport. This is a
331
+ # _container_ method. Styles and
332
+ # transforms specified on this object will be used by objects
333
+ # contained within, unless overridden by an inner container or
334
+ # the contained object itself.
335
+ def rvg(cols, rows, x=0, y=0, &block)
336
+ rvg = RVG.new(cols, rows, &block)
337
+ begin
338
+ x, y = Float(x), Float(y)
339
+ rescue ArgumentError
340
+ args = [cols, rows, x, y]
341
+ raise ArgumentError, "at least one argument is not convertable to Float (got #{args.collect {|a| a.class}.join(', ')})"
342
+ end
343
+ rvg.corner(x, y)
344
+ @content << rvg
345
+ return rvg
346
+ end
347
+
348
+ # Defines a group.
349
+ #
350
+ # This method constructs a new
351
+ # Group _container_ object. The styles and
352
+ # transforms specified on this object will be used by objects
353
+ # contained within, unless overridden by an inner container or
354
+ # the contained object itself.
355
+ # Define grouped elements by calling RVG::Embellishable
356
+ # methods within the associated block.
357
+ def g(&block)
358
+ group = Group.new(&block)
359
+ @content << group
360
+ return group
361
+ end
362
+
363
+ end # module StructureConstructors
364
+
365
+ # Methods that construct raster image objects within a container
366
+ module ImageConstructors
367
+
368
+ # Composite a raster image at [<tt>x</tt>,<tt>y</tt>]
369
+ # in a viewport of the specified <tt>width</tt> and <tt>height</tt>.
370
+ # If not specified, the width and height are the width and height
371
+ # of the image. Use the RVG::PreserveAspectRatio#preserve_aspect_ratio method to
372
+ # control the placement and scaling of the image within the
373
+ # viewport. By default, the image is scaled to fit inside the
374
+ # viewport and centered within the viewport.
375
+ def image(image, width=nil, height=nil, x=0, y=0)
376
+ img = Image.new(image, width, height, x, y)
377
+ @content << img
378
+ return img
379
+ end
380
+
381
+ end # module ImageConstructors
382
+
383
+ # Methods that create shapes, text, and other drawable objects
384
+ # within container objects such as ::Magick::RVG and
385
+ # ::Magick::RVG::Group
386
+ module Embellishable
387
+ include StructureConstructors
388
+ include ShapeConstructors
389
+ include TextConstructors
390
+ include UseConstructors
391
+ include ImageConstructors
392
+ end # module Embellishable
393
+
394
+ end # class Magick::RVG
395
+