diff --git a/lib/compass/sass_extensions/sprites/image.rb b/lib/compass/sass_extensions/sprites/image.rb index 4ee6a186a0..c9e07d704e 100644 --- a/lib/compass/sass_extensions/sprites/image.rb +++ b/lib/compass/sass_extensions/sprites/image.rb @@ -8,9 +8,10 @@ class Image PARENT = %r{(.+)[-_](.+)$} REPEAT_X = 'repeat-x' + REPEAT_Y = 'repeat-y' NO_REPEAT = 'no-repeat' - VALID_REPEATS = [REPEAT_X, NO_REPEAT] + VALID_REPEATS = [REPEAT_Y, REPEAT_X, NO_REPEAT] attr_reader :relative_file, :options, :base attr_accessor :top, :left @@ -73,6 +74,10 @@ def repeat_x? repeat == REPEAT_X end + def repeat_y? + repeat == REPEAT_Y + end + def no_repeat? repeat == NO_REPEAT end diff --git a/lib/compass/sass_extensions/sprites/layout/horizontal.rb b/lib/compass/sass_extensions/sprites/layout/horizontal.rb index 166d40dd58..e46c18fa2e 100644 --- a/lib/compass/sass_extensions/sprites/layout/horizontal.rb +++ b/lib/compass/sass_extensions/sprites/layout/horizontal.rb @@ -6,20 +6,35 @@ class Horizontal < SpriteLayout def layout! calculate_height! - calculate_positions! calculate_width! + calculate_positions! + tile_images_that_repeat! end private # ===========================================================================================> def calculate_height! @height = @images.map {|image| image.height + image.offset}.max + if repeating_images? + calculate_repeat_extra_height! + end + @height end def calculate_width! @width = @images.inject(0) { |sum, image| sum += (image.width + image.spacing) } end + def repeating_images? + @repeating_images ||= @images.any?(&:repeat_y?) + end + + def calculate_repeat_extra_height! + m = @images.inject(1) {|m,img| img.repeat_y? ? m.lcm(img.height) : m } + remainder = @height % m + @height += (m - remainder) unless remainder.zero? + end + def calculate_positions! @images.each_with_index do |image, index| image.top = image.position.unit_str == '%' ? (@height - image.height) * (image.position.value / 100.0) : image.position.value @@ -29,6 +44,21 @@ def calculate_positions! end end + def tile_images_that_repeat! + return unless repeating_images? + @images.map {|img| img if img.repeat_y?}.compact.each do |image| + y = (image.top + image.height) + while y < @height do + begin + img = image.dup + img.top = y.to_i + @images << img + y += image.height + end + end #while + end + end + end end end diff --git a/test/units/sprites/image_test.rb b/test/units/sprites/image_test.rb index bd3e44abaf..dc80d38128 100644 --- a/test/units/sprites/image_test.rb +++ b/test/units/sprites/image_test.rb @@ -74,6 +74,11 @@ def test_image(options ={}) assert img.repeat_x? end + test 'image repeat-y' do + img = test_image "selectors_ten_by_ten_repeat" => Sass::Script::String.new('repeat-y') + assert img.repeat_y? + end + test 'image position' do image = test_image "selectors_ten_by_ten_position" => Sass::Script::Number.new(100, ["px"]) assert_equal 100, image.position.value diff --git a/test/units/sprites/layout_test.rb b/test/units/sprites/layout_test.rb index 371e3eb3ce..d15b6558e7 100644 --- a/test/units/sprites/layout_test.rb +++ b/test/units/sprites/layout_test.rb @@ -67,6 +67,22 @@ def horizontal(options= {}) assert_equal 12, map.width end + test "repeat-y layout single image" do + opts = {"layout" => Sass::Script::String.new('horizontal'), "squares_ten_by_ten_repeat" => Sass::Script::String.new('repeat-y')} + map = sprite_map_test(@options.merge(opts), 'squares/*.png') + assert_equal 30, map.width + assert_equal 20, map.height + assert_equal 3, map.images.size + assert_equal [[0,0], [0,10], [10,0]], map.images.map { |img| [img.top, img.left] } + assert map.horizontal? + end + + test "repeat-y layout multi image" do + opts = {"layout" => Sass::Script::String.new('horizontal'), "repeat_x_three_repeat" => Sass::Script::String.new('repeat-y'), "repeat_x_four_repeat" => Sass::Script::String.new('repeat-y')} + map = sprite_map_test(@options.merge(opts), 'repeat_x/*.png') + assert_equal [[0, 0], [0, 5], [0, 9], [0, 10], [0, 13], [4, 5], [8, 5], [3, 10], [6, 10], [9, 10]], map.images.map { |img| [img.top, img.left] } + end + # VERTICAL LAYOUT it "should have a vertical layout" do