class Magick::RVG
def self.convert_one_to_float(arg)
def self.convert_one_to_float(arg) begin farg = Float(arg) rescue ArgumentError, TypeError raise ArgumentError, "argument cannot be converted to Float (got #{arg.class})" end farg end
def self.convert_to_float(*args)
def self.convert_to_float(*args) allow_nil = false if args.last == :allow_nil allow_nil = true args.pop end begin fargs = args.map { |a| allow_nil && a.nil? ? a : Float(a) } rescue ArgumentError, TypeError raise ArgumentError, fmsg(*args) end fargs end
def self.fmsg(*args)
Convert an array of method arguments to Float objects. If any
def self.fmsg(*args) "at least one argument cannot be converted to Float (got #{args.map(&:class).join(', ')})" end
def add_outermost_primitives(gc)
- Private: -
def add_outermost_primitives(gc) 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
def add_primitives(gc)
- Private: -
def add_primitives(gc) raise ArgumentError, 'RVG width or height undefined' if @width.nil? || @height.nil? return self if @width.zero? || @height.zero? gc.push add_outermost_primitives(gc) gc.pop end
def background_fill=(color)
Sets the canvas background color. Either a Magick::Pixel or a color name.
def background_fill=(color) warn 'background_fill= has no effect in nested RVG objects' if @nested if color.is_a?(Magick::Pixel) @background_fill = color else 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 StandardError raise ArgumentError, "argument must be a color name or a Pixel (got #{color.class})" end end end
def background_fill_opacity=(opacity)
Opacity of the background fill color, a number between 0.0 (transparent) and
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
def background_image=(bg_image)
def background_image=(bg_image) warn 'background_image= has no effect in nested RVG objects' if @nested raise ArgumentError, "background image must be an Image (got #{bg_image.class})" if bg_image && !bg_image.is_a?(Magick::Image) @background_image = bg_image end
def background_pattern=(filler)
The object must have a fill method. See the Fill Classes
Sets an object to use to fill the canvas background.
def background_pattern=(filler) warn 'background_pattern= has no effect in nested RVG objects' if @nested @background_pattern = filler end
def background_position=(pos)
image proportions. Center the image on the canvas. Color any part of
[:fit] Scale the image to fit within the canvas while retaining the
[:tiled] Tile the image across the canvas.
[:scaled] Scale the image to the canvas width and height.
How to position the background image on the canvas. One of the following symbols:
def background_position=(pos) warn 'background_position= has no effect in nested RVG objects' if @nested bg_pos = pos.to_s.downcase raise ArgumentError, "background position must be `scaled', `tiled', or `fit' (#{pos} given)" unless %w[scaled tiled fit].include?(bg_pos) @background_position = bg_pos.to_sym end
def bgfill
background_fill defaults to 'none'. If background_fill has been set to something
def bgfill if @background_fill.nil? color = Magick::Pixel.new(0, 0, 0, Magick::OpaqueAlpha) else color = @background_fill color.alpha = @background_fill_opacity * Magick::OpaqueAlpha end color end
def corner(x, y)
- Private: -
def corner(x, y) @nested = true @x = Float(x) @y = Float(y) translate(@x, @y) if @x != 0.0 || @y != 0.0 end
def deep_equal(other)
def deep_equal(other) if self != other puts "#{c.inspect} not equal.\nself:#{self} != other:#{other}" return false end true end
def deep_equal(other)
def deep_equal(other) ivs = instance_variables ivs.each do |iv| itv = instance_variable_get(iv) otv = other.instance_variable_get(iv) if itv.respond_to?(:deep_equal) if itv.equal?(otv) puts "#{iv} has deep_equal but self.#{iv} and other.#{iv} are the same object." return false end unless itv.deep_equal(otv) puts "Not equal.\nself.#{iv}=#{itv.inspect}\nother.#{iv}=#{otv.inspect}" return false end else case itv when Float, Symbol, TrueClass, FalseClass, Integer, NilClass return false if itv != otv else if itv.equal?(otv) puts "#{iv} is dup-able but self.#{iv} and other.#{iv} are the same object." return false end if itv != otv puts "Not equal.\nself.#{iv}=#{itv.inspect}\nother.#{iv}=#{otv.inspect}" return false end end end end true end
def dpi=(n)
def dpi=(n) unless defined?(@dpi) [Float, Integer].each do |c| c.class_eval <<-END_DEFS, __FILE__, __LINE__ + 1 # the default measurement - 1px is 1 pixel def px self end # inches def in self * ::Magick::RVG.dpi end # millimeters def mm self * ::Magick::RVG.dpi / 25.4 end # centimeters def cm self * ::Magick::RVG.dpi / 2.54 end # points def pt self * ::Magick::RVG.dpi / 72.0 end # picas def pc self * ::Magick::RVG.dpi / 6.0 end # percentage of the argument def pct(of) self * Float(of) / 100.0 end # the default is deg def deg self end # radians -> degrees def rad self * 180.0 / Math::PI end # grads -> degrees def grad self * 9.0 / 10.0 end END_DEFS end end @dpi = Float(n) @dpi rescue ArgumentError raise TypeError, "Can't convert `#{n}' to Float" end
def draw
Construct a canvas or reuse an existing canvas.
def draw raise 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
def initialize(width = nil, height = nil)
on the object are used by contained objects such as shapes, text, and
RVG objects are _containers_. That is, styles and transforms defined
#background_fill= or #background_image= methods.
canvas is transparent. You can specify a different canvas with the
Drawing occurs on a +canvas+ created by the #draw method. By default the
corner in the containing canvas on which the nested RVG object is placed.
On nested RVG objects [+x+, +y+] is the coordinate of the upper-left
The +x+ and +y+ arguments have no meaning for the outermost RVG object.
You can group the drawing method calls in the optional associated block.
one or more drawing methods on the RVG object.
Draw a +width+ x +height+ image. The image is specified by calling
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
def new_canvas
def new_canvas if @background_pattern canvas = Magick::Image.new(@width, @height, @background_pattern) elsif @background_image canvas = if @width != @background_image.columns || @height != @background_image.rows 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) { |options| options.background_color = bgcolor } bg_image = bg.composite!(bg_image, Magick::CenterGravity, Magick::OverCompositeOp) end bg_image end else @background_image.copy end else @background_image.copy end else bgcolor = bgfill canvas = Magick::Image.new(Integer(@width), Integer(@height)) { |options| options.background_color = bgcolor } end canvas[:desc] = @desc if @desc canvas[:title] = @title if @title canvas[:metadata] = @metadata if @metadata canvas end
def print_gc(gc)
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
def ref(x, y, rw, rh)
- Private: -
def ref(x, y, rw, rh) translate(x, y) if x != 0 || y != 0 @width = rw if rw @height = rh if rh end