/****************************************************************************

gif_font.c - utility font handling and simple drawing for the GIF library

****************************************************************************/
// SPDX-License-Identifier: MIT
// SPDX-File-Copyright-Txt: (C) Eric S. Raymond <esr@thyrsus.com>

#include <limits.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#include "gif_lib.h"

/****************************************************************************
 Ascii 8 by 8 regular font - only first 128 characters are supported.
*****************************************************************************/

/*
 * Each array entry holds the bits for 8 horizontal scan lines, topmost
 * first.  The most significant bit of each constant is the leftmost bit of
 * the scan line.
 */
/*@+charint@*/
const unsigned char GifAsciiTable8x8[][GIF_FONT_WIDTH] = {
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* Ascii 0 */
    {0x3c, 0x42, 0xa5, 0x81, 0xbd, 0x42, 0x3c, 0x00}, /* Ascii 1 */
    {0x3c, 0x7e, 0xdb, 0xff, 0xc3, 0x7e, 0x3c, 0x00}, /* Ascii 2 */
    {0x00, 0xee, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00}, /* Ascii 3 */
    {0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00}, /* Ascii 4 */
    {0x00, 0x3c, 0x18, 0xff, 0xff, 0x08, 0x18, 0x00}, /* Ascii 5 */
    {0x10, 0x38, 0x7c, 0xfe, 0xfe, 0x10, 0x38, 0x00}, /* Ascii 6 */
    {0x00, 0x00, 0x18, 0x3c, 0x18, 0x00, 0x00, 0x00}, /* Ascii 7 */
    {0xff, 0xff, 0xe7, 0xc3, 0xe7, 0xff, 0xff, 0xff}, /* Ascii 8 */
    {0x00, 0x3c, 0x42, 0x81, 0x81, 0x42, 0x3c, 0x00}, /* Ascii 9 */
    {0xff, 0xc3, 0xbd, 0x7e, 0x7e, 0xbd, 0xc3, 0xff}, /* Ascii 10 */
    {0x1f, 0x07, 0x0d, 0x7c, 0xc6, 0xc6, 0x7c, 0x00}, /* Ascii 11 */
    {0x00, 0x7e, 0xc3, 0xc3, 0x7e, 0x18, 0x7e, 0x18}, /* Ascii 12 */
    {0x04, 0x06, 0x07, 0x04, 0x04, 0xfc, 0xf8, 0x00}, /* Ascii 13 */
    {0x0c, 0x0a, 0x0d, 0x0b, 0xf9, 0xf9, 0x1f, 0x1f}, /* Ascii 14 */
    {0x00, 0x92, 0x7c, 0x44, 0xc6, 0x7c, 0x92, 0x00}, /* Ascii 15 */
    {0x00, 0x00, 0x60, 0x78, 0x7e, 0x78, 0x60, 0x00}, /* Ascii 16 */
    {0x00, 0x00, 0x06, 0x1e, 0x7e, 0x1e, 0x06, 0x00}, /* Ascii 17 */
    {0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x18}, /* Ascii 18 */
    {0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00}, /* Ascii 19 */
    {0xff, 0xb6, 0x76, 0x36, 0x36, 0x36, 0x36, 0x00}, /* Ascii 20 */
    {0x7e, 0xc1, 0xdc, 0x22, 0x22, 0x1f, 0x83, 0x7e}, /* Ascii 21 */
    {0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00}, /* Ascii 22 */
    {0x18, 0x7e, 0x18, 0x18, 0x7e, 0x18, 0x00, 0xff}, /* Ascii 23 */
    {0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00}, /* Ascii 24 */
    {0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x00}, /* Ascii 25 */
    {0x00, 0x04, 0x06, 0xff, 0x06, 0x04, 0x00, 0x00}, /* Ascii 26 */
    {0x00, 0x20, 0x60, 0xff, 0x60, 0x20, 0x00, 0x00}, /* Ascii 27 */
    {0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0x00}, /* Ascii 28 */
    {0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00}, /* Ascii 29 */
    {0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x00, 0x00}, /* Ascii 30 */
    {0x00, 0x00, 0x00, 0xfe, 0x7c, 0x38, 0x10, 0x00}, /* Ascii 31 */
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* */
    {0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x30, 0x00}, /* ! */
    {0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* " */
    {0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00}, /* # */
    {0x10, 0x7c, 0xd2, 0x7c, 0x86, 0x7c, 0x10, 0x00}, /* $ */
    {0xf0, 0x96, 0xfc, 0x18, 0x3e, 0x72, 0xde, 0x00}, /* % */
    {0x30, 0x48, 0x30, 0x78, 0xce, 0xcc, 0x78, 0x00}, /* & */
    {0x0c, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ' */
    {0x10, 0x60, 0xc0, 0xc0, 0xc0, 0x60, 0x10, 0x00}, /* ( */
    {0x10, 0x0c, 0x06, 0x06, 0x06, 0x0c, 0x10, 0x00}, /* ) */
    {0x00, 0x54, 0x38, 0xfe, 0x38, 0x54, 0x00, 0x00}, /* * */
    {0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00}, /* + */
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x70}, /* , */
    {0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00}, /* - */
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00}, /* . */
    {0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x00}, /* / */
    {0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00}, /* 0 */
    {0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x3c, 0x00}, /* 1 */
    {0x7c, 0xc6, 0x06, 0x0c, 0x30, 0x60, 0xfe, 0x00}, /* 2 */
    {0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00}, /* 3 */
    {0x0e, 0x1e, 0x36, 0x66, 0xfe, 0x06, 0x06, 0x00}, /* 4 */
    {0xfe, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0xfc, 0x00}, /* 5 */
    {0x7c, 0xc6, 0xc0, 0xfc, 0xc6, 0xc6, 0x7c, 0x00}, /* 6 */
    {0xfe, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x60, 0x00}, /* 7 */
    {0x7c, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0x7c, 0x00}, /* 8 */
    {0x7c, 0xc6, 0xc6, 0x7e, 0x06, 0xc6, 0x7c, 0x00}, /* 9 */
    {0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00}, /* : */
    {0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x20, 0x00}, /* }, */
    {0x00, 0x1c, 0x30, 0x60, 0x30, 0x1c, 0x00, 0x00}, /* < */
    {0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00}, /* = */
    {0x00, 0x70, 0x18, 0x0c, 0x18, 0x70, 0x00, 0x00}, /* > */
    {0x7c, 0xc6, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00}, /* ? */
    {0x7c, 0x82, 0x9a, 0xaa, 0xaa, 0x9e, 0x7c, 0x00}, /* @ */
    {0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00}, /* A */
    {0xfc, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xfc, 0x00}, /* B */
    {0x7c, 0xc6, 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x00}, /* C */
    {0xf8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0xf8, 0x00}, /* D */
    {0xfe, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xfe, 0x00}, /* E */
    {0xfe, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0x00}, /* F */
    {0x7c, 0xc6, 0xc0, 0xce, 0xc6, 0xc6, 0x7e, 0x00}, /* G */
    {0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00}, /* H */
    {0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00}, /* I */
    {0x1e, 0x06, 0x06, 0x06, 0xc6, 0xc6, 0x7c, 0x00}, /* J */
    {0xc6, 0xcc, 0xd8, 0xf0, 0xd8, 0xcc, 0xc6, 0x00}, /* K */
    {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00}, /* L */
    {0xc6, 0xee, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0x00}, /* M */
    {0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00}, /* N */
    {0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00}, /* O */
    {0xfc, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0xc0, 0x00}, /* P */
    {0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x06}, /* Q */
    {0xfc, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xc6, 0x00}, /* R */
    {0x78, 0xcc, 0x60, 0x30, 0x18, 0xcc, 0x78, 0x00}, /* S */
    {0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00}, /* T */
    {0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00}, /* U */
    {0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00}, /* V */
    {0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00}, /* W */
    {0xc6, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0xc6, 0x00}, /* X */
    {0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x00}, /* Y */
    {0xfe, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xfe, 0x00}, /* Z */
    {0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00}, /* [ */
    {0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x00}, /* \ */
    {0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00}, /* ] */
    {0x00, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00}, /* ^ */
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}, /* _ */
    {0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ` */
    {0x00, 0x00, 0x7c, 0x06, 0x7e, 0xc6, 0x7e, 0x00}, /* a */
    {0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xe6, 0xdc, 0x00}, /* b */
    {0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0x7e, 0x00}, /* c */
    {0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xce, 0x76, 0x00}, /* d */
    {0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7e, 0x00}, /* e */
    {0x1e, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x30, 0x00}, /* f */
    {0x00, 0x00, 0x7e, 0xc6, 0xce, 0x76, 0x06, 0x7c}, /* g */
    {0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x00}, /* */
    {0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00}, /* i */
    {0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0xf0}, /* j */
    {0xc0, 0xc0, 0xcc, 0xd8, 0xf0, 0xd8, 0xcc, 0x00}, /* k */
    {0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00}, /* l */
    {0x00, 0x00, 0xcc, 0xfe, 0xd6, 0xc6, 0xc6, 0x00}, /* m */
    {0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x00}, /* n */
    {0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00}, /* o */
    {0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xe6, 0xdc, 0xc0}, /* p */
    {0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xce, 0x76, 0x06}, /* q */
    {0x00, 0x00, 0x6e, 0x70, 0x60, 0x60, 0x60, 0x00}, /* r */
    {0x00, 0x00, 0x7c, 0xc0, 0x7c, 0x06, 0xfc, 0x00}, /* s */
    {0x30, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x1c, 0x00}, /* t */
    {0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x00}, /* u */
    {0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00}, /* v */
    {0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xfe, 0x6c, 0x00}, /* w */
    {0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00}, /* x */
    {0x00, 0x00, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0x7c}, /* y */
    {0x00, 0x00, 0xfc, 0x18, 0x30, 0x60, 0xfc, 0x00}, /* z */
    {0x0e, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0e, 0x00}, /* { */
    {0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, /* | */
    {0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00}, /* } */
    {0x00, 0x00, 0x70, 0x9a, 0x0e, 0x00, 0x00, 0x00}, /* ~ */
    {0x00, 0x00, 0x18, 0x3c, 0x66, 0xff, 0x00, 0x00}  /* Ascii 127 */
};
/*@=charint@*/

static bool GifImageGetGeometry(const SavedImage *Image,
                                size_t *width,
                                size_t *height,
                                size_t *pixels)
{
    size_t w, h;

    if (Image == NULL || Image->RasterBits == NULL) {
        return false;
    }
    if (Image->ImageDesc.Width <= 0 || Image->ImageDesc.Height <= 0) {
        return false;
    }

    w = (size_t)Image->ImageDesc.Width;
    h = (size_t)Image->ImageDesc.Height;
    if (w > SIZE_MAX / h) {
        return false;
    }

    if (width != NULL) {
        *width = w;
    }
    if (height != NULL) {
        *height = h;
    }
    if (pixels != NULL) {
        *pixels = w * h;
    }
    return true;
}

static void GifPutPixelClipped(SavedImage *Image, int x, int y, GifPixelType color)
{
    size_t width, height;

    if (!GifImageGetGeometry(Image, &width, &height, NULL)) {
        return;
    }
    if (x < 0 || y < 0) {
        return;
    }
    if ((size_t)x >= width || (size_t)y >= height) {
        return;
    }

    Image->RasterBits[(size_t)y * width + (size_t)x] = color;
}

void GifDrawText8x8(SavedImage *Image, const int x, const int y,
                    const char *legend, const int color)
{
    int i;
    const unsigned char *cp;

    if (legend == NULL) {
        return;
    }

    for (i = 0; i < GIF_FONT_HEIGHT; i++) {
        int row_y = y + i;

        if (row_y < 0 || row_y > INT_MAX) {
            continue;
        }

        for (cp = (const unsigned char *)legend; *cp != '\0'; cp++) {
            size_t char_index = (size_t)(cp - (const unsigned char *)legend);
            size_t j;
            int glyph_x;
            unsigned int glyph;

            if (*cp >= 128) {
                continue;
            }
            if (char_index > (size_t)(INT_MAX / GIF_FONT_WIDTH)) {
                break;
            }

            glyph_x = x + (int)(char_index * GIF_FONT_WIDTH);
            glyph = GifAsciiTable8x8[*cp][i];
            for (j = 0; j < GIF_FONT_WIDTH; j++) {
                if ((glyph & (1U << (GIF_FONT_WIDTH - 1 - j))) != 0U) {
                    if (glyph_x <= INT_MAX - (int)j) {
                        GifPutPixelClipped(Image, glyph_x + (int)j, row_y,
                                           (GifPixelType)color);
                    }
                }
            }
        }
    }
}

void GifDrawBox(SavedImage *Image, const int x, const int y, const int w,
                const int d, const int color)
{
    int j;

    if (w < 0 || d < 0) {
        return;
    }

    for (j = 0; j <= w; j++) {
        if (x <= INT_MAX - j) {
            GifPutPixelClipped(Image, x + j, y, (GifPixelType)color);
            if (y <= INT_MAX - d) {
                GifPutPixelClipped(Image, x + j, y + d,
                                   (GifPixelType)color);
            }
        }
    }

    for (j = 0; j <= d; j++) {
        if (y <= INT_MAX - j) {
            GifPutPixelClipped(Image, x, y + j, (GifPixelType)color);
            if (x <= INT_MAX - w) {
                GifPutPixelClipped(Image, x + w, y + j,
                                   (GifPixelType)color);
            }
        }
    }
}

void GifDrawRectangle(SavedImage *Image, const int x, const int y, const int w,
                      const int d, const int color)
{
    size_t width, height;
    size_t row;
    size_t x0, y0, x1, y1;

    if (!GifImageGetGeometry(Image, &width, &height, NULL)) {
        return;
    }
    if (w <= 0 || d <= 0) {
        return;
    }

    x0 = (x <= 0) ? 0U : (size_t)x;
    y0 = (y <= 0) ? 0U : (size_t)y;

    if (x >= 0 && (size_t)x < width) {
        size_t rw = (size_t)w;
        x1 = rw > width - (size_t)x ? width : (size_t)x + rw;
    } else if (x < 0) {
        size_t rw = (size_t)w;
        size_t start = (size_t)(-x);
        if (rw <= start) {
            return;
        }
        x1 = rw - start;
        if (x1 > width) {
            x1 = width;
        }
    } else {
        return;
    }

    if (y >= 0 && (size_t)y < height) {
        size_t rh = (size_t)d;
        y1 = rh > height - (size_t)y ? height : (size_t)y + rh;
    } else if (y < 0) {
        size_t rh = (size_t)d;
        size_t start = (size_t)(-y);
        if (rh <= start) {
            return;
        }
        y1 = rh - start;
        if (y1 > height) {
            y1 = height;
        }
    } else {
        return;
    }

    if (x0 >= x1 || y0 >= y1) {
        return;
    }

    for (row = y0; row < y1; row++) {
        memset(Image->RasterBits + row * width + x0, (GifPixelType)color,
               x1 - x0);
    }
}

void GifDrawBoxedText8x8(SavedImage *Image, const int x, const int y,
                         const char *legend, const int border, const int bg,
                         const int fg)
{
    size_t j = 0, LineCount = 0, TextWidth = 0;
    const char *cp;
    char *dup;
    size_t legend_len;

    if (legend == NULL || border < 0) {
        return;
    }

    /* compute size of text to box */
    for (cp = legend; *cp != '\0'; cp++) {
        if (*cp == '\r' || *cp == '\n') {
            if (j > TextWidth) {
                TextWidth = j;
            }
            j = 0;
            LineCount++;
        } else if (*cp != '\t') {
            ++j;
        }
    }
    LineCount++;         /* count last line */
    if (j > TextWidth) { /* last line might be longer than any previous */
        TextWidth = j;
    }

    legend_len = strlen(legend);
    dup = malloc(legend_len + 1);
    /* FIXME: should return bad status, but that would require API change */
    if (dup != NULL) {
        size_t fill_w = 0, fill_h = 0, box_w = 0, box_h = 0;
        int i = 0;
        char *line, *next;

        if (TextWidth <= (SIZE_MAX - (size_t)(2 * border)) / GIF_FONT_WIDTH) {
            box_w = (size_t)(2 * border) + TextWidth * GIF_FONT_WIDTH;
            if (box_w > 0) {
                fill_w = box_w - 1;
            }
        }
        if (LineCount <= (SIZE_MAX - (size_t)(2 * border)) / GIF_FONT_HEIGHT) {
            box_h = (size_t)(2 * border) + LineCount * GIF_FONT_HEIGHT;
            if (box_h > 0) {
                fill_h = box_h - 1;
            }
        }

        if (fill_w > (size_t)INT_MAX) {
            fill_w = (size_t)INT_MAX;
        }
        if (fill_h > (size_t)INT_MAX) {
            fill_h = (size_t)INT_MAX;
        }
        if (box_w > (size_t)INT_MAX) {
            box_w = (size_t)INT_MAX;
        }
        if (box_h > (size_t)INT_MAX) {
            box_h = (size_t)INT_MAX;
        }

        /* fill the box */
        GifDrawRectangle(Image, x + 1, y + 1, (int)fill_w, (int)fill_h,
                         bg);
        memcpy(dup, legend, legend_len + 1);

        for (line = dup; line != NULL; line = next) {
            size_t leadspace = 0;
            char *eol = strpbrk(line, "\r\n");

            next = NULL;
            if (eol != NULL) {
                next = eol + 1;
                if ((*eol == '\r' && *next == '\n') ||
                    (*eol == '\n' && *next == '\r')) {
                    ++next;
                }
                *eol = '\0';
            }

            if (line[0] == '\t') {
                size_t linelen = strlen(line + 1);
                if (linelen < TextWidth) {
                    leadspace = (TextWidth - linelen) / 2;
                }
                ++line;
            }

            if ((size_t)i <= (size_t)(INT_MAX / GIF_FONT_HEIGHT)) {
                int text_x = x + border;
                int text_y = y + border + (GIF_FONT_HEIGHT * i++);

                if (leadspace <= (size_t)(INT_MAX / GIF_FONT_WIDTH) &&
                    text_x <= INT_MAX - (int)(leadspace * GIF_FONT_WIDTH)) {
                    text_x += (int)(leadspace * GIF_FONT_WIDTH);
                }
                GifDrawText8x8(Image, text_x, text_y, line, fg);
            }
        }
        free(dup);

        /* outline the box */
        GifDrawBox(Image, x, y, (int)box_w, (int)box_h, fg);
    }
}

/* end */
