/*
**  ClanLib SDK
**  Copyright (c) 1997-2005 The ClanLib Team
**
**  This software is provided 'as-is', without any express or implied
**  warranty.  In no event will the authors be held liable for any damages
**  arising from the use of this software.
**
**  Permission is granted to anyone to use this software for any purpose,
**  including commercial applications, and to alter it and redistribute it
**  freely, subject to the following restrictions:
**
**  1. The origin of this software must not be misrepresented; you must not
**     claim that you wrote the original software. If you use this software
**     in a product, an acknowledgment in the product documentation would be
**     appreciated but is not required.
**  2. Altered source versions must be plainly marked as such, and must not be
**     misrepresented as being the original software.
**  3. This notice may not be removed or altered from any source distribution.
**
**  Note: Some of the libraries ClanLib may link to may have additional
**  requirements or restrictions.
**
**  File Author(s):
**
**    Magnus Norddahl
**    (if your name is missing here, please add it)
*/

#include "API/Display/pixel_buffer.h"
#include "Display/display_precomp.h"
#include "sprite_packer_generic.h"

/////////////////////////////////////////////////////////////////////////////
// CL_SpritePacker_Generic construction:

CL_SpritePacker_Generic::CL_SpritePacker_Generic(const CL_SpriteDescription &desc)
: description(desc)
{
}

/////////////////////////////////////////////////////////////////////////////
// CL_SpritePacker_Generic::Node implementation:

CL_SpritePacker_Generic::Node::Node()
{
	child[0] = NULL;
	child[1] = NULL;

	image = NULL;
}

CL_SpritePacker_Generic::Node::Node(const CL_Rect &new_rect)
{
	rect = new_rect;

	child[0] = NULL;
	child[1] = NULL;

	image = NULL;
}

CL_SpritePacker_Generic::Node::~Node()
{
	clear();
}

void CL_SpritePacker_Generic::Node::clear()
{
	if(child[0])
	{
		delete child[0];
		child[0] = NULL;
	}
	if(child[1])
	{
		delete child[1];
		child[1] = NULL;
	}
	image = NULL;
}

CL_SpritePacker_Generic::Node *CL_SpritePacker_Generic::Node::insert(CL_SpriteDescription::FramePair new_image)
{
	// If we're not a leaf
	if(child[0] && child[1])
	{
		// Try inserting into first child
		Node *new_node = child[0]->insert(new_image);
		if(new_node != NULL)
			return new_node;
        
		// No room, insert into second
		return child[1]->insert(new_image);
	}
	else
	{
		// If there's already a texture here, return
		if (image)
			return NULL;

		int image_width  = new_image.second.get_width()  + 2;
		int image_height = new_image.second.get_height() + 2;
		
		// If we're too small, return
		if (image_width > rect.get_width() || image_height > rect.get_height())
			return NULL;

		// If we're just right, accept
		if (image_width == rect.get_width() && image_height == rect.get_height())
		{
			image      = new_image.first;
			image_rect = new_image.second;
			image_rect.right  += 2;
			image_rect.bottom += 2;
			return this;
		}
        
		// Otherwise, decide which way to split
		int dw = rect.get_width() - image_width;
		int dh = rect.get_height() - image_height;
        
		if (dw > dh)
		{
			child[0] = new Node(CL_Rect(rect.left, rect.top, rect.left + image_width, rect.bottom));
			child[1] = new Node(CL_Rect(rect.left + image_width, rect.top, rect.right, rect.bottom));
		}
		else
		{
			child[0] = new Node(CL_Rect(rect.left, rect.top, rect.right, rect.top + image_height));
			child[1] = new Node(CL_Rect(rect.left, rect.top + image_height, rect.right, rect.bottom));
		}
        
		// Insert into first child we created
		return child[0]->insert(new_image);
	}
}
