#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#include "typedfs.h"
#include "common.h"

#include "raster.h"
#include "ras_comp.h"

#include "rasterut.cc"


/* Raster 2D abstract class */

/** Release one continuous piece of memory, and pointers into it. */
void Raster2DACompact::Erase2DBlock(void)
{
if(Data2D)
  {
  if(Data2D[0]) 
    {
    free(Data2D[0]);
    Data2D[0] = NULL;
    }   
  free(Data2D);
  Data2D=NULL;
  }
Data1D=NULL;
Size2D=0;
}


/** Allocate one continuous piece of memory. */
void Raster2DACompact::Allocate2D(unsigned NewSize1D, unsigned NewSize2D)
{
int i;

 if(Size2D==NewSize2D && Size1D==NewSize1D && Data2D!=NULL) return; //no change
 if(Data2D) Erase();

 Data2D = (void **)calloc(sizeof(void *),NewSize2D);
 if(!Data2D) return;		/*Not Enough memory*/

 Data2D[0] = (void *)malloc( (NewSize1D*NewSize2D*GetPlanes()) / 8 );
 if(!Data2D[0])
 {
   free(Data2D);
   Data2D = NULL;
   return;
 }

 Size2D=NewSize2D;
 Size1D=NewSize1D;
 for(i=1;i<NewSize2D;i++)
	{
	Data2D[i] = (uint8_t*)(Data2D[i-1]) + (NewSize1D*GetPlanes())/8;	
	}
}

/* Specialised Raster 2D modules */
class Raster2DC_1Bit: virtual public Raster2DACompact, public Raster1D_1Bit {};
class Raster2DC_2Bit: virtual public Raster2DACompact, public Raster1D_2Bit {};
class Raster2DC_4Bit: virtual public Raster2DACompact, public Raster1D_4Bit {};
class Raster2DC_8Bit: virtual public Raster2DACompact, public Raster1D_8Bit {};
class Raster2DC_16Bit:virtual public Raster2DACompact, public Raster1D_16Bit {};
class Raster2DC_24Bit:virtual public Raster2DACompact, public Raster1D_24Bit {};
class Raster2DC_32Bit:virtual public Raster2DACompact, public Raster1D_32Bit {};


Raster2DAbstract *CreateCompRaster2D(unsigned SizeX, unsigned SizeY, int Planes)
{
Raster2DAbstract *Raster=NULL;

switch(Planes)
   {
   case  0:return(NULL);
   case  1:Raster=new Raster2DC_1Bit;   break;
   case  2:Raster=new Raster2DC_2Bit;   break;
   case  4:Raster=new Raster2DC_4Bit;   break;
   case  8:Raster=new Raster2DC_8Bit;   break;
   case 16:Raster=new Raster2DC_16Bit;  break;
   case 24:Raster=new Raster2DC_24Bit;  break;
   case 32:Raster=new Raster2DC_32Bit;  break;
   default:return(NULL);
   }
if(Raster)
   {
   Raster->Allocate2D(SizeX,SizeY);
   if(Raster->Data2D==NULL)
	{
	delete Raster;
	return(NULL);
	}
   }

return(Raster);
}


class Raster2DC_8BitRGB: virtual public Raster2DACompact, public Raster1D_8BitRGB {};
class Raster2DC_16BitRGB: virtual public Raster2DACompact, public Raster1D_16BitRGB {};


Raster2DAbstract *CreateCompRaster2DRGB(unsigned SizeX, unsigned SizeY, int Planes)
{
Raster2DAbstract *Raster=NULL;

 switch(Planes)
   {
   case  8:Raster=new Raster2DC_8BitRGB;   break;
   case 16:Raster=new Raster2DC_16BitRGB;  break;
   default:return(NULL);
   }

 if(Raster)
   {
   Raster->Allocate2D(SizeX,SizeY);
   if(Raster->Data2D==NULL)
	{
	delete Raster;
	return(NULL);
	}
   }

return(Raster);
}
