class Prawn::SVG::Elements::Gradient

Constants

TAG_NAME_TO_TYPE

Public Instance Methods

gradient_arguments(element) click to toggle source
# File lib/prawn/svg/elements/gradient.rb, line 18
def gradient_arguments(element)
  case @units
  when :bounding_box
    x1, y1, x2, y2 = element.bounding_box
    return if y2.nil?

    width = x2 - x1
    height = y1 - y2

    from = [x1 + width * @x1, y1 - height * @y1]
    to   = [x1 + width * @x2, y1 - height * @y2]

  when :user_space
    from = [@x1, @y1]
    to   = [@x2, @y2]
  end

  # Passing in a transformation matrix to the apply_transformations option is supported
  # by a monkey patch installed by prawn-svg.  Prawn only sees this as a truthy variable.
  #
  # See Prawn::SVG::Extensions::AdditionalGradientTransforms for details.
  {from: from, to: to, stops: @stops, apply_transformations: @transform_matrix || true}
end
parse() click to toggle source
# File lib/prawn/svg/elements/gradient.rb, line 4
def parse
  # A gradient tag without an ID is inaccessible and can never be used
  raise SkipElementQuietly if attributes['id'].nil?

  assert_compatible_prawn_version
  load_gradient_configuration
  load_coordinates
  load_stops

  document.gradients[attributes['id']] = self

  raise SkipElementQuietly # we don't want anything pushed onto the call stack
end

Private Instance Methods

assert_compatible_prawn_version() click to toggle source
# File lib/prawn/svg/elements/gradient.rb, line 48
def assert_compatible_prawn_version
  if (Prawn::VERSION.split(".").map(&:to_i) <=> [2, 2, 0]) == -1
    raise SkipElementError, "Prawn 2.2.0+ must be used if you'd like prawn-svg to render gradients"
  end
end
load_coordinates() click to toggle source
# File lib/prawn/svg/elements/gradient.rb, line 66
def load_coordinates
  case @units
  when :bounding_box
    @x1 = parse_zero_to_one(attributes["x1"], 0)
    @y1 = parse_zero_to_one(attributes["y1"], 0)
    @x2 = parse_zero_to_one(attributes["x2"], 1)
    @y2 = parse_zero_to_one(attributes["y2"], 0)

  when :user_space
    @x1 = x(attributes["x1"])
    @y1 = y(attributes["y1"])
    @x2 = x(attributes["x2"])
    @y2 = y(attributes["y2"])
  end
end
load_gradient_configuration() click to toggle source
# File lib/prawn/svg/elements/gradient.rb, line 54
def load_gradient_configuration
  @units = attributes["gradientUnits"] == 'userSpaceOnUse' ? :user_space : :bounding_box

  if transform = attributes["gradientTransform"]
    @transform_matrix = parse_transform_attribute(transform)
  end

  if (spread_method = attributes['spreadMethod']) && spread_method != "pad"
    warnings << "prawn-svg only currently supports the 'pad' spreadMethod attribute value"
  end
end
load_stops() click to toggle source
# File lib/prawn/svg/elements/gradient.rb, line 82
def load_stops
  stop_elements = source.elements.map do |child|
    element = Prawn::SVG::Elements::Base.new(document, child, [], Prawn::SVG::State.new)
    element.process
    element
  end.select do |element|
    element.name == 'stop' && element.attributes["offset"]
  end

  @stops = stop_elements.each.with_object([]) do |child, result|
    offset = parse_zero_to_one(child.attributes["offset"])

    # Offsets must be strictly increasing (SVG 13.2.4)
    if result.last && result.last.first > offset
      offset = result.last.first
    end

    if color_hex = Prawn::SVG::Color.color_to_hex(child.properties.stop_color)
      result << [offset, color_hex]
    end
  end

  raise SkipElementError, "gradient does not have any valid stops" if @stops.empty?

  @stops.unshift([0, @stops.first.last]) if @stops.first.first > 0
  @stops.push([1, @stops.last.last])     if @stops.last.first  < 1
end
parse_zero_to_one(string, default = 0) click to toggle source
# File lib/prawn/svg/elements/gradient.rb, line 110
def parse_zero_to_one(string, default = 0)
  string = string.to_s.strip
  return default if string == ""

  value = string.to_f
  value /= 100.0 if string[-1..-1] == '%'
  [0.0, value, 1.0].sort[1]
end
type() click to toggle source
# File lib/prawn/svg/elements/gradient.rb, line 44
def type
  TAG_NAME_TO_TYPE.fetch(name)
end