aboutsummaryrefslogtreecommitdiff
path: root/modules/mod_map/file_fnt.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mod_map/file_fnt.c')
-rw-r--r--modules/mod_map/file_fnt.c601
1 files changed, 601 insertions, 0 deletions
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++ */ ;
+}
+
+/* --------------------------------------------------------------------------- */