mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-18 20:15:35 -04:00
C client: Now gets slightly further before crashing in release mode
This commit is contained in:
parent
af821dacdf
commit
cdd45b3259
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include "freetype/ft2build.h"
|
#include "freetype/ft2build.h"
|
||||||
#include "freetype/freetype.h"
|
#include "freetype/freetype.h"
|
||||||
|
#include "freetype/ftsnames.h"
|
||||||
|
#include "freetype/ftmodapi.h"
|
||||||
|
|
||||||
#if CC_BUILD_WIN
|
#if CC_BUILD_WIN
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
@ -691,7 +693,6 @@ void Waitable_WaitFor(void* handle, UInt32 milliseconds) {
|
|||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*--------------------------------------------------------Font/Text--------------------------------------------------------*
|
*--------------------------------------------------------Font/Text--------------------------------------------------------*
|
||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
#include "freetype\ftsnames.h"
|
|
||||||
FT_Library lib;
|
FT_Library lib;
|
||||||
StringsBuffer norm_fonts, bold_fonts;
|
StringsBuffer norm_fonts, bold_fonts;
|
||||||
static void Font_Init(void);
|
static void Font_Init(void);
|
||||||
@ -852,14 +853,38 @@ Size2D Platform_TextDraw(struct DrawTextArgs* args, Bitmap* bmp, Int32 x, Int32
|
|||||||
s.Width = x - s.Width; return s;
|
s.Width = x - s.Width; return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CC_BUILD_WIN
|
struct FT_MemoryRec_ ft_mem;
|
||||||
|
static void* FT_AllocWrapper(FT_Memory memory, long size) {
|
||||||
|
return Mem_Alloc(size, 1, "Freetype data");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FT_FreeWrapper(FT_Memory memory, void* block) {
|
||||||
|
Mem_Free(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* FT_ReallocWrapper(FT_Memory memory, long cur_size, long new_size, void* block) {
|
||||||
|
return Mem_Realloc(block, new_size, 1, "Freetype data");
|
||||||
|
}
|
||||||
|
|
||||||
static void Font_Init(void) {
|
static void Font_Init(void) {
|
||||||
FT_Error err = FT_Init_FreeType(&lib);
|
ft_mem.alloc = FT_AllocWrapper;
|
||||||
|
ft_mem.free = FT_FreeWrapper;
|
||||||
|
ft_mem.realloc = FT_ReallocWrapper;
|
||||||
|
|
||||||
|
FT_Error err = FT_New_Library(&ft_mem, &lib);
|
||||||
|
if (err) ErrorHandler_Fail2(err, "Failed to init freetype");
|
||||||
|
|
||||||
|
FT_Add_Default_Modules(lib);
|
||||||
|
FT_Set_Default_Properties(lib);
|
||||||
|
|
||||||
|
#if CC_BUILD_WIN
|
||||||
String dir = String_FromConst("C:\\Windows\\fonts");
|
String dir = String_FromConst("C:\\Windows\\fonts");
|
||||||
|
#elif CC_BUILD_NIX
|
||||||
|
String dir = String_FromConst("usr/share/fonts");
|
||||||
|
#endif
|
||||||
Directory_Enum(&dir, NULL, Font_DirCallback);
|
Directory_Enum(&dir, NULL, Font_DirCallback);
|
||||||
}
|
}
|
||||||
#elif CC_BUILD_NIX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
|
@ -175,438 +175,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef FT_DEBUG_AUTOFIT
|
|
||||||
|
|
||||||
#include FT_CONFIG_STANDARD_LIBRARY_H
|
|
||||||
|
|
||||||
/* The dump functions are used in the `ftgrid' demo program, too. */
|
|
||||||
#define AF_DUMP( varformat ) \
|
|
||||||
do \
|
|
||||||
{ \
|
|
||||||
if ( to_stdout ) \
|
|
||||||
printf varformat; \
|
|
||||||
else \
|
|
||||||
FT_TRACE7( varformat ); \
|
|
||||||
} while ( 0 )
|
|
||||||
|
|
||||||
|
|
||||||
static const char*
|
|
||||||
af_dir_str( AF_Direction dir )
|
|
||||||
{
|
|
||||||
const char* result;
|
|
||||||
|
|
||||||
|
|
||||||
switch ( dir )
|
|
||||||
{
|
|
||||||
case AF_DIR_UP:
|
|
||||||
result = "up";
|
|
||||||
break;
|
|
||||||
case AF_DIR_DOWN:
|
|
||||||
result = "down";
|
|
||||||
break;
|
|
||||||
case AF_DIR_LEFT:
|
|
||||||
result = "left";
|
|
||||||
break;
|
|
||||||
case AF_DIR_RIGHT:
|
|
||||||
result = "right";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
result = "none";
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define AF_INDEX_NUM( ptr, base ) (int)( (ptr) ? ( (ptr) - (base) ) : -1 )
|
|
||||||
|
|
||||||
|
|
||||||
static char*
|
|
||||||
af_print_idx( char* p,
|
|
||||||
int idx )
|
|
||||||
{
|
|
||||||
if ( idx == -1 )
|
|
||||||
{
|
|
||||||
p[0] = '-';
|
|
||||||
p[1] = '-';
|
|
||||||
p[2] = '\0';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ft_sprintf( p, "%d", idx );
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
af_get_segment_index( AF_GlyphHints hints,
|
|
||||||
int point_idx,
|
|
||||||
int dimension )
|
|
||||||
{
|
|
||||||
AF_AxisHints axis = &hints->axis[dimension];
|
|
||||||
AF_Point point = hints->points + point_idx;
|
|
||||||
AF_Segment segments = axis->segments;
|
|
||||||
AF_Segment limit = segments + axis->num_segments;
|
|
||||||
AF_Segment segment;
|
|
||||||
|
|
||||||
|
|
||||||
for ( segment = segments; segment < limit; segment++ )
|
|
||||||
{
|
|
||||||
if ( segment->first <= segment->last )
|
|
||||||
{
|
|
||||||
if ( point >= segment->first && point <= segment->last )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AF_Point p = segment->first;
|
|
||||||
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if ( point == p )
|
|
||||||
goto Exit;
|
|
||||||
|
|
||||||
if ( p == segment->last )
|
|
||||||
break;
|
|
||||||
|
|
||||||
p = p->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Exit:
|
|
||||||
if ( segment == limit )
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return (int)( segment - segments );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
af_get_edge_index( AF_GlyphHints hints,
|
|
||||||
int segment_idx,
|
|
||||||
int dimension )
|
|
||||||
{
|
|
||||||
AF_AxisHints axis = &hints->axis[dimension];
|
|
||||||
AF_Edge edges = axis->edges;
|
|
||||||
AF_Segment segment = axis->segments + segment_idx;
|
|
||||||
|
|
||||||
|
|
||||||
return segment_idx == -1 ? -1 : AF_INDEX_NUM( segment->edge, edges );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
void
|
|
||||||
af_glyph_hints_dump_points( AF_GlyphHints hints,
|
|
||||||
FT_Bool to_stdout )
|
|
||||||
{
|
|
||||||
AF_Point points = hints->points;
|
|
||||||
AF_Point limit = points + hints->num_points;
|
|
||||||
AF_Point* contour = hints->contours;
|
|
||||||
AF_Point* climit = contour + hints->num_contours;
|
|
||||||
AF_Point point;
|
|
||||||
|
|
||||||
|
|
||||||
AF_DUMP(( "Table of points:\n" ));
|
|
||||||
|
|
||||||
if ( hints->num_points )
|
|
||||||
{
|
|
||||||
AF_DUMP(( " index hedge hseg vedge vseg flags "
|
|
||||||
/* " XXXXX XXXXX XXXXX XXXXX XXXXX XXXXXX" */
|
|
||||||
" xorg yorg xscale yscale xfit yfit" ));
|
|
||||||
/* " XXXXX XXXXX XXXX.XX XXXX.XX XXXX.XX XXXX.XX" */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
AF_DUMP(( " (none)\n" ));
|
|
||||||
|
|
||||||
for ( point = points; point < limit; point++ )
|
|
||||||
{
|
|
||||||
int point_idx = AF_INDEX_NUM( point, points );
|
|
||||||
int segment_idx_0 = af_get_segment_index( hints, point_idx, 0 );
|
|
||||||
int segment_idx_1 = af_get_segment_index( hints, point_idx, 1 );
|
|
||||||
|
|
||||||
char buf1[16], buf2[16], buf3[16], buf4[16];
|
|
||||||
|
|
||||||
|
|
||||||
/* insert extra newline at the beginning of a contour */
|
|
||||||
if ( contour < climit && *contour == point )
|
|
||||||
{
|
|
||||||
AF_DUMP(( "\n" ));
|
|
||||||
contour++;
|
|
||||||
}
|
|
||||||
|
|
||||||
AF_DUMP(( " %5d %5s %5s %5s %5s %s"
|
|
||||||
" %5d %5d %7.2f %7.2f %7.2f %7.2f\n",
|
|
||||||
point_idx,
|
|
||||||
af_print_idx( buf1,
|
|
||||||
af_get_edge_index( hints, segment_idx_1, 1 ) ),
|
|
||||||
af_print_idx( buf2, segment_idx_1 ),
|
|
||||||
af_print_idx( buf3,
|
|
||||||
af_get_edge_index( hints, segment_idx_0, 0 ) ),
|
|
||||||
af_print_idx( buf4, segment_idx_0 ),
|
|
||||||
( point->flags & AF_FLAG_NEAR )
|
|
||||||
? " near "
|
|
||||||
: ( point->flags & AF_FLAG_WEAK_INTERPOLATION )
|
|
||||||
? " weak "
|
|
||||||
: "strong",
|
|
||||||
|
|
||||||
point->fx,
|
|
||||||
point->fy,
|
|
||||||
point->ox / 64.0,
|
|
||||||
point->oy / 64.0,
|
|
||||||
point->x / 64.0,
|
|
||||||
point->y / 64.0 ));
|
|
||||||
}
|
|
||||||
AF_DUMP(( "\n" ));
|
|
||||||
}
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static const char*
|
|
||||||
af_edge_flags_to_string( FT_UInt flags )
|
|
||||||
{
|
|
||||||
static char temp[32];
|
|
||||||
int pos = 0;
|
|
||||||
|
|
||||||
|
|
||||||
if ( flags & AF_EDGE_ROUND )
|
|
||||||
{
|
|
||||||
ft_memcpy( temp + pos, "round", 5 );
|
|
||||||
pos += 5;
|
|
||||||
}
|
|
||||||
if ( flags & AF_EDGE_SERIF )
|
|
||||||
{
|
|
||||||
if ( pos > 0 )
|
|
||||||
temp[pos++] = ' ';
|
|
||||||
ft_memcpy( temp + pos, "serif", 5 );
|
|
||||||
pos += 5;
|
|
||||||
}
|
|
||||||
if ( pos == 0 )
|
|
||||||
return "normal";
|
|
||||||
|
|
||||||
temp[pos] = '\0';
|
|
||||||
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Dump the array of linked segments. */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
void
|
|
||||||
af_glyph_hints_dump_segments( AF_GlyphHints hints,
|
|
||||||
FT_Bool to_stdout )
|
|
||||||
{
|
|
||||||
FT_Int dimension;
|
|
||||||
|
|
||||||
|
|
||||||
for ( dimension = 1; dimension >= 0; dimension-- )
|
|
||||||
{
|
|
||||||
AF_AxisHints axis = &hints->axis[dimension];
|
|
||||||
AF_Point points = hints->points;
|
|
||||||
AF_Edge edges = axis->edges;
|
|
||||||
AF_Segment segments = axis->segments;
|
|
||||||
AF_Segment limit = segments + axis->num_segments;
|
|
||||||
AF_Segment seg;
|
|
||||||
|
|
||||||
char buf1[16], buf2[16], buf3[16];
|
|
||||||
|
|
||||||
|
|
||||||
AF_DUMP(( "Table of %s segments:\n",
|
|
||||||
dimension == AF_DIMENSION_HORZ ? "vertical"
|
|
||||||
: "horizontal" ));
|
|
||||||
if ( axis->num_segments )
|
|
||||||
{
|
|
||||||
AF_DUMP(( " index pos delta dir from to "
|
|
||||||
/* " XXXXX XXXXX XXXXX XXXXX XXXX XXXX" */
|
|
||||||
" link serif edge"
|
|
||||||
/* " XXXX XXXXX XXXX" */
|
|
||||||
" height extra flags\n" ));
|
|
||||||
/* " XXXXXX XXXXX XXXXXXXXXXX" */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
AF_DUMP(( " (none)\n" ));
|
|
||||||
|
|
||||||
for ( seg = segments; seg < limit; seg++ )
|
|
||||||
AF_DUMP(( " %5d %5d %5d %5s %4d %4d"
|
|
||||||
" %4s %5s %4s"
|
|
||||||
" %6d %5d %11s\n",
|
|
||||||
AF_INDEX_NUM( seg, segments ),
|
|
||||||
seg->pos,
|
|
||||||
seg->delta,
|
|
||||||
af_dir_str( (AF_Direction)seg->dir ),
|
|
||||||
AF_INDEX_NUM( seg->first, points ),
|
|
||||||
AF_INDEX_NUM( seg->last, points ),
|
|
||||||
|
|
||||||
af_print_idx( buf1, AF_INDEX_NUM( seg->link, segments ) ),
|
|
||||||
af_print_idx( buf2, AF_INDEX_NUM( seg->serif, segments ) ),
|
|
||||||
af_print_idx( buf3, AF_INDEX_NUM( seg->edge, edges ) ),
|
|
||||||
|
|
||||||
seg->height,
|
|
||||||
seg->height - ( seg->max_coord - seg->min_coord ),
|
|
||||||
af_edge_flags_to_string( seg->flags ) ));
|
|
||||||
AF_DUMP(( "\n" ));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Fetch number of segments. */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
FT_Error
|
|
||||||
af_glyph_hints_get_num_segments( AF_GlyphHints hints,
|
|
||||||
FT_Int dimension,
|
|
||||||
FT_Int* num_segments )
|
|
||||||
{
|
|
||||||
AF_Dimension dim;
|
|
||||||
AF_AxisHints axis;
|
|
||||||
|
|
||||||
|
|
||||||
dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT;
|
|
||||||
|
|
||||||
axis = &hints->axis[dim];
|
|
||||||
*num_segments = axis->num_segments;
|
|
||||||
|
|
||||||
return FT_Err_Ok;
|
|
||||||
}
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Fetch offset of segments into user supplied offset array. */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
FT_Error
|
|
||||||
af_glyph_hints_get_segment_offset( AF_GlyphHints hints,
|
|
||||||
FT_Int dimension,
|
|
||||||
FT_Int idx,
|
|
||||||
FT_Pos *offset,
|
|
||||||
FT_Bool *is_blue,
|
|
||||||
FT_Pos *blue_offset )
|
|
||||||
{
|
|
||||||
AF_Dimension dim;
|
|
||||||
AF_AxisHints axis;
|
|
||||||
AF_Segment seg;
|
|
||||||
|
|
||||||
|
|
||||||
if ( !offset )
|
|
||||||
return FT_THROW( Invalid_Argument );
|
|
||||||
|
|
||||||
dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT;
|
|
||||||
|
|
||||||
axis = &hints->axis[dim];
|
|
||||||
|
|
||||||
if ( idx < 0 || idx >= axis->num_segments )
|
|
||||||
return FT_THROW( Invalid_Argument );
|
|
||||||
|
|
||||||
seg = &axis->segments[idx];
|
|
||||||
*offset = ( dim == AF_DIMENSION_HORZ ) ? seg->first->fx
|
|
||||||
: seg->first->fy;
|
|
||||||
if ( seg->edge )
|
|
||||||
*is_blue = (FT_Bool)( seg->edge->blue_edge != 0 );
|
|
||||||
else
|
|
||||||
*is_blue = FALSE;
|
|
||||||
|
|
||||||
if ( *is_blue )
|
|
||||||
*blue_offset = seg->edge->blue_edge->org;
|
|
||||||
else
|
|
||||||
*blue_offset = 0;
|
|
||||||
|
|
||||||
return FT_Err_Ok;
|
|
||||||
}
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Dump the array of linked edges. */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
void
|
|
||||||
af_glyph_hints_dump_edges( AF_GlyphHints hints,
|
|
||||||
FT_Bool to_stdout )
|
|
||||||
{
|
|
||||||
FT_Int dimension;
|
|
||||||
|
|
||||||
|
|
||||||
for ( dimension = 1; dimension >= 0; dimension-- )
|
|
||||||
{
|
|
||||||
AF_AxisHints axis = &hints->axis[dimension];
|
|
||||||
AF_Edge edges = axis->edges;
|
|
||||||
AF_Edge limit = edges + axis->num_edges;
|
|
||||||
AF_Edge edge;
|
|
||||||
|
|
||||||
char buf1[16], buf2[16];
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
|
|
||||||
* since they have a constant X coordinate.
|
|
||||||
*/
|
|
||||||
if ( dimension == AF_DIMENSION_HORZ )
|
|
||||||
AF_DUMP(( "Table of %s edges (1px=%.2fu, 10u=%.2fpx):\n",
|
|
||||||
"vertical",
|
|
||||||
65536.0 * 64.0 / hints->x_scale,
|
|
||||||
10.0 * hints->x_scale / 65536.0 / 64.0 ));
|
|
||||||
else
|
|
||||||
AF_DUMP(( "Table of %s edges (1px=%.2fu, 10u=%.2fpx):\n",
|
|
||||||
"horizontal",
|
|
||||||
65536.0 * 64.0 / hints->y_scale,
|
|
||||||
10.0 * hints->y_scale / 65536.0 / 64.0 ));
|
|
||||||
|
|
||||||
if ( axis->num_edges )
|
|
||||||
{
|
|
||||||
AF_DUMP(( " index pos dir link serif"
|
|
||||||
/* " XXXXX XXXX.XX XXXXX XXXX XXXXX" */
|
|
||||||
" blue opos pos flags\n" ));
|
|
||||||
/* " X XXXX.XX XXXX.XX XXXXXXXXXXX" */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
AF_DUMP(( " (none)\n" ));
|
|
||||||
|
|
||||||
for ( edge = edges; edge < limit; edge++ )
|
|
||||||
AF_DUMP(( " %5d %7.2f %5s %4s %5s"
|
|
||||||
" %c %7.2f %7.2f %11s\n",
|
|
||||||
AF_INDEX_NUM( edge, edges ),
|
|
||||||
(int)edge->opos / 64.0,
|
|
||||||
af_dir_str( (AF_Direction)edge->dir ),
|
|
||||||
af_print_idx( buf1, AF_INDEX_NUM( edge->link, edges ) ),
|
|
||||||
af_print_idx( buf2, AF_INDEX_NUM( edge->serif, edges ) ),
|
|
||||||
|
|
||||||
edge->blue_edge ? 'y' : 'n',
|
|
||||||
edge->opos / 64.0,
|
|
||||||
edge->pos / 64.0,
|
|
||||||
af_edge_flags_to_string( edge->flags ) ));
|
|
||||||
AF_DUMP(( "\n" ));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#undef AF_DUMP
|
|
||||||
|
|
||||||
#endif /* !FT_DEBUG_AUTOFIT */
|
|
||||||
|
|
||||||
|
|
||||||
/* Compute the direction value of a given vector. */
|
/* Compute the direction value of a given vector. */
|
||||||
|
|
||||||
FT_LOCAL_DEF( AF_Direction )
|
FT_LOCAL_DEF( AF_Direction )
|
||||||
|
@ -21,38 +21,6 @@
|
|||||||
#include "afloader.h"
|
#include "afloader.h"
|
||||||
#include "aferrors.h"
|
#include "aferrors.h"
|
||||||
|
|
||||||
#ifdef FT_DEBUG_AUTOFIT
|
|
||||||
|
|
||||||
#ifndef FT_MAKE_OPTION_SINGLE_OBJECT
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
extern void
|
|
||||||
af_glyph_hints_dump_segments( AF_GlyphHints hints,
|
|
||||||
FT_Bool to_stdout );
|
|
||||||
extern void
|
|
||||||
af_glyph_hints_dump_points( AF_GlyphHints hints,
|
|
||||||
FT_Bool to_stdout );
|
|
||||||
extern void
|
|
||||||
af_glyph_hints_dump_edges( AF_GlyphHints hints,
|
|
||||||
FT_Bool to_stdout );
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int _af_debug_disable_horz_hints;
|
|
||||||
int _af_debug_disable_vert_hints;
|
|
||||||
int _af_debug_disable_blue_hints;
|
|
||||||
|
|
||||||
/* we use a global object instead of a local one for debugging */
|
|
||||||
AF_GlyphHintsRec _af_debug_hints_rec[1];
|
|
||||||
|
|
||||||
void* _af_debug_hints = _af_debug_hints_rec;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include FT_INTERNAL_OBJECTS_H
|
#include FT_INTERNAL_OBJECTS_H
|
||||||
#include FT_INTERNAL_DEBUG_H
|
#include FT_INTERNAL_DEBUG_H
|
||||||
#include FT_DRIVER_H
|
#include FT_DRIVER_H
|
||||||
@ -469,11 +437,6 @@
|
|||||||
af_autofitter_done( FT_Module ft_module ) /* AF_Module */
|
af_autofitter_done( FT_Module ft_module ) /* AF_Module */
|
||||||
{
|
{
|
||||||
FT_UNUSED( ft_module );
|
FT_UNUSED( ft_module );
|
||||||
|
|
||||||
#ifdef FT_DEBUG_AUTOFIT
|
|
||||||
if ( _af_debug_hints_rec->memory )
|
|
||||||
af_glyph_hints_done( _af_debug_hints_rec );
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -487,42 +450,6 @@
|
|||||||
FT_Error error = FT_Err_Ok;
|
FT_Error error = FT_Err_Ok;
|
||||||
FT_Memory memory = module->root.library->memory;
|
FT_Memory memory = module->root.library->memory;
|
||||||
|
|
||||||
#ifdef FT_DEBUG_AUTOFIT
|
|
||||||
|
|
||||||
/* in debug mode, we use a global object that survives this routine */
|
|
||||||
|
|
||||||
AF_GlyphHints hints = _af_debug_hints_rec;
|
|
||||||
AF_LoaderRec loader[1];
|
|
||||||
|
|
||||||
FT_UNUSED( size );
|
|
||||||
|
|
||||||
|
|
||||||
if ( hints->memory )
|
|
||||||
af_glyph_hints_done( hints );
|
|
||||||
|
|
||||||
af_glyph_hints_init( hints, memory );
|
|
||||||
af_loader_init( loader, hints );
|
|
||||||
|
|
||||||
error = af_loader_load_glyph( loader, module, slot->face,
|
|
||||||
glyph_index, load_flags );
|
|
||||||
|
|
||||||
#ifdef FT_DEBUG_LEVEL_TRACE
|
|
||||||
if ( ft_trace_levels[FT_COMPONENT] )
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
af_glyph_hints_dump_points( hints, 0 );
|
|
||||||
af_glyph_hints_dump_segments( hints, 0 );
|
|
||||||
af_glyph_hints_dump_edges( hints, 0 );
|
|
||||||
#ifdef FT_DEBUG_LEVEL_TRACE
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
af_loader_done( loader );
|
|
||||||
|
|
||||||
return error;
|
|
||||||
|
|
||||||
#else /* !FT_DEBUG_AUTOFIT */
|
|
||||||
|
|
||||||
AF_GlyphHintsRec hints[1];
|
AF_GlyphHintsRec hints[1];
|
||||||
AF_LoaderRec loader[1];
|
AF_LoaderRec loader[1];
|
||||||
|
|
||||||
@ -539,8 +466,6 @@
|
|||||||
af_glyph_hints_done( hints );
|
af_glyph_hints_done( hints );
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
#endif /* !FT_DEBUG_AUTOFIT */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,23 +48,6 @@
|
|||||||
|
|
||||||
FT_BEGIN_HEADER
|
FT_BEGIN_HEADER
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*************************************************************************/
|
|
||||||
/***** *****/
|
|
||||||
/***** D E B U G G I N G *****/
|
|
||||||
/***** *****/
|
|
||||||
/*************************************************************************/
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
#ifdef FT_DEBUG_AUTOFIT
|
|
||||||
|
|
||||||
extern int _af_debug_disable_horz_hints;
|
|
||||||
extern int _af_debug_disable_vert_hints;
|
|
||||||
extern int _af_debug_disable_blue_hints;
|
|
||||||
extern void* _af_debug_hints;
|
|
||||||
|
|
||||||
#endif /* FT_DEBUG_AUTOFIT */
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
@ -1952,61 +1952,6 @@ FT_BEGIN_HEADER
|
|||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* <Function> */
|
|
||||||
/* FT_Init_FreeType */
|
|
||||||
/* */
|
|
||||||
/* <Description> */
|
|
||||||
/* Initialize a new FreeType library object. The set of modules */
|
|
||||||
/* that are registered by this function is determined at build time. */
|
|
||||||
/* */
|
|
||||||
/* <Output> */
|
|
||||||
/* alibrary :: A handle to a new library object. */
|
|
||||||
/* */
|
|
||||||
/* <Return> */
|
|
||||||
/* FreeType error code. 0~means success. */
|
|
||||||
/* */
|
|
||||||
/* <Note> */
|
|
||||||
/* In case you want to provide your own memory allocating routines, */
|
|
||||||
/* use @FT_New_Library instead, followed by a call to */
|
|
||||||
/* @FT_Add_Default_Modules (or a series of calls to @FT_Add_Module) */
|
|
||||||
/* and @FT_Set_Default_Properties. */
|
|
||||||
/* */
|
|
||||||
/* See the documentation of @FT_Library and @FT_Face for */
|
|
||||||
/* multi-threading issues. */
|
|
||||||
/* */
|
|
||||||
/* If you need reference-counting (cf. @FT_Reference_Library), use */
|
|
||||||
/* @FT_New_Library and @FT_Done_Library. */
|
|
||||||
/* */
|
|
||||||
/* If compilation option FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES is */
|
|
||||||
/* set, this function reads the `FREETYPE_PROPERTIES' environment */
|
|
||||||
/* variable to control driver properties. See section @properties */
|
|
||||||
/* for more. */
|
|
||||||
/* */
|
|
||||||
FT_EXPORT( FT_Error )
|
|
||||||
FT_Init_FreeType( FT_Library *alibrary );
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* <Function> */
|
|
||||||
/* FT_Done_FreeType */
|
|
||||||
/* */
|
|
||||||
/* <Description> */
|
|
||||||
/* Destroy a given FreeType library object and all of its children, */
|
|
||||||
/* including resources, drivers, faces, sizes, etc. */
|
|
||||||
/* */
|
|
||||||
/* <Input> */
|
|
||||||
/* library :: A handle to the target library object. */
|
|
||||||
/* */
|
|
||||||
/* <Return> */
|
|
||||||
/* FreeType error code. 0~means success. */
|
|
||||||
/* */
|
|
||||||
FT_EXPORT( FT_Error )
|
|
||||||
FT_Done_FreeType( FT_Library library );
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* <Enum> */
|
/* <Enum> */
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
|
|
||||||
#include "ftadvanc.c"
|
#include "ftadvanc.c"
|
||||||
#include "ftcalc.c"
|
#include "ftcalc.c"
|
||||||
#include "ftdbgmem.c"
|
|
||||||
#include "ftfntfmt.c"
|
#include "ftfntfmt.c"
|
||||||
#include "ftgloadr.c"
|
#include "ftgloadr.c"
|
||||||
#include "fthash.c"
|
#include "fthash.c"
|
||||||
|
@ -1,999 +0,0 @@
|
|||||||
/***************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* ftdbgmem.c */
|
|
||||||
/* */
|
|
||||||
/* Memory debugger (body). */
|
|
||||||
/* */
|
|
||||||
/* Copyright 2001-2018 by */
|
|
||||||
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
|
|
||||||
/* */
|
|
||||||
/* This file is part of the FreeType project, and may only be used, */
|
|
||||||
/* modified, and distributed under the terms of the FreeType project */
|
|
||||||
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
|
|
||||||
/* this file you indicate that you have read the license and */
|
|
||||||
/* understand and accept it fully. */
|
|
||||||
/* */
|
|
||||||
/***************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
#include "ft2build.h"
|
|
||||||
#include FT_CONFIG_CONFIG_H
|
|
||||||
#include FT_INTERNAL_DEBUG_H
|
|
||||||
#include FT_INTERNAL_MEMORY_H
|
|
||||||
#include FT_SYSTEM_H
|
|
||||||
#include FT_ERRORS_H
|
|
||||||
#include FT_TYPES_H
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef FT_DEBUG_MEMORY
|
|
||||||
|
|
||||||
#define KEEPALIVE /* `Keep alive' means that freed blocks aren't released
|
|
||||||
* to the heap. This is useful to detect double-frees
|
|
||||||
* or weird heap corruption, but it uses large amounts of
|
|
||||||
* memory, however.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include FT_CONFIG_STANDARD_LIBRARY_H
|
|
||||||
|
|
||||||
FT_BASE_DEF( const char* ) _ft_debug_file = NULL;
|
|
||||||
FT_BASE_DEF( long ) _ft_debug_lineno = 0;
|
|
||||||
|
|
||||||
extern void
|
|
||||||
FT_DumpMemory( FT_Memory memory );
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct FT_MemSourceRec_* FT_MemSource;
|
|
||||||
typedef struct FT_MemNodeRec_* FT_MemNode;
|
|
||||||
typedef struct FT_MemTableRec_* FT_MemTable;
|
|
||||||
|
|
||||||
|
|
||||||
#define FT_MEM_VAL( addr ) ( (FT_PtrDist)(FT_Pointer)( addr ) )
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This structure holds statistics for a single allocation/release
|
|
||||||
* site. This is useful to know where memory operations happen the
|
|
||||||
* most.
|
|
||||||
*/
|
|
||||||
typedef struct FT_MemSourceRec_
|
|
||||||
{
|
|
||||||
const char* file_name;
|
|
||||||
long line_no;
|
|
||||||
|
|
||||||
FT_Long cur_blocks; /* current number of allocated blocks */
|
|
||||||
FT_Long max_blocks; /* max. number of allocated blocks */
|
|
||||||
FT_Long all_blocks; /* total number of blocks allocated */
|
|
||||||
|
|
||||||
FT_Long cur_size; /* current cumulative allocated size */
|
|
||||||
FT_Long max_size; /* maximum cumulative allocated size */
|
|
||||||
FT_Long all_size; /* total cumulative allocated size */
|
|
||||||
|
|
||||||
FT_Long cur_max; /* current maximum allocated size */
|
|
||||||
|
|
||||||
FT_UInt32 hash;
|
|
||||||
FT_MemSource link;
|
|
||||||
|
|
||||||
} FT_MemSourceRec;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We don't need a resizable array for the memory sources because
|
|
||||||
* their number is pretty limited within FreeType.
|
|
||||||
*/
|
|
||||||
#define FT_MEM_SOURCE_BUCKETS 128
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This structure holds information related to a single allocated
|
|
||||||
* memory block. If KEEPALIVE is defined, blocks that are freed by
|
|
||||||
* FreeType are never released to the system. Instead, their `size'
|
|
||||||
* field is set to `-size'. This is mainly useful to detect double
|
|
||||||
* frees, at the price of a large memory footprint during execution.
|
|
||||||
*/
|
|
||||||
typedef struct FT_MemNodeRec_
|
|
||||||
{
|
|
||||||
FT_Byte* address;
|
|
||||||
FT_Long size; /* < 0 if the block was freed */
|
|
||||||
|
|
||||||
FT_MemSource source;
|
|
||||||
|
|
||||||
#ifdef KEEPALIVE
|
|
||||||
const char* free_file_name;
|
|
||||||
FT_Long free_line_no;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
FT_MemNode link;
|
|
||||||
|
|
||||||
} FT_MemNodeRec;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The global structure, containing compound statistics and all hash
|
|
||||||
* tables.
|
|
||||||
*/
|
|
||||||
typedef struct FT_MemTableRec_
|
|
||||||
{
|
|
||||||
FT_Long size;
|
|
||||||
FT_Long nodes;
|
|
||||||
FT_MemNode* buckets;
|
|
||||||
|
|
||||||
FT_Long alloc_total;
|
|
||||||
FT_Long alloc_current;
|
|
||||||
FT_Long alloc_max;
|
|
||||||
FT_Long alloc_count;
|
|
||||||
|
|
||||||
FT_Bool bound_total;
|
|
||||||
FT_Long alloc_total_max;
|
|
||||||
|
|
||||||
FT_Bool bound_count;
|
|
||||||
FT_Long alloc_count_max;
|
|
||||||
|
|
||||||
FT_MemSource sources[FT_MEM_SOURCE_BUCKETS];
|
|
||||||
|
|
||||||
FT_Bool keep_alive;
|
|
||||||
|
|
||||||
FT_Memory memory;
|
|
||||||
FT_Pointer memory_user;
|
|
||||||
FT_Alloc_Func alloc;
|
|
||||||
FT_Free_Func free;
|
|
||||||
FT_Realloc_Func realloc;
|
|
||||||
|
|
||||||
} FT_MemTableRec;
|
|
||||||
|
|
||||||
|
|
||||||
#define FT_MEM_SIZE_MIN 7
|
|
||||||
#define FT_MEM_SIZE_MAX 13845163
|
|
||||||
|
|
||||||
#define FT_FILENAME( x ) ( (x) ? (x) : "unknown file" )
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Prime numbers are ugly to handle. It would be better to implement
|
|
||||||
* L-Hashing, which is 10% faster and doesn't require divisions.
|
|
||||||
*/
|
|
||||||
static const FT_Int ft_mem_primes[] =
|
|
||||||
{
|
|
||||||
7,
|
|
||||||
11,
|
|
||||||
19,
|
|
||||||
37,
|
|
||||||
73,
|
|
||||||
109,
|
|
||||||
163,
|
|
||||||
251,
|
|
||||||
367,
|
|
||||||
557,
|
|
||||||
823,
|
|
||||||
1237,
|
|
||||||
1861,
|
|
||||||
2777,
|
|
||||||
4177,
|
|
||||||
6247,
|
|
||||||
9371,
|
|
||||||
14057,
|
|
||||||
21089,
|
|
||||||
31627,
|
|
||||||
47431,
|
|
||||||
71143,
|
|
||||||
106721,
|
|
||||||
160073,
|
|
||||||
240101,
|
|
||||||
360163,
|
|
||||||
540217,
|
|
||||||
810343,
|
|
||||||
1215497,
|
|
||||||
1823231,
|
|
||||||
2734867,
|
|
||||||
4102283,
|
|
||||||
6153409,
|
|
||||||
9230113,
|
|
||||||
13845163,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static FT_Long
|
|
||||||
ft_mem_closest_prime( FT_Long num )
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
|
|
||||||
for ( i = 0;
|
|
||||||
i < sizeof ( ft_mem_primes ) / sizeof ( ft_mem_primes[0] ); i++ )
|
|
||||||
if ( ft_mem_primes[i] > num )
|
|
||||||
return ft_mem_primes[i];
|
|
||||||
|
|
||||||
return FT_MEM_SIZE_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ft_mem_debug_panic( const char* fmt,
|
|
||||||
... )
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
|
|
||||||
printf( "FreeType.Debug: " );
|
|
||||||
|
|
||||||
va_start( ap, fmt );
|
|
||||||
vprintf( fmt, ap );
|
|
||||||
va_end( ap );
|
|
||||||
|
|
||||||
printf( "\n" );
|
|
||||||
exit( EXIT_FAILURE );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static FT_Pointer
|
|
||||||
ft_mem_table_alloc( FT_MemTable table,
|
|
||||||
FT_Long size )
|
|
||||||
{
|
|
||||||
FT_Memory memory = table->memory;
|
|
||||||
FT_Pointer block;
|
|
||||||
|
|
||||||
|
|
||||||
memory->user = table->memory_user;
|
|
||||||
block = table->alloc( memory, size );
|
|
||||||
memory->user = table;
|
|
||||||
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ft_mem_table_free( FT_MemTable table,
|
|
||||||
FT_Pointer block )
|
|
||||||
{
|
|
||||||
FT_Memory memory = table->memory;
|
|
||||||
|
|
||||||
|
|
||||||
memory->user = table->memory_user;
|
|
||||||
table->free( memory, block );
|
|
||||||
memory->user = table;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ft_mem_table_resize( FT_MemTable table )
|
|
||||||
{
|
|
||||||
FT_Long new_size;
|
|
||||||
|
|
||||||
|
|
||||||
new_size = ft_mem_closest_prime( table->nodes );
|
|
||||||
if ( new_size != table->size )
|
|
||||||
{
|
|
||||||
FT_MemNode* new_buckets;
|
|
||||||
FT_Long i;
|
|
||||||
|
|
||||||
|
|
||||||
new_buckets = (FT_MemNode *)
|
|
||||||
ft_mem_table_alloc(
|
|
||||||
table,
|
|
||||||
new_size * (FT_Long)sizeof ( FT_MemNode ) );
|
|
||||||
if ( !new_buckets )
|
|
||||||
return;
|
|
||||||
|
|
||||||
FT_ARRAY_ZERO( new_buckets, new_size );
|
|
||||||
|
|
||||||
for ( i = 0; i < table->size; i++ )
|
|
||||||
{
|
|
||||||
FT_MemNode node, next, *pnode;
|
|
||||||
FT_PtrDist hash;
|
|
||||||
|
|
||||||
|
|
||||||
node = table->buckets[i];
|
|
||||||
while ( node )
|
|
||||||
{
|
|
||||||
next = node->link;
|
|
||||||
hash = FT_MEM_VAL( node->address ) % (FT_PtrDist)new_size;
|
|
||||||
pnode = new_buckets + hash;
|
|
||||||
|
|
||||||
node->link = pnode[0];
|
|
||||||
pnode[0] = node;
|
|
||||||
|
|
||||||
node = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( table->buckets )
|
|
||||||
ft_mem_table_free( table, table->buckets );
|
|
||||||
|
|
||||||
table->buckets = new_buckets;
|
|
||||||
table->size = new_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static FT_MemTable
|
|
||||||
ft_mem_table_new( FT_Memory memory )
|
|
||||||
{
|
|
||||||
FT_MemTable table;
|
|
||||||
|
|
||||||
|
|
||||||
table = (FT_MemTable)memory->alloc( memory, sizeof ( *table ) );
|
|
||||||
if ( !table )
|
|
||||||
goto Exit;
|
|
||||||
|
|
||||||
FT_ZERO( table );
|
|
||||||
|
|
||||||
table->size = FT_MEM_SIZE_MIN;
|
|
||||||
table->nodes = 0;
|
|
||||||
|
|
||||||
table->memory = memory;
|
|
||||||
|
|
||||||
table->memory_user = memory->user;
|
|
||||||
|
|
||||||
table->alloc = memory->alloc;
|
|
||||||
table->realloc = memory->realloc;
|
|
||||||
table->free = memory->free;
|
|
||||||
|
|
||||||
table->buckets = (FT_MemNode *)
|
|
||||||
memory->alloc(
|
|
||||||
memory,
|
|
||||||
table->size * (FT_Long)sizeof ( FT_MemNode ) );
|
|
||||||
if ( table->buckets )
|
|
||||||
FT_ARRAY_ZERO( table->buckets, table->size );
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memory->free( memory, table );
|
|
||||||
table = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Exit:
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ft_mem_table_destroy( FT_MemTable table )
|
|
||||||
{
|
|
||||||
FT_Long i;
|
|
||||||
FT_Long leak_count = 0;
|
|
||||||
FT_Long leaks = 0;
|
|
||||||
|
|
||||||
|
|
||||||
FT_DumpMemory( table->memory );
|
|
||||||
|
|
||||||
/* remove all blocks from the table, revealing leaked ones */
|
|
||||||
for ( i = 0; i < table->size; i++ )
|
|
||||||
{
|
|
||||||
FT_MemNode *pnode = table->buckets + i, next, node = *pnode;
|
|
||||||
|
|
||||||
|
|
||||||
while ( node )
|
|
||||||
{
|
|
||||||
next = node->link;
|
|
||||||
node->link = NULL;
|
|
||||||
|
|
||||||
if ( node->size > 0 )
|
|
||||||
{
|
|
||||||
printf(
|
|
||||||
"leaked memory block at address %p, size %8ld in (%s:%ld)\n",
|
|
||||||
(void*)node->address,
|
|
||||||
node->size,
|
|
||||||
FT_FILENAME( node->source->file_name ),
|
|
||||||
node->source->line_no );
|
|
||||||
|
|
||||||
leak_count++;
|
|
||||||
leaks += node->size;
|
|
||||||
|
|
||||||
ft_mem_table_free( table, node->address );
|
|
||||||
}
|
|
||||||
|
|
||||||
node->address = NULL;
|
|
||||||
node->size = 0;
|
|
||||||
|
|
||||||
ft_mem_table_free( table, node );
|
|
||||||
node = next;
|
|
||||||
}
|
|
||||||
table->buckets[i] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ft_mem_table_free( table, table->buckets );
|
|
||||||
table->buckets = NULL;
|
|
||||||
|
|
||||||
table->size = 0;
|
|
||||||
table->nodes = 0;
|
|
||||||
|
|
||||||
/* remove all sources */
|
|
||||||
for ( i = 0; i < FT_MEM_SOURCE_BUCKETS; i++ )
|
|
||||||
{
|
|
||||||
FT_MemSource source, next;
|
|
||||||
|
|
||||||
|
|
||||||
for ( source = table->sources[i]; source != NULL; source = next )
|
|
||||||
{
|
|
||||||
next = source->link;
|
|
||||||
ft_mem_table_free( table, source );
|
|
||||||
}
|
|
||||||
|
|
||||||
table->sources[i] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf( "FreeType: total memory allocations = %ld\n",
|
|
||||||
table->alloc_total );
|
|
||||||
printf( "FreeType: maximum memory footprint = %ld\n",
|
|
||||||
table->alloc_max );
|
|
||||||
|
|
||||||
ft_mem_table_free( table, table );
|
|
||||||
|
|
||||||
if ( leak_count > 0 )
|
|
||||||
ft_mem_debug_panic(
|
|
||||||
"FreeType: %ld bytes of memory leaked in %ld blocks\n",
|
|
||||||
leaks, leak_count );
|
|
||||||
|
|
||||||
printf( "FreeType: no memory leaks detected\n" );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static FT_MemNode*
|
|
||||||
ft_mem_table_get_nodep( FT_MemTable table,
|
|
||||||
FT_Byte* address )
|
|
||||||
{
|
|
||||||
FT_PtrDist hash;
|
|
||||||
FT_MemNode *pnode, node;
|
|
||||||
|
|
||||||
|
|
||||||
hash = FT_MEM_VAL( address );
|
|
||||||
pnode = table->buckets + ( hash % (FT_PtrDist)table->size );
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
node = pnode[0];
|
|
||||||
if ( !node )
|
|
||||||
break;
|
|
||||||
|
|
||||||
if ( node->address == address )
|
|
||||||
break;
|
|
||||||
|
|
||||||
pnode = &node->link;
|
|
||||||
}
|
|
||||||
return pnode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static FT_MemSource
|
|
||||||
ft_mem_table_get_source( FT_MemTable table )
|
|
||||||
{
|
|
||||||
FT_UInt32 hash;
|
|
||||||
FT_MemSource node, *pnode;
|
|
||||||
|
|
||||||
|
|
||||||
/* cast to FT_PtrDist first since void* can be larger */
|
|
||||||
/* than FT_UInt32 and GCC 4.1.1 emits a warning */
|
|
||||||
hash = (FT_UInt32)(FT_PtrDist)(void*)_ft_debug_file +
|
|
||||||
(FT_UInt32)( 5 * _ft_debug_lineno );
|
|
||||||
pnode = &table->sources[hash % FT_MEM_SOURCE_BUCKETS];
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
node = *pnode;
|
|
||||||
if ( !node )
|
|
||||||
break;
|
|
||||||
|
|
||||||
if ( node->file_name == _ft_debug_file &&
|
|
||||||
node->line_no == _ft_debug_lineno )
|
|
||||||
goto Exit;
|
|
||||||
|
|
||||||
pnode = &node->link;
|
|
||||||
}
|
|
||||||
|
|
||||||
node = (FT_MemSource)ft_mem_table_alloc( table, sizeof ( *node ) );
|
|
||||||
if ( !node )
|
|
||||||
ft_mem_debug_panic(
|
|
||||||
"not enough memory to perform memory debugging\n" );
|
|
||||||
|
|
||||||
node->file_name = _ft_debug_file;
|
|
||||||
node->line_no = _ft_debug_lineno;
|
|
||||||
|
|
||||||
node->cur_blocks = 0;
|
|
||||||
node->max_blocks = 0;
|
|
||||||
node->all_blocks = 0;
|
|
||||||
|
|
||||||
node->cur_size = 0;
|
|
||||||
node->max_size = 0;
|
|
||||||
node->all_size = 0;
|
|
||||||
|
|
||||||
node->cur_max = 0;
|
|
||||||
|
|
||||||
node->link = NULL;
|
|
||||||
node->hash = hash;
|
|
||||||
*pnode = node;
|
|
||||||
|
|
||||||
Exit:
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ft_mem_table_set( FT_MemTable table,
|
|
||||||
FT_Byte* address,
|
|
||||||
FT_Long size,
|
|
||||||
FT_Long delta )
|
|
||||||
{
|
|
||||||
FT_MemNode *pnode, node;
|
|
||||||
|
|
||||||
|
|
||||||
if ( table )
|
|
||||||
{
|
|
||||||
FT_MemSource source;
|
|
||||||
|
|
||||||
|
|
||||||
pnode = ft_mem_table_get_nodep( table, address );
|
|
||||||
node = *pnode;
|
|
||||||
if ( node )
|
|
||||||
{
|
|
||||||
if ( node->size < 0 )
|
|
||||||
{
|
|
||||||
/* This block was already freed. Our memory is now completely */
|
|
||||||
/* corrupted! */
|
|
||||||
/* This can only happen in keep-alive mode. */
|
|
||||||
ft_mem_debug_panic(
|
|
||||||
"memory heap corrupted (allocating freed block)" );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* This block was already allocated. This means that our memory */
|
|
||||||
/* is also corrupted! */
|
|
||||||
ft_mem_debug_panic(
|
|
||||||
"memory heap corrupted (re-allocating allocated block at"
|
|
||||||
" %p, of size %ld)\n"
|
|
||||||
"org=%s:%d new=%s:%d\n",
|
|
||||||
node->address, node->size,
|
|
||||||
FT_FILENAME( node->source->file_name ), node->source->line_no,
|
|
||||||
FT_FILENAME( _ft_debug_file ), _ft_debug_lineno );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we need to create a new node in this table */
|
|
||||||
node = (FT_MemNode)ft_mem_table_alloc( table, sizeof ( *node ) );
|
|
||||||
if ( !node )
|
|
||||||
ft_mem_debug_panic( "not enough memory to run memory tests" );
|
|
||||||
|
|
||||||
node->address = address;
|
|
||||||
node->size = size;
|
|
||||||
node->source = source = ft_mem_table_get_source( table );
|
|
||||||
|
|
||||||
if ( delta == 0 )
|
|
||||||
{
|
|
||||||
/* this is an allocation */
|
|
||||||
source->all_blocks++;
|
|
||||||
source->cur_blocks++;
|
|
||||||
if ( source->cur_blocks > source->max_blocks )
|
|
||||||
source->max_blocks = source->cur_blocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( size > source->cur_max )
|
|
||||||
source->cur_max = size;
|
|
||||||
|
|
||||||
if ( delta != 0 )
|
|
||||||
{
|
|
||||||
/* we are growing or shrinking a reallocated block */
|
|
||||||
source->cur_size += delta;
|
|
||||||
table->alloc_current += delta;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* we are allocating a new block */
|
|
||||||
source->cur_size += size;
|
|
||||||
table->alloc_current += size;
|
|
||||||
}
|
|
||||||
|
|
||||||
source->all_size += size;
|
|
||||||
|
|
||||||
if ( source->cur_size > source->max_size )
|
|
||||||
source->max_size = source->cur_size;
|
|
||||||
|
|
||||||
node->free_file_name = NULL;
|
|
||||||
node->free_line_no = 0;
|
|
||||||
|
|
||||||
node->link = pnode[0];
|
|
||||||
|
|
||||||
pnode[0] = node;
|
|
||||||
table->nodes++;
|
|
||||||
|
|
||||||
table->alloc_total += size;
|
|
||||||
|
|
||||||
if ( table->alloc_current > table->alloc_max )
|
|
||||||
table->alloc_max = table->alloc_current;
|
|
||||||
|
|
||||||
if ( table->nodes * 3 < table->size ||
|
|
||||||
table->size * 3 < table->nodes )
|
|
||||||
ft_mem_table_resize( table );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ft_mem_table_remove( FT_MemTable table,
|
|
||||||
FT_Byte* address,
|
|
||||||
FT_Long delta )
|
|
||||||
{
|
|
||||||
if ( table )
|
|
||||||
{
|
|
||||||
FT_MemNode *pnode, node;
|
|
||||||
|
|
||||||
|
|
||||||
pnode = ft_mem_table_get_nodep( table, address );
|
|
||||||
node = *pnode;
|
|
||||||
if ( node )
|
|
||||||
{
|
|
||||||
FT_MemSource source;
|
|
||||||
|
|
||||||
|
|
||||||
if ( node->size < 0 )
|
|
||||||
ft_mem_debug_panic(
|
|
||||||
"freeing memory block at %p more than once at (%s:%ld)\n"
|
|
||||||
"block allocated at (%s:%ld) and released at (%s:%ld)",
|
|
||||||
address,
|
|
||||||
FT_FILENAME( _ft_debug_file ), _ft_debug_lineno,
|
|
||||||
FT_FILENAME( node->source->file_name ), node->source->line_no,
|
|
||||||
FT_FILENAME( node->free_file_name ), node->free_line_no );
|
|
||||||
|
|
||||||
/* scramble the node's content for additional safety */
|
|
||||||
FT_MEM_SET( address, 0xF3, node->size );
|
|
||||||
|
|
||||||
if ( delta == 0 )
|
|
||||||
{
|
|
||||||
source = node->source;
|
|
||||||
|
|
||||||
source->cur_blocks--;
|
|
||||||
source->cur_size -= node->size;
|
|
||||||
|
|
||||||
table->alloc_current -= node->size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( table->keep_alive )
|
|
||||||
{
|
|
||||||
/* we simply invert the node's size to indicate that the node */
|
|
||||||
/* was freed. */
|
|
||||||
node->size = -node->size;
|
|
||||||
node->free_file_name = _ft_debug_file;
|
|
||||||
node->free_line_no = _ft_debug_lineno;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
table->nodes--;
|
|
||||||
|
|
||||||
*pnode = node->link;
|
|
||||||
|
|
||||||
node->size = 0;
|
|
||||||
node->source = NULL;
|
|
||||||
|
|
||||||
ft_mem_table_free( table, node );
|
|
||||||
|
|
||||||
if ( table->nodes * 3 < table->size ||
|
|
||||||
table->size * 3 < table->nodes )
|
|
||||||
ft_mem_table_resize( table );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ft_mem_debug_panic(
|
|
||||||
"trying to free unknown block at %p in (%s:%ld)\n",
|
|
||||||
address,
|
|
||||||
FT_FILENAME( _ft_debug_file ), _ft_debug_lineno );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static FT_Pointer
|
|
||||||
ft_mem_debug_alloc( FT_Memory memory,
|
|
||||||
FT_Long size )
|
|
||||||
{
|
|
||||||
FT_MemTable table = (FT_MemTable)memory->user;
|
|
||||||
FT_Byte* block;
|
|
||||||
|
|
||||||
|
|
||||||
if ( size <= 0 )
|
|
||||||
ft_mem_debug_panic( "negative block size allocation (%ld)", size );
|
|
||||||
|
|
||||||
/* return NULL if the maximum number of allocations was reached */
|
|
||||||
if ( table->bound_count &&
|
|
||||||
table->alloc_count >= table->alloc_count_max )
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* return NULL if this allocation would overflow the maximum heap size */
|
|
||||||
if ( table->bound_total &&
|
|
||||||
table->alloc_total_max - table->alloc_current > size )
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
block = (FT_Byte *)ft_mem_table_alloc( table, size );
|
|
||||||
if ( block )
|
|
||||||
{
|
|
||||||
ft_mem_table_set( table, block, size, 0 );
|
|
||||||
|
|
||||||
table->alloc_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ft_debug_file = "<unknown>";
|
|
||||||
_ft_debug_lineno = 0;
|
|
||||||
|
|
||||||
return (FT_Pointer)block;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ft_mem_debug_free( FT_Memory memory,
|
|
||||||
FT_Pointer block )
|
|
||||||
{
|
|
||||||
FT_MemTable table = (FT_MemTable)memory->user;
|
|
||||||
|
|
||||||
|
|
||||||
if ( !block )
|
|
||||||
ft_mem_debug_panic( "trying to free NULL in (%s:%ld)",
|
|
||||||
FT_FILENAME( _ft_debug_file ),
|
|
||||||
_ft_debug_lineno );
|
|
||||||
|
|
||||||
ft_mem_table_remove( table, (FT_Byte*)block, 0 );
|
|
||||||
|
|
||||||
if ( !table->keep_alive )
|
|
||||||
ft_mem_table_free( table, block );
|
|
||||||
|
|
||||||
table->alloc_count--;
|
|
||||||
|
|
||||||
_ft_debug_file = "<unknown>";
|
|
||||||
_ft_debug_lineno = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static FT_Pointer
|
|
||||||
ft_mem_debug_realloc( FT_Memory memory,
|
|
||||||
FT_Long cur_size,
|
|
||||||
FT_Long new_size,
|
|
||||||
FT_Pointer block )
|
|
||||||
{
|
|
||||||
FT_MemTable table = (FT_MemTable)memory->user;
|
|
||||||
FT_MemNode node, *pnode;
|
|
||||||
FT_Pointer new_block;
|
|
||||||
FT_Long delta;
|
|
||||||
|
|
||||||
const char* file_name = FT_FILENAME( _ft_debug_file );
|
|
||||||
FT_Long line_no = _ft_debug_lineno;
|
|
||||||
|
|
||||||
|
|
||||||
/* unlikely, but possible */
|
|
||||||
if ( new_size == cur_size )
|
|
||||||
return block;
|
|
||||||
|
|
||||||
/* the following is valid according to ANSI C */
|
|
||||||
#if 0
|
|
||||||
if ( !block || !cur_size )
|
|
||||||
ft_mem_debug_panic( "trying to reallocate NULL in (%s:%ld)",
|
|
||||||
file_name, line_no );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* while the following is allowed in ANSI C also, we abort since */
|
|
||||||
/* such case should be handled by FreeType. */
|
|
||||||
if ( new_size <= 0 )
|
|
||||||
ft_mem_debug_panic(
|
|
||||||
"trying to reallocate %p to size 0 (current is %ld) in (%s:%ld)",
|
|
||||||
block, cur_size, file_name, line_no );
|
|
||||||
|
|
||||||
/* check `cur_size' value */
|
|
||||||
pnode = ft_mem_table_get_nodep( table, (FT_Byte*)block );
|
|
||||||
node = *pnode;
|
|
||||||
if ( !node )
|
|
||||||
ft_mem_debug_panic(
|
|
||||||
"trying to reallocate unknown block at %p in (%s:%ld)",
|
|
||||||
block, file_name, line_no );
|
|
||||||
|
|
||||||
if ( node->size <= 0 )
|
|
||||||
ft_mem_debug_panic(
|
|
||||||
"trying to reallocate freed block at %p in (%s:%ld)",
|
|
||||||
block, file_name, line_no );
|
|
||||||
|
|
||||||
if ( node->size != cur_size )
|
|
||||||
ft_mem_debug_panic( "invalid ft_realloc request for %p. cur_size is "
|
|
||||||
"%ld instead of %ld in (%s:%ld)",
|
|
||||||
block, cur_size, node->size, file_name, line_no );
|
|
||||||
|
|
||||||
/* return NULL if the maximum number of allocations was reached */
|
|
||||||
if ( table->bound_count &&
|
|
||||||
table->alloc_count >= table->alloc_count_max )
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
delta = new_size - cur_size;
|
|
||||||
|
|
||||||
/* return NULL if this allocation would overflow the maximum heap size */
|
|
||||||
if ( delta > 0 &&
|
|
||||||
table->bound_total &&
|
|
||||||
table->alloc_current + delta > table->alloc_total_max )
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
new_block = (FT_Pointer)ft_mem_table_alloc( table, new_size );
|
|
||||||
if ( !new_block )
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
ft_mem_table_set( table, (FT_Byte*)new_block, new_size, delta );
|
|
||||||
|
|
||||||
ft_memcpy( new_block, block, cur_size < new_size ? (size_t)cur_size
|
|
||||||
: (size_t)new_size );
|
|
||||||
|
|
||||||
ft_mem_table_remove( table, (FT_Byte*)block, delta );
|
|
||||||
|
|
||||||
_ft_debug_file = "<unknown>";
|
|
||||||
_ft_debug_lineno = 0;
|
|
||||||
|
|
||||||
if ( !table->keep_alive )
|
|
||||||
ft_mem_table_free( table, block );
|
|
||||||
|
|
||||||
return new_block;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern FT_Int
|
|
||||||
ft_mem_debug_init( FT_Memory memory )
|
|
||||||
{
|
|
||||||
FT_MemTable table;
|
|
||||||
FT_Int result = 0;
|
|
||||||
|
|
||||||
|
|
||||||
if ( ft_getenv( "FT2_DEBUG_MEMORY" ) )
|
|
||||||
{
|
|
||||||
table = ft_mem_table_new( memory );
|
|
||||||
if ( table )
|
|
||||||
{
|
|
||||||
const char* p;
|
|
||||||
|
|
||||||
|
|
||||||
memory->user = table;
|
|
||||||
memory->alloc = ft_mem_debug_alloc;
|
|
||||||
memory->realloc = ft_mem_debug_realloc;
|
|
||||||
memory->free = ft_mem_debug_free;
|
|
||||||
|
|
||||||
p = ft_getenv( "FT2_ALLOC_TOTAL_MAX" );
|
|
||||||
if ( p )
|
|
||||||
{
|
|
||||||
FT_Long total_max = ft_strtol( p, NULL, 10 );
|
|
||||||
|
|
||||||
|
|
||||||
if ( total_max > 0 )
|
|
||||||
{
|
|
||||||
table->bound_total = 1;
|
|
||||||
table->alloc_total_max = total_max;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p = ft_getenv( "FT2_ALLOC_COUNT_MAX" );
|
|
||||||
if ( p )
|
|
||||||
{
|
|
||||||
FT_Long total_count = ft_strtol( p, NULL, 10 );
|
|
||||||
|
|
||||||
|
|
||||||
if ( total_count > 0 )
|
|
||||||
{
|
|
||||||
table->bound_count = 1;
|
|
||||||
table->alloc_count_max = total_count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p = ft_getenv( "FT2_KEEP_ALIVE" );
|
|
||||||
if ( p )
|
|
||||||
{
|
|
||||||
FT_Long keep_alive = ft_strtol( p, NULL, 10 );
|
|
||||||
|
|
||||||
|
|
||||||
if ( keep_alive > 0 )
|
|
||||||
table->keep_alive = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern void
|
|
||||||
ft_mem_debug_done( FT_Memory memory )
|
|
||||||
{
|
|
||||||
FT_MemTable table = (FT_MemTable)memory->user;
|
|
||||||
|
|
||||||
|
|
||||||
if ( table )
|
|
||||||
{
|
|
||||||
memory->free = table->free;
|
|
||||||
memory->realloc = table->realloc;
|
|
||||||
memory->alloc = table->alloc;
|
|
||||||
|
|
||||||
ft_mem_table_destroy( table );
|
|
||||||
memory->user = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
ft_mem_source_compare( const void* p1,
|
|
||||||
const void* p2 )
|
|
||||||
{
|
|
||||||
FT_MemSource s1 = *(FT_MemSource*)p1;
|
|
||||||
FT_MemSource s2 = *(FT_MemSource*)p2;
|
|
||||||
|
|
||||||
|
|
||||||
if ( s2->max_size > s1->max_size )
|
|
||||||
return 1;
|
|
||||||
else if ( s2->max_size < s1->max_size )
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern void
|
|
||||||
FT_DumpMemory( FT_Memory memory )
|
|
||||||
{
|
|
||||||
FT_MemTable table = (FT_MemTable)memory->user;
|
|
||||||
|
|
||||||
|
|
||||||
if ( table )
|
|
||||||
{
|
|
||||||
FT_MemSource* bucket = table->sources;
|
|
||||||
FT_MemSource* limit = bucket + FT_MEM_SOURCE_BUCKETS;
|
|
||||||
FT_MemSource* sources;
|
|
||||||
FT_Int nn, count;
|
|
||||||
const char* fmt;
|
|
||||||
|
|
||||||
|
|
||||||
count = 0;
|
|
||||||
for ( ; bucket < limit; bucket++ )
|
|
||||||
{
|
|
||||||
FT_MemSource source = *bucket;
|
|
||||||
|
|
||||||
|
|
||||||
for ( ; source; source = source->link )
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
sources = (FT_MemSource*)
|
|
||||||
ft_mem_table_alloc(
|
|
||||||
table, count * (FT_Long)sizeof ( *sources ) );
|
|
||||||
|
|
||||||
count = 0;
|
|
||||||
for ( bucket = table->sources; bucket < limit; bucket++ )
|
|
||||||
{
|
|
||||||
FT_MemSource source = *bucket;
|
|
||||||
|
|
||||||
|
|
||||||
for ( ; source; source = source->link )
|
|
||||||
sources[count++] = source;
|
|
||||||
}
|
|
||||||
|
|
||||||
ft_qsort( sources,
|
|
||||||
(size_t)count,
|
|
||||||
sizeof ( *sources ),
|
|
||||||
ft_mem_source_compare );
|
|
||||||
|
|
||||||
printf( "FreeType Memory Dump: "
|
|
||||||
"current=%ld max=%ld total=%ld count=%ld\n",
|
|
||||||
table->alloc_current, table->alloc_max,
|
|
||||||
table->alloc_total, table->alloc_count );
|
|
||||||
printf( " block block sizes sizes sizes source\n" );
|
|
||||||
printf( " count high sum highsum max location\n" );
|
|
||||||
printf( "-------------------------------------------------\n" );
|
|
||||||
|
|
||||||
fmt = "%6ld %6ld %8ld %8ld %8ld %s:%d\n";
|
|
||||||
|
|
||||||
for ( nn = 0; nn < count; nn++ )
|
|
||||||
{
|
|
||||||
FT_MemSource source = sources[nn];
|
|
||||||
|
|
||||||
|
|
||||||
printf( fmt,
|
|
||||||
source->cur_blocks, source->max_blocks,
|
|
||||||
source->cur_size, source->max_size, source->cur_max,
|
|
||||||
FT_FILENAME( source->file_name ),
|
|
||||||
source->line_no );
|
|
||||||
}
|
|
||||||
printf( "------------------------------------------------\n" );
|
|
||||||
|
|
||||||
ft_mem_table_free( table, sources );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* !FT_DEBUG_MEMORY */
|
|
||||||
|
|
||||||
/* ANSI C doesn't like empty source files */
|
|
||||||
typedef int _debug_mem_dummy;
|
|
||||||
|
|
||||||
#endif /* !FT_DEBUG_MEMORY */
|
|
||||||
|
|
||||||
|
|
||||||
/* END */
|
|
@ -188,64 +188,4 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* documentation is in freetype.h */
|
|
||||||
|
|
||||||
FT_EXPORT_DEF( FT_Error )
|
|
||||||
FT_Init_FreeType( FT_Library *alibrary )
|
|
||||||
{
|
|
||||||
FT_Error error;
|
|
||||||
FT_Memory memory;
|
|
||||||
|
|
||||||
|
|
||||||
/* check of `alibrary' delayed to `FT_New_Library' */
|
|
||||||
|
|
||||||
/* First of all, allocate a new system object -- this function is part */
|
|
||||||
/* of the system-specific component, i.e. `ftsystem.c'. */
|
|
||||||
|
|
||||||
memory = FT_New_Memory();
|
|
||||||
if ( !memory )
|
|
||||||
{
|
|
||||||
FT_ERROR(( "FT_Init_FreeType: cannot find memory manager\n" ));
|
|
||||||
return FT_THROW( Unimplemented_Feature );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* build a library out of it, then fill it with the set of */
|
|
||||||
/* default drivers. */
|
|
||||||
|
|
||||||
error = FT_New_Library( memory, alibrary );
|
|
||||||
if ( error )
|
|
||||||
FT_Done_Memory( memory );
|
|
||||||
else
|
|
||||||
FT_Add_Default_Modules( *alibrary );
|
|
||||||
|
|
||||||
FT_Set_Default_Properties( *alibrary );
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* documentation is in freetype.h */
|
|
||||||
|
|
||||||
FT_EXPORT_DEF( FT_Error )
|
|
||||||
FT_Done_FreeType( FT_Library library )
|
|
||||||
{
|
|
||||||
FT_Memory memory;
|
|
||||||
|
|
||||||
|
|
||||||
if ( !library )
|
|
||||||
return FT_THROW( Invalid_Library_Handle );
|
|
||||||
|
|
||||||
memory = library->memory;
|
|
||||||
|
|
||||||
/* Discard the library object */
|
|
||||||
FT_Done_Library( library );
|
|
||||||
|
|
||||||
/* discard memory manager */
|
|
||||||
FT_Done_Memory( memory );
|
|
||||||
|
|
||||||
return FT_Err_Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* END */
|
/* END */
|
||||||
|
@ -922,39 +922,6 @@ FT_BEGIN_HEADER
|
|||||||
FT_String* glyph_name );
|
FT_String* glyph_name );
|
||||||
|
|
||||||
|
|
||||||
#ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* <Function> */
|
|
||||||
/* FT_New_Memory */
|
|
||||||
/* */
|
|
||||||
/* <Description> */
|
|
||||||
/* Creates a new memory object. */
|
|
||||||
/* */
|
|
||||||
/* <Return> */
|
|
||||||
/* A pointer to the new memory object. 0 in case of error. */
|
|
||||||
/* */
|
|
||||||
FT_BASE( FT_Memory )
|
|
||||||
FT_New_Memory( void );
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* <Function> */
|
|
||||||
/* FT_Done_Memory */
|
|
||||||
/* */
|
|
||||||
/* <Description> */
|
|
||||||
/* Discards memory manager. */
|
|
||||||
/* */
|
|
||||||
/* <Input> */
|
|
||||||
/* memory :: A handle to the memory manager. */
|
|
||||||
/* */
|
|
||||||
FT_BASE( void )
|
|
||||||
FT_Done_Memory( FT_Memory memory );
|
|
||||||
|
|
||||||
#endif /* !FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM */
|
|
||||||
|
|
||||||
|
|
||||||
/* Define default raster's interface. The default raster is located in */
|
/* Define default raster's interface. The default raster is located in */
|
||||||
/* `src/base/ftraster.c'. */
|
/* `src/base/ftraster.c'. */
|
||||||
|
@ -105,7 +105,7 @@ FT_BEGIN_HEADER
|
|||||||
/* cff:no-stem-darkening=1 \ */
|
/* cff:no-stem-darkening=1 \ */
|
||||||
/* autofitter:warping=1 */
|
/* autofitter:warping=1 */
|
||||||
/* */
|
/* */
|
||||||
#define FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
|
#undef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
@ -373,24 +373,6 @@ FT_BEGIN_HEADER
|
|||||||
/* #define FT_DEBUG_AUTOFIT */
|
/* #define FT_DEBUG_AUTOFIT */
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* Memory Debugging */
|
|
||||||
/* */
|
|
||||||
/* FreeType now comes with an integrated memory debugger that is */
|
|
||||||
/* capable of detecting simple errors like memory leaks or double */
|
|
||||||
/* deletes. To compile it within your build of the library, you */
|
|
||||||
/* should define FT_DEBUG_MEMORY here. */
|
|
||||||
/* */
|
|
||||||
/* Note that the memory debugger is only activated at runtime when */
|
|
||||||
/* when the _environment_ variable `FT2_DEBUG_MEMORY' is defined also! */
|
|
||||||
/* */
|
|
||||||
/* Do not #undef this macro here since the build system might define */
|
|
||||||
/* it for certain configurations only. */
|
|
||||||
/* */
|
|
||||||
/* #define FT_DEBUG_MEMORY */
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* Module errors */
|
/* Module errors */
|
||||||
|
@ -122,19 +122,6 @@
|
|||||||
#define ft_qsort qsort
|
#define ft_qsort qsort
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************/
|
|
||||||
/* */
|
|
||||||
/* memory allocation */
|
|
||||||
/* */
|
|
||||||
/**********************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
#define ft_scalloc calloc
|
|
||||||
#define ft_sfree free
|
|
||||||
#define ft_smalloc malloc
|
|
||||||
#define ft_srealloc realloc
|
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* miscellaneous */
|
/* miscellaneous */
|
||||||
|
@ -218,13 +218,7 @@
|
|||||||
if ( stream && stream->read )
|
if ( stream && stream->read )
|
||||||
{
|
{
|
||||||
FT_Memory memory = stream->memory;
|
FT_Memory memory = stream->memory;
|
||||||
|
|
||||||
#ifdef FT_DEBUG_MEMORY
|
|
||||||
ft_mem_free( memory, *pbytes );
|
|
||||||
*pbytes = NULL;
|
|
||||||
#else
|
|
||||||
FT_FREE( *pbytes );
|
FT_FREE( *pbytes );
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
*pbytes = NULL;
|
*pbytes = NULL;
|
||||||
}
|
}
|
||||||
@ -258,17 +252,9 @@
|
|||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FT_DEBUG_MEMORY
|
|
||||||
/* assume _ft_debug_file and _ft_debug_lineno are already set */
|
|
||||||
stream->base = (unsigned char*)ft_mem_qalloc( memory,
|
|
||||||
(FT_Long)count,
|
|
||||||
&error );
|
|
||||||
if ( error )
|
|
||||||
goto Exit;
|
|
||||||
#else
|
|
||||||
if ( FT_QALLOC( stream->base, count ) )
|
if ( FT_QALLOC( stream->base, count ) )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
#endif
|
|
||||||
/* read it */
|
/* read it */
|
||||||
read_bytes = stream->read( stream, stream->pos,
|
read_bytes = stream->read( stream, stream->pos,
|
||||||
stream->base, count );
|
stream->base, count );
|
||||||
@ -327,13 +313,7 @@
|
|||||||
if ( stream->read )
|
if ( stream->read )
|
||||||
{
|
{
|
||||||
FT_Memory memory = stream->memory;
|
FT_Memory memory = stream->memory;
|
||||||
|
|
||||||
#ifdef FT_DEBUG_MEMORY
|
|
||||||
ft_mem_free( memory, stream->base );
|
|
||||||
stream->base = NULL;
|
|
||||||
#else
|
|
||||||
FT_FREE( stream->base );
|
FT_FREE( stream->base );
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
stream->cursor = NULL;
|
stream->cursor = NULL;
|
||||||
stream->limit = NULL;
|
stream->limit = NULL;
|
||||||
|
@ -34,103 +34,6 @@
|
|||||||
#include FT_TYPES_H
|
#include FT_TYPES_H
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* MEMORY MANAGEMENT INTERFACE */
|
|
||||||
/* */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* It is not necessary to do any error checking for the */
|
|
||||||
/* allocation-related functions. This will be done by the higher level */
|
|
||||||
/* routines like ft_mem_alloc() or ft_mem_realloc(). */
|
|
||||||
/* */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* <Function> */
|
|
||||||
/* ft_alloc */
|
|
||||||
/* */
|
|
||||||
/* <Description> */
|
|
||||||
/* The memory allocation function. */
|
|
||||||
/* */
|
|
||||||
/* <Input> */
|
|
||||||
/* memory :: A pointer to the memory object. */
|
|
||||||
/* */
|
|
||||||
/* size :: The requested size in bytes. */
|
|
||||||
/* */
|
|
||||||
/* <Return> */
|
|
||||||
/* The address of newly allocated block. */
|
|
||||||
/* */
|
|
||||||
FT_CALLBACK_DEF( void* )
|
|
||||||
ft_alloc( FT_Memory memory,
|
|
||||||
long size )
|
|
||||||
{
|
|
||||||
FT_UNUSED( memory );
|
|
||||||
|
|
||||||
return ft_smalloc( (size_t)size );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* <Function> */
|
|
||||||
/* ft_realloc */
|
|
||||||
/* */
|
|
||||||
/* <Description> */
|
|
||||||
/* The memory reallocation function. */
|
|
||||||
/* */
|
|
||||||
/* <Input> */
|
|
||||||
/* memory :: A pointer to the memory object. */
|
|
||||||
/* */
|
|
||||||
/* cur_size :: The current size of the allocated memory block. */
|
|
||||||
/* */
|
|
||||||
/* new_size :: The newly requested size in bytes. */
|
|
||||||
/* */
|
|
||||||
/* block :: The current address of the block in memory. */
|
|
||||||
/* */
|
|
||||||
/* <Return> */
|
|
||||||
/* The address of the reallocated memory block. */
|
|
||||||
/* */
|
|
||||||
FT_CALLBACK_DEF( void* )
|
|
||||||
ft_realloc( FT_Memory memory,
|
|
||||||
long cur_size,
|
|
||||||
long new_size,
|
|
||||||
void* block )
|
|
||||||
{
|
|
||||||
FT_UNUSED( memory );
|
|
||||||
FT_UNUSED( cur_size );
|
|
||||||
|
|
||||||
return ft_srealloc( block, (size_t)new_size );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* <Function> */
|
|
||||||
/* ft_free */
|
|
||||||
/* */
|
|
||||||
/* <Description> */
|
|
||||||
/* The memory release function. */
|
|
||||||
/* */
|
|
||||||
/* <Input> */
|
|
||||||
/* memory :: A pointer to the memory object. */
|
|
||||||
/* */
|
|
||||||
/* block :: The address of block in memory to be freed. */
|
|
||||||
/* */
|
|
||||||
FT_CALLBACK_DEF( void )
|
|
||||||
ft_free( FT_Memory memory,
|
|
||||||
void* block )
|
|
||||||
{
|
|
||||||
FT_UNUSED( memory );
|
|
||||||
|
|
||||||
ft_sfree( block );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* RESOURCE MANAGEMENT INTERFACE */
|
/* RESOURCE MANAGEMENT INTERFACE */
|
||||||
@ -269,52 +172,4 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT */
|
#endif /* !FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT */
|
||||||
|
|
||||||
#ifdef FT_DEBUG_MEMORY
|
|
||||||
|
|
||||||
extern FT_Int
|
|
||||||
ft_mem_debug_init( FT_Memory memory );
|
|
||||||
|
|
||||||
extern void
|
|
||||||
ft_mem_debug_done( FT_Memory memory );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* documentation is in ftobjs.h */
|
|
||||||
|
|
||||||
FT_BASE_DEF( FT_Memory )
|
|
||||||
FT_New_Memory( void )
|
|
||||||
{
|
|
||||||
FT_Memory memory;
|
|
||||||
|
|
||||||
|
|
||||||
memory = (FT_Memory)ft_smalloc( sizeof ( *memory ) );
|
|
||||||
if ( memory )
|
|
||||||
{
|
|
||||||
memory->user = NULL;
|
|
||||||
memory->alloc = ft_alloc;
|
|
||||||
memory->realloc = ft_realloc;
|
|
||||||
memory->free = ft_free;
|
|
||||||
#ifdef FT_DEBUG_MEMORY
|
|
||||||
ft_mem_debug_init( memory );
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* documentation is in ftobjs.h */
|
|
||||||
|
|
||||||
FT_BASE_DEF( void )
|
|
||||||
FT_Done_Memory( FT_Memory memory )
|
|
||||||
{
|
|
||||||
#ifdef FT_DEBUG_MEMORY
|
|
||||||
ft_mem_debug_done( memory );
|
|
||||||
#endif
|
|
||||||
ft_sfree( memory );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* END */
|
/* END */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user