lib/rvg/rvg.rb in rmagick-2.15.3 vs lib/rvg/rvg.rb in rmagick-2.15.4
- old
+ new
@@ -25,11 +25,10 @@
#
# This software is OSI Certified Open Source Software.
# OSI Certified is a certification mark of the Open Source Initiative.
#
#++############################################################################
-
require 'rmagick'
require 'rvg/misc'
require 'rvg/describable'
require 'rvg/stylable'
require 'rvg/transformable'
@@ -45,236 +44,240 @@
require 'pp' if ENV['debug_rvg']
# RVG is the main class in this library. All graphic elements
# must be contained within an RVG object.
module Magick
- class RVG
- include Stylable
- include Transformable
- include Stretchable
- include Embellishable
- include Describable
- include Duplicatable
+ class RVG
+ include Stylable
+ include Transformable
+ include Stretchable
+ include Embellishable
+ include Describable
+ include Duplicatable
- private
+ private
- # background_fill defaults to 'none'. If background_fill has been set to something
- # else, combine it with the background_fill_opacity.
- def bgfill
- if @background_fill.nil?
- color = Magick::Pixel.new(0,0,0,Magick::TransparentOpacity)
- else
- color = @background_fill
- color.opacity = (1.0 - @background_fill_opacity) * Magick::TransparentOpacity
- end
- color
- end
+ # background_fill defaults to 'none'. If background_fill has been set to something
+ # else, combine it with the background_fill_opacity.
+ def bgfill
+ if @background_fill.nil?
+ color = Magick::Pixel.new(0,0,0,Magick::TransparentOpacity)
+ else
+ color = @background_fill
+ color.opacity = (1.0 - @background_fill_opacity) * Magick::TransparentOpacity
+ end
+ color
+ end
- def new_canvas
- if @background_pattern
- canvas = Magick::Image.new(@width, @height, @background_pattern)
- elsif @background_image
- if @width != @background_image.columns || @height != @background_image.rows
- canvas = case @background_position
- when :scaled
- @background_image.resize(@width, @height)
- when :tiled
- Magick::Image.new(@width, @height, Magick::TextureFill.new(@background_image))
- when :fit
- width, height = @width, @height
- bgcolor = bgfill
- @background_image.change_geometry(Magick::Geometry.new(width, height)) do |new_cols, new_rows|
- bg_image = @background_image.resize(new_cols, new_rows)
- if bg_image.columns != width || bg_image.rows != height
- bg = Magick::Image.new(width, height) { self.background_color = bgcolor }
- bg_image = bg.composite!(bg_image, Magick::CenterGravity, Magick::OverCompositeOp)
- end
- bg_image
- end
- end
- else
- canvas = @background_image.copy
+ def new_canvas
+ if @background_pattern
+ canvas = Magick::Image.new(@width, @height, @background_pattern)
+ elsif @background_image
+ if @width != @background_image.columns || @height != @background_image.rows
+ canvas = case @background_position
+ when :scaled
+ @background_image.resize(@width, @height)
+ when :tiled
+ Magick::Image.new(@width, @height, Magick::TextureFill.new(@background_image))
+ when :fit
+ width = @width
+ height = @height
+ bgcolor = bgfill
+ @background_image.change_geometry(Magick::Geometry.new(width, height)) do |new_cols, new_rows|
+ bg_image = @background_image.resize(new_cols, new_rows)
+ if bg_image.columns != width || bg_image.rows != height
+ bg = Magick::Image.new(width, height) { self.background_color = bgcolor }
+ bg_image = bg.composite!(bg_image, Magick::CenterGravity, Magick::OverCompositeOp)
end
- else
- bgcolor = bgfill
- canvas = Magick::Image.new(Integer(@width), Integer(@height)) { self.background_color = bgcolor }
- end
- canvas[:desc] = @desc if @desc
- canvas[:title] = @title if @title
- canvas[:metadata] = @metadata if @metadata
- canvas
+ bg_image
+ end
+ end
+ else
+ canvas = @background_image.copy
end
+ else
+ bgcolor = bgfill
+ canvas = Magick::Image.new(Integer(@width), Integer(@height)) { self.background_color = bgcolor }
+ end
+ canvas[:desc] = @desc if @desc
+ canvas[:title] = @title if @title
+ canvas[:metadata] = @metadata if @metadata
+ canvas
+ end
- if ENV['debug_prim']
- def print_gc(gc)
- primitives = gc.inspect.split(/\n/)
- indent = 0
- primitives.each do |cmd|
- indent -= 1 if cmd['pop ']
- print((' '*indent), cmd, "\n")
- indent += 1 if cmd['push ']
- end
- end
+ if ENV['debug_prim']
+ def print_gc(gc)
+ primitives = gc.inspect.split(/\n/)
+ indent = 0
+ primitives.each do |cmd|
+ indent -= 1 if cmd['pop ']
+ print((' '*indent), cmd, "\n")
+ indent += 1 if cmd['push ']
end
+ end
+ end
- public
+ public
- WORD_SEP = / / # Regexp to separate words
+ WORD_SEP = / / # Regexp to separate words
- # The background image specified by background_image=
- attr_reader :background_image
- # The background image layout specified by background_position=
- attr_reader :background_position
- # The background fill color specified by background_fill=
- attr_reader :background_fill
- # The background fill color opacity specified by background_fill_opacity=
- attr_reader :background_fill_opacity
- # The image after drawing has completed
- attr_reader :canvas
- # For embedded RVG objects, the x-axis coordinate of the upper-left corner
- attr_reader :x
- # For embedded RVG objects, the x-axis coordinate of the upper-left corner
- attr_reader :y
- attr_reader :width, :height
+ # The background image specified by background_image=
+ attr_reader :background_image
+ # The background image layout specified by background_position=
+ attr_reader :background_position
+ # The background fill color specified by background_fill=
+ attr_reader :background_fill
+ # The background fill color opacity specified by background_fill_opacity=
+ attr_reader :background_fill_opacity
+ # The image after drawing has completed
+ attr_reader :canvas
+ # For embedded RVG objects, the x-axis coordinate of the upper-left corner
+ attr_reader :x
+ # For embedded RVG objects, the x-axis coordinate of the upper-left corner
+ attr_reader :y
+ attr_reader :width, :height
- # Sets an image to use as the canvas background. See background_position= for layout options.
- def background_image=(bg_image)
- warn 'background_image= has no effect in nested RVG objects' if @nested
- if bg_image && !bg_image.is_a?(Magick::Image)
- fail ArgumentError, "background image must be an Image (got #{bg_image.class})"
- end
- @background_image = bg_image
- end
+ # Sets an image to use as the canvas background. See background_position= for layout options.
+ def background_image=(bg_image)
+ warn 'background_image= has no effect in nested RVG objects' if @nested
+ if bg_image && !bg_image.is_a?(Magick::Image)
+ fail ArgumentError, "background image must be an Image (got #{bg_image.class})"
+ end
+ @background_image = bg_image
+ end
- # Sets an object to use to fill the canvas background.
- # The object must have a <tt>fill</tt> method. See the <b>Fill Classes</b>
- # section in the RMagick doc for more information.
- def background_pattern=(filler)
- warn 'background_pattern= has no effect in nested RVG objects' if @nested
- @background_pattern = filler
- end
+ # Sets an object to use to fill the canvas background.
+ # The object must have a <tt>fill</tt> method. See the <b>Fill Classes</b>
+ # section in the RMagick doc for more information.
+ def background_pattern=(filler)
+ warn 'background_pattern= has no effect in nested RVG objects' if @nested
+ @background_pattern = filler
+ end
- # How to position the background image on the canvas. One of the following symbols:
- # [:scaled] Scale the image to the canvas width and height.
- # [:tiled] Tile the image across the canvas.
- # [:fit] Scale the image to fit within the canvas while retaining the
- # image proportions. Center the image on the canvas. Color any part of
- # the canvas not covered by the image with the background color.
- def background_position=(pos)
- warn 'background_position= has no effect in nested RVG objects' if @nested
- bg_pos = pos.to_s.downcase
- unless ['scaled', 'tiled', 'fit'].include?(bg_pos)
- fail ArgumentError, "background position must be `scaled', `tiled', or `fit' (#{pos} given)"
- end
- @background_position = bg_pos.to_sym
- end
+ # How to position the background image on the canvas. One of the following symbols:
+ # [:scaled] Scale the image to the canvas width and height.
+ # [:tiled] Tile the image across the canvas.
+ # [:fit] Scale the image to fit within the canvas while retaining the
+ # image proportions. Center the image on the canvas. Color any part of
+ # the canvas not covered by the image with the background color.
+ def background_position=(pos)
+ warn 'background_position= has no effect in nested RVG objects' if @nested
+ bg_pos = pos.to_s.downcase
+ unless ['scaled', 'tiled', 'fit'].include?(bg_pos)
+ fail ArgumentError, "background position must be `scaled', `tiled', or `fit' (#{pos} given)"
+ end
+ @background_position = bg_pos.to_sym
+ end
- # Sets the canvas background color. Either a Magick::Pixel or a color name.
- # The default fill is "none", that is, transparent black.
- def background_fill=(color)
- warn 'background_fill= has no effect in nested RVG objects' if @nested
- if !color.is_a?(Magick::Pixel)
- begin
- @background_fill = Magick::Pixel.from_color(color)
- rescue Magick::ImageMagickError
- raise ArgumentError, "unknown color `#{color}'"
- rescue TypeError
- raise TypeError, "cannot convert #{color.class} into Pixel"
- rescue
- raise ArgumentError, "argument must be a color name or a Pixel (got #{color.class})"
- end
- else
- @background_fill = color
- end
+ # Sets the canvas background color. Either a Magick::Pixel or a color name.
+ # The default fill is "none", that is, transparent black.
+ def background_fill=(color)
+ warn 'background_fill= has no effect in nested RVG objects' if @nested
+ if !color.is_a?(Magick::Pixel)
+ begin
+ @background_fill = Magick::Pixel.from_color(color)
+ rescue Magick::ImageMagickError
+ raise ArgumentError, "unknown color `#{color}'"
+ rescue TypeError
+ raise TypeError, "cannot convert #{color.class} into Pixel"
+ rescue
+ raise ArgumentError, "argument must be a color name or a Pixel (got #{color.class})"
end
+ else
+ @background_fill = color
+ end
+ end
- # Opacity of the background fill color, a number between 0.0 (transparent) and
- # 1.0 (opaque). The default is 1.0 when the background_fill= attribute has been set.
- def background_fill_opacity=(opacity)
- warn 'background_fill_opacity= has no effect in nested RVG objects' if @nested
- begin
- @background_fill_opacity = Float(opacity)
- rescue ArgumentError
- raise ArgumentError, "background_fill_opacity must be a number between 0 and 1 (#{opacity} given)"
- end
- end
+ # Opacity of the background fill color, a number between 0.0 (transparent) and
+ # 1.0 (opaque). The default is 1.0 when the background_fill= attribute has been set.
+ def background_fill_opacity=(opacity)
+ warn 'background_fill_opacity= has no effect in nested RVG objects' if @nested
+ begin
+ @background_fill_opacity = Float(opacity)
+ rescue ArgumentError
+ raise ArgumentError, "background_fill_opacity must be a number between 0 and 1 (#{opacity} given)"
+ end
+ end
- # Draw a +width+ x +height+ image. The image is specified by calling
- # one or more drawing methods on the RVG object.
- # You can group the drawing method calls in the optional associated block.
- # The +x+ and +y+ arguments have no meaning for the outermost RVG object.
- # On nested RVG objects [+x+, +y+] is the coordinate of the upper-left
- # corner in the containing canvas on which the nested RVG object is placed.
- #
- # Drawing occurs on a +canvas+ created by the #draw method. By default the
- # canvas is transparent. You can specify a different canvas with the
- # #background_fill= or #background_image= methods.
- #
- # RVG objects are _containers_. That is, styles and transforms defined
- # on the object are used by contained objects such as shapes, text, and
- # groups unless overridden by an inner container or the object itself.
- def initialize(width=nil, height=nil)
- super
- @width, @height = width, height
- @content = Content.new
- @canvas = nil
- @background_fill = nil
- @background_fill_opacity = 1.0 # applies only if background_fill= is used
- @background_position = :scaled
- @background_pattern, @background_image, @desc, @title, @metadata = nil
- @x, @y = 0.0, 0.0
- @nested = false
- yield(self) if block_given?
- end
+ # Draw a +width+ x +height+ image. The image is specified by calling
+ # one or more drawing methods on the RVG object.
+ # You can group the drawing method calls in the optional associated block.
+ # The +x+ and +y+ arguments have no meaning for the outermost RVG object.
+ # On nested RVG objects [+x+, +y+] is the coordinate of the upper-left
+ # corner in the containing canvas on which the nested RVG object is placed.
+ #
+ # Drawing occurs on a +canvas+ created by the #draw method. By default the
+ # canvas is transparent. You can specify a different canvas with the
+ # #background_fill= or #background_image= methods.
+ #
+ # RVG objects are _containers_. That is, styles and transforms defined
+ # on the object are used by contained objects such as shapes, text, and
+ # groups unless overridden by an inner container or the object itself.
+ def initialize(width = nil, height = nil)
+ super
+ @width = width
+ @height = height
+ @content = Content.new
+ @canvas = nil
+ @background_fill = nil
+ @background_fill_opacity = 1.0 # applies only if background_fill= is used
+ @background_position = :scaled
+ @background_pattern, @background_image, @desc, @title, @metadata = nil
+ @x = 0.0
+ @y = 0.0
+ @nested = false
+ yield(self) if block_given?
+ end
- # Construct a canvas or reuse an existing canvas.
- # Execute drawing commands. Return the canvas.
- def draw
- fail StandardError, 'draw not permitted in nested RVG objects' if @nested
- @canvas ||= new_canvas # allow drawing over existing canvas
- gc = Utility::GraphicContext.new
- add_outermost_primitives(gc)
- pp(self) if ENV['debug_rvg']
- print_gc(gc) if ENV['debug_prim']
- gc.draw(@canvas)
- @canvas
- end
+ # Construct a canvas or reuse an existing canvas.
+ # Execute drawing commands. Return the canvas.
+ def draw
+ fail StandardError, 'draw not permitted in nested RVG objects' if @nested
+ @canvas ||= new_canvas # allow drawing over existing canvas
+ gc = Utility::GraphicContext.new
+ add_outermost_primitives(gc)
+ pp(self) if ENV['debug_rvg']
+ print_gc(gc) if ENV['debug_prim']
+ gc.draw(@canvas)
+ @canvas
+ end
- # Accept #use arguments. Use (x,y) to generate an additional translate.
- # Override @width and @height if new values are supplied.
- def ref(x, y, rw, rh) #:nodoc:
- translate(x, y) if x != 0 || y != 0
- @width = rw if rw
- @height = rh if rh
- end
+ # Accept #use arguments. Use (x,y) to generate an additional translate.
+ # Override @width and @height if new values are supplied.
+ def ref(x, y, rw, rh) #:nodoc:
+ translate(x, y) if x != 0 || y != 0
+ @width = rw if rw
+ @height = rh if rh
+ end
- # Used by Magick::Embellishable.rvg to set non-0 x- and y-coordinates
- def corner(x, y) #:nodoc:
- @nested = true
- @x, @y = Float(x), Float(y)
- translate(@x, @y) if @x != 0.0 || @y != 0.0
- end
+ # Used by Magick::Embellishable.rvg to set non-0 x- and y-coordinates
+ def corner(x, y) #:nodoc:
+ @nested = true
+ @x = Float(x)
+ @y = Float(y)
+ translate(@x, @y) if @x != 0.0 || @y != 0.0
+ end
- # Primitives for the outermost RVG object
- def add_outermost_primitives(gc) #:nodoc:
- add_transform_primitives(gc)
- gc.push
- add_viewbox_primitives(@width, @height, gc)
- add_style_primitives(gc)
- @content.each { |element| element.add_primitives(gc) }
- gc.pop
- self
- end
+ # Primitives for the outermost RVG object
+ def add_outermost_primitives(gc) #:nodoc:
+ add_transform_primitives(gc)
+ gc.push
+ add_viewbox_primitives(@width, @height, gc)
+ add_style_primitives(gc)
+ @content.each { |element| element.add_primitives(gc) }
+ gc.pop
+ self
+ end
- # Primitives for nested RVG objects
- def add_primitives(gc) #:nodoc:
- if @width.nil? || @height.nil?
- fail ArgumentError, 'RVG width or height undefined'
- elsif @width == 0 || @height == 0
- return self
- end
- gc.push
- add_outermost_primitives(gc)
- gc.pop
- end
- end # end class RVG
+ # Primitives for nested RVG objects
+ def add_primitives(gc) #:nodoc:
+ if @width.nil? || @height.nil?
+ fail ArgumentError, 'RVG width or height undefined'
+ elsif @width == 0 || @height == 0
+ return self
+ end
+ gc.push
+ add_outermost_primitives(gc)
+ gc.pop
+ end
+ end # end class RVG
end # end module Magick