/* Copyright (C) 2004-2005 Michael Liebscher This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * font_manager.c: Font management. * */ #include "../wolfiphone.h" /* ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; ( = ) ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ / ] ^ - ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ */ #define MAX_FONTS 4 font_t *myfonts[ MAX_FONTS ]; PRIVATE W32 num_fonts = 0; typedef struct { char *start, *end; } string_seg_t; font_t *createFont( const char *filename ) { font_t *temp_font; char *datname; filehandle_t *fp; W32 size; W32 i; if( num_fonts == (MAX_FONTS - 1) ) { Com_Printf( "[createFont]: No more font slots open\n" ); return NULL; } temp_font = Z_Malloc( sizeof( font_t ) ); temp_font->texfont = TM_FindTexture( filename, TT_Pic ); if( NULL == temp_font->texfont ) { Com_Printf( "[createFont]: unable to open file (%s)\n", filename ); Z_Free( temp_font ); return NULL; } memset( temp_font->nCharWidth, 0, sizeof( temp_font->nCharWidth ) ); datname = MM_MALLOC( strlen( filename ) + 1 ); FS_StripExtension( (char *)filename, datname ); my_strlcat( datname, ".dat", strlen( filename ) + 1 ); fp = FS_OpenFile( datname, 0 ); if( NULL == fp ) { Com_Printf( "[createFont]: unable to open file (%s)\n", datname ); MM_FREE( datname ); Z_Free( temp_font ); return NULL; } size = FS_GetFileSize( fp ); // check header size if( size < 10 ) { Com_Printf( "[createFont]: File (%s) has incorrect file length\n", datname ); MM_FREE( datname ); Z_Free( temp_font ); FS_CloseFile( fp ); return NULL; } // Check sig of font dat file FS_ReadFile( &size, 1, 4, fp ); FS_ReadFile( &temp_font->nMaxWidth, 1, 1, fp ); FS_ReadFile( &temp_font->nMaxHeight, 1, 1, fp ); FS_ReadFile( &size, 1, 4, fp ); size = LittleLong( size ); if( size > 127 ) { Com_Printf( "[createFont]: File (%s) has incorrect Character Width array\n", datname ); MM_FREE( datname ); Z_Free( temp_font ); FS_CloseFile( fp ); return NULL; } FS_ReadFile( &temp_font->nCharWidth, 1, size, fp ); FS_CloseFile( fp ); temp_font->nSize = 2; temp_font->colour[ 3 ] = 255; temp_font->hFrac = (float)(temp_font->nMaxHeight / (float)temp_font->texfont->height); temp_font->wFrac = (float)(temp_font->nMaxWidth / (float)temp_font->texfont->width); for( i = 0 ; i < MAX_FONTS ; ++i ) { if( ! myfonts[ i ] ) { break; } } if( i == (MAX_FONTS - 1) ) { Com_Printf( "[createFont]: No more font slots open\n" ); MM_FREE( datname ); Z_Free( temp_font ); return NULL; } myfonts[ i ] = temp_font; MM_FREE( datname ); return temp_font; } void Font_Init( void ) { W32 i; for( i = 0 ; i < MAX_FONTS ; ++i ) { myfonts[ i ] = NULL; } (void)createFont( "iphone/font1.tga" ); // (void)createFont( "iphone/font2.tga" ); } void Font_Shutdown( void ) { } void Font_GetMsgDimensions( FONTSELECT fs, const char *string, int *w, int *h ) { int width = 0; int mx = 0; W16 scale; int height; if( ! myfonts[ fs ] ) { *w = *h = 0; return; } scale = myfonts[ fs ]->nMaxHeight * myfonts[ fs ]->nSize; height = scale; while( *string ) { if( *string == '\n' ) { if( mx > width ) { width = mx; } mx = 0; height += scale; ++string; continue; } mx += myfonts[ fs ]->nCharWidth[ (*string)-32 ] * myfonts[ fs ]->nSize; ++string; } if( mx > width ) { width = mx; } *w = width; *h = height; } void Font_SetSize( FONTSELECT fs, W16 size ) { if( myfonts[ fs ] ) { myfonts[ fs ]->nSize = size; } } W16 Font_GetSize( FONTSELECT fs ) { if( myfonts[ fs ] ) { return( myfonts[ fs ]->nMaxHeight * myfonts[ fs ]->nSize ); } return 0; } void Font_SetColour( FONTSELECT fs, colour3_t c ) { if( myfonts[ fs ] ) { myfonts[ fs ]->colour[ 0 ] = c[ 0 ]; myfonts[ fs ]->colour[ 1 ] = c[ 1 ]; myfonts[ fs ]->colour[ 2 ] = c[ 2 ]; } } extern void R_Draw_Character( int x, int y, int num, font_t *myfont ); void Font_put_line( FONTSELECT fs, int x, int y, const char *string ) { int mx = x; W16 scale; if( ! myfonts[ fs ] ) { return; } scale = myfonts[ fs ]->nSize; while( *string ) { if( *string == '\n' ) { mx = x; y += myfonts[ fs ]->nMaxHeight * scale; ++string; continue; } R_Draw_Character( mx, y, *string, myfonts[ fs ] ); mx += myfonts[ fs ]->nCharWidth[ (*string)-32 ] * scale; ++string; } } void Font_put_lineR2L( FONTSELECT fs, int x, int y, const char *string ) { int mx = x; unsigned int charindex; unsigned int i; if( ! myfonts[ fs ] ) { return; } for ( i = 0; i < strlen( string ); ++i ) { charindex = strlen( string ) - i - 1; mx -= myfonts[ fs ]->nCharWidth[ string[ charindex ]-32 ] * myfonts[ fs ]->nSize; R_Draw_Character( mx, y, string[ charindex ], myfonts[ fs ] ); } } W16 Font_put_character( FONTSELECT fs, int x, int y, W16 num ) { if( ! myfonts[ fs ] || num > 126 ) { return 0; } R_Draw_Character( x, y, num, myfonts[ fs ] ); return( myfonts[ fs ]->nCharWidth[ num - 32 ] * myfonts[ fs ]->nSize ); } void Font_put_line_size( FONTSELECT fs, int x, int y, const char *start, const char *end ) { int mx = x; W16 scale; if( ! myfonts[ fs ] ) { return; } scale = myfonts[ fs ]->nSize; while( start != end ) { R_Draw_Character( mx, y, *start, myfonts[ fs ] ); mx += myfonts[ fs ]->nCharWidth[ (*start)-32 ] * scale; ++start; } } W8 Font_get_line( FONTSELECT fs, int line_width, string_seg_t *sst ) { int x = 0, last_word_width = 0, last_word_spaces = 0; int in_a_word = 0; int t_words = 0; int t_spaces = 0; int chars_width = 0; W16 scale; const char *word_start = sst->start; if( ! myfonts[ fs ] ) { return false; } scale = myfonts[ fs ]->nSize; if( line_width < 0 ) { line_width = 1000000; } while( *sst->end != '\0' && *sst->end != '\n' ) { char c = *sst->end; int c_width = myfonts[ fs ]->nCharWidth[ c - 32 ] * scale; // FIX ME // we exceeded the space available for this line if( x + c_width > line_width ) { if( in_a_word ) { chars_width = last_word_width; sst->end = (char *)word_start; t_spaces = last_word_spaces; } return t_words ? true : false; } x += c_width; if( c != ' ' ) { if( ! in_a_word ) { last_word_width = chars_width; word_start = sst->end; } in_a_word = 1; chars_width += c_width; } else { if( in_a_word ) { in_a_word = 0; t_words++; last_word_spaces = t_spaces; } t_spaces++; } ++sst->end; } if( in_a_word ) { t_words++; } if( *sst->end != '\0' && *sst->end == '\n' ) { ++sst->end; } return t_words ? true : false; } void Font_put_paragraph( FONTSELECT fs, short x, short y, const char *string, int space_between_lines, int line_width_in_pixel ) { string_seg_t sst; sst.start = sst.end = (char *)string; if( ! myfonts[ fs ] ) { return; } while( Font_get_line( fs, line_width_in_pixel, &sst ) ) { Font_put_line_size( fs, x, y, sst.start, sst.end ); if( *sst.end != '\0' && *sst.end == ' ' ) { sst.start = sst.end; ++sst.start; sst.end = sst.start; } else if( *sst.end != '\0' && *sst.end == '\n' ) { while( *sst.end == '\n' ) { ++sst.end; y += Font_GetSize( fs ) + space_between_lines; } sst.start = sst.end; } else { sst.start = sst.end; } y += Font_GetSize( fs ) + space_between_lines; } }