
 /* SD_BufferSubs.c
    - Functions for handling external drivers -
    (c) 1990-95 by Andreas R. Kleinert
    Last changes : 30.04.1995
 */

#include "svoperator.h"

#include <proto/superview.h>


/* *************************************************** */
/* *						     * */
/* * SVP_SVP_DoOperation :                           * */
/* *						     * */
/* *************************************************** */

void __saveds __stdargs SVLI_256ToGrayScales(struct SV_GfxBuffer *gfxb, ULONG destdepth);
void __saveds __stdargs SVLI_24ToGrayScales(UBYTE *source, UBYTE *dest, UBYTE *color, ULONG width, ULONG height, ULONG destdepth);
ULONG __saveds __stdargs SVLI_GetDestDepth(void);
ULONG __saveds __stdargs IsHamBuffer(struct SV_GfxBuffer *gfxb);

ULONG __saveds __asm SVP_DoOperation(  register __a1 struct SVOperatorHandle  *SVOperatorHandle_a1,
                                       register __a2 struct SV_GfxBuffer      *source,
                                       register __a3 struct SV_GfxBuffer     **dest,
                                       register __d1 APTR                      future)
{
 struct SVOperatorHandle *SVOperatorHandle = SVOperatorHandle_a1;
 ULONG retval = SVERR_NO_ERROR;
 ULONG destdepth;

 struct SV_GfxBuffer *newsource;

 if( (!source) || (!dest) || (!SVOperatorHandle) ) return(SVERR_ILLEGAL_ACCESS);

 SVOperatorHandle->ah_ramhandle = SVSUP_GetMemList();
 if(!SVOperatorHandle->ah_ramhandle) return(SVERR_NO_MEMORY);


 if(source->svgfx_BufferType > SVGFX_BUFFERTYPE_ONEPLANE) return(SVERR_ACTION_NOT_SUPPORTED);

 if( IsHamBuffer(source) ) return( SVERR_HAM_DATA );

 if(source->svgfx_BufferType != SVGFX_BUFFERTYPE_ONEPLANE)
  {
   if(source->svgfx_BufferType == SVGFX_BUFFERTYPE_BITPLANE)
    {
     retval = SVSUP_BitPlaneToOnePlane8(source, &newsource);

     if(newsource)
      {
       SVSUP_AddMemEntry(SVOperatorHandle->ah_ramhandle, newsource);

       if((newsource)->svgfx_Buffer) SVSUP_AddMemEntry(SVOperatorHandle->ah_ramhandle, (newsource)->svgfx_Buffer);

      }else retval = SVERR_NO_MEMORY;

    }else retval = SVERR_UNKNOWN_PARAMETERS;

  }else newsource = source;

 if(retval) return(retval);

 *dest = SVSUP_AllocMemEntry(SVOperatorHandle->ah_ramhandle, sizeof(struct SV_GfxBuffer), MEMF_CLEAR|MEMF_PUBLIC);
 if(*dest)
  {
   ULONG nd;

   CopyMem(newsource, *dest, sizeof(struct SV_GfxBuffer));

   destdepth = source->svgfx_ColorDepth;

   if(source->svgfx_ColorDepth > (nd = SVLI_GetDestDepth()) ) destdepth = nd;

   if((*dest)->svgfx_Buffer = SVSUP_AllocMemEntry(SVOperatorHandle->ah_ramhandle, (*dest)->svgfx_BufferSize, MEMF_CLEAR|MEMF_PUBLIC))
    {
     CopyMem(newsource->svgfx_Buffer, (*dest)->svgfx_Buffer, (*dest)->svgfx_BufferSize);

     if(source->svgfx_ColorDepth == 24) SVLI_24ToGrayScales(source->svgfx_Buffer, (*dest)->svgfx_Buffer, (UBYTE *) (*dest)->svgfx_Colors, source->svgfx_Width, source->svgfx_Height, destdepth);
      else                              SVLI_256ToGrayScales(*dest, destdepth);

     (*dest)->svgfx_Version    = 1;

     (*dest)->svgfx_BufferSize = source->svgfx_Width * source->svgfx_Height;
     (*dest)->svgfx_ColorDepth = destdepth;
     (*dest)->svgfx_PixelBits  = 8;

    }else
    {
     *dest = N;
     retval = SVERR_NO_MEMORY;
    }

  }else retval = SVERR_NO_MEMORY;

 return(retval);
}

ULONG __saveds __stdargs IsHamBuffer(struct SV_GfxBuffer *gfxb)
{
 ULONG isham = FALSE;

 if(gfxb->svgfx_Version > 1) if(gfxb->svgfx_NativeDIPF & DIPF_IS_HAM) isham = TRUE;
 if(!isham)                  if(gfxb->svgfx_ViewMode32 & HAM_KEY)     isham = TRUE;

 return(isham);
}

void __saveds __stdargs SVLI_256ToGrayScales(struct SV_GfxBuffer *gfxb, ULONG destdepth)
{
 ULONG i, colors, grey;

 if(destdepth == gfxb->svgfx_ColorDepth)
  {
   colors = ColorAcc(gfxb->svgfx_ColorDepth);

   for(i=0; i<colors; i++)
    {
     grey = (gfxb->svgfx_Colors[i][0] * 30 + gfxb->svgfx_Colors[i][1] * 59 + gfxb->svgfx_Colors[i][2] * 11) / 100;

     gfxb->svgfx_Colors[i][0] = (gfxb->svgfx_Colors[i][1] = (gfxb->svgfx_Colors[i][2] = (UBYTE) grey) );
    }
  }else
  {
   ULONG i, j, r, g, b, div, width, height;
   UBYTE *color, *dest;

   dest   = gfxb->svgfx_Buffer;
   width  = gfxb->svgfx_Width;
   height = gfxb->svgfx_Height;
   div    = 100 * ColorAcc(8 - destdepth);

   for(i=0; i<height; i++)
    {
     for(j=0; j<width; j++)
      {
       color = (UBYTE *) gfxb->svgfx_Colors + *dest * 3;

       r = *color++;
       g = *color++;
       b = *color++;

       *dest++ = (r*30 + g*59 + b*11) / div;
      }
    }

   colors = ColorAcc(destdepth);
   color  = (UBYTE *) gfxb->svgfx_Colors;

   for(i=0; i<256; i++) /* initialize them all, the space is there always */
    {
     *color++ = (UBYTE) i * (256 / colors);
     *color++ = (UBYTE) i * (256 / colors);
     *color++ = (UBYTE) i * (256 / colors);
    }

   *--color = 0xFF;
   *--color = 0xFF;
   *--color = 0xFF;
  }
}

void __saveds __stdargs SVLI_24ToGrayScales(UBYTE *source, UBYTE *dest, UBYTE *color, ULONG width, ULONG height, ULONG destdepth)
{
 ULONG i, j;

 if(destdepth == 8)
  {
   for(i=0; i<255; i++)
    {
     *color++ = i;
     *color++ = i;
     *color++ = i;
    }

   for(i=0; i<height; i++)
    {
     for(j=0; j<width; j++) *dest++ = ( (*source++ * 30) + (*source++ * 59) + (*source++ * 11) ) / 100;
    }
  }else
  {
   ULONG div, colors;

   colors = ColorAcc(destdepth);

   for(i=0; i<256; i++) /* initialize them all, the space is there always */
    {
     *color++ = (UBYTE) i * (256 / colors);
     *color++ = (UBYTE) i * (256 / colors);
     *color++ = (UBYTE) i * (256 / colors);
    }

   *--color = 0xFF;
   *--color = 0xFF;
   *--color = 0xFF;

   div = 100 * ColorAcc(8 - destdepth);

   for(i=0; i<height; i++)
    {
     for(j=0; j<width; j++) for(j=0; j<width; j++) *dest++ = ( (*source++ * 30) + (*source++ * 59) + (*source++ * 11) ) / div;
    }
  }
}


ULONG __saveds __stdargs SVLI_GetDestDepth(void)
{
 struct SV_ControlPad *pad;
 char *content; 
 ULONG destdepth = 8; /* default */

 if(SVSUP_LoadControlPad("ENV:superview-library/ExtractGrayScales.controlpad", &pad))
  {
   if(SVSUP_FindControlPad(pad, "COLORDEPTH", &content))
    {
     if(content) destdepth = atol(content);
    }

   SVSUP_FreeControlPad(pad);
  }

 if(destdepth < 1) destdepth = 1;
 if(destdepth > 8) destdepth = 8;

 return(destdepth);
}
