class ODFWriter::Image

Image: replace images

Constants

IMAGE_DIR_NAME

constants

Public Class Methods

unique_image_names(doc) click to toggle source
# File lib/odf_writer/image.rb, line 88
def self.unique_image_names(doc)
  nodes   = doc.xpath("//draw:frame[@draw:name='#{@name}']")
  padding = Math.log10(nodes.length).to_i + 1 if nodes.present?
  nodes.each_with_index do |node, i|
    num = "%.#{padding}i" % i
    node.attribute('name').value = "IMAGE_#{num}_" + node.attribute('name').value
  end
end

Public Instance Methods

replace!(doc, manifest, template, item=nil ) click to toggle source

replace!

# File lib/odf_writer/image.rb, line 43
def replace!(doc, manifest, template, item=nil )

  image_data = value(item)
  
  if is_image?(image_data) 
    
    # find placeholder image
    nodes = find_image_nodes( doc )
    return if nodes.blank?
    
    # find manifest
    man = manifest.xpath("//manifest:manifest") rescue nil
    return if man.blank?
    
    # each placeholder image
    nodes.each do |node|
    
      # create unique filename for image in .odt file
      path = ::File.join(IMAGE_DIR_NAME, "#{SecureRandom.hex(20).upcase}#{::File.extname(image_data[:filename])}")
      mime = Rack::Mime.mime_type(File.extname(image_data[:filename]))
      
      # set path and mime type of placeholder image
      node.attribute('href').value = path
      if node.attribute('mime-type').present?
        node.attribute('mime-type').value = mime
      else
        node.set_attribute('mime-type', mime)
      end
      
      # set width and height of placeholder image
      parent = node.parent
      if parent.name == "frame"
        width  = parent.attribute('width').value
        height = parent.attribute('height').value
        parent.attribute('height').value = recalc_height(:x => image_data[:width], :y => image_data[:height], :newx => width, :newy => height)
      end
      
      # add image to .odt file
      add_image_file( image_data[:bytes], path, mime, doc, man, template )
      
    end
  end
  
end

Private Instance Methods

add_image_file(bytes, path, mime, doc, manifest, template ) click to toggle source

add_image_file

# File lib/odf_writer/image.rb, line 144
def add_image_file(bytes, path, mime, doc, manifest, template )

  file_entry = Nokogiri::XML::Node.new('manifest:file-entry', doc)
  file_entry.set_attribute('manifest:full-path', path)
  file_entry.set_attribute('manifest:media-type', mime)
  manifest.children.after file_entry
      
  template.output_stream.put_next_entry(path)
  template.output_stream.write bytes
  
end
find_image_nodes(doc) click to toggle source

find_image_nodes

# File lib/odf_writer/image.rb, line 114
def find_image_nodes(doc)
  doc.xpath(".//draw:frame[@draw:name='#{@name}']/draw:image")
end
is_image?(obj) click to toggle source

is_image?

# File lib/odf_writer/image.rb, line 107
def is_image?(obj)
  obj.is_a?(Hash) && (obj.keys & [:filename, :width, :height, :bytes]).length == 4
end
recalc_height(nums) click to toggle source

recalc_height

# File lib/odf_writer/image.rb, line 121
def recalc_height(nums)

  numericals = {}
  dimensions = {}
  
  #remove dimensions like 'px' or 'cm' or 'in' or 'pt'
  [:x, :y, :newx, :newy].each do |v|
    num = nums[v].to_s.match(/[0-9.]+/)
    numericals[v] = num[0].to_f if num
    dimensions[v] = nums[v].to_s.gsub(/\A[0-9.]+/, "")
  end
  
  if [:x, :y, :newx, :newy].all?{|i| numericals[i].present? }
    y = numericals[:newx] / numericals[:x] * numericals[:y]
  end 
  
  y ? "#{'%.3f'%y}#{dimensions[:newy]}" : nums[:newy]
  
end