module SpriteFactory::Layout::Packed

Public Class Methods

findNode(root, w, h) click to toggle source
# File lib/sprite_factory/layout/packed.rb, line 56
def self.findNode(root, w, h)
  if root[:used]
    findNode(root[:right], w, h) || findNode(root[:down], w, h)
  elsif (w <= root[:w]) && (h <= root[:h])
    root
  end
end
grow(root, w, h) click to toggle source
# File lib/sprite_factory/layout/packed.rb, line 70
def self.grow(root, w, h)

  canGrowDown  = (w <= root[:w])
  canGrowRight = (h <= root[:h])

  shouldGrowRight = canGrowRight && (root[:h] >= (root[:w] + w))
  shouldGrowDown  = canGrowDown  && (root[:w] >= (root[:h] + h))

  if shouldGrowRight
    growRight(root, w, h)
  elsif shouldGrowDown
    growDown(root, w, h)
  elsif canGrowRight
    growRight(root, w, h)
  elsif canGrowDown
    growDown(root, w, h)
  else
    raise RuntimeError, "can't fit #{w}x#{h} block into root #{root[:w]}x#{root[:h]} - this should not happen if images are pre-sorted correctly"
  end

end
growDown(root, w, h) click to toggle source
# File lib/sprite_factory/layout/packed.rb, line 104
def self.growDown(root, w, h)
  return {
    :used  => true,
    :x     => 0,
    :y     => 0,
    :w     => root[:w],
    :h     => root[:h] + h,
    :down  => { :x => 0, :y => root[:h], :w => root[:w], :h => h },
    :right => root
  }
end
growRight(root, w, h) click to toggle source
# File lib/sprite_factory/layout/packed.rb, line 92
def self.growRight(root, w, h)
  return {
    :used  => true,
    :x     => 0,
    :y     => 0,
    :w     => root[:w] + w,
    :h     => root[:h],
    :down  => root,
    :right => { :x => root[:w], :y => 0, :w => w, :h => root[:h] }
  }
end
layout(images, options = {}) click to toggle source
# File lib/sprite_factory/layout/packed.rb, line 7
def self.layout(images, options = {})

  raise NotImplementedError, ":packed layout does not support fixed :width/:height option" if options[:width] || options[:height]

  return { :width => 0, :height => 0 } if images.empty?

  hpadding = options[:hpadding] || 0
  vpadding = options[:vpadding] || 0
  hmargin  = options[:hmargin]  || 0
  vmargin  = options[:vmargin]  || 0

  images.each do |i|
    i[:w] = i[:width]  + (2*hpadding) + (2*hmargin)
    i[:h] = i[:height] + (2*vpadding) + (2*vmargin)
  end

  images.sort! do |a,b|
    diff = [b[:w], b[:h]].max <=> [a[:w], a[:h]].max
    diff = [b[:w], b[:h]].min <=> [a[:w], a[:h]].min if diff.zero?
    diff = b[:h] <=> a[:h] if diff.zero?
    diff = b[:w]  <=> a[:w]  if diff.zero?
    diff
  end

  root = { :x => 0, :y => 0, :w => images[0][:w], :h => images[0][:h] }

  images.each do |i|
    if (node = findNode(root, i[:w], i[:h]))
      placeImage(i, node, hpadding, vpadding, hmargin, vmargin)
      splitNode(node, i[:w], i[:h])
    else
      root = grow(root, i[:w], i[:h])
      redo
    end
  end

  { :width => root[:w], :height => root[:h] }

end
placeImage(image, node, hpadding, vpadding, hmargin, vmargin) click to toggle source
# File lib/sprite_factory/layout/packed.rb, line 47
def self.placeImage(image, node, hpadding, vpadding, hmargin, vmargin)
  image[:cssx] = node[:x] + hmargin
  image[:cssy] = node[:y] + vmargin
  image[:cssw] = image[:width]  + (2*hpadding)
  image[:cssh] = image[:height] + (2*vpadding)
  image[:x]    = image[:cssx] + hpadding 
  image[:y]    = image[:cssy] + vpadding
end
splitNode(node, w, h) click to toggle source
# File lib/sprite_factory/layout/packed.rb, line 64
def self.splitNode(node, w, h)
  node[:used]  = true
  node[:down]  = { :x => node[:x],     :y => node[:y] + h, :w => node[:w],     :h => node[:h] - h }
  node[:right] = { :x => node[:x] + w, :y => node[:y],     :w => node[:w] - w, :h => h            }
end