package CSS::SpriteMaker::Layout::FixedDimension; use strict; use warnings; use base 'CSS::SpriteMaker::Layout'; =head1 NAME CSS::SpriteMaker::Layout::FixedDimension my $FixedDimensionLayout = CSS::SpriteMaker::Layout::FixedDimension->new( # example $rh_item_info input structure { "1" => { width => 128, height => 128, }, ... }, # max 10 items on the same row, { dimension => 'horizontal', n => 10 }, ); Layout maximum I<n> items on a row. Items are chosen at random. Input $rh_item_info structure must contain the following keys for this layout to produce a result: - width : the width in pixels of the image; - height : the height in pixels of the image; The following input parameters B<must> be specified: - n : number of maximum items to place on the same row The following input parameters are optional: - dimension: can be 'horizontal' (default) or 'vertical'. =head1 VERSION Version 0.01 =cut our $VERSION = '0.01'; =head2 new Instantiates the layout: my $FixedDimensionLayout = CSS::SpriteMaker::Layout::FixedDimension->new( $rh_item_info, { dimension => 'vertical' # 'horizontal' is the default n => 10 # compulsory! } ); =cut sub new { my $class = shift; my $rh_items_info = shift; my $rh_input_params = shift; # defaults $rh_input_params->{dimension} //= 'horizontal'; my $self = bless {}, $class; if (!$rh_items_info) { die 'no items info hashref was passed in construction to this layout'; } $self->_layout_items($rh_items_info, $rh_input_params); $self->finalize(); return $self; } =head2 _layout_items =cut sub _layout_items { my $self = shift; my $rh_items_info = shift; my $rh_input_params = shift; if (!exists $rh_input_params->{n} || !defined $rh_input_params->{n}) { die "the layout parameter 'n' is required for this layout to produce a result."; } my $n = $rh_input_params->{n}; my $dimension = $rh_input_params->{dimension}; # 1. put items from the same directory in the same row my $dimension_id = $dimension eq 'horizontal' ? '0' : '1'; my @xy = (0, 0); my @total_wh = (0, 0); my $dimension_size = 0; my $i = 0; for my $id (keys %$rh_items_info) { my @wh = ($rh_items_info->{$id}{width}, $rh_items_info->{$id}{height}); # condition to switch to the next row if ($i == $n) { # this item must go on the next row $xy[1-$dimension_id] += $dimension_size; $xy[$dimension_id] = 0; $dimension_size = 0; # reset condition $i = 0; } # chain on the current row... $self->set_item_coord($id, @xy); # prepare next element $xy[$dimension_id] += $wh[$dimension_id]; # calculate dimension size (height or width based on dimension) $dimension_size = $wh[1-$dimension_id] if $wh[1-$dimension_id] > $dimension_size; # update min/max sizes if ($xy[$dimension_id] > $total_wh[$dimension_id]) { $total_wh[$dimension_id] = $xy[$dimension_id]; } if ($xy[1-$dimension_id] + $dimension_size > $total_wh[1-$dimension_id]) { $total_wh[1-$dimension_id] = $xy[1-$dimension_id] + $dimension_size } $i++; } $self->{width} = $total_wh[0]; $self->{height} = $total_wh[1]; return; } 1;