From ea1947ffcc606d757357398b24e74a3f4ecefa07 Mon Sep 17 00:00:00 2001 From: neonloop Date: Wed, 20 Oct 2021 14:54:27 +0000 Subject: Initial commit from steward-fu release --- modules/mod_map/file_fnt.c | 601 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 601 insertions(+) create mode 100644 modules/mod_map/file_fnt.c (limited to 'modules/mod_map/file_fnt.c') diff --git a/modules/mod_map/file_fnt.c b/modules/mod_map/file_fnt.c new file mode 100644 index 0000000..6263404 --- /dev/null +++ b/modules/mod_map/file_fnt.c @@ -0,0 +1,601 @@ +/* + * Copyright � 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright � 2002-2006 Fenix Team (Fenix) + * Copyright � 1999-2002 Jos� Luis Cebri�n Pag�e (Fenix) + * + * This file is part of Bennu - Game Development + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ + +/* --------------------------------------------------------------------------- */ + +#include "libfont.h" +#include "mod_map.h" + +/* --------------------------------------------------------------------------- */ + +typedef struct _chardata +{ + int width; + int height; + int xadvance; + int yadvance; + int xoffset; + int yoffset; + int fileoffset ; +} +_chardata ; + +static int gr_font_loadfrom( file * fp ); + +/* --------------------------------------------------------------------------- */ +/* + * FUNCTION : gr_font_load + * + * Load a font from a given file, in FNT (DIV) format + * + * PARAMS : + * filename Name of the file + * + * RETURN VALUE : + * ID of the new font, or -1 if error + * + */ + +int gr_font_load( char * filename ) +{ + file * fp ; + int result; + + if ( !filename ) return -1; + + fp = file_open( filename, "rb" ) ; + if ( !fp ) return -1 ; + + result = gr_font_loadfrom( fp ); + + file_close( fp ); + + return result; +} + +/* --------------------------------------------------------------------------- */ + +static int gr_font_loadfrom( file * fp ) +{ + char header[8]; + int bpp; + int types, i, id; + uint32_t y; + FONT * f; + PALETTE * pal = NULL; + + struct + { + int width ; + int height ; + int yoffset ; + int fileoffset ; + } + oldchardata[256]; + + _chardata chardata[256] ; + + if ( font_count == MAX_FONTS ) return -1 ; + + /* Read the file header */ + + if ( file_read( fp, header, sizeof( header ) ) != sizeof( header ) ) return -1; + + if ( + memcmp( header, FNT_MAGIC, 7 ) != 0 && + memcmp( header, FNX_MAGIC, 7 ) != 0 ) + { + return -1; + } + + bpp = header[7]; + if ( bpp == 0 ) bpp = 8; + + /* Read or ignore the palette */ + + if ( bpp == 8 && !( pal = gr_read_pal_with_gamma( fp ) ) ) return -1 ; + + /* Read the character data (detect old format) */ + + if ( header[2] == 'x' ) + { + if ( !file_readSint32( fp, &types ) ) + { + pal_destroy( pal ); + return -1 ; + } + if ( file_read( fp, chardata, sizeof( chardata ) ) != sizeof( chardata ) ) + { + pal_destroy( pal ); + return -1 ; + } + for ( i = 0 ; i < 256 ; i++ ) + { + ARRANGE_DWORD( &chardata[i].width ); + ARRANGE_DWORD( &chardata[i].height ); + ARRANGE_DWORD( &chardata[i].xadvance ); + ARRANGE_DWORD( &chardata[i].yadvance ); + ARRANGE_DWORD( &chardata[i].xoffset ); + ARRANGE_DWORD( &chardata[i].yoffset ); + ARRANGE_DWORD( &chardata[i].fileoffset ); + } + } + else + { + if ( !file_readSint32( fp, &types ) ) + { + pal_destroy( pal ); + return -1 ; + } + if ( file_read( fp, oldchardata, sizeof( oldchardata ) ) != sizeof( oldchardata ) ) + { + pal_destroy( pal ); + return -1 ; + } + for ( i = 0 ; i < 256 ; i++ ) + { + ARRANGE_DWORD( &oldchardata[i].width ); + ARRANGE_DWORD( &oldchardata[i].height ); + ARRANGE_DWORD( &oldchardata[i].yoffset ); + ARRANGE_DWORD( &oldchardata[i].fileoffset ); + + chardata[i].width = oldchardata[i].width; + chardata[i].height = oldchardata[i].height; + chardata[i].xoffset = 0; + chardata[i].yoffset = oldchardata[i].yoffset; + chardata[i].xadvance = oldchardata[i].width; + chardata[i].yadvance = oldchardata[i].height + oldchardata[i].yoffset; + chardata[i].fileoffset = oldchardata[i].fileoffset; + } + } + + /* Create the font */ + + if ( header[2] == 'x' ) + id = gr_font_new( types, header[7] ) ; + else + id = gr_font_new( CHARSET_CP850, 8 ) ; + + if ( id == -1 ) + { + pal_destroy( pal ); + return -1 ; + } + + f = fonts[id]; + if ( !f ) + { + gr_font_destroy( id ); + pal_destroy( pal ); + return -1 ; + } + + /* Load the character bitmaps */ + + for ( i = 0 ; i < 256 ; i++ ) + { + GRAPH * gr; + uint8_t * ptr; + + f->glyph[i].xadvance = chardata[i].xadvance ; + f->glyph[i].yadvance = chardata[i].yadvance ; + + if ( chardata[i].fileoffset == 0 || chardata[i].width == 0 || chardata[i].height == 0 ) continue ; + + f->glyph[i].xoffset = chardata[i].xoffset ; + f->glyph[i].yoffset = chardata[i].yoffset ; + + file_seek( fp, chardata[i].fileoffset, SEEK_SET ) ; + f->glyph[i].bitmap = gr = bitmap_new( i, chardata[i].width, chardata[i].height, f->bpp ) ; + if ( !gr ) + { + gr_font_destroy( id ); + pal_destroy( pal ); + return -1 ; + } + bitmap_add_cpoint( gr, 0, 0 ) ; + gr->format->palette = pal; + pal_use( pal ); + + for ( y = 0, ptr = gr->data; y < gr->height; y++, ptr += gr->pitch ) + { + if ( file_read( fp, ptr, gr->widthb ) != gr->widthb ) break ; + + if ( gr->format->depth == 16 ) + { + ARRANGE_WORDS( ptr, ( int )gr->width ); + } + else if ( gr->format->depth == 32 ) + { + ARRANGE_DWORDS( ptr, ( int )gr->width ); + } + } + + f->glyph[i].yoffset = chardata[i].yoffset ; + } + if ( f->glyph[32].xadvance == 0 ) f->glyph[32].xadvance = f->glyph['j'].xadvance ; + + pal_destroy( pal ); // Elimino la instancia inicial + + return id ; +} + +/* --------------------------------------------------------------------------- */ +/* + * FUNCTION : gr_font_save + * + * Write a font to disk, in FNT/FNX format + * + * PARAMS : + * fontid ID of the font to save + * filename Name of the file to create + * + * RETURN VALUE : + * 1 if succeded or 0 otherwise + * + */ + +int gr_font_save( int fontid, const char * filename ) +{ + if ( !filename ) return 0; + + file * file; + int n; + uint32_t y; + long offset; + uint8_t * block = NULL ; + uint8_t * lineptr; + + FONT * font; + uint8_t header[8]; + _chardata chardata[256] ; + int palette_saved = 0; + + if ( fontid < 0 || fontid > MAX_FONTS || !fonts[fontid] ) return 0; + + font = fonts[fontid]; + + /* Open the file */ + + file = file_open( filename, "wb0" ); + if ( !file ) return 0; + + /* Write the header */ + + strcpy( ( char * ) header, FNX_MAGIC ); + header[7] = font->bpp; + file_write( file, &header, 8 ); + + /* Write the character information */ + + memset( chardata, 0, sizeof( chardata ) ); + offset = 8 + 4 + (( font->bpp == 8 ) ? 576 + 768 : 0 ) + sizeof( chardata ); + + for ( n = 0 ; n < 256 ; n++ ) + { + chardata[n].xadvance = font->glyph[n].xadvance; + chardata[n].yadvance = font->glyph[n].yadvance; + + if ( font->glyph[n].bitmap ) + { + /* Write the palette */ + if ( !palette_saved && font->bpp == 8 ) + { + uint8_t colors[256][3]; + uint8_t * block = calloc( 576, 1 ) ; + rgb_component * gpal = NULL; + int k; + + if ( font->glyph[n].bitmap->format->palette ) + gpal = font->glyph[n].bitmap->format->palette->rgb; + else if ( sys_pixel_format->palette ) + gpal = sys_pixel_format->palette->rgb; + else + gpal = ( rgb_component * ) default_palette; + + /* Generate palette info */ + for ( k = 0 ; k < 256 ; k++ ) + { + colors[k][0] = gpal[k].r >> 2 ; + colors[k][1] = gpal[k].g >> 2 ; + colors[k][2] = gpal[k].b >> 2 ; + } + + file_write( file, &colors, sizeof(colors) ) ; + file_write( file, block, 576 ) ; + free( block ) ; + palette_saved = 1; + } + + chardata[n].width = font->glyph[n].bitmap->width; + chardata[n].height = font->glyph[n].bitmap->height; + chardata[n].xadvance = font->glyph[n].xadvance; + chardata[n].yadvance = font->glyph[n].yadvance; + chardata[n].xoffset = font->glyph[n].xoffset; + chardata[n].yoffset = font->glyph[n].yoffset; + chardata[n].fileoffset = offset; + + offset += font->glyph[n].bitmap->widthb * chardata[n].height; + } + + ARRANGE_DWORD( &chardata[n].xadvance ); + ARRANGE_DWORD( &chardata[n].yadvance ); + ARRANGE_DWORD( &chardata[n].width ); + ARRANGE_DWORD( &chardata[n].width ); + ARRANGE_DWORD( &chardata[n].xoffset ); + ARRANGE_DWORD( &chardata[n].yoffset ); + ARRANGE_DWORD( &chardata[n].fileoffset ); + } + + file_writeSint32( file, &font->charset ); + + file_write( file, &chardata, sizeof( chardata ) ); + + /* Write the character bitmaps */ + + for ( n = 0 ; n < 256 ; n++ ) + { + if ( font->glyph[n].bitmap ) + { + GRAPH * gr = font->glyph[n].bitmap; + + if ( gr->format->depth != font->bpp ) + { + file_close( file ); + return 0; + } + + if ( gr->format->depth > 8 ) + { + if (( block = malloc( gr->widthb ) ) == NULL ) + { + file_close( file ); + return 0; + } + } + + lineptr = gr->data; + + for ( y = 0 ; y < gr->height ; y++, lineptr += gr->pitch ) + { + if ( gr->format->depth > 8 ) + { + memcpy( block, lineptr, gr->widthb ); + if ( gr->format->depth == 16 ) + { + ARRANGE_WORDS( block, ( int )gr->width ); +/* gr_convert16_ScreenTo565(( uint16_t * )block, gr->width ); */ + file_write( file, block, gr->widthb ); + } + else if ( gr->format->depth == 32 ) + { + file_writeUint32A( file, ( uint32_t * ) block, gr->width ); + } + } + else + { + file_write( file, lineptr, gr->widthb ); + } + } + + if ( gr->format->depth > 8 ) free( block ); + } + } + + file_close( file ); + + return 1; +} + +/* --------------------------------------------------------------------------- */ +/* + * FUNCTION : gr_load_bdf + * + * Load a BDF font from disk. This is a very simple loader that ignores + * anything that is not relevant to screen display or non-horizontal + * writing fonts. + * + * PARAMS : + * filename Name of the BDF file + * + * RETURN VALUE : + * ID of the font if succeded or -1 otherwise + * + */ + +int gr_load_bdf( const char * filename ) +{ + if ( !filename ) return -1; + + file * fp; + char line[2048]; + uint8_t * ptr, * optr; + FONT * font; + int id, x, y, i; + int error = 0; + + uint8_t nibbleh[256]; + uint8_t nibblel[256]; + + int default_xadvance = 0; + int default_yadvance = 0; + int in_char = 0; + int encoding = -1; + int width = 0; + int height = 0; + int xoffset = 0; + int yoffset = 0; + int xadvance = 0; + int yadvance = 0; + int minyoffset = 0; + int len; + + /* Arrays used to convert hex ASCII to binary */ + + memset( nibbleh, 0, sizeof( nibbleh ) ); + memset( nibblel, 0, sizeof( nibblel ) ); + + for ( i = '0' ; i <= '9' ; i++ ) + { + nibbleh[i] = (( i - '0' ) << 4 ); + nibblel[i] = i - '0'; + } + for ( i = 10 ; i <= 15 ; i++ ) + { + nibbleh['A' + i - 10] = ( i << 4 ); + nibbleh['a' + i - 10] = ( i << 4 ); + nibblel['A' + i - 10] = i; + nibblel['a' + i - 10] = i; + } + + /* Open the file and create the font */ + + fp = file_open( filename, "r" ); + if ( !fp ) return -1; + + id = gr_font_new( CHARSET_ISO8859, 1 ); + if ( id < 0 ) return -1; + font = fonts[id]; + font->maxwidth = 0; + font->maxheight = 0; + + /* Process the file, a line each time */ + + for ( line[2047] = 0 ; ; ) + { + if ( !( len = file_gets( fp, line, 2047 ) ) ) break; + if ( line[len-1] == '\n' ) line[len-1] = '\0'; + + /* Handle global-level commands */ + + if ( strncmp( line, "DWIDTH ", 7 ) == 0 && !in_char ) + { + default_xadvance = atoi( line + 7 ); + ptr = ( uint8_t * ) strchr( line + 7, ' ' ); + if ( ptr ) default_yadvance = atoi( ( char * ) ptr + 1 ); + } + else if ( strncmp( line, "STARTCHAR", 9 ) == 0 ) + { + in_char = 1; + encoding = -1; + height = 0; + xadvance = default_xadvance; + yadvance = default_yadvance; + } + else if ( strncmp( line, "ENDCHAR", 7 ) == 0 ) + { + in_char = 0; + } + + /* Handle character-level commands */ + + else if ( strncmp( line, "DWIDTH ", 7 ) == 0 && in_char ) + { + xadvance = atoi( line + 7 ); + ptr = ( uint8_t * ) strchr( line + 7, ' ' ); + if ( ptr ) yadvance = atoi( ( char * ) ptr + 1 ); + } + else if ( strncmp( line, "ENCODING ", 9 ) == 0 && in_char ) + { + encoding = atoi( line + 9 ); + if ( encoding == -1 ) + { + ptr = ( uint8_t * ) strchr( line + 7, ' ' ); + if ( ptr ) encoding = atoi( ( char * ) ptr + 1 ); + } + } + else if ( strncmp( line, "BBX ", 4 ) == 0 && in_char ) + { + width = atoi( ( char * ) line + 4 ); + if ( width & 7 ) width = ( width & ~7 ) + 8; + if (( ptr = ( uint8_t * ) strchr( ( char * ) line + 4, ' ' ) ) == NULL ) continue; + height = atoi( ( char * ) ptr + 1 ); + if (( ptr = ( uint8_t * ) strchr( ( char * ) ptr + 1, ' ' ) ) == NULL ) continue; + xoffset = atoi( ( char * ) ptr + 1 ); + if (( ptr = ( uint8_t * ) strchr( ( char * ) ptr + 1, ' ' ) ) == NULL ) continue; + yoffset = atoi( ( char * ) ptr + 1 ); + } + else if ( strncmp( line, "BITMAP", 6 ) == 0 ) + { + /* Read bitmap data */ + if ( encoding >= 0 && encoding < 256 && height > 0 ) + { + font->glyph[encoding].xadvance = xadvance; + font->glyph[encoding].yadvance = yadvance; + font->glyph[encoding].xoffset = xoffset; + font->glyph[encoding].yoffset = -yoffset - height; + + if ( minyoffset > -yoffset - height ) minyoffset = -yoffset - height; + + error = 1; + font->glyph[encoding].bitmap = bitmap_new( encoding, width, height, 1 ); + if ( font->glyph[encoding].bitmap == 0 ) break; + bitmap_add_cpoint( font->glyph[encoding].bitmap, 0, 0 ) ; + + if ( font->maxwidth < width ) font->maxwidth = width; + if ( font->maxheight < height ) font->maxheight = height; + + for ( y = 0 ; y < height ; y++ ) + { + if ( !( len = file_gets( fp, line, 2047 ) ) ) break; + if ( line[len-1] == '\n' ) line[len-1] = '\0'; + ptr = ( uint8_t * ) line; + optr = ( uint8_t * ) font->glyph[encoding].bitmap->data + font->glyph[encoding].bitmap->pitch * y; + + for ( x = 0 ; x < width ; x += 8 ) + { + if ( !ptr[0] || !ptr[1] ) break; + *optr++ = nibbleh[ptr[0]] | nibblel[ptr[1]]; + ptr += 2; + } + } + if ( y != height ) break; + error = 0; + } + } + } + + file_close( fp ); + + if ( error ) + { + gr_font_destroy( id ); + return -1; + } + + /* Adjust yoffsets to positive */ + + for ( i = 0 ; i < 256 ; i++ ) font->glyph[i].yoffset -= minyoffset; + + if ( font->glyph[32].xadvance == 0 ) font->glyph[32].xadvance = font->glyph['j'].xadvance; + +// fonts[font_count] = font ; + return id /* font_count++ */ ; +} + +/* --------------------------------------------------------------------------- */ -- cgit v1.2.3