#ifndef UNSUPPORTED
static INLINE void
drawchar (struct image *img, int x, int y, int fgcolor, unsigned char letter)
{
    int fontwidth = (RWIDTH (letter) + 7) / 8;
    const unsigned char *bitmap = &DATA[letter * HEIGHT * fontwidth];
    cpixel_t *current;
    int yend = y + HEIGHT;
    if (y < 0)
        bitmap -= y, y = 0;
    if (yend > img->height)
        yend = img->height;
    for (; y < yend; y++) {
        int b = *(bitmap++);
        int i = (1 << (RWIDTH (letter) - 1));
        if (fontwidth == 2) {
            b <<= 8;
            b |= *bitmap++;
        }
        current = (cpixel_t *) img->currlines[y];
        p_inc (current, x);
        while (i) {
            if (i & b) {
                p_set (current, fgcolor);
            }
            i >>= 1;
            p_inc (current, 1);
        }
    }
}

static INLINE void
hline (struct image *img, int x, int y, int length, int fgcolor)
{
    cpixel_t *current = (cpixel_t *) img->currlines[y], *end = (cpixel_t *) img->currlines[y];
    p_inc (current, x);
    p_inc (end, x + length);
#ifdef bpp1
    memset (current, fgcolor, end - current + 1);
#else
    while (current <= end) {
        p_set (current, fgcolor);
        p_inc (current, 1);
    }
#endif
}

static INLINE void
vline (struct image *img, int x, int y, int length, int fgcolor)
{
    length += y;
    while (y <= length) {
        cpixel_t *current = (cpixel_t *) img->currlines[y];
        p_inc (current, x);
        p_set (current, fgcolor);
        y++;
    }
}

static INLINE void
rectangle (struct image *img, int x, int y, int width, int height, int fgcolor)
{
    height += y;
    while (y < height)
        hline (img, x, y, width - 1, fgcolor), y++;
}

static INLINE char *
savevline (struct image *img, int x, int y, int length)
{
    cpixel_t *saved = (cpixel_t *) malloc (length * bpp + bpp), *s = saved;
    length += y;
    while (y <= length) {
        cpixel_t *current = (cpixel_t *) img->currlines[y];
        p_copy (s, 0, current, x);
        p_inc (s, 1);
        y++;
    }
    return (char *) saved;
}

static INLINE void
restorevline (struct image *img, char *saved, int x, int y, int length)
{
    cpixel_t *s = (cpixel_t *) saved;
    length += y;
    while (y <= length) {
        cpixel_t *current = (cpixel_t *) img->currlines[y];
        p_copy (current, x, s, 0);
        p_inc (s, 1);
        y++;
    }
}

static INLINE char *
saveline (struct image *img, int x, int y, int x2, int y2)
{
    int dx = x2 - x;
    int dy = y2 - y;
    int ady = abs (dy);
    if (dx < ady) {
        cpixel_t *saved = (cpixel_t *) malloc ((ady + 1) * bpp * 2), *s = saved;
        int plus = (dx << 16) / ady;
        if (dy < 0) {
            int dy = (x << 16) /*| (65536 / 2) */ ;
            ady = y;
            while (ady >= y2) {
                cpixel_t *current = (cpixel_t *) img->currlines[ady];
                p_inc (current, (dy >> 16));
                p_copy (s, 0, current, 0);
                p_copy (s, 1, current, 1);
                p_inc (s, 2);
                dy += plus;
                ady--;
            }
        } else {
            int dy = (x << 16) /*| (65536 / 2) */ ;
            ady = y;
            while (ady <= y2) {
                cpixel_t *current = (cpixel_t *) img->currlines[ady];
                p_inc (current, (dy >> 16));
                p_copy (s, 0, current, 0);
                p_copy (s, 1, current, 1);
                p_inc (s, 2);
                dy += plus;
                ady++;
            }
        }
        return ((char *) saved);
    } else {
        cpixel_t *saved = (cpixel_t *) malloc ((dx + 1) * bpp * 2), *s = saved;
        int plus = (dy << 16) / dx;
        ady = x;
        dy = (y << 16);
        while (ady <= x2) {
            cpixel_t *current = (cpixel_t *) img->currlines[dy >> 16];
            p_copy (s, 0, current, ady);
            current = (cpixel_t *) img->currlines[(dy >> 16) + 1];
            p_copy (s, 1, current, ady);
            p_inc (s, 2);
            dy += plus;
            ady++;
        }
        return ((char *) saved);
    }
}

static INLINE void
restoreline (struct image *img, char *saved, int x, int y, int x2, int y2)
{
    int dx = x2 - x;
    int dy = y2 - y;
    int ady = abs (dy);
    if (dx < ady) {
        cpixel_t *s = (cpixel_t *) saved;
        int plus = (dx << 16) / ady;
        if (dy < 0) {
            int dy = (x << 16) /*| (65536 / 2) */ ;
            ady = y;
            while (ady >= y2) {
                cpixel_t *current = (cpixel_t *) img->currlines[ady];
                p_inc (current, (dy >> 16));
                p_copy (current, 0, s, 0);
                p_copy (current, 1, s, 1);
                p_inc (s, 2);
                dy += plus;
                ady--;
            }
        } else {
            int dy = (x << 16) /*| (65536 / 2) */ ;
            ady = y;
            while (ady <= y2) {
                cpixel_t *current = (cpixel_t *) img->currlines[ady];
                p_inc (current, (dy >> 16));
                p_copy (current, 0, s, 0);
                p_copy (current, 1, s, 1);
                p_inc (s, 2);
                dy += plus;
                ady++;
            }
        }
    } else {
        cpixel_t *s = (cpixel_t *) saved;
        int plus = (dy << 16) / dx;
        ady = x;
        dy = (y << 16);
        while (ady <= x2) {
            cpixel_t *current = (cpixel_t *) img->currlines[dy >> 16];
            p_copy (current, ady, s, 0);
            current = (cpixel_t *) img->currlines[(dy >> 16) + 1];
            p_copy (current, ady, s, 1);
            p_inc (s, 2);
            dy += plus;
            ady++;
        }
    }
}

#ifdef bpp1
#define myinterpol(a,b,n) intergray(a,b,n)
#else
#define myinterpol(a,b,n) interpol(a,b,n,rmask,gmask,bmask)
#endif
static INLINE void
line (struct image *img, int x, int y, int x2, int y2, int color)
{
    int dx = x2 - x;
    int dy = y2 - y;
    int ady = abs (dy);
#ifndef bpp1
    int rmask = img->palette->info.truec.rmask;
    int gmask = img->palette->info.truec.gmask;
    int bmask = img->palette->info.truec.bmask;
#endif
#ifdef bpp1
    if (img->palette->type &= (C256 | FIXEDCOLOR)) {
        if (dx < ady) {
            int plus = (dx << 16) / ady;
            if (dy < 0) {
                int dy = (x << 16) | (65536 / 2);
                ady = y;
                while (ady >= y2) {
                    cpixel_t *current = (cpixel_t *) img->currlines[ady];
                    p_inc (current, (dy >> 16));
                    p_set (current, color);
                    dy += plus;
                    ady--;
                }
            } else {
                int dy = (x << 16) | (65536 / 2);
                ady = y;
                while (ady <= y2) {
                    cpixel_t *current = (cpixel_t *) img->currlines[ady];
                    p_inc (current, (dy >> 16));
                    p_set (current, color);
                    dy += plus;
                    ady++;
                }
            }
        } else {
            int plus = (dy << 16) / dx;
            ady = x;
            dy = (y << 16) | (65536 / 2);
            while (ady <= x2) {
                cpixel_t *current = (cpixel_t *) img->currlines[dy >> 16];
                p_setp (current, ady, color);
                dy += plus;
                ady++;
            }
        }
        return;
    }
#endif

    if (dx < ady) {
        int plus = (dx << 16) / ady;
        if (dy < 0) {
            int dy = (x << 16);
            ady = y;
            while (ady >= y2) {
                cpixel_t *current = (cpixel_t *) img->currlines[ady];
                p_inc (current, (dy >> 16));
                p_set (current, myinterpol (p_get (current), color, ((dy & 65535) >> 8)));
                p_setp (current, 1, myinterpol (color, p_getp (current, 1), ((dy & 65535) >> 8)));
                dy += plus;
                ady--;
            }
        } else {
            int dy = (x << 16);
            ady = y;
            while (ady <= y2) {
                cpixel_t *current = (cpixel_t *) img->currlines[ady];
                p_inc (current, (dy >> 16));
                p_set (current, myinterpol (p_get (current), color, ((dy & 65535) >> 8)));
                p_setp (current, 1, myinterpol (color, p_getp (current, 1), ((dy & 65535) >> 8)));
                dy += plus;
                ady++;
            }
        }
    } else {
        int plus = (dy << 16) / dx;
        ady = x;
        dy = (y << 16);
        while (ady <= x2) {
            cpixel_t *current = (cpixel_t *) img->currlines[dy >> 16];
            p_setp (current, ady, myinterpol (p_getp (current, ady), color, ((dy & 65535) >> 8)));
            current = (cpixel_t *) img->currlines[(dy >> 16) + 1];
            p_setp (current, ady, myinterpol (color, p_getp (current, ady), ((dy & 65535) >> 8)));
            dy += plus;
            ady++;
        }
    }
}

#undef myinterpol
#endif

#undef drawchar
#undef hline
#undef vline
#undef rectangle
#undef line
#undef restoreline
#undef saveline
#undef savevline
#undef restorevline
