/* ppmdraw.h - header file for simple drawing routines in libppm
**
** Simple, yes, and also fairly slow if the truth be told; but also very
** flexible and powerful.
**
** The two basic concepts are the drawproc and clientdata.  All the drawing
** routines take a drawproc that does the actual drawing.  A drawproc draws
** a single point, and it looks like this:
*/
void
ppmd_point_drawproc(pixel**     const pixels, 
                    int         const cols, 
                    int         const rows, 
                    pixval      const maxval, 
                    int         const x, 
                    int         const y, 
                    const void* const clientdata );
/*
** So, you call a drawing routine, e.g. ppmd_line(), and pass it a drawproc;
** it calls the drawproc for each point it wants to draw.  Why so complicated?
** Because you can define your own drawprocs to do more interesting things than
** simply draw the point.  For example, you could make one that calls back into
** another drawing routine, say ppmd_circle() to draw a circle at each point
** of a line.
**
** Slow?  Well sure, we're talking results here, not realtime.  You can do
** tricks with this arrangement that you couldn't even think of before.
** Still, to speed things up for the 90% case you can use this:
*/
#define PPMD_NULLDRAWPROC NULL
/*
** Just like ppmd_point_drawproc() it simply draws the point, but it's done
** inline, and clipping is assumed to be handled at a higher level.
**
** Now, what about clientdata.  Well, it's an arbitrary pointer, and can
** mean something different to each different drawproc.  For the above two
** drawprocs, clientdata should be a pointer to a pixel holding the color
** to be drawn.  Other drawprocs can use it to point to something else,
** e.g. some structure to be modified, or they can ignore it.
*/


/* Outline drawing routines.  Lines, splines, circles, etc. */

int ppmd_setlinetype ARGS(( int type ));
#define PPMD_LINETYPE_NORMAL 0
#define PPMD_LINETYPE_NODIAGS 1
/* If you set NODIAGS, all pixels drawn by ppmd_line() will be 4-connected
** instead of 8-connected; in other words, no diagonals.  This is useful
** for some applications, for example when you draw many parallel lines
** and you want them to fit together without gaps.
*/

int ppmd_setlineclip ARGS(( int clip ));
#define ppmd_setlineclipping(x)     ppmd_setlineclip(x)
/* Normally, ppmd_line() clips to the edges of the pixmap.  You can use this
** routine to disable the clipping, for example if you are using a drawproc
** that wants to do its own clipping.
*/

void
ppmd_line(pixel**      const pixels, 
          int          const cols, 
          int          const rows, 
          pixval       const maxval, 
          int          const x0, 
          int          const y0, 
          int          const x1, 
          int          const y1, 
          void (*drawprocP)(pixel**, int, int, pixval, int, int, const void*),
          const void * const clientdata);
/* Draws a line from (x0, y0) to (x1, y1).
*/

void
ppmd_spline3(pixel** const pixels, 
             int     const cols, 
             int const rows, 
             pixval const maxval, 
             int const x0, 
             int const y0, 
             int const x1, 
             int const y1, 
             int const x2, 
             int const y2, 
             void (*drawprocP)(pixel**, int, int, pixval, 
                               int, int, const void*), 
             const void* const clientdata );
/* Draws a three-point spline from (x0, y0) to (x2, y2), with (x1, y1) as
** the control point.  All drawing is done via ppmd_line(), so the routines
** that control it control ppmd_spline3() as well.
*/

void
ppmd_polyspline(pixel** const pixels, 
                int const cols, 
                int const rows, 
                pixval const maxval, 
                int const x0, 
                int const y0, 
                int const nc, 
                int* const xc, 
                int* const yc, 
                int const x1, 
                int const y1, 
                void (*drawprocP)(pixel**, int, int, pixval, 
                                  int, int, const void*), 
                const void* const clientdata );
/* Draws a bunch of splines end to end.  (x0, y0) and (x1, y1) are the initial
** and final points, and the xc and yc are the intermediate control points.
** nc is the number of these control points.
*/

void
ppmd_circle(pixel** const pixels, 
            int const cols, 
            int const rows, 
            pixval const maxval, 
            int const cx, 
            int const cy, 
            int const radius, 
            void (*drawprocP)(pixel**, int, int, pixval, 
                              int, int, const void*), 
            const void* const clientdata);
/* Draws a circle centered at (cx, cy) with the specified radius.
*/


/* Simple filling routines.  Ok, so there's only one. */

void
ppmd_filledrectangle(pixel** const pixels, 
                     int const cols, 
                     int const rows, 
                     pixval const maxval, 
                     int const x, 
                     int const y, 
                     int const width, 
                     int const height, 
                     void (*drawprocP)(pixel**, int, int, pixval, 
                                       int, int, const void*),
                     const void* const clientdata );
/* Fills in the rectangle [x, y, width, height].
*/


/* Arbitrary filling routines.  With these you can fill any outline that
** you can draw with the outline routines.
*/

char* ppmd_fill_init ARGS(( void ));
/* Returns a blank fillhandle.
*/

void
ppmd_fill_drawproc(pixel** const pixels, 
                   int const cols, 
                   int const rows, 
                   pixval const maxval, 
                   int const x, 
                   int const y, 
                   const void* const clientdata);
/* Use this drawproc to trace the outline you want filled.  Be sure to use
** the fillhandle as the clientdata.
*/

void
ppmd_fill(pixel** const pixels, 
          int const cols, 
          int const rows, 
          pixval const maxval, 
          char* const fillhandle, 
          void (*drawprocP)(pixel**, int, int, pixval, 
                            int, int, const void*), 
          const void* const clientdata);
/* Once you've traced the outline, give the fillhandle to this routine to
** do the actual drawing.  As usual, it takes a drawproc and clientdata;
** you could define drawprocs to do stipple fills and such.
*/

/* Text drawing routines. */

void
ppmd_text(pixel**      const pixels, 
          int          const cols, 
          int          const rows, 
          pixval       const maxval, 
          int          const xpos, 
          int          const ypos, 
          int          const height, 
          int          const angle, 
          const char * const sArg, 
          void (*drawprocP)(pixel**, int, int, pixval, int, int, const void*), 
          const void*  const clientdata);
/* Draws the null-terminated string s left justified at the point
** (x, y).  The text will be height pixels high and will be aligned on a
** baseline inclined angle degrees with the X axis.  The supplied
** drawproc and clientdata are passed to ppmd_line() which performs the
** actual drawing.
*/

void
ppmd_text_box(int const height, 
              int const angle, 
              const char * const s, 
              int * const left, 
              int * const top, 
              int * const right, 
              int * const bottom);
/* Calculates the extents box for text drawn by ppm_text with the given
** string, size, and orientation.  Most extent box calculations should use
** an angle specification of zero to calculate the unrotated box enclosing
** the text.  If you need the extents of rotated text, however, you can
** call ppmd_text_box with a nonzero angle.
*/
