Skip to content
Commits on Source (26)
......@@ -11,8 +11,8 @@ WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
of the stable FreeType 2 source packages from our server, you most
probably have to rename its directory, for example:
mv freetype-2.13.0 freetype on Unix
rename freetype-2.13.0 freetype on Windows
mv freetype-2.13.1 freetype on Unix
rename freetype-2.13.1 freetype on Windows
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
......
......@@ -167,7 +167,7 @@ grDevice gr_beos_device =
init_device,
done_device,
(grDeviceInitSurfaceFunc) Window::init_surface,
Window::init_surface,
0,
0
......
......@@ -154,9 +154,9 @@
}
static
void listen_event( grSurface* surface,
int event_mask,
grEvent* grevent )
int listen_event( grSurface* surface,
int event_mask,
grEvent* grevent )
{
grEvent our_grevent;
EventRecord mac_event;
......@@ -200,7 +200,7 @@
/* destroy the window here, since done_surface() doesn't get called */
done_window();
*grevent = our_grevent;
return;
return 1;
case updateEvt:
if ( theWindow && (WindowPtr)mac_event.message == theWindow )
{
......@@ -243,7 +243,7 @@
our_grevent.type = gr_event_key;
our_grevent.key = grKeyEsc;
*grevent = our_grevent;
return;
return 1;
}
}
else if (part == inContent)
......@@ -265,6 +265,7 @@
}
}
}
return 0;
}
......@@ -359,10 +360,10 @@ grSurface* init_surface( grSurface* surface,
theWindow = NewCWindow(NULL, &bounds, "\p???", 1, 0, (WindowRef)-1, 1, 0);
/* fill in surface interface */
surface->done = (grDoneSurfaceFunc) done_surface;
surface->refresh_rect = (grRefreshRectFunc) refresh_rectangle;
surface->set_title = (grSetTitleFunc) set_title;
surface->listen_event = (grListenEventFunc) listen_event;
surface->done = done_surface;
surface->refresh_rect = refresh_rectangle;
surface->set_title = set_title;
surface->listen_event = listen_event;
return surface;
}
......@@ -386,7 +387,7 @@ grSurface* init_surface( grSurface* surface,
init_device,
done_device,
(grDeviceInitSurfaceFunc) init_surface,
init_surface,
0,
0
......
......@@ -170,8 +170,11 @@
/* close a given window */
static
void done_surface( grPMSurface* surface )
void done_surface( grSurface* baseSurface )
{
grPMSurface* surface = (grPMSurface*)baseSurface;
LOG(( "Os2PM: done_surface(%08lx)\n", (long)surface ));
if ( surface->frame_window )
......@@ -260,12 +263,15 @@
static
void refresh_rectangle( grPMSurface* surface,
int x,
int y,
int w,
int h )
void refresh_rectangle( grSurface* baseSurface,
int x,
int y,
int w,
int h )
{
grPMSurface* surface = (grPMSurface*)baseSurface;
LOG(( "Os2PM: refresh_rectangle( %08lx, %d, %d, %d, %d )\n",
(long)surface, x, y, w, h ));
......@@ -291,10 +297,11 @@
static
void set_title( grPMSurface* surface,
void set_title( grSurface* baseSurface,
const char* title )
{
ULONG rc;
grPMSurface* surface = (grPMSurface*)baseSurface;
ULONG rc;
#if 1
LOG(( "Os2PM: set_title( %08lx == %08lx, %s )\n",
......@@ -311,11 +318,12 @@
static
void listen_event( grPMSurface* surface,
int event_mask,
grEvent* grevent )
int listen_event( grSurface* baseSurface,
int event_mask,
grEvent* grevent )
{
ULONG ulRequestCount;
grPMSurface* surface = (grPMSurface*)baseSurface;
ULONG ulRequestCount;
(void) event_mask; /* ignored for now */
......@@ -325,14 +333,15 @@
*grevent = surface->event;
DosResetEventSem( surface->event_lock, &ulRequestCount );
return;
return 1;
}
static
grPMSurface* init_surface( grPMSurface* surface,
grBitmap* bitmap )
grPMSurface* init_surface( grSurface* baseSurface,
grBitmap* bitmap )
{
grPMSurface* surface = (grPMSurface*)baseSurface;
PBITMAPINFO2 bit;
SIZEL sizl = { 0, 0 };
LONG palette[256];
......@@ -474,10 +483,10 @@
LOCK(surface->image_lock);
UNLOCK(surface->image_lock);
surface->root.done = (grDoneSurfaceFunc) done_surface;
surface->root.refresh_rect = (grRefreshRectFunc) refresh_rectangle;
surface->root.set_title = (grSetTitleFunc) set_title;
surface->root.listen_event = (grListenEventFunc) listen_event;
surface->root.done = done_surface;
surface->root.refresh_rect = refresh_rectangle;
surface->root.set_title = set_title;
surface->root.listen_event = listen_event;
/* convert_rectangle( surface, 0, 0, bitmap->width, bitmap->rows ); */
return surface;
......@@ -743,7 +752,7 @@
init_device,
done_device,
(grDeviceInitSurfaceFunc) init_surface,
init_surface,
0,
0
......
......@@ -110,8 +110,11 @@
/* destroys the surface*/
static void
gr_win32_surface_done( grWin32Surface* surface )
gr_win32_surface_done( grSurface* baseSurface )
{
grWin32Surface* surface = (grWin32Surface*)baseSurface;
/* The graphical window has perhaps already destroyed itself */
if ( surface->window )
{
......@@ -134,15 +137,17 @@ gr_win32_surface_done( grWin32Surface* surface )
static void
gr_win32_surface_refresh_rectangle(
grWin32Surface* surface,
int x,
int y,
int w,
int h )
grSurface* baseSurface,
int x,
int y,
int w,
int h )
{
int delta;
RECT rect;
grBitmap* bitmap = &surface->root.bitmap;
grWin32Surface* surface = (grWin32Surface*)baseSurface;
int delta;
RECT rect;
grBitmap* bitmap = &surface->root.bitmap;
LOG(( "gr_win32_surface_refresh_rectangle: ( %p, %d, %d, %d, %d )\n",
surface->root.bitmap.buffer, x, y, w, h ));
......@@ -234,21 +239,25 @@ gr_win32_surface_refresh_rectangle(
static void
gr_win32_surface_set_title( grWin32Surface* surface,
const char* title )
gr_win32_surface_set_title( grSurface* baseSurface,
const char* title )
{
grWin32Surface* surface = (grWin32Surface*)baseSurface;
SetWindowText( surface->window, title );
}
static int
gr_win32_surface_set_icon( grWin32Surface* surface,
grBitmap* icon )
gr_win32_surface_set_icon( grSurface* baseSurface,
grBitmap* icon )
{
int s[] = { GetSystemMetrics( SM_CYSMICON ),
GetSystemMetrics( SM_CYICON ) };
WPARAM wParam;
HICON hIcon;
grWin32Surface* surface = (grWin32Surface*)baseSurface;
int s[] = { GetSystemMetrics( SM_CYSMICON ),
GetSystemMetrics( SM_CYICON ) };
WPARAM wParam;
HICON hIcon;
if ( !icon )
return s[1];
......@@ -330,12 +339,13 @@ gr_win32_surface_resize( grWin32Surface* surface,
return 1;
}
static void
gr_win32_surface_listen_event( grWin32Surface* surface,
int event_mask,
grEvent* grevent )
static int
gr_win32_surface_listen_event( grSurface* baseSurface,
int event_mask,
grEvent* grevent )
{
MSG msg;
grWin32Surface* surface = (grWin32Surface*)baseSurface;
MSG msg;
event_mask=event_mask; /* unused parameter */
......@@ -359,7 +369,7 @@ gr_win32_surface_listen_event( grWin32Surface* surface,
grevent->type = gr_event_resize;
grevent->x = width;
grevent->y = height;
return;
return 1;
}
}
break;
......@@ -373,11 +383,13 @@ gr_win32_surface_listen_event( grWin32Surface* surface,
? "KeyPress: Char = '%c'\n"
: "KeyPress: Char = <%02x>\n",
msg.wParam ));
return;
return 1;
}
break;
}
}
return 0;
}
......@@ -427,10 +439,11 @@ DWORD WINAPI Window_ThreadProc( LPVOID lpParameter )
static int
gr_win32_surface_init( grWin32Surface* surface,
grBitmap* bitmap )
gr_win32_surface_init( grSurface* baseSurface,
grBitmap* bitmap )
{
MSG msg;
grWin32Surface* surface = (grWin32Surface*)baseSurface;
MSG msg;
/* Set default mode */
......@@ -546,11 +559,11 @@ gr_win32_surface_init( grWin32Surface* surface,
goto Fail;
/* wrap up */
surface->root.done = (grDoneSurfaceFunc) gr_win32_surface_done;
surface->root.refresh_rect = (grRefreshRectFunc) gr_win32_surface_refresh_rectangle;
surface->root.set_title = (grSetTitleFunc) gr_win32_surface_set_title;
surface->root.set_icon = (grSetIconFunc) gr_win32_surface_set_icon;
surface->root.listen_event = (grListenEventFunc) gr_win32_surface_listen_event;
surface->root.done = gr_win32_surface_done;
surface->root.refresh_rect = gr_win32_surface_refresh_rectangle;
surface->root.set_title = gr_win32_surface_set_title;
surface->root.set_icon = gr_win32_surface_set_icon;
surface->root.listen_event = gr_win32_surface_listen_event;
LOG(( "Surface initialized: %dx%dx%d\n",
surface->root.bitmap.width, surface->root.bitmap.rows,
......@@ -559,7 +572,7 @@ gr_win32_surface_init( grWin32Surface* surface,
return 1;
Fail:
gr_win32_surface_done( surface );
gr_win32_surface_done( &surface->root );
return 0;
}
......@@ -696,7 +709,7 @@ LRESULT CALLBACK Message_Process( HWND handle, UINT mess,
gr_win32_device_init,
gr_win32_device_done,
(grDeviceInitSurfaceFunc) gr_win32_surface_init,
gr_win32_surface_init,
0,
0
......
......@@ -965,9 +965,10 @@
/* close a given window */
static void
gr_x11_surface_done( grX11Surface* surface )
gr_x11_surface_done( grSurface* baseSurface )
{
Display* display = surface->display;
grX11Surface* surface = (grX11Surface*)baseSurface;
Display* display = surface->display;
if ( display )
......@@ -992,13 +993,14 @@
static void
gr_x11_surface_refresh_rect( grX11Surface* surface,
int x,
int y,
int w,
int h )
gr_x11_surface_refresh_rect( grSurface* baseSurface,
int x,
int y,
int w,
int h )
{
grX11Blitter blit;
grX11Surface* surface = (grX11Surface*)baseSurface;
grX11Blitter blit;
if ( surface->convert &&
......@@ -1015,17 +1017,21 @@
static void
gr_x11_surface_set_title( grX11Surface* surface,
const char* title )
gr_x11_surface_set_title( grSurface* baseSurface,
const char* title )
{
grX11Surface* surface = (grX11Surface*)baseSurface;
XStoreName( surface->display, surface->win, title );
}
static int
gr_x11_surface_set_icon( grX11Surface* surface,
grBitmap* icon )
gr_x11_surface_set_icon( grSurface* baseSurface,
grBitmap* icon )
{
grX11Surface* surface = (grX11Surface*)baseSurface;
const unsigned char* s = (const unsigned char*)"\x80\x40\x20\x10";
unsigned long* buffer;
unsigned long* dst;
......@@ -1151,17 +1157,18 @@
static int
gr_x11_surface_listen_event( grX11Surface* surface,
int event_mask,
grEvent* grevent )
gr_x11_surface_listen_event( grSurface* baseSurface,
int event_mask,
grEvent* grevent )
{
Display* display = surface->display;
XEvent x_event;
XExposeEvent exposed;
KeySym key;
grX11Surface* surface = (grX11Surface*)baseSurface;
Display* display = surface->display;
XEvent x_event;
XExposeEvent exposed;
KeySym key;
int num;
grKey grkey;
int num;
grKey grkey;
/* XXX: for now, ignore the event mask, and only exit when */
/* a key is pressed */
......@@ -1289,11 +1296,11 @@
static int
gr_x11_surface_init( grX11Surface* surface,
grBitmap* bitmap )
gr_x11_surface_init( grSurface* baseSurface,
grBitmap* bitmap )
{
Display* display;
grX11Surface* surface = (grX11Surface*)baseSurface;
Display* display;
surface->key_number = 0;
surface->key_cursor = 0;
......@@ -1447,11 +1454,11 @@
(unsigned char *)&pid, 1 );
}
surface->root.done = (grDoneSurfaceFunc)gr_x11_surface_done;
surface->root.refresh_rect = (grRefreshRectFunc)gr_x11_surface_refresh_rect;
surface->root.set_title = (grSetTitleFunc) gr_x11_surface_set_title;
surface->root.set_icon = (grSetIconFunc) gr_x11_surface_set_icon;
surface->root.listen_event = (grListenEventFunc)gr_x11_surface_listen_event;
surface->root.done = gr_x11_surface_done;
surface->root.refresh_rect = gr_x11_surface_refresh_rect;
surface->root.set_title = gr_x11_surface_set_title;
surface->root.set_icon = gr_x11_surface_set_icon;
surface->root.listen_event = gr_x11_surface_listen_event;
return 1;
}
......@@ -1465,7 +1472,7 @@
gr_x11_device_init,
gr_x11_device_done,
(grDeviceInitSurfaceFunc) gr_x11_surface_init,
gr_x11_surface_init,
0,
0
......
'\" t
.TH FTBENCH 1 "February 2023" "FreeType 2.13.0"
.TH FTBENCH 1 "June 2023" "FreeType 2.13.1"
.
.
.SH NAME
......@@ -27,6 +27,12 @@ This program is part of the FreeType demos package.
.SH OPTIONS
.
.TP
.BI "\-a\ \(dq" "axis1\ axis2\ .\|.\|." \(dq
For Multiple Master, GX, or OpenType variation fonts, specify design
coordinates for each axis at start-up.
Ignored for all other font formats.
.
.TP
.BI \-b \ tests
Perform chosen tests:
.
......
.TH FTDIFF 1 "February 2023" "FreeType 2.13.0"
.TH FTDIFF 1 "June 2023" "FreeType 2.13.1"
.
.
.SH NAME
......
.TH FTDUMP 1 "February 2023" "FreeType 2.13.0"
.TH FTDUMP 1 "June 2023" "FreeType 2.13.1"
.
.
.SH NAME
......
.TH FTGAMMA 1 "February 2023" "FreeType 2.13.0"
.TH FTGAMMA 1 "June 2023" "FreeType 2.13.1"
.
.
.SH NAME
......
.TH FTGRID 1 "February 2023" "FreeType 2.13.0"
.TH FTGRID 1 "June 2023" "FreeType 2.13.1"
.
.
.SH NAME
......
.TH FTLINT 1 "February 2023" "FreeType 2.13.0"
.TH FTLINT 1 "June 2023" "FreeType 2.13.1"
.
.
.SH NAME
......
.TH FTMULTI 1 "February 2023" "FreeType 2.13.0"
.TH FTMULTI 1 "June 2023" "FreeType 2.13.1"
.
.
.SH NAME
......
.TH FTSDF 1 "February 2023" "FreeType 2.13.0"
.TH FTSDF 1 "June 2023" "FreeType 2.13.1"
.
.
.SH NAME
......
.TH FTSTRING 1 "February 2023" "FreeType 2.13.0"
.TH FTSTRING 1 "June 2023" "FreeType 2.13.1"
.
.
.SH NAME
......
.TH FTVALID 1 "February 2023" "FreeType 2.13.0"
.TH FTVALID 1 "June 2023" "FreeType 2.13.1"
.
.
.SH NAME
......
.TH FTVIEW 1 "February 2023" "FreeType 2.13.0"
.TH FTVIEW 1 "June 2023" "FreeType 2.13.1"
.
.
.SH NAME
......@@ -81,6 +81,7 @@ for rendering.
Set start-up rendering mode (0 <=
.I mode
<= 6).
This corresponds to the keystrokes 'A' to 'G' within the program.
.
.TP
.BI \-L \ W1 , W2 , W3 , W4 , W5
......
.TH TTDEBUG 1 "February 2023" "FreeType 2.13.0"
.TH TTDEBUG 1 "June 2023" "FreeType 2.13.1"
.
.
.SH NAME
......
......@@ -17,7 +17,7 @@
# possible since the subproject might not be cloned yet, so we have to
# hard-code the string.
project('freetype-demos', 'c', 'cpp',
version: '2.13.0')
version: '2.13.1')
# Access to the FreeType 2 source tree is required, since some of the demo
......
......@@ -29,11 +29,14 @@
#include <freetype/ftdriver.h>
#include <freetype/ftglyph.h>
#include <freetype/ftlcdfil.h>
#include <freetype/ftmm.h>
#include <freetype/ftmodapi.h>
#include <freetype/ftoutln.h>
#include <freetype/ftstroke.h>
#include <freetype/ftsynth.h>
#define MAX_MM_AXES 16
#ifdef UNIX
#include <unistd.h>
#else
......@@ -105,6 +108,11 @@
static FTC_SBitCache sbit_cache;
static FTC_ImageTypeRec font_type;
static FT_MM_Var* multimaster = NULL;
static FT_Fixed design_pos [MAX_MM_AXES];
static FT_Fixed requested_pos[MAX_MM_AXES];
static unsigned int requested_cnt = 0;
static unsigned int used_num_axes = 0;
enum {
FT_BENCH_LOAD_GLYPH,
......@@ -172,7 +180,7 @@
/*
* Dummy face requester (the face object is already loaded)
* Face requester for cache testing
*/
static FT_Error
......@@ -183,10 +191,9 @@
{
FT_UNUSED( face_id );
FT_UNUSED( library );
FT_UNUSED( request_data );
*aface = (FT_Face)request_data;
return FT_Err_Ok;
return get_face( aface );
}
......@@ -269,13 +276,6 @@
if ( test->cache_first )
{
if ( !cache_man )
{
printf( " %-25s no cache manager\n", test->title );
return;
}
TIMER_RESET( &timer );
test->bench( &timer, face, test->user_data );
}
......@@ -444,10 +444,9 @@
FOREACH( i )
{
if ( FT_Load_Glyph( face, (FT_UInt)i, load_flags ) )
continue;
if ( FT_Get_Glyph( face->glyph, &glyph ) )
if ( FT_Load_Glyph( face, (FT_UInt)i, load_flags ) ||
face->glyph->format != FT_GLYPH_FORMAT_OUTLINE ||
FT_Get_Glyph( face->glyph, &glyph ) )
continue;
TIMER_START( timer );
......@@ -589,12 +588,6 @@
FT_UNUSED( face );
if ( !cmap_cache )
{
if ( FTC_CMapCache_New( cache_man, &cmap_cache ) )
return 0;
}
TIMER_START( timer );
for ( i = 0; i < charset->size; i++ )
......@@ -625,12 +618,6 @@
FT_UNUSED( user_data );
if ( !image_cache )
{
if ( FTC_ImageCache_New( cache_man, &image_cache ) )
return 0;
}
TIMER_START( timer );
FOREACH( i )
......@@ -662,12 +649,6 @@
FT_UNUSED( user_data );
if ( !sbit_cache )
{
if ( FTC_SBitCache_New( cache_man, &sbit_cache ) )
return 0;
}
TIMER_START( timer );
FOREACH( i )
......@@ -952,6 +933,49 @@
if ( error )
fprintf( stderr, "couldn't load font resource\n");
/* Set up MM_Var. */
if ( requested_cnt != 0 )
{
unsigned int n;
error = FT_Get_MM_Var( *face, &multimaster );
if ( error )
{
fprintf( stderr, "couldn't load MultiMaster info\n" );
return error;
}
used_num_axes = multimaster->num_axis;
for ( n = 0; n < used_num_axes; n++ )
{
FT_Var_Axis* a = multimaster->axis + n;
design_pos[n] = n < requested_cnt ? requested_pos[n] : a->def;
if ( design_pos[n] < a->minimum )
design_pos[n] = a->minimum;
else if ( design_pos[n] > a->maximum )
design_pos[n] = a->maximum;
if ( !FT_IS_SFNT( *face ) )
design_pos[n] = FT_RoundFix( design_pos[n] );
}
error = FT_Set_Var_Design_Coordinates( *face,
used_num_axes,
design_pos );
if ( error )
{
fprintf( stderr, "couldn't set design coordinates\n" );
return error;
}
FT_Done_MM_Var( lib, multimaster );
}
return error;
}
......@@ -1050,6 +1074,21 @@
#define TEST( x ) ( !test_string || strchr( test_string, (x) ) )
static void
parse_design_coords( char *s )
{
for ( requested_cnt = 0;
requested_cnt < MAX_MM_AXES && *s;
requested_cnt++ )
{
requested_pos[requested_cnt] = (FT_Fixed)( strtod( s, &s ) * 65536.0 );
while ( *s==' ' )
++s;
}
}
int
main( int argc,
char** argv )
......@@ -1062,7 +1101,6 @@
unsigned int size = FACE_SIZE;
int max_iter = 0;
double max_time = BENCH_TIME;
int compare_cached = 0;
int j;
unsigned int versions[2] = { TT_INTERPRETER_VERSION_35,
......@@ -1134,19 +1172,27 @@
int opt;
opt = getopt( argc, argv, "b:Cc:e:f:H:I:i:l:m:pr:s:t:v" );
opt = getopt( argc, argv, "a:b:Cc:e:f:H:I:i:l:m:pr:s:t:v" );
if ( opt == -1 )
break;
switch ( opt )
{
case 'a':
parse_design_coords( optarg );
break;
case 'b':
test_string = optarg;
break;
case 'C':
compare_cached = 1;
FTC_Manager_New( lib,
0, 0, max_bytes,
face_requester,
NULL,
&cache_man );
break;
case 'c':
......@@ -1360,18 +1406,13 @@
}
}
FTC_Manager_New( lib,
0,
0,
max_bytes,
face_requester,
face,
&cache_man );
font_type.face_id = (FTC_FaceID)1;
font_type.width = size;
font_type.height = size;
font_type.flags = load_flags;
if ( cache_man )
{
font_type.face_id = (FTC_FaceID)1;
font_type.width = size;
font_type.height = size;
font_type.flags = load_flags;
}
printf( "\n"
"font preloading into memory: %s\n"
......@@ -1412,20 +1453,26 @@
test.bench = test_load;
benchmark( face, &test, max_iter, max_time );
if ( compare_cached )
if ( cache_man )
{
test.cache_first = 1;
test.title = "Load (image cached)";
test.bench = test_image_cache;
benchmark( face, &test, max_iter, max_time );
test.title = "Load (sbit cached)";
test.bench = test_sbit_cache;
if ( size )
if ( !FTC_ImageCache_New( cache_man, &image_cache ) )
{
test.title = "Load (image cached)";
test.bench = test_image_cache;
benchmark( face, &test, max_iter, max_time );
else
printf( " %-25s disabled (size = 0)\n", test.title );
}
if ( !FTC_SBitCache_New( cache_man, &sbit_cache ) )
{
test.title = "Load (sbit cached)";
test.bench = test_sbit_cache;
if ( size )
benchmark( face, &test, max_iter, max_time );
else
printf( " %-25s disabled (size = 0)\n", test.title );
}
}
break;
......@@ -1476,7 +1523,7 @@
FT_Matrix rot30 = { 0xDDB4, -0x8000, 0x8000, 0xDDB4 };
/* rotate outlines by 30 degrees so that CBox and BBox are different */
/* rotate outlines by 30 degrees so that CBox and BBox differ */
FT_Set_Transform( face, &rot30, NULL );
benchmark( face, &test, max_iter, max_time );
FT_Set_Transform( face, NULL, NULL );
......@@ -1499,7 +1546,8 @@
benchmark( face, &test, max_iter, max_time );
if ( compare_cached )
if ( cache_man &&
!FTC_CMapCache_New( cache_man, &cmap_cache ) )
{
test.cache_first = 1;
......@@ -1551,25 +1599,11 @@
}
}
Exit:
/* The following is a bit subtle: When we call FTC_Manager_Done, this
* normally destroys all FT_Face objects that the cache might have
* created by calling the face requester.
*
* However, this little benchmark uses a tricky face requester that
* doesn't create a new FT_Face through FT_New_Face but simply passes a
* pointer to the one that was previously created.
*
* If the cache manager has been used before, the call to
* FTC_Manager_Done discards our single FT_Face.
*
* In the case where no cache manager is in place, or if no test was
* run, the call to FT_Done_FreeType releases any remaining FT_Face
* object anyway.
*/
if ( cache_man )
FTC_Manager_Done( cache_man );
Exit:
/* releases any remaining FT_Face object too */
FT_Done_FreeType( lib );
return 0;
......