File: row_fitter.rb

package info (click to toggle)
ruby-compass 1.0.1~dfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 8,152 kB
  • ctags: 1,795
  • sloc: ruby: 12,901; makefile: 127; perl: 43; xml: 14; sh: 4
file content (92 lines) | stat: -rw-r--r-- 2,125 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
require 'forwardable'

module Compass
  module SassExtensions
    module Sprites
      class RowFitter
        extend Forwardable

        attr_reader :images, :rows
        def_delegators :rows, :[]

        def initialize(images)
          @images = images.sort do |a,b|
            if a.height == b.height
              b.width <=> a.width
            else
              a.height <=> b.height
            end
          end
          @rows = []
        end

        def fit!(style = :scan)
          send("#{style}_fit")
          @rows
        end

        def width
          @width ||= @images.collect(&:width).max
        end
        
        def height
          @height ||= @rows.inject(0) {|sum, row| sum += row.height}
        end

        def efficiency
          @rows.inject(0) { |sum, row| sum += row.efficiency } ** @rows.length
        end

        private
        def new_row(image = nil)
          row = Compass::SassExtensions::Sprites::ImageRow.new(width)
          row.add(image) if image
          row
        end

        def fast_fit
          row = new_row
          @images.each do |image|
            if !row.add(image)
              @rows << row
              row = new_row(image)
            end
          end

          @rows << row
        end

        def scan_fit
          fast_fit

          moved_images = []

          begin
            removed = false

            catch :done do
              @rows.each do |row|
                (@rows - [ row ]).each do |other_row|
                  other_row.images.each do |image|
                    if !moved_images.include?(image)
                      if row.will_fit?(image)
                        other_row.delete(image)
                        row << image

                        @rows.delete(other_row) if other_row.empty?
                        removed = true

                        moved_images << image
                        throw :done
                      end
                    end
                  end
                end
              end
            end
          end while removed
        end
      end
    end
  end
end