📄 ftmulti.c
字号:
/****************************************************************************/
/* */
/* The FreeType project -- a free and portable quality TrueType renderer. */
/* */
/* Copyright 1996-2000, 2003, 2004, 2005 by */
/* D. Turner, R.Wilhelm, and W. Lemberg */
/* */
/* */
/* FTMulti- a simple multiple masters font viewer */
/* */
/* Press F1 when running this program to have a list of key-bindings */
/* */
/****************************************************************************/
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_MULTIPLE_MASTERS_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 jumps 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_Encoding encoding = FT_ENCODING_NONE;
FT_Error error; /* error 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 = 1; /* 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;
unsigned char autorun;
int graph_init = 0;
int render_mode = 1;
int use_grays = 1;
FT_MM_Var *multimaster = NULL;
FT_Fixed design_pos [T1_MAX_MM_AXIS];
FT_Fixed requested_pos[T1_MAX_MM_AXIS];
int requested_cnt = 0;
#define RASTER_BUFF_SIZE 32768
char raster_buff[RASTER_BUFF_SIZE];
#define DEBUGxxx
#ifdef DEBUG
#define LOG( x ) LogMessage##x
#else
#define LOG( x ) /* empty */
#endif
#ifdef DEBUG
static void
LogMessage( const char* fmt, ... )
{
va_list ap;
va_start( ap, fmt );
vfprintf( stderr, fmt, ap );
va_end( ap );
}
#endif
/* PanicZ */
static void
PanicZ( const char* message )
{
fprintf( stderr, "%s\n error = 0x%04x\n", message, error );
exit( 1 );
}
static unsigned long
make_tag( char *s )
{
int i;
unsigned long l = 0;
for ( i = 0; i < 4; i++ )
{
if ( !s[i] )
break;
l <<= 8;
l += (unsigned long)s[i];
}
return l;
}
static void
parse_design_coords( char *s )
{
for ( requested_cnt = 0; requested_cnt < T1_MAX_MM_AXIS && *s;
requested_cnt++ )
{
requested_pos[requested_cnt] = (FT_Fixed)( strtod( s, &s ) * 65536.0 );
while ( *s==' ' )
++s;
}
}
/* Clears the Bit bitmap/pixmap */
static void
Clear_Display( void )
{
long bitmap_size = (long)bit.pitch * bit.rows;
if ( bitmap_size < 0 )
bitmap_size = -bitmap_size;
memset( bit.buffer, 0, bitmap_size );
}
/* Initialize the display bitmap named `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 FLOOR( x ) ( (x) & -64 )
#define CEIL( x ) ( ( (x) + 63 ) & -64 )
#define TRUNC( x ) ( (x) >> 6 )
/* Render a single glyph with the `grays' component */
static FT_Error
Render_Glyph( int x_offset,
int y_offset )
{
grBitmap bit3;
FT_Pos x_top, y_top;
/* first, render the glyph image into a bitmap */
if ( glyph->format != FT_GLYPH_FORMAT_BITMAP )
{
error = FT_Render_Glyph( glyph, antialias ? FT_RENDER_MODE_NORMAL
: FT_RENDER_MODE_MONO );
if ( error )
return error;
}
/* now blit it to our display screen */
bit3.rows = glyph->bitmap.rows;
bit3.width = glyph->bitmap.width;
bit3.pitch = glyph->bitmap.pitch;
bit3.buffer = glyph->bitmap.buffer;
switch ( glyph->bitmap.pixel_mode )
{
case FT_PIXEL_MODE_MONO:
bit3.mode = gr_pixel_mode_mono;
bit3.grays = 0;
break;
case FT_PIXEL_MODE_GRAY:
bit3.mode = gr_pixel_mode_gray;
bit3.grays = glyph->bitmap.num_grays;
}
/* Then, blit the image to the target surface */
x_top = x_offset + glyph->bitmap_left;
y_top = y_offset - glyph->bitmap_top;
grBlitGlyphToBitmap( &bit, &bit3, x_top, y_top, fore_color );
return 0;
}
static void
Reset_Scale( int pointSize )
{
(void)FT_Set_Char_Size( face, pointSize << 6, pointSize << 6, res, res );
}
static FT_Error
LoadChar( int idx,
int hint )
{
int flags;
flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
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 pt_size )
{
FT_F26Dot6 start_x, start_y, step_x, step_y, x, y;
int i;
start_x = 4;
start_y = 36 + pt_size;
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 ) ) )
{
#ifdef DEBUG
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" ));
}
#endif
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 )
{
FT_F26Dot6 start_x, start_y, step_x, step_y, x, y;
int i;
const unsigned char* p;
start_x = 4;
start_y = 32 + 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 ) ) )
{
#ifdef DEBUG
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" ));
}
#endif
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 Multiple Masters Glyph Viewer - part of the FreeType test suite" );
grLn();
grWriteln( "This program is used to display all glyphs from one or" );
grWriteln( "several Multiple Masters 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( " space : toggle rendering mode" );
grLn();
grWriteln( " n : next font" );
grWriteln( " p : previous font" );
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( " F3 : decrement first axis pos by 1/50th of its range" );
grWriteln( " F4 : increment first axis pos by 1/50th of its range" );
grWriteln( " F5 : decrement second axis pos by 1/50th of its range" );
grWriteln( " F6 : increment second axis pos by 1/50th of its range" );
grWriteln( " F7 : decrement third axis pos by 1/50th of its range" );
grWriteln( " F8 : increment third axis pos by 1/50th of its range" );
grWriteln( " F9 : decrement index by 100" );
grWriteln( " F10 : increment index by 100" );
grWriteln( " F11 : decrement index by 1000" );
grWriteln( " F12 : increment index by 1000" );
grLn();
grWriteln( "press any key to exit this help screen" );
grRefreshSurface( surface );
grListenSurface( surface, gr_event_key, &dummy_event );
}
static int
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -