home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: SysTools
/
SysTools.zip
/
ft-beta.zip
/
freetype
/
test
/
timer.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-10-06
|
15KB
|
524 lines
/****************************************************************************/
/* */
/* The FreeType project - a Free and Portable Quality TrueType Renderer. */
/* */
/* Copyright 1996, 1997 by */
/* D. Turner, R.Wilhelm, and W. Lemberg */
/* */
/* timer : A simple performance benchmark. Now with graylevel rendering */
/* with the '-g' option. */
/* */
/* Be aware that the timer program benchmarks different things */
/* in each release of the FreeType library. Thus, performance */
/* should only be compared between similar release numbers. */
/* */
/* */
/* NOTE : This is just a test program that is used to show off and */
/* debug the current engine; which is still in alpha. In no */
/* way does it shows the final high-level interface that */
/* client applications will use. Wait for at least a beta for */
/* this. */
/* */
/****************************************************************************/
#include "freetype.h"
#include "ttraster.h"
#include "tterror.h" /* for Panic */
#include "ttengine.h"
#include "gmain.h"
#include "gdriver.h"
#include "gevents.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h> /* for 'clock' */
/* SunOS 4.1.* does not define CLOCKS_PER_SEC, so include <sys/param.h> */
/* to get the HZ macro which is the equivalent. */
#if defined(__sun__) && !defined(SVR4) && !defined(__SVR4)
#include <sys/param.h>
#define CLOCKS_PER_SEC HZ
#endif
#ifdef TT_STATIC_RASTER
#define RAS_OPS /* void */
#define RAS_OP /* void */
#else
#define RAS_OPS ((TRaster_Instance*)engine.raster_component),
#define RAS_OP ((TRaster_Instance*)engine.raster_component)
#endif /* TT_STATIC_RASTER */
#define RENDER_Glyph(glyph,target) \
Render_Glyph( RAS_OPS glyph, target )
#define RENDER_Gray_Glyph(glyph,target,palette) \
Render_Gray_Glyph( RAS_OPS glyph, target, palette )
#define SET_High_Precision( high ) \
Set_High_Precision( RAS_OPS high )
#define SET_Second_Pass( pass ) \
Set_Second_Pass( RAS_OPS pass )
#define MAX_GLYPHS 512 /* Maximum number of glyphs rendered at one time */
char Header[128];
TT_Error error;
TT_Face face;
TT_Instance instance;
TT_Glyph glyph;
TT_Glyph_Outline outline;
TT_Glyph_Metrics metrics;
TT_Face_Properties properties;
TT_F26Dot6* cur_x;
TT_F26Dot6* cur_y;
unsigned short* cur_endContour;
unsigned char* cur_touch;
int max_points;
int max_contours;
int start_point[MAX_GLYPHS];
int num_points [MAX_GLYPHS];
unsigned short start_contour[MAX_GLYPHS];
int num_contours [MAX_GLYPHS];
int num_glyphs;
int tab_glyphs;
int cur_glyph;
int cur_point;
unsigned short cur_contour;
TT_Raster_Map Bit;
int Fail;
int Num;
short visual; /* display glyphs while rendering */
short gray_render; /* smooth fonts with gray levels */
static void Clear_Buffer();
/*******************************************************************/
/* */
/* Get_Time: */
/* */
/* returns the current time in milliseconds. */
/* */
/*******************************************************************/
long Get_Time()
{
return clock() * 1000 / CLOCKS_PER_SEC;
}
/*******************************************************************/
/* */
/* Init_Engine : */
/* */
/* Allocate bitmap, render pool and other structs... */
/* */
/*******************************************************************/
void Init_Engine()
{
Bit.rows = vio_Height; /* The whole window */
Bit.width = vio_Width;
if ( gray_render )
{
Bit.cols = Bit.width;
Bit.flow = TT_Flow_Up;
Bit.size = Bit.rows * Bit.width;
}
else
{
Bit.cols = (Bit.width + 7) / 8; /* convert to # of bytes */
Bit.flow = TT_Flow_Up;
Bit.size = Bit.rows * Bit.cols; /* number of bytes in buffer */
}
Bit.bitmap = (void*)malloc( Bit.size );
if ( !Bit.bitmap )
Panic( "ERROR: not enough memory to allocate bitmap!\n" );
SET_High_Precision( 0 );
/* set low precision */
SET_Second_Pass( 0 );
/* Disable horizontal drop-out control */
Clear_Buffer();
}
/*******************************************************************/
/* */
/* Clear_Buffer */
/* */
/* Clear current bitmap */
/* */
/*******************************************************************/
static void Clear_Buffer()
{
if ( gray_render )
memset( Bit.bitmap, gray_palette[0], Bit.size );
else
memset( Bit.bitmap, 0, Bit.size );
}
/*******************************************************************/
/* */
/* LoadTrueTypeChar */
/* */
/* Load a glyph into memory. */
/* */
/*******************************************************************/
TT_Error LoadTrueTypeChar( int idx )
{
short numP, numC;
TT_F26Dot6 *cx, *cy; /* current x and y arrays */
unsigned short* ccontour; /* current contour array */
unsigned char* ctouch; /* current touch array */
int j;
error = TT_Load_Glyph( instance, glyph, idx, TTLOAD_DEFAULT );
if (error)
return error;
TT_Get_Glyph_Outline( glyph, &outline );
/* debugging */
/*
if ( idx == 0 && !visual )
{
Message( "points = %d\n", outline.points );
for ( j = 0; j < outline.points; j++ )
Message( "%02x (%01hx,%01hx)\n",
j, outline.xCoord[j], outline.yCoord[j] );
Message( "\n" );
}
*/
numP = outline.points;
numC = outline.contours;
numP -= 2; /* get rid of phantom points */
start_point[cur_glyph] = cur_point;
num_points [cur_glyph] = numP;
start_contour[cur_glyph] = cur_contour;
num_contours [cur_glyph] = numC;
cx = cur_x + cur_point;
cy = cur_y + cur_point;
ctouch = cur_touch + cur_point;
ccontour = cur_endContour + cur_contour;
for ( j = 0; j < numP; j++ )
{
cx[j] = outline.xCoord[j] + vio_Width * 16 - 32;
cy[j] = outline.yCoord[j] + vio_Height * 16 - 32;
ctouch[j] = outline.flag[j];
}
for ( j = 0; j < numC; j++ )
{
ccontour[j] = outline.conStarts[j];
}
cur_point += numP;
cur_contour += numC;
cur_glyph++;
return TT_Err_Ok;
}
/*******************************************************************/
/* */
/* ConvertRaster */
/* */
/* Perform scan conversion */
/* */
/*******************************************************************/
TT_Error ConvertRaster( int index )
{
outline.xCoord = cur_x + start_point[index];
outline.yCoord = cur_y + start_point[index];
outline.flag = cur_touch + start_point[index];
outline.points = num_points[index];
outline.contours = num_contours[index];
outline.conStarts = cur_endContour + start_contour[index];
outline.dropout_mode = 2;
/* Note : for gray-levels, we use the default palette. */
/* Make up your own if necessary. */
if ( gray_render )
return RENDER_Gray_Glyph( &outline, &Bit, gray_palette );
else
return RENDER_Glyph( &outline, &Bit );
}
int main( int argc, char** argv )
{
int i, total, mode, base, rendered_glyphs;
char filename[128 + 4];
char alt_filename[128 + 4];
char* execname;
/* TEvent event; */
long t, t0, tz0;
execname = argv[0];
gray_render = 0;
visual = 0;
while ( argc > 1 && argv[1][0] == '-' )
{
switch (argv[1][1])
{
case 'g':
gray_render = 1;
break;
case 'v':
visual = 1;
break;
default:
Panic( "ERROR: unknown argument '%s'!\n", argv[1] );
}
argc--;
argv++;
}
if ( argc != 2 )
{
Message( "Time: simple performance timer - part of the FreeType project\n" );
Message( "-------------------------------------------------------------\n\n" );
Message( "Usage: %s [-g] [-v] fontname[.ttf|.ttc]\n\n", execname );
Message( " where '-g' asks for gray-levels rendering\n" );
Message( " '-v' displays while rendering (slower)\n" );
exit( 1 );
}
i = strlen( argv[1] );
while ( i > 0 && argv[1][i] != '\\' )
{
if ( argv[1][i] == '.' )
i = 0;
i--;
}
filename[128] = '\0';
alt_filename[128] = '\0';
strncpy( filename, argv[1], 128 );
strncpy( alt_filename, argv[1], 128 );
if ( i >= 0 )
{
strncpy( filename + strlen( filename ), ".ttf", 4 );
strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 );
}
/* Initialize engine */
if ( (error = TT_Init_FreeType()) )
Panic( "ERROR : While initializing engine, code = %d\n", error );
/* Load face */
error = TT_Open_Face( filename, &face );
if (error == TT_Err_Could_Not_Open_File)
{
strcpy( filename, alt_filename );
error = TT_Open_Face( alt_filename, &face );
}
if (error)
Panic( "ERROR: could not find/open %s\n", filename );
/* get face properties and allocate preload arrays */
TT_Get_Face_Properties( face, &properties );
num_glyphs = properties.num_Glyphs;
tab_glyphs = MAX_GLYPHS;
if ( tab_glyphs > num_glyphs ) tab_glyphs = num_glyphs;
max_points = properties.max_Points * tab_glyphs;
cur_x = malloc( max_points * sizeof ( TT_F26Dot6 ) );
cur_y = malloc( max_points * sizeof ( TT_F26Dot6 ) );
cur_touch = malloc( max_points );
max_contours = properties.max_Contours * tab_glyphs;
cur_endContour = (unsigned short*)malloc( max_contours * sizeof ( unsigned short ) );
if ( !cur_x || !cur_y || !cur_touch || !cur_endContour )
Panic( "Error: not enough memory for preload array\n" );
/* create glyph */
error = TT_New_Glyph( face, &glyph );
if (error)
Panic( "ERROR : could not create glyph container\n" );
/* create instance */
error = TT_New_Instance( face, &instance );
if (error)
Panic( "ERROR : could not create instance for %s\n", filename );
error = TT_Set_Instance_PointSize( instance, 400 );
if (error)
Panic( "ERROR : could not reset instance for %s\n", filename );
if ( gray_render )
mode = Graphics_Mode_Gray;
else
mode = Graphics_Mode_Mono;
if ( visual )
{
if ( !SetGraphScreen( mode ) )
Panic( "ERROR: could not set graphics mode\n" );
}
else
{
/* This is the default bitmap size used */
vio_Width = 640;
vio_Height = 450;
}
Init_Engine();
Num = 0;
Fail = 0;
total = num_glyphs;
base = 0;
rendered_glyphs = 0;
t0 = 0; /* Initial time */
tz0 = Get_Time();
while ( total > 0 )
{
/* First, preload 'tab_glyphs' in memory */
cur_glyph = 0;
cur_point = 0;
cur_contour = 0;
Message( "loading %d glyphs", tab_glyphs );
for ( Num = 0; Num < tab_glyphs; Num++ )
{
error = LoadTrueTypeChar( base + Num );
if (error)
Fail++;
total--;
}
base += tab_glyphs;
if ( tab_glyphs > total )
tab_glyphs = total;
Message( ", rendering... " );
/* Now, render the loaded glyphs */
t = Get_Time();
for ( Num = 0; Num < cur_glyph; Num++ )
{
if ( (error = ConvertRaster( Num )) )
Fail++;
else
{
rendered_glyphs ++;
if ( visual )
{
sprintf( Header, "Glyph : %5d", Num );
Display_Bitmap_On_Screen( Bit.bitmap, Bit.rows, Bit.cols );
/* Get_Event( &event ); */
Clear_Buffer();
}
}
}
t = Get_Time() - t;
if ( t < 0 ) t += 100 * 60 * 60;
Message( " = %f s\n", (double)t / 1000 );
t0 += t;
}
tz0 = Get_Time() - tz0;
if ( visual ) RestoreScreen();
TT_Close_Face( face );
Message( "\n" );
Message( "rendered glyphs = %d\n", rendered_glyphs );
Message( "render time = %f s\n", (double)t0 / 1000 );
Message( "fails = %d\n", Fail );
Message( "average glyphs/s = %f\n",
(double)rendered_glyphs / t0 * 1000 );
Message( "total timing = %f s\n", (double)tz0 / 1000 );
Message( "Fails = %d\n", Fail );
TT_Done_FreeType();
return 0;
}
/* End */