/*
 * A Drawing Mode for ImageFX 1.5
 *
 */

#include <exec/types.h>
#include <scan/modall.h>

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

                                Library Vectors

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

struct Buffer *buf;
int last_y, brow;
UBYTE *red, *grn, *blu;

/*
 * Initialize before a series of PutColor or PutGrey's.  This is
 * guaranteed to be called before any PutColor or PutGrey's.
 *
 */
int __asm DM_PutInit (void)
{
   /*
    * This mode requires an undo buffer...
    *
    */
   buf = ObtainBuffer(3);
   if (buf == NULL) return(0);

   last_y = -1;
   brow = buf->BytesPerRow;

   return(1);
}

/*
 * Cleanup after a series of PutColor or PutGrey's.
 *
 */
void __asm DM_PutCleanup (void)
{
   ReleaseBuffer(buf);
}


short __inline do_sharp (UBYTE *pix, short x, short y)
{
   short val;
   short a1, a2, a3, a4;

   if (y > 0)
      a1 = pix[x-brow];
   else
      a1 = pix[x];

   if (y < buf->Height-1)
      a2 = pix[x+brow];
   else
      a2 = pix[x];

   if (x > 0)
      a3 = pix[x-1];
   else
      a3 = pix[x];

   if (x < buf->Width-1)
      a4 = pix[x+1];
   else
      a4 = pix[x];

   val = (pix[x] * 5) - a1 - a2 - a3 - a4;

   return(val);
}

/*
 * Write a color pixel.
 *
 */
void __asm DM_PutColor (register __a0 short *destr,
                        register __a1 short *destg,
                        register __a2 short *destb,
//                      register __d0 LONG oldr,
//                      register __d1 LONG oldg,
//                      register __d2 LONG oldb,
//                      register __d3 LONG newr,
//                      register __d4 LONG newg,
//                      register __d5 LONG newb,
                        register __d6 LONG x,
                        register __d7 LONG y)
{
   y -= buf->ViewTop;
   x -= buf->ViewLeft;

   if (y != last_y) {
      if (!GetBufLines (buf, &red, &grn, &blu, y - 1, 3)) {
         last_y = -1;
         return;
      }
      red += brow; grn += brow; blu += brow;
      last_y = y;
   }

   *destr = do_sharp(red, x, y);
   *destg = do_sharp(grn, x, y);
   *destb = do_sharp(blu, x, y);
}

/*
 * Write a greyscale pixel.
 *
 */
void __asm DM_PutGrey  (register __a0 short *destg,
                        register __d0 LONG oldg,
                        register __d1 LONG newg,
                        register __d6 LONG x,
                        register __d7 LONG y)
{
   y -= buf->ViewTop;
   x -= buf->ViewLeft;

   if (y != last_y) {
      if (!GetBufLines (buf, &red, &grn, &blu, y - 1, 3)) {
         last_y = -1;
         return;
      }
      red += brow; grn += brow; blu += brow;
      last_y = y;
   }

   *destg = do_sharp(red, x, y);
}

/*
 * Set state information for each point along a curve.  This is called
 * at every point along a user-drawn curve (freehand draw, airbrush, etc.)
 *
 * You cannot rely on this being called after DM_PutInit(), or
 * vice versa.
 *
 * x, y, and z will be -1 if the drawing tool in question is
 * not a curve (eg. a box or something).
 *
 */
void __asm DM_NewPoint (register __d0 int n,
                        register __d1 int total,
                        register __d2 int x,
                        register __d3 int y,
                        register __d4 int z)
{
}

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

                         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) DM_PutInit,
   (ULONG) DM_PutCleanup,
   (ULONG) DM_PutColor,
   (ULONG) DM_PutGrey,
   (ULONG) DM_NewPoint,

   /* 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: Sharpen Drawing Mode 1.04.17 (13.6.93)";
UBYTE LibraryType    = NT_DRAWMODE;

/*
 * 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);
}

