2004-07-06 00:19:52 +04:00
/* ufont.c
* Licensed under the GNU General Public License ,
* http : //www.opensource.org/licenses/gpl-license
* Copyright 2000 James Bursa < bursa @ users . sourceforge . net >
* Copyright 2004 John Tytgat < John . Tytgat @ aaug . net >
*/
/** \file
* UFont - Unicode wrapper for non - Unicode aware FontManager
*
* This code allows non - Unicode aware FontManager to be used for
* displaying Unicode encoded text lines . It needs the ! UFont
* resource ( accessed via UFont $ Path ) .
*/
# include <assert.h>
# include <limits.h>
# include <wchar.h>
# include "oslib/osfile.h"
# include "ufont.h"
// #define DEBUG_UFONT
// #define DEBUG_ACTIVATE_SANITY_CHECK
2004-07-09 00:16:23 +04:00
// #define DEBUG_DUMP_INTERNALS
2004-07-06 00:19:52 +04:00
# ifdef DEBUG_UFONT
# define dbg_fprintf fprintf
# else
# define dbg_fprintf (1)?0:fprintf
# endif
# ifdef DEBUG_ACTIVATE_SANITY_CHECK
# define do_sanity_check sanity_check
# else
# define do_sanity_check (1)?0:sanity_check
# endif
# define MALLOC_CHUNK 256
typedef struct usage_chain_s usage_chain_t ;
typedef struct virtual_fh_s virtual_fh_t ;
/* Virtual font handle :
*/
struct virtual_fh_s
{
const char * fontNameP ; /* => malloc'ed block holding RISC OS font name */
int xsize , ysize ; /* font size */
int xres , yres ; /* requested or actual resolution */
unsigned int usage ; /* the higher, the more this font handle is used for setting its glyphs */
unsigned int refCount ; /* number of times this struct is refered from ufont_f element */
usage_chain_t * usageP ; /* Ptr to element usage chain; if non NULL, we have a RISC OS font handle allocated. When refCount is 0, this is not necessary NULL. */
} ;
# define kInitialFHArraySize 20
static virtual_fh_t * oVirtualFHArrayP ;
static size_t oCurVirtualFHArrayElems ;
static size_t oMaxVirtualFHArrayElems ;
/* Usage chain (one element per open RISC OS font handle) :
*/
struct usage_chain_s
{
usage_chain_t * nextP ;
usage_chain_t * prevP ;
size_t chainTimer ; /* When equal to oChainTimer, you can not throw this element out the chain. */
font_f ro_fhandle ; /* RISC OS font handle (garanteed non zero) */
virtual_fh_t * virFHP ;
} ;
typedef struct ufont_map_s ufont_map_t ;
struct ufont_map_s
{
byte fontnr [ 65536 ] ; /* Must be 1st (comes straight from 'Data' file). Each entry is an index in the virtual_font_index array. */
byte character [ 65536 ] ; /* Must be 2nd (comes straight from 'Data' file) */
const char * uFontNameP ; /* => malloc'ed block holding UFont name */
unsigned int refCount ;
ufont_map_t * nextP ;
} ;
static const ufont_map_t * oMapCollectionP ;
struct ufont_font
{
2004-07-09 00:16:23 +04:00
ufont_map_t * mapP ;
unsigned int virtual_handles_used ; /* Number of filled virtual_font_index[] elements */
2004-07-06 00:19:52 +04:00
size_t virtual_font_index [ 256 ] ; /* Index in the oVirtualFHArrayP */
} ;
/* Walking the chain starting with oUsageChain->nextP and continuing via
* - > nextP until reaching oUsageChain again , results in equal or
* decreasing - > virFHP - > usage values .
* Also walking the chain starting with oUsageChain - > prevP and continuing
* via - > prevP until reaching oUsageChain again , results in equal or
* increasing - > virFHP - > usage values .
*/
static usage_chain_t oUsageChain ;
static size_t oCurUsageChainElems ;
/* Maximum number of RISC OS handles open by UFont :
*/
# define kMaxUsageChainElems 80
static size_t oChainTimer ;
static os_error * create_map ( const char * fontNameP , const ufont_map_t * * mapPP ) ;
static os_error * delete_map ( ufont_map_t * mapP ) ;
static int eat_utf8 ( wchar_t * pwc , const byte * s , int n ) ;
static os_error * addref_virtual_fonthandle ( const char * fontNameP , int xsize , int ysize , int xres , int yres , int * xresOutP , int * yresOutP , size_t * offsetP ) ;
static os_error * deref_virtual_fonthandle ( size_t offset ) ;
static os_error * activate_virtual_fh ( virtual_fh_t * virFHP ) ;
static os_error * remove_usage_chain_elem ( usage_chain_t * usageElemP ) ;
static void repos_usage_chain_elem ( usage_chain_t * usageElemP ) ;
static const char * get_rofontname ( font_f rofhandle ) ;
2004-07-09 00:16:23 +04:00
# ifdef DEBUG_DUMP_INTERNALS
2004-07-06 00:19:52 +04:00
static void dump_internals ( void ) ;
2004-07-09 00:16:23 +04:00
# endif
2004-07-06 00:19:52 +04:00
static int sanity_check ( const char * testMsgP ) ;
/* UFont error messages :
*/
static os_error error_badparams = { error_BAD_PARAMETERS , " Bad parameters " } ;
static os_error error_exists = { error_FONT_NOT_FOUND , " UFont Fonts/Data file not found " } ;
static os_error error_memory = { error_FONT_NO_ROOM , " Insufficient memory for font " } ;
static os_error error_size = { error_FONT_BAD_FONT_FILE , " Wrong size of font file " } ;
static os_error error_fnt_corrupt = { 1 /** \todo */ , " UFont is corrupt " } ;
static os_error error_toomany_handles = { 2 /** \todo */ , " Too many UFont handles are needed to fulfill current request " } ;
static os_error error_noufont = { 3 /** \todo */ , " Unable to find UFont font " } ;
static os_error error_badrohandle = { 4 /** \todo */ , " Invalid internal RISC OS font handle " } ;
/*
* UFont_FindFont
*
* = > as Font_FindFont , but
* font_name does not support ' \ ' qualifiers
*
* < = as Font_FindFont , but
* handle is 32 - bit
* Results from xres_out and yres_out are questionable because we
* delay - loading the real font data .
*/
os_error *
xufont_find_font ( char const * fontNameP ,
int xsize ,
int ysize ,
int xres ,
int yres ,
ufont_f * font ,
int * xresOutP ,
int * yresOutP )
{
ufont_f fontP ;
const char * old_font ;
char * fonts_file ;
char file_name [ 256 ] ; // \todo: fixed size, i.e. not safe.
fileswitch_object_type objType ;
int size ;
os_error * errorP ;
if ( font = = NULL )
return & error_badparams ;
/* Be sure never to return garbage as result. */
* font = NULL ;
/* Allocate memory for UFont font set */
if ( ( fontP = ( ufont_f ) calloc ( 1 , sizeof ( struct ufont_font ) ) ) = = NULL )
return & error_memory ;
if ( ( errorP = create_map ( fontNameP , & fontP - > mapP ) ) ! = NULL )
{
( void ) xufont_lose_font ( fontP ) ;
return errorP ;
}
if ( fontP - > mapP = = NULL )
{
( void ) xufont_lose_font ( fontP ) ;
return & error_noufont ;
}
/* Find size of Fonts file :
*/
strcpy ( file_name , fontNameP ) ;
strcat ( file_name , " .Fonts " ) ;
if ( ( errorP = xosfile_read_stamped_path ( file_name , " UFont: " , & objType , NULL , NULL , & size , NULL , NULL ) ) ! = NULL )
{
( void ) xufont_lose_font ( fontP ) ;
return errorP ;
}
if ( objType ! = fileswitch_IS_FILE )
{
( void ) xufont_lose_font ( fontP ) ;
return & error_exists ;
}
if ( ( fonts_file = ( char * ) malloc ( size ) ) = = NULL )
{
( void ) xufont_lose_font ( fontP ) ;
return & error_memory ;
}
/* Load Fonts :
*/
if ( ( errorP = xosfile_load_stamped_path ( file_name , fonts_file , " UFont: " , NULL , NULL , NULL , NULL , NULL ) ) ! = NULL )
{
( void ) xufont_lose_font ( fontP ) ;
free ( ( void * ) fonts_file ) ;
return errorP ;
}
/* Open all fonts listed in Fonts :
*/
for ( old_font = fonts_file , fontP - > virtual_handles_used = 0 ;
old_font - fonts_file < size ;
old_font + = strlen ( old_font ) + 1 , + + fontP - > virtual_handles_used )
{
/* UFont can maximum have 256 real RISC OS fonts :
*/
if ( fontP - > virtual_handles_used < 256 )
{
dbg_fprintf ( stderr , " %i %s: " , fontP - > virtual_handles_used , old_font ) ;
errorP = addref_virtual_fonthandle ( old_font , xsize , ysize , xres , yres , xresOutP , yresOutP , & fontP - > virtual_font_index [ fontP - > virtual_handles_used ] ) ;
}
else
errorP = & error_fnt_corrupt ;
if ( errorP ! = NULL )
{
( void ) xufont_lose_font ( fontP ) ;
free ( ( void * ) fonts_file ) ;
return errorP ;
}
dbg_fprintf ( stderr , " %i \n " , fontP - > virtual_font_index [ fontP - > virtual_handles_used ] ) ;
}
/* free Fonts */
free ( ( void * ) fonts_file ) ; fonts_file = NULL ;
* font = fontP ;
if ( xresOutP ! = NULL )
* xresOutP = 96 ;
if ( yresOutP ! = NULL )
* yresOutP = 96 ;
return NULL ;
}
/*
* UFont_LoseFont
*
* = > font handle as returned by UFont_FindFont
* Even if there was an error returned , we tried to delete as much
* as possible . The ufont_f is definately not reusable afterwards .
*/
os_error *
xufont_lose_font ( ufont_f fontP )
{
2004-07-09 00:16:23 +04:00
unsigned int index ;
2004-07-06 00:19:52 +04:00
os_error * theErrorP ;
theErrorP = ( fontP - > mapP ! = NULL ) ? delete_map ( fontP - > mapP ) : NULL ;
/* Close all fonts used :
*/
for ( index = 0 ; index < fontP - > virtual_handles_used ; + + index )
{
os_error * errorP ;
dbg_fprintf ( stderr , " About to deref virtual font handle %d \n " , fontP - > virtual_font_index [ index ] ) ;
if ( ( errorP = deref_virtual_fonthandle ( fontP - > virtual_font_index [ index ] ) ) ! = NULL )
theErrorP = errorP ;
}
/* Free ufont structure :
*/
free ( ( void * ) fontP ) ;
return theErrorP ;
}
/*
* UFont_Paint
*
* = > font handle as returned by UFont_FindFont
* string is Unicode UTF - 8 encoded
* other parameters as Font_Paint
*/
os_error *
xufont_paint ( ufont_f fontP ,
unsigned char const * string ,
font_string_flags flags ,
int xpos ,
int ypos ,
font_paint_block const * block ,
os_trfm const * trfm ,
int length )
{
char * result ;
os_error * error ;
if ( ( flags & font_GIVEN_LENGTH ) = = 0 )
length = INT_MAX ;
dbg_fprintf ( stderr , " xufont_paint() : size %d, consider len %d \n " , strlen ( string ) , length ) ;
if ( ( error = xufont_convert ( fontP , string , length , & result , NULL ) ) ! = NULL )
return error ;
if ( result [ 0 ] = = ' \0 ' )
return NULL ;
assert ( result [ 0 ] = = font_COMMAND_FONT ) ;
error = xfont_paint ( result [ 1 ] , & result [ 2 ] ,
( flags & ( ~ font_GIVEN_LENGTH ) ) | font_GIVEN_FONT ,
xpos , ypos , block , trfm , 0 ) ;
return error ;
}
/*
* UFont_ScanString
*
* = > font handle as returned by UFont_FindFont
* string is Unicode UTF - 8 encoded
* split length is index in string , not pointer
* other parameters as Font_ScanString
*
* < = as Font_ScanString
*/
os_error *
xufont_scan_string ( ufont_f fontP ,
unsigned char const * string ,
font_string_flags flags ,
int x ,
int y ,
font_scan_block const * block ,
os_trfm const * trfm ,
int length ,
unsigned char const * * split_point ,
int * x_out ,
int * y_out ,
int * length_out )
{
char * result ;
char * split_point_i ;
unsigned int * table ;
os_error * error ;
if ( ( flags & font_GIVEN_LENGTH ) = = 0 )
length = INT_MAX ;
dbg_fprintf ( stderr , " xufont_scan_string() : size %d, consider len %d \n " , strlen ( string ) , length ) ;
if ( ( error = xufont_convert ( fontP , string , length , & result , & table ) ) ! = NULL )
return error ;
if ( result [ 0 ] = = ' \0 ' )
{
if ( split_point ! = NULL )
* split_point = string ;
if ( x_out ! = NULL )
* x_out = 0 ;
if ( y_out ! = NULL )
* y_out = 0 ;
if ( length_out ! = NULL )
* length_out = 0 ;
return NULL ;
}
assert ( result [ 0 ] = = font_COMMAND_FONT ) ;
error = xfont_scan_string ( result [ 1 ] , & result [ 2 ] ,
( flags & ( ~ font_GIVEN_LENGTH ) ) | font_GIVEN_FONT ,
x , y , block , trfm , 0 ,
( split_point ) ? & split_point_i : NULL ,
x_out , y_out , length_out ) ;
if ( error ! = NULL )
return error ;
if ( split_point ! = NULL )
{
dbg_fprintf ( stderr , " RISC OS scan string split at offset %d (char %d) \n " , split_point_i - result , * split_point_i ) ;
* split_point = & string [ table [ split_point_i - result ] ] ;
dbg_fprintf ( stderr , " UTF-8 Split offset at %d (char %d) \n " , * split_point - string , * * split_point ) ;
}
return NULL ;
}
/**
* Given a text line , return the number of bytes which can be set using
* one RISC OS font and the bounding box fitting that part of the text
* only .
*
* \ param font a ufont font handle , as returned by xufont_find_font ( ) .
* \ param string string text . Does not have to be NUL terminated .
* \ param flags FontManger flags to be used internally
* \ param length length in bytes of the text to consider .
* \ param width returned width of the text which can be set with one RISC OS font . If 0 , then error happened or initial text length was 0.
* \ param rofontname returned name of the RISC OS font which can be used to set the text . If NULL , then error happened or initial text length was 0.
* \ param rotext returned string containing the characters in returned RISC OS font . Not necessary NUL terminated . free ( ) after use . If NULL , then error happened or initial text length was 0.
* \ param rolength length of return rotext string . If 0 , then error happened or initial text length was 0.
* \ param consumed number of bytes of the given text which can be set with one RISC OS font . If 0 , then error happened or initial text length was 0.
*/
os_error * xufont_txtenum ( ufont_f fontP ,
unsigned char const * string ,
font_string_flags flags ,
size_t length ,
int * widthP ,
unsigned char const * * rofontnameP ,
unsigned char const * * rotextP ,
size_t * rolengthP ,
size_t * consumedP )
{
char * result , * end_result ;
unsigned int * table ;
os_error * errorP ;
int width ;
const char * rofontname ;
char * rotext ;
size_t rolength ;
* rotextP = * rofontnameP = NULL ;
* consumedP = * rolengthP = * widthP = 0 ;
if ( ( flags & font_GIVEN_LENGTH ) = = 0 )
length = INT_MAX ;
if ( length = = 0 )
return NULL ;
if ( ( errorP = xufont_convert ( fontP , string , length , & result , & table ) ) ! = NULL )
return errorP ;
if ( result [ 0 ] = = ' \0 ' )
return NULL ;
assert ( result [ 0 ] = = font_COMMAND_FONT ) ;
/* Find how many characters starting at <result + 2> onwards
are set using the RISC OS font with handle < result + 1 > */
for ( end_result = result + 2 ; * end_result ! = ' \0 ' & & * end_result ! = font_COMMAND_FONT ; + + end_result )
;
rolength = end_result - result - 2 ;
if ( ( errorP = xfont_scan_string ( result [ 1 ] , & result [ 2 ] ,
flags | font_GIVEN_LENGTH | font_GIVEN_FONT ,
0x7fffffff , 0x7fffffff ,
NULL , NULL ,
rolength ,
NULL ,
& width , NULL ,
NULL ) ) ! = NULL )
return errorP ;
if ( ( rofontname = get_rofontname ( result [ 1 ] ) ) = = NULL )
return & error_badrohandle ;
if ( ( rotext = malloc ( rolength ) ) = = NULL )
return & error_memory ;
memcpy ( rotext , result + 2 , rolength ) ;
* widthP = width ;
* rofontnameP = rofontname ;
* rotextP = rotext ;
* rolengthP = rolength ;
* consumedP = table [ end_result - result ] ;
return NULL ;
}
/*
* UFont_Convert
*
* = > initial font
* UTF - 8 string to convert to RISC OS font numbers and codes .
* max length to convert ( characters ) or NUL char terminated .
*
* < = string converted to Font_Paint format
* table of offsets in UTF - 8 string
*/
os_error *
xufont_convert ( ufont_f fontP ,
unsigned char const * string ,
size_t length ,
char * * presult , /* may not be NULL ! */
size_t * * ptable /* may be NULL */ )
{
static char * resultP ;
static size_t * tableP ;
static size_t currentSize ;
size_t max_length ;
size_t string_index , new_string_index , result_index ;
virtual_fh_t * curVirFH = NULL ;
assert ( presult ! = NULL ) ;
do_sanity_check ( " xufont_convert() : begin " ) ;
/* Find upfront if we're NUL char terminated or length terminated. */
for ( max_length = 0 ; max_length < length & & string [ max_length ] ! = ' \0 ' ; + + max_length )
/* no body */ ;
/* Increase timer so we can enforce a set of usage elements to remain active.
*/
+ + oChainTimer ;
/* Ensure memory block.
*/
if ( resultP = = NULL )
{
if ( ( resultP = ( char * ) malloc ( MALLOC_CHUNK ) ) = = NULL )
return & error_memory ;
currentSize = MALLOC_CHUNK ;
}
if ( tableP = = NULL & & ( tableP = ( size_t * ) malloc ( MALLOC_CHUNK * sizeof ( size_t ) ) ) = = NULL )
return & error_memory ;
dbg_fprintf ( stderr , " xufont_convert() : " ) ;
for ( string_index = 0 , result_index = 0 ;
string_index < max_length ;
string_index = new_string_index )
{
wchar_t wchar ;
int result = eat_utf8 ( & wchar , & string [ string_index ] , max_length - string_index ) ;
if ( result = = 0 )
{
/* Too few input bytes : abort conversion */
fprintf ( stderr , " eat_utf8() : too few input bytes \n " ) ;
break ;
}
else if ( result < 0 )
{
/* Corrupt UTF-8 stream : skip <-result> input characters. */
fprintf ( stderr , " eat_utf8() : error %d \n " , result ) ;
fprintf ( stderr , " String <%.*s> error pos %d \n " , length , string , string_index ) ;
wchar = ' ? ' ;
new_string_index = string_index - result ;
}
else
{
/* Normal case : one wchar_t produced, <result> bytes consumed. */
if ( wchar > = 0x10000 )
wchar = ' ? ' ;
new_string_index = string_index + result ;
}
dbg_fprintf ( stderr , " src offset 0x%x : 0x%x " , string_index , wchar ) ;
/* Reserve room for at least 32 more entries.
*/
if ( result_index + 32 > currentSize )
{
if ( ( resultP = realloc ( resultP , currentSize * 2 ) ) = = NULL
| | ( tableP = realloc ( tableP , currentSize * 2 * sizeof ( size_t ) ) ) = = NULL )
return & error_memory ;
currentSize * = 2 ;
}
{
const byte fontnr = fontP - > mapP - > fontnr [ wchar ] ;
virtual_fh_t * virFHP ;
usage_chain_t * usageP ;
assert ( fontnr < fontP - > virtual_handles_used ) ;
virFHP = & oVirtualFHArrayP [ fontP - > virtual_font_index [ fontnr ] ] ;
/* Check if current font is ok :
*/
if ( virFHP ! = curVirFH )
{
os_error * errorP ;
curVirFH = virFHP ;
/* Make sure we have a RISC OS font handle associated :
*/
if ( ( errorP = activate_virtual_fh ( virFHP ) ) ! = NULL )
return errorP ;
usageP = virFHP - > usageP ;
assert ( usageP ! = NULL ) ;
assert ( usageP - > ro_fhandle ! = 0 ) ;
tableP [ result_index ] = tableP [ result_index + 1 ] = string_index ;
resultP [ result_index + + ] = font_COMMAND_FONT ;
resultP [ result_index + + ] = usageP - > ro_fhandle ;
dbg_fprintf ( stderr , " {%i} " , resultP [ result_index - 1 ] ) ;
}
else
{
usageP = virFHP - > usageP ;
assert ( usageP ! = NULL ) ;
}
+ + virFHP - > usage ;
/* By increasing the usage counter, it might that the oUsageChain needs
* reordering .
*/
if ( usageP ! = oUsageChain . nextP & & virFHP - > usage > usageP - > prevP - > virFHP - > usage )
repos_usage_chain_elem ( usageP ) ;
tableP [ result_index ] = string_index ;
resultP [ result_index + + ] = fontP - > mapP - > character [ wchar ] ;
dbg_fprintf ( stderr , " [0x%x] " , resultP [ result_index - 1 ] ) ;
}
}
resultP [ result_index ] = 0 ;
* presult = resultP ;
tableP [ result_index ] = string_index ;
if ( ptable ! = NULL )
* ptable = tableP ;
# ifdef DEBUG_UFONT
fprintf ( stderr , " \n RISC OS font string result: \n " ) ;
for ( result_index = 0 ; resultP [ result_index ] ! = 0 ; + + result_index )
fprintf ( stderr , " Dst offset %d : 0x%x (src offset %d) \n " , result_index , resultP [ result_index ] , tableP [ result_index ] ) ;
# endif
do_sanity_check ( " xufont_convert() : end " ) ;
dbg_fprintf ( stderr , " --- After convert() \n " ) ;
//dump_internals();
return NULL ;
}
/* Creates or reuses an existing ufont_map_t
*/
static os_error * create_map ( const char * uFontNameP , const ufont_map_t * * mapPP )
{
ufont_map_t * curMapP ;
size_t uFontNameLen = strlen ( uFontNameP ) ;
char * fileNameP ;
os_error * errorP ;
/* Make sure we never return garbage results.
*/
* mapPP = NULL ;
if ( ( fileNameP = ( char * ) alloca ( uFontNameLen + sizeof ( " .Data " ) ) ) = = NULL )
return & error_memory ;
memcpy ( fileNameP , uFontNameP , uFontNameLen ) ;
do {
fileswitch_object_type objType ;
int size ;
memcpy ( & fileNameP [ uFontNameLen ] , " .Data " , sizeof ( " .Data " ) ) ;
if ( ( errorP = xosfile_read_stamped_path ( fileNameP , " UFont: " , & objType , NULL , NULL , & size , NULL , NULL ) ) ! = NULL )
return errorP ;
if ( objType = = fileswitch_NOT_FOUND )
{
/* Look for the Data file one directory level up. */
while ( uFontNameLen ! = 0 & & fileNameP [ - - uFontNameLen ] ! = ' . ' )
/* no body */ ;
if ( uFontNameLen = = 0 )
return & error_exists ;
}
else if ( objType = = fileswitch_IS_FILE )
{
if ( size ! = 2 * 65536 )
return & error_size ;
break ;
}
else
return & error_exists ;
} while ( 1 ) ;
/* Try to reuse an existing map :
*/
for ( curMapP = oMapCollectionP ; curMapP ! = NULL ; curMapP = curMapP - > nextP )
{
size_t curUFontNameLen = strlen ( curMapP - > uFontNameP ) ;
if ( uFontNameLen ! = curUFontNameLen )
continue ;
if ( memcmp ( fileNameP , curMapP - > uFontNameP , curUFontNameLen ) ! = 0 )
break ;
}
if ( curMapP ! = NULL )
{
+ + curMapP - > refCount ;
* mapPP = curMapP ;
return NULL ;
}
/* We need to create & load new map into memory :
*/
if ( ( curMapP = ( ufont_map_t * ) malloc ( sizeof ( ufont_map_t ) ) ) = = NULL )
return & error_memory ;
/* Load Data file :
*/
if ( ( errorP = xosfile_load_stamped_path ( fileNameP , ( byte * ) & curMapP - > fontnr [ 0 ] , " UFont: " , NULL , NULL , NULL , NULL , NULL ) ) ! = NULL )
{
free ( ( void * ) curMapP ) ;
return errorP ;
}
fileNameP [ uFontNameLen ] = ' \0 ' ;
if ( ( curMapP - > uFontNameP = strdup ( fileNameP ) ) = = NULL )
{
free ( ( void * ) curMapP ) ;
return & error_memory ;
}
curMapP - > refCount = 1 ;
curMapP - > nextP = oMapCollectionP ;
oMapCollectionP = curMapP ;
* mapPP = curMapP ;
return NULL ;
}
static os_error * delete_map ( ufont_map_t * mapP )
{
assert ( mapP - > refCount > 0 ) ;
- - mapP - > refCount ;
/* \todo: we don't remove the map from the oMapCollection list. Should we ?
*/
return NULL ;
}
/* Returns:
* x > 0 : number of bytes consumed at s , valid wchar_t returned at pwc [ 0 ]
* x = 0 : too few input bytes , pwc [ 0 ] is undefined
* x < 0 : illegal UTF - 8 stream , skip - x characters at s , pwc [ 0 ] is undefined
*/
static int eat_utf8 ( wchar_t * pwc , const byte * s , int n )
{
byte c ;
int i ;
#if 0
fputs ( " < " , stderr ) ;
for ( i = 0 ; i < n ; + + i )
fputc ( s [ i ] , stderr ) ;
fputs ( " > \n " , stderr ) ;
# endif
if ( n < 1 )
return 0 ; /* not enough input bytes */
else if ( ( c = s [ 0 ] ) < 0x80 ) {
* pwc = c ;
return 1 ;
} else if ( c < 0xc2 )
goto do_sync ;
else if ( c < 0xe0 ) {
if ( n < 2 )
return 0 ; /* not enough input bytes */
if ( ! ( ( s [ 1 ] ^ 0x80 ) < 0x40 ) )
goto do_sync ;
* pwc = ( ( wchar_t ) ( c & 0x1f ) < < 6 ) | ( wchar_t ) ( s [ 1 ] ^ 0x80 ) ;
return 2 ;
} else if ( c < 0xf0 ) {
if ( n < 3 )
return 0 ; /* not enough input bytes */
if ( ! ( ( s [ 1 ] ^ 0x80 ) < 0x40 & & ( s [ 2 ] ^ 0x80 ) < 0x40 & & ( c > = 0xe1 | | s [ 1 ] > = 0xa0 ) ) )
goto do_sync ;
* pwc = ( ( wchar_t ) ( c & 0x0f ) < < 12 ) | ( ( wchar_t ) ( s [ 1 ] ^ 0x80 ) < < 6 ) | ( wchar_t ) ( s [ 2 ] ^ 0x80 ) ;
return 3 ;
} else if ( c < 0xf8 ) {
if ( n < 4 )
return 0 ; /* not enough input bytes */
if ( ! ( ( s [ 1 ] ^ 0x80 ) < 0x40 & & ( s [ 2 ] ^ 0x80 ) < 0x40 & & ( s [ 3 ] ^ 0x80 ) < 0x40 & & ( c > = 0xf1 | | s [ 1 ] > = 0x90 ) ) )
goto do_sync ;
* pwc = ( ( wchar_t ) ( c & 0x07 ) < < 18 ) | ( ( wchar_t ) ( s [ 1 ] ^ 0x80 ) < < 12 ) | ( ( wchar_t ) ( s [ 2 ] ^ 0x80 ) < < 6 ) | ( wchar_t ) ( s [ 3 ] ^ 0x80 ) ;
return 4 ;
} else if ( c < 0xfc ) {
if ( n < 5 )
return 0 ; /* not enough input bytes */
if ( ! ( ( s [ 1 ] ^ 0x80 ) < 0x40 & & ( s [ 2 ] ^ 0x80 ) < 0x40 & & ( s [ 3 ] ^ 0x80 ) < 0x40 & & ( s [ 4 ] ^ 0x80 ) < 0x40 & & ( c > = 0xf9 | | s [ 1 ] > = 0x88 ) ) )
goto do_sync ;
* pwc = ( ( wchar_t ) ( c & 0x03 ) < < 24 ) | ( ( wchar_t ) ( s [ 1 ] ^ 0x80 ) < < 18 ) | ( ( wchar_t ) ( s [ 2 ] ^ 0x80 ) < < 12 ) | ( ( wchar_t ) ( s [ 3 ] ^ 0x80 ) < < 6 ) | ( wchar_t ) ( s [ 4 ] ^ 0x80 ) ;
return 5 ;
} else if ( c < 0xfe ) {
if ( n < 6 )
return 0 ; /* not enough input bytes */
if ( ! ( ( s [ 1 ] ^ 0x80 ) < 0x40 & & ( s [ 2 ] ^ 0x80 ) < 0x40 & & ( s [ 3 ] ^ 0x80 ) < 0x40 & & ( s [ 4 ] ^ 0x80 ) < 0x40 & & ( s [ 5 ] ^ 0x80 ) < 0x40 & & ( c > = 0xfd | | s [ 1 ] > = 0x84 ) ) )
goto do_sync ;
* pwc = ( ( wchar_t ) ( c & 0x01 ) < < 30 ) | ( ( wchar_t ) ( s [ 1 ] ^ 0x80 ) < < 24 ) | ( ( wchar_t ) ( s [ 2 ] ^ 0x80 ) < < 18 ) | ( ( wchar_t ) ( s [ 3 ] ^ 0x80 ) < < 12 ) | ( ( wchar_t ) ( s [ 4 ] ^ 0x80 ) < < 6 ) | ( wchar_t ) ( s [ 5 ] ^ 0x80 ) ;
return 6 ;
}
do_sync :
/* The UTF-8 sequence at s is illegal, skipping from s onwards
* until first non top character is found or % 11 xxxxxx is found
* ( both valid UTF - 8 * starts * - not necessary valid sequences ) .
*/
for ( i = 1 ; i < n & & ! ( ( s [ i ] & 0x80 ) = = 0x00 | | ( s [ i ] & 0xC0 ) = = 0xC0 ) ; + + i )
/* no body */ ;
return - i ;
}
/* Adds the RISC OS font <fontNameP> to the oVirtualFHArrayP list and
* returns the index in that array .
* oVirtualFHArrayP can be reallocated ( and all virFHP ptrs in oUsageChain ) .
* Results in xresOutP and yresOutP are not always that meaningful because
* of the delayed - loading of the real RISC OS font data .
* xresOutP and / or yresOutP may be NULL .
*/
static os_error * addref_virtual_fonthandle ( const char * fontNameP , int xsize , int ysize , int xres , int yres , int * xresOutP , int * yresOutP , size_t * offsetP )
{
size_t curIndex ;
virtual_fh_t * unusedSlotP ;
assert ( offsetP ! = NULL ) ;
do_sanity_check ( " addref_virtual_fonthandle() : begin " ) ;
if ( oVirtualFHArrayP = = NULL )
{
if ( ( oVirtualFHArrayP = ( virtual_fh_t * ) calloc ( kInitialFHArraySize , sizeof ( virtual_fh_t ) ) ) = = NULL )
return & error_memory ;
/* oCurVirtualFHArrayElems = 0; Isn't really necessary because of static */
oMaxVirtualFHArrayElems = kInitialFHArraySize ;
}
/* Check for duplicate (and find first unused slot if any) :
*/
for ( unusedSlotP = NULL , curIndex = 0 ;
curIndex < oCurVirtualFHArrayElems ;
+ + curIndex )
{
virtual_fh_t * virFHP = & oVirtualFHArrayP [ curIndex ] ;
if ( virFHP - > fontNameP ! = NULL /* case strdup(fontNameP) failed */
& & stricmp ( virFHP - > fontNameP , fontNameP ) = = 0
& & virFHP - > xsize = = xsize & & virFHP - > ysize = = ysize )
{
if ( xresOutP ! = NULL )
* xresOutP = virFHP - > xres ;
if ( yresOutP ! = NULL )
* yresOutP = virFHP - > yres ;
+ + virFHP - > refCount ;
* offsetP = curIndex ;
do_sanity_check ( " addref_virtual_fonthandle() : case 1 " ) ;
return NULL ;
}
if ( virFHP - > refCount = = 0 & & unusedSlotP = = NULL )
unusedSlotP = virFHP ;
}
/* Can we reuse a slot ?
* I . e . a virtual FH which refCount is zero .
*/
if ( unusedSlotP ! = NULL )
{
if ( unusedSlotP - > usageP ! = NULL )
{
os_error * errorP ;
/* This slot is refered in the usage chain, we have to unlink it.
*/
if ( ( errorP = remove_usage_chain_elem ( unusedSlotP - > usageP ) ) ! = NULL )
return errorP ;
}
unusedSlotP - > usage = 0 ;
if ( unusedSlotP - > fontNameP ! = NULL )
free ( ( void * ) unusedSlotP - > fontNameP ) ;
if ( ( unusedSlotP - > fontNameP = strdup ( fontNameP ) ) = = NULL )
return & error_memory ;
unusedSlotP - > xsize = xsize ;
unusedSlotP - > ysize = ysize ;
unusedSlotP - > xres = ( xres > 1 ) ? xres : 96 ;
if ( xresOutP ! = NULL )
* xresOutP = unusedSlotP - > xres ;
unusedSlotP - > yres = ( yres > 1 ) ? yres : 96 ;
if ( yresOutP ! = NULL )
* yresOutP = unusedSlotP - > yres ;
unusedSlotP - > refCount = 1 ;
* offsetP = unusedSlotP - oVirtualFHArrayP ;
do_sanity_check ( " addref_virtual_fonthandle() : case 2 " ) ;
return NULL ;
}
/* Add new entry :
*/
if ( oCurVirtualFHArrayElems = = oMaxVirtualFHArrayElems )
{
virtual_fh_t * newVirtualFHArrayP ;
size_t extraOffset ;
usage_chain_t * usageP ;
/* Don't use realloc() as when that fails, we don't even have the original
* memory block anymore .
*/
if ( ( newVirtualFHArrayP = ( virtual_fh_t * ) calloc ( 2 * oMaxVirtualFHArrayElems , sizeof ( virtual_fh_t ) ) ) = = NULL )
return & error_memory ;
memcpy ( newVirtualFHArrayP , oVirtualFHArrayP , oMaxVirtualFHArrayElems * sizeof ( virtual_fh_t ) ) ;
free ( ( void * ) oVirtualFHArrayP ) ;
extraOffset = ( const char * ) newVirtualFHArrayP - ( const char * ) oVirtualFHArrayP ;
oVirtualFHArrayP = newVirtualFHArrayP ;
oMaxVirtualFHArrayElems * = 2 ;
/* Update the virFHP pointers in the usage chain :
*/
if ( oUsageChain . nextP ! = NULL )
{
for ( usageP = oUsageChain . nextP ; usageP ! = & oUsageChain ; usageP = usageP - > nextP )
usageP - > virFHP = ( virtual_fh_t * ) & ( ( char * ) usageP - > virFHP ) [ extraOffset ] ;
}
}
unusedSlotP = & oVirtualFHArrayP [ oCurVirtualFHArrayElems ] ;
if ( ( unusedSlotP - > fontNameP = ( const char * ) strdup ( fontNameP ) ) = = NULL )
return & error_memory ;
unusedSlotP - > xsize = xsize ;
unusedSlotP - > ysize = ysize ;
unusedSlotP - > xres = ( xres > 1 ) ? xres : 96 ;
if ( xresOutP ! = NULL )
* xresOutP = unusedSlotP - > xres ;
unusedSlotP - > yres = ( yres > 1 ) ? yres : 96 ;
if ( yresOutP ! = NULL )
* yresOutP = unusedSlotP - > yres ;
unusedSlotP - > refCount = 1 ;
* offsetP = oCurVirtualFHArrayElems + + ;
do_sanity_check ( " addref_virtual_fonthandle() : case 3 " ) ;
return NULL ;
}
2004-07-09 00:16:23 +04:00
/**
* Deref virtual_fh_t element in oVirtualFHArrayP array .
2004-07-06 00:19:52 +04:00
*/
static os_error * deref_virtual_fonthandle ( size_t offset )
{
2004-07-09 00:16:23 +04:00
assert ( /* offset >= 0 && */ offset < oCurVirtualFHArrayElems ) ;
assert ( oVirtualFHArrayP [ offset ] . refCount > 0 ) ;
2004-07-06 00:19:52 +04:00
2004-07-09 00:16:23 +04:00
/* When the refCount reaches 0, it will be reused by preference when a
* new usageChain element is needed in addref_virtual_fonthandle ( ) .
*/
- - oVirtualFHArrayP [ offset ] . refCount ;
2004-07-06 00:19:52 +04:00
2004-07-09 00:16:23 +04:00
do_sanity_check ( " deref_virtual_fonthandle() " ) ;
return NULL ;
2004-07-06 00:19:52 +04:00
}
2004-07-09 00:16:23 +04:00
/**
* Virtual font handle < virFHP > needs to have a RISC OS font handle
2004-07-06 00:19:52 +04:00
* associated via virFHP - > usageP . For this we can throw out all other
* usage chain elements which have a chainTimer different from oChainTimer .
* However , we may not have more than kMaxUsageChainElems chain elements
* active .
* Afterwards : either an error , either virFHP - > usageP points to an usage chain
* element in the oUsageChain linked list and that usage chain element has
* a valid RISC OS font handle associated .
*/
static os_error * activate_virtual_fh ( virtual_fh_t * virFHP )
{
2004-07-09 00:16:23 +04:00
usage_chain_t * usageP ;
2004-07-06 00:19:52 +04:00
2004-07-09 00:16:23 +04:00
dbg_fprintf ( stderr , " +++ activate_virtual_fh(virFHP %p, usageP ? %p) \n " , virFHP , virFHP - > usageP ) ;
do_sanity_check ( " activate_virtual_fh() : begin " ) ;
2004-07-06 00:19:52 +04:00
2004-07-09 00:16:23 +04:00
/* The easiest case : we already have a RISC OS font handle :
*/
if ( ( usageP = virFHP - > usageP ) ! = NULL ) {
usageP - > chainTimer = oChainTimer ;
assert ( usageP - > ro_fhandle ! = 0 ) ;
assert ( usageP - > virFHP = = virFHP ) ;
do_sanity_check ( " activate_virtual_fh() : case 1 " ) ;
dbg_fprintf ( stderr , " --- done, activate_virtual_fh(), case 1 \n " ) ;
return NULL ;
}
2004-07-06 00:19:52 +04:00
2004-07-09 00:16:23 +04:00
/* The second easiest case : we're still allowed to create an extra
* chain element :
*/
if ( oCurUsageChainElems < kMaxUsageChainElems ) {
os_error * errorP ;
if ( ( usageP = ( usage_chain_t * ) malloc ( sizeof ( usage_chain_t ) ) ) = = NULL )
return & error_memory ;
usageP - > chainTimer = oChainTimer ;
if ( ( errorP = xfont_find_font ( virFHP - > fontNameP ,
virFHP - > xsize , virFHP - > ysize ,
virFHP - > xres , virFHP - > yres ,
& usageP - > ro_fhandle ,
& virFHP - > xres , & virFHP - > yres ) ) ! = NULL ) {
free ( ( void * ) usageP ) ;
return errorP ;
}
usageP - > virFHP = virFHP ;
virFHP - > usageP = usageP ;
+ + oCurUsageChainElems ;
/* Make sure oUsageChain nextP and prevP point to at least something (is
* only executed once and should probably better be done in a global
* init routine ) .
*/
if ( oUsageChain . nextP = = NULL )
oUsageChain . nextP = oUsageChain . prevP = & oUsageChain ;
}
else {
os_error * errorP ;
/* The more difficult one : we need to reuse a usage chain element.
* Take the last one because that is least used but skip the onces
* with chainTimer equal to the current oChainTimer because those
* RISC OS font handles are still used in the font string we ' re
* currently processing .
*/
for ( usageP = oUsageChain . prevP ;
usageP ! = & oUsageChain & & usageP - > chainTimer = = oChainTimer ;
usageP = usageP - > prevP )
/* no body */ ;
if ( usageP = = & oUsageChain ) {
/* Painful : all usage chain elements are in use and we already have the
* maximum of chain elements reached .
*/
return & error_toomany_handles ;
}
usageP - > chainTimer = oChainTimer ;
/* The virtual font handle currently in usageP->virFHP no longer has a real
* RISC OS font handle anymore .
*/
usageP - > virFHP - > usageP = NULL ;
if ( ( errorP = xfont_lose_font ( usageP - > ro_fhandle ) ) ! = NULL )
return errorP ;
if ( ( errorP = xfont_find_font ( virFHP - > fontNameP ,
virFHP - > xsize , virFHP - > ysize ,
virFHP - > xres , virFHP - > yres ,
& usageP - > ro_fhandle ,
& virFHP - > xres , & virFHP - > yres ) ) ! = NULL )
return errorP ;
usageP - > virFHP = virFHP ;
virFHP - > usageP = usageP ;
/* Delink :
*/
usageP - > prevP - > nextP = usageP - > nextP ;
usageP - > nextP - > prevP = usageP - > prevP ;
}
/* Link usageP in the oUsageChain based on its current virFHP->usage value :
*/
{
const unsigned int usage = virFHP - > usage ;
usage_chain_t * runUsageP ;
for ( runUsageP = & oUsageChain ;
runUsageP ! = oUsageChain . nextP & & runUsageP - > prevP - > virFHP - > usage < = usage ;
runUsageP = runUsageP - > prevP )
/* no body */ ;
/* We have to link usageP between runUsageP and runUsageP->prevP
* because runUsageP - > prevP has higher usage than the one we need to
* link in - or - we ' re at the end / start .
*/
usageP - > nextP = runUsageP ;
usageP - > prevP = runUsageP - > prevP ;
runUsageP - > prevP - > nextP = usageP ;
runUsageP - > prevP = usageP ;
}
do_sanity_check ( " activate_virtual_fh() : case 2 " ) ;
dbg_fprintf ( stderr , " --- done, activate_virtual_fh(), case 2 \n " ) ;
2004-07-06 00:19:52 +04:00
2004-07-09 00:16:23 +04:00
return NULL ;
2004-07-06 00:19:52 +04:00
}
2004-07-09 00:16:23 +04:00
/**
* Remove the usage_chaint_t element from the usage chain
2004-07-06 00:19:52 +04:00
*/
static os_error * remove_usage_chain_elem ( usage_chain_t * usageP )
{
2004-07-09 00:16:23 +04:00
os_error * errorP ;
2004-07-06 00:19:52 +04:00
2004-07-09 00:16:23 +04:00
assert ( usageP ! = NULL ) ;
assert ( oCurUsageChainElems > 0 ) ;
assert ( usageP - > ro_fhandle ! = 0 ) ;
assert ( usageP - > virFHP ! = NULL ) ;
2004-07-06 00:19:52 +04:00
2004-07-09 00:16:23 +04:00
if ( ( errorP = xfont_lose_font ( usageP - > ro_fhandle ) ) ! = NULL )
return errorP ;
2004-07-06 00:19:52 +04:00
2004-07-09 00:16:23 +04:00
usageP - > virFHP - > usageP = NULL ;
2004-07-06 00:19:52 +04:00
2004-07-09 00:16:23 +04:00
/* Delink it :
*/
usageP - > prevP - > nextP = usageP - > nextP ;
usageP - > nextP - > prevP = usageP - > prevP ;
2004-07-06 00:19:52 +04:00
2004-07-09 00:16:23 +04:00
- - oCurUsageChainElems ;
free ( ( void * ) usageP ) ;
2004-07-06 00:19:52 +04:00
2004-07-09 00:16:23 +04:00
do_sanity_check ( " remove_usage_chain_elem() : end " ) ;
return NULL ;
2004-07-06 00:19:52 +04:00
}
2004-07-09 00:16:23 +04:00
/***
* Should be called when the usage_chain_t element is no longer in the right
* place in the chain based on its virFHP - > usage value .
*
* usageP is no longer in the right place in the chain because its
2004-07-06 00:19:52 +04:00
* - > virFHP - > usage value increased . Reposition it towards prev
* direction .
*/
static void repos_usage_chain_elem ( usage_chain_t * usageP )
{
2004-07-09 00:16:23 +04:00
usage_chain_t * prev1P , * prev2P ;
const unsigned int curUsage = usageP - > virFHP - > usage ;
2004-07-06 00:19:52 +04:00
2004-07-09 00:16:23 +04:00
dbg_fprintf ( stderr , " +++ repos_usage_chain_elem(%p) \n " , usageP ) ;
2004-07-06 00:19:52 +04:00
2004-07-09 00:16:23 +04:00
/* If this assert goes off, then it means that this routine shouldn't
* have been called .
*/
assert ( curUsage > usageP - > prevP - > virFHP - > usage ) ;
2004-07-06 00:19:52 +04:00
2004-07-09 00:16:23 +04:00
/* Delink :
*/
usageP - > prevP - > nextP = usageP - > nextP ;
usageP - > nextP - > prevP = usageP - > prevP ;
2004-07-06 00:19:52 +04:00
2004-07-09 00:16:23 +04:00
/* Place usageElemP between prev1P and prev2P.
*/
for ( prev1P = usageP - > prevP , prev2P = prev1P - > prevP ;
prev2P ! = & oUsageChain & & curUsage > prev2P - > virFHP - > usage ;
prev1P = prev2P , prev2P = prev2P - > prevP ) {
dbg_fprintf ( stderr , " > prev1P %p (%d), usageElemP %p (%d), prev2P %p (%d), dummy %p \n " , prev1P , prev1P - > virFHP - > usage , usageP , usageP - > virFHP - > usage , prev2P , prev2P - > virFHP - > usage , & oUsageChain ) ;
assert ( prev1P - > virFHP - > usage < = prev2P - > virFHP - > usage ) ;
}
2004-07-06 00:19:52 +04:00
2004-07-09 00:16:23 +04:00
dbg_fprintf ( stderr , " prev1P %p (%d), usageElemP %p (%d), prev2P %p (%d), dummy %p \n " , prev1P , prev1P - > virFHP - > usage , usageP , usageP - > virFHP - > usage , prev2P , prev2P - > virFHP - > usage , & oUsageChain ) ;
2004-07-06 00:19:52 +04:00
2004-07-09 00:16:23 +04:00
/* Relink between prev1P and prev2P :
*/
prev1P - > prevP = usageP ;
usageP - > prevP = prev2P ;
prev2P - > nextP = usageP ;
usageP - > nextP = prev1P ;
2004-07-06 00:19:52 +04:00
2004-07-09 00:16:23 +04:00
do_sanity_check ( " repos_usage_chain_elem() : end " ) ;
dbg_fprintf ( stderr , " --- done, repos_usage_chain_elem() \n " ) ;
2004-07-06 00:19:52 +04:00
}
/**
* Retrieves the RISC OS font name of given RISC OS fonthandle .
*
* \ param rofhandle RISC OS font handle
*/
static const char * get_rofontname ( font_f rofhandle )
{
usage_chain_t * usageP ;
if ( oUsageChain . nextP = = NULL )
return NULL ;
for ( usageP = oUsageChain . nextP ; usageP ! = & oUsageChain ; usageP = usageP - > nextP )
if ( usageP - > ro_fhandle = = rofhandle )
return usageP - > virFHP - > fontNameP ;
return NULL ;
}
2004-07-09 00:16:23 +04:00
# ifdef DEBUG_DUMP_INTERNALS
/**
* Prints to stderr the complete internal state of UFont .
*/
2004-07-06 00:19:52 +04:00
static void dump_internals ( void )
{
2004-07-09 00:16:23 +04:00
fprintf ( stderr , " Dump UFont internals: \n - Virtual font handle array at %p (length %d, max length %d) \n - Usage chain elements %d \n - Chain timer is %d \n Dump usage chain (first dummy at %p): \n " , oVirtualFHArrayP , oCurVirtualFHArrayElems , oMaxVirtualFHArrayElems , oCurUsageChainElems , oChainTimer , & oUsageChain ) ;
if ( oUsageChain . prevP = = NULL | | oUsageChain . nextP = = NULL ) {
fprintf ( stderr , " Empty usage chain \n " ) ;
if ( oUsageChain . prevP ! = oUsageChain . nextP )
fprintf ( stderr , " *** Corrupted empty usage chain: next %p, prev %p \n " , oUsageChain . nextP , oUsageChain . prevP ) ;
if ( oCurUsageChainElems ! = 0 )
fprintf ( stderr , " *** Current usage chain length is wrong \n " ) ;
}
else {
size_t usageCount ;
const usage_chain_t * usageP ;
for ( usageCount = 0 , usageP = oUsageChain . nextP ; usageP ! = & oUsageChain ; + + usageCount , usageP = usageP - > nextP ) {
fprintf ( stderr , " -%d- : cur %p, next %p, prev %p, timer %d, RISC OS font handle %d, virtual font %p (%d, %s), usage %d \n " , usageCount , usageP , usageP - > nextP , usageP - > prevP , usageP - > chainTimer , usageP - > ro_fhandle , usageP - > virFHP , usageP - > virFHP - oVirtualFHArrayP , usageP - > virFHP - > fontNameP , usageP - > virFHP - > usage ) ;
if ( usageP - > nextP - > prevP ! = usageP )
fprintf ( stderr , " *** Bad usageP->nextP->prevP != usageP \n " ) ;
if ( usageP - > prevP - > nextP ! = usageP )
fprintf ( stderr , " *** Bad usageP->prevP->nextP != usageP \n " ) ;
if ( usageP - > virFHP < oVirtualFHArrayP | | usageP - > virFHP > = & oVirtualFHArrayP [ oCurVirtualFHArrayElems ] )
fprintf ( stderr , " *** Bad virtual font handle \n " ) ;
}
if ( usageCount ! = oCurUsageChainElems )
fprintf ( stderr , " *** Current usage chain length is wrong \n " ) ;
if ( usageCount > kMaxUsageChainElems )
fprintf ( stderr , " *** Current usage chain is too long \n " ) ;
}
2004-07-06 00:19:52 +04:00
2004-07-09 00:16:23 +04:00
if ( oVirtualFHArrayP ! = NULL ) {
size_t fhIndex ;
fprintf ( stderr , " Dump virtual font handles: \n " ) ;
for ( fhIndex = 0 ; fhIndex < oCurVirtualFHArrayElems ; + + fhIndex ) {
const virtual_fh_t * virFHP = & oVirtualFHArrayP [ fhIndex ] ;
fprintf ( stderr , " -%d (%p)- : <%s>, size %d,%d, res %d,%d, usage %d, ref count %d, usage chain ptr %p \n " , fhIndex , virFHP , virFHP - > fontNameP , virFHP - > xsize , virFHP - > ysize , virFHP - > xres , virFHP - > yres , virFHP - > usage , virFHP - > refCount , virFHP - > usageP ) ;
if ( virFHP - > usageP ! = NULL ) {
const usage_chain_t * usageP ;
for ( usageP = oUsageChain . nextP ;
usageP ! = virFHP - > usageP & & usageP ! = & oUsageChain ;
usageP = usageP - > nextP )
/* no body */ ;
if ( usageP ! = virFHP - > usageP )
fprintf ( stderr , " *** Usage chain ptr could not be found in usage chain \n " ) ;
}
}
}
2004-07-06 00:19:52 +04:00
}
2004-07-09 00:16:23 +04:00
# endif
2004-07-06 00:19:52 +04:00
2004-07-09 00:16:23 +04:00
/**
* Does do a full sanity check of UFont internal datastructures .
* Will assert ( ) when something odd if found .
*/
2004-07-06 00:19:52 +04:00
static int sanity_check ( const char * testMsgP )
{
2004-07-09 00:16:23 +04:00
dbg_fprintf ( stderr , " Sanity check <%s> \n " , testMsgP ) ;
if ( oUsageChain . prevP = = NULL | | oUsageChain . nextP = = NULL ) {
assert ( oUsageChain . prevP = = oUsageChain . nextP ) ;
assert ( oCurUsageChainElems = = 0 ) ;
}
else {
size_t usageCount ;
const usage_chain_t * usageP ;
/* We should see equal or decreasing usage values.
*/
for ( usageCount = 0 , usageP = oUsageChain . nextP ; usageP ! = & oUsageChain ; + + usageCount , usageP = usageP - > nextP ) {
assert ( usageP - > nextP - > prevP = = usageP ) ;
assert ( usageP - > prevP - > nextP = = usageP ) ;
assert ( usageP - > chainTimer < = oChainTimer ) ;
assert ( usageP - > ro_fhandle ! = 0 ) ;
assert ( oVirtualFHArrayP ! = NULL ) ;
assert ( usageP - > virFHP > = oVirtualFHArrayP & & usageP - > virFHP < & oVirtualFHArrayP [ oCurVirtualFHArrayElems ] ) ;
assert ( usageP - > virFHP - > usageP = = usageP ) ;
assert ( usageP = = oUsageChain . prevP | | usageP - > virFHP - > usage > = usageP - > nextP - > virFHP - > usage ) ;
}
assert ( usageCount = = oCurUsageChainElems ) ;
assert ( usageCount < = kMaxUsageChainElems ) ;
}
if ( oVirtualFHArrayP ! = NULL ) {
size_t fhIndex ;
for ( fhIndex = 0 ; fhIndex < oCurVirtualFHArrayElems ; + + fhIndex ) {
const virtual_fh_t * virFHP = & oVirtualFHArrayP [ fhIndex ] ;
if ( virFHP - > usageP ! = NULL ) {
const usage_chain_t * usageP ;
assert ( virFHP - > fontNameP ! = NULL ) ;
assert ( virFHP - > xsize > 0 & & virFHP - > ysize > 0 ) ;
assert ( virFHP - > xres > 0 & & virFHP - > yres > 0 ) ;
for ( usageP = oUsageChain . nextP ;
usageP ! = virFHP - > usageP & & usageP ! = & oUsageChain ;
usageP = usageP - > nextP )
/* no body */ ;
assert ( usageP = = virFHP - > usageP ) ;
}
}
}
return 0 ;
2004-07-06 00:19:52 +04:00
}