# 
#	Opt/Surface.pm
#
#	A package for manipulating SDL_Surface *
#
#	Copyright (C) 2003 David J. Goehrig

package SDL::Opt::Surface;

use strict;
use SDL;

require SDL::Opt::Rect;
require SDL::Opt::Color;
require SDL::Palette;

sub new {
	my $proto = shift;	
	my $class = ref($proto) || $proto;
	my %options = @_;
	my $self;

	verify (%options, qw/ -name -n -flags -fl -width -w -height -h -depth -d
				-pitch -p -Rmask -r -Gmask -g -Bmask -b -Amask -a
				-from -f /) if $SDL::DEBUG;
	
	if ( $options{-name} ne "" && exists $SDL::{IMGLoad} ) {		
	   $self = \SDL::IMGLoad($options{-name});	
	} else {
		my $f = $options{-flags}  	|| $options{-fl} 	|| SDL::ANYFORMAT();
		my $w = $options{-width} 	|| $options{-w}		|| 1;
		my $h = $options{-height} 	|| $options{-h}		|| 1;	
		my $d = $options{-depth} 	|| $options{-d}		|| 8;
		my $p = $options{-pitch} 	|| $options{-p}		|| $w*$d;              
		my $r = $options{-Rmask} 	|| $options{-r}	
			||  ( SDL::BigEndian() ? 0xff000000 : 0x000000ff );
		my $g = $options{-Gmask} 	|| $options{-g}
			||  ( SDL::BigEndian() ? 0x00ff0000 : 0x0000ff00 );
		my $b = $options{-Bmask} 	|| $options{-b}
			||  ( SDL::BigEndian() ? 0x0000ff00 : 0x00ff0000 );
		my $a = $options{-Amask} 	|| $options{-a}
			||  ( SDL::BigEndian() ? 0x000000ff : 0xff000000 );

		if ( $options{-from}|| $options{-f} ) { 
			my $src = $options{-from}|| $options{-f};
			$self = \SDL::CreateRGBSurfaceFrom($src,$w,$h,$d,$p,$r,$g,$b,$a);
		} else {
			$self = \SDL::CreateRGBSurface($f,$w,$h,$d,$r,$g,$b,$a);
		}
	}
	die "SDL::Surface::new failed. ", SDL::GetError()
		unless ( $$self{-surface});
	bless $self,$class;
	return $self;
}

sub DESTROY {		
	SDL::FreeSurface(${$_[0]});
}

sub flags {
	SDL::SurfaceFlags(${$_[0]});
}

sub palette {
	SDL::SurfacePalette(${$_[0]});
}

sub bpp {
	SDL::SurfaceBitsPerPixel(${$_[0]});
}

sub bytes_per_pixel {
	SDL::SurfaceBytesPerPixel(${$_[0]});
}

sub Rshift {
	SDL::SurfaceRshift(${$_[0]});
}

sub Gshift {
	SDL::SurfaceGshift(${$_[0]});
}

sub Bshift {
	SDL::SurfaceBshift(${$_[0]});
}

sub Ashift {
	SDL::SurfaceAshift(${$_[0]});
}

sub Rmask {
	SDL::SurfaceRmask(${$_[0]});
}

sub Gmask {
	SDL::SurfaceGmask(${$_[0]});
}

sub Bmask {
	SDL::SurfaceBmask(${$_[0]});
}

sub Amask {
	SDL::SurfaceAmask(${$_[0]});
}

sub color_key {
	SDL::SurfaceColorKey(${$_[0]});
}

sub alpha {
	SDL::SurfaceAlpha(${$_[0]});
}

sub width {
	SDL::SurfaceW(${$_[0]});
}

sub height {
	SDL::SurfaceH(${$_[0]});
}

sub pitch {
	SDL::SurfacePitch(${$_[0]});
}

sub pixels {
	SDL::SurfacePixels(${$_[0]});
}

sub pixel {
	die "SDL::Opt::Surface::pixel requires a SDL::Opt::Color"
		unless $_[3] && $SDL::DEBUG && $_[3]->isa("SDL::Opt::Color");
	$_[3] ?
		new SDL::Opt::Color -color => SDL::SurfacePixel(${$_[0]},$_[1],$_[2],${$_[3]}) :
		new SDL::Opt::Color -color => SDL::SurfacePixel(${$_[0]},$_[1],$_[2]);
}

sub fill {
	die "SDL::Opt::Surface::fill requires a SDL::Opt::Rect object"
		unless !$SDL::DEBUG || $_[1]->isa('SDL::Opt::Rect');
	die "SDL::Opt::Surface::fill requires a SDL::Opt::Color object"
		unless !$SDL::DEBUG || $_[2]->isa('SDL::Opt::Color');
	return SDL::FillRect(${$_[0]},${$_[1]},${$_[2]});
}

sub lockp {
	SDL::MUSTLOCK(${$_[0]});
}

sub lock {
	SDL::SurfaceLock(${$_[0]});
}

sub unlock {
	SDL::SurfaceUnlock(${$_[0]});
}

sub update {
	my $self = shift;;
	if ($SDL::DEBUG) {
		for (@_) { 
			die "SDL::Opt::Surface::update requires SDL::Opt::Rect objects"
				unless $_->isa('SDL::Opt::Rect');
		}
	}
	SDL::UpdateRects($$self, map { ${$_} } @_ );
}

sub flip {
	SDL::Flip(${$_[0]});
}

sub blit {
	if ($SDL::DEBUG) {
		die "SDL::Opt::Surface::blit requires SDL::Opt::Rect objects"
			unless ! $SDL::DEBUG || $_[1]->isa('SDL::Opt::Rect') 
				&& $_[3]->('SDL::Opt::Rect');
		die "SDL::Opt::Surface::blit requires SDL::Opt::Surface objects"
			unless ! $SDL::DEBUG || $_[2]->isa('SDL::Opt::Surface'); 
	}
	SDL::BlitSurface(map { ${$_} } @_);
}

sub set_colors {
	my $self = shift;
	my $start = shift;
	for (@_) {
		die "SDL::Opt::Surface::set_colors requires SDL::Opt::Color objects"
			unless !$SDL::DEBUG || $_->isa('SDL::Opt::Color');
	}
	return SDL::SetColors($$self, $start, map { ${$_} } @_);
}

sub set_color_key {
	die "SDL::Opt::Surface::set_color_key requires a SDL::Opt::Color object"
		unless !$SDL::DEBUG || $_[2]->isa('SDL::Opt::Color');
	SDL::SetColorKey(${$_[0]},$_[1],$_[2]->pixel());
}

sub set_alpha {
	SDL::SetAlpha(${$_[0]},$_[1],$_[2]);
}

sub display_format {
	my $self = shift;
	my $tmp = SDL::DisplayFormat ($$self);
	SDL::FreeSurface ($$self);
	$self = \$tmp;
	$self;
}

sub rgb {
	my $self = shift;
	my $tmp = SDL::ConvertRGB($$self);
	SDL::FreeSurface($$self);
	$self = \$tmp;
	$self;
}

sub rgba {
	my $self = shift;
	my $tmp = SDL::ConvertRGBA($$self);
	SDL::FreeSurface($$self);
	$self = \$tmp;
	$self;
}

sub print {
	my ($self,$x,$y,@text) = @_;
	SDL::PutString( $$self, $x, $y, join('',@text));
}

sub save_bmp {
	SDL::SaveBMP( ${$_[0]},$_[1]);
}

sub video_info {
	shift;
	SDL::VideoInfo();
}

1;

__END__;

=pod 

=head1 NAME

SDL::Opt::Surface - a SDL perl extension

=head1 SYNOPSIS

  use SDL::Opt::Surface;
  $image = new SDL::Opt::Surface(-name=>"yomama.jpg");

=head1 DESCRIPTION

The L<SDL::Opt::Surface> module encapsulates the SDL_Surface* structure, and
many of its ancillatory functions.  It has a similar interface to the L<SDL::Surface>
class. Where it differs:

=over 4

=item *

All methods require SDL::Opt::* objects.  If $SDL::DEBUG is false, no type checks will be made.

=item *

C<SDL::Opt::Surface::set_color_key> takes a flag and an SDL::Opt::Color object only.

=back

=head1 AUTHOR

David J. Goehrig

=head1 SEE ALSO

L<perl> L<SDL::Opt::Rect> L<SDL::Opt::Color> L<SDL::Surface>

=cut

