#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "display.h"
#include "freetype.h"
#include "gevents.h"
#include "gdriver.h"
#include "gmain.h"
#define Pi 3.1415926535
#define MAXPTSIZE 500
#define Center_X ( Bit.width / 2 )
#define Center_Y ( Bit.rows / 2 )
char Header[128];
TT_Engine engine;
TT_Face face;
TT_Instance instance;
TT_Glyph glyph;
TT_CharMap char_map;
TT_Glyph_Metrics metrics;
TT_Outline outline;
TT_Face_Properties properties;
TT_Instance_Metrics imetrics;
int num_glyphs;
int ptsize;
int hinted;
int Rotation;
int Fail;
int Num;
unsigned char autorun;
int gray_render;
short glyph_code[128];
int num_codes;
static void CharToUnicode( char* source )
{
unsigned short i, n;
unsigned short platform, encoding;
n = properties.num_CharMaps;
for ( i = 0; i < n; i++ )
{
TT_Get_CharMap_ID( face, i, &platform, &encoding );
if ( (platform == 3 && encoding == 1 ) ||
(platform == 0 && encoding == 0 ) )
{
TT_Get_CharMap( face, i, &char_map );
i = n + 1;
}
}
if ( i == n )
Panic( "Sorry, but this font doesn't contain any Unicode mapping table\n" );
for ( n = 0; n < 128 && source[n]; n++ )
glyph_code[n] = TT_Char_Index( char_map, (short)source[n] );
#if 0
glyph_code[n] = TT_Char_Index( char_map, ToUnicode( source[n] ) );
#endif
num_codes = n;
}
static TT_Error Reset_Scale( int pointSize )
{
TT_Error error;
if ( (error = TT_Set_Instance_PointSize( instance, pointSize )) )
{
RestoreScreen();
printf( "error = 0x%x\n", (int)error );
Panic( "could not reset instance\n" );
}
TT_Get_Instance_Metrics( instance, &imetrics );
if ( gray_render )
{
Init_Small( imetrics.x_ppem, imetrics.y_ppem );
Clear_Small();
}
return TT_Err_Ok;
}
static TT_Error LoadTrueTypeChar( int idx, int hint )
{
int flags;
flags = TTLOAD_SCALE_GLYPH;
if ( hint )
flags |= TTLOAD_HINT_GLYPH;
return TT_Load_Glyph( instance, glyph, idx, flags );
}
static TT_Error Render_All( void )
{
TT_F26Dot6 x, y, z, minx, miny, maxx, maxy;
int i;
TT_Error error;
x = y = 0;
minx = miny = maxx = maxy = 0;
for ( i = 0; i < num_codes; i++ )
{
if ( !(error = LoadTrueTypeChar( glyph_code[i], hinted )) )
{
TT_Get_Glyph_Metrics( glyph, &metrics );
z = x + metrics.bbox.xMin;
if ( minx > z )
minx = z;
z = x + metrics.bbox.xMax;
if ( maxx < z )
maxx = z;
z = y + metrics.bbox.yMin;
if ( miny > z )
miny = z;
z = y + metrics.bbox.yMax;
if ( maxy < z )
maxy = z;
x += metrics.advance & -64;
}
else
Fail++;
}
minx = ( minx & -64 ) >> 6;
miny = ( miny & -64 ) >> 6;
maxx = ( (maxx+63) & -64 ) >> 6;
maxy = ( (maxy+63) & -64 ) >> 6;
maxx -= minx;
maxy -= miny;
minx = (Bit.width - maxx)/2;
miny = (Bit.rows + miny)/2;
maxx += minx;
maxy += maxy;
x = minx;
y = miny;
for ( i = 0; i < num_codes; i++ )
{
if ( !(error = LoadTrueTypeChar( glyph_code[i], hinted )) )
{
TT_Get_Glyph_Metrics( glyph, &metrics );
Render_Single_Glyph( gray_render, glyph, x, y );
x += metrics.advance/64;
}
}
return TT_Err_Ok;
}
static int Process_Event( TEvent* event )
{
switch ( event->what )
{
case event_Quit:
return 0;
case event_Keyboard:
if ( event->info == 'h' )
hinted = !hinted;
break;
case event_Rotate_Glyph:
break;
case event_Scale_Glyph:
ptsize += event->info;
if ( ptsize < 1 ) ptsize = 1;
if ( ptsize > MAXPTSIZE ) ptsize = MAXPTSIZE;
break;
case event_Change_Glyph:
break;
}
return 1;
}
static void usage( char* execname )
{
printf( "\n" );
printf( "ftstring: simple String Test Display -- part of the FreeType project\n" );
printf( "--------------------------------------------------------------------\n" );
printf( "\n" );
printf( "Usage: %s [options below] ppem fontname[.ttf|.ttc] [string]\n",
execname );
printf( "\n" );
printf( " -g gray-level rendering (default: none)\n" );
printf( " -r R use resolution R dpi (default: 96)\n" );
printf( "\n" );
exit( EXIT_FAILURE );
}
int main( int argc, char** argv )
{
int i, old_ptsize, orig_ptsize, file;
int XisSetup = 0;
char filename[128 + 4];
char alt_filename[128 + 4];
char* execname;
int option;
int res = 96;
TT_Error error;
TEvent event;
execname = argv[0];
while ( 1 )
{
option = ft_getopt( argc, argv, "gr:" );
if ( option == -1 )
break;
switch ( option )
{
case 'g':
gray_render = 1;
break;
case 'r':
res = atoi( ft_optarg );
if ( res < 1 )
usage( execname );
break;
default:
usage( execname );
break;
}
}
argc -= ft_optind;
argv += ft_optind;
if ( argc <= 1 )
usage( execname );
if ( sscanf( argv[0], "%d", &orig_ptsize ) != 1 )
orig_ptsize = 64;
file = 1;
if ( (error = TT_Init_FreeType( &engine )) )
Panic( "Error while initializing engine, code = 0x%x.\n", error );
ptsize = orig_ptsize;
hinted = 1;
i = strlen( argv[file] );
while ( i > 0 && argv[file][i] != '\\' && argv[file][i] != '/' )
{
if ( argv[file][i] == '.' )
i = 0;
i--;
}
filename[128] = '\0';
alt_filename[128] = '\0';
strncpy( filename, argv[file], 128 );
strncpy( alt_filename, argv[file], 128 );
if ( i >= 0 )
{
strncpy( filename + strlen( filename ), ".ttf", 4 );
strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 );
}
error = TT_Open_Face( engine, filename, &face );
if ( error == TT_Err_Could_Not_Open_File )
{
strcpy( filename, alt_filename );
error = TT_Open_Face( engine, alt_filename, &face );
}
if ( error == TT_Err_Could_Not_Open_File )
Panic( "Could not find/open %s.\n", filename );
else if (error)
Panic( "Error while opening %s, error code = 0x%x.\n",
filename, error );
TT_Get_Face_Properties( face, &properties );
num_glyphs = properties.num_Glyphs;
error = TT_New_Glyph( face, &glyph );
if ( error )
Panic( "Could not create glyph container.\n" );
error = TT_New_Instance( face, &instance );
if ( error )
Panic( "Could not create instance for %s.\n", filename );
error = TT_Set_Instance_Resolutions( instance, res, res );
if ( error )
Panic( "Could not set device resolutions." );
if ( !XisSetup )
{
XisSetup = 1;
if ( gray_render )
{
if ( !SetGraphScreen( Graphics_Mode_Gray ) )
Panic( "Could not set up grayscale graphics mode.\n" );
TT_Set_Raster_Gray_Palette( engine, virtual_palette );
}
else
{
if ( !SetGraphScreen( Graphics_Mode_Mono ) )
Panic( "Could not set up mono graphics mode.\n" );
}
}
Init_Display( gray_render );
Reset_Scale( ptsize );
old_ptsize = ptsize;
Fail = 0;
Num = 0;
CharToUnicode( ( argv[2] ? argv[2] :
"The quick brown fox jumps over the lazy dog" ) );
for ( ;; )
{
int key;
Clear_Display();
Render_All();
if ( gray_render )
Convert_To_Display_Palette();
sprintf( Header, "%s: ptsize: %4d hinting: %s",
ft_basename( filename ), ptsize,
hinted ? "on" : "off" );
Display_Bitmap_On_Screen( Bit.bitmap, Bit.rows, Bit.cols );
#ifndef X11
#ifndef OS2
Print_XY( 0, 0, Header );
#endif
#endif
Get_Event( &event );
if ( !( key = Process_Event( &event ) ) )
goto Fin;
if ( ptsize != old_ptsize )
{
if ( Reset_Scale( ptsize ) )
Panic( "Could not resize font.\n" );
old_ptsize = ptsize;
}
}
Fin:
RestoreScreen();
TT_Done_FreeType( engine );
printf( "Execution completed successfully.\n" );
printf( "Fails = %d.\n", Fail );
exit( EXIT_SUCCESS );
return 0;
}