?? ftbench.c
字號:
/****************************************************************************/
/* */
/* The FreeType project -- a free and portable quality TrueType renderer. */
/* */
/* Copyright 2002, 2003, 2004, 2005, 2006 by */
/* D. Turner, R.Wilhelm, and W. Lemberg */
/* */
/* ftbench: bench some common FreeType call paths */
/* */
/****************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include FT_CACHE_H
#include FT_CACHE_CHARMAP_H
#include FT_CACHE_IMAGE_H
#include FT_CACHE_SMALL_BITMAPS_H
#ifdef UNIX
#include <sys/time.h>
#endif
#include "common.h"
typedef struct {
double t0;
double total;
} btimer_t;
typedef int
(*bcall_t)( btimer_t* timer,
FT_Face face,
void* user_data );
typedef struct {
const char* title;
bcall_t bench;
int cache_first;
void* user_data;
} btest_t;
typedef struct
{
FT_Int size;
FT_ULong* code;
} bcharset_t;
FT_Error
get_face( FT_Face* face );
/*
* Globals
*/
#define CACHE_SIZE 1024
#define BENCH_TIME 2.0f
#define FACE_SIZE 10
FT_Library lib;
FTC_Manager cache_man;
FTC_CMapCache cmap_cache;
FTC_ImageCache image_cache;
FTC_SBitCache sbit_cache;
FTC_ImageTypeRec font_type;
enum {
FT_BENCH_LOAD_GLYPH,
FT_BENCH_RENDER,
FT_BENCH_GET_GLYPH,
FT_BENCH_GET_CBOX,
FT_BENCH_CMAP,
FT_BENCH_CMAP_ITER,
FT_BENCH_NEW_FACE,
N_FT_BENCH
};
const char* bench_desc[] = {
"Load a glyph",
"Render a glyph",
"Get FT_Glyph",
"Get glyph cbox",
"Get glyph index",
"Iterate CMap",
"Open a new face",
NULL
};
int preload;
char* filename;
FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL;
FT_Int32 load_flags = FT_LOAD_DEFAULT;
/*
* Dummy face requester (the face object is already loaded)
*/
FT_Error
face_requester( FTC_FaceID face_id,
FT_Library library,
FT_Pointer request_data,
FT_Face* aface )
{
FT_UNUSED( face_id );
FT_UNUSED( library );
*aface = (FT_Face)request_data;
return 0;
}
/*
* timer
*/
double
get_time(void)
{
#ifdef UNIX
struct timeval tv;
gettimeofday(&tv, NULL);
return (double)tv.tv_sec + (double)tv.tv_usec / 1E6;
#else
/* clock() has an awful precision (~10ms) under Linux 2.4 + glibc 2.2 */
return (double)clock() / (double)CLOCKS_PER_SEC;
#endif
}
#define TIMER_START( timer ) ( timer )->t0 = get_time()
#define TIMER_STOP( timer ) ( timer )->total += get_time() - ( timer )->t0
#define TIMER_GET( timer ) ( timer )->total
#define TIMER_RESET( timer ) ( timer )->total = 0
/*
* Bench code
*/
void
benchmark( FT_Face face,
btest_t* test,
int max_iter,
double max_time )
{
int n, done;
btimer_t timer, elapsed;
if ( test->cache_first )
{
if ( !cache_man )
{
printf( "%-25s : no cache manager\n", test->title );
return;
}
TIMER_RESET( &timer );
test->bench( &timer, face, test->user_data );
}
printf( "%-25s : ", test->title );
fflush( stdout );
n = done = 0;
TIMER_RESET( &timer );
TIMER_RESET( &elapsed );
for ( n = 0; !max_iter || n < max_iter; n++ )
{
TIMER_START( &elapsed );
done += test->bench( &timer, face, test->user_data );
TIMER_STOP( &elapsed );
if ( TIMER_GET( &elapsed ) > max_time )
break;
}
printf("%5.3f us/op\n", TIMER_GET( &timer ) * 1E6 / (double)done);
}
/*
* Various tests
*/
int
test_load( btimer_t* timer,
FT_Face face,
void* user_data )
{
int i, done = 0;
FT_UNUSED( user_data );
TIMER_START( timer );
for ( i = 0; i < face->num_glyphs; i++ )
{
if ( !FT_Load_Glyph( face, i, load_flags ) )
done++;
}
TIMER_STOP( timer );
return done;
}
int
test_render( btimer_t* timer,
FT_Face face,
void* user_data )
{
int i, done = 0;
FT_UNUSED( user_data );
for ( i = 0; i < face->num_glyphs; i++ )
{
if ( FT_Load_Glyph( face, i, load_flags ) )
continue;
TIMER_START( timer );
if ( !FT_Render_Glyph( face->glyph, render_mode ) )
done++;
TIMER_STOP( timer );
}
return done;
}
int
test_get_glyph( btimer_t* timer,
FT_Face face,
void* user_data )
{
FT_Glyph glyph;
int i, done = 0;
FT_UNUSED( user_data );
for ( i = 0; i < face->num_glyphs; i++ )
{
if ( FT_Load_Glyph( face, i, load_flags ) )
continue;
TIMER_START( timer );
if ( !FT_Get_Glyph( face->glyph, &glyph ) )
{
FT_Done_Glyph( glyph );
done++;
}
TIMER_STOP( timer );
}
return done;
}
int
test_get_cbox( btimer_t* timer,
FT_Face face,
void* user_data )
{
FT_Glyph glyph;
FT_BBox bbox;
int i, done = 0;
FT_UNUSED( user_data );
for ( i = 0; i < face->num_glyphs; i++ )
{
if ( FT_Load_Glyph( face, i, load_flags ) )
continue;
if ( FT_Get_Glyph( face->glyph, &glyph ) )
continue;
TIMER_START( timer );
FT_Glyph_Get_CBox( glyph, FT_GLYPH_BBOX_PIXELS, &bbox );
TIMER_STOP( timer );
FT_Done_Glyph( glyph );
done++;
}
return done;
}
int
test_get_char_index( btimer_t* timer,
FT_Face face,
void* user_data )
{
bcharset_t* charset = (bcharset_t*)user_data;
int i, done = 0;
TIMER_START( timer );
for ( i = 0; i < charset->size; i++ )
{
if ( FT_Get_Char_Index(face, charset->code[i]) )
done++;
}
TIMER_STOP( timer );
return done;
}
int
test_cmap_cache( btimer_t* timer,
FT_Face face,
void* user_data )
{
bcharset_t* charset = (bcharset_t*)user_data;
int i, done = 0;
FT_UNUSED( face );
if ( !cmap_cache )
{
if ( FTC_CMapCache_New(cache_man, &cmap_cache) )
return 0;
}
TIMER_START( timer );
for ( i = 0; i < charset->size; i++ )
{
if ( FTC_CMapCache_Lookup( cmap_cache, font_type.face_id, 0, charset->code[i] ) )
done++;
}
TIMER_STOP( timer );
return done;
}
int
test_image_cache( btimer_t* timer,
FT_Face face,
void* user_data )
{
FT_Glyph glyph;
int i, done = 0;
FT_UNUSED( user_data );
if ( !image_cache )
{
if ( FTC_ImageCache_New(cache_man, &image_cache) )
return 0;
}
TIMER_START( timer );
for ( i = 0; i < face->num_glyphs; i++ )
{
if ( !FTC_ImageCache_Lookup(image_cache, &font_type, i, &glyph, NULL) )
done++;
}
TIMER_STOP( timer );
return done;
}
int
test_sbit_cache( btimer_t* timer,
FT_Face face,
void* user_data )
{
FTC_SBit glyph;
int i, done = 0;
FT_UNUSED( user_data );
if ( !sbit_cache )
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -