view dmtext_bm.c @ 73:295d08376744

Add function for saving a bitmap font.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 01 Oct 2012 14:18:35 +0300
parents a791146e3094
children e6535609c161
line wrap: on
line source

/*
 * DMLib
 * -- Bitmap and TTF text & font support
 * Programmed and designed by Matti 'ccr' Hamalainen
 * (C) Copyright 2012 Tecnic Software productions (TNSP)
 */
#include "dmtext.h"
#include "dmresw.h"


void dmDrawBMTextConst(SDL_Surface *screen, DMBitmapFont *font, int mode, int xc, int yc, const char *fmt)
{
    const char *ptr = fmt;
    DMScaledBlitFunc blit = dmGetScaledBlitFunc(font->glyphs[0]->format, screen->format, mode);

    while (*ptr)
    {
        SDL_Surface *glyph;
        int pos;
        int ch = *ptr++;

        if (ch == 'ยง')
        {
            xc += 15;
            continue;
        }
        else
        if (ch >= 'A' && ch <= 'Z')
            pos = ch - 'A' + 256 + 1;
        else
        if (ch >= 'a' && ch <= 'z')
            pos = ch - 'a' + 1;
        else
        if (ch >= '0' && ch <= '9')
            pos = ch - '0' + 48;
        else
            pos = ch;
        
        if (pos >= 0 && pos < font->nglyphs)
        {
            glyph = font->glyphs[pos];
            blit(glyph, xc, yc, glyph->w, glyph->h, screen);
            xc += glyph->w;
        }
        else
            xc += font->width;
    }
}


void dmDrawBMTextVA(SDL_Surface *screen, DMBitmapFont *font, int mode, int xc, int yc, const char *fmt, va_list ap)
{
    char *tmp = dm_strdup_vprintf(fmt, ap);
    if (tmp != NULL)
    {
        dmDrawBMTextConst(screen, font, mode, xc, yc, tmp);
        dmFree(tmp);
    }
}


void dmDrawBMText(SDL_Surface *screen, DMBitmapFont *font, int mode, int xc, int yc, const char *fmt, ...)
{
    va_list ap;
    
    va_start(ap, fmt);
    dmDrawBMTextVA(screen, font, mode, xc, yc, fmt, ap);
    va_end(ap);
}


DMBitmapFont *dmNewBitmapFont(int nglyphs)
{
    DMBitmapFont *font = dmMalloc0(sizeof(DMBitmapFont));
    if (font == NULL)
        return NULL;
    
    font->nglyphs = nglyphs;
    font->glyphs = dmCalloc(nglyphs, sizeof(SDL_Surface *));
    
    return font;
}


int dmFreeBitmapFont(DMBitmapFont *font)
{
    int i;

    if (font == NULL)
        return DMERR_NULLPTR;
    
    for (i = 0; i < font->nglyphs; i++)
    {
        if (font->glyphs[i] != NULL)
        {
            SDL_FreeSurface(font->glyphs[i]);
            font->glyphs[i] = NULL;
        }
    }

    dmFree(font);
    return DMERR_OK;
}


int dmLoadBitmapFont(DMResource *res, DMBitmapFont **pfont)
{
    return DMERR_OK;
}


int dmCreateBitmapFontFromImage(SDL_Surface *image, int width, int height, DMBitmapFont **pfont)
{
    int glyph, xc, yc, xglyphs, yglyphs;
    DMBitmapFont *font;

    if (image->w < width || width < 4 || image->h < height || height < 4)
        return DMERR_INVALID_ARGS;
    
    xglyphs = image->w / width;
    yglyphs = image->h / height;
    
    if ((font = dmNewBitmapFont(xglyphs * yglyphs)) == NULL)
        return DMERR_MALLOC;

    font->width = width;
    font->height = height;

    fprintf(stderr, "%d x %d split as %d x %d blocks => %d x %d = %d glyphs\n",
        image->w, image->h,
        width, height,
        xglyphs, yglyphs, xglyphs * yglyphs);
    
    glyph = 0;
    for (yc = 0; yc < yglyphs; yc++)
    for (xc = 0; xc < xglyphs; xc++)
    {
        SDL_Surface *bmp = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height,
            image->format->BitsPerPixel,
            image->format->Rmask,
            image->format->Gmask,
            image->format->Bmask,
            image->format->Amask);
        
        if (bmp == NULL)
        {
            dmFreeBitmapFont(font);
            return DMERR_MALLOC;
        }

        SDL_Rect r;
        r.x = xc * width;
        r.y = yc * height;
        r.w = width;
        r.h = height;
        
        SDL_BlitSurface(image, &r, bmp, NULL);
        
        font->glyphs[glyph++] = bmp;
    }
    
    *pfont = font;
    return DMERR_OK;
}

int dmSaveBitmapFont(DMResource *res, DMBitmapFont *font)
{
    int i;

    dmf_write_str(res, (Uint8 *) "DMFONT", 6);
    dmf_write_le16(res, 0x0100);
    dmf_write_le32(res, font->width);
    dmf_write_le32(res, font->height);
    dmf_write_le32(res, font->nglyphs);

    for (i = 0; i < font->nglyphs; i++)
    {
        SDL_Surface *glyph = font->glyphs[i];
        dmf_write_le32(res, glyph->w);
        dmf_write_le32(res, glyph->h);
        dmf_write_le32(res, glyph->pitch);
        dmf_write_str(res, glyph->pixels, glyph->h * glyph->pitch);
    }
        
    return DMERR_OK;
}