/*  $Id: sprite_packer_generic.cpp,v 1.13 2003/08/14 20:22:14 mbn Exp $
**
**  ClanLib Game SDK
**  Copyright (C) 2003  The ClanLib Team
**  For a total list of contributers see the file CREDITS.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This library is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
**  Lesser General Public License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
*/

#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);
	}
}
