/*         ______   ___    ___
 *        /\  _  \ /\_ \  /\_ \
 *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
 *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
 *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
 *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
 *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
 *                                           /\____/
 *                                           \_/__/
 *
 *      Monochrome character drawing routines.
 *
 *      By Shawn Hargreaves.
 *
 *      See readme.txt for copyright information.
 */


#include "allegro.h"
#include "allegro/internal/aintern.h"



/* helper macro for drawing glyphs in each color depth */
#define DRAW_GLYPH(bits, size)                                               \
{                                                                            \
   AL_CONST unsigned char *data = glyph->dat;                                \
   unsigned long addr;                                                       \
   int w = glyph->w;                                                         \
   int h = glyph->h;                                                         \
   int stride = (w+7)/8;                                                     \
   int lgap = 0;                                                             \
   int d, i, j;                                                              \
									     \
   if (bmp->clip) {                                                          \
      /* clip the top */                                                     \
      if (y < bmp->ct) {                                                     \
	 d = bmp->ct - y;                                                    \
									     \
	 h -= d;                                                             \
	 if (h <= 0)                                                         \
	    return;                                                          \
									     \
	 data += d*stride;                                                   \
	 y = bmp->ct;                                                        \
      }                                                                      \
									     \
      /* clip the bottom */                                                  \
      if (y+h >= bmp->cb) {                                                  \
	 h = bmp->cb - y;                                                    \
	 if (h <= 0)                                                         \
	    return;                                                          \
      }                                                                      \
									     \
      /* clip the left */                                                    \
      if (x < bmp->cl) {                                                     \
	 d = bmp->cl - x;                                                    \
									     \
	 w -= d;                                                             \
	 if (w <= 0)                                                         \
	    return;                                                          \
									     \
	 data += d/8;                                                        \
	 lgap = d&7;                                                         \
	 x = bmp->cl;                                                        \
      }                                                                      \
									     \
      /* clip the right */                                                   \
      if (x+w >= bmp->cr) {                                                  \
	 w = bmp->cr - x;                                                    \
	 if (w <= 0)                                                         \
	    return;                                                          \
      }                                                                      \
   }                                                                         \
									     \
   stride -= (lgap+w+7)/8;                                                   \
									     \
   /* draw it */                                                             \
   bmp_select(bmp);                                                          \
									     \
   while (h--) {                                                             \
      addr = bmp_write_line(bmp, y++) + x*size;                              \
									     \
      j = 0;                                                                 \
      i = 0x80 >> lgap;                                                      \
      d = *(data++);                                                         \
									     \
      if (bg >= 0) {                                                         \
	 /* opaque mode drawing loop */                                      \
	 for (;;) {                                                          \
	    if (d & i)                                                       \
	       bmp_write##bits(addr, color);                                 \
	    else                                                             \
	       bmp_write##bits(addr, bg);                                    \
									     \
	    j++;                                                             \
	    if (j == w)                                                      \
	       break;                                                        \
									     \
	    i >>= 1;                                                         \
	    if (!i) {                                                        \
	       i = 0x80;                                                     \
	       d = *(data++);                                                \
	    }                                                                \
									     \
	    addr += size;                                                    \
	 }                                                                   \
      }                                                                      \
      else {                                                                 \
	 /* masked mode drawing loop */                                      \
	 for (;;) {                                                          \
	    if (d & i)                                                       \
	       bmp_write##bits(addr, color);                                 \
									     \
	    j++;                                                             \
	    if (j == w)                                                      \
	       break;                                                        \
									     \
	    i >>= 1;                                                         \
	    if (!i) {                                                        \
	       i = 0x80;                                                     \
	       d = *(data++);                                                \
	    }                                                                \
									     \
	    addr += size;                                                    \
	 }                                                                   \
      }                                                                      \
									     \
      data += stride;                                                        \
   }                                                                         \
									     \
   bmp_unwrite_line(bmp);                                                    \
}



#ifdef ALLEGRO_COLOR8

/* _linear_draw_glyph8:
 *  Draws a glyph onto an 8 bit bitmap.
 */
void _linear_draw_glyph8(BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)
{
   DRAW_GLYPH(8, 1);
}

#endif



#ifdef ALLEGRO_COLOR16

/* _linear_draw_glyph16:
 *  Draws a glyph onto a 16 bit bitmap.
 */
void _linear_draw_glyph16(BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)
{
   DRAW_GLYPH(16, sizeof(int16_t));
}

#endif



#ifdef ALLEGRO_COLOR24

/* _linear_draw_glyph24:
 *  Draws a glyph onto a 24 bit bitmap.
 */
void _linear_draw_glyph24(BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)
{
   DRAW_GLYPH(24, 3);
}

#endif



#ifdef ALLEGRO_COLOR32

/* _linear_draw_glyph32:
 *  Draws a glyph onto a 32 bit bitmap.
 */
void _linear_draw_glyph32(BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)
{
   DRAW_GLYPH(32, sizeof(int32_t));
}

#endif

