📄 ftcommon.c
字号:
/****************************************************************************/
/* */
/* The FreeType project -- a free and portable quality TrueType renderer. */
/* */
/* Copyright 2005, 2006 by */
/* D. Turner, R.Wilhelm, and W. Lemberg */
/* */
/* */
/* ftcommon.c - common routines for the FreeType demo programs. */
/* */
/****************************************************************************/
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_CACHE_H
#include FT_CACHE_MANAGER_H
#include FT_BITMAP_H
#include "ftcommon.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
FT_Error error;
#undef NODEBUG
#ifndef NODEBUG
void
LogMessage( const char* fmt, ... )
{
va_list ap;
va_start( ap, fmt );
vfprintf( stderr, fmt, ap );
va_end( ap );
}
#endif /* NODEBUG */
/* PanicZ */
void
PanicZ( const char* message )
{
fprintf( stderr, "%s\n error = 0x%04x\n", message, error );
exit( 1 );
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** DISPLAY-SPECIFIC DEFINITIONS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
#define DIM_X 500
#define DIM_Y 400
FTDemo_Display*
FTDemo_Display_New( grPixelMode mode )
{
FTDemo_Display* display;
grSurface* surface;
grBitmap bit;
display = (FTDemo_Display *)malloc( sizeof( FTDemo_Display ) );
if ( !display )
return NULL;
if ( mode != gr_pixel_mode_gray &&
mode != gr_pixel_mode_rgb24 )
return NULL;
grInitDevices();
bit.mode = mode;
bit.width = DIM_X;
bit.rows = DIM_Y;
bit.grays = 256;
surface = grNewSurface( 0, &bit );
if ( !surface )
{
free( display );
return NULL;
}
display->surface = surface;
display->bitmap = &surface->bitmap;
grSetGlyphGamma( 1.0 );
memset( &display->fore_color, 0, sizeof( grColor ) );
memset( &display->back_color, 0xff, sizeof( grColor ) );
return display;
}
void
FTDemo_Display_Done( FTDemo_Display* display )
{
grDoneBitmap( display->bitmap );
grDoneSurface( display->surface );
grDoneDevices();
free( display );
}
void
FTDemo_Display_Clear( FTDemo_Display* display )
{
grBitmap* bit = display->bitmap;
int pitch = bit->pitch;
if ( pitch < 0 )
pitch = -pitch;
if ( bit->mode == gr_pixel_mode_gray )
memset( bit->buffer, display->back_color.value, pitch * bit->rows );
else
{
unsigned char* p = bit->buffer;
int i, j;
for ( i = 0; i < bit->rows; i++ )
{
for ( j = 0; j < bit->width; j++ )
memcpy( p + 3 * j, display->back_color.chroma, 3 );
p += pitch;
}
}
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** FREETYPE-SPECIFIC DEFINITIONS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
#define FLOOR( x ) ( (x) & -64 )
#define CEIL( x ) ( ( (x) + 63 ) & -64 )
#define ROUND( x ) ( ( (x) + 32 ) & -64 )
#define TRUNC( x ) ( (x) >> 6 )
static
const char* file_suffixes[] =
{
".ttf",
".ttc",
".otf",
".pfa",
".pfb",
0
};
/*************************************************************************/
/* */
/* The face requester is a function provided by the client application */
/* to the cache manager, whose role is to translate an `abstract' face */
/* ID into a real FT_Face object. */
/* */
/* In this program, the face IDs are simply pointers to TFont objects. */
/* */
static FT_Error
my_face_requester( FTC_FaceID face_id,
FT_Library lib,
FT_Pointer request_data,
FT_Face* aface )
{
PFont font = (PFont)face_id;
FT_UNUSED( request_data );
if ( font->file_address != NULL )
error = FT_New_Memory_Face( lib, font->file_address, font->file_size,
font->face_index, aface );
else
error = FT_New_Face( lib,
font->filepathname,
font->face_index,
aface );
if ( !error )
{
char* suffix;
char orig[4];
suffix = strrchr( font->filepathname, '.' );
if ( suffix && ( strcasecmp( suffix, ".pfa" ) == 0 ||
strcasecmp( suffix, ".pfb" ) == 0 ) )
{
suffix++;
memcpy( orig, suffix, 4 );
memcpy( suffix, "afm", 4 );
FT_Attach_File( *aface, font->filepathname );
memcpy( suffix, "pfm", 4 );
FT_Attach_File( *aface, font->filepathname );
memcpy( suffix, orig, 4 );
}
if ( (*aface)->charmaps )
(*aface)->charmap = (*aface)->charmaps[font->cmap_index];
}
return error;
}
FTDemo_Handle*
FTDemo_New( FT_Encoding encoding )
{
FTDemo_Handle* handle;
handle = (FTDemo_Handle *)malloc( sizeof( FTDemo_Handle ) );
if ( !handle )
return NULL;
memset( handle, 0, sizeof( FTDemo_Handle ) );
error = FT_Init_FreeType( &handle->library );
if ( error )
PanicZ( "could not initialize FreeType" );
error = FTC_Manager_New( handle->library, 0, 0, 0,
my_face_requester, 0, &handle->cache_manager );
if ( error )
PanicZ( "could not initialize cache manager" );
error = FTC_SBitCache_New( handle->cache_manager, &handle->sbits_cache );
if ( error )
PanicZ( "could not initialize small bitmaps cache" );
error = FTC_ImageCache_New( handle->cache_manager, &handle->image_cache );
if ( error )
PanicZ( "could not initialize glyph image cache" );
error = FTC_CMapCache_New( handle->cache_manager, &handle->cmap_cache );
if ( error )
PanicZ( "could not initialize charmap cache" );
FT_Bitmap_New( &handle->bitmap );
handle->encoding = encoding;
handle->hinted = 1;
handle->antialias = 1;
handle->use_sbits = 1;
handle->low_prec = 0;
handle->autohint = 0;
handle->lcd_mode = 0;
handle->use_sbits_cache = 1;
/* string_init */
memset( handle->string, 0, sizeof( TGlyph ) * MAX_GLYPHS );
handle->string_length = 0;
handle->string_reload = 1;
return handle;
}
void
FTDemo_Done( FTDemo_Handle* handle )
{
int i;
for ( i = 0; i < handle->max_fonts; i++ )
{
if ( handle->fonts[i] )
{
if ( handle->fonts[i]->filepathname )
free( (void*)handle->fonts[i]->filepathname );
free( handle->fonts[i] );
}
}
free( handle->fonts );
/* string_done */
for ( i = 0; i < MAX_GLYPHS; i++ )
{
PGlyph glyph = handle->string + i;
if ( glyph->image )
FT_Done_Glyph( glyph->image );
}
FT_Bitmap_Done( handle->library, &handle->bitmap );
FTC_Manager_Done( handle->cache_manager );
FT_Done_FreeType( handle->library );
free( handle );
}
FT_Error
FTDemo_Install_Font( FTDemo_Handle* handle,
const char* filepath )
{
static char filename[1024 + 5];
int i, len, num_faces;
FT_Face face;
len = strlen( filepath );
if ( len > 1024 )
len = 1024;
strncpy( filename, filepath, len );
filename[len] = 0;
error = FT_New_Face( handle->library, filename, 0, &face );
#ifndef macintosh
/* could not open the file directly; we will now try various */
/* suffixes like `.ttf' or `.pfb' */
if ( error )
{
const char** suffix;
char* p;
int found = 0;
suffix = file_suffixes;
p = filename + len - 1;
while ( p >= filename && *p != '\\' && *p != '/' )
{
if ( *p == '.' )
break;
p--;
}
/* no suffix found */
if ( p < filename || *p != '.' )
p = filename + len;
for ( suffix = file_suffixes; suffix[0]; suffix++ )
{
/* try with current suffix */
strcpy( p, suffix[0] );
error = FT_New_Face( handle->library, filename, 0, &face );
if ( !error )
{
found = 1;
break;
}
}
/* really couldn't open this file */
if ( !found )
return error;
}
#endif /* !macintosh */
/* allocate new font object */
num_faces = face->num_faces;
for ( i = 0; i < num_faces; i++ )
{
PFont font;
if ( i > 0 )
{
error = FT_New_Face( handle->library, filename, i, &face );
if ( error )
continue;
}
if ( handle->encoding != FT_ENCODING_NONE )
{
error = FT_Select_Charmap( face, handle->encoding );
if ( error )
{
FT_Done_Face( face );
return error;
}
}
font = (PFont)malloc( sizeof ( *font ) );
font->filepathname = (char*)malloc( strlen( filename ) + 1 );
strcpy( (char*)font->filepathname, filename );
font->face_index = i;
font->cmap_index = face->charmap ? FT_Get_Charmap_Index( face->charmap )
: 0;
if ( handle->preload )
{
FILE* file = fopen( filename, "rb" );
size_t file_size;
if ( file == NULL ) /* shouldn't happen */
{
free( font );
return FT_Err_Invalid_Argument;
}
fseek( file, 0, SEEK_END );
file_size = ftell( file );
fseek( file, 0, SEEK_SET );
font->file_address = malloc( file_size );
fread( font->file_address, 1, file_size, file );
font->file_size = file_size;
fclose( file );
}
else
{
font->file_address = NULL;
font->file_size = 0;
}
switch ( handle->encoding )
{
case FT_ENCODING_NONE:
font->num_indices = face->num_glyphs;
break;
case FT_ENCODING_UNICODE:
font->num_indices = 0x110000L;
break;
case FT_ENCODING_MS_SYMBOL:
case FT_ENCODING_ADOBE_LATIN_1:
case FT_ENCODING_ADOBE_STANDARD:
case FT_ENCODING_ADOBE_EXPERT:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -