📄 ftbench.c
字号:
/****************************************************************************//* *//* The FreeType project -- a free and portable quality TrueType renderer. *//* *//* Copyright 2002, 2003, 2004 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>#endiftypedef int(*bench_t)(FT_UInt idx, FT_UInt charcode);typedef struct charmap_t_{ FT_UInt charcode; FT_UInt index;} charmap_t;/* * Globals */#define CACHE_SIZE 1024#define BENCH_TIME 2.0fFT_Library lib;FT_Face face;FTC_Manager cache_man;FTC_CMapCache cmap_cache;FTC_ImageCache image_cache;FTC_SBitCache sbit_cache;FTC_ImageTypeRec font_type;charmap_t* cmap = NULL;double bench_time = BENCH_TIME;int preload = 0;FT_Byte* memory_file = NULL;long memory_size;/* * Dummy face requester (the face object is already loaded) */FT_Errorface_requester (FTC_FaceID face_id, FT_Library library, FT_Pointer request_data,\ FT_Face* aface){ FT_UNUSED( face_id ); FT_UNUSED( library ); FT_UNUSED( request_data ); *aface = face; return 0;}/* * Bench code */doubleget_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}voidget_cmap(void){ FT_ULong charcode; FT_UInt gindex; int i; if (cmap) return; /* Already available */ cmap = (charmap_t*)calloc(face->num_glyphs, sizeof(charmap_t)); if (face->charmap) { i = 0; charcode = FT_Get_First_Char(face, &gindex); /* certain fonts contain a broken charmap that will map character codes */ /* to out-of-bounds glyph indices. Take care of that here !! */ /* */ while ( gindex && i < face->num_glyphs ) { cmap[i].index = gindex; cmap[i].charcode = charcode; i++; charcode = FT_Get_Next_Char(face, charcode, &gindex); } } else /* no charmap, do an identity mapping */ for (i = 0; i < face->num_glyphs; i++) { cmap[i].index = i; cmap[i].charcode = i; i++; }}voidbench(bench_t bench_func, const char* title, int max){ int i, n, done; double t0, delta; printf("%-30s : ", title); fflush(stdout); get_cmap(); n = 0; done = 0; t0 = get_time(); do { for (i = 0; i < face->num_glyphs; i++) if (!(*bench_func)(cmap[i].index, cmap[i].charcode)) done++; n++; delta = get_time() - t0; } while ((!max || n < max) && delta < bench_time); printf("%5.3f us/op\n", delta * 1E6 / (double)done);}/* * Various tests */intload_test(FT_UInt idx, FT_UInt charcode){ FT_UNUSED( charcode ); return FT_Load_Glyph(face, idx, FT_LOAD_DEFAULT);}intfetch_test(FT_UInt idx, FT_UInt charcode){ FT_Glyph glyph; FT_Error error; FT_UNUSED( charcode ); error = FT_Load_Glyph( face, idx, FT_LOAD_DEFAULT ); if ( !error ) { error = FT_Get_Glyph( face->glyph, &glyph ); if ( !error ) FT_Done_Glyph( glyph ); } return error;}intcbox_test(FT_UInt idx, FT_UInt charcode){ FT_BBox bbox; FT_Glyph glyph; FT_Error error; FT_UNUSED( charcode ); error = FT_Load_Glyph( face, idx, FT_LOAD_DEFAULT ); if ( !error ) { error = FT_Get_Glyph( face->glyph, &glyph ); if ( !error ) { FT_Glyph_Get_CBox( glyph, FT_GLYPH_BBOX_PIXELS, &bbox ); FT_Done_Glyph( glyph ); } } return error;}intcmap_test(FT_UInt idx, FT_UInt charcode){ FT_UNUSED( idx ); return !FT_Get_Char_Index(face, charcode);}intcmap_cache_test(FT_UInt idx, FT_UInt charcode){ FT_UNUSED( idx ); return !FTC_CMapCache_Lookup( cmap_cache, (FTC_FaceID)1, 0, charcode );}intimage_cache_test(FT_UInt idx, FT_UInt charcode){ FT_Glyph glyph; FT_UNUSED( charcode ); return FTC_ImageCache_Lookup(image_cache, &font_type, idx, &glyph, NULL);}intsbit_cache_test(FT_UInt idx, FT_UInt charcode){ FTC_SBit glyph; FT_UNUSED( charcode ); return FTC_SBitCache_Lookup(sbit_cache, &font_type, idx, &glyph, NULL);}voidbench_open_close( const char* filename, const char* title, int max){ int n, done; double t0, delta; printf("%-30s : ", title); fflush(stdout); n = 0; done = 0; t0 = get_time(); do { FT_Face bench_face; FT_Error error; if ( preload ) error = FT_New_Memory_Face( lib, memory_file, memory_size, 0, &bench_face ); else error = FT_New_Face( lib, filename, 0, &bench_face ); if ( !error ) { FT_Done_Face( bench_face ); } done++; n++; delta = get_time() - t0; } while ((!max || n < max) && delta < bench_time); printf("%5.3f us/op\n", delta * 1E6 / (double)done);}voidbench_cmap_parse( const char* title, int max ){ int n, done; double t0, delta; printf("%-30s : ", title); fflush(stdout); n = 0; done = 0; t0 = get_time(); do { FT_UInt gindex; FT_ULong charcode; charcode = FT_Get_First_Char( face, &gindex ); while ( gindex != 0 ) charcode = FT_Get_Next_Char( face, charcode, &gindex ); done++; n++; delta = get_time() - t0; } while ((!max || n < max) && delta < bench_time); printf("%5.3f us/op\n", delta * 1E6 / (double)done);}/* * main */void usage(void){ fprintf( stderr, "ftbench: bench some common FreeType paths\n" "-----------------------------------------\n\n" "Usage: ftbench [options] fontname\n\n" "options:\n" ); fprintf( stderr, " -m : max cache size in KByte (default is %d)\n", CACHE_SIZE ); fprintf( stderr, " -t : max time per bench in seconds (default is %.0f)\n", BENCH_TIME ); fprintf( stderr, " -p : preload font file in memory\n" " -b tests : perform chosen tests (default is all)\n" " a : Load\n" " b : Load + Get_Glyph\n" " c : Load + Get_Glyph + Get_CBox\n" " d : Get_Char_Index\n" " e : CMap cache\n" " f : Outline cache\n" " g : Bitmap cache\n" " h : SBit cache\n" " i : Open/Close\n" " j : Charmap iteration\n" ); exit( 1 );}#define TEST(x) (!tests || strchr(tests, x))intmain(int argc, char** argv){ long max_bytes = CACHE_SIZE * 1024; char* tests = NULL; int size; while (argc > 1 && argv[1][0] == '-') { switch (argv[1][1]) { case 'm': argc--; argv++; if (argc < 2 || sscanf(argv[1], "%ld", &max_bytes) != 1) usage(); max_bytes *= 1024; break; case 'p': preload = 1; break; case 't': argc--; argv++; if (argc < 2 || sscanf(argv[1], "%lf", &bench_time) != 1) usage(); break; case 'b': argc--; argv++; if (argc < 2) usage(); tests = argv[1]; break; default: fprintf(stderr, "Unknown argument `%s'\n\n", argv[1]); usage(); break; } argc--; argv++; } if ( argc != 2 ) usage(); if (FT_Init_FreeType(&lib)) { fprintf( stderr, "could not initialize font library\n" ); return 1; } if ( preload ) { FILE* file = fopen( argv[1], "rb" ); if ( file == NULL ) { fprintf( stderr, "couldn't find or open `%s'\n", argv[1] ); return 1; } fseek( file, 0, SEEK_END ); memory_size = ftell( file ); fseek( file, 0, SEEK_SET ); memory_file = (FT_Byte*)malloc( memory_size ); if ( memory_file == NULL ) { fprintf( stderr, "couldn't allocate memory to pre-load font file\n" ); return 1; } fread( memory_file, 1, memory_size, file ); if ( FT_New_Memory_Face( lib, memory_file, memory_size, 0, &face ) ) { fprintf( stderr, "couldn't load font resource\n" ); return 1; } } else if ( FT_New_Face(lib, argv[1], 0, &face) ) { fprintf( stderr, "couldn't load font resource\n"); return 1; } if (FT_IS_SCALABLE(face)) { /* We're not benchmarking the scanline renderer, pick any size */ size = 10; FT_Set_Pixel_Sizes(face, size, size); } else size = face->available_sizes[0].width; if (TEST('a')) bench( load_test, "Load", 0); if (TEST('b')) bench( fetch_test, "Load + Get_Glyph", 0); if (TEST('c')) bench( cbox_test, "Load + Get_Glyph + Get_CBox", 0);#if 0 cmap_desc.face_id = (void*)1; cmap_desc.type = FTC_CMAP_BY_INDEX; cmap_desc.u.encoding = FT_ENCODING_NONE;#endif if (TEST('d') && face->charmap) /* some fonts (eg. windings) don't have a charmap */ { bench( cmap_test, "Get_Char_Index", 0); } if (!FTC_Manager_New(lib, 0, 0, max_bytes, face_requester, NULL, &cache_man)) { if (TEST('e') && face->charmap && !FTC_CMapCache_New(cache_man, &cmap_cache)) { bench( cmap_cache_test, "CMap cache (1st run)", 1); bench( cmap_cache_test, "CMap cache", 0); } font_type.face_id = (FTC_FaceID)1; font_type.width = (short) size; font_type.height = (short) size; if (!FTC_ImageCache_New(cache_man, &image_cache)) { if (TEST('f')) { font_type.flags = FT_LOAD_NO_BITMAP; bench( image_cache_test, "Outline cache (1st run)", 1); bench( image_cache_test, "Outline cache", 0); } if (TEST('g')) { font_type.flags = FT_LOAD_RENDER; bench( image_cache_test, "Bitmap cache (1st run)", 1); bench( image_cache_test, "Bitmap cache", 0); } } if (TEST('h') && !FTC_SBitCache_New(cache_man, &sbit_cache)) { font_type.flags = FT_LOAD_DEFAULT; bench( sbit_cache_test, "SBit cache (1st run)", 1); bench( sbit_cache_test, "SBit cache", 0); } } if (TEST('i') ) bench_open_close( argv[1], "Open/Close file", 0 ); if (TEST('j')) bench_cmap_parse( "Charmap iteration", 0 ); if (cmap) free (cmap); if (cache_man) FTC_Manager_Done(cache_man); FT_Done_FreeType(lib); return 0;}/* End */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -