refactored and extracted sprite methods into modules

This commit is contained in:
Scott Davis 2011-05-17 15:09:15 -04:00
parent bf0662cf87
commit fc034092aa
5 changed files with 206 additions and 127 deletions

View File

@ -1,4 +1,9 @@
require 'digest/md5'
#modules
require 'compass/sass_extensions/sprites/sprite'
require 'compass/sass_extensions/sprites/processing'
require 'compass/sass_extensions/sprites/image_helper'
#classes
require 'compass/sass_extensions/sprites/sprite_map'
require 'compass/sass_extensions/sprites/image'
require 'compass/sass_extensions/sprites/image_row'
@ -8,7 +13,6 @@ require 'compass/sass_extensions/sprites/engines'
module Compass
module SassExtensions
module Sprites
end
end
end

View File

@ -1,11 +1,14 @@
require 'compass/sass_extensions/sprites/helpers/image_helper'
require 'compass/sass_extensions/sprites/helpers/processing_helper'
module Compass
module SassExtensions
module Sprites
class Base < Sass::Script::Literal
attr_accessor :image_names, :path, :name, :map, :kwargs
attr_accessor :images, :width, :height
include Sprite
include Processing
include ImageHelper
include ProcessingHelper
# Initialize a new aprite object from a relative file path
# the path is relative to the <tt>images_path</tt> confguration option
@ -17,20 +20,7 @@ module Compass
new(sprites, sprite_map, context, kwargs)
end
# Loads the sprite engine
def require_engine!
self.class.send(:include, eval("::Compass::SassExtensions::Sprites::#{modulize}Engine"))
end
# Changing this string will invalidate all previously generated sprite images.
# We should do so only when the packing algorithm changes
SPRITE_VERSION = "1"
attr_accessor :image_names, :path, :name, :map, :kwargs
attr_accessor :images, :width, :height
def initialize(sprites, sprite_map, context, kwargs)
def initialize(sprites, sprite_map, context, kwargs)
require_engine!
@image_names = sprites
@path = sprite_map.path
@ -47,115 +37,9 @@ module Compass
compute_image_metadata!
end
# Calculates the overal image dimensions
# collects image sizes and input parameters for each sprite
# Calculates the height
def compute_image_metadata!
@width = 0
init_images
compute_image_positions!
@height = @images.last.top + @images.last.height
end
# Creates the Sprite::Image objects for each image and calculates the width
def init_images
@images = image_names.collect do |relative_file|
image = Compass::SassExtensions::Sprites::Image.new(self, relative_file, kwargs)
@width = [ @width, image.width + image.offset ].max
image
end
end
# Calculates the overal image dimensions
# collects image sizes and input parameters for each sprite
def compute_image_positions!
if kwargs.get_var('smart-pack').value
smart_packing
else
legacy_packing
end
end
# Validates that the sprite_names are valid sass
def validate!
for sprite_name in sprite_names
unless sprite_name =~ /\A#{Sass::SCSS::RX::IDENT}\Z/
raise Sass::SyntaxError, "#{sprite_name} must be a legal css identifier"
end
end
end
# The on-the-disk filename of the sprite
def filename
File.join(Compass.configuration.images_path, "#{path}-#{uniqueness_hash}.png")
end
# Generate a sprite image if necessary
def generate
if generation_required?
if kwargs.get_var('cleanup').value
cleanup_old_sprites
end
sprite_data = construct_sprite
save!(sprite_data)
Compass.configuration.run_callback(:sprite_generated, sprite_data)
end
end
def cleanup_old_sprites
Dir[File.join(Compass.configuration.images_path, "#{path}-*.png")].each do |file|
FileUtils.rm file
end
end
# Does this sprite need to be generated
def generation_required?
!File.exists?(filename) || outdated?
end
# Returns the uniqueness hash for this sprite object
def uniqueness_hash
@uniqueness_hash ||= begin
sum = Digest::MD5.new
sum << SPRITE_VERSION
sum << path
images.each do |image|
[:relative_file, :height, :width, :repeat, :spacing, :position, :digest].each do |attr|
sum << image.send(attr).to_s
end
end
sum.hexdigest[0...10]
end
@uniqueness_hash
end
# Saves the sprite engine
def save!(output_png)
saved = output_png.save filename
Compass.configuration.run_callback(:sprite_saved, filename)
saved
end
# All the full-path filenames involved in this sprite
def image_filenames
@images.map(&:file)
end
# Checks whether this sprite is outdated
def outdated?
if File.exists?(filename)
return @images.map(&:mtime).any? { |imtime| imtime.to_i > self.mtime.to_i }
end
true
end
# Mtime of the sprite file
def mtime
@mtime ||= File.mtime(filename)
# Loads the sprite engine
def require_engine!
self.class.send(:include, eval("::Compass::SassExtensions::Sprites::#{modulize}Engine"))
end
def inspect

View File

@ -0,0 +1,32 @@
module Compass
module SassExtensions
module Sprites
module ImageHelper
# Fetches the Sprite::Image object for the supplied name
def image_for(name)
@images.detect { |img| img.name == name}
end
# Returns true if the image name has a hover selector image
def has_hover?(name)
!image_for("#{name}_hover").nil?
end
# Returns true if the image name has a target selector image
def has_target?(name)
!image_for("#{name}_target").nil?
end
# Returns true if the image name has an active selector image
def has_active?(name)
!image_for("#{name}_active").nil?
end
# Return and array of image names that make up this sprite
def sprite_names
image_names.map { |f| File.basename(f, '.png') }
end
end
end
end
end

View File

@ -0,0 +1,34 @@
module Compass
module SassExtensions
module Sprites
module Processing
def smart_packing
fitter = ::Compass::SassExtensions::Sprites::RowFitter.new(@images)
current_y = 0
fitter.fit!.each do |row|
current_x = 0
row.images.each_with_index do |image, index|
image.left = current_x
image.top = current_y
current_x += image.width
image.left = image.position.unit_str == "%" ? (@width - image.width) * (image.position.value / 100) : image.position.value
end
current_y += row.height
end
end
def legacy_packing
@images.each_with_index do |image, index|
image.left = image.position.unit_str == "%" ? (@width - image.width) * (image.position.value / 100) : image.position.value
next if index == 0
last_image = @images[index-1]
image.top = last_image.top + last_image.height + [image.spacing, last_image.spacing].max
last_image = image
end
end
end
end
end
end

View File

@ -0,0 +1,125 @@
module Compass
module SassExtensions
module Sprites
module Sprite
# Changing this string will invalidate all previously generated sprite images.
# We should do so only when the packing algorithm changes
SPRITE_VERSION = "1"
# Calculates the overal image dimensions
# collects image sizes and input parameters for each sprite
# Calculates the height
def compute_image_metadata!
@width = 0
init_images
compute_image_positions!
@height = @images.last.top + @images.last.height
end
# Creates the Sprite::Image objects for each image and calculates the width
def init_images
@images = image_names.collect do |relative_file|
image = Compass::SassExtensions::Sprites::Image.new(self, relative_file, kwargs)
@width = [ @width, image.width + image.offset ].max
image
end
end
# Calculates the overal image dimensions
# collects image sizes and input parameters for each sprite
def compute_image_positions!
if kwargs.get_var('smart-pack').value
smart_packing
else
legacy_packing
end
end
# Validates that the sprite_names are valid sass
def validate!
for sprite_name in sprite_names
unless sprite_name =~ /\A#{Sass::SCSS::RX::IDENT}\Z/
raise Sass::SyntaxError, "#{sprite_name} must be a legal css identifier"
end
end
end
# The on-the-disk filename of the sprite
def filename
File.join(Compass.configuration.images_path, "#{path}-#{uniqueness_hash}.png")
end
# Generate a sprite image if necessary
def generate
if generation_required?
if kwargs.get_var('cleanup').value
cleanup_old_sprites
end
sprite_data = construct_sprite
save!(sprite_data)
Compass.configuration.run_callback(:sprite_generated, sprite_data)
end
end
def cleanup_old_sprites
Dir[File.join(Compass.configuration.images_path, "#{path}-*.png")].each do |file|
FileUtils.rm file
end
end
# Does this sprite need to be generated
def generation_required?
!File.exists?(filename) || outdated?
end
# Returns the uniqueness hash for this sprite object
def uniqueness_hash
@uniqueness_hash ||= begin
sum = Digest::MD5.new
sum << SPRITE_VERSION
sum << path
images.each do |image|
[:relative_file, :height, :width, :repeat, :spacing, :position, :digest].each do |attr|
sum << image.send(attr).to_s
end
end
sum.hexdigest[0...10]
end
@uniqueness_hash
end
# Saves the sprite engine
def save!(output_png)
saved = output_png.save filename
Compass.configuration.run_callback(:sprite_saved, filename)
saved
end
# All the full-path filenames involved in this sprite
def image_filenames
@images.map(&:file)
end
# Checks whether this sprite is outdated
def outdated?
if File.exists?(filename)
return @images.map(&:mtime).any? { |imtime| imtime.to_i > self.mtime.to_i }
end
true
end
# Mtime of the sprite file
def mtime
@mtime ||= File.mtime(filename)
end
# Calculate the size of the sprite
def size
[width, height]
end
end
end
end
end