FreeType 1.31.1
This commit is contained in:
486
test/ftstring.c
Normal file
486
test/ftstring.c
Normal file
@@ -0,0 +1,486 @@
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* The FreeType project -- a free and portable quality TrueType renderer. */
|
||||
/* */
|
||||
/* Copyright 1996-1999 by */
|
||||
/* D. Turner, R.Wilhelm, and W. Lemberg */
|
||||
/* */
|
||||
/* ftstring: Making string text from individual glyph information. */
|
||||
/* */
|
||||
/* Keys: */
|
||||
/* */
|
||||
/* + : fast scale up */
|
||||
/* - : fast scale down */
|
||||
/* u : fine scale down */
|
||||
/* j : fine scale up */
|
||||
/* */
|
||||
/* h : toggle hinting */
|
||||
/* */
|
||||
/* ESC : exit */
|
||||
/* */
|
||||
/* */
|
||||
/* NOTE: This is just a test program that is used to show off and */
|
||||
/* debug the current engine. */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common.h" /* for Panic() and Message() only */
|
||||
#include "display.h"
|
||||
#include "freetype.h"
|
||||
|
||||
#include "gevents.h"
|
||||
#include "gdriver.h"
|
||||
#include "gmain.h"
|
||||
|
||||
#define Pi 3.1415926535
|
||||
|
||||
#define MAXPTSIZE 500 /* dtp */
|
||||
#define Center_X ( Bit.width / 2 ) /* dtp */
|
||||
#define Center_Y ( Bit.rows / 2 ) /* dtp */
|
||||
|
||||
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;
|
||||
|
||||
/* Convert an ASCII string to a string of glyph indexes. */
|
||||
/* */
|
||||
/* IMPORTANT NOTE: */
|
||||
/* */
|
||||
/* There is no portable way to convert from any system's char. code */
|
||||
/* to Unicode. This function simply takes a char. string as argument */
|
||||
/* and "interprets" each character as a Unicode char. index with no */
|
||||
/* further check. */
|
||||
/* */
|
||||
/* This mapping is only valid for the ASCII character set (i.e., */
|
||||
/* codes 32 to 127); all other codes (like accentuated characters) */
|
||||
/* will produce more or less random results, depending on the system */
|
||||
/* being run. */
|
||||
|
||||
static void CharToUnicode( char* source )
|
||||
{
|
||||
unsigned short i, n;
|
||||
unsigned short platform, encoding;
|
||||
|
||||
/* First, look for a Unicode charmap */
|
||||
|
||||
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
|
||||
/* Note, if you have a function, say ToUnicode(), to convert from */
|
||||
/* char codes to Unicode, use the following line instead: */
|
||||
|
||||
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 );
|
||||
|
||||
/* now re-allocate the small bitmap */
|
||||
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;
|
||||
|
||||
|
||||
/* On the first pass, we compute the compound bounding box */
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
/* We now center the bbox inside the target bitmap */
|
||||
|
||||
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;
|
||||
|
||||
/* On the second pass, we render each glyph to its centered position. */
|
||||
/* This is slow, because we reload each glyph to render it! */
|
||||
|
||||
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: /* ESC or q */
|
||||
return 0;
|
||||
|
||||
case event_Keyboard:
|
||||
if ( event->info == 'h' ) /* Toggle hinting */
|
||||
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;
|
||||
|
||||
/* Initialize engine */
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
/* Load face */
|
||||
|
||||
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 );
|
||||
|
||||
/* get face properties and allocate preload arrays */
|
||||
|
||||
TT_Get_Face_Properties( face, &properties );
|
||||
|
||||
num_glyphs = properties.num_Glyphs;
|
||||
|
||||
/* create glyph */
|
||||
|
||||
error = TT_New_Glyph( face, &glyph );
|
||||
if ( error )
|
||||
Panic( "Could not create glyph container.\n" );
|
||||
|
||||
/* create instance */
|
||||
|
||||
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 ); /* for safety reasons */
|
||||
|
||||
return 0; /* never reached */
|
||||
}
|
||||
|
||||
|
||||
/* End */
|
||||
Reference in New Issue
Block a user