e5680279b2
drastically reduce the heap usage of FreeType, especially in the case of memory-mapped files. The idea is to avoid loading and decoding tables in the heap, and instead access the raw data whenever possible (i.e. when it doesn't compromise performance). This had several impacts: first, opening vera.ttf uses a ridiculous amount of memory (when the FT_Library footprint is accounted for), until you start loading glyphs. Even then, you'll save at least 20 Kb compared to the non optimized case. performance of various operations, including open/close has also been dramatically improved. More optimisations to come. The auto-hinter eats memory like crazy? This must be stopped...
431 lines
19 KiB
C
431 lines
19 KiB
C
/***************************************************************************/
|
|
/* */
|
|
/* ttdriver.c */
|
|
/* */
|
|
/* TrueType font driver implementation (body). */
|
|
/* */
|
|
/* Copyright 1996-2001, 2002, 2003, 2004 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_INTERNAL_DEBUG_H
|
|
#include FT_INTERNAL_STREAM_H
|
|
#include FT_INTERNAL_SFNT_H
|
|
#include FT_TRUETYPE_IDS_H
|
|
#include FT_SERVICE_XFREE86_NAME_H
|
|
|
|
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
|
|
#include FT_MULTIPLE_MASTERS_H
|
|
#include FT_SERVICE_MULTIPLE_MASTERS_H
|
|
#endif
|
|
|
|
#include "ttdriver.h"
|
|
#include "ttgload.h"
|
|
|
|
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
|
|
#include "ttgxvar.h"
|
|
#endif
|
|
|
|
#include "tterrors.h"
|
|
|
|
|
|
/*************************************************************************/
|
|
/* */
|
|
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
|
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
|
/* messages during execution. */
|
|
/* */
|
|
#undef FT_COMPONENT
|
|
#define FT_COMPONENT trace_ttdriver
|
|
|
|
|
|
/*************************************************************************/
|
|
/*************************************************************************/
|
|
/*************************************************************************/
|
|
/**** ****/
|
|
/**** ****/
|
|
/**** F A C E S ****/
|
|
/**** ****/
|
|
/**** ****/
|
|
/*************************************************************************/
|
|
/*************************************************************************/
|
|
/*************************************************************************/
|
|
|
|
|
|
#undef PAIR_TAG
|
|
#define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \
|
|
(FT_ULong)right )
|
|
|
|
|
|
/*************************************************************************/
|
|
/* */
|
|
/* <Function> */
|
|
/* tt_get_kerning */
|
|
/* */
|
|
/* <Description> */
|
|
/* A driver method used to return the kerning vector between two */
|
|
/* glyphs of the same face. */
|
|
/* */
|
|
/* <Input> */
|
|
/* face :: A handle to the source face object. */
|
|
/* */
|
|
/* left_glyph :: The index of the left glyph in the kern pair. */
|
|
/* */
|
|
/* right_glyph :: The index of the right glyph in the kern pair. */
|
|
/* */
|
|
/* <Output> */
|
|
/* kerning :: The kerning vector. This is in font units for */
|
|
/* scalable formats, and in pixels for fixed-sizes */
|
|
/* formats. */
|
|
/* */
|
|
/* <Return> */
|
|
/* FreeType error code. 0 means success. */
|
|
/* */
|
|
/* <Note> */
|
|
/* Only horizontal layouts (left-to-right & right-to-left) are */
|
|
/* supported by this function. Other layouts, or more sophisticated */
|
|
/* kernings, are out of scope of this method (the basic driver */
|
|
/* interface is meant to be simple). */
|
|
/* */
|
|
/* They can be implemented by format-specific interfaces. */
|
|
/* */
|
|
static FT_Error
|
|
tt_get_kerning( FT_Face ttface, /* TT_Face */
|
|
FT_UInt left_glyph,
|
|
FT_UInt right_glyph,
|
|
FT_Vector* kerning )
|
|
{
|
|
TT_Face face = (TT_Face)ttface;
|
|
SFNT_Service sfnt = (SFNT_Service) face->sfnt;
|
|
|
|
kerning->x = 0;
|
|
kerning->y = 0;
|
|
|
|
if ( sfnt )
|
|
kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph );
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
#undef PAIR_TAG
|
|
|
|
|
|
/*************************************************************************/
|
|
/*************************************************************************/
|
|
/*************************************************************************/
|
|
/**** ****/
|
|
/**** ****/
|
|
/**** S I Z E S ****/
|
|
/**** ****/
|
|
/**** ****/
|
|
/*************************************************************************/
|
|
/*************************************************************************/
|
|
/*************************************************************************/
|
|
|
|
|
|
/*************************************************************************/
|
|
/* */
|
|
/* <Function> */
|
|
/* Set_Char_Sizes */
|
|
/* */
|
|
/* <Description> */
|
|
/* A driver method used to reset a size's character sizes (horizontal */
|
|
/* and vertical) expressed in fractional points. */
|
|
/* */
|
|
/* <Input> */
|
|
/* char_width :: The character width expressed in 26.6 */
|
|
/* fractional points. */
|
|
/* */
|
|
/* char_height :: The character height expressed in 26.6 */
|
|
/* fractional points. */
|
|
/* */
|
|
/* horz_resolution :: The horizontal resolution of the output device. */
|
|
/* */
|
|
/* vert_resolution :: The vertical resolution of the output device. */
|
|
/* */
|
|
/* <InOut> */
|
|
/* size :: A handle to the target size object. */
|
|
/* */
|
|
/* <Return> */
|
|
/* FreeType error code. 0 means success. */
|
|
/* */
|
|
static FT_Error
|
|
Set_Char_Sizes( FT_Size ttsize, /* TT_Size */
|
|
FT_F26Dot6 char_width,
|
|
FT_F26Dot6 char_height,
|
|
FT_UInt horz_resolution,
|
|
FT_UInt vert_resolution )
|
|
{
|
|
TT_Size size = (TT_Size)ttsize;
|
|
FT_Size_Metrics* metrics = &size->root.metrics;
|
|
FT_Size_Metrics* metrics2 = &size->metrics;
|
|
TT_Face face = (TT_Face)size->root.face;
|
|
FT_Long dim_x, dim_y;
|
|
|
|
|
|
*metrics2 = *metrics;
|
|
|
|
/* This bit flag, when set, indicates that the pixel size must be */
|
|
/* truncated to an integer. Nearly all TrueType fonts have this */
|
|
/* bit set, as hinting won't work really well otherwise. */
|
|
/* */
|
|
if ( ( face->header.Flags & 8 ) != 0 )
|
|
{
|
|
/* we need to use rounding in the following computations. Otherwise,
|
|
* the resulting hinted outlines will be very slightly distorted
|
|
*/
|
|
dim_x = ( ( char_width * horz_resolution + (36+32*72) ) / 72 ) & ~63;
|
|
dim_y = ( ( char_height * vert_resolution + (36+32*72) ) / 72 ) & ~63;
|
|
}
|
|
else
|
|
{
|
|
dim_x = ( ( char_width * horz_resolution + 36 ) / 72 );
|
|
dim_y = ( ( char_height * vert_resolution + 36 ) / 72 );
|
|
}
|
|
|
|
/* we only modify "metrics2", not "metrics", so these changes have */
|
|
/* no effect on the result of the auto-hinter when it is used */
|
|
/* */
|
|
metrics2->x_ppem = (FT_UShort)( dim_x >> 6 );
|
|
metrics2->y_ppem = (FT_UShort)( dim_y >> 6 );
|
|
metrics2->x_scale = FT_DivFix( dim_x, face->root.units_per_EM );
|
|
metrics2->y_scale = FT_DivFix( dim_y, face->root.units_per_EM );
|
|
|
|
size->ttmetrics.valid = FALSE;
|
|
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
|
|
size->strike_index = 0xFFFFU;
|
|
#endif
|
|
|
|
return tt_size_reset( size );
|
|
}
|
|
|
|
|
|
/*************************************************************************/
|
|
/* */
|
|
/* <Function> */
|
|
/* Set_Pixel_Sizes */
|
|
/* */
|
|
/* <Description> */
|
|
/* A driver method used to reset a size's character sizes (horizontal */
|
|
/* and vertical) expressed in integer pixels. */
|
|
/* */
|
|
/* <InOut> */
|
|
/* size :: A handle to the target size object. */
|
|
/* */
|
|
/* <Return> */
|
|
/* FreeType error code. 0 means success. */
|
|
/* */
|
|
static FT_Error
|
|
Set_Pixel_Sizes( FT_Size ttsize, /* TT_Size */
|
|
FT_UInt pixel_width,
|
|
FT_UInt pixel_height )
|
|
{
|
|
TT_Size size = (TT_Size)ttsize;
|
|
|
|
FT_UNUSED( pixel_width );
|
|
FT_UNUSED( pixel_height );
|
|
|
|
|
|
/* many things have been pre-computed by the base layer */
|
|
|
|
size->metrics = size->root.metrics;
|
|
size->ttmetrics.valid = FALSE;
|
|
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
|
|
size->strike_index = 0xFFFFU;
|
|
#endif
|
|
|
|
return tt_size_reset( size );
|
|
}
|
|
|
|
|
|
/*************************************************************************/
|
|
/* */
|
|
/* <Function> */
|
|
/* Load_Glyph */
|
|
/* */
|
|
/* <Description> */
|
|
/* A driver method used to load a glyph within a given glyph slot. */
|
|
/* */
|
|
/* <Input> */
|
|
/* slot :: A handle to the target slot object where the glyph */
|
|
/* will be loaded. */
|
|
/* */
|
|
/* size :: A handle to the source face size at which the glyph */
|
|
/* must be scaled, loaded, etc. */
|
|
/* */
|
|
/* glyph_index :: The index of the glyph in the font file. */
|
|
/* */
|
|
/* load_flags :: A flag indicating what to load for this glyph. The */
|
|
/* FTLOAD_??? constants can be used to control the */
|
|
/* glyph loading process (e.g., whether the outline */
|
|
/* should be scaled, whether to load bitmaps or not, */
|
|
/* whether to hint the outline, etc). */
|
|
/* */
|
|
/* <Return> */
|
|
/* FreeType error code. 0 means success. */
|
|
/* */
|
|
static FT_Error
|
|
Load_Glyph( FT_GlyphSlot ttslot, /* TT_GlyphSlot */
|
|
FT_Size ttsize, /* TT_Size */
|
|
FT_UInt glyph_index,
|
|
FT_Int32 load_flags )
|
|
{
|
|
TT_GlyphSlot slot = (TT_GlyphSlot)ttslot;
|
|
TT_Size size = (TT_Size)ttsize;
|
|
FT_Error error;
|
|
|
|
|
|
if ( !slot )
|
|
return TT_Err_Invalid_Slot_Handle;
|
|
|
|
/* check whether we want a scaled outline or bitmap */
|
|
if ( !size )
|
|
load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
|
|
|
|
if ( load_flags & FT_LOAD_NO_SCALE )
|
|
size = NULL;
|
|
|
|
/* reset the size object if necessary */
|
|
if ( size )
|
|
{
|
|
/* these two object must have the same parent */
|
|
if ( size->root.face != slot->face )
|
|
return TT_Err_Invalid_Face_Handle;
|
|
|
|
if ( !size->ttmetrics.valid )
|
|
{
|
|
if ( FT_SET_ERROR( tt_size_reset( size ) ) )
|
|
return error;
|
|
}
|
|
}
|
|
|
|
/* now load the glyph outline if necessary */
|
|
error = TT_Load_Glyph( size, slot, glyph_index, load_flags );
|
|
|
|
/* force drop-out mode to 2 - irrelevant now */
|
|
/* slot->outline.dropout_mode = 2; */
|
|
|
|
return error;
|
|
}
|
|
|
|
|
|
/*************************************************************************/
|
|
/*************************************************************************/
|
|
/*************************************************************************/
|
|
/**** ****/
|
|
/**** ****/
|
|
/**** D R I V E R I N T E R F A C E ****/
|
|
/**** ****/
|
|
/**** ****/
|
|
/*************************************************************************/
|
|
/*************************************************************************/
|
|
/*************************************************************************/
|
|
|
|
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
|
|
static const FT_Service_MultiMastersRec tt_service_gx_multi_masters =
|
|
{
|
|
(FT_Get_MM_Func) NULL,
|
|
(FT_Set_MM_Design_Func) NULL,
|
|
(FT_Set_MM_Blend_Func) TT_Set_MM_Blend,
|
|
(FT_Get_MM_Var_Func) TT_Get_MM_Var,
|
|
(FT_Set_Var_Design_Func)TT_Set_Var_Design
|
|
};
|
|
#endif
|
|
|
|
|
|
static const FT_ServiceDescRec tt_services[] =
|
|
{
|
|
{ FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_TRUETYPE },
|
|
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
|
|
{ FT_SERVICE_ID_MULTI_MASTERS, &tt_service_gx_multi_masters },
|
|
#endif
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
|
|
FT_CALLBACK_DEF( FT_Module_Interface )
|
|
tt_get_interface( FT_Module driver, /* TT_Driver */
|
|
const char* tt_interface )
|
|
{
|
|
FT_Module_Interface result;
|
|
FT_Module sfntd;
|
|
SFNT_Service sfnt;
|
|
|
|
|
|
result = ft_service_list_lookup( tt_services, tt_interface );
|
|
if ( result != NULL )
|
|
return result;
|
|
|
|
/* only return the default interface from the SFNT module */
|
|
sfntd = FT_Get_Module( driver->library, "sfnt" );
|
|
if ( sfntd )
|
|
{
|
|
sfnt = (SFNT_Service)( sfntd->clazz->module_interface );
|
|
if ( sfnt )
|
|
return sfnt->get_interface( driver, tt_interface );
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* The FT_DriverInterface structure is defined in ftdriver.h. */
|
|
|
|
FT_CALLBACK_TABLE_DEF
|
|
const FT_Driver_ClassRec tt_driver_class =
|
|
{
|
|
{
|
|
FT_MODULE_FONT_DRIVER |
|
|
FT_MODULE_DRIVER_SCALABLE |
|
|
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
|
|
FT_MODULE_DRIVER_HAS_HINTER,
|
|
#else
|
|
0,
|
|
#endif
|
|
|
|
sizeof ( TT_DriverRec ),
|
|
|
|
"truetype", /* driver name */
|
|
0x10000L, /* driver version == 1.0 */
|
|
0x20000L, /* driver requires FreeType 2.0 or above */
|
|
|
|
(void*)0, /* driver specific interface */
|
|
|
|
tt_driver_init,
|
|
tt_driver_done,
|
|
tt_get_interface,
|
|
},
|
|
|
|
sizeof ( TT_FaceRec ),
|
|
sizeof ( TT_SizeRec ),
|
|
sizeof ( FT_GlyphSlotRec ),
|
|
|
|
tt_face_init,
|
|
tt_face_done,
|
|
tt_size_init,
|
|
tt_size_done,
|
|
0, /* FT_Slot_InitFunc */
|
|
0, /* FT_Slot_DoneFunc */
|
|
|
|
Set_Char_Sizes,
|
|
Set_Pixel_Sizes,
|
|
Load_Glyph,
|
|
|
|
tt_get_kerning,
|
|
0, /* FT_Face_AttachFunc */
|
|
0 /* FT_Face_GetAdvancesFunc */
|
|
};
|
|
|
|
|
|
/* END */
|