
 /* SV_BufferSubs.c
    - Functions for Buffering UtahRLE Files -
    (c) 1993-95 by Andreas R. Kleinert
    Last changes : 07.10.1995
 */


#include "svobject.h"

ULONG __saveds __asm SVO_ReadToGfxBuffer( register __a1 struct SVObjectHandle *SVObjectHandle_a1);
ULONG __saveds __asm SVO_GetGfxBuffer(    register __a1 struct SVObjectHandle *SVObjectHandle_a1,
                                          register __a2 struct SV_GfxBuffer **bufferhandle,
                                          register __a3 ULONG future);
ULONG __saveds __asm SVO_SetGfxBuffer(    register __a1 struct SVObjectHandle *SVObjectHandle_a1,
                                          register __a2 struct SV_GfxBuffer *bufferhandle,
                                          register __a3 ULONG future);


ULONG __saveds __stdargs SVLI_UnPackRLE(struct SVObjectHandle *SVObjectHandle, struct rle_hdr *RLEHeader, UBYTE *dptr, ULONG width, ULONG height);

ULONG __saveds __stdargs SVLI_BestModeID(ULONG pic_width, ULONG pic_height, ULONG pic_depth);

/* *************************************************** */
/* *						     * */
/* * ...                                             * */
/* *						     * */
/* *************************************************** */

ULONG __saveds __asm SVO_ReadToGfxBuffer( register __a1 struct SVObjectHandle *SVObjectHandle_a1)
{
 struct SVObjectHandle *SVObjectHandle = SVObjectHandle_a1;

 ULONG retval = SVERR_NO_ERROR, rleret = N;
 ULONG pic_width, pic_height, pic_depth;

 struct rle_hdr __aligned RLEHeader;


 if(!SVObjectHandle) return(SVERR_NO_HANDLE);


 if(!(SVObjectHandle->ah_filehandle_dest = Open(SVObjectHandle->ah_ReadName, MODE_OLDFILE))) return(SVERR_FILE_NOT_FOUND);
 if(!(SVObjectHandle->ah_FILE_dest       = fopen(SVObjectHandle->ah_ReadName, "r")))         return(SVERR_FILE_NOT_FOUND);


 RLEHeader.rle_file = SVObjectHandle->ah_FILE_dest;

 rleret = rle_get_setup(&RLEHeader);
 if(rleret != RLE_SUCCESS)
  {
   switch(rleret)
    {
     case RLE_NO_SPACE: return(SVERR_NO_MEMORY);          break;
     default:           return(SVERR_UNKNOWN_PARAMETERS); break;
    }
  }

 SVObjectHandle->ah_Type = SVObjectBase->svb_SVObject->svo_SubTypeCode[0];


 pic_width  = RLEHeader.xmax - RLEHeader.xmin + 1;
 pic_height = RLEHeader.ymax - RLEHeader.ymin + 1;
 pic_depth  = RLEHeader.ncolors << 3;

 RLEHeader.xmin = 0;          /* align pic_width */
 RLEHeader.xmax = pic_width - 1;


 if(RLEHeader.ncmap && (RLEHeader.ncmap!=3) ) return(SVERR_UNKNOWN_PARAMETERS);
 if(pic_depth != 24)                              return(SVERR_UNKNOWN_PARAMETERS);

 RLE_CLR_BIT(RLEHeader, RLE_ALPHA); /* don't want Alpha Channel */


 SVObjectHandle->ah_SV_GfxBuffer = AllocVec(sizeof(struct SV_GfxBuffer), (MEMF_CLEAR|MEMF_PUBLIC));
 if(!SVObjectHandle->ah_SV_GfxBuffer) return(SVERR_NO_MEMORY);

 SVObjectHandle->ah_SV_GfxBuffer->svgfx_Version = SVGFX_VERSION;

 SVObjectHandle->ah_SV_GfxBuffer->svgfx_BufferType   = SVGFX_BUFFERTYPE_ONEPLANE;
 SVObjectHandle->ah_SV_GfxBuffer->svgfx_Width        = pic_width;
 SVObjectHandle->ah_SV_GfxBuffer->svgfx_Height       = pic_height;
 SVObjectHandle->ah_SV_GfxBuffer->svgfx_ColorDepth   = 24;
 SVObjectHandle->ah_SV_GfxBuffer->svgfx_PixelBits    = 24;

 SVObjectHandle->ah_SV_GfxBuffer->svgfx_BufferSize   = pic_width * pic_height * 3;

 SVObjectHandle->ah_SV_GfxBuffer->svgfx_Buffer = AllocVec(SVObjectHandle->ah_SV_GfxBuffer->svgfx_BufferSize, (MEMF_CLEAR|MEMF_PUBLIC));
 if(!SVObjectHandle->ah_SV_GfxBuffer->svgfx_Buffer) return(SVERR_NO_MEMORY);

 SVObjectHandle->ah_SV_GfxBuffer->svgfx_ViewMode32 = SVLI_BestModeID(pic_width, pic_height, 24);

 retval = SVLI_UnPackRLE(SVObjectHandle, &RLEHeader, SVObjectHandle->ah_SV_GfxBuffer->svgfx_Buffer, pic_width, pic_height);


 /* Close files immediately after usage */

 if(SVObjectHandle->ah_filehandle_source) Close(SVObjectHandle->ah_filehandle_source);
 if(SVObjectHandle->ah_filehandle_dest)   Close(SVObjectHandle->ah_filehandle_dest);

 if(SVObjectHandle->ah_FILE_source) fclose(SVObjectHandle->ah_FILE_source);
 if(SVObjectHandle->ah_FILE_dest)   fclose(SVObjectHandle->ah_FILE_dest);

 SVObjectHandle->ah_filehandle_source = N;
 SVObjectHandle->ah_filehandle_dest   = N;

 SVObjectHandle->ah_FILE_source       = N;
 SVObjectHandle->ah_FILE_dest         = N;


 return(retval);
}

ULONG __saveds __asm SVO_GetGfxBuffer(    register __a1 struct SVObjectHandle *SVObjectHandle_a1,
                                          register __a2 struct SV_GfxBuffer **bufferhandle,
                                          register __a3 ULONG future)
{
 struct SVObjectHandle *SVObjectHandle = SVObjectHandle_a1;
 ULONG retval = SVERR_NO_ERROR;

 if(!SVObjectHandle) return(SVERR_NO_HANDLE);

 if(!bufferhandle) return(SVERR_ILLEGAL_ACCESS);

 *bufferhandle = SVObjectHandle->ah_SV_GfxBuffer;

 return(retval);
}

ULONG __saveds __asm SVO_SetGfxBuffer(    register __a1 struct SVObjectHandle *SVObjectHandle_a1,
                                          register __a2 struct SV_GfxBuffer *bufferhandle,
                                          register __a3 ULONG future)
{
 struct SVObjectHandle *SVObjectHandle = SVObjectHandle_a1;
 ULONG retval = SVERR_NO_ERROR;

 if(!SVObjectHandle) return(SVERR_NO_HANDLE);

 if(!bufferhandle) return(SVERR_ILLEGAL_ACCESS);

 SVObjectHandle->ah_SV_GfxBuffer2 = bufferhandle;

 return(retval);
}

ULONG __saveds __stdargs SVLI_UnPackRLE(struct SVObjectHandle *SVObjectHandle, struct rle_hdr *RLEHeader, UBYTE *dptr, ULONG width, ULONG height)
{
 ULONG j, w3, w3_2, hmax;
 UBYTE *start, *r_row, *g_row, *b_row, *row_vec[3];

 w3   = width * 3;
 w3_2 = w3 << 1;

 start = AllocVec(w3, MEMF_CLEAR|MEMF_PUBLIC);
 if(!start) return(SVERR_NO_MEMORY);

 row_vec[2] = (row_vec[1] = (row_vec[0] = start) + width) + width;

 dptr += (w3 * (hmax = height));
 dptr -= w3;

 while(height--)
  {
   if(SVObjectHandle->ah_ProgressFunc)
    {
     if(height & 7)
      {
       SVObjectHandle->ah_SVProgress.svpr_Percent = (hmax-height)*100/hmax;
       SVLI_Progress(SVObjectHandle, &SVObjectHandle->ah_SVProgress, SVObjectHandle->ah_ProgressData, SVObjectHandle->ah_ProgressFuture);
      }
    }

   r_row = row_vec[0];
   g_row = row_vec[1];
   b_row = row_vec[2];

   rle_getrow(RLEHeader, &row_vec[0]);

   for(j=0; j<width; j++)
    {
     *dptr++ = *r_row++;
     *dptr++ = *g_row++;
     *dptr++ = *b_row++;
    }

   dptr -= w3_2;
  }

 FreeVec(start);

 return(SVERR_NO_ERROR);
}

ULONG __saveds __stdargs SVLI_BestModeID(ULONG pic_width, ULONG pic_height, ULONG pic_depth)
{
 ULONG getdepth, mode_id;
                   getdepth = pic_depth;
 if(pic_depth > 8) getdepth = 8;

                           mode_id = SVSUP_GetBestModeID(pic_width, pic_height, getdepth);
 if(mode_id == INVALID_ID) mode_id = SVSUP_GetBestModeID(pic_width, pic_height, 4);
 if(mode_id == INVALID_ID) mode_id = N;

 return(mode_id);
}


ULONG __saveds __asm SVO_SetProgressFunc( register __a1 struct SVObjectHandle *SVObjectHandle_a1, register __a2 VOID (*progressfunc)(void), register __a3 APTR progressdata, register __d2 future)
{
 struct SVObjectHandle *SVObjectHandle = SVObjectHandle_a1;

 if(!SVObjectHandle) return(SVERR_NO_HANDLE);

 SVObjectHandle->ah_ProgressFunc   = progressfunc;
 SVObjectHandle->ah_ProgressData   = progressdata;
 SVObjectHandle->ah_ProgressFuture = future;

 return(SVERR_NO_ERROR);
}

void __saveds __asm SVLI_Progress(register __a1 struct SVObjectHandle *SVObjectHandle_a1, register __a2 struct SVProgress *pr, register __a3 APTR progressdata, register __d2 ULONG future)
{
 struct SVObjectHandle *SVObjectHandle = SVObjectHandle_a1;

 if(SVObjectHandle) if(SVObjectHandle->ah_ProgressFunc) (*SVObjectHandle->ah_ProgressFunc)();
}

ULONG __saveds __asm SVO_UnLinkGfxBuffer( register __a1 struct SVObjectHandle *SVObjectHandle_a1,
                                          register __a2 struct SV_GfxBuffer **bufferhandle,
                                          register __a3 ULONG future)
{
 struct SVObjectHandle *SVObjectHandle = SVObjectHandle_a1;
 ULONG retval = SVERR_NO_ERROR;

 if(!SVObjectHandle) return(SVERR_NO_HANDLE);

 if(!bufferhandle) return(SVERR_ILLEGAL_ACCESS);

 *bufferhandle = SVObjectHandle->ah_SV_GfxBuffer;
                 SVObjectHandle->ah_SV_GfxBuffer = N;

 return(retval);
}

ULONG __saveds __asm SVO_GetTypeExtension( register __a2 UBYTE *ext, register __a3 APTR future)
{
 if(!ext) return(SVERR_ILLEGAL_ACCESS);

 strcpy(ext, ".URLE");

 return(SVERR_NO_ERROR);
}
