From 4dd1223682e42e32fc5b43881c25574373527b6c Mon Sep 17 00:00:00 2001 From: John Bintz Date: Fri, 25 May 2012 20:19:00 -0400 Subject: [PATCH] add support for alternate file sources for image size analysis --- lib/compass/configuration.rb | 3 +- .../sass_extensions/functions/image_size.rb | 56 +++++++++++-------- test/units/sass_extensions_test.rb | 21 +++++-- 3 files changed, 51 insertions(+), 29 deletions(-) diff --git a/lib/compass/configuration.rb b/lib/compass/configuration.rb index 79b3b3f2..dc23077a 100644 --- a/lib/compass/configuration.rb +++ b/lib/compass/configuration.rb @@ -40,7 +40,8 @@ module Compass :preferred_syntax, :disable_warnings, :sprite_engine, - :chunky_png_options + :chunky_png_options, + :images_file_source ].flatten ARRAY_ATTRIBUTES = [ diff --git a/lib/compass/sass_extensions/functions/image_size.rb b/lib/compass/sass_extensions/functions/image_size.rb index 97bf85c3..436c4de7 100644 --- a/lib/compass/sass_extensions/functions/image_size.rb +++ b/lib/compass/sass_extensions/functions/image_size.rb @@ -4,7 +4,7 @@ module Compass::SassExtensions::Functions::ImageSize width, _ = image_dimensions(image_file) Sass::Script::Number.new(width,["px"]) end - + # Returns the height of the image relative to the images directory def image_height(image_file) _, height = image_dimensions(image_file) @@ -23,13 +23,23 @@ module Compass::SassExtensions::Functions::ImageSize raise Sass::SyntaxError, "Unrecognized file type: #{@file_type}" end - private + private + def open_file_source + source = Compass.configuration.images_file_source || lambda { |file| File.open(file, 'rb') } + + io = source.call(@file) + result = yield io + io.close + + result + end + def get_size_for_png - File.open(@file, "rb") {|io| io.read}[0x10..0x18].unpack('NN') + open_file_source {|io| io.read}[0x10..0x18].unpack('NN') end def get_size_for_gif - File.open(@file, "rb") {|io| io.read}[6..10].unpack('SS') + open_file_source {|io| io.read}[6..10].unpack('SS') end def get_size_for_jpg @@ -37,22 +47,24 @@ module Compass::SassExtensions::Functions::ImageSize end def get_size_for_jpeg - jpeg = JPEG.new(@file) - [jpeg.width, jpeg.height] + open_file_source do |io| + jpeg = JPEG.new(io) + [ jpeg.width, jpeg.height ] + end end end -private + private def image_dimensions(image_file) options[:compass] ||= {} options[:compass][:image_dimensions] ||= {} options[:compass][:image_dimensions][image_file.value] = ImageProperties.new(image_path_for_size(image_file.value)).size end - + def image_path_for_size(image_file) if File.exists?(image_file) - return image_file + return image_file end real_path(image_file) end @@ -69,15 +81,11 @@ private class JPEG attr_reader :width, :height, :bits - def initialize(file) - if file.kind_of? IO - examine(file) - else - File.open(file, 'rb') { |io| examine(io) } - end + def initialize(io) + examine(io) end - private + private def examine(io) class << io unless method_defined?(:readbyte) @@ -99,15 +107,15 @@ private while marker = io.next case marker - when 0xC0..0xC3, 0xC5..0xC7, 0xC9..0xCB, 0xCD..0xCF # SOF markers - length, @bits, @height, @width, components = io.readsof - raise 'malformed JPEG' unless length == 8 + components * 3 - when 0xD9, 0xDA then break # EOI, SOS - when 0xFE then @comment = io.readframe # COM - when 0xE1 then io.readframe # APP1, contains EXIF tag - else io.readframe # ignore frame + when 0xC0..0xC3, 0xC5..0xC7, 0xC9..0xCB, 0xCD..0xCF # SOF markers + length, @bits, @height, @width, components = io.readsof + raise 'malformed JPEG' unless length == 8 + components * 3 + when 0xD9, 0xDA then break # EOI, SOS + when 0xFE then @comment = io.readframe # COM + when 0xE1 then io.readframe # APP1, contains EXIF tag + else io.readframe # ignore frame end end end -end + end end diff --git a/test/units/sass_extensions_test.rb b/test/units/sass_extensions_test.rb index 67ffb895..bf989b3f 100644 --- a/test/units/sass_extensions_test.rb +++ b/test/units/sass_extensions_test.rb @@ -166,16 +166,29 @@ class SassExtensionsTest < Test::Unit::TestCase base64_string = File.read(File.join(Compass.configuration.fonts_path, "bgrove.base64.txt")).chomp assert_equal "url('data:font/truetype;base64,#{base64_string}') format('truetype')", evaluate("inline_font_files('bgrove.ttf', truetype)") end - - + def test_image_size_should_respond_to_to_path object = mock() object.expects(:to_path).returns('foo.jpg') object.expects(:respond_to?).with(:to_path).returns(true) - + Compass::SassExtensions::Functions::ImageSize::ImageProperties.new(object) end - + + def test_image_properites_should_be_able_to_use_file_like_object + source = Class.new do + def self.open(*args, &block) + File.open(*args, &block) + end + end + + Compass.configuration.images_file_source = lambda { |file| source.open(file) } + + properties = Compass::SassExtensions::Functions::ImageSize::ImageProperties.new('test/fixtures/sprites/public/images/colors/blue.png') + + assert_equal [ 10, 10 ], properties.size + end + def test_reject assert_equal "b d", evaluate("reject(a b c d, a, c)") assert_equal "a b c d", evaluate("reject(a b c d, e)")