f0df85ba2a
A lot of internal modifications have been performed lately on the source in order to provide the following enhancements: - more generic module support: The FT_Module type is now defined to represent a handle to a given module. The file <freetype/ftmodule.h> contains the FT_Module_Class definition, as well as the module-loading public API The FT_Driver type is still defined, and still represents a pointer to a font driver. Note that FT_Add_Driver is replaced by FT_Add_Module, FT_Get_Driver by FT_Get_Module, etc.. - support for generic glyph image types: The FT_Renderer type is a pointer to a module used to perform various operations on glyph image. Each renderer is capable of handling images in a single format (e.g. ft_glyph_format_outline). Its functions are used to: - transform an glyph image - render a glyph image into a bitmap - return the control box (dimensions) of a given glyph image The scan converters "ftraster.c" and "ftgrays.c" have been moved to the new directory "src/renderer", and are used to provide two default renderer modules. One corresponds to the "standard" scan-converter, the other to the "smooth" one. The current renderer can be set through the new function FT_Set_Renderer. The old raster-related function FT_Set_Raster, FT_Get_Raster and FT_Set_Raster_Mode have now disappeared, in favor of the new: FT_Get_Renderer FT_Set_Renderer see the file <freetype/ftrender.h> for more details.. These changes were necessary to properly support different scalable formats in the future, like bi-color glyphs, etc.. - glyph loader object: A new internal object, called a 'glyph loader' has been introduced in the base layer. It is used by all scalable format font drivers to load glyphs and composites. This object has been created to reduce the code size of each driver, as each one of them basically re-implemented its functionality. See <freetype/internal/ftobjs.h> and the FT_GlyphLoader type for more information.. - FT_GlyphSlot had new fields: In order to support extended features (see below), the FT_GlyphSlot structure has a few new fields: linearHoriAdvance: this field gives the linearly scaled (i.e. scaled but unhinted) advance width for the glyph, expressed as a 16.16 fixed pixel value. This is useful to perform WYSIWYG text. linearVertAdvance: this field gives the linearly scaled advance height for the glyph (relevant in vertical glyph layouts only). This is useful to perform WYSIWYG text. Note that the two above field replace the removed "metrics2" field in the glyph slot. advance: this field is a vector that gives the transformed advance for the glyph. By default, it corresponds to the advance width, unless FT_LOAD_VERTICAL_LAYOUT was specified when calling FT_Load_Glyph or FT_Load_Char bitmap_left: this field gives the distance in integer pixels from the current pen position to the left-most pixel of a glyph image WHEN IT IS A BITMAP. It is only valid when the "format" field is set to "ft_glyph_format_bitmap", for example, after calling the new function FT_Render_Glyph. bitmap_top: this field gives the distance in integer pixels from the current pen position (located on the baseline) to the top-most pixel of the glyph image WHEN IT IS A BITMAP. Positive values correspond to upwards Y. loader: this is a new private field for the glyph slot. Client applications should not touch it.. - support for transforms and direct rendering in FT_Load_Glyph: Most of the functionality found in <freetype/ftglyph.h> has been moved to the core library. Hence, the following: - a transform can be specified for a face through FT_Set_Transform. this transform is applied by FT_Load_Glyph to scalable glyph images (i.e. NOT TO BITMAPS) before the function returns, unless the bit flag FT_LOAD_IGNORE_TRANSFORM was set in the load flags.. - once a glyph image has been loaded, it can be directly converted to a bitmap by using the new FT_Render_Glyph function. Note that this function takes the glyph image from the glyph slot, and converts it to a bitmap whose properties are returned in "face.glyph.bitmap", "face.glyph.bitmap_left" and "face.glyph.bitmap_top". The original native image might be lost after the conversion. - when using the new bit flag FT_LOAD_RENDER, the FT_Load_Glyph and FT_Load_Char functions will call FT_Render_Glyph automatically when needed.
844 lines
20 KiB
C
844 lines
20 KiB
C
/****************************************************************************/
|
|
/* */
|
|
/* The FreeType project -- a free and portable quality TrueType renderer. */
|
|
/* */
|
|
/* Copyright 1996-2000 by */
|
|
/* D. Turner, R.Wilhelm, and W. Lemberg */
|
|
/* */
|
|
/* */
|
|
/* FTView - a simple font viewer. */
|
|
/* */
|
|
/* This is a new version using the MiGS graphics subsystem for */
|
|
/* blitting and display. */
|
|
/* */
|
|
/* Press F1 when running this program to have a list of key-bindings */
|
|
/* */
|
|
/****************************************************************************/
|
|
|
|
|
|
#include <freetype/freetype.h>
|
|
#include <freetype/ftrender.h>
|
|
|
|
/* the following header shouldn't be used in normal programs */
|
|
#include <freetype/internal/ftdebug.h>
|
|
|
|
#include "common.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
|
|
#include "graph.h"
|
|
#include "grfont.h"
|
|
|
|
#define DIM_X 500
|
|
#define DIM_Y 400
|
|
|
|
#define CENTER_X ( bit.width / 2 )
|
|
#define CENTER_Y ( bit.rows / 2 )
|
|
|
|
#define MAXPTSIZE 500 /* dtp */
|
|
|
|
|
|
char Header[128];
|
|
char* new_header = 0;
|
|
|
|
const unsigned char* Text = (unsigned char*)
|
|
"The quick brown fox jumped over the lazy dog 0123456789 "
|
|
"\342\352\356\373\364\344\353\357\366\374\377\340\371\351\350\347 "
|
|
"&#~\"\'(-`_^@)=+\260 ABCDEFGHIJKLMNOPQRSTUVWXYZ "
|
|
"$\243^\250*\265\371%!\247:/;.,?<>";
|
|
|
|
FT_Library library; /* the FreeType library */
|
|
FT_Face face; /* the font face */
|
|
FT_Size size; /* the font size */
|
|
FT_GlyphSlot glyph; /* the glyph slot */
|
|
|
|
FT_Error error; /* error code returned by FreeType */
|
|
|
|
grSurface* surface; /* current display surface */
|
|
grBitmap bit; /* current display bitmap */
|
|
|
|
int num_glyphs; /* number of glyphs */
|
|
int ptsize; /* current point size */
|
|
|
|
int hinted = 1; /* is glyph hinting active? */
|
|
int antialias = 0; /* is anti-aliasing active? */
|
|
int use_sbits = 1; /* do we use embedded bitmaps? */
|
|
int low_prec = 0; /* force low precision */
|
|
int Num; /* current first glyph index */
|
|
|
|
int res = 72;
|
|
|
|
static grColor fore_color = { 255 };
|
|
|
|
int Fail;
|
|
|
|
int graph_init = 0;
|
|
|
|
int render_mode = 1;
|
|
int use_grays = 1;
|
|
int debug = 0;
|
|
int trace_level = 0;
|
|
|
|
/* the standard raster's interface */
|
|
FT_Renderer std_renderer;
|
|
FT_Renderer smooth_renderer;
|
|
|
|
|
|
#define RASTER_BUFF_SIZE 32768
|
|
char raster_buff[RASTER_BUFF_SIZE];
|
|
|
|
|
|
#define LOG( x ) LogMessage##x
|
|
|
|
static
|
|
void LogMessage( const char* fmt, ... )
|
|
{
|
|
va_list ap;
|
|
|
|
|
|
va_start( ap, fmt );
|
|
vfprintf( stderr, fmt, ap );
|
|
va_end( ap );
|
|
}
|
|
|
|
|
|
/* PanicZ */
|
|
static
|
|
void PanicZ( const char* message )
|
|
{
|
|
fprintf( stderr, "%s\n error = 0x%04x\n", message, error );
|
|
exit( 1 );
|
|
}
|
|
|
|
|
|
/* Clears the Bit bitmap/pixmap */
|
|
static
|
|
void Clear_Display( void )
|
|
{
|
|
long size = (long)bit.pitch * bit.rows;
|
|
|
|
|
|
if ( size < 0 )
|
|
size = -size;
|
|
memset( bit.buffer, 0, size );
|
|
}
|
|
|
|
|
|
/* Initialize the display bitmap `bit' */
|
|
static
|
|
void Init_Display( void )
|
|
{
|
|
grInitDevices();
|
|
|
|
bit.mode = gr_pixel_mode_gray;
|
|
bit.width = DIM_X;
|
|
bit.rows = DIM_Y;
|
|
bit.grays = 256;
|
|
|
|
surface = grNewSurface( 0, &bit );
|
|
if ( !surface )
|
|
PanicZ( "could not allocate display surface\n" );
|
|
|
|
graph_init = 1;
|
|
}
|
|
|
|
|
|
#define MAX_BUFFER 300000
|
|
|
|
#define FLOOR( x ) ( (x) & -64 )
|
|
#define CEIL( x ) ( ( (x) + 63 ) & -64 )
|
|
#define TRUNC( x ) ( (x) >> 6 )
|
|
|
|
static
|
|
char bit_buffer[MAX_BUFFER];
|
|
|
|
|
|
/* Render a single glyph with the `grays' component */
|
|
static
|
|
FT_Error Render_Glyph( int x_offset,
|
|
int y_offset )
|
|
{
|
|
/* first, render the glyph into an intermediate buffer */
|
|
FT_Bitmap bit2;
|
|
grBitmap bit3;
|
|
int width, height, pitch, size;
|
|
int left, right, top, bottom;
|
|
int x_top, y_top;
|
|
|
|
|
|
left = FLOOR( glyph->metrics.horiBearingX );
|
|
right = CEIL( glyph->metrics.horiBearingX + glyph->metrics.width );
|
|
width = TRUNC( right - left );
|
|
|
|
top = CEIL( glyph->metrics.horiBearingY );
|
|
bottom = FLOOR( glyph->metrics.horiBearingY - glyph->metrics.height );
|
|
height = TRUNC( top - bottom );
|
|
|
|
if ( glyph->format == ft_glyph_format_outline )
|
|
{
|
|
pitch = antialias ? ( width + 3 ) & -4
|
|
: ( width + 7 ) >> 3;
|
|
size = pitch * height;
|
|
|
|
if ( size > MAX_BUFFER )
|
|
return FT_Err_Out_Of_Memory;
|
|
|
|
bit2.width = width;
|
|
bit2.rows = height;
|
|
bit2.pitch = pitch;
|
|
bit2.pixel_mode = antialias ? ft_pixel_mode_grays : ft_pixel_mode_mono;
|
|
bit2.buffer = bit_buffer;
|
|
|
|
bit3.rows = bit2.rows;
|
|
bit3.width = bit2.width;
|
|
bit3.pitch = bit2.pitch;
|
|
bit3.mode = antialias ? bit.mode : gr_pixel_mode_mono;
|
|
bit3.buffer = bit_buffer;
|
|
bit3.grays = 256;
|
|
|
|
FT_Outline_Translate( &glyph->outline, -left, -bottom );
|
|
memset( bit_buffer, 0, size );
|
|
|
|
if ( low_prec )
|
|
glyph->outline.flags &= ~ft_outline_high_precision;
|
|
|
|
error = FT_Outline_Get_Bitmap( library, &glyph->outline, &bit2 );
|
|
}
|
|
else
|
|
{
|
|
bit3.rows = glyph->bitmap.rows;
|
|
bit3.width = glyph->bitmap.width;
|
|
bit3.pitch = glyph->bitmap.pitch;
|
|
bit3.mode = gr_pixel_mode_mono;
|
|
bit3.buffer = glyph->bitmap.buffer;
|
|
bit3.grays = 0;
|
|
}
|
|
|
|
/* Then, blit the image to the target surface */
|
|
x_top = x_offset + TRUNC( left );
|
|
y_top = y_offset - TRUNC( top );
|
|
|
|
#if 0
|
|
if ( bit.pitch < 0 )
|
|
y_top = bit.rows - y_top;
|
|
#endif
|
|
|
|
grBlitGlyphToBitmap( &bit, &bit3, x_top, y_top, fore_color );
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static
|
|
FT_Error Reset_Scale( int pointSize )
|
|
{
|
|
FT_Error error;
|
|
|
|
|
|
error = FT_Set_Char_Size( face, pointSize << 6,
|
|
pointSize << 6,
|
|
res,
|
|
res );
|
|
if ( error )
|
|
{
|
|
/* to be written */
|
|
}
|
|
|
|
return FT_Err_Ok;
|
|
}
|
|
|
|
|
|
static
|
|
FT_Error LoadChar( int idx,
|
|
int hint )
|
|
{
|
|
int flags;
|
|
|
|
|
|
flags = FT_LOAD_DEFAULT;
|
|
|
|
if ( !hint )
|
|
flags |= FT_LOAD_NO_HINTING;
|
|
|
|
if ( !use_sbits )
|
|
flags |= FT_LOAD_NO_BITMAP;
|
|
|
|
return FT_Load_Glyph( face, idx, flags );
|
|
}
|
|
|
|
|
|
static
|
|
FT_Error Render_All( int first_glyph,
|
|
int ptsize )
|
|
{
|
|
FT_F26Dot6 start_x, start_y, step_x, step_y, x, y;
|
|
int i;
|
|
|
|
FT_Error error;
|
|
|
|
|
|
start_x = 4;
|
|
start_y = 16 + ptsize ;
|
|
|
|
step_x = size->metrics.x_ppem + 4;
|
|
step_y = size->metrics.y_ppem + 10;
|
|
|
|
x = start_x;
|
|
y = start_y;
|
|
|
|
i = first_glyph;
|
|
|
|
#if 0
|
|
while ( i < first_glyph + 1 )
|
|
#else
|
|
while ( i < num_glyphs )
|
|
#endif
|
|
{
|
|
if ( !( error = LoadChar( i, hinted ) ) )
|
|
{
|
|
if ( debug && trace_level > 1 )
|
|
{
|
|
if ( i <= first_glyph + 6 )
|
|
{
|
|
LOG(( "metrics[%02d] = [%x %x]\n",
|
|
i,
|
|
glyph->metrics.horiBearingX,
|
|
glyph->metrics.horiAdvance ));
|
|
|
|
if ( i == first_glyph + 6 )
|
|
LOG(( "-------------------------\n" ));
|
|
}
|
|
}
|
|
|
|
Render_Glyph( x, y );
|
|
|
|
x += ( glyph->metrics.horiAdvance >> 6 ) + 1;
|
|
|
|
if ( x + size->metrics.x_ppem > bit.width )
|
|
{
|
|
x = start_x;
|
|
y += step_y;
|
|
|
|
if ( y >= bit.rows )
|
|
return FT_Err_Ok;
|
|
}
|
|
}
|
|
else
|
|
Fail++;
|
|
|
|
i++;
|
|
}
|
|
|
|
return FT_Err_Ok;
|
|
}
|
|
|
|
|
|
static
|
|
FT_Error Render_Text( int first_glyph,
|
|
int ptsize )
|
|
{
|
|
FT_F26Dot6 start_x, start_y, step_x, step_y, x, y;
|
|
int i;
|
|
|
|
FT_Error error;
|
|
const unsigned char* p;
|
|
|
|
|
|
start_x = 4;
|
|
start_y = 12 + size->metrics.y_ppem;
|
|
|
|
step_x = size->metrics.x_ppem + 4;
|
|
step_y = size->metrics.y_ppem + 10;
|
|
|
|
x = start_x;
|
|
y = start_y;
|
|
|
|
i = first_glyph;
|
|
p = Text;
|
|
while ( i > 0 && *p )
|
|
{
|
|
p++;
|
|
i--;
|
|
}
|
|
|
|
while ( *p )
|
|
{
|
|
if ( !( error = LoadChar( FT_Get_Char_Index( face,
|
|
(unsigned char)*p ),
|
|
hinted ) ) )
|
|
{
|
|
if ( debug && trace_level > 1 )
|
|
{
|
|
if ( i <= first_glyph + 6 )
|
|
{
|
|
LOG(( "metrics[%02d] = [%x %x]\n",
|
|
i,
|
|
glyph->metrics.horiBearingX,
|
|
glyph->metrics.horiAdvance ));
|
|
|
|
if ( i == first_glyph + 6 )
|
|
LOG(( "-------------------------\n" ));
|
|
}
|
|
}
|
|
|
|
Render_Glyph( x, y );
|
|
|
|
x += ( glyph->metrics.horiAdvance >> 6 ) + 1;
|
|
|
|
if ( x + size->metrics.x_ppem > bit.width )
|
|
{
|
|
x = start_x;
|
|
y += step_y;
|
|
|
|
if ( y >= bit.rows )
|
|
return FT_Err_Ok;
|
|
}
|
|
}
|
|
else
|
|
Fail++;
|
|
|
|
i++;
|
|
p++;
|
|
}
|
|
|
|
return FT_Err_Ok;
|
|
}
|
|
|
|
|
|
static
|
|
void Help( void )
|
|
{
|
|
grEvent dummy_event;
|
|
|
|
|
|
Clear_Display();
|
|
grGotoxy( 0, 0 );
|
|
grSetMargin( 2, 1 );
|
|
grGotobitmap( &bit );
|
|
|
|
grWriteln("FreeType Glyph Viewer - part of the FreeType test suite" );
|
|
grLn();
|
|
grWriteln("This program is used to display all glyphs from one or" );
|
|
grWriteln("several font files, with the FreeType library.");
|
|
grLn();
|
|
grWriteln("Use the following keys :");
|
|
grLn();
|
|
grWriteln(" F1 or ? : display this help screen" );
|
|
grWriteln(" a : toggle anti-aliasing" );
|
|
grWriteln(" h : toggle outline hinting" );
|
|
grWriteln(" b : toggle embedded bitmaps" );
|
|
grWriteln(" l : toggle low precision rendering" );
|
|
grWriteln(" g : toggle between `smooth' and `standard' anti-aliaser" );
|
|
grWriteln(" space : toggle rendering mode" );
|
|
grLn();
|
|
grWriteln(" Up : increase pointsize by 1 unit" );
|
|
grWriteln(" Down : decrease pointsize by 1 unit" );
|
|
grWriteln(" Page Up : increase pointsize by 10 units" );
|
|
grWriteln(" Page Down : decrease pointsize by 10 units" );
|
|
grLn();
|
|
grWriteln(" Right : increment first glyph index" );
|
|
grWriteln(" Left : decrement first glyph index" );
|
|
grLn();
|
|
grWriteln(" F7 : decrement first glyph index by 10" );
|
|
grWriteln(" F8 : increment first glyph index by 10" );
|
|
grWriteln(" F9 : decrement first glyph index by 100");
|
|
grWriteln(" F10 : increment first glyph index by 100");
|
|
grWriteln(" F11 : decrement first glyph index by 1000");
|
|
grWriteln(" F12 : increment first glyph index by 1000");
|
|
grLn();
|
|
grWriteln("press any key to exit this help screen");
|
|
|
|
grRefreshSurface( surface );
|
|
grListenSurface( surface, gr_event_key, &dummy_event );
|
|
}
|
|
|
|
|
|
static
|
|
void reset_raster( void )
|
|
{
|
|
if ( antialias && use_grays && smooth_renderer )
|
|
FT_Set_Renderer( library, smooth_renderer, 0, 0 );
|
|
else
|
|
FT_Set_Renderer( library, std_renderer, 0, 0 );
|
|
}
|
|
|
|
|
|
static
|
|
int Process_Event( grEvent* event )
|
|
{
|
|
int i;
|
|
|
|
|
|
switch ( event->key )
|
|
{
|
|
case grKeyEsc: /* ESC or q */
|
|
case grKEY( 'q' ):
|
|
return 0;
|
|
|
|
case grKEY( 'a' ):
|
|
antialias = !antialias;
|
|
new_header = antialias ? "anti-aliasing is now on"
|
|
: "anti-aliasing is now off";
|
|
reset_raster();
|
|
return 1;
|
|
|
|
case grKEY( 'b' ):
|
|
use_sbits = !use_sbits;
|
|
new_header = use_sbits
|
|
? "embedded bitmaps are now used when available"
|
|
: "embedded bitmaps are now ignored";
|
|
return 1;
|
|
|
|
case grKEY( 'n' ):
|
|
case grKEY( 'p' ):
|
|
return (int)event->key;
|
|
|
|
case grKEY( 'g' ):
|
|
use_grays = !use_grays;
|
|
new_header = use_grays
|
|
? "now using the smooth anti-aliaser"
|
|
: "now using the standard anti-aliaser";
|
|
reset_raster();
|
|
break;
|
|
|
|
case grKEY( 'l' ):
|
|
low_prec = !low_prec;
|
|
new_header = low_prec
|
|
? "rendering precision is now forced to low"
|
|
: "rendering precision is now normal";
|
|
break;
|
|
|
|
case grKEY( 'h' ):
|
|
hinted = !hinted;
|
|
new_header = hinted ? "glyph hinting is now active"
|
|
: "glyph hinting is now ignored";
|
|
break;
|
|
|
|
case grKEY( ' ' ):
|
|
render_mode ^= 1;
|
|
new_header = render_mode ? "rendering all glyphs in font"
|
|
: "rendering test text string" ;
|
|
break;
|
|
|
|
case grKeyF1:
|
|
case grKEY( '?' ):
|
|
Help();
|
|
return 1;
|
|
|
|
#if 0
|
|
case grKeyF3: i = 16; goto Do_Rotate;
|
|
case grKeyF4: i = -16; goto Do_Rotate;
|
|
case grKeyF5: i = 1; goto Do_Rotate;
|
|
case grKeyF6: i = -1; goto Do_Rotate;
|
|
#endif
|
|
|
|
case grKeyPageUp: i = 10; goto Do_Scale;
|
|
case grKeyPageDown: i = -10; goto Do_Scale;
|
|
case grKeyUp: i = 1; goto Do_Scale;
|
|
case grKeyDown: i = -1; goto Do_Scale;
|
|
|
|
case grKeyLeft: i = -1; goto Do_Glyph;
|
|
case grKeyRight: i = 1; goto Do_Glyph;
|
|
case grKeyF7: i = -10; goto Do_Glyph;
|
|
case grKeyF8: i = 10; goto Do_Glyph;
|
|
case grKeyF9: i = -100; goto Do_Glyph;
|
|
case grKeyF10: i = 100; goto Do_Glyph;
|
|
case grKeyF11: i = -1000; goto Do_Glyph;
|
|
case grKeyF12: i = 1000; goto Do_Glyph;
|
|
|
|
default:
|
|
;
|
|
}
|
|
return 1;
|
|
|
|
#if 0
|
|
Do_Rotate:
|
|
Rotation = ( Rotation + i ) & 1023;
|
|
return 1;
|
|
#endif
|
|
|
|
Do_Scale:
|
|
ptsize += i;
|
|
if ( ptsize < 1 ) ptsize = 1;
|
|
if ( ptsize > MAXPTSIZE ) ptsize = MAXPTSIZE;
|
|
return 1;
|
|
|
|
Do_Glyph:
|
|
Num += i;
|
|
if ( Num < 0 ) Num = 0;
|
|
if ( Num >= num_glyphs ) Num = num_glyphs - 1;
|
|
return 1;
|
|
}
|
|
|
|
|
|
static
|
|
void usage( char* execname )
|
|
{
|
|
fprintf( stderr, "\n" );
|
|
fprintf( stderr, "ftview: simple glyph viewer -- part of the FreeType project\n" );
|
|
fprintf( stderr, "-----------------------------------------------------------\n" );
|
|
fprintf( stderr, "\n" );
|
|
fprintf( stderr, "Usage: %s [options below] ppem fontname[.ttf|.ttc] ...\n",
|
|
execname );
|
|
fprintf( stderr, "\n" );
|
|
fprintf( stderr, " -d enable debugging messages\n" );
|
|
fprintf( stderr, " -l N set debugging trace level to N (default: 0, max: 7)\n" );
|
|
fprintf( stderr, " -r R use resolution R dpi (default: 72 dpi)\n" );
|
|
fprintf( stderr, " -f index specify first glyph index to display\n" );
|
|
fprintf( stderr, "\n" );
|
|
|
|
exit( 1 );
|
|
}
|
|
|
|
|
|
int main( int argc,
|
|
char* argv[] )
|
|
{
|
|
int i, old_ptsize, orig_ptsize, file;
|
|
int first_glyph = 0;
|
|
int XisSetup = 0;
|
|
char filename[128 + 4];
|
|
char alt_filename[128 + 4];
|
|
char* execname;
|
|
int option;
|
|
int file_loaded;
|
|
|
|
FT_Error error;
|
|
grEvent event;
|
|
|
|
|
|
execname = ft_basename( argv[0] );
|
|
|
|
while ( 1 )
|
|
{
|
|
option = getopt( argc, argv, "df:l:r:" );
|
|
|
|
if ( option == -1 )
|
|
break;
|
|
|
|
switch ( option )
|
|
{
|
|
case 'd':
|
|
debug = 1;
|
|
break;
|
|
|
|
case 'f':
|
|
first_glyph = atoi( optarg );
|
|
break;
|
|
|
|
case 'l':
|
|
trace_level = atoi( optarg );
|
|
if ( trace_level < 1 || trace_level > 7 )
|
|
usage( execname );
|
|
break;
|
|
|
|
case 'r':
|
|
res = atoi( optarg );
|
|
if ( res < 1 )
|
|
usage( execname );
|
|
break;
|
|
|
|
default:
|
|
usage( execname );
|
|
break;
|
|
}
|
|
}
|
|
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
if ( argc <= 1 )
|
|
usage( execname );
|
|
|
|
if ( sscanf( argv[0], "%d", &orig_ptsize ) != 1 )
|
|
orig_ptsize = 64;
|
|
|
|
file = 1;
|
|
|
|
if ( debug )
|
|
{
|
|
#ifdef FT_DEBUG_LEVEL_TRACE
|
|
FT_SetTraceLevel( trace_any, trace_level );
|
|
#else
|
|
trace_level = 0;
|
|
#endif
|
|
}
|
|
|
|
/* Initialize engine */
|
|
error = FT_Init_FreeType( &library );
|
|
if ( error )
|
|
PanicZ( "Could not initialize FreeType library" );
|
|
|
|
/* retrieve the standard raster's interface */
|
|
std_renderer = (FT_Renderer)FT_Get_Module( library, "standard renderer" );
|
|
if (!std_renderer)
|
|
PanicZ( "Could not retrieve standard renderer" );
|
|
|
|
smooth_renderer = (FT_Renderer)FT_Get_Module( library, "smooth renderer" );
|
|
|
|
NewFile:
|
|
ptsize = orig_ptsize;
|
|
hinted = 1;
|
|
file_loaded = 0;
|
|
|
|
filename[128] = '\0';
|
|
alt_filename[128] = '\0';
|
|
|
|
strncpy( filename, argv[file], 128 );
|
|
strncpy( alt_filename, argv[file], 128 );
|
|
|
|
/* try to load the file name as is, first */
|
|
error = FT_New_Face( library, argv[file], 0, &face );
|
|
if ( !error )
|
|
goto Success;
|
|
|
|
#ifndef macintosh
|
|
i = strlen( argv[file] );
|
|
while ( i > 0 && argv[file][i] != '\\' && argv[file][i] != '/' )
|
|
{
|
|
if ( argv[file][i] == '.' )
|
|
i = 0;
|
|
i--;
|
|
}
|
|
|
|
if ( i >= 0 )
|
|
{
|
|
strncpy( filename + strlen( filename ), ".ttf", 4 );
|
|
strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 );
|
|
}
|
|
#endif
|
|
|
|
/* Load face */
|
|
error = FT_New_Face( library, filename, 0, &face );
|
|
if ( error )
|
|
goto Display_Font;
|
|
|
|
Success:
|
|
file_loaded++;
|
|
|
|
error = Reset_Scale( ptsize );
|
|
if ( error )
|
|
goto Display_Font;
|
|
|
|
num_glyphs = face->num_glyphs;
|
|
glyph = face->glyph;
|
|
size = face->size;
|
|
|
|
Display_Font:
|
|
/* initialize graphics if needed */
|
|
if ( !XisSetup )
|
|
{
|
|
XisSetup = 1;
|
|
Init_Display();
|
|
}
|
|
|
|
grSetTitle( surface, "FreeType Glyph Viewer - press F1 for help" );
|
|
old_ptsize = ptsize;
|
|
|
|
if ( file_loaded >= 1 )
|
|
{
|
|
Fail = 0;
|
|
Num = first_glyph;
|
|
|
|
if ( Num >= num_glyphs )
|
|
Num = num_glyphs - 1;
|
|
|
|
if ( Num < 0 )
|
|
Num = 0;
|
|
}
|
|
|
|
for ( ;; )
|
|
{
|
|
int key;
|
|
|
|
|
|
Clear_Display();
|
|
|
|
if ( file_loaded >= 1 )
|
|
{
|
|
switch ( render_mode )
|
|
{
|
|
case 0:
|
|
Render_Text( Num, ptsize );
|
|
break;
|
|
|
|
default:
|
|
Render_All( Num, ptsize );
|
|
}
|
|
|
|
sprintf( Header, "%s %s (file `%s')",
|
|
face->family_name,
|
|
face->style_name,
|
|
ft_basename( filename ) );
|
|
|
|
if ( !new_header )
|
|
new_header = Header;
|
|
|
|
grWriteCellString( &bit, 0, 0, new_header, fore_color );
|
|
new_header = 0;
|
|
|
|
sprintf( Header, "at %d points, first glyph = %d",
|
|
ptsize,
|
|
Num );
|
|
}
|
|
else
|
|
sprintf( Header, "`%s': not a font file or could not be opened",
|
|
ft_basename( filename ) );
|
|
|
|
grWriteCellString( &bit, 0, 8, Header, fore_color );
|
|
grRefreshSurface( surface );
|
|
|
|
grListenSurface( surface, 0, &event );
|
|
if ( !( key = Process_Event( &event ) ) )
|
|
goto End;
|
|
|
|
if ( key == 'n' )
|
|
{
|
|
if (file_loaded >= 1)
|
|
FT_Done_Face( face );
|
|
|
|
if ( file < argc - 1 )
|
|
file++;
|
|
|
|
goto NewFile;
|
|
}
|
|
|
|
if ( key == 'p' )
|
|
{
|
|
if ( file_loaded >= 1 )
|
|
FT_Done_Face( face );
|
|
|
|
if ( file > 1 )
|
|
file--;
|
|
|
|
goto NewFile;
|
|
}
|
|
|
|
if ( ptsize != old_ptsize )
|
|
{
|
|
if ( Reset_Scale( ptsize ) )
|
|
PanicZ( "Could not resize font." );
|
|
|
|
old_ptsize = ptsize;
|
|
}
|
|
}
|
|
|
|
End:
|
|
#if 0
|
|
grDoneSurface(surface);
|
|
grDone();
|
|
#endif
|
|
|
|
printf( "Execution completed successfully.\n" );
|
|
printf( "Fails = %d\n", Fail );
|
|
|
|
exit( 0 ); /* for safety reasons */
|
|
return 0; /* never reached */
|
|
}
|
|
|
|
|
|
/* End */
|