/*
 * Rub-Through Drawing Style
 *
 * Brings swap buffer pixels into the main buffer.
 *
 */

#include <exec/types.h>
#include <scan/modall.h>
#include <scan/drawinfo.h>
#include <string.h>
#include "common.h"


/**********************************************************************\

                                Library Vectors

\**********************************************************************/

/*
 * XDM_Attr:
 *
 * Return to ImageFX some information about the Drawing Style (eg.
 * whether Options are needed, whether we work on greyscale or
 * color, etc.).  Called when ImageFX first scans the drawing
 * style directory.
 *
 */
ULONG __saveds __asm XDS_Attr (register __a0 struct XDrawAttr *attr)
{
   attr->Flags    = 0;
   attr->Priority = 126;
   return(0);
}

/*
 * XDS_Begin:
 *
 * Prepare before a pixel affecting operation.
 *
 */
int __saveds __asm XDS_Begin (register __a0 struct IDrawInfo *di)
{
   return(1);
}

/*
 * XDS_End:
 *
 * Cleanup after a pixel affecting operation.
 *
 */
void __saveds __asm XDS_End (register __a0 struct IDrawInfo *di)
{
}

/*
 * XDS_Get:
 *
 *
 */
int __saveds __asm XDS_Get (register __a0 struct IDrawInfo *di)
{
   struct Buffer *buf = ScanBase->MainBuffer;
   struct Buffer *sbuf = ScanBase->SwapBuffer;
   UBYTE *sr, *sg, *sb;
   UBYTE *dr, *dg, *db;
   UBYTE *red, *grn, *blu;
   int i, j;
   int w, h;
   int x, y;
   int xo, xl;

   if (!buf) return(0);
   if (!sbuf) return(0);

   GetFromBuf(buf, di);

#ifdef USE_BUFFERS

   /*
    * Only copy if space has been allocated for us.  Some drawing
    * modes may not require this information, so the buffers may
    * not be allocated to save time & space.
    */

   if (di->BPen)
   {

      w = di->Width;
      h = di->Height;

      for (j = 0, y = di->TE; j < h; j++, y++)
      {

         GetBufLine(di->BPen, &dr, &dg, &db, j);

         if ((y >= 0) && (y < sbuf->Height))
         {
            if (GetBufLine(sbuf, &red, &grn, &blu, y))
            {
               sr = red + di->LE;
               sg = grn + di->LE;
               sb = blu + di->LE;
               for (x = di->LE, i = 0; i < w; i++, x++) {
                  if ((x < 0) || (x >= sbuf->Width)) {
                     dr[i] = dg[i] = db[i] = 0;
                  }
                  else {
                     dr[i] = sr[i];
                     dg[i] = sg[i];
                     db[i] = sb[i];
                  }
               }

            }
         }
         else
         {
            /* outside bounds of image is black */
            memset(dr, 0, w);
            memset(dg, 0, w);
            memset(db, 0, w);
         }

         PutBufLine(di->BPen);

      }

   }

#else

   /*
    * Only copy if space has been allocated for us.  Some drawing
    * modes may not require this information, so the buffers may
    * not be allocated to save time & space.
    */

   if (di->PenR && di->PenG && di->PenB)
   {

      w = di->Width;
      h = di->Height;

      dr = di->PenR;
      dg = di->PenG;
      db = di->PenB;

      for (j = 0, y = di->TE; j < h; j++, y++)
      {

         if ((y >= 0) && (y < sbuf->Height))
         {
            if (GetBufLine(sbuf, &red, &grn, &blu, y))
            {
               sr = red + di->LE;
               sg = grn + di->LE;
               sb = blu + di->LE;
               for (x = di->LE, i = 0; i < w; i++, x++) {
                  if ((x < 0) || (x >= sbuf->Width)) {
                     dr[i] = dg[i] = db[i] = 0;
                  }
                  else {
                     dr[i] = sr[i];
                     dg[i] = sg[i];
                     db[i] = sb[i];
                  }
               }

            }
         }
         else
         {
            /* outside bounds of image is black */
            memset(dr, 0, w);
            memset(dg, 0, w);
            memset(db, 0, w);
         }

         dr += di->Width;
         dg += di->Width;
         db += di->Width;

      }

   }

#endif

   return(1);
}

/*
 * XDS_Put:
 *
 *
 */
int __saveds __asm XDS_Put (register __a0 struct IDrawInfo *di)
{
   struct Buffer *buf = ScanBase->MainBuffer;

   if (!ScanBase->SwapBuffer) return(0);

   PutToBuf(buf, di);

   return(1);
}

/*
 * XDS_Options:
 *
 * Present a window to the user allowing him to adjust drawing style
 * options.  Arguments may optionally be passed from an Arexx command.
 *
 */
int __saveds __asm XDS_Options (register __a0 LONG *args)
{
   return(0);
}

/*
 * XDS_LoadPrefs:
 *
 * Set preferences according to information loaded from disk.
 *
 */
int __saveds __asm XDS_LoadPrefs (register __a0 void *prefs)
{
   return(1);
}

/*
 * XDS_SavePrefs:
 *
 * Request preferences settings that are about to be saved to disk.
 *
 */
int __saveds __asm XDS_SavePrefs (register __a0 void *prefs)
{
   return(1);
}


int __saveds __asm XDS_Init (void)
{
   return(1);
}

void __saveds __asm XDS_Cleanup (void)
{
}



/**********************************************************************\

                         Library Initialization Stuff

\**********************************************************************/

/*
 * This is the table of all the functions that can be called in this
 * module.  The first four (Open, Close, Expunge, and Null) are reserved
 * for system use and MUST be specified in the order shown.  The actual
 * functions are in the standard module startup code.
 */
ULONG FuncTable[] = {
   /* These four MUST be present in this order */
   (ULONG) LibOpen,
   (ULONG) LibClose,
   (ULONG) LibExpunge,
   (ULONG) LibNull,

   /* Specific to the module */
   (ULONG) XDS_Attr,
   (ULONG) XDS_Begin,
   (ULONG) XDS_End,
   (ULONG) XDS_Get,
   (ULONG) XDS_Put,
   (ULONG) XDS_Options,
   (ULONG) XDS_LoadPrefs,
   (ULONG) XDS_SavePrefs,
   (ULONG) 0,
   (ULONG) 0,
   (ULONG) XDS_Init,
   (ULONG) XDS_Cleanup,

   /* End with -1L */
   (ULONG) -1L
};

/*
 * These are used by the standard module startup code.
 * LibraryName is the name of the library, and LibraryID is a short
 * description of the library.  Both of these are largely irrelavent,
 * but they are included just for completeness.
 */
UBYTE LibraryID[]    = "$VER: Rub-Through Drawing Style 2.0.20 (15.2.95)";
UBYTE LibraryType    = NT_XDRAWSTYLE;

/*
 * This is called by the standard module startup code when Image Scan
 * first opens the module.  Here we should fill in the NumGads,
 * NewGad, Language, and LangCount fields of the provided ModuleBase
 * structure if necessary.
 */
long  __asm UserOpen (register __a6 struct ModuleBase *modbase)
{
   return(TRUE);
}

/*
 * This is called by the standard module startup code when Image Scan
 * closes the module.  It should cleanup anything allocated or obtained
 * in the UserOpen() function.
 */
long  __asm UserClose (register __a6 struct ModuleBase *modbase)
{
   return(TRUE);
}

