Parent

Prawn::Svg::Element

Attributes

attributes[R]
base_calls[R]
calls[RW]
document[R]
element[R]
parent_calls[R]
state[R]

Public Class Methods

new(document, element, parent_calls, state) click to toggle source
# File lib/prawn/svg/element.rb, line 5
def initialize(document, element, parent_calls, state)
  @document = document
  @element = element
  @parent_calls = parent_calls
  @state = state
  @base_calls = @calls = []

  combine_attributes_and_style_declarations
  apply_styles

  if id = @attributes["id"]
    document.elements_by_id[id] = self
  end
end

Public Instance Methods

add_call(name, *arguments) click to toggle source
# File lib/prawn/svg/element.rb, line 34
def add_call(name, *arguments)
  @calls << [name.to_s, arguments, []]
end
add_call_and_enter(name, *arguments) click to toggle source
# File lib/prawn/svg/element.rb, line 38
def add_call_and_enter(name, *arguments)
  @calls << [name.to_s, arguments, []]
  @calls = @calls.last.last
end
add_calls_from_element(other) click to toggle source
# File lib/prawn/svg/element.rb, line 47
def add_calls_from_element(other)
  @calls.concat other.base_calls
end
append_calls_to_parent() click to toggle source
# File lib/prawn/svg/element.rb, line 43
def append_calls_to_parent
  @parent_calls.concat(@base_calls)
end
each_child_element() click to toggle source
# File lib/prawn/svg/element.rb, line 24
def each_child_element
  element.elements.each do |e|
    yield self.class.new(@document, e, @calls, @state.dup)
  end
end
name() click to toggle source
# File lib/prawn/svg/element.rb, line 20
def name
  @name ||= element.name
end
warnings() click to toggle source
# File lib/prawn/svg/element.rb, line 30
def warnings
  @document.warnings
end

Protected Instance Methods

apply_styles() click to toggle source
# File lib/prawn/svg/element.rb, line 53
def apply_styles
  parse_transform_attribute_and_call
  parse_opacity_attributes_and_call
  parse_clip_path_attribute_and_call
  draw_types = parse_fill_and_stroke_attributes_and_call
  parse_stroke_width_attribute_and_call
  parse_font_attributes_and_call

  if draw_types.length > 0 && !@state[:disable_drawing] && !Prawn::Svg::Parser::CONTAINER_TAGS.include?(element.name)
    add_call_and_enter(draw_types.join("_and_"))
  end
end
clamp(value, min_value, max_value) click to toggle source
# File lib/prawn/svg/element.rb, line 196
def clamp(value, min_value, max_value)
  [[value, min_value].max, max_value].min
end
combine_attributes_and_style_declarations() click to toggle source
# File lib/prawn/svg/element.rb, line 200
def combine_attributes_and_style_declarations
  if @document && @document.css_parser
    tag_style = @document.css_parser.find_by_selector(element.name)
    id_style = @document.css_parser.find_by_selector("##{element.attributes["id"]}") if element.attributes["id"]

    if classes = element.attributes["class"]
      class_styles = classes.strip.split(/\s+/).collect do |class_name|
        @document.css_parser.find_by_selector(".#{class_name}")
      end
    end

    element_style = element.attributes['style']

    style = [tag_style, class_styles, id_style, element_style].flatten.collect do |s|
      s.nil? || s.strip == "" ? "" : "#{s}#{";" unless s.match(/;\s*\z/)}"
    end.join
  else
    style = element.attributes['style'] || ""
  end

  @attributes = parse_css_declarations(style)
  element.attributes.each {|n,v| @attributes[n] = v unless @attributes[n]}
end
parse_clip_path_attribute_and_call() click to toggle source
# File lib/prawn/svg/element.rb, line 115
def parse_clip_path_attribute_and_call
  return unless clip_path = @attributes['clip-path']

  if (matches = clip_path.strip.match(/\Aurl\(#(.*)\)\z/)).nil?
    document.warnings << "Only clip-path attributes with the form 'url(#xxx)' are supported"
  elsif (clip_path_element = @document.elements_by_id[matches[1]]).nil?
    document.warnings << "clip-path ID '#{matches[1]}' not defined"
  elsif clip_path_element.element.name != "clipPath"
    document.warnings << "clip-path ID '#{matches[1]}' does not point to a clipPath tag"
  else
    add_call_and_enter 'save_graphics_state'
    add_calls_from_element clip_path_element
    add_call "clip"
  end
end
parse_css_declarations(declarations) click to toggle source
# File lib/prawn/svg/element.rb, line 224
def parse_css_declarations(declarations)
  # copied from css_parser
  declarations.gsub!(/(^[\s]*)|([\s]*$)/, '')

  output = {}
  declarations.split(/[\;$]+/).each do |decs|
    if matches = decs.match(/\s*(.[^:]*)\s*\:\s*(.[^;]*)\s*(;|\Z)/)
      property, value, end_of_declaration = matches.captures
      output[property] = value
    end
  end
  output
end
parse_css_method_calls(string) click to toggle source
# File lib/prawn/svg/element.rb, line 188
def parse_css_method_calls(string)
  string.scan(/\s*(\w+)\(([^)]+)\)\s*/).collect do |call|
    name, argument_string = call
    arguments = argument_string.strip.split(/\s*[,\s]\s*/)
    [name, arguments]
  end
end
parse_fill_and_stroke_attributes_and_call() click to toggle source
# File lib/prawn/svg/element.rb, line 131
def parse_fill_and_stroke_attributes_and_call
  draw_types = []
  [:fill, :stroke].each do |type|
    dec = @attributes[type.to_s]
    if dec == "none"
      state[type] = false
    elsif dec
      state[type] = true
      if color = Prawn::Svg::Color.color_to_hex(dec)
        add_call "#{type}_color", color
      end
    end

    draw_types << type.to_s if state[type]
  end
  draw_types
end
parse_font_attributes_and_call() click to toggle source
# File lib/prawn/svg/element.rb, line 153
def parse_font_attributes_and_call
  if size = @attributes['font-size']
    @state[:font_size] = size.to_f * @document.scale
  end
  if weight = @attributes['font-weight']
    font_updated = true
    @state[:font_weight] = Prawn::Svg::Font.weight_for_css_font_weight(weight)
  end
  if style = @attributes['font-style']
    font_updated = true
    @state[:font_style] = style == 'italic' ? :italic : nil
  end
  if (family = @attributes['font-family']) && family.strip != ""
    font_updated = true
    @state[:font_family] = family
  end

  if @state[:font_family] && font_updated
    usable_font_families = [@state[:font_family], document.fallback_font_name]

    font_used = usable_font_families.compact.detect do |name|
      if font = Prawn::Svg::Font.load(name, @state[:font_weight], @state[:font_style])
        @state[:font_subfamily] = font.subfamily
        add_call_and_enter 'font', font.name, :style => @state[:font_subfamily]
        true
      end
    end

    if font_used.nil?
      @document.warnings << "Font family '#{@state[:font_family]}' style '#{@state[:font_style] || 'normal'}' is not a known font, and the fallback font could not be found."
    end
  end
end
parse_opacity_attributes_and_call() click to toggle source
# File lib/prawn/svg/element.rb, line 101
def parse_opacity_attributes_and_call
  # We can't do nested opacities quite like the SVG requires, but this is close enough.
  fill_opacity = stroke_opacity = clamp(@attributes['opacity'].to_f, 0, 1) if @attributes['opacity']
  fill_opacity = clamp(@attributes['fill-opacity'].to_f, 0, 1) if @attributes['fill-opacity']
  stroke_opacity = clamp(@attributes['stroke-opacity'].to_f, 0, 1) if @attributes['stroke-opacity']

  if fill_opacity || stroke_opacity
    state[:fill_opacity] = (state[:fill_opacity] || 1) * (fill_opacity || 1)
    state[:stroke_opacity] = (state[:stroke_opacity] || 1) * (stroke_opacity || 1)

    add_call_and_enter 'transparent', state[:fill_opacity], state[:stroke_opacity]
  end
end
parse_stroke_width_attribute_and_call() click to toggle source
# File lib/prawn/svg/element.rb, line 149
def parse_stroke_width_attribute_and_call
  add_call('line_width', @document.distance(@attributes['stroke-width'])) if @attributes['stroke-width']
end
parse_transform_attribute_and_call() click to toggle source
# File lib/prawn/svg/element.rb, line 66
def parse_transform_attribute_and_call
  return unless transform = @attributes['transform']

  parse_css_method_calls(transform).each do |name, arguments|
    case name
    when 'translate'
      x, y = arguments
      add_call_and_enter name, @document.distance(x), -@document.distance(y)

    when 'rotate'
      r, x, y = arguments.collect {|a| a.to_f}
      if arguments.length == 3
        add_call_and_enter name, -r, :origin => [@document.x(x), @document.y(y)]
      else
        add_call_and_enter name, -r, :origin => [0, @document.y('0')]
      end

    when 'scale'
      x_scale = arguments[0].to_f
      y_scale = (arguments[1] || x_scale).to_f
      add_call_and_enter "transformation_matrix", x_scale, 0, 0, y_scale, 0, 0

    when 'matrix'
      if arguments.length != 6
        @document.warnings << "transform 'matrix' must have six arguments"
      else
        a, b, c, d, e, f = arguments.collect {|argument| argument.to_f}
        add_call_and_enter "transformation_matrix", a, -b, -c, d, @document.distance(e), -@document.distance(f)
      end
    else
      @document.warnings << "Unknown transformation '#{name}'; ignoring"
    end
  end
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.