libhydride/ftgl/font-manager.c
2017-11-09 22:54:55 +03:00

242 lines
6.4 KiB
C

/* Freetype GL - A C OpenGL Freetype engine
*
* Distributed under the OSI-approved BSD 2-Clause License. See accompanying
* file `LICENSE` for more details.
*/
#if 0
# if !defined(_WIN32) && !defined(_WIN64)
# include <fontconfig/fontconfig.h>
# endif
#endif
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "font-manager.h"
// ------------------------------------------------------------ file_exists ---
static int
file_exists( const char * filename )
{
FILE * file = fopen( filename, "r" );
if ( file )
{
fclose(file);
return 1;
}
return 0;
}
// ------------------------------------------------------- font_manager_new ---
font_manager_t *
font_manager_new( size_t width, size_t height, size_t depth )
{
font_manager_t *self;
texture_atlas_t *atlas = texture_atlas_new( width, height, depth );
self = (font_manager_t *) malloc( sizeof(font_manager_t) );
if( !self )
{
fprintf( stderr,
"line %d: No more memory for allocating data\n", __LINE__ );
exit( EXIT_FAILURE );
}
self->atlas = atlas;
self->fonts = vector_new( sizeof(texture_font_t *) );
self->cache = strdup( " " );
return self;
}
// ---------------------------------------------------- font_manager_delete ---
void
font_manager_delete( font_manager_t * self )
{
size_t i;
texture_font_t *font;
assert( self );
for( i=0; i<vector_size( self->fonts ); ++i)
{
font = *(texture_font_t **) vector_get( self->fonts, i );
texture_font_delete( font );
}
vector_delete( self->fonts );
texture_atlas_delete( self->atlas );
if( self->cache )
{
free( self->cache );
}
free( self );
}
// ----------------------------------------------- font_manager_delete_font ---
void
font_manager_delete_font( font_manager_t * self,
texture_font_t * font)
{
size_t i;
texture_font_t *other;
assert( self );
assert( font );
for( i=0; i<self->fonts->size;++i )
{
other = (texture_font_t *) vector_get( self->fonts, i );
if ( (strcmp(font->filename, other->filename) == 0)
&& ( font->size == other->size) )
{
vector_erase( self->fonts, i);
break;
}
}
texture_font_delete( font );
}
// ----------------------------------------- font_manager_get_from_filename ---
texture_font_t *
font_manager_get_from_filename( font_manager_t *self,
const char * filename,
const float size )
{
size_t i;
texture_font_t *font;
assert( self );
for( i=0; i<vector_size(self->fonts); ++i )
{
font = * (texture_font_t **) vector_get( self->fonts, i );
if( (strcmp(font->filename, filename) == 0) && ( font->size == size) )
{
return font;
}
}
font = texture_font_new_from_file( self->atlas, size, filename );
if( font )
{
vector_push_back( self->fonts, &font );
texture_font_load_glyphs( font, self->cache );
return font;
}
fprintf( stderr, "Unable to load \"%s\" (size=%.1f)\n", filename, size );
return 0;
}
// ----------------------------------------- font_manager_get_from_description ---
texture_font_t *
font_manager_get_from_description( font_manager_t *self,
const char * family,
const float size,
const int bold,
const int italic )
{
texture_font_t *font;
char *filename = 0;
assert( self );
if( file_exists( family ) )
{
filename = strdup( family );
}
else
{
#if defined(_WIN32) || defined(_WIN64)
fprintf( stderr, "\"font_manager_get_from_description\" not implemented yet.\n" );
return 0;
#endif
filename = font_manager_match_description( self, family, size, bold, italic );
if( !filename )
{
fprintf( stderr, "No \"%s (size=%.1f, bold=%d, italic=%d)\" font available.\n",
family, size, bold, italic );
return 0;
}
}
font = font_manager_get_from_filename( self, filename, size );
free( filename );
return font;
}
// ------------------------------------------- font_manager_get_from_markup ---
texture_font_t *
font_manager_get_from_markup( font_manager_t *self,
const markup_t *markup )
{
assert( self );
assert( markup );
return font_manager_get_from_description( self, markup->family, markup->size,
markup->bold, markup->italic );
}
// ----------------------------------------- font_manager_match_description ---
char *
font_manager_match_description( font_manager_t * self,
const char * family,
const float size,
const int bold,
const int italic )
{
// Use of fontconfig is disabled by default.
#if 1
return 0;
#else
# if defined _WIN32 || defined _WIN64
fprintf( stderr, "\"font_manager_match_description\" not implemented for windows.\n" );
return 0;
# endif
char *filename = 0;
int weight = FC_WEIGHT_REGULAR;
int slant = FC_SLANT_ROMAN;
if ( bold )
{
weight = FC_WEIGHT_BOLD;
}
if( italic )
{
slant = FC_SLANT_ITALIC;
}
FcInit();
FcPattern *pattern = FcPatternCreate();
FcPatternAddDouble( pattern, FC_SIZE, size );
FcPatternAddInteger( pattern, FC_WEIGHT, weight );
FcPatternAddInteger( pattern, FC_SLANT, slant );
FcPatternAddString( pattern, FC_FAMILY, (FcChar8*) family );
FcConfigSubstitute( 0, pattern, FcMatchPattern );
FcDefaultSubstitute( pattern );
FcResult result;
FcPattern *match = FcFontMatch( 0, pattern, &result );
FcPatternDestroy( pattern );
if ( !match )
{
fprintf( stderr, "fontconfig error: could not match family '%s'", family );
return 0;
}
else
{
FcValue value;
FcResult result = FcPatternGet( match, FC_FILE, 0, &value );
if ( result )
{
fprintf( stderr, "fontconfig error: could not match family '%s'", family );
}
else
{
filename = strdup( (char *)(value.u.s) );
}
}
FcPatternDestroy( match );
return filename;
#endif
}