class Prawn::SVG::Elements::Base

Constants

COMMA_WSP_REGEXP
MissingAttributesError
PAINT_TYPES
SVG_NAMESPACE
SkipElementError
SkipElementQuietly

Attributes

attributes[R]
base_calls[R]
calls[RW]
document[R]
parent_calls[R]
properties[R]
source[R]
state[R]

Public Class Methods

new(document, source, parent_calls, state) click to toggle source
# File lib/prawn/svg/elements/base.rb, line 30
def initialize(document, source, parent_calls, state)
  @document = document
  @source = source
  @parent_calls = parent_calls
  @state = state
  @base_calls = @calls = []
  @attributes = {}
  @properties = Prawn::SVG::Properties.new

  if source && !state.inside_use
    id = source.attributes['id']
    id = id.strip if id

    document.elements_by_id[id] = self if id && id != ''
  end
end

Public Instance Methods

name() click to toggle source
# File lib/prawn/svg/elements/base.rb, line 67
def name
  @name ||= source ? source.name : '???'
end
parse_and_apply() click to toggle source
# File lib/prawn/svg/elements/base.rb, line 52
def parse_and_apply
  parse_standard_attributes
  parse

  apply_calls_from_standard_attributes
  apply

  process_child_elements if container?

  append_calls_to_parent unless computed_properties.display == 'none'
rescue SkipElementQuietly
rescue SkipElementError => e
  @document.warnings << e.message
end
process() click to toggle source
# File lib/prawn/svg/elements/base.rb, line 47
def process
  extract_attributes_and_properties
  parse_and_apply
end

Protected Instance Methods

add_call(name, *arguments, **kwarguments) click to toggle source
# File lib/prawn/svg/elements/base.rb, line 91
def add_call(name, *arguments, **kwarguments)
  @calls << [name.to_s, arguments, kwarguments, []]
end
add_call_and_enter(name, *arguments, **kwarguments) click to toggle source
# File lib/prawn/svg/elements/base.rb, line 95
def add_call_and_enter(name, *arguments, **kwarguments)
  @calls << [name.to_s, arguments, kwarguments, []]
  @calls = @calls.last.last
end
add_calls_from_element(other) click to toggle source
# File lib/prawn/svg/elements/base.rb, line 113
def add_calls_from_element(other)
  @calls.concat duplicate_calls(other.base_calls)
end
append_calls_to_parent() click to toggle source
# File lib/prawn/svg/elements/base.rb, line 109
def append_calls_to_parent
  @parent_calls.concat(@base_calls)
end
apply() click to toggle source
# File lib/prawn/svg/elements/base.rb, line 75
def apply; end
apply_calls_from_standard_attributes() click to toggle source
# File lib/prawn/svg/elements/base.rb, line 149
def apply_calls_from_standard_attributes
  parse_transform_attribute_and_call
  parse_opacity_attributes_and_call
  parse_clip_path_attribute_and_call
  apply_colors
  parse_stroke_attributes_and_call
  apply_drawing_call
end
apply_colors() click to toggle source
# File lib/prawn/svg/elements/base.rb, line 179
def apply_colors
  PAINT_TYPES.each do |type|
    color = properties.send(type)

    next if [nil, 'inherit', 'none'].include?(color)

    color = computed_properties.color if color == 'currentColor'

    results = Prawn::SVG::Color.parse(color, document.gradients, document.color_mode)

    success = results.detect do |result|
      case result
      when Prawn::SVG::Color::RGB, Prawn::SVG::Color::CMYK
        add_call "#{type}_color", result.value
        true
      when Prawn::SVG::Elements::Gradient
        arguments = result.gradient_arguments(self)
        if arguments
          add_call "#{type}_gradient", **arguments
          true
        end
      end
    end

    # If we were unable to find a suitable color candidate,
    # we turn off this type of paint.
    computed_properties.set(type, 'none') if success.nil?
  end
end
apply_drawing_call() click to toggle source
# File lib/prawn/svg/elements/base.rb, line 158
def apply_drawing_call
  return if state.disable_drawing || !drawable?

  fill   = computed_properties.fill != 'none'
  stroke = computed_properties.stroke != 'none'

  if fill
    command = stroke ? 'fill_and_stroke' : 'fill'

    if computed_properties.fill_rule == 'evenodd'
      add_call_and_enter(command, fill_rule: :even_odd)
    else
      add_call_and_enter(command)
    end
  elsif stroke
    add_call_and_enter('stroke')
  else
    add_call_and_enter('end_path')
  end
end
bounding_box() click to toggle source
# File lib/prawn/svg/elements/base.rb, line 77
def bounding_box; end
clone_element_source(source) click to toggle source
# File lib/prawn/svg/elements/base.rb, line 273
def clone_element_source(source)
  new_source = source.dup
  document.element_styles[new_source] = document.element_styles[source]
  new_source
end
container?() click to toggle source
# File lib/prawn/svg/elements/base.rb, line 79
def container?
  false
end
drawable?() click to toggle source
# File lib/prawn/svg/elements/base.rb, line 83
def drawable?
  !container?
end
extract_attributes_and_properties() click to toggle source
# File lib/prawn/svg/elements/base.rb, line 209
def extract_attributes_and_properties
  if (styles = document.element_styles[source])
    # TODO : implement !important, at the moment it's just ignored
    styles.each do |name, value, _important|
      @properties.set(name, value)
    end
  end

  @properties.load_hash(parse_css_declarations(source.attributes['style'] || ''))

  source.attributes.each do |name, value|
    # Properties#set returns nil if it's not a recognised property name
    @properties.set(name, value) or @attributes[name] = value
  end

  state.computed_properties.compute_properties(@properties)
end
extract_element_from_url_id_reference(values, expected_type = nil) click to toggle source
# File lib/prawn/svg/elements/base.rb, line 253
def extract_element_from_url_id_reference(values, expected_type = nil)
  Prawn::SVG::CSS::ValuesParser.parse(values).detect do |value|
    case value
    in ['url', [url]]
      element = document.elements_by_id[url[1..]] if url.start_with?('#')
      break element if element && (expected_type.nil? || element.name == expected_type)
    else
      nil
    end
  end
end
href_attribute() click to toggle source
# File lib/prawn/svg/elements/base.rb, line 265
def href_attribute
  attributes['xlink:href'] || attributes['href']
end
new_call_context_from_base() { || ... } click to toggle source
# File lib/prawn/svg/elements/base.rb, line 117
def new_call_context_from_base
  old_calls = @calls
  @calls = @base_calls
  yield
  @calls = old_calls
end
overflow_hidden?() click to toggle source
# File lib/prawn/svg/elements/base.rb, line 269
def overflow_hidden?
  ['hidden', 'scroll'].include?(computed_properties.overflow)
end
parse() click to toggle source
# File lib/prawn/svg/elements/base.rb, line 73
def parse; end
parse_css_declarations(declarations) click to toggle source
# File lib/prawn/svg/elements/base.rb, line 227
def parse_css_declarations(declarations)
  # copied from css_parser
  declarations
    .gsub(/(^\s*)|(\s*$)/, '')
    .split(/[;$]+/m)
    .each_with_object({}) do |decs, output|
      if (matches = decs.match(/\s*(.[^:]*)\s*:\s*(.[^;]*)\s*(;|\Z)/i))
        property, value, = matches.captures
        output[property.downcase] = value
      end
    end
end
parse_standard_attributes() click to toggle source
# File lib/prawn/svg/elements/base.rb, line 87
def parse_standard_attributes
  parse_xml_space_attribute
end
pop_call_position() click to toggle source
# File lib/prawn/svg/elements/base.rb, line 105
def pop_call_position
  @calls = @call_positions.pop
end
process_child_elements() click to toggle source
# File lib/prawn/svg/elements/base.rb, line 124
def process_child_elements
  return unless source

  svg_child_elements.each do |elem|
    if (element_class = Prawn::SVG::Elements::TAG_CLASS_MAPPING[elem.name.to_sym])
      add_call 'save'

      child = element_class.new(@document, elem, @calls, state.dup)
      child.process

      add_call 'restore'
    else
      @document.warnings << "Unknown tag '#{elem.name}'; ignoring"
    end
  end
end
push_call_position() click to toggle source
# File lib/prawn/svg/elements/base.rb, line 100
def push_call_position
  @call_positions ||= []
  @call_positions << @calls
end
require_attributes(*names) click to toggle source
# File lib/prawn/svg/elements/base.rb, line 240
def require_attributes(*names)
  missing_attrs = names - attributes.keys
  if missing_attrs.any?
    raise MissingAttributesError, "Must have attributes #{missing_attrs.join(', ')} on tag #{name}; skipping tag"
  end
end
require_positive_value(*args) click to toggle source
# File lib/prawn/svg/elements/base.rb, line 247
def require_positive_value(*args)
  if args.any? { |arg| arg.nil? || arg <= 0 }
    raise SkipElementError, "Invalid attributes on tag #{name}; skipping tag"
  end
end
svg_child_elements() click to toggle source
# File lib/prawn/svg/elements/base.rb, line 141
def svg_child_elements
  source.elements.select do |elem|
    # To be strict, we shouldn't treat namespace-less elements as SVG, but for
    # backwards compatibility, and because it doesn't hurt, we will.
    elem.namespace == SVG_NAMESPACE || elem.namespace == ''
  end
end