added dependencies and build files (loosely inspired by Sebastian Dorda's love-native-android)

This commit is contained in:
Martin Felis
2013-12-05 17:58:37 +01:00
parent 9604528a96
commit 95a086a47f
3700 changed files with 1691119 additions and 0 deletions
+39
View File
@@ -0,0 +1,39 @@
# FreeType 2 src/autofit Jamfile
#
# Copyright 2003, 2004, 2005, 2006, 2007, 2009 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.
SubDir FT2_TOP src autofit ;
{
local _sources ;
# define FT2_AUTOFIT2 to enable experimental latin hinter replacement
if $(FT2_AUTOFIT2)
{
DEFINES += FT_OPTION_AUTOFIT2 ;
}
if $(FT2_MULTI)
{
_sources = afangles afglobal afhints aflatin afcjk afindic afloader afmodule afdummy afwarp afpic ;
if $(FT2_AUTOFIT2)
{
_sources += aflatin2 ;
}
}
else
{
_sources = autofit ;
}
Library $(FT2_LIB) : $(_sources).c ;
}
# end of src/autofit Jamfile
@@ -0,0 +1,292 @@
/***************************************************************************/
/* */
/* afangles.c */
/* */
/* Routines used to compute vector angles with limited accuracy */
/* and very high speed. It also contains sorting routines (body). */
/* */
/* Copyright 2003, 2004, 2005, 2006 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 "aftypes.h"
#if 0
FT_LOCAL_DEF( FT_Int )
af_corner_is_flat( FT_Pos x_in,
FT_Pos y_in,
FT_Pos x_out,
FT_Pos y_out )
{
FT_Pos ax = x_in;
FT_Pos ay = y_in;
FT_Pos d_in, d_out, d_corner;
if ( ax < 0 )
ax = -ax;
if ( ay < 0 )
ay = -ay;
d_in = ax + ay;
ax = x_out;
if ( ax < 0 )
ax = -ax;
ay = y_out;
if ( ay < 0 )
ay = -ay;
d_out = ax + ay;
ax = x_out + x_in;
if ( ax < 0 )
ax = -ax;
ay = y_out + y_in;
if ( ay < 0 )
ay = -ay;
d_corner = ax + ay;
return ( d_in + d_out - d_corner ) < ( d_corner >> 4 );
}
FT_LOCAL_DEF( FT_Int )
af_corner_orientation( FT_Pos x_in,
FT_Pos y_in,
FT_Pos x_out,
FT_Pos y_out )
{
FT_Pos delta;
delta = x_in * y_out - y_in * x_out;
if ( delta == 0 )
return 0;
else
return 1 - 2 * ( delta < 0 );
}
#endif
/*
* We are not using `af_angle_atan' anymore, but we keep the source
* code below just in case...
*/
#if 0
/*
* The trick here is to realize that we don't need a very accurate angle
* approximation. We are going to use the result of `af_angle_atan' to
* only compare the sign of angle differences, or check whether its
* magnitude is very small.
*
* The approximation
*
* dy * PI / (|dx|+|dy|)
*
* should be enough, and much faster to compute.
*/
FT_LOCAL_DEF( AF_Angle )
af_angle_atan( FT_Fixed dx,
FT_Fixed dy )
{
AF_Angle angle;
FT_Fixed ax = dx;
FT_Fixed ay = dy;
if ( ax < 0 )
ax = -ax;
if ( ay < 0 )
ay = -ay;
ax += ay;
if ( ax == 0 )
angle = 0;
else
{
angle = ( AF_ANGLE_PI2 * dy ) / ( ax + ay );
if ( dx < 0 )
{
if ( angle >= 0 )
angle = AF_ANGLE_PI - angle;
else
angle = -AF_ANGLE_PI - angle;
}
}
return angle;
}
#elif 0
/* the following table has been automatically generated with */
/* the `mather.py' Python script */
#define AF_ATAN_BITS 8
static const FT_Byte af_arctan[1L << AF_ATAN_BITS] =
{
0, 0, 1, 1, 1, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 5,
5, 5, 6, 6, 6, 7, 7, 7,
8, 8, 8, 9, 9, 9, 10, 10,
10, 10, 11, 11, 11, 12, 12, 12,
13, 13, 13, 14, 14, 14, 14, 15,
15, 15, 16, 16, 16, 17, 17, 17,
18, 18, 18, 18, 19, 19, 19, 20,
20, 20, 21, 21, 21, 21, 22, 22,
22, 23, 23, 23, 24, 24, 24, 24,
25, 25, 25, 26, 26, 26, 26, 27,
27, 27, 28, 28, 28, 28, 29, 29,
29, 30, 30, 30, 30, 31, 31, 31,
31, 32, 32, 32, 33, 33, 33, 33,
34, 34, 34, 34, 35, 35, 35, 35,
36, 36, 36, 36, 37, 37, 37, 38,
38, 38, 38, 39, 39, 39, 39, 40,
40, 40, 40, 41, 41, 41, 41, 42,
42, 42, 42, 42, 43, 43, 43, 43,
44, 44, 44, 44, 45, 45, 45, 45,
46, 46, 46, 46, 46, 47, 47, 47,
47, 48, 48, 48, 48, 48, 49, 49,
49, 49, 50, 50, 50, 50, 50, 51,
51, 51, 51, 51, 52, 52, 52, 52,
52, 53, 53, 53, 53, 53, 54, 54,
54, 54, 54, 55, 55, 55, 55, 55,
56, 56, 56, 56, 56, 57, 57, 57,
57, 57, 57, 58, 58, 58, 58, 58,
59, 59, 59, 59, 59, 59, 60, 60,
60, 60, 60, 61, 61, 61, 61, 61,
61, 62, 62, 62, 62, 62, 62, 63,
63, 63, 63, 63, 63, 64, 64, 64
};
FT_LOCAL_DEF( AF_Angle )
af_angle_atan( FT_Fixed dx,
FT_Fixed dy )
{
AF_Angle angle;
/* check trivial cases */
if ( dy == 0 )
{
angle = 0;
if ( dx < 0 )
angle = AF_ANGLE_PI;
return angle;
}
else if ( dx == 0 )
{
angle = AF_ANGLE_PI2;
if ( dy < 0 )
angle = -AF_ANGLE_PI2;
return angle;
}
angle = 0;
if ( dx < 0 )
{
dx = -dx;
dy = -dy;
angle = AF_ANGLE_PI;
}
if ( dy < 0 )
{
FT_Pos tmp;
tmp = dx;
dx = -dy;
dy = tmp;
angle -= AF_ANGLE_PI2;
}
if ( dx == 0 && dy == 0 )
return 0;
if ( dx == dy )
angle += AF_ANGLE_PI4;
else if ( dx > dy )
angle += af_arctan[FT_DivFix( dy, dx ) >> ( 16 - AF_ATAN_BITS )];
else
angle += AF_ANGLE_PI2 -
af_arctan[FT_DivFix( dx, dy ) >> ( 16 - AF_ATAN_BITS )];
if ( angle > AF_ANGLE_PI )
angle -= AF_ANGLE_2PI;
return angle;
}
#endif /* 0 */
FT_LOCAL_DEF( void )
af_sort_pos( FT_UInt count,
FT_Pos* table )
{
FT_UInt i, j;
FT_Pos swap;
for ( i = 1; i < count; i++ )
{
for ( j = i; j > 0; j-- )
{
if ( table[j] > table[j - 1] )
break;
swap = table[j];
table[j] = table[j - 1];
table[j - 1] = swap;
}
}
}
FT_LOCAL_DEF( void )
af_sort_widths( FT_UInt count,
AF_Width table )
{
FT_UInt i, j;
AF_WidthRec swap;
for ( i = 1; i < count; i++ )
{
for ( j = i; j > 0; j-- )
{
if ( table[j].org > table[j - 1].org )
break;
swap = table[j];
table[j] = table[j - 1];
table[j - 1] = swap;
}
}
}
/* END */
@@ -0,0 +1,7 @@
/*
* afangles.h
*
* This is a dummy file, used to please the build system. It is never
* included by the auto-fitter sources.
*
*/
File diff suppressed because it is too large Load Diff
+57
View File
@@ -0,0 +1,57 @@
/***************************************************************************/
/* */
/* afcjk.h */
/* */
/* Auto-fitter hinting routines for CJK script (specification). */
/* */
/* Copyright 2006, 2007 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. */
/* */
/***************************************************************************/
#ifndef __AFCJK_H__
#define __AFCJK_H__
#include "afhints.h"
FT_BEGIN_HEADER
/* the CJK-specific script class */
AF_DECLARE_SCRIPT_CLASS(af_cjk_script_class)
FT_LOCAL( FT_Error )
af_cjk_metrics_init( AF_LatinMetrics metrics,
FT_Face face );
FT_LOCAL( void )
af_cjk_metrics_scale( AF_LatinMetrics metrics,
AF_Scaler scaler );
FT_LOCAL( FT_Error )
af_cjk_hints_init( AF_GlyphHints hints,
AF_LatinMetrics metrics );
FT_LOCAL( FT_Error )
af_cjk_hints_apply( AF_GlyphHints hints,
FT_Outline* outline,
AF_LatinMetrics metrics );
/* */
FT_END_HEADER
#endif /* __AFCJK_H__ */
/* END */
@@ -0,0 +1,60 @@
/***************************************************************************/
/* */
/* afdummy.c */
/* */
/* Auto-fitter dummy routines to be used if no hinting should be */
/* performed (body). */
/* */
/* Copyright 2003, 2004, 2005 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 "afdummy.h"
#include "afhints.h"
static FT_Error
af_dummy_hints_init( AF_GlyphHints hints,
AF_ScriptMetrics metrics )
{
af_glyph_hints_rescale( hints,
metrics );
return 0;
}
static FT_Error
af_dummy_hints_apply( AF_GlyphHints hints,
FT_Outline* outline )
{
FT_UNUSED( hints );
FT_UNUSED( outline );
return 0;
}
AF_DEFINE_SCRIPT_CLASS(af_dummy_script_class,
AF_SCRIPT_NONE,
NULL,
sizeof( AF_ScriptMetricsRec ),
(AF_Script_InitMetricsFunc) NULL,
(AF_Script_ScaleMetricsFunc)NULL,
(AF_Script_DoneMetricsFunc) NULL,
(AF_Script_InitHintsFunc) af_dummy_hints_init,
(AF_Script_ApplyHintsFunc) af_dummy_hints_apply
)
/* END */
@@ -0,0 +1,42 @@
/***************************************************************************/
/* */
/* afdummy.h */
/* */
/* Auto-fitter dummy routines to be used if no hinting should be */
/* performed (specification). */
/* */
/* Copyright 2003, 2004, 2005 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. */
/* */
/***************************************************************************/
#ifndef __AFDUMMY_H__
#define __AFDUMMY_H__
#include "aftypes.h"
FT_BEGIN_HEADER
/* A dummy script metrics class used when no hinting should
* be performed. This is the default for non-latin glyphs!
*/
AF_DECLARE_SCRIPT_CLASS(af_dummy_script_class)
/* */
FT_END_HEADER
#endif /* __AFDUMMY_H__ */
/* END */
@@ -0,0 +1,40 @@
/***************************************************************************/
/* */
/* aferrors.h */
/* */
/* Autofitter error codes (specification only). */
/* */
/* Copyright 2005 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. */
/* */
/***************************************************************************/
/*************************************************************************/
/* */
/* This file is used to define the Autofitter error enumeration */
/* constants. */
/* */
/*************************************************************************/
#ifndef __AFERRORS_H__
#define __AFERRORS_H__
#include FT_MODULE_ERRORS_H
#undef __FTERRORS_H__
#define FT_ERR_PREFIX AF_Err_
#define FT_ERR_BASE FT_Mod_Err_Autofit
#include FT_ERRORS_H
#endif /* __AFERRORS_H__ */
/* END */
@@ -0,0 +1,323 @@
/***************************************************************************/
/* */
/* afglobal.c */
/* */
/* Auto-fitter routines to compute global hinting values (body). */
/* */
/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 "afglobal.h"
#include "afdummy.h"
#include "aflatin.h"
#include "afcjk.h"
#include "afindic.h"
#include "afpic.h"
#include "aferrors.h"
#ifdef FT_OPTION_AUTOFIT2
#include "aflatin2.h"
#endif
#ifndef FT_CONFIG_OPTION_PIC
/* when updating this table, don't forget to update
AF_SCRIPT_CLASSES_COUNT and autofit_module_class_pic_init */
/* populate this list when you add new scripts */
static AF_ScriptClass const af_script_classes[] =
{
&af_dummy_script_class,
#ifdef FT_OPTION_AUTOFIT2
&af_latin2_script_class,
#endif
&af_latin_script_class,
&af_cjk_script_class,
&af_indic_script_class,
NULL /* do not remove */
};
#endif /* FT_CONFIG_OPTION_PIC */
/* index of default script in `af_script_classes' */
#define AF_SCRIPT_LIST_DEFAULT 2
/* a bit mask indicating an uncovered glyph */
#define AF_SCRIPT_LIST_NONE 0x7F
/* if this flag is set, we have an ASCII digit */
#define AF_DIGIT 0x80
/*
* Note that glyph_scripts[] is used to map each glyph into
* an index into the `af_script_classes' array.
*
*/
typedef struct AF_FaceGlobalsRec_
{
FT_Face face;
FT_Long glyph_count; /* same as face->num_glyphs */
FT_Byte* glyph_scripts;
AF_ScriptMetrics metrics[AF_SCRIPT_MAX];
} AF_FaceGlobalsRec;
/* Compute the script index of each glyph within a given face. */
static FT_Error
af_face_globals_compute_script_coverage( AF_FaceGlobals globals )
{
FT_Error error = AF_Err_Ok;
FT_Face face = globals->face;
FT_CharMap old_charmap = face->charmap;
FT_Byte* gscripts = globals->glyph_scripts;
FT_UInt ss, i;
/* the value 255 means `uncovered glyph' */
FT_MEM_SET( globals->glyph_scripts,
AF_SCRIPT_LIST_NONE,
globals->glyph_count );
error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
if ( error )
{
/*
* Ignore this error; we simply use the default script.
* XXX: Shouldn't we rather disable hinting?
*/
error = AF_Err_Ok;
goto Exit;
}
/* scan each script in a Unicode charmap */
for ( ss = 0; AF_SCRIPT_CLASSES_GET[ss]; ss++ )
{
AF_ScriptClass clazz = AF_SCRIPT_CLASSES_GET[ss];
AF_Script_UniRange range;
if ( clazz->script_uni_ranges == NULL )
continue;
/*
* Scan all unicode points in the range and set the corresponding
* glyph script index.
*/
for ( range = clazz->script_uni_ranges; range->first != 0; range++ )
{
FT_ULong charcode = range->first;
FT_UInt gindex;
gindex = FT_Get_Char_Index( face, charcode );
if ( gindex != 0 &&
gindex < (FT_ULong)globals->glyph_count &&
gscripts[gindex] == AF_SCRIPT_LIST_NONE )
{
gscripts[gindex] = (FT_Byte)ss;
}
for (;;)
{
charcode = FT_Get_Next_Char( face, charcode, &gindex );
if ( gindex == 0 || charcode > range->last )
break;
if ( gindex < (FT_ULong)globals->glyph_count &&
gscripts[gindex] == AF_SCRIPT_LIST_NONE )
{
gscripts[gindex] = (FT_Byte)ss;
}
}
}
}
/* mark ASCII digits */
for ( i = 0x30; i <= 0x39; i++ )
{
FT_UInt gindex = FT_Get_Char_Index( face, i );
if ( gindex != 0 && gindex < (FT_ULong)globals->glyph_count )
gscripts[gindex] |= AF_DIGIT;
}
Exit:
/*
* By default, all uncovered glyphs are set to the latin script.
* XXX: Shouldn't we disable hinting or do something similar?
*/
{
FT_Long nn;
for ( nn = 0; nn < globals->glyph_count; nn++ )
{
if ( ( gscripts[nn] & ~AF_DIGIT ) == AF_SCRIPT_LIST_NONE )
{
gscripts[nn] &= ~AF_SCRIPT_LIST_NONE;
gscripts[nn] |= AF_SCRIPT_LIST_DEFAULT;
}
}
}
FT_Set_Charmap( face, old_charmap );
return error;
}
FT_LOCAL_DEF( FT_Error )
af_face_globals_new( FT_Face face,
AF_FaceGlobals *aglobals )
{
FT_Error error;
FT_Memory memory;
AF_FaceGlobals globals = NULL;
memory = face->memory;
if ( !FT_ALLOC( globals, sizeof ( *globals ) +
face->num_glyphs * sizeof ( FT_Byte ) ) )
{
globals->face = face;
globals->glyph_count = face->num_glyphs;
globals->glyph_scripts = (FT_Byte*)( globals + 1 );
error = af_face_globals_compute_script_coverage( globals );
if ( error )
{
af_face_globals_free( globals );
globals = NULL;
}
}
*aglobals = globals;
return error;
}
FT_LOCAL_DEF( void )
af_face_globals_free( AF_FaceGlobals globals )
{
if ( globals )
{
FT_Memory memory = globals->face->memory;
FT_UInt nn;
for ( nn = 0; nn < AF_SCRIPT_MAX; nn++ )
{
if ( globals->metrics[nn] )
{
AF_ScriptClass clazz = AF_SCRIPT_CLASSES_GET[nn];
FT_ASSERT( globals->metrics[nn]->clazz == clazz );
if ( clazz->script_metrics_done )
clazz->script_metrics_done( globals->metrics[nn] );
FT_FREE( globals->metrics[nn] );
}
}
globals->glyph_count = 0;
globals->glyph_scripts = NULL; /* no need to free this one! */
globals->face = NULL;
FT_FREE( globals );
}
}
FT_LOCAL_DEF( FT_Error )
af_face_globals_get_metrics( AF_FaceGlobals globals,
FT_UInt gindex,
FT_UInt options,
AF_ScriptMetrics *ametrics )
{
AF_ScriptMetrics metrics = NULL;
FT_UInt gidx;
AF_ScriptClass clazz;
FT_UInt script = options & 15;
const FT_Offset script_max = sizeof ( AF_SCRIPT_CLASSES_GET ) /
sizeof ( AF_SCRIPT_CLASSES_GET[0] );
FT_Error error = AF_Err_Ok;
if ( gindex >= (FT_ULong)globals->glyph_count )
{
error = AF_Err_Invalid_Argument;
goto Exit;
}
gidx = script;
if ( gidx == 0 || gidx + 1 >= script_max )
gidx = globals->glyph_scripts[gindex] & AF_SCRIPT_LIST_NONE;
clazz = AF_SCRIPT_CLASSES_GET[gidx];
if ( script == 0 )
script = clazz->script;
metrics = globals->metrics[clazz->script];
if ( metrics == NULL )
{
/* create the global metrics object when needed */
FT_Memory memory = globals->face->memory;
if ( FT_ALLOC( metrics, clazz->script_metrics_size ) )
goto Exit;
metrics->clazz = clazz;
if ( clazz->script_metrics_init )
{
error = clazz->script_metrics_init( metrics, globals->face );
if ( error )
{
if ( clazz->script_metrics_done )
clazz->script_metrics_done( metrics );
FT_FREE( metrics );
goto Exit;
}
}
globals->metrics[clazz->script] = metrics;
}
Exit:
*ametrics = metrics;
return error;
}
FT_LOCAL_DEF( FT_Bool )
af_face_globals_is_digit( AF_FaceGlobals globals,
FT_UInt gindex )
{
if ( gindex < (FT_ULong)globals->glyph_count )
return (FT_Bool)( globals->glyph_scripts[gindex] & AF_DIGIT );
return (FT_Bool)0;
}
/* END */
@@ -0,0 +1,71 @@
/***************************************************************************/
/* */
/* afglobal.h */
/* */
/* Auto-fitter routines to compute global hinting values */
/* (specification). */
/* */
/* Copyright 2003, 2004, 2005, 2007, 2009 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. */
/* */
/***************************************************************************/
#ifndef __AF_GLOBAL_H__
#define __AF_GLOBAL_H__
#include "aftypes.h"
FT_BEGIN_HEADER
/************************************************************************/
/************************************************************************/
/***** *****/
/***** F A C E G L O B A L S *****/
/***** *****/
/************************************************************************/
/************************************************************************/
/*
* model the global hints data for a given face, decomposed into
* script-specific items
*/
typedef struct AF_FaceGlobalsRec_* AF_FaceGlobals;
FT_LOCAL( FT_Error )
af_face_globals_new( FT_Face face,
AF_FaceGlobals *aglobals );
FT_LOCAL( FT_Error )
af_face_globals_get_metrics( AF_FaceGlobals globals,
FT_UInt gindex,
FT_UInt options,
AF_ScriptMetrics *ametrics );
FT_LOCAL( void )
af_face_globals_free( AF_FaceGlobals globals );
FT_LOCAL_DEF( FT_Bool )
af_face_globals_is_digit( AF_FaceGlobals globals,
FT_UInt gindex );
/* */
FT_END_HEADER
#endif /* __AF_GLOBALS_H__ */
/* END */
File diff suppressed because it is too large Load Diff
+332
View File
@@ -0,0 +1,332 @@
/***************************************************************************/
/* */
/* afhints.h */
/* */
/* Auto-fitter hinting routines (specification). */
/* */
/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2010 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. */
/* */
/***************************************************************************/
#ifndef __AFHINTS_H__
#define __AFHINTS_H__
#include "aftypes.h"
#define xxAF_SORT_SEGMENTS
FT_BEGIN_HEADER
/*
* The definition of outline glyph hints. These are shared by all
* script analysis routines (until now).
*/
typedef enum AF_Dimension_
{
AF_DIMENSION_HORZ = 0, /* x coordinates, */
/* i.e., vertical segments & edges */
AF_DIMENSION_VERT = 1, /* y coordinates, */
/* i.e., horizontal segments & edges */
AF_DIMENSION_MAX /* do not remove */
} AF_Dimension;
/* hint directions -- the values are computed so that two vectors are */
/* in opposite directions iff `dir1 + dir2 == 0' */
typedef enum AF_Direction_
{
AF_DIR_NONE = 4,
AF_DIR_RIGHT = 1,
AF_DIR_LEFT = -1,
AF_DIR_UP = 2,
AF_DIR_DOWN = -2
} AF_Direction;
/* point hint flags */
typedef enum AF_Flags_
{
AF_FLAG_NONE = 0,
/* point type flags */
AF_FLAG_CONIC = 1 << 0,
AF_FLAG_CUBIC = 1 << 1,
AF_FLAG_CONTROL = AF_FLAG_CONIC | AF_FLAG_CUBIC,
/* point extremum flags */
AF_FLAG_EXTREMA_X = 1 << 2,
AF_FLAG_EXTREMA_Y = 1 << 3,
/* point roundness flags */
AF_FLAG_ROUND_X = 1 << 4,
AF_FLAG_ROUND_Y = 1 << 5,
/* point touch flags */
AF_FLAG_TOUCH_X = 1 << 6,
AF_FLAG_TOUCH_Y = 1 << 7,
/* candidates for weak interpolation have this flag set */
AF_FLAG_WEAK_INTERPOLATION = 1 << 8,
/* all inflection points in the outline have this flag set */
AF_FLAG_INFLECTION = 1 << 9
} AF_Flags;
/* edge hint flags */
typedef enum AF_Edge_Flags_
{
AF_EDGE_NORMAL = 0,
AF_EDGE_ROUND = 1 << 0,
AF_EDGE_SERIF = 1 << 1,
AF_EDGE_DONE = 1 << 2
} AF_Edge_Flags;
typedef struct AF_PointRec_* AF_Point;
typedef struct AF_SegmentRec_* AF_Segment;
typedef struct AF_EdgeRec_* AF_Edge;
typedef struct AF_PointRec_
{
FT_UShort flags; /* point flags used by hinter */
FT_Char in_dir; /* direction of inwards vector */
FT_Char out_dir; /* direction of outwards vector */
FT_Pos ox, oy; /* original, scaled position */
FT_Short fx, fy; /* original, unscaled position (font units) */
FT_Pos x, y; /* current position */
FT_Pos u, v; /* current (x,y) or (y,x) depending on context */
AF_Point next; /* next point in contour */
AF_Point prev; /* previous point in contour */
} AF_PointRec;
typedef struct AF_SegmentRec_
{
FT_Byte flags; /* edge/segment flags for this segment */
FT_Char dir; /* segment direction */
FT_Short pos; /* position of segment */
FT_Short min_coord; /* minimum coordinate of segment */
FT_Short max_coord; /* maximum coordinate of segment */
FT_Short height; /* the hinted segment height */
AF_Edge edge; /* the segment's parent edge */
AF_Segment edge_next; /* link to next segment in parent edge */
AF_Segment link; /* (stem) link segment */
AF_Segment serif; /* primary segment for serifs */
FT_Pos num_linked; /* number of linked segments */
FT_Pos score; /* used during stem matching */
FT_Pos len; /* used during stem matching */
AF_Point first; /* first point in edge segment */
AF_Point last; /* last point in edge segment */
AF_Point* contour; /* ptr to first point of segment's contour */
} AF_SegmentRec;
typedef struct AF_EdgeRec_
{
FT_Short fpos; /* original, unscaled position (font units) */
FT_Pos opos; /* original, scaled position */
FT_Pos pos; /* current position */
FT_Byte flags; /* edge flags */
FT_Char dir; /* edge direction */
FT_Fixed scale; /* used to speed up interpolation between edges */
AF_Width blue_edge; /* non-NULL if this is a blue edge */
AF_Edge link;
AF_Edge serif;
FT_Short num_linked;
FT_Int score;
AF_Segment first;
AF_Segment last;
} AF_EdgeRec;
typedef struct AF_AxisHintsRec_
{
FT_Int num_segments;
FT_Int max_segments;
AF_Segment segments;
#ifdef AF_SORT_SEGMENTS
FT_Int mid_segments;
#endif
FT_Int num_edges;
FT_Int max_edges;
AF_Edge edges;
AF_Direction major_dir;
} AF_AxisHintsRec, *AF_AxisHints;
typedef struct AF_GlyphHintsRec_
{
FT_Memory memory;
FT_Fixed x_scale;
FT_Pos x_delta;
FT_Fixed y_scale;
FT_Pos y_delta;
FT_Pos edge_distance_threshold;
FT_Int max_points;
FT_Int num_points;
AF_Point points;
FT_Int max_contours;
FT_Int num_contours;
AF_Point* contours;
AF_AxisHintsRec axis[AF_DIMENSION_MAX];
FT_UInt32 scaler_flags; /* copy of scaler flags */
FT_UInt32 other_flags; /* free for script-specific */
/* implementations */
AF_ScriptMetrics metrics;
FT_Pos xmin_delta; /* used for warping */
FT_Pos xmax_delta;
} AF_GlyphHintsRec;
#define AF_HINTS_TEST_SCALER( h, f ) ( (h)->scaler_flags & (f) )
#define AF_HINTS_TEST_OTHER( h, f ) ( (h)->other_flags & (f) )
#ifdef AF_DEBUG
#define AF_HINTS_DO_HORIZONTAL( h ) \
( !_af_debug_disable_horz_hints && \
!AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_HORIZONTAL ) )
#define AF_HINTS_DO_VERTICAL( h ) \
( !_af_debug_disable_vert_hints && \
!AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_VERTICAL ) )
#define AF_HINTS_DO_ADVANCE( h ) \
!AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_ADVANCE )
#define AF_HINTS_DO_BLUES( h ) ( !_af_debug_disable_blue_hints )
#else /* !AF_DEBUG */
#define AF_HINTS_DO_HORIZONTAL( h ) \
!AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_HORIZONTAL )
#define AF_HINTS_DO_VERTICAL( h ) \
!AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_VERTICAL )
#define AF_HINTS_DO_ADVANCE( h ) \
!AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_ADVANCE )
#define AF_HINTS_DO_BLUES( h ) 1
#endif /* !AF_DEBUG */
FT_LOCAL( AF_Direction )
af_direction_compute( FT_Pos dx,
FT_Pos dy );
FT_LOCAL( FT_Error )
af_axis_hints_new_segment( AF_AxisHints axis,
FT_Memory memory,
AF_Segment *asegment );
FT_LOCAL( FT_Error)
af_axis_hints_new_edge( AF_AxisHints axis,
FT_Int fpos,
AF_Direction dir,
FT_Memory memory,
AF_Edge *edge );
FT_LOCAL( void )
af_glyph_hints_init( AF_GlyphHints hints,
FT_Memory memory );
/*
* recompute all AF_Point in a AF_GlyphHints from the definitions
* in a source outline
*/
FT_LOCAL( void )
af_glyph_hints_rescale( AF_GlyphHints hints,
AF_ScriptMetrics metrics );
FT_LOCAL( FT_Error )
af_glyph_hints_reload( AF_GlyphHints hints,
FT_Outline* outline );
FT_LOCAL( void )
af_glyph_hints_save( AF_GlyphHints hints,
FT_Outline* outline );
FT_LOCAL( void )
af_glyph_hints_align_edge_points( AF_GlyphHints hints,
AF_Dimension dim );
FT_LOCAL( void )
af_glyph_hints_align_strong_points( AF_GlyphHints hints,
AF_Dimension dim );
FT_LOCAL( void )
af_glyph_hints_align_weak_points( AF_GlyphHints hints,
AF_Dimension dim );
#ifdef AF_USE_WARPER
FT_LOCAL( void )
af_glyph_hints_scale_dim( AF_GlyphHints hints,
AF_Dimension dim,
FT_Fixed scale,
FT_Pos delta );
#endif
FT_LOCAL( void )
af_glyph_hints_done( AF_GlyphHints hints );
/* */
#define AF_SEGMENT_LEN( seg ) ( (seg)->max_coord - (seg)->min_coord )
#define AF_SEGMENT_DIST( seg1, seg2 ) ( ( (seg1)->pos > (seg2)->pos ) \
? (seg1)->pos - (seg2)->pos \
: (seg2)->pos - (seg1)->pos )
FT_END_HEADER
#endif /* __AFHINTS_H__ */
/* END */
+130
View File
@@ -0,0 +1,130 @@
/***************************************************************************/
/* */
/* afindic.c */
/* */
/* Auto-fitter hinting routines for Indic scripts (body). */
/* */
/* Copyright 2007 by */
/* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. */
/* */
/* 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 "aftypes.h"
#include "aflatin.h"
#ifdef AF_CONFIG_OPTION_INDIC
#include "afindic.h"
#include "aferrors.h"
#include "afcjk.h"
#ifdef AF_USE_WARPER
#include "afwarp.h"
#endif
static FT_Error
af_indic_metrics_init( AF_LatinMetrics metrics,
FT_Face face )
{
/* use CJK routines */
return af_cjk_metrics_init( metrics, face );
}
static void
af_indic_metrics_scale( AF_LatinMetrics metrics,
AF_Scaler scaler )
{
/* use CJK routines */
af_cjk_metrics_scale( metrics, scaler );
}
static FT_Error
af_indic_hints_init( AF_GlyphHints hints,
AF_LatinMetrics metrics )
{
/* use CJK routines */
return af_cjk_hints_init( hints, metrics );
}
static FT_Error
af_indic_hints_apply( AF_GlyphHints hints,
FT_Outline* outline,
AF_LatinMetrics metrics)
{
/* use CJK routines */
return af_cjk_hints_apply( hints, outline, metrics );
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** I N D I C S C R I P T C L A S S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
static const AF_Script_UniRangeRec af_indic_uniranges[] =
{
#if 0
AF_UNIRANGE_REC( 0x0100UL, 0xFFFFUL ), /* why this? */
#endif
AF_UNIRANGE_REC( 0x0900UL, 0x0DFFUL), /* Indic Range */
AF_UNIRANGE_REC( 0UL, 0UL)
};
AF_DEFINE_SCRIPT_CLASS(af_indic_script_class,
AF_SCRIPT_INDIC,
af_indic_uniranges,
sizeof( AF_LatinMetricsRec ),
(AF_Script_InitMetricsFunc) af_indic_metrics_init,
(AF_Script_ScaleMetricsFunc)af_indic_metrics_scale,
(AF_Script_DoneMetricsFunc) NULL,
(AF_Script_InitHintsFunc) af_indic_hints_init,
(AF_Script_ApplyHintsFunc) af_indic_hints_apply
)
#else /* !AF_CONFIG_OPTION_INDIC */
static const AF_Script_UniRangeRec af_indic_uniranges[] =
{
{ 0, 0 }
};
AF_DEFINE_SCRIPT_CLASS(af_indic_script_class,
AF_SCRIPT_INDIC,
af_indic_uniranges,
sizeof( AF_LatinMetricsRec ),
(AF_Script_InitMetricsFunc) NULL,
(AF_Script_ScaleMetricsFunc)NULL,
(AF_Script_DoneMetricsFunc) NULL,
(AF_Script_InitHintsFunc) NULL,
(AF_Script_ApplyHintsFunc) NULL
)
#endif /* !AF_CONFIG_OPTION_INDIC */
/* END */
@@ -0,0 +1,40 @@
/***************************************************************************/
/* */
/* afindic.h */
/* */
/* Auto-fitter hinting routines for Indic scripts (specification). */
/* */
/* Copyright 2007 by */
/* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. */
/* */
/* 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. */
/* */
/***************************************************************************/
#ifndef __AFINDIC_H__
#define __AFINDIC_H__
#include "afhints.h"
FT_BEGIN_HEADER
/* the Indic-specific script class */
AF_DECLARE_SCRIPT_CLASS(af_indic_script_class)
/* */
FT_END_HEADER
#endif /* __AFINDIC_H__ */
/* END */
File diff suppressed because it is too large Load Diff
+212
View File
@@ -0,0 +1,212 @@
/***************************************************************************/
/* */
/* aflatin.h */
/* */
/* Auto-fitter hinting routines for latin script (specification). */
/* */
/* Copyright 2003, 2004, 2005, 2006, 2007, 2009 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. */
/* */
/***************************************************************************/
#ifndef __AFLATIN_H__
#define __AFLATIN_H__
#include "afhints.h"
FT_BEGIN_HEADER
/* the latin-specific script class */
AF_DECLARE_SCRIPT_CLASS(af_latin_script_class)
/* constants are given with units_per_em == 2048 in mind */
#define AF_LATIN_CONSTANT( metrics, c ) \
( ( (c) * (FT_Long)( (AF_LatinMetrics)(metrics) )->units_per_em ) / 2048 )
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** L A T I N G L O B A L M E T R I C S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*
* The following declarations could be embedded in the file `aflatin.c';
* they have been made semi-public to allow alternate script hinters to
* re-use some of them.
*/
/* Latin (global) metrics management */
enum
{
AF_LATIN_BLUE_CAPITAL_TOP,
AF_LATIN_BLUE_CAPITAL_BOTTOM,
AF_LATIN_BLUE_SMALL_F_TOP,
AF_LATIN_BLUE_SMALL_TOP,
AF_LATIN_BLUE_SMALL_BOTTOM,
AF_LATIN_BLUE_SMALL_MINOR,
AF_LATIN_BLUE_MAX
};
#define AF_LATIN_IS_TOP_BLUE( b ) ( (b) == AF_LATIN_BLUE_CAPITAL_TOP || \
(b) == AF_LATIN_BLUE_SMALL_F_TOP || \
(b) == AF_LATIN_BLUE_SMALL_TOP )
#define AF_LATIN_MAX_WIDTHS 16
#define AF_LATIN_MAX_BLUES AF_LATIN_BLUE_MAX
enum
{
AF_LATIN_BLUE_ACTIVE = 1 << 0,
AF_LATIN_BLUE_TOP = 1 << 1,
AF_LATIN_BLUE_ADJUSTMENT = 1 << 2, /* used for scale adjustment */
/* optimization */
AF_LATIN_BLUE_FLAG_MAX
};
typedef struct AF_LatinBlueRec_
{
AF_WidthRec ref;
AF_WidthRec shoot;
FT_UInt flags;
} AF_LatinBlueRec, *AF_LatinBlue;
typedef struct AF_LatinAxisRec_
{
FT_Fixed scale;
FT_Pos delta;
FT_UInt width_count;
AF_WidthRec widths[AF_LATIN_MAX_WIDTHS];
FT_Pos edge_distance_threshold;
FT_Pos standard_width;
FT_Bool extra_light;
/* ignored for horizontal metrics */
FT_Bool control_overshoot;
FT_UInt blue_count;
AF_LatinBlueRec blues[AF_LATIN_BLUE_MAX];
FT_Fixed org_scale;
FT_Pos org_delta;
} AF_LatinAxisRec, *AF_LatinAxis;
typedef struct AF_LatinMetricsRec_
{
AF_ScriptMetricsRec root;
FT_UInt units_per_em;
AF_LatinAxisRec axis[AF_DIMENSION_MAX];
} AF_LatinMetricsRec, *AF_LatinMetrics;
FT_LOCAL( FT_Error )
af_latin_metrics_init( AF_LatinMetrics metrics,
FT_Face face );
FT_LOCAL( void )
af_latin_metrics_scale( AF_LatinMetrics metrics,
AF_Scaler scaler );
FT_LOCAL( void )
af_latin_metrics_init_widths( AF_LatinMetrics metrics,
FT_Face face,
FT_ULong charcode );
FT_LOCAL( void )
af_latin_metrics_check_digits( AF_LatinMetrics metrics,
FT_Face face );
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** L A T I N G L Y P H A N A L Y S I S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
enum
{
AF_LATIN_HINTS_HORZ_SNAP = 1 << 0, /* enable stem width snapping */
AF_LATIN_HINTS_VERT_SNAP = 1 << 1, /* enable stem height snapping */
AF_LATIN_HINTS_STEM_ADJUST = 1 << 2, /* enable stem width/height */
/* adjustment */
AF_LATIN_HINTS_MONO = 1 << 3 /* indicate monochrome */
/* rendering */
};
#define AF_LATIN_HINTS_DO_HORZ_SNAP( h ) \
AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_HORZ_SNAP )
#define AF_LATIN_HINTS_DO_VERT_SNAP( h ) \
AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_VERT_SNAP )
#define AF_LATIN_HINTS_DO_STEM_ADJUST( h ) \
AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_STEM_ADJUST )
#define AF_LATIN_HINTS_DO_MONO( h ) \
AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_MONO )
/*
* This shouldn't normally be exported. However, other scripts might
* like to use this function as-is.
*/
FT_LOCAL( FT_Error )
af_latin_hints_compute_segments( AF_GlyphHints hints,
AF_Dimension dim );
/*
* This shouldn't normally be exported. However, other scripts might
* want to use this function as-is.
*/
FT_LOCAL( void )
af_latin_hints_link_segments( AF_GlyphHints hints,
AF_Dimension dim );
/*
* This shouldn't normally be exported. However, other scripts might
* want to use this function as-is.
*/
FT_LOCAL( FT_Error )
af_latin_hints_compute_edges( AF_GlyphHints hints,
AF_Dimension dim );
FT_LOCAL( FT_Error )
af_latin_hints_detect_features( AF_GlyphHints hints,
AF_Dimension dim );
/* */
FT_END_HEADER
#endif /* __AFLATIN_H__ */
/* END */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,39 @@
/***************************************************************************/
/* */
/* aflatin2.h */
/* */
/* Auto-fitter hinting routines for latin script (specification). */
/* */
/* Copyright 2003, 2004, 2005, 2006, 2007 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. */
/* */
/***************************************************************************/
#ifndef __AFLATIN2_H__
#define __AFLATIN2_H__
#include "afhints.h"
FT_BEGIN_HEADER
/* the latin-specific script class */
AF_DECLARE_SCRIPT_CLASS(af_latin2_script_class)
/* */
FT_END_HEADER
#endif /* __AFLATIN_H__ */
/* END */
@@ -0,0 +1,539 @@
/***************************************************************************/
/* */
/* afloader.c */
/* */
/* Auto-fitter glyph loading routines (body). */
/* */
/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 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 "afloader.h"
#include "afhints.h"
#include "afglobal.h"
#include "aferrors.h"
FT_LOCAL_DEF( FT_Error )
af_loader_init( AF_Loader loader,
FT_Memory memory )
{
FT_ZERO( loader );
af_glyph_hints_init( &loader->hints, memory );
#ifdef AF_DEBUG
_af_debug_hints = &loader->hints;
#endif
return FT_GlyphLoader_New( memory, &loader->gloader );
}
FT_LOCAL_DEF( FT_Error )
af_loader_reset( AF_Loader loader,
FT_Face face )
{
FT_Error error = AF_Err_Ok;
loader->face = face;
loader->globals = (AF_FaceGlobals)face->autohint.data;
FT_GlyphLoader_Rewind( loader->gloader );
if ( loader->globals == NULL )
{
error = af_face_globals_new( face, &loader->globals );
if ( !error )
{
face->autohint.data =
(FT_Pointer)loader->globals;
face->autohint.finalizer =
(FT_Generic_Finalizer)af_face_globals_free;
}
}
return error;
}
FT_LOCAL_DEF( void )
af_loader_done( AF_Loader loader )
{
af_glyph_hints_done( &loader->hints );
loader->face = NULL;
loader->globals = NULL;
#ifdef AF_DEBUG
_af_debug_hints = NULL;
#endif
FT_GlyphLoader_Done( loader->gloader );
loader->gloader = NULL;
}
static FT_Error
af_loader_load_g( AF_Loader loader,
AF_Scaler scaler,
FT_UInt glyph_index,
FT_Int32 load_flags,
FT_UInt depth )
{
FT_Error error;
FT_Face face = loader->face;
FT_GlyphLoader gloader = loader->gloader;
AF_ScriptMetrics metrics = loader->metrics;
AF_GlyphHints hints = &loader->hints;
FT_GlyphSlot slot = face->glyph;
FT_Slot_Internal internal = slot->internal;
error = FT_Load_Glyph( face, glyph_index, load_flags );
if ( error )
goto Exit;
loader->transformed = internal->glyph_transformed;
if ( loader->transformed )
{
FT_Matrix inverse;
loader->trans_matrix = internal->glyph_matrix;
loader->trans_delta = internal->glyph_delta;
inverse = loader->trans_matrix;
FT_Matrix_Invert( &inverse );
FT_Vector_Transform( &loader->trans_delta, &inverse );
}
/* set linear metrics */
slot->linearHoriAdvance = slot->metrics.horiAdvance;
slot->linearVertAdvance = slot->metrics.vertAdvance;
switch ( slot->format )
{
case FT_GLYPH_FORMAT_OUTLINE:
/* translate the loaded glyph when an internal transform is needed */
if ( loader->transformed )
FT_Outline_Translate( &slot->outline,
loader->trans_delta.x,
loader->trans_delta.y );
/* copy the outline points in the loader's current */
/* extra points which is used to keep original glyph coordinates */
error = FT_GLYPHLOADER_CHECK_POINTS( gloader,
slot->outline.n_points + 4,
slot->outline.n_contours );
if ( error )
goto Exit;
FT_ARRAY_COPY( gloader->current.outline.points,
slot->outline.points,
slot->outline.n_points );
FT_ARRAY_COPY( gloader->current.outline.contours,
slot->outline.contours,
slot->outline.n_contours );
FT_ARRAY_COPY( gloader->current.outline.tags,
slot->outline.tags,
slot->outline.n_points );
gloader->current.outline.n_points = slot->outline.n_points;
gloader->current.outline.n_contours = slot->outline.n_contours;
/* compute original horizontal phantom points (and ignore */
/* vertical ones) */
loader->pp1.x = hints->x_delta;
loader->pp1.y = hints->y_delta;
loader->pp2.x = FT_MulFix( slot->metrics.horiAdvance,
hints->x_scale ) + hints->x_delta;
loader->pp2.y = hints->y_delta;
/* be sure to check for spacing glyphs */
if ( slot->outline.n_points == 0 )
goto Hint_Metrics;
/* now load the slot image into the auto-outline and run the */
/* automatic hinting process */
if ( metrics->clazz->script_hints_apply )
metrics->clazz->script_hints_apply( hints,
&gloader->current.outline,
metrics );
/* we now need to hint the metrics according to the change in */
/* width/positioning that occurred during the hinting process */
if ( scaler->render_mode != FT_RENDER_MODE_LIGHT )
{
FT_Pos old_rsb, old_lsb, new_lsb;
FT_Pos pp1x_uh, pp2x_uh;
AF_AxisHints axis = &hints->axis[AF_DIMENSION_HORZ];
AF_Edge edge1 = axis->edges; /* leftmost edge */
AF_Edge edge2 = edge1 +
axis->num_edges - 1; /* rightmost edge */
if ( axis->num_edges > 1 && AF_HINTS_DO_ADVANCE( hints ) )
{
old_rsb = loader->pp2.x - edge2->opos;
old_lsb = edge1->opos;
new_lsb = edge1->pos;
/* remember unhinted values to later account */
/* for rounding errors */
pp1x_uh = new_lsb - old_lsb;
pp2x_uh = edge2->pos + old_rsb;
/* prefer too much space over too little space */
/* for very small sizes */
if ( old_lsb < 24 )
pp1x_uh -= 8;
if ( old_rsb < 24 )
pp2x_uh += 8;
loader->pp1.x = FT_PIX_ROUND( pp1x_uh );
loader->pp2.x = FT_PIX_ROUND( pp2x_uh );
if ( loader->pp1.x >= new_lsb && old_lsb > 0 )
loader->pp1.x -= 64;
if ( loader->pp2.x <= edge2->pos && old_rsb > 0 )
loader->pp2.x += 64;
slot->lsb_delta = loader->pp1.x - pp1x_uh;
slot->rsb_delta = loader->pp2.x - pp2x_uh;
}
else
{
FT_Pos pp1x = loader->pp1.x;
FT_Pos pp2x = loader->pp2.x;
loader->pp1.x = FT_PIX_ROUND( pp1x );
loader->pp2.x = FT_PIX_ROUND( pp2x );
slot->lsb_delta = loader->pp1.x - pp1x;
slot->rsb_delta = loader->pp2.x - pp2x;
}
}
else
{
FT_Pos pp1x = loader->pp1.x;
FT_Pos pp2x = loader->pp2.x;
loader->pp1.x = FT_PIX_ROUND( pp1x + hints->xmin_delta );
loader->pp2.x = FT_PIX_ROUND( pp2x + hints->xmax_delta );
slot->lsb_delta = loader->pp1.x - pp1x;
slot->rsb_delta = loader->pp2.x - pp2x;
}
/* good, we simply add the glyph to our loader's base */
FT_GlyphLoader_Add( gloader );
break;
case FT_GLYPH_FORMAT_COMPOSITE:
{
FT_UInt nn, num_subglyphs = slot->num_subglyphs;
FT_UInt num_base_subgs, start_point;
FT_SubGlyph subglyph;
start_point = gloader->base.outline.n_points;
/* first of all, copy the subglyph descriptors in the glyph loader */
error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs );
if ( error )
goto Exit;
FT_ARRAY_COPY( gloader->current.subglyphs,
slot->subglyphs,
num_subglyphs );
gloader->current.num_subglyphs = num_subglyphs;
num_base_subgs = gloader->base.num_subglyphs;
/* now, read each subglyph independently */
for ( nn = 0; nn < num_subglyphs; nn++ )
{
FT_Vector pp1, pp2;
FT_Pos x, y;
FT_UInt num_points, num_new_points, num_base_points;
/* gloader.current.subglyphs can change during glyph loading due */
/* to re-allocation -- we must recompute the current subglyph on */
/* each iteration */
subglyph = gloader->base.subglyphs + num_base_subgs + nn;
pp1 = loader->pp1;
pp2 = loader->pp2;
num_base_points = gloader->base.outline.n_points;
error = af_loader_load_g( loader, scaler, subglyph->index,
load_flags, depth + 1 );
if ( error )
goto Exit;
/* recompute subglyph pointer */
subglyph = gloader->base.subglyphs + num_base_subgs + nn;
if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS )
{
pp1 = loader->pp1;
pp2 = loader->pp2;
}
else
{
loader->pp1 = pp1;
loader->pp2 = pp2;
}
num_points = gloader->base.outline.n_points;
num_new_points = num_points - num_base_points;
/* now perform the transform required for this subglyph */
if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE |
FT_SUBGLYPH_FLAG_XY_SCALE |
FT_SUBGLYPH_FLAG_2X2 ) )
{
FT_Vector* cur = gloader->base.outline.points +
num_base_points;
FT_Vector* limit = cur + num_new_points;
for ( ; cur < limit; cur++ )
FT_Vector_Transform( cur, &subglyph->transform );
}
/* apply offset */
if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) )
{
FT_Int k = subglyph->arg1;
FT_UInt l = subglyph->arg2;
FT_Vector* p1;
FT_Vector* p2;
if ( start_point + k >= num_base_points ||
l >= (FT_UInt)num_new_points )
{
error = AF_Err_Invalid_Composite;
goto Exit;
}
l += num_base_points;
/* for now, only use the current point coordinates; */
/* we may consider another approach in the near future */
p1 = gloader->base.outline.points + start_point + k;
p2 = gloader->base.outline.points + start_point + l;
x = p1->x - p2->x;
y = p1->y - p2->y;
}
else
{
x = FT_MulFix( subglyph->arg1, hints->x_scale ) + hints->x_delta;
y = FT_MulFix( subglyph->arg2, hints->y_scale ) + hints->y_delta;
x = FT_PIX_ROUND( x );
y = FT_PIX_ROUND( y );
}
{
FT_Outline dummy = gloader->base.outline;
dummy.points += num_base_points;
dummy.n_points = (short)num_new_points;
FT_Outline_Translate( &dummy, x, y );
}
}
}
break;
default:
/* we don't support other formats (yet?) */
error = AF_Err_Unimplemented_Feature;
}
Hint_Metrics:
if ( depth == 0 )
{
FT_BBox bbox;
FT_Vector vvector;
vvector.x = slot->metrics.vertBearingX - slot->metrics.horiBearingX;
vvector.y = slot->metrics.vertBearingY - slot->metrics.horiBearingY;
vvector.x = FT_MulFix( vvector.x, metrics->scaler.x_scale );
vvector.y = FT_MulFix( vvector.y, metrics->scaler.y_scale );
/* transform the hinted outline if needed */
if ( loader->transformed )
{
FT_Outline_Transform( &gloader->base.outline, &loader->trans_matrix );
FT_Vector_Transform( &vvector, &loader->trans_matrix );
}
#if 1
/* we must translate our final outline by -pp1.x and compute */
/* the new metrics */
if ( loader->pp1.x )
FT_Outline_Translate( &gloader->base.outline, -loader->pp1.x, 0 );
#endif
FT_Outline_Get_CBox( &gloader->base.outline, &bbox );
bbox.xMin = FT_PIX_FLOOR( bbox.xMin );
bbox.yMin = FT_PIX_FLOOR( bbox.yMin );
bbox.xMax = FT_PIX_CEIL( bbox.xMax );
bbox.yMax = FT_PIX_CEIL( bbox.yMax );
slot->metrics.width = bbox.xMax - bbox.xMin;
slot->metrics.height = bbox.yMax - bbox.yMin;
slot->metrics.horiBearingX = bbox.xMin;
slot->metrics.horiBearingY = bbox.yMax;
slot->metrics.vertBearingX = FT_PIX_FLOOR( bbox.xMin + vvector.x );
slot->metrics.vertBearingY = FT_PIX_FLOOR( bbox.yMax + vvector.y );
/* for mono-width fonts (like Andale, Courier, etc.) we need */
/* to keep the original rounded advance width; ditto for */
/* digits if all have the same advance width */
#if 0
if ( !FT_IS_FIXED_WIDTH( slot->face ) )
slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
else
slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
x_scale );
#else
if ( FT_IS_FIXED_WIDTH( slot->face ) ||
( af_face_globals_is_digit( loader->globals, glyph_index ) &&
metrics->digits_have_same_width ) )
{
slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
metrics->scaler.x_scale );
/* Set delta values to 0. Otherwise code that uses them is */
/* going to ruin the fixed advance width. */
slot->lsb_delta = 0;
slot->rsb_delta = 0;
}
else
{
/* non-spacing glyphs must stay as-is */
if ( slot->metrics.horiAdvance )
slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
}
#endif
slot->metrics.vertAdvance = FT_MulFix( slot->metrics.vertAdvance,
metrics->scaler.y_scale );
slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
slot->metrics.vertAdvance = FT_PIX_ROUND( slot->metrics.vertAdvance );
/* now copy outline into glyph slot */
FT_GlyphLoader_Rewind( internal->loader );
error = FT_GlyphLoader_CopyPoints( internal->loader, gloader );
if ( error )
goto Exit;
slot->outline = internal->loader->base.outline;
slot->format = FT_GLYPH_FORMAT_OUTLINE;
}
#ifdef DEBUG_HINTER
af_debug_hinter = hinter;
#endif
Exit:
return error;
}
FT_LOCAL_DEF( FT_Error )
af_loader_load_glyph( AF_Loader loader,
FT_Face face,
FT_UInt gindex,
FT_UInt32 load_flags )
{
FT_Error error;
FT_Size size = face->size;
AF_ScalerRec scaler;
if ( !size )
return AF_Err_Invalid_Argument;
FT_ZERO( &scaler );
scaler.face = face;
scaler.x_scale = size->metrics.x_scale;
scaler.x_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */
scaler.y_scale = size->metrics.y_scale;
scaler.y_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */
scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags );
scaler.flags = 0; /* XXX: fix this */
error = af_loader_reset( loader, face );
if ( !error )
{
AF_ScriptMetrics metrics;
FT_UInt options = 0;
#ifdef FT_OPTION_AUTOFIT2
/* XXX: undocumented hook to activate the latin2 hinter */
if ( load_flags & ( 1UL << 20 ) )
options = 2;
#endif
error = af_face_globals_get_metrics( loader->globals, gindex,
options, &metrics );
if ( !error )
{
loader->metrics = metrics;
if ( metrics->clazz->script_metrics_scale )
metrics->clazz->script_metrics_scale( metrics, &scaler );
else
metrics->scaler = scaler;
load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM;
load_flags &= ~FT_LOAD_RENDER;
if ( metrics->clazz->script_hints_init )
{
error = metrics->clazz->script_hints_init( &loader->hints,
metrics );
if ( error )
goto Exit;
}
error = af_loader_load_g( loader, &scaler, gindex, load_flags, 0 );
}
}
Exit:
return error;
}
/* END */
@@ -0,0 +1,73 @@
/***************************************************************************/
/* */
/* afloader.h */
/* */
/* Auto-fitter glyph loading routines (specification). */
/* */
/* Copyright 2003, 2004, 2005 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. */
/* */
/***************************************************************************/
#ifndef __AF_LOADER_H__
#define __AF_LOADER_H__
#include "afhints.h"
#include "afglobal.h"
FT_BEGIN_HEADER
typedef struct AF_LoaderRec_
{
FT_Face face; /* current face */
AF_FaceGlobals globals; /* current face globals */
FT_GlyphLoader gloader; /* glyph loader */
AF_GlyphHintsRec hints;
AF_ScriptMetrics metrics;
FT_Bool transformed;
FT_Matrix trans_matrix;
FT_Vector trans_delta;
FT_Vector pp1;
FT_Vector pp2;
/* we don't handle vertical phantom points */
} AF_LoaderRec, *AF_Loader;
FT_LOCAL( FT_Error )
af_loader_init( AF_Loader loader,
FT_Memory memory );
FT_LOCAL( FT_Error )
af_loader_reset( AF_Loader loader,
FT_Face face );
FT_LOCAL( void )
af_loader_done( AF_Loader loader );
FT_LOCAL( FT_Error )
af_loader_load_glyph( AF_Loader loader,
FT_Face face,
FT_UInt gindex,
FT_UInt32 load_flags );
/* */
FT_END_HEADER
#endif /* __AF_LOADER_H__ */
/* END */
@@ -0,0 +1,94 @@
/***************************************************************************/
/* */
/* afmodule.c */
/* */
/* Auto-fitter module implementation (body). */
/* */
/* Copyright 2003, 2004, 2005, 2006 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 "afmodule.h"
#include "afloader.h"
#include "afpic.h"
#ifdef AF_DEBUG
int _af_debug;
int _af_debug_disable_horz_hints;
int _af_debug_disable_vert_hints;
int _af_debug_disable_blue_hints;
void* _af_debug_hints;
#endif
#include FT_INTERNAL_OBJECTS_H
typedef struct FT_AutofitterRec_
{
FT_ModuleRec root;
AF_LoaderRec loader[1];
} FT_AutofitterRec, *FT_Autofitter;
FT_CALLBACK_DEF( FT_Error )
af_autofitter_init( FT_Autofitter module )
{
return af_loader_init( module->loader, module->root.library->memory );
}
FT_CALLBACK_DEF( void )
af_autofitter_done( FT_Autofitter module )
{
af_loader_done( module->loader );
}
FT_CALLBACK_DEF( FT_Error )
af_autofitter_load_glyph( FT_Autofitter module,
FT_GlyphSlot slot,
FT_Size size,
FT_UInt glyph_index,
FT_Int32 load_flags )
{
FT_UNUSED( size );
return af_loader_load_glyph( module->loader, slot->face,
glyph_index, load_flags );
}
FT_DEFINE_AUTOHINTER_SERVICE(af_autofitter_service,
NULL,
NULL,
NULL,
(FT_AutoHinter_GlyphLoadFunc)af_autofitter_load_glyph
)
FT_DEFINE_MODULE(autofit_module_class,
FT_MODULE_HINTER,
sizeof ( FT_AutofitterRec ),
"autofitter",
0x10000L, /* version 1.0 of the autofitter */
0x20000L, /* requires FreeType 2.0 or above */
(const void*)&AF_AF_AUTOFITTER_SERVICE_GET,
(FT_Module_Constructor)af_autofitter_init,
(FT_Module_Destructor) af_autofitter_done,
(FT_Module_Requester) NULL
)
/* END */
@@ -0,0 +1,37 @@
/***************************************************************************/
/* */
/* afmodule.h */
/* */
/* Auto-fitter module implementation (specification). */
/* */
/* Copyright 2003, 2004, 2005 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. */
/* */
/***************************************************************************/
#ifndef __AFMODULE_H__
#define __AFMODULE_H__
#include <ft2build.h>
#include FT_INTERNAL_OBJECTS_H
#include FT_MODULE_H
FT_BEGIN_HEADER
FT_DECLARE_MODULE(autofit_module_class)
FT_END_HEADER
#endif /* __AFMODULE_H__ */
/* END */
+94
View File
@@ -0,0 +1,94 @@
/***************************************************************************/
/* */
/* afpic.c */
/* */
/* The FreeType position independent code services for autofit module. */
/* */
/* Copyright 2009, 2010 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* 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_FREETYPE_H
#include FT_INTERNAL_OBJECTS_H
#include "afpic.h"
#ifdef FT_CONFIG_OPTION_PIC
/* forward declaration of PIC init functions from afmodule.c */
void FT_Init_Class_af_autofitter_service( FT_Library, FT_AutoHinter_ServiceRec*);
/* forward declaration of PIC init functions from script classes */
#include "aflatin.h"
#include "aflatin2.h"
#include "afcjk.h"
#include "afdummy.h"
#include "afindic.h"
void
autofit_module_class_pic_free( FT_Library library )
{
FT_PIC_Container* pic_container = &library->pic_container;
FT_Memory memory = library->memory;
if ( pic_container->autofit )
{
FT_FREE( pic_container->autofit );
pic_container->autofit = NULL;
}
}
FT_Error
autofit_module_class_pic_init( FT_Library library )
{
FT_PIC_Container* pic_container = &library->pic_container;
FT_UInt ss;
FT_Error error = AF_Err_Ok;
AFModulePIC* container;
FT_Memory memory = library->memory;
/* allocate pointer, clear and set global container pointer */
if ( FT_ALLOC ( container, sizeof ( *container ) ) )
return error;
FT_MEM_SET( container, 0, sizeof ( *container ) );
pic_container->autofit = container;
/* initialize pointer table - this is how the module usually expects this data */
for ( ss = 0 ; ss < AF_SCRIPT_CLASSES_REC_COUNT ; ss++ )
{
container->af_script_classes[ss] = &container->af_script_classes_rec[ss];
}
container->af_script_classes[AF_SCRIPT_CLASSES_COUNT-1] = NULL;
/* add call to initialization function when you add new scripts */
ss = 0;
FT_Init_Class_af_dummy_script_class(&container->af_script_classes_rec[ss++]);
#ifdef FT_OPTION_AUTOFIT2
FT_Init_Class_af_latin2_script_class(&container->af_script_classes_rec[ss++]);
#endif
FT_Init_Class_af_latin_script_class(&container->af_script_classes_rec[ss++]);
FT_Init_Class_af_cjk_script_class(&container->af_script_classes_rec[ss++]);
FT_Init_Class_af_indic_script_class(&container->af_script_classes_rec[ss++]);
FT_Init_Class_af_autofitter_service(library, &container->af_autofitter_service);
/*Exit:*/
if(error)
autofit_module_class_pic_free(library);
return error;
}
#endif /* FT_CONFIG_OPTION_PIC */
/* END */
+64
View File
@@ -0,0 +1,64 @@
/***************************************************************************/
/* */
/* afpic.h */
/* */
/* The FreeType position independent code services for autofit module. */
/* */
/* Copyright 2009 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* 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. */
/* */
/***************************************************************************/
#ifndef __AFPIC_H__
#define __AFPIC_H__
FT_BEGIN_HEADER
#include FT_INTERNAL_PIC_H
#ifndef FT_CONFIG_OPTION_PIC
#define AF_SCRIPT_CLASSES_GET af_script_classes
#define AF_AF_AUTOFITTER_SERVICE_GET af_autofitter_service
#else /* FT_CONFIG_OPTION_PIC */
#include "aftypes.h"
/* increase these when you add new scripts, and update autofit_module_class_pic_init */
#ifdef FT_OPTION_AUTOFIT2
#define AF_SCRIPT_CLASSES_COUNT 6
#else
#define AF_SCRIPT_CLASSES_COUNT 5
#endif
#define AF_SCRIPT_CLASSES_REC_COUNT (AF_SCRIPT_CLASSES_COUNT-1)
typedef struct AFModulePIC_
{
AF_ScriptClass af_script_classes[AF_SCRIPT_CLASSES_COUNT];
AF_ScriptClassRec af_script_classes_rec[AF_SCRIPT_CLASSES_REC_COUNT];
FT_AutoHinter_ServiceRec af_autofitter_service;
} AFModulePIC;
#define GET_PIC(lib) ((AFModulePIC*)((lib)->pic_container.autofit))
#define AF_SCRIPT_CLASSES_GET (GET_PIC(FT_FACE_LIBRARY(globals->face))->af_script_classes)
#define AF_AF_AUTOFITTER_SERVICE_GET (GET_PIC(library)->af_autofitter_service)
#endif /* FT_CONFIG_OPTION_PIC */
/* */
FT_END_HEADER
#endif /* __AFPIC_H__ */
/* END */
+403
View File
@@ -0,0 +1,403 @@
/***************************************************************************/
/* */
/* aftypes.h */
/* */
/* Auto-fitter types (specification only). */
/* */
/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 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. */
/* */
/***************************************************************************/
/*************************************************************************
*
* The auto-fitter is a complete rewrite of the old auto-hinter.
* Its main feature is the ability to differentiate between different
* scripts in order to apply language-specific rules.
*
* The code has also been compartmentized into several entities that
* should make algorithmic experimentation easier than with the old
* code.
*
* Finally, we get rid of the Catharon license, since this code is
* released under the FreeType one.
*
*************************************************************************/
#ifndef __AFTYPES_H__
#define __AFTYPES_H__
#include "ft2build.h"
#include FT_FREETYPE_H
#include FT_OUTLINE_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
FT_BEGIN_HEADER
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** D E B U G G I N G *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
#define xxAF_USE_WARPER /* only define to use warp hinting */
#define xxAF_DEBUG
#ifdef AF_DEBUG
#include FT_CONFIG_STANDARD_LIBRARY_H
#define AF_LOG( x ) do { if ( _af_debug ) printf x; } while ( 0 )
extern int _af_debug;
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;
#else /* !AF_DEBUG */
#define AF_LOG( x ) do { } while ( 0 ) /* nothing */
#endif /* !AF_DEBUG */
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** U T I L I T Y S T U F F *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
typedef struct AF_WidthRec_
{
FT_Pos org; /* original position/width in font units */
FT_Pos cur; /* current/scaled position/width in device sub-pixels */
FT_Pos fit; /* current/fitted position/width in device sub-pixels */
} AF_WidthRec, *AF_Width;
FT_LOCAL( void )
af_sort_pos( FT_UInt count,
FT_Pos* table );
FT_LOCAL( void )
af_sort_widths( FT_UInt count,
AF_Width widths );
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** A N G L E T Y P E S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*
* The auto-fitter doesn't need a very high angular accuracy;
* this allows us to speed up some computations considerably with a
* light Cordic algorithm (see afangles.c).
*/
typedef FT_Int AF_Angle;
#define AF_ANGLE_PI 256
#define AF_ANGLE_2PI ( AF_ANGLE_PI * 2 )
#define AF_ANGLE_PI2 ( AF_ANGLE_PI / 2 )
#define AF_ANGLE_PI4 ( AF_ANGLE_PI / 4 )
#if 0
/*
* compute the angle of a given 2-D vector
*/
FT_LOCAL( AF_Angle )
af_angle_atan( FT_Pos dx,
FT_Pos dy );
/*
* compute `angle2 - angle1'; the result is always within
* the range [-AF_ANGLE_PI .. AF_ANGLE_PI - 1]
*/
FT_LOCAL( AF_Angle )
af_angle_diff( AF_Angle angle1,
AF_Angle angle2 );
#endif /* 0 */
#define AF_ANGLE_DIFF( result, angle1, angle2 ) \
FT_BEGIN_STMNT \
AF_Angle _delta = (angle2) - (angle1); \
\
\
_delta %= AF_ANGLE_2PI; \
if ( _delta < 0 ) \
_delta += AF_ANGLE_2PI; \
\
if ( _delta > AF_ANGLE_PI ) \
_delta -= AF_ANGLE_2PI; \
\
result = _delta; \
FT_END_STMNT
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** O U T L I N E S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* opaque handle to glyph-specific hints -- see `afhints.h' for more
* details
*/
typedef struct AF_GlyphHintsRec_* AF_GlyphHints;
/* This structure is used to model an input glyph outline to
* the auto-hinter. The latter will set the `hints' field
* depending on the glyph's script.
*/
typedef struct AF_OutlineRec_
{
FT_Face face;
FT_Outline outline;
FT_UInt outline_resolution;
FT_Int advance;
FT_UInt metrics_resolution;
AF_GlyphHints hints;
} AF_OutlineRec;
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** S C A L E R S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*
* A scaler models the target pixel device that will receive the
* auto-hinted glyph image.
*/
typedef enum AF_ScalerFlags_
{
AF_SCALER_FLAG_NO_HORIZONTAL = 1, /* disable horizontal hinting */
AF_SCALER_FLAG_NO_VERTICAL = 2, /* disable vertical hinting */
AF_SCALER_FLAG_NO_ADVANCE = 4 /* disable advance hinting */
} AF_ScalerFlags;
typedef struct AF_ScalerRec_
{
FT_Face face; /* source font face */
FT_Fixed x_scale; /* from font units to 1/64th device pixels */
FT_Fixed y_scale; /* from font units to 1/64th device pixels */
FT_Pos x_delta; /* in 1/64th device pixels */
FT_Pos y_delta; /* in 1/64th device pixels */
FT_Render_Mode render_mode; /* monochrome, anti-aliased, LCD, etc. */
FT_UInt32 flags; /* additional control flags, see above */
} AF_ScalerRec, *AF_Scaler;
#define AF_SCALER_EQUAL_SCALES( a, b ) \
( (a)->x_scale == (b)->x_scale && \
(a)->y_scale == (b)->y_scale && \
(a)->x_delta == (b)->x_delta && \
(a)->y_delta == (b)->y_delta )
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** S C R I P T S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*
* The list of know scripts. Each different script corresponds to the
* following information:
*
* - A set of Unicode ranges to test whether the face supports the
* script.
*
* - A specific global analyzer that will compute global metrics
* specific to the script.
*
* - A specific glyph analyzer that will compute segments and
* edges for each glyph covered by the script.
*
* - A specific grid-fitting algorithm that will distort the
* scaled glyph outline according to the results of the glyph
* analyzer.
*
* Note that a given analyzer and/or grid-fitting algorithm can be
* used by more than one script.
*/
typedef enum AF_Script_
{
AF_SCRIPT_NONE = 0,
AF_SCRIPT_LATIN = 1,
AF_SCRIPT_CJK = 2,
AF_SCRIPT_INDIC = 3,
#ifdef FT_OPTION_AUTOFIT2
AF_SCRIPT_LATIN2,
#endif
/* add new scripts here. Don't forget to update the list in */
/* `afglobal.c'. */
AF_SCRIPT_MAX /* do not remove */
} AF_Script;
typedef struct AF_ScriptClassRec_ const* AF_ScriptClass;
typedef struct AF_ScriptMetricsRec_
{
AF_ScriptClass clazz;
AF_ScalerRec scaler;
FT_Bool digits_have_same_width;
} AF_ScriptMetricsRec, *AF_ScriptMetrics;
/* This function parses an FT_Face to compute global metrics for
* a specific script.
*/
typedef FT_Error
(*AF_Script_InitMetricsFunc)( AF_ScriptMetrics metrics,
FT_Face face );
typedef void
(*AF_Script_ScaleMetricsFunc)( AF_ScriptMetrics metrics,
AF_Scaler scaler );
typedef void
(*AF_Script_DoneMetricsFunc)( AF_ScriptMetrics metrics );
typedef FT_Error
(*AF_Script_InitHintsFunc)( AF_GlyphHints hints,
AF_ScriptMetrics metrics );
typedef void
(*AF_Script_ApplyHintsFunc)( AF_GlyphHints hints,
FT_Outline* outline,
AF_ScriptMetrics metrics );
typedef struct AF_Script_UniRangeRec_
{
FT_UInt32 first;
FT_UInt32 last;
} AF_Script_UniRangeRec;
#define AF_UNIRANGE_REC( a, b ) { (FT_UInt32)(a), (FT_UInt32)(b) }
typedef const AF_Script_UniRangeRec *AF_Script_UniRange;
typedef struct AF_ScriptClassRec_
{
AF_Script script;
AF_Script_UniRange script_uni_ranges; /* last must be { 0, 0 } */
FT_Offset script_metrics_size;
AF_Script_InitMetricsFunc script_metrics_init;
AF_Script_ScaleMetricsFunc script_metrics_scale;
AF_Script_DoneMetricsFunc script_metrics_done;
AF_Script_InitHintsFunc script_hints_init;
AF_Script_ApplyHintsFunc script_hints_apply;
} AF_ScriptClassRec;
/* Declare and define vtables for classes */
#ifndef FT_CONFIG_OPTION_PIC
#define AF_DECLARE_SCRIPT_CLASS(script_class) \
FT_CALLBACK_TABLE const AF_ScriptClassRec \
script_class;
#define AF_DEFINE_SCRIPT_CLASS(script_class, script_, ranges, m_size, \
m_init, m_scale, m_done, h_init, h_apply) \
FT_CALLBACK_TABLE_DEF const AF_ScriptClassRec \
script_class = \
{ \
script_, \
ranges, \
\
m_size, \
\
m_init, \
m_scale, \
m_done, \
\
h_init, \
h_apply \
};
#else
#define AF_DECLARE_SCRIPT_CLASS(script_class) \
FT_LOCAL(void) \
FT_Init_Class_##script_class(AF_ScriptClassRec* ac);
#define AF_DEFINE_SCRIPT_CLASS(script_class, script_, ranges, m_size, \
m_init, m_scale, m_done, h_init, h_apply) \
FT_LOCAL_DEF(void) \
FT_Init_Class_##script_class(AF_ScriptClassRec* ac) \
{ \
ac->script = script_; \
ac->script_uni_ranges = ranges; \
\
ac->script_metrics_size = m_size; \
\
ac->script_metrics_init = m_init; \
ac->script_metrics_scale = m_scale; \
ac->script_metrics_done = m_done; \
\
ac->script_hints_init = h_init; \
ac->script_hints_apply = h_apply; \
}
#endif
/* */
FT_END_HEADER
#endif /* __AFTYPES_H__ */
/* END */
+338
View File
@@ -0,0 +1,338 @@
/***************************************************************************/
/* */
/* afwarp.c */
/* */
/* Auto-fitter warping algorithm (body). */
/* */
/* Copyright 2006, 2007 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 "afwarp.h"
#ifdef AF_USE_WARPER
#if 1
static const AF_WarpScore
af_warper_weights[64] =
{
35, 32, 30, 25, 20, 15, 12, 10, 5, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, -1, -2, -5, -8,-10,-10,-20,-20,-30,-30,
-30,-30,-20,-20,-10,-10, -8, -5, -2, -1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 5, 10, 12, 15, 20, 25, 30, 32,
};
#else
static const AF_WarpScore
af_warper_weights[64] =
{
30, 20, 10, 5, 4, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, -1, -2, -2, -5, -5,-10,-10,-15,-20,
-20,-15,-15,-10,-10, -5, -5, -2, -2, -1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 4, 5, 10, 20,
};
#endif
static void
af_warper_compute_line_best( AF_Warper warper,
FT_Fixed scale,
FT_Pos delta,
FT_Pos xx1,
FT_Pos xx2,
AF_WarpScore base_distort,
AF_Segment segments,
FT_UInt num_segments )
{
FT_Int idx_min, idx_max, idx0;
FT_UInt nn;
AF_WarpScore scores[65];
for ( nn = 0; nn < 65; nn++ )
scores[nn] = 0;
idx0 = xx1 - warper->t1;
/* compute minimum and maximum indices */
{
FT_Pos xx1min = warper->x1min;
FT_Pos xx1max = warper->x1max;
FT_Pos w = xx2 - xx1;
if ( xx1min + w < warper->x2min )
xx1min = warper->x2min - w;
xx1max = warper->x1max;
if ( xx1max + w > warper->x2max )
xx1max = warper->x2max - w;
idx_min = xx1min - warper->t1;
idx_max = xx1max - warper->t1;
if ( idx_min < 0 || idx_min > idx_max || idx_max > 64 )
{
AF_LOG(( "invalid indices:\n"
" min=%d max=%d, xx1=%ld xx2=%ld,\n"
" x1min=%ld x1max=%ld, x2min=%ld x2max=%ld\n",
idx_min, idx_max, xx1, xx2,
warper->x1min, warper->x1max,
warper->x2min, warper->x2max ));
return;
}
}
for ( nn = 0; nn < num_segments; nn++ )
{
FT_Pos len = segments[nn].max_coord - segments[nn].min_coord;
FT_Pos y0 = FT_MulFix( segments[nn].pos, scale ) + delta;
FT_Pos y = y0 + ( idx_min - idx0 );
FT_Int idx;
for ( idx = idx_min; idx <= idx_max; idx++, y++ )
scores[idx] += af_warper_weights[y & 63] * len;
}
/* find best score */
{
FT_Int idx;
for ( idx = idx_min; idx <= idx_max; idx++ )
{
AF_WarpScore score = scores[idx];
AF_WarpScore distort = base_distort + ( idx - idx0 );
if ( score > warper->best_score ||
( score == warper->best_score &&
distort < warper->best_distort ) )
{
warper->best_score = score;
warper->best_distort = distort;
warper->best_scale = scale;
warper->best_delta = delta + ( idx - idx0 );
}
}
}
}
FT_LOCAL_DEF( void )
af_warper_compute( AF_Warper warper,
AF_GlyphHints hints,
AF_Dimension dim,
FT_Fixed *a_scale,
FT_Pos *a_delta )
{
AF_AxisHints axis;
AF_Point points;
FT_Fixed org_scale;
FT_Pos org_delta;
FT_UInt nn, num_points, num_segments;
FT_Int X1, X2;
FT_Int w;
AF_WarpScore base_distort;
AF_Segment segments;
/* get original scaling transformation */
if ( dim == AF_DIMENSION_VERT )
{
org_scale = hints->y_scale;
org_delta = hints->y_delta;
}
else
{
org_scale = hints->x_scale;
org_delta = hints->x_delta;
}
warper->best_scale = org_scale;
warper->best_delta = org_delta;
warper->best_score = INT_MIN;
warper->best_distort = 0;
axis = &hints->axis[dim];
segments = axis->segments;
num_segments = axis->num_segments;
points = hints->points;
num_points = hints->num_points;
*a_scale = org_scale;
*a_delta = org_delta;
/* get X1 and X2, minimum and maximum in original coordinates */
if ( num_segments < 1 )
return;
#if 1
X1 = X2 = points[0].fx;
for ( nn = 1; nn < num_points; nn++ )
{
FT_Int X = points[nn].fx;
if ( X < X1 )
X1 = X;
if ( X > X2 )
X2 = X;
}
#else
X1 = X2 = segments[0].pos;
for ( nn = 1; nn < num_segments; nn++ )
{
FT_Int X = segments[nn].pos;
if ( X < X1 )
X1 = X;
if ( X > X2 )
X2 = X;
}
#endif
if ( X1 >= X2 )
return;
warper->x1 = FT_MulFix( X1, org_scale ) + org_delta;
warper->x2 = FT_MulFix( X2, org_scale ) + org_delta;
warper->t1 = AF_WARPER_FLOOR( warper->x1 );
warper->t2 = AF_WARPER_CEIL( warper->x2 );
warper->x1min = warper->x1 & ~31;
warper->x1max = warper->x1min + 32;
warper->x2min = warper->x2 & ~31;
warper->x2max = warper->x2min + 32;
if ( warper->x1max > warper->x2 )
warper->x1max = warper->x2;
if ( warper->x2min < warper->x1 )
warper->x2min = warper->x1;
warper->w0 = warper->x2 - warper->x1;
if ( warper->w0 <= 64 )
{
warper->x1max = warper->x1;
warper->x2min = warper->x2;
}
warper->wmin = warper->x2min - warper->x1max;
warper->wmax = warper->x2max - warper->x1min;
#if 1
{
int margin = 16;
if ( warper->w0 <= 128 )
{
margin = 8;
if ( warper->w0 <= 96 )
margin = 4;
}
if ( warper->wmin < warper->w0 - margin )
warper->wmin = warper->w0 - margin;
if ( warper->wmax > warper->w0 + margin )
warper->wmax = warper->w0 + margin;
}
if ( warper->wmin < warper->w0 * 3 / 4 )
warper->wmin = warper->w0 * 3 / 4;
if ( warper->wmax > warper->w0 * 5 / 4 )
warper->wmax = warper->w0 * 5 / 4;
#else
/* no scaling, just translation */
warper->wmin = warper->wmax = warper->w0;
#endif
for ( w = warper->wmin; w <= warper->wmax; w++ )
{
FT_Fixed new_scale;
FT_Pos new_delta;
FT_Pos xx1, xx2;
xx1 = warper->x1;
xx2 = warper->x2;
if ( w >= warper->w0 )
{
xx1 -= w - warper->w0;
if ( xx1 < warper->x1min )
{
xx2 += warper->x1min - xx1;
xx1 = warper->x1min;
}
}
else
{
xx1 -= w - warper->w0;
if ( xx1 > warper->x1max )
{
xx2 -= xx1 - warper->x1max;
xx1 = warper->x1max;
}
}
if ( xx1 < warper->x1 )
base_distort = warper->x1 - xx1;
else
base_distort = xx1 - warper->x1;
if ( xx2 < warper->x2 )
base_distort += warper->x2 - xx2;
else
base_distort += xx2 - warper->x2;
base_distort *= 10;
new_scale = org_scale + FT_DivFix( w - warper->w0, X2 - X1 );
new_delta = xx1 - FT_MulFix( X1, new_scale );
af_warper_compute_line_best( warper, new_scale, new_delta, xx1, xx2,
base_distort,
segments, num_segments );
}
{
FT_Fixed best_scale = warper->best_scale;
FT_Pos best_delta = warper->best_delta;
hints->xmin_delta = FT_MulFix( X1, best_scale - org_scale )
+ best_delta;
hints->xmax_delta = FT_MulFix( X2, best_scale - org_scale )
+ best_delta;
*a_scale = best_scale;
*a_delta = best_delta;
}
}
#else /* !AF_USE_WARPER */
char af_warper_dummy = 0; /* make compiler happy */
#endif /* !AF_USE_WARPER */
/* END */
@@ -0,0 +1,64 @@
/***************************************************************************/
/* */
/* afwarp.h */
/* */
/* Auto-fitter warping algorithm (specification). */
/* */
/* Copyright 2006, 2007 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. */
/* */
/***************************************************************************/
#ifndef __AFWARP_H__
#define __AFWARP_H__
#include "afhints.h"
FT_BEGIN_HEADER
#define AF_WARPER_SCALE
#define AF_WARPER_FLOOR( x ) ( (x) & ~63 )
#define AF_WARPER_CEIL( x ) AF_WARPER_FLOOR( (x) + 63 )
typedef FT_Int32 AF_WarpScore;
typedef struct AF_WarperRec_
{
FT_Pos x1, x2;
FT_Pos t1, t2;
FT_Pos x1min, x1max;
FT_Pos x2min, x2max;
FT_Pos w0, wmin, wmax;
FT_Fixed best_scale;
FT_Pos best_delta;
AF_WarpScore best_score;
AF_WarpScore best_distort;
} AF_WarperRec, *AF_Warper;
FT_LOCAL( void )
af_warper_compute( AF_Warper warper,
AF_GlyphHints hints,
AF_Dimension dim,
FT_Fixed *a_scale,
FT_Fixed *a_delta );
FT_END_HEADER
#endif /* __AFWARP_H__ */
/* END */
@@ -0,0 +1,41 @@
/***************************************************************************/
/* */
/* autofit.c */
/* */
/* Auto-fitter module (body). */
/* */
/* Copyright 2003, 2004, 2005, 2006, 2007 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. */
/* */
/***************************************************************************/
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include <ft2build.h>
#include "afpic.c"
#include "afangles.c"
#include "afglobal.c"
#include "afhints.c"
#include "afdummy.c"
#include "aflatin.c"
#ifdef FT_OPTION_AUTOFIT2
#include "aflatin2.c"
#endif
#include "afcjk.c"
#include "afindic.c"
#include "afloader.c"
#include "afmodule.c"
#ifdef AF_USE_WARPER
#include "afwarp.c"
#endif
/* END */
@@ -0,0 +1,23 @@
#
# FreeType 2 auto-fitter module definition
#
# Copyright 2003, 2004, 2005, 2006 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.
FTMODULE_H_COMMANDS += AUTOFIT_MODULE
define AUTOFIT_MODULE
$(OPEN_DRIVER) FT_Module_Class, autofit_module_class $(CLOSE_DRIVER)
$(ECHO_DRIVER)autofit $(ECHO_DRIVER_DESC)automatic hinting module$(ECHO_DRIVER_DONE)
endef
# EOF
@@ -0,0 +1,78 @@
#
# FreeType 2 auto-fitter module configuration rules
#
# Copyright 2003, 2004, 2005, 2006, 2007 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.
# AUTOF driver directory
#
AUTOF_DIR := $(SRC_DIR)/autofit
# compilation flags for the driver
#
AUTOF_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(AUTOF_DIR))
# AUTOF driver sources (i.e., C files)
#
AUTOF_DRV_SRC := $(AUTOF_DIR)/afangles.c \
$(AUTOF_DIR)/afcjk.c \
$(AUTOF_DIR)/afdummy.c \
$(AUTOF_DIR)/afglobal.c \
$(AUTOF_DIR)/afhints.c \
$(AUTOF_DIR)/afindic.c \
$(AUTOF_DIR)/aflatin.c \
$(AUTOF_DIR)/afloader.c \
$(AUTOF_DIR)/afmodule.c \
$(AUTOF_DIR)/afwarp.c
# AUTOF driver headers
#
AUTOF_DRV_H := $(AUTOF_DRV_SRC:%c=%h) \
$(AUTOF_DIR)/aftypes.h \
$(AUTOF_DIR)/aferrors.h
# AUTOF driver object(s)
#
# AUTOF_DRV_OBJ_M is used during `multi' builds.
# AUTOF_DRV_OBJ_S is used during `single' builds.
#
AUTOF_DRV_OBJ_M := $(AUTOF_DRV_SRC:$(AUTOF_DIR)/%.c=$(OBJ_DIR)/%.$O)
AUTOF_DRV_OBJ_S := $(OBJ_DIR)/autofit.$O
# AUTOF driver source file for single build
#
AUTOF_DRV_SRC_S := $(AUTOF_DIR)/autofit.c
# AUTOF driver - single object
#
$(AUTOF_DRV_OBJ_S): $(AUTOF_DRV_SRC_S) $(AUTOF_DRV_SRC) \
$(FREETYPE_H) $(AUTOF_DRV_H)
$(AUTOF_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(AUTOF_DRV_SRC_S))
# AUTOF driver - multiple objects
#
$(OBJ_DIR)/%.$O: $(AUTOF_DIR)/%.c $(FREETYPE_H) $(AUTOF_DRV_H)
$(AUTOF_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<)
# update main driver object lists
#
DRV_OBJS_S += $(AUTOF_DRV_OBJ_S)
DRV_OBJS_M += $(AUTOF_DRV_OBJ_M)
# EOF
+83
View File
@@ -0,0 +1,83 @@
/***************************************************************************/
/* */
/* basepic.c */
/* */
/* The FreeType position independent code services for base. */
/* */
/* Copyright 2009 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* 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_FREETYPE_H
#include FT_INTERNAL_OBJECTS_H
#include "basepic.h"
#ifdef FT_CONFIG_OPTION_PIC
/* forward declaration of PIC init functions from ftglyph.c */
void FT_Init_Class_ft_outline_glyph_class(FT_Glyph_Class*);
void FT_Init_Class_ft_bitmap_glyph_class(FT_Glyph_Class*);
/* forward declaration of PIC init functions from ftinit.c */
FT_Error ft_create_default_module_classes(FT_Library);
void ft_destroy_default_module_classes(FT_Library);
void
ft_base_pic_free( FT_Library library )
{
FT_PIC_Container* pic_container = &library->pic_container;
FT_Memory memory = library->memory;
if ( pic_container->base )
{
/* Destroy default module classes (in case FT_Add_Default_Modules was used) */
ft_destroy_default_module_classes( library );
FT_FREE( pic_container->base );
pic_container->base = NULL;
}
}
FT_Error
ft_base_pic_init( FT_Library library )
{
FT_PIC_Container* pic_container = &library->pic_container;
FT_Error error = FT_Err_Ok;
BasePIC* container;
FT_Memory memory = library->memory;
/* allocate pointer, clear and set global container pointer */
if ( FT_ALLOC ( container, sizeof ( *container ) ) )
return error;
FT_MEM_SET( container, 0, sizeof(*container) );
pic_container->base = container;
/* initialize default modules list and pointers */
error = ft_create_default_module_classes( library );
if ( error )
goto Exit;
/* initialize pointer table - this is how the module usually expects this data */
FT_Init_Class_ft_outline_glyph_class(&container->ft_outline_glyph_class);
FT_Init_Class_ft_bitmap_glyph_class(&container->ft_bitmap_glyph_class);
Exit:
if(error)
ft_base_pic_free(library);
return error;
}
#endif /* FT_CONFIG_OPTION_PIC */
/* END */
+62
View File
@@ -0,0 +1,62 @@
/***************************************************************************/
/* */
/* basepic.h */
/* */
/* The FreeType position independent code services for base. */
/* */
/* Copyright 2009 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* 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. */
/* */
/***************************************************************************/
#ifndef __BASEPIC_H__
#define __BASEPIC_H__
FT_BEGIN_HEADER
#include FT_INTERNAL_PIC_H
#ifndef FT_CONFIG_OPTION_PIC
#define FT_OUTLINE_GLYPH_CLASS_GET &ft_outline_glyph_class
#define FT_BITMAP_GLYPH_CLASS_GET &ft_bitmap_glyph_class
#define FT_DEFAULT_MODULES_GET ft_default_modules
#else /* FT_CONFIG_OPTION_PIC */
#include FT_GLYPH_H
typedef struct BasePIC_
{
FT_Module_Class** default_module_classes;
FT_Glyph_Class ft_outline_glyph_class;
FT_Glyph_Class ft_bitmap_glyph_class;
} BasePIC;
#define GET_PIC(lib) ((BasePIC*)((lib)->pic_container.base))
#define FT_OUTLINE_GLYPH_CLASS_GET (&GET_PIC(library)->ft_outline_glyph_class)
#define FT_BITMAP_GLYPH_CLASS_GET (&GET_PIC(library)->ft_bitmap_glyph_class)
#define FT_DEFAULT_MODULES_GET (GET_PIC(library)->default_module_classes)
void
ft_base_pic_free( FT_Library library );
FT_Error
ft_base_pic_init( FT_Library library );
#endif /* FT_CONFIG_OPTION_PIC */
/* */
FT_END_HEADER
#endif /* __BASEPIC_H__ */
/* END */
+163
View File
@@ -0,0 +1,163 @@
/***************************************************************************/
/* */
/* ftadvanc.c */
/* */
/* Quick computation of advance widths (body). */
/* */
/* Copyright 2008, 2009 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_ADVANCES_H
#include FT_INTERNAL_OBJECTS_H
static FT_Error
_ft_face_scale_advances( FT_Face face,
FT_Fixed* advances,
FT_UInt count,
FT_Int32 flags )
{
FT_Fixed scale;
FT_UInt nn;
if ( flags & FT_LOAD_NO_SCALE )
return FT_Err_Ok;
if ( face->size == NULL )
return FT_Err_Invalid_Size_Handle;
if ( flags & FT_LOAD_VERTICAL_LAYOUT )
scale = face->size->metrics.y_scale;
else
scale = face->size->metrics.x_scale;
/* this must be the same scaling as to get linear{Hori,Vert}Advance */
/* (see `FT_Load_Glyph' implementation in src/base/ftobjs.c) */
for ( nn = 0; nn < count; nn++ )
advances[nn] = FT_MulDiv( advances[nn], scale, 64 );
return FT_Err_Ok;
}
/* at the moment, we can perform fast advance retrieval only in */
/* the following cases: */
/* */
/* - unscaled load */
/* - unhinted load */
/* - light-hinted load */
#define LOAD_ADVANCE_FAST_CHECK( flags ) \
( flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) || \
FT_LOAD_TARGET_MODE( flags ) == FT_RENDER_MODE_LIGHT )
/* documentation is in ftadvanc.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_Advance( FT_Face face,
FT_UInt gindex,
FT_Int32 flags,
FT_Fixed *padvance )
{
FT_Face_GetAdvancesFunc func;
if ( !face )
return FT_Err_Invalid_Face_Handle;
if ( gindex >= (FT_UInt)face->num_glyphs )
return FT_Err_Invalid_Glyph_Index;
func = face->driver->clazz->get_advances;
if ( func && LOAD_ADVANCE_FAST_CHECK( flags ) )
{
FT_Error error;
error = func( face, gindex, 1, flags, padvance );
if ( !error )
return _ft_face_scale_advances( face, padvance, 1, flags );
if ( error != FT_ERROR_BASE( FT_Err_Unimplemented_Feature ) )
return error;
}
return FT_Get_Advances( face, gindex, 1, flags, padvance );
}
/* documentation is in ftadvanc.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_Advances( FT_Face face,
FT_UInt start,
FT_UInt count,
FT_Int32 flags,
FT_Fixed *padvances )
{
FT_Face_GetAdvancesFunc func;
FT_UInt num, end, nn;
FT_Error error = FT_Err_Ok;
if ( !face )
return FT_Err_Invalid_Face_Handle;
num = (FT_UInt)face->num_glyphs;
end = start + count;
if ( start >= num || end < start || end > num )
return FT_Err_Invalid_Glyph_Index;
if ( count == 0 )
return FT_Err_Ok;
func = face->driver->clazz->get_advances;
if ( func && LOAD_ADVANCE_FAST_CHECK( flags ) )
{
error = func( face, start, count, flags, padvances );
if ( !error )
goto Exit;
if ( error != FT_ERROR_BASE( FT_Err_Unimplemented_Feature ) )
return error;
}
error = FT_Err_Ok;
if ( flags & FT_ADVANCE_FLAG_FAST_ONLY )
return FT_Err_Unimplemented_Feature;
flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
for ( nn = 0; nn < count; nn++ )
{
error = FT_Load_Glyph( face, start + nn, flags );
if ( error )
break;
padvances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
? face->glyph->advance.y
: face->glyph->advance.x;
}
if ( error )
return error;
Exit:
return _ft_face_scale_advances( face, padvances, count, flags );
}
/* END */
+121
View File
@@ -0,0 +1,121 @@
/***************************************************************************/
/* */
/* ftapi.c */
/* */
/* The FreeType compatibility functions (body). */
/* */
/* Copyright 2002 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_LIST_H
#include FT_OUTLINE_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_TRUETYPE_TABLES_H
#include FT_OUTLINE_H
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** C O M P A T I B I L I T Y ****/
/**** ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/* backwards compatibility API */
FT_BASE_DEF( void )
FT_New_Memory_Stream( FT_Library library,
FT_Byte* base,
FT_ULong size,
FT_Stream stream )
{
FT_UNUSED( library );
FT_Stream_OpenMemory( stream, base, size );
}
FT_BASE_DEF( FT_Error )
FT_Seek_Stream( FT_Stream stream,
FT_ULong pos )
{
return FT_Stream_Seek( stream, pos );
}
FT_BASE_DEF( FT_Error )
FT_Skip_Stream( FT_Stream stream,
FT_Long distance )
{
return FT_Stream_Skip( stream, distance );
}
FT_BASE_DEF( FT_Error )
FT_Read_Stream( FT_Stream stream,
FT_Byte* buffer,
FT_ULong count )
{
return FT_Stream_Read( stream, buffer, count );
}
FT_BASE_DEF( FT_Error )
FT_Read_Stream_At( FT_Stream stream,
FT_ULong pos,
FT_Byte* buffer,
FT_ULong count )
{
return FT_Stream_ReadAt( stream, pos, buffer, count );
}
FT_BASE_DEF( FT_Error )
FT_Extract_Frame( FT_Stream stream,
FT_ULong count,
FT_Byte** pbytes )
{
return FT_Stream_ExtractFrame( stream, count, pbytes );
}
FT_BASE_DEF( void )
FT_Release_Frame( FT_Stream stream,
FT_Byte** pbytes )
{
FT_Stream_ReleaseFrame( stream, pbytes );
}
FT_BASE_DEF( FT_Error )
FT_Access_Frame( FT_Stream stream,
FT_ULong count )
{
return FT_Stream_EnterFrame( stream, count );
}
FT_BASE_DEF( void )
FT_Forget_Frame( FT_Stream stream )
{
FT_Stream_ExitFrame( stream );
}
/* END */
+41
View File
@@ -0,0 +1,41 @@
/***************************************************************************/
/* */
/* ftbase.c */
/* */
/* Single object library component (body only). */
/* */
/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009 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>
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include "ftpic.c"
#include "basepic.c"
#include "ftadvanc.c"
#include "ftcalc.c"
#include "ftdbgmem.c"
#include "ftgloadr.c"
#include "ftobjs.c"
#include "ftoutln.c"
#include "ftrfork.c"
#include "ftsnames.c"
#include "ftstream.c"
#include "fttrigon.c"
#include "ftutil.c"
#if defined( FT_MACINTOSH ) && !defined ( DARWIN_NO_CARBON )
#include "ftmac.c"
#endif
/* END */
+68
View File
@@ -0,0 +1,68 @@
/***************************************************************************/
/* */
/* ftbase.h */
/* */
/* The FreeType private functions used in base module (specification). */
/* */
/* Copyright 2008, 2010 by */
/* David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. */
/* */
/* 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. */
/* */
/***************************************************************************/
#ifndef __FTBASE_H__
#define __FTBASE_H__
#include <ft2build.h>
#include FT_INTERNAL_OBJECTS_H
FT_BEGIN_HEADER
/* Assume the stream is sfnt-wrapped PS Type1 or sfnt-wrapped CID-keyed */
/* font, and try to load a face specified by the face_index. */
FT_LOCAL( FT_Error )
open_face_PS_from_sfnt_stream( FT_Library library,
FT_Stream stream,
FT_Long face_index,
FT_Int num_params,
FT_Parameter *params,
FT_Face *aface );
/* Create a new FT_Face given a buffer and a driver name. */
/* From ftmac.c. */
FT_LOCAL( FT_Error )
open_face_from_buffer( FT_Library library,
FT_Byte* base,
FT_ULong size,
FT_Long face_index,
const char* driver_name,
FT_Face *aface );
#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
/* Mac OS X/Darwin kernel often changes recommended method to access */
/* the resource fork and older methods makes the kernel issue the */
/* warning of deprecated method. To calm it down, the methods based */
/* on Darwin VFS should be grouped and skip the rest methods after */
/* the case the resource is opened but found to lack a font in it. */
FT_LOCAL( FT_Bool )
raccess_rule_by_darwin_vfs( FT_UInt rule_index );
#endif /* FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
FT_END_HEADER
#endif /* __FTBASE_H__ */
/* END */
+662
View File
@@ -0,0 +1,662 @@
/***************************************************************************/
/* */
/* ftbbox.c */
/* */
/* FreeType bbox computation (body). */
/* */
/* Copyright 1996-2001, 2002, 2004, 2006, 2010 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. */
/* */
/***************************************************************************/
/*************************************************************************/
/* */
/* This component has a _single_ role: to compute exact outline bounding */
/* boxes. */
/* */
/*************************************************************************/
#include <ft2build.h>
#include FT_BBOX_H
#include FT_IMAGE_H
#include FT_OUTLINE_H
#include FT_INTERNAL_CALC_H
#include FT_INTERNAL_OBJECTS_H
typedef struct TBBox_Rec_
{
FT_Vector last;
FT_BBox bbox;
} TBBox_Rec;
/*************************************************************************/
/* */
/* <Function> */
/* BBox_Move_To */
/* */
/* <Description> */
/* This function is used as a `move_to' and `line_to' emitter during */
/* FT_Outline_Decompose(). It simply records the destination point */
/* in `user->last'; no further computations are necessary since we */
/* use the cbox as the starting bbox which must be refined. */
/* */
/* <Input> */
/* to :: A pointer to the destination vector. */
/* */
/* <InOut> */
/* user :: A pointer to the current walk context. */
/* */
/* <Return> */
/* Always 0. Needed for the interface only. */
/* */
static int
BBox_Move_To( FT_Vector* to,
TBBox_Rec* user )
{
user->last = *to;
return 0;
}
#define CHECK_X( p, bbox ) \
( p->x < bbox.xMin || p->x > bbox.xMax )
#define CHECK_Y( p, bbox ) \
( p->y < bbox.yMin || p->y > bbox.yMax )
/*************************************************************************/
/* */
/* <Function> */
/* BBox_Conic_Check */
/* */
/* <Description> */
/* Finds the extrema of a 1-dimensional conic Bezier curve and update */
/* a bounding range. This version uses direct computation, as it */
/* doesn't need square roots. */
/* */
/* <Input> */
/* y1 :: The start coordinate. */
/* */
/* y2 :: The coordinate of the control point. */
/* */
/* y3 :: The end coordinate. */
/* */
/* <InOut> */
/* min :: The address of the current minimum. */
/* */
/* max :: The address of the current maximum. */
/* */
static void
BBox_Conic_Check( FT_Pos y1,
FT_Pos y2,
FT_Pos y3,
FT_Pos* min,
FT_Pos* max )
{
if ( y1 <= y3 && y2 == y1 ) /* flat arc */
goto Suite;
if ( y1 < y3 )
{
if ( y2 >= y1 && y2 <= y3 ) /* ascending arc */
goto Suite;
}
else
{
if ( y2 >= y3 && y2 <= y1 ) /* descending arc */
{
y2 = y1;
y1 = y3;
y3 = y2;
goto Suite;
}
}
y1 = y3 = y1 - FT_MulDiv( y2 - y1, y2 - y1, y1 - 2*y2 + y3 );
Suite:
if ( y1 < *min ) *min = y1;
if ( y3 > *max ) *max = y3;
}
/*************************************************************************/
/* */
/* <Function> */
/* BBox_Conic_To */
/* */
/* <Description> */
/* This function is used as a `conic_to' emitter during */
/* FT_Outline_Decompose(). It checks a conic Bezier curve with the */
/* current bounding box, and computes its extrema if necessary to */
/* update it. */
/* */
/* <Input> */
/* control :: A pointer to a control point. */
/* */
/* to :: A pointer to the destination vector. */
/* */
/* <InOut> */
/* user :: The address of the current walk context. */
/* */
/* <Return> */
/* Always 0. Needed for the interface only. */
/* */
/* <Note> */
/* In the case of a non-monotonous arc, we compute directly the */
/* extremum coordinates, as it is sufficiently fast. */
/* */
static int
BBox_Conic_To( FT_Vector* control,
FT_Vector* to,
TBBox_Rec* user )
{
/* we don't need to check `to' since it is always an `on' point, thus */
/* within the bbox */
if ( CHECK_X( control, user->bbox ) )
BBox_Conic_Check( user->last.x,
control->x,
to->x,
&user->bbox.xMin,
&user->bbox.xMax );
if ( CHECK_Y( control, user->bbox ) )
BBox_Conic_Check( user->last.y,
control->y,
to->y,
&user->bbox.yMin,
&user->bbox.yMax );
user->last = *to;
return 0;
}
/*************************************************************************/
/* */
/* <Function> */
/* BBox_Cubic_Check */
/* */
/* <Description> */
/* Finds the extrema of a 1-dimensional cubic Bezier curve and */
/* updates a bounding range. This version uses splitting because we */
/* don't want to use square roots and extra accuracy. */
/* */
/* <Input> */
/* p1 :: The start coordinate. */
/* */
/* p2 :: The coordinate of the first control point. */
/* */
/* p3 :: The coordinate of the second control point. */
/* */
/* p4 :: The end coordinate. */
/* */
/* <InOut> */
/* min :: The address of the current minimum. */
/* */
/* max :: The address of the current maximum. */
/* */
#if 0
static void
BBox_Cubic_Check( FT_Pos p1,
FT_Pos p2,
FT_Pos p3,
FT_Pos p4,
FT_Pos* min,
FT_Pos* max )
{
FT_Pos stack[32*3 + 1], *arc;
arc = stack;
arc[0] = p1;
arc[1] = p2;
arc[2] = p3;
arc[3] = p4;
do
{
FT_Pos y1 = arc[0];
FT_Pos y2 = arc[1];
FT_Pos y3 = arc[2];
FT_Pos y4 = arc[3];
if ( y1 == y4 )
{
if ( y1 == y2 && y1 == y3 ) /* flat */
goto Test;
}
else if ( y1 < y4 )
{
if ( y2 >= y1 && y2 <= y4 && y3 >= y1 && y3 <= y4 ) /* ascending */
goto Test;
}
else
{
if ( y2 >= y4 && y2 <= y1 && y3 >= y4 && y3 <= y1 ) /* descending */
{
y2 = y1;
y1 = y4;
y4 = y2;
goto Test;
}
}
/* unknown direction -- split the arc in two */
arc[6] = y4;
arc[1] = y1 = ( y1 + y2 ) / 2;
arc[5] = y4 = ( y4 + y3 ) / 2;
y2 = ( y2 + y3 ) / 2;
arc[2] = y1 = ( y1 + y2 ) / 2;
arc[4] = y4 = ( y4 + y2 ) / 2;
arc[3] = ( y1 + y4 ) / 2;
arc += 3;
goto Suite;
Test:
if ( y1 < *min ) *min = y1;
if ( y4 > *max ) *max = y4;
arc -= 3;
Suite:
;
} while ( arc >= stack );
}
#else
static void
test_cubic_extrema( FT_Pos y1,
FT_Pos y2,
FT_Pos y3,
FT_Pos y4,
FT_Fixed u,
FT_Pos* min,
FT_Pos* max )
{
/* FT_Pos a = y4 - 3*y3 + 3*y2 - y1; */
FT_Pos b = y3 - 2*y2 + y1;
FT_Pos c = y2 - y1;
FT_Pos d = y1;
FT_Pos y;
FT_Fixed uu;
FT_UNUSED ( y4 );
/* The polynomial is */
/* */
/* P(x) = a*x^3 + 3b*x^2 + 3c*x + d , */
/* */
/* dP/dx = 3a*x^2 + 6b*x + 3c . */
/* */
/* However, we also have */
/* */
/* dP/dx(u) = 0 , */
/* */
/* which implies by subtraction that */
/* */
/* P(u) = b*u^2 + 2c*u + d . */
if ( u > 0 && u < 0x10000L )
{
uu = FT_MulFix( u, u );
y = d + FT_MulFix( c, 2*u ) + FT_MulFix( b, uu );
if ( y < *min ) *min = y;
if ( y > *max ) *max = y;
}
}
static void
BBox_Cubic_Check( FT_Pos y1,
FT_Pos y2,
FT_Pos y3,
FT_Pos y4,
FT_Pos* min,
FT_Pos* max )
{
/* always compare first and last points */
if ( y1 < *min ) *min = y1;
else if ( y1 > *max ) *max = y1;
if ( y4 < *min ) *min = y4;
else if ( y4 > *max ) *max = y4;
/* now, try to see if there are split points here */
if ( y1 <= y4 )
{
/* flat or ascending arc test */
if ( y1 <= y2 && y2 <= y4 && y1 <= y3 && y3 <= y4 )
return;
}
else /* y1 > y4 */
{
/* descending arc test */
if ( y1 >= y2 && y2 >= y4 && y1 >= y3 && y3 >= y4 )
return;
}
/* There are some split points. Find them. */
{
FT_Pos a = y4 - 3*y3 + 3*y2 - y1;
FT_Pos b = y3 - 2*y2 + y1;
FT_Pos c = y2 - y1;
FT_Pos d;
FT_Fixed t;
/* We need to solve `ax^2+2bx+c' here, without floating points! */
/* The trick is to normalize to a different representation in order */
/* to use our 16.16 fixed point routines. */
/* */
/* We compute FT_MulFix(b,b) and FT_MulFix(a,c) after normalization. */
/* These values must fit into a single 16.16 value. */
/* */
/* We normalize a, b, and c to `8.16' fixed float values to ensure */
/* that its product is held in a `16.16' value. */
{
FT_ULong t1, t2;
int shift = 0;
/* The following computation is based on the fact that for */
/* any value `y', if `n' is the position of the most */
/* significant bit of `abs(y)' (starting from 0 for the */
/* least significant bit), then `y' is in the range */
/* */
/* -2^n..2^n-1 */
/* */
/* We want to shift `a', `b', and `c' concurrently in order */
/* to ensure that they all fit in 8.16 values, which maps */
/* to the integer range `-2^23..2^23-1'. */
/* */
/* Necessarily, we need to shift `a', `b', and `c' so that */
/* the most significant bit of its absolute values is at */
/* _most_ at position 23. */
/* */
/* We begin by computing `t1' as the bitwise `OR' of the */
/* absolute values of `a', `b', `c'. */
t1 = (FT_ULong)( ( a >= 0 ) ? a : -a );
t2 = (FT_ULong)( ( b >= 0 ) ? b : -b );
t1 |= t2;
t2 = (FT_ULong)( ( c >= 0 ) ? c : -c );
t1 |= t2;
/* Now we can be sure that the most significant bit of `t1' */
/* is the most significant bit of either `a', `b', or `c', */
/* depending on the greatest integer range of the particular */
/* variable. */
/* */
/* Next, we compute the `shift', by shifting `t1' as many */
/* times as necessary to move its MSB to position 23. This */
/* corresponds to a value of `t1' that is in the range */
/* 0x40_0000..0x7F_FFFF. */
/* */
/* Finally, we shift `a', `b', and `c' by the same amount. */
/* This ensures that all values are now in the range */
/* -2^23..2^23, i.e., they are now expressed as 8.16 */
/* fixed-float numbers. This also means that we are using */
/* 24 bits of precision to compute the zeros, independently */
/* of the range of the original polynomial coefficients. */
/* */
/* This algorithm should ensure reasonably accurate values */
/* for the zeros. Note that they are only expressed with */
/* 16 bits when computing the extrema (the zeros need to */
/* be in 0..1 exclusive to be considered part of the arc). */
if ( t1 == 0 ) /* all coefficients are 0! */
return;
if ( t1 > 0x7FFFFFUL )
{
do
{
shift++;
t1 >>= 1;
} while ( t1 > 0x7FFFFFUL );
/* this loses some bits of precision, but we use 24 of them */
/* for the computation anyway */
a >>= shift;
b >>= shift;
c >>= shift;
}
else if ( t1 < 0x400000UL )
{
do
{
shift++;
t1 <<= 1;
} while ( t1 < 0x400000UL );
a <<= shift;
b <<= shift;
c <<= shift;
}
}
/* handle a == 0 */
if ( a == 0 )
{
if ( b != 0 )
{
t = - FT_DivFix( c, b ) / 2;
test_cubic_extrema( y1, y2, y3, y4, t, min, max );
}
}
else
{
/* solve the equation now */
d = FT_MulFix( b, b ) - FT_MulFix( a, c );
if ( d < 0 )
return;
if ( d == 0 )
{
/* there is a single split point at -b/a */
t = - FT_DivFix( b, a );
test_cubic_extrema( y1, y2, y3, y4, t, min, max );
}
else
{
/* there are two solutions; we need to filter them */
d = FT_SqrtFixed( (FT_Int32)d );
t = - FT_DivFix( b - d, a );
test_cubic_extrema( y1, y2, y3, y4, t, min, max );
t = - FT_DivFix( b + d, a );
test_cubic_extrema( y1, y2, y3, y4, t, min, max );
}
}
}
}
#endif
/*************************************************************************/
/* */
/* <Function> */
/* BBox_Cubic_To */
/* */
/* <Description> */
/* This function is used as a `cubic_to' emitter during */
/* FT_Outline_Decompose(). It checks a cubic Bezier curve with the */
/* current bounding box, and computes its extrema if necessary to */
/* update it. */
/* */
/* <Input> */
/* control1 :: A pointer to the first control point. */
/* */
/* control2 :: A pointer to the second control point. */
/* */
/* to :: A pointer to the destination vector. */
/* */
/* <InOut> */
/* user :: The address of the current walk context. */
/* */
/* <Return> */
/* Always 0. Needed for the interface only. */
/* */
/* <Note> */
/* In the case of a non-monotonous arc, we don't compute directly */
/* extremum coordinates, we subdivide instead. */
/* */
static int
BBox_Cubic_To( FT_Vector* control1,
FT_Vector* control2,
FT_Vector* to,
TBBox_Rec* user )
{
/* we don't need to check `to' since it is always an `on' point, thus */
/* within the bbox */
if ( CHECK_X( control1, user->bbox ) ||
CHECK_X( control2, user->bbox ) )
BBox_Cubic_Check( user->last.x,
control1->x,
control2->x,
to->x,
&user->bbox.xMin,
&user->bbox.xMax );
if ( CHECK_Y( control1, user->bbox ) ||
CHECK_Y( control2, user->bbox ) )
BBox_Cubic_Check( user->last.y,
control1->y,
control2->y,
to->y,
&user->bbox.yMin,
&user->bbox.yMax );
user->last = *to;
return 0;
}
FT_DEFINE_OUTLINE_FUNCS(bbox_interface,
(FT_Outline_MoveTo_Func) BBox_Move_To,
(FT_Outline_LineTo_Func) BBox_Move_To,
(FT_Outline_ConicTo_Func)BBox_Conic_To,
(FT_Outline_CubicTo_Func)BBox_Cubic_To,
0, 0
)
/* documentation is in ftbbox.h */
FT_EXPORT_DEF( FT_Error )
FT_Outline_Get_BBox( FT_Outline* outline,
FT_BBox *abbox )
{
FT_BBox cbox;
FT_BBox bbox;
FT_Vector* vec;
FT_UShort n;
if ( !abbox )
return FT_Err_Invalid_Argument;
if ( !outline )
return FT_Err_Invalid_Outline;
/* if outline is empty, return (0,0,0,0) */
if ( outline->n_points == 0 || outline->n_contours <= 0 )
{
abbox->xMin = abbox->xMax = 0;
abbox->yMin = abbox->yMax = 0;
return 0;
}
/* We compute the control box as well as the bounding box of */
/* all `on' points in the outline. Then, if the two boxes */
/* coincide, we exit immediately. */
vec = outline->points;
bbox.xMin = bbox.xMax = cbox.xMin = cbox.xMax = vec->x;
bbox.yMin = bbox.yMax = cbox.yMin = cbox.yMax = vec->y;
vec++;
for ( n = 1; n < outline->n_points; n++ )
{
FT_Pos x = vec->x;
FT_Pos y = vec->y;
/* update control box */
if ( x < cbox.xMin ) cbox.xMin = x;
if ( x > cbox.xMax ) cbox.xMax = x;
if ( y < cbox.yMin ) cbox.yMin = y;
if ( y > cbox.yMax ) cbox.yMax = y;
if ( FT_CURVE_TAG( outline->tags[n] ) == FT_CURVE_TAG_ON )
{
/* update bbox for `on' points only */
if ( x < bbox.xMin ) bbox.xMin = x;
if ( x > bbox.xMax ) bbox.xMax = x;
if ( y < bbox.yMin ) bbox.yMin = y;
if ( y > bbox.yMax ) bbox.yMax = y;
}
vec++;
}
/* test two boxes for equality */
if ( cbox.xMin < bbox.xMin || cbox.xMax > bbox.xMax ||
cbox.yMin < bbox.yMin || cbox.yMax > bbox.yMax )
{
/* the two boxes are different, now walk over the outline to */
/* get the Bezier arc extrema. */
FT_Error error;
TBBox_Rec user;
#ifdef FT_CONFIG_OPTION_PIC
FT_Outline_Funcs bbox_interface;
Init_Class_bbox_interface(&bbox_interface);
#endif
user.bbox = bbox;
error = FT_Outline_Decompose( outline, &bbox_interface, &user );
if ( error )
return error;
*abbox = user.bbox;
}
else
*abbox = bbox;
return FT_Err_Ok;
}
/* END */
+663
View File
@@ -0,0 +1,663 @@
/***************************************************************************/
/* */
/* ftbitmap.c */
/* */
/* FreeType utility functions for bitmaps (body). */
/* */
/* Copyright 2004, 2005, 2006, 2007, 2008, 2009 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_BITMAP_H
#include FT_IMAGE_H
#include FT_INTERNAL_OBJECTS_H
static
const FT_Bitmap null_bitmap = { 0, 0, 0, 0, 0, 0, 0, 0 };
/* documentation is in ftbitmap.h */
FT_EXPORT_DEF( void )
FT_Bitmap_New( FT_Bitmap *abitmap )
{
*abitmap = null_bitmap;
}
/* documentation is in ftbitmap.h */
FT_EXPORT_DEF( FT_Error )
FT_Bitmap_Copy( FT_Library library,
const FT_Bitmap *source,
FT_Bitmap *target)
{
FT_Memory memory = library->memory;
FT_Error error = FT_Err_Ok;
FT_Int pitch = source->pitch;
FT_ULong size;
if ( source == target )
return FT_Err_Ok;
if ( source->buffer == NULL )
{
*target = *source;
return FT_Err_Ok;
}
if ( pitch < 0 )
pitch = -pitch;
size = (FT_ULong)( pitch * source->rows );
if ( target->buffer )
{
FT_Int target_pitch = target->pitch;
FT_ULong target_size;
if ( target_pitch < 0 )
target_pitch = -target_pitch;
target_size = (FT_ULong)( target_pitch * target->rows );
if ( target_size != size )
(void)FT_QREALLOC( target->buffer, target_size, size );
}
else
(void)FT_QALLOC( target->buffer, size );
if ( !error )
{
unsigned char *p;
p = target->buffer;
*target = *source;
target->buffer = p;
FT_MEM_COPY( target->buffer, source->buffer, size );
}
return error;
}
static FT_Error
ft_bitmap_assure_buffer( FT_Memory memory,
FT_Bitmap* bitmap,
FT_UInt xpixels,
FT_UInt ypixels )
{
FT_Error error;
int pitch;
int new_pitch;
FT_UInt bpp;
FT_Int i, width, height;
unsigned char* buffer;
width = bitmap->width;
height = bitmap->rows;
pitch = bitmap->pitch;
if ( pitch < 0 )
pitch = -pitch;
switch ( bitmap->pixel_mode )
{
case FT_PIXEL_MODE_MONO:
bpp = 1;
new_pitch = ( width + xpixels + 7 ) >> 3;
break;
case FT_PIXEL_MODE_GRAY2:
bpp = 2;
new_pitch = ( width + xpixels + 3 ) >> 2;
break;
case FT_PIXEL_MODE_GRAY4:
bpp = 4;
new_pitch = ( width + xpixels + 1 ) >> 1;
break;
case FT_PIXEL_MODE_GRAY:
case FT_PIXEL_MODE_LCD:
case FT_PIXEL_MODE_LCD_V:
bpp = 8;
new_pitch = ( width + xpixels );
break;
default:
return FT_Err_Invalid_Glyph_Format;
}
/* if no need to allocate memory */
if ( ypixels == 0 && new_pitch <= pitch )
{
/* zero the padding */
FT_Int bit_width = pitch * 8;
FT_Int bit_last = ( width + xpixels ) * bpp;
if ( bit_last < bit_width )
{
FT_Byte* line = bitmap->buffer + ( bit_last >> 3 );
FT_Byte* end = bitmap->buffer + pitch;
FT_Int shift = bit_last & 7;
FT_UInt mask = 0xFF00U >> shift;
FT_Int count = height;
for ( ; count > 0; count--, line += pitch, end += pitch )
{
FT_Byte* write = line;
if ( shift > 0 )
{
write[0] = (FT_Byte)( write[0] & mask );
write++;
}
if ( write < end )
FT_MEM_ZERO( write, end-write );
}
}
return FT_Err_Ok;
}
if ( FT_QALLOC_MULT( buffer, new_pitch, bitmap->rows + ypixels ) )
return error;
if ( bitmap->pitch > 0 )
{
FT_Int len = ( width * bpp + 7 ) >> 3;
for ( i = 0; i < bitmap->rows; i++ )
FT_MEM_COPY( buffer + new_pitch * ( ypixels + i ),
bitmap->buffer + pitch * i, len );
}
else
{
FT_Int len = ( width * bpp + 7 ) >> 3;
for ( i = 0; i < bitmap->rows; i++ )
FT_MEM_COPY( buffer + new_pitch * i,
bitmap->buffer + pitch * i, len );
}
FT_FREE( bitmap->buffer );
bitmap->buffer = buffer;
if ( bitmap->pitch < 0 )
new_pitch = -new_pitch;
/* set pitch only, width and height are left untouched */
bitmap->pitch = new_pitch;
return FT_Err_Ok;
}
/* documentation is in ftbitmap.h */
FT_EXPORT_DEF( FT_Error )
FT_Bitmap_Embolden( FT_Library library,
FT_Bitmap* bitmap,
FT_Pos xStrength,
FT_Pos yStrength )
{
FT_Error error;
unsigned char* p;
FT_Int i, x, y, pitch;
FT_Int xstr, ystr;
if ( !library )
return FT_Err_Invalid_Library_Handle;
if ( !bitmap || !bitmap->buffer )
return FT_Err_Invalid_Argument;
if ( ( ( FT_PIX_ROUND( xStrength ) >> 6 ) > FT_INT_MAX ) ||
( ( FT_PIX_ROUND( yStrength ) >> 6 ) > FT_INT_MAX ) )
return FT_Err_Invalid_Argument;
xstr = (FT_Int)FT_PIX_ROUND( xStrength ) >> 6;
ystr = (FT_Int)FT_PIX_ROUND( yStrength ) >> 6;
if ( xstr == 0 && ystr == 0 )
return FT_Err_Ok;
else if ( xstr < 0 || ystr < 0 )
return FT_Err_Invalid_Argument;
switch ( bitmap->pixel_mode )
{
case FT_PIXEL_MODE_GRAY2:
case FT_PIXEL_MODE_GRAY4:
{
FT_Bitmap tmp;
FT_Int align;
if ( bitmap->pixel_mode == FT_PIXEL_MODE_GRAY2 )
align = ( bitmap->width + xstr + 3 ) / 4;
else
align = ( bitmap->width + xstr + 1 ) / 2;
FT_Bitmap_New( &tmp );
error = FT_Bitmap_Convert( library, bitmap, &tmp, align );
if ( error )
return error;
FT_Bitmap_Done( library, bitmap );
*bitmap = tmp;
}
break;
case FT_PIXEL_MODE_MONO:
if ( xstr > 8 )
xstr = 8;
break;
case FT_PIXEL_MODE_LCD:
xstr *= 3;
break;
case FT_PIXEL_MODE_LCD_V:
ystr *= 3;
break;
}
error = ft_bitmap_assure_buffer( library->memory, bitmap, xstr, ystr );
if ( error )
return error;
pitch = bitmap->pitch;
if ( pitch > 0 )
p = bitmap->buffer + pitch * ystr;
else
{
pitch = -pitch;
p = bitmap->buffer + pitch * ( bitmap->rows - 1 );
}
/* for each row */
for ( y = 0; y < bitmap->rows ; y++ )
{
/*
* Horizontally:
*
* From the last pixel on, make each pixel or'ed with the
* `xstr' pixels before it.
*/
for ( x = pitch - 1; x >= 0; x-- )
{
unsigned char tmp;
tmp = p[x];
for ( i = 1; i <= xstr; i++ )
{
if ( bitmap->pixel_mode == FT_PIXEL_MODE_MONO )
{
p[x] |= tmp >> i;
/* the maximum value of 8 for `xstr' comes from here */
if ( x > 0 )
p[x] |= p[x - 1] << ( 8 - i );
#if 0
if ( p[x] == 0xff )
break;
#endif
}
else
{
if ( x - i >= 0 )
{
if ( p[x] + p[x - i] > bitmap->num_grays - 1 )
{
p[x] = (unsigned char)(bitmap->num_grays - 1);
break;
}
else
{
p[x] = (unsigned char)(p[x] + p[x-i]);
if ( p[x] == bitmap->num_grays - 1 )
break;
}
}
else
break;
}
}
}
/*
* Vertically:
*
* Make the above `ystr' rows or'ed with it.
*/
for ( x = 1; x <= ystr; x++ )
{
unsigned char* q;
q = p - bitmap->pitch * x;
for ( i = 0; i < pitch; i++ )
q[i] |= p[i];
}
p += bitmap->pitch;
}
bitmap->width += xstr;
bitmap->rows += ystr;
return FT_Err_Ok;
}
/* documentation is in ftbitmap.h */
FT_EXPORT_DEF( FT_Error )
FT_Bitmap_Convert( FT_Library library,
const FT_Bitmap *source,
FT_Bitmap *target,
FT_Int alignment )
{
FT_Error error = FT_Err_Ok;
FT_Memory memory;
if ( !library )
return FT_Err_Invalid_Library_Handle;
memory = library->memory;
switch ( source->pixel_mode )
{
case FT_PIXEL_MODE_MONO:
case FT_PIXEL_MODE_GRAY:
case FT_PIXEL_MODE_GRAY2:
case FT_PIXEL_MODE_GRAY4:
case FT_PIXEL_MODE_LCD:
case FT_PIXEL_MODE_LCD_V:
{
FT_Int pad;
FT_Long old_size;
old_size = target->rows * target->pitch;
if ( old_size < 0 )
old_size = -old_size;
target->pixel_mode = FT_PIXEL_MODE_GRAY;
target->rows = source->rows;
target->width = source->width;
pad = 0;
if ( alignment > 0 )
{
pad = source->width % alignment;
if ( pad != 0 )
pad = alignment - pad;
}
target->pitch = source->width + pad;
if ( target->rows * target->pitch > old_size &&
FT_QREALLOC( target->buffer,
old_size, target->rows * target->pitch ) )
return error;
}
break;
default:
error = FT_Err_Invalid_Argument;
}
switch ( source->pixel_mode )
{
case FT_PIXEL_MODE_MONO:
{
FT_Byte* s = source->buffer;
FT_Byte* t = target->buffer;
FT_Int i;
target->num_grays = 2;
for ( i = source->rows; i > 0; i-- )
{
FT_Byte* ss = s;
FT_Byte* tt = t;
FT_Int j;
/* get the full bytes */
for ( j = source->width >> 3; j > 0; j-- )
{
FT_Int val = ss[0]; /* avoid a byte->int cast on each line */
tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7 );
tt[1] = (FT_Byte)( ( val & 0x40 ) >> 6 );
tt[2] = (FT_Byte)( ( val & 0x20 ) >> 5 );
tt[3] = (FT_Byte)( ( val & 0x10 ) >> 4 );
tt[4] = (FT_Byte)( ( val & 0x08 ) >> 3 );
tt[5] = (FT_Byte)( ( val & 0x04 ) >> 2 );
tt[6] = (FT_Byte)( ( val & 0x02 ) >> 1 );
tt[7] = (FT_Byte)( val & 0x01 );
tt += 8;
ss += 1;
}
/* get remaining pixels (if any) */
j = source->width & 7;
if ( j > 0 )
{
FT_Int val = *ss;
for ( ; j > 0; j-- )
{
tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7);
val <<= 1;
tt += 1;
}
}
s += source->pitch;
t += target->pitch;
}
}
break;
case FT_PIXEL_MODE_GRAY:
case FT_PIXEL_MODE_LCD:
case FT_PIXEL_MODE_LCD_V:
{
FT_Int width = source->width;
FT_Byte* s = source->buffer;
FT_Byte* t = target->buffer;
FT_Int s_pitch = source->pitch;
FT_Int t_pitch = target->pitch;
FT_Int i;
target->num_grays = 256;
for ( i = source->rows; i > 0; i-- )
{
FT_ARRAY_COPY( t, s, width );
s += s_pitch;
t += t_pitch;
}
}
break;
case FT_PIXEL_MODE_GRAY2:
{
FT_Byte* s = source->buffer;
FT_Byte* t = target->buffer;
FT_Int i;
target->num_grays = 4;
for ( i = source->rows; i > 0; i-- )
{
FT_Byte* ss = s;
FT_Byte* tt = t;
FT_Int j;
/* get the full bytes */
for ( j = source->width >> 2; j > 0; j-- )
{
FT_Int val = ss[0];
tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 );
tt[1] = (FT_Byte)( ( val & 0x30 ) >> 4 );
tt[2] = (FT_Byte)( ( val & 0x0C ) >> 2 );
tt[3] = (FT_Byte)( ( val & 0x03 ) );
ss += 1;
tt += 4;
}
j = source->width & 3;
if ( j > 0 )
{
FT_Int val = ss[0];
for ( ; j > 0; j-- )
{
tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 );
val <<= 2;
tt += 1;
}
}
s += source->pitch;
t += target->pitch;
}
}
break;
case FT_PIXEL_MODE_GRAY4:
{
FT_Byte* s = source->buffer;
FT_Byte* t = target->buffer;
FT_Int i;
target->num_grays = 16;
for ( i = source->rows; i > 0; i-- )
{
FT_Byte* ss = s;
FT_Byte* tt = t;
FT_Int j;
/* get the full bytes */
for ( j = source->width >> 1; j > 0; j-- )
{
FT_Int val = ss[0];
tt[0] = (FT_Byte)( ( val & 0xF0 ) >> 4 );
tt[1] = (FT_Byte)( ( val & 0x0F ) );
ss += 1;
tt += 2;
}
if ( source->width & 1 )
tt[0] = (FT_Byte)( ( ss[0] & 0xF0 ) >> 4 );
s += source->pitch;
t += target->pitch;
}
}
break;
default:
;
}
return error;
}
/* documentation is in ftbitmap.h */
FT_EXPORT_DEF( FT_Error )
FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot slot )
{
if ( slot && slot->format == FT_GLYPH_FORMAT_BITMAP &&
!( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
{
FT_Bitmap bitmap;
FT_Error error;
FT_Bitmap_New( &bitmap );
error = FT_Bitmap_Copy( slot->library, &slot->bitmap, &bitmap );
if ( error )
return error;
slot->bitmap = bitmap;
slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
}
return FT_Err_Ok;
}
/* documentation is in ftbitmap.h */
FT_EXPORT_DEF( FT_Error )
FT_Bitmap_Done( FT_Library library,
FT_Bitmap *bitmap )
{
FT_Memory memory;
if ( !library )
return FT_Err_Invalid_Library_Handle;
if ( !bitmap )
return FT_Err_Invalid_Argument;
memory = library->memory;
FT_FREE( bitmap->buffer );
*bitmap = null_bitmap;
return FT_Err_Ok;
}
/* END */
+957
View File
@@ -0,0 +1,957 @@
/***************************************************************************/
/* */
/* ftcalc.c */
/* */
/* Arithmetic computations (body). */
/* */
/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2008 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. */
/* */
/***************************************************************************/
/*************************************************************************/
/* */
/* Support for 1-complement arithmetic has been totally dropped in this */
/* release. You can still write your own code if you need it. */
/* */
/*************************************************************************/
/*************************************************************************/
/* */
/* Implementing basic computation routines. */
/* */
/* FT_MulDiv(), FT_MulFix(), FT_DivFix(), FT_RoundFix(), FT_CeilFix(), */
/* and FT_FloorFix() are declared in freetype.h. */
/* */
/*************************************************************************/
#include <ft2build.h>
#include FT_GLYPH_H
#include FT_INTERNAL_CALC_H
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_OBJECTS_H
#ifdef FT_MULFIX_INLINED
#undef FT_MulFix
#endif
/* we need to define a 64-bits data type here */
#ifdef FT_LONG64
typedef FT_INT64 FT_Int64;
#else
typedef struct FT_Int64_
{
FT_UInt32 lo;
FT_UInt32 hi;
} FT_Int64;
#endif /* FT_LONG64 */
/*************************************************************************/
/* */
/* 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_calc
/* The following three functions are available regardless of whether */
/* FT_LONG64 is defined. */
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_Fixed )
FT_RoundFix( FT_Fixed a )
{
return ( a >= 0 ) ? ( a + 0x8000L ) & ~0xFFFFL
: -((-a + 0x8000L ) & ~0xFFFFL );
}
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_Fixed )
FT_CeilFix( FT_Fixed a )
{
return ( a >= 0 ) ? ( a + 0xFFFFL ) & ~0xFFFFL
: -((-a + 0xFFFFL ) & ~0xFFFFL );
}
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_Fixed )
FT_FloorFix( FT_Fixed a )
{
return ( a >= 0 ) ? a & ~0xFFFFL
: -((-a) & ~0xFFFFL );
}
#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
/* documentation is in ftcalc.h */
FT_EXPORT_DEF( FT_Int32 )
FT_Sqrt32( FT_Int32 x )
{
FT_UInt32 val, root, newroot, mask;
root = 0;
mask = (FT_UInt32)0x40000000UL;
val = (FT_UInt32)x;
do
{
newroot = root + mask;
if ( newroot <= val )
{
val -= newroot;
root = newroot + mask;
}
root >>= 1;
mask >>= 2;
} while ( mask != 0 );
return root;
}
#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
#ifdef FT_LONG64
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_Long )
FT_MulDiv( FT_Long a,
FT_Long b,
FT_Long c )
{
FT_Int s;
FT_Long d;
s = 1;
if ( a < 0 ) { a = -a; s = -1; }
if ( b < 0 ) { b = -b; s = -s; }
if ( c < 0 ) { c = -c; s = -s; }
d = (FT_Long)( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c
: 0x7FFFFFFFL );
return ( s > 0 ) ? d : -d;
}
#ifdef TT_USE_BYTECODE_INTERPRETER
/* documentation is in ftcalc.h */
FT_BASE_DEF( FT_Long )
FT_MulDiv_No_Round( FT_Long a,
FT_Long b,
FT_Long c )
{
FT_Int s;
FT_Long d;
s = 1;
if ( a < 0 ) { a = -a; s = -1; }
if ( b < 0 ) { b = -b; s = -s; }
if ( c < 0 ) { c = -c; s = -s; }
d = (FT_Long)( c > 0 ? (FT_Int64)a * b / c
: 0x7FFFFFFFL );
return ( s > 0 ) ? d : -d;
}
#endif /* TT_USE_BYTECODE_INTERPRETER */
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_Long )
FT_MulFix( FT_Long a,
FT_Long b )
{
#ifdef FT_MULFIX_ASSEMBLER
return FT_MULFIX_ASSEMBLER( a, b );
#else
FT_Int s = 1;
FT_Long c;
if ( a < 0 )
{
a = -a;
s = -1;
}
if ( b < 0 )
{
b = -b;
s = -s;
}
c = (FT_Long)( ( (FT_Int64)a * b + 0x8000L ) >> 16 );
return ( s > 0 ) ? c : -c;
#endif /* FT_MULFIX_ASSEMBLER */
}
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_Long )
FT_DivFix( FT_Long a,
FT_Long b )
{
FT_Int32 s;
FT_UInt32 q;
s = 1;
if ( a < 0 ) { a = -a; s = -1; }
if ( b < 0 ) { b = -b; s = -s; }
if ( b == 0 )
/* check for division by 0 */
q = 0x7FFFFFFFL;
else
/* compute result directly */
q = (FT_UInt32)( ( ( (FT_Int64)a << 16 ) + ( b >> 1 ) ) / b );
return ( s < 0 ? -(FT_Long)q : (FT_Long)q );
}
#else /* !FT_LONG64 */
static void
ft_multo64( FT_UInt32 x,
FT_UInt32 y,
FT_Int64 *z )
{
FT_UInt32 lo1, hi1, lo2, hi2, lo, hi, i1, i2;
lo1 = x & 0x0000FFFFU; hi1 = x >> 16;
lo2 = y & 0x0000FFFFU; hi2 = y >> 16;
lo = lo1 * lo2;
i1 = lo1 * hi2;
i2 = lo2 * hi1;
hi = hi1 * hi2;
/* Check carry overflow of i1 + i2 */
i1 += i2;
hi += (FT_UInt32)( i1 < i2 ) << 16;
hi += i1 >> 16;
i1 = i1 << 16;
/* Check carry overflow of i1 + lo */
lo += i1;
hi += ( lo < i1 );
z->lo = lo;
z->hi = hi;
}
static FT_UInt32
ft_div64by32( FT_UInt32 hi,
FT_UInt32 lo,
FT_UInt32 y )
{
FT_UInt32 r, q;
FT_Int i;
q = 0;
r = hi;
if ( r >= y )
return (FT_UInt32)0x7FFFFFFFL;
i = 32;
do
{
r <<= 1;
q <<= 1;
r |= lo >> 31;
if ( r >= (FT_UInt32)y )
{
r -= y;
q |= 1;
}
lo <<= 1;
} while ( --i );
return q;
}
static void
FT_Add64( FT_Int64* x,
FT_Int64* y,
FT_Int64 *z )
{
register FT_UInt32 lo, hi;
lo = x->lo + y->lo;
hi = x->hi + y->hi + ( lo < x->lo );
z->lo = lo;
z->hi = hi;
}
/* documentation is in freetype.h */
/* The FT_MulDiv function has been optimized thanks to ideas from */
/* Graham Asher. The trick is to optimize computation when everything */
/* fits within 32-bits (a rather common case). */
/* */
/* we compute 'a*b+c/2', then divide it by 'c'. (positive values) */
/* */
/* 46340 is FLOOR(SQRT(2^31-1)). */
/* */
/* if ( a <= 46340 && b <= 46340 ) then ( a*b <= 0x7FFEA810 ) */
/* */
/* 0x7FFFFFFF - 0x7FFEA810 = 0x157F0 */
/* */
/* if ( c < 0x157F0*2 ) then ( a*b+c/2 <= 0x7FFFFFFF ) */
/* */
/* and 2*0x157F0 = 176096 */
/* */
FT_EXPORT_DEF( FT_Long )
FT_MulDiv( FT_Long a,
FT_Long b,
FT_Long c )
{
long s;
/* XXX: this function does not allow 64-bit arguments */
if ( a == 0 || b == c )
return a;
s = a; a = FT_ABS( a );
s ^= b; b = FT_ABS( b );
s ^= c; c = FT_ABS( c );
if ( a <= 46340L && b <= 46340L && c <= 176095L && c > 0 )
a = ( a * b + ( c >> 1 ) ) / c;
else if ( c > 0 )
{
FT_Int64 temp, temp2;
ft_multo64( (FT_Int32)a, (FT_Int32)b, &temp );
temp2.hi = 0;
temp2.lo = (FT_UInt32)(c >> 1);
FT_Add64( &temp, &temp2, &temp );
a = ft_div64by32( temp.hi, temp.lo, (FT_Int32)c );
}
else
a = 0x7FFFFFFFL;
return ( s < 0 ? -a : a );
}
#ifdef TT_USE_BYTECODE_INTERPRETER
FT_BASE_DEF( FT_Long )
FT_MulDiv_No_Round( FT_Long a,
FT_Long b,
FT_Long c )
{
long s;
if ( a == 0 || b == c )
return a;
s = a; a = FT_ABS( a );
s ^= b; b = FT_ABS( b );
s ^= c; c = FT_ABS( c );
if ( a <= 46340L && b <= 46340L && c > 0 )
a = a * b / c;
else if ( c > 0 )
{
FT_Int64 temp;
ft_multo64( (FT_Int32)a, (FT_Int32)b, &temp );
a = ft_div64by32( temp.hi, temp.lo, (FT_Int32)c );
}
else
a = 0x7FFFFFFFL;
return ( s < 0 ? -a : a );
}
#endif /* TT_USE_BYTECODE_INTERPRETER */
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_Long )
FT_MulFix( FT_Long a,
FT_Long b )
{
#ifdef FT_MULFIX_ASSEMBLER
return FT_MULFIX_ASSEMBLER( a, b );
#elif 0
/*
* This code is nonportable. See comment below.
*
* However, on a platform where right-shift of a signed quantity fills
* the leftmost bits by copying the sign bit, it might be faster.
*/
FT_Long sa, sb;
FT_ULong ua, ub;
if ( a == 0 || b == 0x10000L )
return a;
/*
* This is a clever way of converting a signed number `a' into its
* absolute value (stored back into `a') and its sign. The sign is
* stored in `sa'; 0 means `a' was positive or zero, and -1 means `a'
* was negative. (Similarly for `b' and `sb').
*
* Unfortunately, it doesn't work (at least not portably).
*
* It makes the assumption that right-shift on a negative signed value
* fills the leftmost bits by copying the sign bit. This is wrong.
* According to K&R 2nd ed, section `A7.8 Shift Operators' on page 206,
* the result of right-shift of a negative signed value is
* implementation-defined. At least one implementation fills the
* leftmost bits with 0s (i.e., it is exactly the same as an unsigned
* right shift). This means that when `a' is negative, `sa' ends up
* with the value 1 rather than -1. After that, everything else goes
* wrong.
*/
sa = ( a >> ( sizeof ( a ) * 8 - 1 ) );
a = ( a ^ sa ) - sa;
sb = ( b >> ( sizeof ( b ) * 8 - 1 ) );
b = ( b ^ sb ) - sb;
ua = (FT_ULong)a;
ub = (FT_ULong)b;
if ( ua <= 2048 && ub <= 1048576L )
ua = ( ua * ub + 0x8000U ) >> 16;
else
{
FT_ULong al = ua & 0xFFFFU;
ua = ( ua >> 16 ) * ub + al * ( ub >> 16 ) +
( ( al * ( ub & 0xFFFFU ) + 0x8000U ) >> 16 );
}
sa ^= sb,
ua = (FT_ULong)(( ua ^ sa ) - sa);
return (FT_Long)ua;
#else /* 0 */
FT_Long s;
FT_ULong ua, ub;
if ( a == 0 || b == 0x10000L )
return a;
s = a; a = FT_ABS( a );
s ^= b; b = FT_ABS( b );
ua = (FT_ULong)a;
ub = (FT_ULong)b;
if ( ua <= 2048 && ub <= 1048576L )
ua = ( ua * ub + 0x8000UL ) >> 16;
else
{
FT_ULong al = ua & 0xFFFFUL;
ua = ( ua >> 16 ) * ub + al * ( ub >> 16 ) +
( ( al * ( ub & 0xFFFFUL ) + 0x8000UL ) >> 16 );
}
return ( s < 0 ? -(FT_Long)ua : (FT_Long)ua );
#endif /* 0 */
}
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_Long )
FT_DivFix( FT_Long a,
FT_Long b )
{
FT_Int32 s;
FT_UInt32 q;
/* XXX: this function does not allow 64-bit arguments */
s = (FT_Int32)a; a = FT_ABS( a );
s ^= (FT_Int32)b; b = FT_ABS( b );
if ( b == 0 )
{
/* check for division by 0 */
q = (FT_UInt32)0x7FFFFFFFL;
}
else if ( ( a >> 16 ) == 0 )
{
/* compute result directly */
q = (FT_UInt32)( (a << 16) + (b >> 1) ) / (FT_UInt32)b;
}
else
{
/* we need more bits; we have to do it by hand */
FT_Int64 temp, temp2;
temp.hi = (FT_Int32) (a >> 16);
temp.lo = (FT_UInt32)(a << 16);
temp2.hi = 0;
temp2.lo = (FT_UInt32)( b >> 1 );
FT_Add64( &temp, &temp2, &temp );
q = ft_div64by32( temp.hi, temp.lo, (FT_Int32)b );
}
return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
}
#if 0
/* documentation is in ftcalc.h */
FT_EXPORT_DEF( void )
FT_MulTo64( FT_Int32 x,
FT_Int32 y,
FT_Int64 *z )
{
FT_Int32 s;
s = x; x = FT_ABS( x );
s ^= y; y = FT_ABS( y );
ft_multo64( x, y, z );
if ( s < 0 )
{
z->lo = (FT_UInt32)-(FT_Int32)z->lo;
z->hi = ~z->hi + !( z->lo );
}
}
/* apparently, the second version of this code is not compiled correctly */
/* on Mac machines with the MPW C compiler.. tsk, tsk, tsk... */
#if 1
FT_EXPORT_DEF( FT_Int32 )
FT_Div64by32( FT_Int64* x,
FT_Int32 y )
{
FT_Int32 s;
FT_UInt32 q, r, i, lo;
s = x->hi;
if ( s < 0 )
{
x->lo = (FT_UInt32)-(FT_Int32)x->lo;
x->hi = ~x->hi + !x->lo;
}
s ^= y; y = FT_ABS( y );
/* Shortcut */
if ( x->hi == 0 )
{
if ( y > 0 )
q = x->lo / y;
else
q = 0x7FFFFFFFL;
return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
}
r = x->hi;
lo = x->lo;
if ( r >= (FT_UInt32)y ) /* we know y is to be treated as unsigned here */
return ( s < 0 ? 0x80000001UL : 0x7FFFFFFFUL );
/* Return Max/Min Int32 if division overflow. */
/* This includes division by zero! */
q = 0;
for ( i = 0; i < 32; i++ )
{
r <<= 1;
q <<= 1;
r |= lo >> 31;
if ( r >= (FT_UInt32)y )
{
r -= y;
q |= 1;
}
lo <<= 1;
}
return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
}
#else /* 0 */
FT_EXPORT_DEF( FT_Int32 )
FT_Div64by32( FT_Int64* x,
FT_Int32 y )
{
FT_Int32 s;
FT_UInt32 q;
s = x->hi;
if ( s < 0 )
{
x->lo = (FT_UInt32)-(FT_Int32)x->lo;
x->hi = ~x->hi + !x->lo;
}
s ^= y; y = FT_ABS( y );
/* Shortcut */
if ( x->hi == 0 )
{
if ( y > 0 )
q = ( x->lo + ( y >> 1 ) ) / y;
else
q = 0x7FFFFFFFL;
return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
}
q = ft_div64by32( x->hi, x->lo, y );
return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
}
#endif /* 0 */
#endif /* 0 */
#endif /* FT_LONG64 */
/* documentation is in ftglyph.h */
FT_EXPORT_DEF( void )
FT_Matrix_Multiply( const FT_Matrix* a,
FT_Matrix *b )
{
FT_Fixed xx, xy, yx, yy;
if ( !a || !b )
return;
xx = FT_MulFix( a->xx, b->xx ) + FT_MulFix( a->xy, b->yx );
xy = FT_MulFix( a->xx, b->xy ) + FT_MulFix( a->xy, b->yy );
yx = FT_MulFix( a->yx, b->xx ) + FT_MulFix( a->yy, b->yx );
yy = FT_MulFix( a->yx, b->xy ) + FT_MulFix( a->yy, b->yy );
b->xx = xx; b->xy = xy;
b->yx = yx; b->yy = yy;
}
/* documentation is in ftglyph.h */
FT_EXPORT_DEF( FT_Error )
FT_Matrix_Invert( FT_Matrix* matrix )
{
FT_Pos delta, xx, yy;
if ( !matrix )
return FT_Err_Invalid_Argument;
/* compute discriminant */
delta = FT_MulFix( matrix->xx, matrix->yy ) -
FT_MulFix( matrix->xy, matrix->yx );
if ( !delta )
return FT_Err_Invalid_Argument; /* matrix can't be inverted */
matrix->xy = - FT_DivFix( matrix->xy, delta );
matrix->yx = - FT_DivFix( matrix->yx, delta );
xx = matrix->xx;
yy = matrix->yy;
matrix->xx = FT_DivFix( yy, delta );
matrix->yy = FT_DivFix( xx, delta );
return FT_Err_Ok;
}
/* documentation is in ftcalc.h */
FT_BASE_DEF( void )
FT_Matrix_Multiply_Scaled( const FT_Matrix* a,
FT_Matrix *b,
FT_Long scaling )
{
FT_Fixed xx, xy, yx, yy;
FT_Long val = 0x10000L * scaling;
if ( !a || !b )
return;
xx = FT_MulDiv( a->xx, b->xx, val ) + FT_MulDiv( a->xy, b->yx, val );
xy = FT_MulDiv( a->xx, b->xy, val ) + FT_MulDiv( a->xy, b->yy, val );
yx = FT_MulDiv( a->yx, b->xx, val ) + FT_MulDiv( a->yy, b->yx, val );
yy = FT_MulDiv( a->yx, b->xy, val ) + FT_MulDiv( a->yy, b->yy, val );
b->xx = xx; b->xy = xy;
b->yx = yx; b->yy = yy;
}
/* documentation is in ftcalc.h */
FT_BASE_DEF( void )
FT_Vector_Transform_Scaled( FT_Vector* vector,
const FT_Matrix* matrix,
FT_Long scaling )
{
FT_Pos xz, yz;
FT_Long val = 0x10000L * scaling;
if ( !vector || !matrix )
return;
xz = FT_MulDiv( vector->x, matrix->xx, val ) +
FT_MulDiv( vector->y, matrix->xy, val );
yz = FT_MulDiv( vector->x, matrix->yx, val ) +
FT_MulDiv( vector->y, matrix->yy, val );
vector->x = xz;
vector->y = yz;
}
/* documentation is in ftcalc.h */
FT_BASE_DEF( FT_Int32 )
FT_SqrtFixed( FT_Int32 x )
{
FT_UInt32 root, rem_hi, rem_lo, test_div;
FT_Int count;
root = 0;
if ( x > 0 )
{
rem_hi = 0;
rem_lo = x;
count = 24;
do
{
rem_hi = ( rem_hi << 2 ) | ( rem_lo >> 30 );
rem_lo <<= 2;
root <<= 1;
test_div = ( root << 1 ) + 1;
if ( rem_hi >= test_div )
{
rem_hi -= test_div;
root += 1;
}
} while ( --count );
}
return (FT_Int32)root;
}
/* documentation is in ftcalc.h */
FT_BASE_DEF( FT_Int )
ft_corner_orientation( FT_Pos in_x,
FT_Pos in_y,
FT_Pos out_x,
FT_Pos out_y )
{
FT_Long result; /* avoid overflow on 16-bit system */
/* deal with the trivial cases quickly */
if ( in_y == 0 )
{
if ( in_x >= 0 )
result = out_y;
else
result = -out_y;
}
else if ( in_x == 0 )
{
if ( in_y >= 0 )
result = -out_x;
else
result = out_x;
}
else if ( out_y == 0 )
{
if ( out_x >= 0 )
result = in_y;
else
result = -in_y;
}
else if ( out_x == 0 )
{
if ( out_y >= 0 )
result = -in_x;
else
result = in_x;
}
else /* general case */
{
#ifdef FT_LONG64
FT_Int64 delta = (FT_Int64)in_x * out_y - (FT_Int64)in_y * out_x;
if ( delta == 0 )
result = 0;
else
result = 1 - 2 * ( delta < 0 );
#else
FT_Int64 z1, z2;
/* XXX: this function does not allow 64-bit arguments */
ft_multo64( (FT_Int32)in_x, (FT_Int32)out_y, &z1 );
ft_multo64( (FT_Int32)in_y, (FT_Int32)out_x, &z2 );
if ( z1.hi > z2.hi )
result = +1;
else if ( z1.hi < z2.hi )
result = -1;
else if ( z1.lo > z2.lo )
result = +1;
else if ( z1.lo < z2.lo )
result = -1;
else
result = 0;
#endif
}
/* XXX: only the sign of return value, +1/0/-1 must be used */
return (FT_Int)result;
}
/* documentation is in ftcalc.h */
FT_BASE_DEF( FT_Int )
ft_corner_is_flat( FT_Pos in_x,
FT_Pos in_y,
FT_Pos out_x,
FT_Pos out_y )
{
FT_Pos ax = in_x;
FT_Pos ay = in_y;
FT_Pos d_in, d_out, d_corner;
if ( ax < 0 )
ax = -ax;
if ( ay < 0 )
ay = -ay;
d_in = ax + ay;
ax = out_x;
if ( ax < 0 )
ax = -ax;
ay = out_y;
if ( ay < 0 )
ay = -ay;
d_out = ax + ay;
ax = out_x + in_x;
if ( ax < 0 )
ax = -ax;
ay = out_y + in_y;
if ( ay < 0 )
ay = -ay;
d_corner = ax + ay;
return ( d_in + d_out - d_corner ) < ( d_corner >> 4 );
}
/* END */
+997
View File
@@ -0,0 +1,997 @@
/***************************************************************************/
/* */
/* ftdbgmem.c */
/* */
/* Memory debugger (body). */
/* */
/* Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2009 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 = 0;
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 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_ULong size;
FT_ULong nodes;
FT_MemNode* buckets;
FT_ULong alloc_total;
FT_ULong alloc_current;
FT_ULong alloc_max;
FT_ULong alloc_count;
FT_Bool bound_total;
FT_ULong alloc_total_max;
FT_Bool bound_count;
FT_ULong 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_UInt 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_ULong
ft_mem_closest_prime( FT_ULong num )
{
FT_UInt 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;
}
extern 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_ULong new_size;
new_size = ft_mem_closest_prime( table->nodes );
if ( new_size != table->size )
{
FT_MemNode* new_buckets;
FT_ULong i;
new_buckets = (FT_MemNode *)
ft_mem_table_alloc( table,
new_size * sizeof ( FT_MemNode ) );
if ( new_buckets == NULL )
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 ) % 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 == NULL )
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 * 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_ULong i;
FT_DumpMemory( table->memory );
if ( table )
{
FT_Long leak_count = 0;
FT_ULong leaks = 0;
/* 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 = 0;
if ( node->size > 0 )
{
printf(
"leaked memory block at address %p, size %8ld in (%s:%ld)\n",
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] = 0;
}
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 % 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 == NULL )
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 == NULL )
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_ULong 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 == NULL )
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 > (FT_ULong)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 );
}
}
extern 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 > (FT_ULong)size )
return NULL;
block = (FT_Byte *)ft_mem_table_alloc( table, size );
if ( block )
{
ft_mem_table_set( table, block, (FT_ULong)size, 0 );
table->alloc_count++;
}
_ft_debug_file = "<unknown>";
_ft_debug_lineno = 0;
return (FT_Pointer)block;
}
extern void
ft_mem_debug_free( FT_Memory memory,
FT_Pointer block )
{
FT_MemTable table = (FT_MemTable)memory->user;
if ( block == NULL )
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;
}
extern 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 == NULL || cur_size == 0 )
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 = (FT_Long)( new_size - cur_size );
/* return NULL if this allocation would overflow the maximum heap size */
if ( delta > 0 &&
table->bound_total &&
table->alloc_current + (FT_ULong)delta > table->alloc_total_max )
return NULL;
new_block = (FT_Byte *)ft_mem_table_alloc( table, new_size );
if ( new_block == NULL )
return NULL;
ft_mem_table_set( table, (FT_Byte*)new_block, new_size, delta );
ft_memcpy( new_block, block, cur_size < new_size ? cur_size : 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 ( 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 = getenv( "FT2_ALLOC_TOTAL_MAX" );
if ( p != NULL )
{
FT_Long total_max = ft_atol( p );
if ( total_max > 0 )
{
table->bound_total = 1;
table->alloc_total_max = (FT_ULong)total_max;
}
}
p = getenv( "FT2_ALLOC_COUNT_MAX" );
if ( p != NULL )
{
FT_Long total_count = ft_atol( p );
if ( total_count > 0 )
{
table->bound_count = 1;
table->alloc_count_max = (FT_ULong)total_count;
}
}
p = getenv( "FT2_KEEP_ALIVE" );
if ( p != NULL )
{
FT_Long keep_alive = ft_atol( p );
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_UInt 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, sizeof ( *sources ) * count );
count = 0;
for ( bucket = table->sources; bucket < limit; bucket++ )
{
FT_MemSource source = *bucket;
for ( ; source; source = source->link )
sources[count++] = source;
}
ft_qsort( sources, 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 */
+246
View File
@@ -0,0 +1,246 @@
/***************************************************************************/
/* */
/* ftdebug.c */
/* */
/* Debugging and logging component (body). */
/* */
/* Copyright 1996-2001, 2002, 2004, 2008 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. */
/* */
/***************************************************************************/
/*************************************************************************/
/* */
/* This component contains various macros and functions used to ease the */
/* debugging of the FreeType engine. Its main purpose is in assertion */
/* checking, tracing, and error detection. */
/* */
/* There are now three debugging modes: */
/* */
/* - trace mode */
/* */
/* Error and trace messages are sent to the log file (which can be the */
/* standard error output). */
/* */
/* - error mode */
/* */
/* Only error messages are generated. */
/* */
/* - release mode: */
/* */
/* No error message is sent or generated. The code is free from any */
/* debugging parts. */
/* */
/*************************************************************************/
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_INTERNAL_DEBUG_H
#ifdef FT_DEBUG_LEVEL_ERROR
/* documentation is in ftdebug.h */
FT_BASE_DEF( void )
FT_Message( const char* fmt, ... )
{
va_list ap;
va_start( ap, fmt );
vfprintf( stderr, fmt, ap );
va_end( ap );
}
/* documentation is in ftdebug.h */
FT_BASE_DEF( void )
FT_Panic( const char* fmt, ... )
{
va_list ap;
va_start( ap, fmt );
vfprintf( stderr, fmt, ap );
va_end( ap );
exit( EXIT_FAILURE );
}
#endif /* FT_DEBUG_LEVEL_ERROR */
#ifdef FT_DEBUG_LEVEL_TRACE
/* array of trace levels, initialized to 0 */
int ft_trace_levels[trace_count];
/* define array of trace toggle names */
#define FT_TRACE_DEF( x ) #x ,
static const char* ft_trace_toggles[trace_count + 1] =
{
#include FT_INTERNAL_TRACE_H
NULL
};
#undef FT_TRACE_DEF
/* documentation is in ftdebug.h */
FT_BASE_DEF( FT_Int )
FT_Trace_Get_Count( void )
{
return trace_count;
}
/* documentation is in ftdebug.h */
FT_BASE_DEF( const char * )
FT_Trace_Get_Name( FT_Int idx )
{
int max = FT_Trace_Get_Count();
if ( idx < max )
return ft_trace_toggles[idx];
else
return NULL;
}
/*************************************************************************/
/* */
/* Initialize the tracing sub-system. This is done by retrieving the */
/* value of the `FT2_DEBUG' environment variable. It must be a list of */
/* toggles, separated by spaces, `;', or `,'. Example: */
/* */
/* export FT2_DEBUG="any:3 memory:7 stream:5" */
/* */
/* This requests that all levels be set to 3, except the trace level for */
/* the memory and stream components which are set to 7 and 5, */
/* respectively. */
/* */
/* See the file <include/freetype/internal/fttrace.h> for details of the */
/* available toggle names. */
/* */
/* The level must be between 0 and 7; 0 means quiet (except for serious */
/* runtime errors), and 7 means _very_ verbose. */
/* */
FT_BASE_DEF( void )
ft_debug_init( void )
{
const char* ft2_debug = getenv( "FT2_DEBUG" );
if ( ft2_debug )
{
const char* p = ft2_debug;
const char* q;
for ( ; *p; p++ )
{
/* skip leading whitespace and separators */
if ( *p == ' ' || *p == '\t' || *p == ',' || *p == ';' || *p == '=' )
continue;
/* read toggle name, followed by ':' */
q = p;
while ( *p && *p != ':' )
p++;
if ( *p == ':' && p > q )
{
FT_Int n, i, len = (FT_Int)( p - q );
FT_Int level = -1, found = -1;
for ( n = 0; n < trace_count; n++ )
{
const char* toggle = ft_trace_toggles[n];
for ( i = 0; i < len; i++ )
{
if ( toggle[i] != q[i] )
break;
}
if ( i == len && toggle[i] == 0 )
{
found = n;
break;
}
}
/* read level */
p++;
if ( *p )
{
level = *p++ - '0';
if ( level < 0 || level > 7 )
level = -1;
}
if ( found >= 0 && level >= 0 )
{
if ( found == trace_any )
{
/* special case for `any' */
for ( n = 0; n < trace_count; n++ )
ft_trace_levels[n] = level;
}
else
ft_trace_levels[found] = level;
}
}
}
}
}
#else /* !FT_DEBUG_LEVEL_TRACE */
FT_BASE_DEF( void )
ft_debug_init( void )
{
/* nothing */
}
FT_BASE_DEF( FT_Int )
FT_Trace_Get_Count( void )
{
return 0;
}
FT_BASE_DEF( const char * )
FT_Trace_Get_Name( FT_Int idx )
{
FT_UNUSED( idx );
return NULL;
}
#endif /* !FT_DEBUG_LEVEL_TRACE */
/* END */
+401
View File
@@ -0,0 +1,401 @@
/***************************************************************************/
/* */
/* ftgloadr.c */
/* */
/* The FreeType glyph loader (body). */
/* */
/* Copyright 2002, 2003, 2004, 2005, 2006, 2010 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_GLYPH_LOADER_H
#include FT_INTERNAL_MEMORY_H
#include FT_INTERNAL_OBJECTS_H
#undef FT_COMPONENT
#define FT_COMPONENT trace_gloader
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** *****/
/***** G L Y P H L O A D E R *****/
/***** *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/* */
/* The glyph loader is a simple object which is used to load a set of */
/* glyphs easily. It is critical for the correct loading of composites. */
/* */
/* Ideally, one can see it as a stack of abstract `glyph' objects. */
/* */
/* loader.base Is really the bottom of the stack. It describes a */
/* single glyph image made of the juxtaposition of */
/* several glyphs (those `in the stack'). */
/* */
/* loader.current Describes the top of the stack, on which a new */
/* glyph can be loaded. */
/* */
/* Rewind Clears the stack. */
/* Prepare Set up `loader.current' for addition of a new glyph */
/* image. */
/* Add Add the `current' glyph image to the `base' one, */
/* and prepare for another one. */
/* */
/* The glyph loader is now a base object. Each driver used to */
/* re-implement it in one way or the other, which wasted code and */
/* energy. */
/* */
/*************************************************************************/
/* create a new glyph loader */
FT_BASE_DEF( FT_Error )
FT_GlyphLoader_New( FT_Memory memory,
FT_GlyphLoader *aloader )
{
FT_GlyphLoader loader = NULL;
FT_Error error;
if ( !FT_NEW( loader ) )
{
loader->memory = memory;
*aloader = loader;
}
return error;
}
/* rewind the glyph loader - reset counters to 0 */
FT_BASE_DEF( void )
FT_GlyphLoader_Rewind( FT_GlyphLoader loader )
{
FT_GlyphLoad base = &loader->base;
FT_GlyphLoad current = &loader->current;
base->outline.n_points = 0;
base->outline.n_contours = 0;
base->num_subglyphs = 0;
*current = *base;
}
/* reset the glyph loader, frees all allocated tables */
/* and starts from zero */
FT_BASE_DEF( void )
FT_GlyphLoader_Reset( FT_GlyphLoader loader )
{
FT_Memory memory = loader->memory;
FT_FREE( loader->base.outline.points );
FT_FREE( loader->base.outline.tags );
FT_FREE( loader->base.outline.contours );
FT_FREE( loader->base.extra_points );
FT_FREE( loader->base.subglyphs );
loader->base.extra_points2 = NULL;
loader->max_points = 0;
loader->max_contours = 0;
loader->max_subglyphs = 0;
FT_GlyphLoader_Rewind( loader );
}
/* delete a glyph loader */
FT_BASE_DEF( void )
FT_GlyphLoader_Done( FT_GlyphLoader loader )
{
if ( loader )
{
FT_Memory memory = loader->memory;
FT_GlyphLoader_Reset( loader );
FT_FREE( loader );
}
}
/* re-adjust the `current' outline fields */
static void
FT_GlyphLoader_Adjust_Points( FT_GlyphLoader loader )
{
FT_Outline* base = &loader->base.outline;
FT_Outline* current = &loader->current.outline;
current->points = base->points + base->n_points;
current->tags = base->tags + base->n_points;
current->contours = base->contours + base->n_contours;
/* handle extra points table - if any */
if ( loader->use_extra )
{
loader->current.extra_points = loader->base.extra_points +
base->n_points;
loader->current.extra_points2 = loader->base.extra_points2 +
base->n_points;
}
}
FT_BASE_DEF( FT_Error )
FT_GlyphLoader_CreateExtra( FT_GlyphLoader loader )
{
FT_Error error;
FT_Memory memory = loader->memory;
if ( !FT_NEW_ARRAY( loader->base.extra_points, 2 * loader->max_points ) )
{
loader->use_extra = 1;
loader->base.extra_points2 = loader->base.extra_points +
loader->max_points;
FT_GlyphLoader_Adjust_Points( loader );
}
return error;
}
/* re-adjust the `current' subglyphs field */
static void
FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader loader )
{
FT_GlyphLoad base = &loader->base;
FT_GlyphLoad current = &loader->current;
current->subglyphs = base->subglyphs + base->num_subglyphs;
}
/* Ensure that we can add `n_points' and `n_contours' to our glyph. */
/* This function reallocates its outline tables if necessary. Note that */
/* it DOESN'T change the number of points within the loader! */
/* */
FT_BASE_DEF( FT_Error )
FT_GlyphLoader_CheckPoints( FT_GlyphLoader loader,
FT_UInt n_points,
FT_UInt n_contours )
{
FT_Memory memory = loader->memory;
FT_Error error = FT_Err_Ok;
FT_Outline* base = &loader->base.outline;
FT_Outline* current = &loader->current.outline;
FT_Bool adjust = 0;
FT_UInt new_max, old_max;
/* check points & tags */
new_max = base->n_points + current->n_points + n_points;
old_max = loader->max_points;
if ( new_max > old_max )
{
new_max = FT_PAD_CEIL( new_max, 8 );
if ( new_max > FT_OUTLINE_POINTS_MAX )
return FT_Err_Array_Too_Large;
if ( FT_RENEW_ARRAY( base->points, old_max, new_max ) ||
FT_RENEW_ARRAY( base->tags, old_max, new_max ) )
goto Exit;
if ( loader->use_extra )
{
if ( FT_RENEW_ARRAY( loader->base.extra_points,
old_max * 2, new_max * 2 ) )
goto Exit;
FT_ARRAY_MOVE( loader->base.extra_points + new_max,
loader->base.extra_points + old_max,
old_max );
loader->base.extra_points2 = loader->base.extra_points + new_max;
}
adjust = 1;
loader->max_points = new_max;
}
/* check contours */
old_max = loader->max_contours;
new_max = base->n_contours + current->n_contours +
n_contours;
if ( new_max > old_max )
{
new_max = FT_PAD_CEIL( new_max, 4 );
if ( new_max > FT_OUTLINE_CONTOURS_MAX )
return FT_Err_Array_Too_Large;
if ( FT_RENEW_ARRAY( base->contours, old_max, new_max ) )
goto Exit;
adjust = 1;
loader->max_contours = new_max;
}
if ( adjust )
FT_GlyphLoader_Adjust_Points( loader );
Exit:
return error;
}
/* Ensure that we can add `n_subglyphs' to our glyph. this function */
/* reallocates its subglyphs table if necessary. Note that it DOES */
/* NOT change the number of subglyphs within the loader! */
/* */
FT_BASE_DEF( FT_Error )
FT_GlyphLoader_CheckSubGlyphs( FT_GlyphLoader loader,
FT_UInt n_subs )
{
FT_Memory memory = loader->memory;
FT_Error error = FT_Err_Ok;
FT_UInt new_max, old_max;
FT_GlyphLoad base = &loader->base;
FT_GlyphLoad current = &loader->current;
new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
old_max = loader->max_subglyphs;
if ( new_max > old_max )
{
new_max = FT_PAD_CEIL( new_max, 2 );
if ( FT_RENEW_ARRAY( base->subglyphs, old_max, new_max ) )
goto Exit;
loader->max_subglyphs = new_max;
FT_GlyphLoader_Adjust_Subglyphs( loader );
}
Exit:
return error;
}
/* prepare loader for the addition of a new glyph on top of the base one */
FT_BASE_DEF( void )
FT_GlyphLoader_Prepare( FT_GlyphLoader loader )
{
FT_GlyphLoad current = &loader->current;
current->outline.n_points = 0;
current->outline.n_contours = 0;
current->num_subglyphs = 0;
FT_GlyphLoader_Adjust_Points ( loader );
FT_GlyphLoader_Adjust_Subglyphs( loader );
}
/* add current glyph to the base image - and prepare for another */
FT_BASE_DEF( void )
FT_GlyphLoader_Add( FT_GlyphLoader loader )
{
FT_GlyphLoad base;
FT_GlyphLoad current;
FT_UInt n_curr_contours;
FT_UInt n_base_points;
FT_UInt n;
if ( !loader )
return;
base = &loader->base;
current = &loader->current;
n_curr_contours = current->outline.n_contours;
n_base_points = base->outline.n_points;
base->outline.n_points =
(short)( base->outline.n_points + current->outline.n_points );
base->outline.n_contours =
(short)( base->outline.n_contours + current->outline.n_contours );
base->num_subglyphs += current->num_subglyphs;
/* adjust contours count in newest outline */
for ( n = 0; n < n_curr_contours; n++ )
current->outline.contours[n] =
(short)( current->outline.contours[n] + n_base_points );
/* prepare for another new glyph image */
FT_GlyphLoader_Prepare( loader );
}
FT_BASE_DEF( FT_Error )
FT_GlyphLoader_CopyPoints( FT_GlyphLoader target,
FT_GlyphLoader source )
{
FT_Error error;
FT_UInt num_points = source->base.outline.n_points;
FT_UInt num_contours = source->base.outline.n_contours;
error = FT_GlyphLoader_CheckPoints( target, num_points, num_contours );
if ( !error )
{
FT_Outline* out = &target->base.outline;
FT_Outline* in = &source->base.outline;
FT_ARRAY_COPY( out->points, in->points,
num_points );
FT_ARRAY_COPY( out->tags, in->tags,
num_points );
FT_ARRAY_COPY( out->contours, in->contours,
num_contours );
/* do we need to copy the extra points? */
if ( target->use_extra && source->use_extra )
{
FT_ARRAY_COPY( target->base.extra_points, source->base.extra_points,
num_points );
FT_ARRAY_COPY( target->base.extra_points2, source->base.extra_points2,
num_points );
}
out->n_points = (short)num_points;
out->n_contours = (short)num_contours;
FT_GlyphLoader_Adjust_Points( target );
}
return error;
}
/* END */
+627
View File
@@ -0,0 +1,627 @@
/***************************************************************************/
/* */
/* ftglyph.c */
/* */
/* FreeType convenience functions to handle glyphs (body). */
/* */
/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2007, 2008, 2010 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. */
/* */
/***************************************************************************/
/*************************************************************************/
/* */
/* This file contains the definition of several convenience functions */
/* that can be used by client applications to easily retrieve glyph */
/* bitmaps and outlines from a given face. */
/* */
/* These functions should be optional if you are writing a font server */
/* or text layout engine on top of FreeType. However, they are pretty */
/* handy for many other simple uses of the library. */
/* */
/*************************************************************************/
#include <ft2build.h>
#include FT_GLYPH_H
#include FT_OUTLINE_H
#include FT_BITMAP_H
#include FT_INTERNAL_OBJECTS_H
#include "basepic.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_glyph
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** FT_BitmapGlyph support ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
FT_CALLBACK_DEF( FT_Error )
ft_bitmap_glyph_init( FT_Glyph bitmap_glyph,
FT_GlyphSlot slot )
{
FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph;
FT_Error error = FT_Err_Ok;
FT_Library library = FT_GLYPH( glyph )->library;
if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
{
error = FT_Err_Invalid_Glyph_Format;
goto Exit;
}
glyph->left = slot->bitmap_left;
glyph->top = slot->bitmap_top;
/* do lazy copying whenever possible */
if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
{
glyph->bitmap = slot->bitmap;
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
}
else
{
FT_Bitmap_New( &glyph->bitmap );
error = FT_Bitmap_Copy( library, &slot->bitmap, &glyph->bitmap );
}
Exit:
return error;
}
FT_CALLBACK_DEF( FT_Error )
ft_bitmap_glyph_copy( FT_Glyph bitmap_source,
FT_Glyph bitmap_target )
{
FT_Library library = bitmap_source->library;
FT_BitmapGlyph source = (FT_BitmapGlyph)bitmap_source;
FT_BitmapGlyph target = (FT_BitmapGlyph)bitmap_target;
target->left = source->left;
target->top = source->top;
return FT_Bitmap_Copy( library, &source->bitmap, &target->bitmap );
}
FT_CALLBACK_DEF( void )
ft_bitmap_glyph_done( FT_Glyph bitmap_glyph )
{
FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph;
FT_Library library = FT_GLYPH( glyph )->library;
FT_Bitmap_Done( library, &glyph->bitmap );
}
FT_CALLBACK_DEF( void )
ft_bitmap_glyph_bbox( FT_Glyph bitmap_glyph,
FT_BBox* cbox )
{
FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph;
cbox->xMin = glyph->left << 6;
cbox->xMax = cbox->xMin + ( glyph->bitmap.width << 6 );
cbox->yMax = glyph->top << 6;
cbox->yMin = cbox->yMax - ( glyph->bitmap.rows << 6 );
}
FT_DEFINE_GLYPH(ft_bitmap_glyph_class,
sizeof ( FT_BitmapGlyphRec ),
FT_GLYPH_FORMAT_BITMAP,
ft_bitmap_glyph_init,
ft_bitmap_glyph_done,
ft_bitmap_glyph_copy,
0, /* FT_Glyph_TransformFunc */
ft_bitmap_glyph_bbox,
0 /* FT_Glyph_PrepareFunc */
)
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** FT_OutlineGlyph support ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
FT_CALLBACK_DEF( FT_Error )
ft_outline_glyph_init( FT_Glyph outline_glyph,
FT_GlyphSlot slot )
{
FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
FT_Error error = FT_Err_Ok;
FT_Library library = FT_GLYPH( glyph )->library;
FT_Outline* source = &slot->outline;
FT_Outline* target = &glyph->outline;
/* check format in glyph slot */
if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )
{
error = FT_Err_Invalid_Glyph_Format;
goto Exit;
}
/* allocate new outline */
error = FT_Outline_New( library, source->n_points, source->n_contours,
&glyph->outline );
if ( error )
goto Exit;
FT_Outline_Copy( source, target );
Exit:
return error;
}
FT_CALLBACK_DEF( void )
ft_outline_glyph_done( FT_Glyph outline_glyph )
{
FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline );
}
FT_CALLBACK_DEF( FT_Error )
ft_outline_glyph_copy( FT_Glyph outline_source,
FT_Glyph outline_target )
{
FT_OutlineGlyph source = (FT_OutlineGlyph)outline_source;
FT_OutlineGlyph target = (FT_OutlineGlyph)outline_target;
FT_Error error;
FT_Library library = FT_GLYPH( source )->library;
error = FT_Outline_New( library, source->outline.n_points,
source->outline.n_contours, &target->outline );
if ( !error )
FT_Outline_Copy( &source->outline, &target->outline );
return error;
}
FT_CALLBACK_DEF( void )
ft_outline_glyph_transform( FT_Glyph outline_glyph,
const FT_Matrix* matrix,
const FT_Vector* delta )
{
FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
if ( matrix )
FT_Outline_Transform( &glyph->outline, matrix );
if ( delta )
FT_Outline_Translate( &glyph->outline, delta->x, delta->y );
}
FT_CALLBACK_DEF( void )
ft_outline_glyph_bbox( FT_Glyph outline_glyph,
FT_BBox* bbox )
{
FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
FT_Outline_Get_CBox( &glyph->outline, bbox );
}
FT_CALLBACK_DEF( FT_Error )
ft_outline_glyph_prepare( FT_Glyph outline_glyph,
FT_GlyphSlot slot )
{
FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
slot->format = FT_GLYPH_FORMAT_OUTLINE;
slot->outline = glyph->outline;
slot->outline.flags &= ~FT_OUTLINE_OWNER;
return FT_Err_Ok;
}
FT_DEFINE_GLYPH( ft_outline_glyph_class,
sizeof ( FT_OutlineGlyphRec ),
FT_GLYPH_FORMAT_OUTLINE,
ft_outline_glyph_init,
ft_outline_glyph_done,
ft_outline_glyph_copy,
ft_outline_glyph_transform,
ft_outline_glyph_bbox,
ft_outline_glyph_prepare
)
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** FT_Glyph class and API ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
static FT_Error
ft_new_glyph( FT_Library library,
const FT_Glyph_Class* clazz,
FT_Glyph* aglyph )
{
FT_Memory memory = library->memory;
FT_Error error;
FT_Glyph glyph = NULL;
*aglyph = 0;
if ( !FT_ALLOC( glyph, clazz->glyph_size ) )
{
glyph->library = library;
glyph->clazz = clazz;
glyph->format = clazz->glyph_format;
*aglyph = glyph;
}
return error;
}
/* documentation is in ftglyph.h */
FT_EXPORT_DEF( FT_Error )
FT_Glyph_Copy( FT_Glyph source,
FT_Glyph *target )
{
FT_Glyph copy;
FT_Error error;
const FT_Glyph_Class* clazz;
/* check arguments */
if ( !target )
{
error = FT_Err_Invalid_Argument;
goto Exit;
}
*target = 0;
if ( !source || !source->clazz )
{
error = FT_Err_Invalid_Argument;
goto Exit;
}
clazz = source->clazz;
error = ft_new_glyph( source->library, clazz, &copy );
if ( error )
goto Exit;
copy->advance = source->advance;
copy->format = source->format;
if ( clazz->glyph_copy )
error = clazz->glyph_copy( source, copy );
if ( error )
FT_Done_Glyph( copy );
else
*target = copy;
Exit:
return error;
}
/* documentation is in ftglyph.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_Glyph( FT_GlyphSlot slot,
FT_Glyph *aglyph )
{
FT_Library library;
FT_Error error;
FT_Glyph glyph;
const FT_Glyph_Class* clazz = 0;
if ( !slot )
return FT_Err_Invalid_Slot_Handle;
library = slot->library;
if ( !aglyph )
return FT_Err_Invalid_Argument;
/* if it is a bitmap, that's easy :-) */
if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
clazz = FT_BITMAP_GLYPH_CLASS_GET;
/* if it is an outline */
else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
clazz = FT_OUTLINE_GLYPH_CLASS_GET;
else
{
/* try to find a renderer that supports the glyph image format */
FT_Renderer render = FT_Lookup_Renderer( library, slot->format, 0 );
if ( render )
clazz = &render->glyph_class;
}
if ( !clazz )
{
error = FT_Err_Invalid_Glyph_Format;
goto Exit;
}
/* create FT_Glyph object */
error = ft_new_glyph( library, clazz, &glyph );
if ( error )
goto Exit;
/* copy advance while converting it to 16.16 format */
glyph->advance.x = slot->advance.x << 10;
glyph->advance.y = slot->advance.y << 10;
/* now import the image from the glyph slot */
error = clazz->glyph_init( glyph, slot );
/* if an error occurred, destroy the glyph */
if ( error )
FT_Done_Glyph( glyph );
else
*aglyph = glyph;
Exit:
return error;
}
/* documentation is in ftglyph.h */
FT_EXPORT_DEF( FT_Error )
FT_Glyph_Transform( FT_Glyph glyph,
FT_Matrix* matrix,
FT_Vector* delta )
{
const FT_Glyph_Class* clazz;
FT_Error error = FT_Err_Ok;
if ( !glyph || !glyph->clazz )
error = FT_Err_Invalid_Argument;
else
{
clazz = glyph->clazz;
if ( clazz->glyph_transform )
{
/* transform glyph image */
clazz->glyph_transform( glyph, matrix, delta );
/* transform advance vector */
if ( matrix )
FT_Vector_Transform( &glyph->advance, matrix );
}
else
error = FT_Err_Invalid_Glyph_Format;
}
return error;
}
/* documentation is in ftglyph.h */
FT_EXPORT_DEF( void )
FT_Glyph_Get_CBox( FT_Glyph glyph,
FT_UInt bbox_mode,
FT_BBox *acbox )
{
const FT_Glyph_Class* clazz;
if ( !acbox )
return;
acbox->xMin = acbox->yMin = acbox->xMax = acbox->yMax = 0;
if ( !glyph || !glyph->clazz )
return;
else
{
clazz = glyph->clazz;
if ( !clazz->glyph_bbox )
return;
else
{
/* retrieve bbox in 26.6 coordinates */
clazz->glyph_bbox( glyph, acbox );
/* perform grid fitting if needed */
if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT ||
bbox_mode == FT_GLYPH_BBOX_PIXELS )
{
acbox->xMin = FT_PIX_FLOOR( acbox->xMin );
acbox->yMin = FT_PIX_FLOOR( acbox->yMin );
acbox->xMax = FT_PIX_CEIL( acbox->xMax );
acbox->yMax = FT_PIX_CEIL( acbox->yMax );
}
/* convert to integer pixels if needed */
if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE ||
bbox_mode == FT_GLYPH_BBOX_PIXELS )
{
acbox->xMin >>= 6;
acbox->yMin >>= 6;
acbox->xMax >>= 6;
acbox->yMax >>= 6;
}
}
}
return;
}
/* documentation is in ftglyph.h */
FT_EXPORT_DEF( FT_Error )
FT_Glyph_To_Bitmap( FT_Glyph* the_glyph,
FT_Render_Mode render_mode,
FT_Vector* origin,
FT_Bool destroy )
{
FT_GlyphSlotRec dummy;
FT_GlyphSlot_InternalRec dummy_internal;
FT_Error error = FT_Err_Ok;
FT_Glyph glyph;
FT_BitmapGlyph bitmap = NULL;
const FT_Glyph_Class* clazz;
#ifdef FT_CONFIG_OPTION_PIC
FT_Library library = FT_GLYPH( glyph )->library;
#endif
/* check argument */
if ( !the_glyph )
goto Bad;
/* we render the glyph into a glyph bitmap using a `dummy' glyph slot */
/* then calling FT_Render_Glyph_Internal() */
glyph = *the_glyph;
if ( !glyph )
goto Bad;
clazz = glyph->clazz;
/* when called with a bitmap glyph, do nothing and return successfully */
if ( clazz == FT_BITMAP_GLYPH_CLASS_GET )
goto Exit;
if ( !clazz || !clazz->glyph_prepare )
goto Bad;
FT_MEM_ZERO( &dummy, sizeof ( dummy ) );
FT_MEM_ZERO( &dummy_internal, sizeof ( dummy_internal ) );
dummy.internal = &dummy_internal;
dummy.library = glyph->library;
dummy.format = clazz->glyph_format;
/* create result bitmap glyph */
error = ft_new_glyph( glyph->library, FT_BITMAP_GLYPH_CLASS_GET,
(FT_Glyph*)(void*)&bitmap );
if ( error )
goto Exit;
#if 1
/* if `origin' is set, translate the glyph image */
if ( origin )
FT_Glyph_Transform( glyph, 0, origin );
#else
FT_UNUSED( origin );
#endif
/* prepare dummy slot for rendering */
error = clazz->glyph_prepare( glyph, &dummy );
if ( !error )
error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode );
#if 1
if ( !destroy && origin )
{
FT_Vector v;
v.x = -origin->x;
v.y = -origin->y;
FT_Glyph_Transform( glyph, 0, &v );
}
#endif
if ( error )
goto Exit;
/* in case of success, copy the bitmap to the glyph bitmap */
error = ft_bitmap_glyph_init( (FT_Glyph)bitmap, &dummy );
if ( error )
goto Exit;
/* copy advance */
bitmap->root.advance = glyph->advance;
if ( destroy )
FT_Done_Glyph( glyph );
*the_glyph = FT_GLYPH( bitmap );
Exit:
if ( error && bitmap )
FT_Done_Glyph( FT_GLYPH( bitmap ) );
return error;
Bad:
error = FT_Err_Invalid_Argument;
goto Exit;
}
/* documentation is in ftglyph.h */
FT_EXPORT_DEF( void )
FT_Done_Glyph( FT_Glyph glyph )
{
if ( glyph )
{
FT_Memory memory = glyph->library->memory;
const FT_Glyph_Class* clazz = glyph->clazz;
if ( clazz->glyph_done )
clazz->glyph_done( glyph );
FT_FREE( glyph );
}
}
/* END */
+253
View File
@@ -0,0 +1,253 @@
/***************************************************************************/
/* */
/* ftinit.c */
/* */
/* FreeType initialization layer (body). */
/* */
/* Copyright 1996-2001, 2002, 2005, 2007, 2009 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. */
/* */
/***************************************************************************/
/*************************************************************************/
/* */
/* The purpose of this file is to implement the following two */
/* functions: */
/* */
/* FT_Add_Default_Modules(): */
/* This function is used to add the set of default modules to a */
/* fresh new library object. The set is taken from the header file */
/* `freetype/config/ftmodule.h'. See the document `FreeType 2.0 */
/* Build System' for more information. */
/* */
/* FT_Init_FreeType(): */
/* This function creates a system object for the current platform, */
/* builds a library out of it, then calls FT_Default_Drivers(). */
/* */
/* Note that even if FT_Init_FreeType() uses the implementation of the */
/* system object defined at build time, client applications are still */
/* able to provide their own `ftsystem.c'. */
/* */
/*************************************************************************/
#include <ft2build.h>
#include FT_CONFIG_CONFIG_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
#include FT_MODULE_H
#include "basepic.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_init
#ifndef FT_CONFIG_OPTION_PIC
#undef FT_USE_MODULE
#ifdef __cplusplus
#define FT_USE_MODULE( type, x ) extern "C" const type x;
#else
#define FT_USE_MODULE( type, x ) extern const type x;
#endif
#include FT_CONFIG_MODULES_H
#undef FT_USE_MODULE
#define FT_USE_MODULE( type, x ) (const FT_Module_Class*)&(x),
static
const FT_Module_Class* const ft_default_modules[] =
{
#include FT_CONFIG_MODULES_H
0
};
#else /* FT_CONFIG_OPTION_PIC */
#ifdef __cplusplus
#define FT_EXTERNC extern "C"
#else
#define FT_EXTERNC extern
#endif
/* declare the module's class creation/destruction functions */
#undef FT_USE_MODULE
#define FT_USE_MODULE( type, x ) \
FT_EXTERNC FT_Error FT_Create_Class_##x( FT_Library library, FT_Module_Class** output_class ); \
FT_EXTERNC void FT_Destroy_Class_##x( FT_Library library, FT_Module_Class* clazz );
#include FT_CONFIG_MODULES_H
/* count all module classes */
#undef FT_USE_MODULE
#define FT_USE_MODULE( type, x ) MODULE_CLASS_##x,
enum
{
#include FT_CONFIG_MODULES_H
FT_NUM_MODULE_CLASSES
};
/* destroy all module classes */
#undef FT_USE_MODULE
#define FT_USE_MODULE( type, x ) \
if ( classes[i] ) { FT_Destroy_Class_##x(library, classes[i]); } \
i++; \
FT_BASE_DEF( void )
ft_destroy_default_module_classes( FT_Library library )
{
FT_Module_Class** classes;
FT_Memory memory;
FT_UInt i;
BasePIC* pic_container = (BasePIC*)library->pic_container.base;
if ( !pic_container->default_module_classes )
return;
memory = library->memory;
classes = pic_container->default_module_classes;
i = 0;
#include FT_CONFIG_MODULES_H
FT_FREE( classes );
pic_container->default_module_classes = 0;
}
/* initialize all module classes and the pointer table */
#undef FT_USE_MODULE
#define FT_USE_MODULE( type, x ) \
error = FT_Create_Class_##x(library, &clazz); \
if (error) goto Exit; \
classes[i++] = clazz;
FT_BASE_DEF( FT_Error )
ft_create_default_module_classes( FT_Library library )
{
FT_Error error;
FT_Memory memory;
FT_Module_Class** classes;
FT_Module_Class* clazz;
FT_UInt i;
BasePIC* pic_container = (BasePIC*)library->pic_container.base;
memory = library->memory;
pic_container->default_module_classes = 0;
if ( FT_ALLOC(classes, sizeof(FT_Module_Class*) * (FT_NUM_MODULE_CLASSES + 1) ) )
return error;
/* initialize all pointers to 0, especially the last one */
for (i = 0; i < FT_NUM_MODULE_CLASSES; i++)
classes[i] = 0;
classes[FT_NUM_MODULE_CLASSES] = 0;
i = 0;
#include FT_CONFIG_MODULES_H
Exit:
if (error) ft_destroy_default_module_classes( library );
else pic_container->default_module_classes = classes;
return error;
}
#endif /* FT_CONFIG_OPTION_PIC */
/* documentation is in ftmodapi.h */
FT_EXPORT_DEF( void )
FT_Add_Default_Modules( FT_Library library )
{
FT_Error error;
const FT_Module_Class* const* cur;
/* test for valid `library' delayed to FT_Add_Module() */
cur = FT_DEFAULT_MODULES_GET;
while ( *cur )
{
error = FT_Add_Module( library, *cur );
/* notify errors, but don't stop */
if ( error )
FT_TRACE0(( "FT_Add_Default_Module:"
" Cannot install `%s', error = 0x%x\n",
(*cur)->module_name, error ));
cur++;
}
}
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_Error )
FT_Init_FreeType( FT_Library *alibrary )
{
FT_Error error;
FT_Memory memory;
/* 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_Err_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 );
return error;
}
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_Error )
FT_Done_FreeType( FT_Library library )
{
if ( library )
{
FT_Memory memory = library->memory;
/* Discard the library object */
FT_Done_Library( library );
/* discard memory manager */
FT_Done_Memory( memory );
}
return FT_Err_Ok;
}
/* END */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+54
View File
@@ -0,0 +1,54 @@
/***************************************************************************/
/* */
/* ftpic.c */
/* */
/* The FreeType position independent code services (body). */
/* */
/* Copyright 2009 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* 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_FREETYPE_H
#include FT_INTERNAL_OBJECTS_H
#include "basepic.h"
#ifdef FT_CONFIG_OPTION_PIC
/* documentation is in ftpic.h */
FT_BASE_DEF( FT_Error )
ft_pic_container_init( FT_Library library )
{
FT_PIC_Container* pic_container = &library->pic_container;
FT_Error error = FT_Err_Ok;
FT_MEM_SET( pic_container, 0, sizeof(*pic_container) );
error = ft_base_pic_init( library );
if(error)
return error;
return FT_Err_Ok;
}
/* Destroy the contents of the container. */
FT_BASE_DEF( void )
ft_pic_container_destroy( FT_Library library )
{
ft_base_pic_free( library );
}
#endif /* FT_CONFIG_OPTION_PIC */
/* END */
+871
View File
@@ -0,0 +1,871 @@
/***************************************************************************/
/* */
/* ftrfork.c */
/* */
/* Embedded resource forks accessor (body). */
/* */
/* Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */
/* Masatake YAMATO and Redhat K.K. */
/* */
/* FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are */
/* derived from ftobjs.c. */
/* */
/* 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. */
/* */
/***************************************************************************/
/***************************************************************************/
/* Development of the code in this file is support of */
/* Information-technology Promotion Agency, Japan. */
/***************************************************************************/
#include <ft2build.h>
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_RFORK_H
#undef FT_COMPONENT
#define FT_COMPONENT trace_raccess
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** Resource fork directory access ****/
/**** ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
FT_BASE_DEF( FT_Error )
FT_Raccess_Get_HeaderInfo( FT_Library library,
FT_Stream stream,
FT_Long rfork_offset,
FT_Long *map_offset,
FT_Long *rdata_pos )
{
FT_Error error;
unsigned char head[16], head2[16];
FT_Long map_pos, rdata_len;
int allzeros, allmatch, i;
FT_Long type_list;
FT_UNUSED( library );
error = FT_Stream_Seek( stream, rfork_offset );
if ( error )
return error;
error = FT_Stream_Read( stream, (FT_Byte *)head, 16 );
if ( error )
return error;
*rdata_pos = rfork_offset + ( ( head[0] << 24 ) |
( head[1] << 16 ) |
( head[2] << 8 ) |
head[3] );
map_pos = rfork_offset + ( ( head[4] << 24 ) |
( head[5] << 16 ) |
( head[6] << 8 ) |
head[7] );
rdata_len = ( head[ 8] << 24 ) |
( head[ 9] << 16 ) |
( head[10] << 8 ) |
head[11];
/* map_len = head[12] .. head[15] */
if ( *rdata_pos + rdata_len != map_pos || map_pos == rfork_offset )
return FT_Err_Unknown_File_Format;
error = FT_Stream_Seek( stream, map_pos );
if ( error )
return error;
head2[15] = (FT_Byte)( head[15] + 1 ); /* make it be different */
error = FT_Stream_Read( stream, (FT_Byte*)head2, 16 );
if ( error )
return error;
allzeros = 1;
allmatch = 1;
for ( i = 0; i < 16; ++i )
{
if ( head2[i] != 0 )
allzeros = 0;
if ( head2[i] != head[i] )
allmatch = 0;
}
if ( !allzeros && !allmatch )
return FT_Err_Unknown_File_Format;
/* If we have reached this point then it is probably a mac resource */
/* file. Now, does it contain any interesting resources? */
/* Skip handle to next resource map, the file resource number, and */
/* attributes. */
(void)FT_STREAM_SKIP( 4 /* skip handle to next resource map */
+ 2 /* skip file resource number */
+ 2 ); /* skip attributes */
if ( FT_READ_USHORT( type_list ) )
return error;
if ( type_list == -1 )
return FT_Err_Unknown_File_Format;
error = FT_Stream_Seek( stream, map_pos + type_list );
if ( error )
return error;
*map_offset = map_pos + type_list;
return FT_Err_Ok;
}
static int
ft_raccess_sort_ref_by_id( FT_RFork_Ref* a,
FT_RFork_Ref* b )
{
if ( a->res_id < b->res_id )
return -1;
else if ( a->res_id > b->res_id )
return 1;
else
return 0;
}
FT_BASE_DEF( FT_Error )
FT_Raccess_Get_DataOffsets( FT_Library library,
FT_Stream stream,
FT_Long map_offset,
FT_Long rdata_pos,
FT_Long tag,
FT_Long **offsets,
FT_Long *count )
{
FT_Error error;
int i, j, cnt, subcnt;
FT_Long tag_internal, rpos;
FT_Memory memory = library->memory;
FT_Long temp;
FT_Long *offsets_internal;
FT_RFork_Ref *ref;
error = FT_Stream_Seek( stream, map_offset );
if ( error )
return error;
if ( FT_READ_USHORT( cnt ) )
return error;
cnt++;
for ( i = 0; i < cnt; ++i )
{
if ( FT_READ_LONG( tag_internal ) ||
FT_READ_USHORT( subcnt ) ||
FT_READ_USHORT( rpos ) )
return error;
FT_TRACE2(( "Resource tags: %c%c%c%c\n",
(char)( 0xff & ( tag_internal >> 24 ) ),
(char)( 0xff & ( tag_internal >> 16 ) ),
(char)( 0xff & ( tag_internal >> 8 ) ),
(char)( 0xff & ( tag_internal >> 0 ) ) ));
if ( tag_internal == tag )
{
*count = subcnt + 1;
rpos += map_offset;
error = FT_Stream_Seek( stream, rpos );
if ( error )
return error;
if ( FT_NEW_ARRAY( ref, *count ) )
return error;
for ( j = 0; j < *count; ++j )
{
if ( FT_READ_USHORT( ref[j].res_id ) )
goto Exit;
if ( FT_STREAM_SKIP( 2 ) ) /* resource name */
goto Exit;
if ( FT_READ_LONG( temp ) )
goto Exit;
if ( FT_STREAM_SKIP( 4 ) ) /* mbz */
goto Exit;
ref[j].offset = temp & 0xFFFFFFL;
}
ft_qsort( ref, *count, sizeof ( FT_RFork_Ref ),
( int(*)(const void*, const void*) )
ft_raccess_sort_ref_by_id );
if ( FT_NEW_ARRAY( offsets_internal, *count ) )
goto Exit;
/* XXX: duplicated reference ID,
* gap between reference IDs are acceptable?
* further investigation on Apple implementation is needed.
*/
for ( j = 0; j < *count; ++j )
offsets_internal[j] = rdata_pos + ref[j].offset;
*offsets = offsets_internal;
error = FT_Err_Ok;
Exit:
FT_FREE( ref );
return error;
}
}
return FT_Err_Cannot_Open_Resource;
}
#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** Guessing functions ****/
/**** ****/
/**** When you add a new guessing function, ****/
/**** update FT_RACCESS_N_RULES in ftrfork.h. ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
typedef FT_Error
(*raccess_guess_func)( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_apple_double( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_apple_single( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_darwin_ufs_export( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_darwin_newvfs( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_darwin_hfsplus( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_vfat( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_linux_cap( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_linux_double( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_linux_netatalk( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
/*************************************************************************/
/**** ****/
/**** Helper functions ****/
/**** ****/
/*************************************************************************/
static FT_Error
raccess_guess_apple_generic( FT_Library library,
FT_Stream stream,
char *base_file_name,
FT_Int32 magic,
FT_Long *result_offset );
static FT_Error
raccess_guess_linux_double_from_file_name( FT_Library library,
char * file_name,
FT_Long *result_offset );
static char *
raccess_make_file_name( FT_Memory memory,
const char *original_name,
const char *insertion );
typedef enum FT_RFork_Rule_ {
FT_RFork_Rule_invalid = -2,
FT_RFork_Rule_uknown, /* -1 */
FT_RFork_Rule_apple_double,
FT_RFork_Rule_apple_single,
FT_RFork_Rule_darwin_ufs_export,
FT_RFork_Rule_darwin_newvfs,
FT_RFork_Rule_darwin_hfsplus,
FT_RFork_Rule_vfat,
FT_RFork_Rule_linux_cap,
FT_RFork_Rule_linux_double,
FT_RFork_Rule_linux_netatalk
} FT_RFork_Rule;
/* For fast translation between rule index and rule type,
* the macros FT_RFORK_xxx should be kept consistent with
* the raccess_guess_funcs table
*/
typedef struct raccess_guess_rec_ {
raccess_guess_func func;
FT_RFork_Rule type;
} raccess_guess_rec;
static raccess_guess_rec raccess_guess_table[FT_RACCESS_N_RULES] =
{
{ raccess_guess_apple_double, FT_RFork_Rule_apple_double, },
{ raccess_guess_apple_single, FT_RFork_Rule_apple_single, },
{ raccess_guess_darwin_ufs_export, FT_RFork_Rule_darwin_ufs_export, },
{ raccess_guess_darwin_newvfs, FT_RFork_Rule_darwin_newvfs, },
{ raccess_guess_darwin_hfsplus, FT_RFork_Rule_darwin_hfsplus, },
{ raccess_guess_vfat, FT_RFork_Rule_vfat, },
{ raccess_guess_linux_cap, FT_RFork_Rule_linux_cap, },
{ raccess_guess_linux_double, FT_RFork_Rule_linux_double, },
{ raccess_guess_linux_netatalk, FT_RFork_Rule_linux_netatalk, },
};
FT_BASE_DEF( void )
FT_Raccess_Guess( FT_Library library,
FT_Stream stream,
char* base_name,
char **new_names,
FT_Long *offsets,
FT_Error *errors )
{
FT_Long i;
for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
{
new_names[i] = NULL;
if ( NULL != stream )
errors[i] = FT_Stream_Seek( stream, 0 );
else
errors[i] = FT_Err_Ok;
if ( errors[i] )
continue ;
errors[i] = (raccess_guess_table[i].func)( library,
stream, base_name,
&(new_names[i]),
&(offsets[i]) );
}
return;
}
static FT_RFork_Rule
raccess_get_rule_type_from_rule_index( FT_UInt rule_index )
{
if ( rule_index >= FT_RACCESS_N_RULES )
return FT_RFork_Rule_invalid;
return raccess_guess_table[rule_index].type;
}
FT_LOCAL_DEF( FT_Bool )
raccess_rule_by_darwin_vfs( FT_UInt rule_index )
{
switch( raccess_get_rule_type_from_rule_index( rule_index ) )
{
case FT_RFork_Rule_darwin_newvfs:
case FT_RFork_Rule_darwin_hfsplus:
return TRUE;
default:
return FALSE;
}
}
static FT_Error
raccess_guess_apple_double( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
FT_Int32 magic = ( 0x00 << 24 ) |
( 0x05 << 16 ) |
( 0x16 << 8 ) |
0x07;
*result_file_name = NULL;
if ( NULL == stream )
return FT_Err_Cannot_Open_Stream;
return raccess_guess_apple_generic( library, stream, base_file_name,
magic, result_offset );
}
static FT_Error
raccess_guess_apple_single( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
FT_Int32 magic = ( 0x00 << 24 ) |
( 0x05 << 16 ) |
( 0x16 << 8 ) |
0x00;
*result_file_name = NULL;
if ( NULL == stream )
return FT_Err_Cannot_Open_Stream;
return raccess_guess_apple_generic( library, stream, base_file_name,
magic, result_offset );
}
static FT_Error
raccess_guess_darwin_ufs_export( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
char* newpath;
FT_Error error;
FT_Memory memory;
FT_UNUSED( stream );
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name, "._" );
if ( !newpath )
return FT_Err_Out_Of_Memory;
error = raccess_guess_linux_double_from_file_name( library, newpath,
result_offset );
if ( !error )
*result_file_name = newpath;
else
FT_FREE( newpath );
return error;
}
static FT_Error
raccess_guess_darwin_hfsplus( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
/*
Only meaningful on systems with hfs+ drivers (or Macs).
*/
FT_Error error;
char* newpath;
FT_Memory memory;
FT_Long base_file_len = ft_strlen( base_file_name );
FT_UNUSED( stream );
memory = library->memory;
if ( base_file_len + 6 > FT_INT_MAX )
return FT_Err_Array_Too_Large;
if ( FT_ALLOC( newpath, base_file_len + 6 ) )
return error;
FT_MEM_COPY( newpath, base_file_name, base_file_len );
FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 );
*result_file_name = newpath;
*result_offset = 0;
return FT_Err_Ok;
}
static FT_Error
raccess_guess_darwin_newvfs( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
/*
Only meaningful on systems with Mac OS X (> 10.1).
*/
FT_Error error;
char* newpath;
FT_Memory memory;
FT_Long base_file_len = ft_strlen( base_file_name );
FT_UNUSED( stream );
memory = library->memory;
if ( base_file_len + 18 > FT_INT_MAX )
return FT_Err_Array_Too_Large;
if ( FT_ALLOC( newpath, base_file_len + 18 ) )
return error;
FT_MEM_COPY( newpath, base_file_name, base_file_len );
FT_MEM_COPY( newpath + base_file_len, "/..namedfork/rsrc", 18 );
*result_file_name = newpath;
*result_offset = 0;
return FT_Err_Ok;
}
static FT_Error
raccess_guess_vfat( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
char* newpath;
FT_Memory memory;
FT_UNUSED( stream );
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name,
"resource.frk/" );
if ( !newpath )
return FT_Err_Out_Of_Memory;
*result_file_name = newpath;
*result_offset = 0;
return FT_Err_Ok;
}
static FT_Error
raccess_guess_linux_cap( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
char* newpath;
FT_Memory memory;
FT_UNUSED( stream );
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name, ".resource/" );
if ( !newpath )
return FT_Err_Out_Of_Memory;
*result_file_name = newpath;
*result_offset = 0;
return FT_Err_Ok;
}
static FT_Error
raccess_guess_linux_double( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
char* newpath;
FT_Error error;
FT_Memory memory;
FT_UNUSED( stream );
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name, "%" );
if ( !newpath )
return FT_Err_Out_Of_Memory;
error = raccess_guess_linux_double_from_file_name( library, newpath,
result_offset );
if ( !error )
*result_file_name = newpath;
else
FT_FREE( newpath );
return error;
}
static FT_Error
raccess_guess_linux_netatalk( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
char* newpath;
FT_Error error;
FT_Memory memory;
FT_UNUSED( stream );
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name,
".AppleDouble/" );
if ( !newpath )
return FT_Err_Out_Of_Memory;
error = raccess_guess_linux_double_from_file_name( library, newpath,
result_offset );
if ( !error )
*result_file_name = newpath;
else
FT_FREE( newpath );
return error;
}
static FT_Error
raccess_guess_apple_generic( FT_Library library,
FT_Stream stream,
char *base_file_name,
FT_Int32 magic,
FT_Long *result_offset )
{
FT_Int32 magic_from_stream;
FT_Error error;
FT_Int32 version_number = 0;
FT_UShort n_of_entries;
int i;
FT_UInt32 entry_id, entry_offset, entry_length = 0;
const FT_UInt32 resource_fork_entry_id = 0x2;
FT_UNUSED( library );
FT_UNUSED( base_file_name );
FT_UNUSED( version_number );
FT_UNUSED( entry_length );
if ( FT_READ_LONG( magic_from_stream ) )
return error;
if ( magic_from_stream != magic )
return FT_Err_Unknown_File_Format;
if ( FT_READ_LONG( version_number ) )
return error;
/* filler */
error = FT_Stream_Skip( stream, 16 );
if ( error )
return error;
if ( FT_READ_USHORT( n_of_entries ) )
return error;
if ( n_of_entries == 0 )
return FT_Err_Unknown_File_Format;
for ( i = 0; i < n_of_entries; i++ )
{
if ( FT_READ_LONG( entry_id ) )
return error;
if ( entry_id == resource_fork_entry_id )
{
if ( FT_READ_LONG( entry_offset ) ||
FT_READ_LONG( entry_length ) )
continue;
*result_offset = entry_offset;
return FT_Err_Ok;
}
else
{
error = FT_Stream_Skip( stream, 4 + 4 ); /* offset + length */
if ( error )
return error;
}
}
return FT_Err_Unknown_File_Format;
}
static FT_Error
raccess_guess_linux_double_from_file_name( FT_Library library,
char *file_name,
FT_Long *result_offset )
{
FT_Open_Args args2;
FT_Stream stream2;
char * nouse = NULL;
FT_Error error;
args2.flags = FT_OPEN_PATHNAME;
args2.pathname = file_name;
error = FT_Stream_New( library, &args2, &stream2 );
if ( error )
return error;
error = raccess_guess_apple_double( library, stream2, file_name,
&nouse, result_offset );
FT_Stream_Free( stream2, 0 );
return error;
}
static char*
raccess_make_file_name( FT_Memory memory,
const char *original_name,
const char *insertion )
{
char* new_name = NULL;
const char* tmp;
const char* slash;
size_t new_length;
FT_Error error = FT_Err_Ok;
FT_UNUSED( error );
new_length = ft_strlen( original_name ) + ft_strlen( insertion );
if ( FT_ALLOC( new_name, new_length + 1 ) )
return NULL;
tmp = ft_strrchr( original_name, '/' );
if ( tmp )
{
ft_strncpy( new_name, original_name, tmp - original_name + 1 );
new_name[tmp - original_name + 1] = '\0';
slash = tmp + 1;
}
else
{
slash = original_name;
new_name[0] = '\0';
}
ft_strcat( new_name, insertion );
ft_strcat( new_name, slash );
return new_name;
}
#else /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
/*************************************************************************/
/* Dummy function; just sets errors */
/*************************************************************************/
FT_BASE_DEF( void )
FT_Raccess_Guess( FT_Library library,
FT_Stream stream,
char *base_name,
char **new_names,
FT_Long *offsets,
FT_Error *errors )
{
int i;
FT_UNUSED( library );
FT_UNUSED( stream );
FT_UNUSED( base_name );
for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
{
new_names[i] = NULL;
offsets[i] = 0;
errors[i] = FT_Err_Unimplemented_Feature;
}
}
#endif /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
/* END */
+94
View File
@@ -0,0 +1,94 @@
/***************************************************************************/
/* */
/* ftsnames.c */
/* */
/* Simple interface to access SFNT name tables (which are used */
/* to hold font names, copyright info, notices, etc.) (body). */
/* */
/* This is _not_ used to retrieve glyph names! */
/* */
/* Copyright 1996-2001, 2002, 2009 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_SFNT_NAMES_H
#include FT_INTERNAL_TRUETYPE_TYPES_H
#include FT_INTERNAL_STREAM_H
#ifdef TT_CONFIG_OPTION_SFNT_NAMES
/* documentation is in ftsnames.h */
FT_EXPORT_DEF( FT_UInt )
FT_Get_Sfnt_Name_Count( FT_Face face )
{
return ( face && FT_IS_SFNT( face ) ) ? ((TT_Face)face)->num_names : 0;
}
/* documentation is in ftsnames.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_Sfnt_Name( FT_Face face,
FT_UInt idx,
FT_SfntName *aname )
{
FT_Error error = FT_Err_Invalid_Argument;
if ( aname && face && FT_IS_SFNT( face ) )
{
TT_Face ttface = (TT_Face)face;
if ( idx < (FT_UInt)ttface->num_names )
{
TT_NameEntryRec* entry = ttface->name_table.names + idx;
/* load name on demand */
if ( entry->stringLength > 0 && entry->string == NULL )
{
FT_Memory memory = face->memory;
FT_Stream stream = face->stream;
if ( FT_NEW_ARRAY ( entry->string, entry->stringLength ) ||
FT_STREAM_SEEK( entry->stringOffset ) ||
FT_STREAM_READ( entry->string, entry->stringLength ) )
{
FT_FREE( entry->string );
entry->stringLength = 0;
}
}
aname->platform_id = entry->platformID;
aname->encoding_id = entry->encodingID;
aname->language_id = entry->languageID;
aname->name_id = entry->nameID;
aname->string = (FT_Byte*)entry->string;
aname->string_len = entry->stringLength;
error = FT_Err_Ok;
}
}
return error;
}
#endif /* TT_CONFIG_OPTION_SFNT_NAMES */
/* END */
+864
View File
@@ -0,0 +1,864 @@
/***************************************************************************/
/* */
/* ftstream.c */
/* */
/* I/O stream support (body). */
/* */
/* Copyright 2000-2001, 2002, 2004, 2005, 2006, 2008, 2009, 2010 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_STREAM_H
#include FT_INTERNAL_DEBUG_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_stream
FT_BASE_DEF( void )
FT_Stream_OpenMemory( FT_Stream stream,
const FT_Byte* base,
FT_ULong size )
{
stream->base = (FT_Byte*) base;
stream->size = size;
stream->pos = 0;
stream->cursor = 0;
stream->read = 0;
stream->close = 0;
}
FT_BASE_DEF( void )
FT_Stream_Close( FT_Stream stream )
{
if ( stream && stream->close )
stream->close( stream );
}
FT_BASE_DEF( FT_Error )
FT_Stream_Seek( FT_Stream stream,
FT_ULong pos )
{
FT_Error error = FT_Err_Ok;
if ( stream->read )
{
if ( stream->read( stream, pos, 0, 0 ) )
{
FT_ERROR(( "FT_Stream_Seek:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
pos, stream->size ));
error = FT_Err_Invalid_Stream_Operation;
}
}
/* note that seeking to the first position after the file is valid */
else if ( pos > stream->size )
{
FT_ERROR(( "FT_Stream_Seek:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
pos, stream->size ));
error = FT_Err_Invalid_Stream_Operation;
}
if ( !error )
stream->pos = pos;
return error;
}
FT_BASE_DEF( FT_Error )
FT_Stream_Skip( FT_Stream stream,
FT_Long distance )
{
if ( distance < 0 )
return FT_Err_Invalid_Stream_Operation;
return FT_Stream_Seek( stream, (FT_ULong)( stream->pos + distance ) );
}
FT_BASE_DEF( FT_Long )
FT_Stream_Pos( FT_Stream stream )
{
return stream->pos;
}
FT_BASE_DEF( FT_Error )
FT_Stream_Read( FT_Stream stream,
FT_Byte* buffer,
FT_ULong count )
{
return FT_Stream_ReadAt( stream, stream->pos, buffer, count );
}
FT_BASE_DEF( FT_Error )
FT_Stream_ReadAt( FT_Stream stream,
FT_ULong pos,
FT_Byte* buffer,
FT_ULong count )
{
FT_Error error = FT_Err_Ok;
FT_ULong read_bytes;
if ( pos >= stream->size )
{
FT_ERROR(( "FT_Stream_ReadAt:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
pos, stream->size ));
return FT_Err_Invalid_Stream_Operation;
}
if ( stream->read )
read_bytes = stream->read( stream, pos, buffer, count );
else
{
read_bytes = stream->size - pos;
if ( read_bytes > count )
read_bytes = count;
FT_MEM_COPY( buffer, stream->base + pos, read_bytes );
}
stream->pos = pos + read_bytes;
if ( read_bytes < count )
{
FT_ERROR(( "FT_Stream_ReadAt:"
" invalid read; expected %lu bytes, got %lu\n",
count, read_bytes ));
error = FT_Err_Invalid_Stream_Operation;
}
return error;
}
FT_BASE_DEF( FT_ULong )
FT_Stream_TryRead( FT_Stream stream,
FT_Byte* buffer,
FT_ULong count )
{
FT_ULong read_bytes = 0;
if ( stream->pos >= stream->size )
goto Exit;
if ( stream->read )
read_bytes = stream->read( stream, stream->pos, buffer, count );
else
{
read_bytes = stream->size - stream->pos;
if ( read_bytes > count )
read_bytes = count;
FT_MEM_COPY( buffer, stream->base + stream->pos, read_bytes );
}
stream->pos += read_bytes;
Exit:
return read_bytes;
}
FT_BASE_DEF( FT_Error )
FT_Stream_ExtractFrame( FT_Stream stream,
FT_ULong count,
FT_Byte** pbytes )
{
FT_Error error;
error = FT_Stream_EnterFrame( stream, count );
if ( !error )
{
*pbytes = (FT_Byte*)stream->cursor;
/* equivalent to FT_Stream_ExitFrame(), with no memory block release */
stream->cursor = 0;
stream->limit = 0;
}
return error;
}
FT_BASE_DEF( void )
FT_Stream_ReleaseFrame( FT_Stream stream,
FT_Byte** pbytes )
{
if ( stream && stream->read )
{
FT_Memory memory = stream->memory;
#ifdef FT_DEBUG_MEMORY
ft_mem_free( memory, *pbytes );
*pbytes = NULL;
#else
FT_FREE( *pbytes );
#endif
}
*pbytes = 0;
}
FT_BASE_DEF( FT_Error )
FT_Stream_EnterFrame( FT_Stream stream,
FT_ULong count )
{
FT_Error error = FT_Err_Ok;
FT_ULong read_bytes;
/* check for nested frame access */
FT_ASSERT( stream && stream->cursor == 0 );
if ( stream->read )
{
/* allocate the frame in memory */
FT_Memory memory = stream->memory;
/* simple sanity check */
if ( count > stream->size )
{
FT_ERROR(( "FT_Stream_EnterFrame:"
" frame size (%lu) larger than stream size (%lu)\n",
count, stream->size ));
error = FT_Err_Invalid_Stream_Operation;
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, count, &error );
if ( error )
goto Exit;
#else
if ( FT_QALLOC( stream->base, count ) )
goto Exit;
#endif
/* read it */
read_bytes = stream->read( stream, stream->pos,
stream->base, count );
if ( read_bytes < count )
{
FT_ERROR(( "FT_Stream_EnterFrame:"
" invalid read; expected %lu bytes, got %lu\n",
count, read_bytes ));
FT_FREE( stream->base );
error = FT_Err_Invalid_Stream_Operation;
}
stream->cursor = stream->base;
stream->limit = stream->cursor + count;
stream->pos += read_bytes;
}
else
{
/* check current and new position */
if ( stream->pos >= stream->size ||
stream->size - stream->pos < count )
{
FT_ERROR(( "FT_Stream_EnterFrame:"
" invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n",
stream->pos, count, stream->size ));
error = FT_Err_Invalid_Stream_Operation;
goto Exit;
}
/* set cursor */
stream->cursor = stream->base + stream->pos;
stream->limit = stream->cursor + count;
stream->pos += count;
}
Exit:
return error;
}
FT_BASE_DEF( void )
FT_Stream_ExitFrame( FT_Stream stream )
{
/* IMPORTANT: The assertion stream->cursor != 0 was removed, given */
/* that it is possible to access a frame of length 0 in */
/* some weird fonts (usually, when accessing an array of */
/* 0 records, like in some strange kern tables). */
/* */
/* In this case, the loader code handles the 0-length table */
/* gracefully; however, stream.cursor is really set to 0 by the */
/* FT_Stream_EnterFrame() call, and this is not an error. */
/* */
FT_ASSERT( stream );
if ( stream->read )
{
FT_Memory memory = stream->memory;
#ifdef FT_DEBUG_MEMORY
ft_mem_free( memory, stream->base );
stream->base = NULL;
#else
FT_FREE( stream->base );
#endif
}
stream->cursor = 0;
stream->limit = 0;
}
FT_BASE_DEF( FT_Char )
FT_Stream_GetChar( FT_Stream stream )
{
FT_Char result;
FT_ASSERT( stream && stream->cursor );
result = 0;
if ( stream->cursor < stream->limit )
result = *stream->cursor++;
return result;
}
FT_BASE_DEF( FT_Short )
FT_Stream_GetShort( FT_Stream stream )
{
FT_Byte* p;
FT_Short result;
FT_ASSERT( stream && stream->cursor );
result = 0;
p = stream->cursor;
if ( p + 1 < stream->limit )
result = FT_NEXT_SHORT( p );
stream->cursor = p;
return result;
}
FT_BASE_DEF( FT_Short )
FT_Stream_GetShortLE( FT_Stream stream )
{
FT_Byte* p;
FT_Short result;
FT_ASSERT( stream && stream->cursor );
result = 0;
p = stream->cursor;
if ( p + 1 < stream->limit )
result = FT_NEXT_SHORT_LE( p );
stream->cursor = p;
return result;
}
FT_BASE_DEF( FT_Long )
FT_Stream_GetOffset( FT_Stream stream )
{
FT_Byte* p;
FT_Long result;
FT_ASSERT( stream && stream->cursor );
result = 0;
p = stream->cursor;
if ( p + 2 < stream->limit )
result = FT_NEXT_OFF3( p );
stream->cursor = p;
return result;
}
FT_BASE_DEF( FT_Long )
FT_Stream_GetLong( FT_Stream stream )
{
FT_Byte* p;
FT_Long result;
FT_ASSERT( stream && stream->cursor );
result = 0;
p = stream->cursor;
if ( p + 3 < stream->limit )
result = FT_NEXT_LONG( p );
stream->cursor = p;
return result;
}
FT_BASE_DEF( FT_Long )
FT_Stream_GetLongLE( FT_Stream stream )
{
FT_Byte* p;
FT_Long result;
FT_ASSERT( stream && stream->cursor );
result = 0;
p = stream->cursor;
if ( p + 3 < stream->limit )
result = FT_NEXT_LONG_LE( p );
stream->cursor = p;
return result;
}
FT_BASE_DEF( FT_Char )
FT_Stream_ReadChar( FT_Stream stream,
FT_Error* error )
{
FT_Byte result = 0;
FT_ASSERT( stream );
*error = FT_Err_Ok;
if ( stream->read )
{
if ( stream->read( stream, stream->pos, &result, 1L ) != 1L )
goto Fail;
}
else
{
if ( stream->pos < stream->size )
result = stream->base[stream->pos];
else
goto Fail;
}
stream->pos++;
return result;
Fail:
*error = FT_Err_Invalid_Stream_Operation;
FT_ERROR(( "FT_Stream_ReadChar:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
return 0;
}
FT_BASE_DEF( FT_Short )
FT_Stream_ReadShort( FT_Stream stream,
FT_Error* error )
{
FT_Byte reads[2];
FT_Byte* p = 0;
FT_Short result = 0;
FT_ASSERT( stream );
*error = FT_Err_Ok;
if ( stream->pos + 1 < stream->size )
{
if ( stream->read )
{
if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
goto Fail;
p = reads;
}
else
{
p = stream->base + stream->pos;
}
if ( p )
result = FT_NEXT_SHORT( p );
}
else
goto Fail;
stream->pos += 2;
return result;
Fail:
*error = FT_Err_Invalid_Stream_Operation;
FT_ERROR(( "FT_Stream_ReadShort:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
return 0;
}
FT_BASE_DEF( FT_Short )
FT_Stream_ReadShortLE( FT_Stream stream,
FT_Error* error )
{
FT_Byte reads[2];
FT_Byte* p = 0;
FT_Short result = 0;
FT_ASSERT( stream );
*error = FT_Err_Ok;
if ( stream->pos + 1 < stream->size )
{
if ( stream->read )
{
if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
goto Fail;
p = reads;
}
else
{
p = stream->base + stream->pos;
}
if ( p )
result = FT_NEXT_SHORT_LE( p );
}
else
goto Fail;
stream->pos += 2;
return result;
Fail:
*error = FT_Err_Invalid_Stream_Operation;
FT_ERROR(( "FT_Stream_ReadShortLE:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
return 0;
}
FT_BASE_DEF( FT_Long )
FT_Stream_ReadOffset( FT_Stream stream,
FT_Error* error )
{
FT_Byte reads[3];
FT_Byte* p = 0;
FT_Long result = 0;
FT_ASSERT( stream );
*error = FT_Err_Ok;
if ( stream->pos + 2 < stream->size )
{
if ( stream->read )
{
if (stream->read( stream, stream->pos, reads, 3L ) != 3L )
goto Fail;
p = reads;
}
else
{
p = stream->base + stream->pos;
}
if ( p )
result = FT_NEXT_OFF3( p );
}
else
goto Fail;
stream->pos += 3;
return result;
Fail:
*error = FT_Err_Invalid_Stream_Operation;
FT_ERROR(( "FT_Stream_ReadOffset:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
return 0;
}
FT_BASE_DEF( FT_Long )
FT_Stream_ReadLong( FT_Stream stream,
FT_Error* error )
{
FT_Byte reads[4];
FT_Byte* p = 0;
FT_Long result = 0;
FT_ASSERT( stream );
*error = FT_Err_Ok;
if ( stream->pos + 3 < stream->size )
{
if ( stream->read )
{
if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
goto Fail;
p = reads;
}
else
{
p = stream->base + stream->pos;
}
if ( p )
result = FT_NEXT_LONG( p );
}
else
goto Fail;
stream->pos += 4;
return result;
Fail:
*error = FT_Err_Invalid_Stream_Operation;
FT_ERROR(( "FT_Stream_ReadLong:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
return 0;
}
FT_BASE_DEF( FT_Long )
FT_Stream_ReadLongLE( FT_Stream stream,
FT_Error* error )
{
FT_Byte reads[4];
FT_Byte* p = 0;
FT_Long result = 0;
FT_ASSERT( stream );
*error = FT_Err_Ok;
if ( stream->pos + 3 < stream->size )
{
if ( stream->read )
{
if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
goto Fail;
p = reads;
}
else
{
p = stream->base + stream->pos;
}
if ( p )
result = FT_NEXT_LONG_LE( p );
}
else
goto Fail;
stream->pos += 4;
return result;
Fail:
*error = FT_Err_Invalid_Stream_Operation;
FT_ERROR(( "FT_Stream_ReadLongLE:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
return 0;
}
FT_BASE_DEF( FT_Error )
FT_Stream_ReadFields( FT_Stream stream,
const FT_Frame_Field* fields,
void* structure )
{
FT_Error error;
FT_Bool frame_accessed = 0;
FT_Byte* cursor;
if ( !fields || !stream )
return FT_Err_Invalid_Argument;
cursor = stream->cursor;
error = FT_Err_Ok;
do
{
FT_ULong value;
FT_Int sign_shift;
FT_Byte* p;
switch ( fields->value )
{
case ft_frame_start: /* access a new frame */
error = FT_Stream_EnterFrame( stream, fields->offset );
if ( error )
goto Exit;
frame_accessed = 1;
cursor = stream->cursor;
fields++;
continue; /* loop! */
case ft_frame_bytes: /* read a byte sequence */
case ft_frame_skip: /* skip some bytes */
{
FT_UInt len = fields->size;
if ( cursor + len > stream->limit )
{
error = FT_Err_Invalid_Stream_Operation;
goto Exit;
}
if ( fields->value == ft_frame_bytes )
{
p = (FT_Byte*)structure + fields->offset;
FT_MEM_COPY( p, cursor, len );
}
cursor += len;
fields++;
continue;
}
case ft_frame_byte:
case ft_frame_schar: /* read a single byte */
value = FT_NEXT_BYTE(cursor);
sign_shift = 24;
break;
case ft_frame_short_be:
case ft_frame_ushort_be: /* read a 2-byte big-endian short */
value = FT_NEXT_USHORT(cursor);
sign_shift = 16;
break;
case ft_frame_short_le:
case ft_frame_ushort_le: /* read a 2-byte little-endian short */
value = FT_NEXT_USHORT_LE(cursor);
sign_shift = 16;
break;
case ft_frame_long_be:
case ft_frame_ulong_be: /* read a 4-byte big-endian long */
value = FT_NEXT_ULONG(cursor);
sign_shift = 0;
break;
case ft_frame_long_le:
case ft_frame_ulong_le: /* read a 4-byte little-endian long */
value = FT_NEXT_ULONG_LE(cursor);
sign_shift = 0;
break;
case ft_frame_off3_be:
case ft_frame_uoff3_be: /* read a 3-byte big-endian long */
value = FT_NEXT_UOFF3(cursor);
sign_shift = 8;
break;
case ft_frame_off3_le:
case ft_frame_uoff3_le: /* read a 3-byte little-endian long */
value = FT_NEXT_UOFF3_LE(cursor);
sign_shift = 8;
break;
default:
/* otherwise, exit the loop */
stream->cursor = cursor;
goto Exit;
}
/* now, compute the signed value is necessary */
if ( fields->value & FT_FRAME_OP_SIGNED )
value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift );
/* finally, store the value in the object */
p = (FT_Byte*)structure + fields->offset;
switch ( fields->size )
{
case (8 / FT_CHAR_BIT):
*(FT_Byte*)p = (FT_Byte)value;
break;
case (16 / FT_CHAR_BIT):
*(FT_UShort*)p = (FT_UShort)value;
break;
case (32 / FT_CHAR_BIT):
*(FT_UInt32*)p = (FT_UInt32)value;
break;
default: /* for 64-bit systems */
*(FT_ULong*)p = (FT_ULong)value;
}
/* go to next field */
fields++;
}
while ( 1 );
Exit:
/* close the frame if it was opened by this read */
if ( frame_accessed )
FT_Stream_ExitFrame( stream );
return error;
}
/* END */
File diff suppressed because it is too large Load Diff
+160
View File
@@ -0,0 +1,160 @@
/***************************************************************************/
/* */
/* ftsynth.c */
/* */
/* FreeType synthesizing code for emboldening and slanting (body). */
/* */
/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2010 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_SYNTHESIS_H
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_OBJECTS_H
#include FT_OUTLINE_H
#include FT_BITMAP_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_synth
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** EXPERIMENTAL OBLIQUING SUPPORT ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/* documentation is in ftsynth.h */
FT_EXPORT_DEF( void )
FT_GlyphSlot_Oblique( FT_GlyphSlot slot )
{
FT_Matrix transform;
FT_Outline* outline = &slot->outline;
/* only oblique outline glyphs */
if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )
return;
/* we don't touch the advance width */
/* For italic, simply apply a shear transform, with an angle */
/* of about 12 degrees. */
transform.xx = 0x10000L;
transform.yx = 0x00000L;
transform.xy = 0x06000L;
transform.yy = 0x10000L;
FT_Outline_Transform( outline, &transform );
}
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** EXPERIMENTAL EMBOLDENING/OUTLINING SUPPORT ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/* documentation is in ftsynth.h */
FT_EXPORT_DEF( void )
FT_GlyphSlot_Embolden( FT_GlyphSlot slot )
{
FT_Library library = slot->library;
FT_Face face = slot->face;
FT_Error error;
FT_Pos xstr, ystr;
if ( slot->format != FT_GLYPH_FORMAT_OUTLINE &&
slot->format != FT_GLYPH_FORMAT_BITMAP )
return;
/* some reasonable strength */
xstr = FT_MulFix( face->units_per_EM,
face->size->metrics.y_scale ) / 24;
ystr = xstr;
if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
{
/* ignore error */
(void)FT_Outline_Embolden( &slot->outline, xstr );
/* this is more than enough for most glyphs; if you need accurate */
/* values, you have to call FT_Outline_Get_CBox */
xstr = xstr * 2;
ystr = xstr;
}
else /* slot->format == FT_GLYPH_FORMAT_BITMAP */
{
/* round to full pixels */
xstr &= ~63;
if ( xstr == 0 )
xstr = 1 << 6;
ystr &= ~63;
/*
* XXX: overflow check for 16-bit system, for compatibility
* with FT_GlyphSlot_Embolden() since freetype-2.1.10.
* unfortunately, this function return no informations
* about the cause of error.
*/
if ( ( ystr >> 6 ) > FT_INT_MAX || ( ystr >> 6 ) < FT_INT_MIN )
{
FT_TRACE1(( "FT_GlyphSlot_Embolden:" ));
FT_TRACE1(( "too strong embolding parameter ystr=%d\n", ystr ));
return;
}
error = FT_GlyphSlot_Own_Bitmap( slot );
if ( error )
return;
error = FT_Bitmap_Embolden( library, &slot->bitmap, xstr, ystr );
if ( error )
return;
}
if ( slot->advance.x )
slot->advance.x += xstr;
if ( slot->advance.y )
slot->advance.y += ystr;
slot->metrics.width += xstr;
slot->metrics.height += ystr;
slot->metrics.horiBearingY += ystr;
slot->metrics.horiAdvance += xstr;
slot->metrics.vertBearingX -= xstr / 2;
slot->metrics.vertBearingY += ystr;
slot->metrics.vertAdvance += ystr;
/* XXX: 16-bit overflow case must be excluded before here */
if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
slot->bitmap_top += (FT_Int)( ystr >> 6 );
}
/* END */
+318
View File
@@ -0,0 +1,318 @@
/***************************************************************************/
/* */
/* ftsystem.c */
/* */
/* ANSI-specific FreeType low-level system interface (body). */
/* */
/* Copyright 1996-2001, 2002, 2006, 2008, 2009, 2010 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. */
/* */
/***************************************************************************/
/*************************************************************************/
/* */
/* This file contains the default interface used by FreeType to access */
/* low-level, i.e. memory management, i/o access as well as thread */
/* synchronisation. It can be replaced by user-specific routines if */
/* necessary. */
/* */
/*************************************************************************/
#include <ft2build.h>
#include FT_CONFIG_CONFIG_H
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_SYSTEM_H
#include FT_ERRORS_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 );
}
/*************************************************************************/
/* */
/* <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, 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 */
/* */
/*************************************************************************/
/*************************************************************************/
/* */
/* 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_io
/* We use the macro STREAM_FILE for convenience to extract the */
/* system-specific stream handle from a given FreeType stream object */
#define STREAM_FILE( stream ) ( (FT_FILE*)stream->descriptor.pointer )
/*************************************************************************/
/* */
/* <Function> */
/* ft_ansi_stream_close */
/* */
/* <Description> */
/* The function to close a stream. */
/* */
/* <Input> */
/* stream :: A pointer to the stream object. */
/* */
FT_CALLBACK_DEF( void )
ft_ansi_stream_close( FT_Stream stream )
{
ft_fclose( STREAM_FILE( stream ) );
stream->descriptor.pointer = NULL;
stream->size = 0;
stream->base = 0;
}
/*************************************************************************/
/* */
/* <Function> */
/* ft_ansi_stream_io */
/* */
/* <Description> */
/* The function to open a stream. */
/* */
/* <Input> */
/* stream :: A pointer to the stream object. */
/* */
/* offset :: The position in the data stream to start reading. */
/* */
/* buffer :: The address of buffer to store the read data. */
/* */
/* count :: The number of bytes to read from the stream. */
/* */
/* <Return> */
/* The number of bytes actually read. If `count' is zero (this is, */
/* the function is used for seeking), a non-zero return value */
/* indicates an error. */
/* */
FT_CALLBACK_DEF( unsigned long )
ft_ansi_stream_io( FT_Stream stream,
unsigned long offset,
unsigned char* buffer,
unsigned long count )
{
FT_FILE* file;
if ( !count && offset > stream->size )
return 1;
file = STREAM_FILE( stream );
if ( stream->pos != offset )
ft_fseek( file, offset, SEEK_SET );
return (unsigned long)ft_fread( buffer, 1, count, file );
}
/* documentation is in ftstream.h */
FT_BASE_DEF( FT_Error )
FT_Stream_Open( FT_Stream stream,
const char* filepathname )
{
FT_FILE* file;
if ( !stream )
return FT_Err_Invalid_Stream_Handle;
stream->descriptor.pointer = NULL;
stream->pathname.pointer = (char*)filepathname;
stream->base = 0;
stream->pos = 0;
stream->read = NULL;
stream->close = NULL;
file = ft_fopen( filepathname, "rb" );
if ( !file )
{
FT_ERROR(( "FT_Stream_Open:"
" could not open `%s'\n", filepathname ));
return FT_Err_Cannot_Open_Resource;
}
ft_fseek( file, 0, SEEK_END );
stream->size = ft_ftell( file );
if ( !stream->size )
{
FT_ERROR(( "FT_Stream_Open:" ));
FT_ERROR(( " opened `%s' but zero-sized\n", filepathname ));
ft_fclose( file );
return FT_Err_Cannot_Open_Stream;
}
ft_fseek( file, 0, SEEK_SET );
stream->descriptor.pointer = file;
stream->read = ft_ansi_stream_io;
stream->close = ft_ansi_stream_close;
FT_TRACE1(( "FT_Stream_Open:" ));
FT_TRACE1(( " opened `%s' (%d bytes) successfully\n",
filepathname, stream->size ));
return FT_Err_Ok;
}
#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 = 0;
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 */
+546
View File
@@ -0,0 +1,546 @@
/***************************************************************************/
/* */
/* fttrigon.c */
/* */
/* FreeType trigonometric functions (body). */
/* */
/* Copyright 2001, 2002, 2003, 2004, 2005 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_OBJECTS_H
#include FT_TRIGONOMETRY_H
/* the following is 0.2715717684432231 * 2^30 */
#define FT_TRIG_COSCALE 0x11616E8EUL
/* this table was generated for FT_PI = 180L << 16, i.e. degrees */
#define FT_TRIG_MAX_ITERS 23
static const FT_Fixed
ft_trig_arctan_table[24] =
{
4157273L, 2949120L, 1740967L, 919879L, 466945L, 234379L, 117304L,
58666L, 29335L, 14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L,
57L, 29L, 14L, 7L, 4L, 2L, 1L
};
/* the Cordic shrink factor, multiplied by 2^32 */
#define FT_TRIG_SCALE 1166391785UL /* 0x4585BA38UL */
#ifdef FT_CONFIG_HAS_INT64
/* multiply a given value by the CORDIC shrink factor */
static FT_Fixed
ft_trig_downscale( FT_Fixed val )
{
FT_Fixed s;
FT_Int64 v;
s = val;
val = ( val >= 0 ) ? val : -val;
v = ( val * (FT_Int64)FT_TRIG_SCALE ) + 0x100000000UL;
val = (FT_Fixed)( v >> 32 );
return ( s >= 0 ) ? val : -val;
}
#else /* !FT_CONFIG_HAS_INT64 */
/* multiply a given value by the CORDIC shrink factor */
static FT_Fixed
ft_trig_downscale( FT_Fixed val )
{
FT_Fixed s;
FT_UInt32 v1, v2, k1, k2, hi, lo1, lo2, lo3;
s = val;
val = ( val >= 0 ) ? val : -val;
v1 = (FT_UInt32)val >> 16;
v2 = (FT_UInt32)(val & 0xFFFFL);
k1 = (FT_UInt32)FT_TRIG_SCALE >> 16; /* constant */
k2 = (FT_UInt32)(FT_TRIG_SCALE & 0xFFFFL); /* constant */
hi = k1 * v1;
lo1 = k1 * v2 + k2 * v1; /* can't overflow */
lo2 = ( k2 * v2 ) >> 16;
lo3 = ( lo1 >= lo2 ) ? lo1 : lo2;
lo1 += lo2;
hi += lo1 >> 16;
if ( lo1 < lo3 )
hi += (FT_UInt32)0x10000UL;
val = (FT_Fixed)hi;
return ( s >= 0 ) ? val : -val;
}
#endif /* !FT_CONFIG_HAS_INT64 */
static FT_Int
ft_trig_prenorm( FT_Vector* vec )
{
FT_Fixed x, y, z;
FT_Int shift;
x = vec->x;
y = vec->y;
z = ( ( x >= 0 ) ? x : - x ) | ( (y >= 0) ? y : -y );
shift = 0;
#if 1
/* determine msb bit index in `shift' */
if ( z >= ( 1L << 16 ) )
{
z >>= 16;
shift += 16;
}
if ( z >= ( 1L << 8 ) )
{
z >>= 8;
shift += 8;
}
if ( z >= ( 1L << 4 ) )
{
z >>= 4;
shift += 4;
}
if ( z >= ( 1L << 2 ) )
{
z >>= 2;
shift += 2;
}
if ( z >= ( 1L << 1 ) )
{
z >>= 1;
shift += 1;
}
if ( shift <= 27 )
{
shift = 27 - shift;
vec->x = x << shift;
vec->y = y << shift;
}
else
{
shift -= 27;
vec->x = x >> shift;
vec->y = y >> shift;
shift = -shift;
}
#else /* 0 */
if ( z < ( 1L << 27 ) )
{
do
{
shift++;
z <<= 1;
} while ( z < ( 1L << 27 ) );
vec->x = x << shift;
vec->y = y << shift;
}
else if ( z > ( 1L << 28 ) )
{
do
{
shift++;
z >>= 1;
} while ( z > ( 1L << 28 ) );
vec->x = x >> shift;
vec->y = y >> shift;
shift = -shift;
}
#endif /* 0 */
return shift;
}
static void
ft_trig_pseudo_rotate( FT_Vector* vec,
FT_Angle theta )
{
FT_Int i;
FT_Fixed x, y, xtemp;
const FT_Fixed *arctanptr;
x = vec->x;
y = vec->y;
/* Get angle between -90 and 90 degrees */
while ( theta <= -FT_ANGLE_PI2 )
{
x = -x;
y = -y;
theta += FT_ANGLE_PI;
}
while ( theta > FT_ANGLE_PI2 )
{
x = -x;
y = -y;
theta -= FT_ANGLE_PI;
}
/* Initial pseudorotation, with left shift */
arctanptr = ft_trig_arctan_table;
if ( theta < 0 )
{
xtemp = x + ( y << 1 );
y = y - ( x << 1 );
x = xtemp;
theta += *arctanptr++;
}
else
{
xtemp = x - ( y << 1 );
y = y + ( x << 1 );
x = xtemp;
theta -= *arctanptr++;
}
/* Subsequent pseudorotations, with right shifts */
i = 0;
do
{
if ( theta < 0 )
{
xtemp = x + ( y >> i );
y = y - ( x >> i );
x = xtemp;
theta += *arctanptr++;
}
else
{
xtemp = x - ( y >> i );
y = y + ( x >> i );
x = xtemp;
theta -= *arctanptr++;
}
} while ( ++i < FT_TRIG_MAX_ITERS );
vec->x = x;
vec->y = y;
}
static void
ft_trig_pseudo_polarize( FT_Vector* vec )
{
FT_Fixed theta;
FT_Fixed yi, i;
FT_Fixed x, y;
const FT_Fixed *arctanptr;
x = vec->x;
y = vec->y;
/* Get the vector into the right half plane */
theta = 0;
if ( x < 0 )
{
x = -x;
y = -y;
theta = 2 * FT_ANGLE_PI2;
}
if ( y > 0 )
theta = - theta;
arctanptr = ft_trig_arctan_table;
if ( y < 0 )
{
/* Rotate positive */
yi = y + ( x << 1 );
x = x - ( y << 1 );
y = yi;
theta -= *arctanptr++; /* Subtract angle */
}
else
{
/* Rotate negative */
yi = y - ( x << 1 );
x = x + ( y << 1 );
y = yi;
theta += *arctanptr++; /* Add angle */
}
i = 0;
do
{
if ( y < 0 )
{
/* Rotate positive */
yi = y + ( x >> i );
x = x - ( y >> i );
y = yi;
theta -= *arctanptr++;
}
else
{
/* Rotate negative */
yi = y - ( x >> i );
x = x + ( y >> i );
y = yi;
theta += *arctanptr++;
}
} while ( ++i < FT_TRIG_MAX_ITERS );
/* round theta */
if ( theta >= 0 )
theta = FT_PAD_ROUND( theta, 32 );
else
theta = -FT_PAD_ROUND( -theta, 32 );
vec->x = x;
vec->y = theta;
}
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( FT_Fixed )
FT_Cos( FT_Angle angle )
{
FT_Vector v;
v.x = FT_TRIG_COSCALE >> 2;
v.y = 0;
ft_trig_pseudo_rotate( &v, angle );
return v.x / ( 1 << 12 );
}
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( FT_Fixed )
FT_Sin( FT_Angle angle )
{
return FT_Cos( FT_ANGLE_PI2 - angle );
}
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( FT_Fixed )
FT_Tan( FT_Angle angle )
{
FT_Vector v;
v.x = FT_TRIG_COSCALE >> 2;
v.y = 0;
ft_trig_pseudo_rotate( &v, angle );
return FT_DivFix( v.y, v.x );
}
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( FT_Angle )
FT_Atan2( FT_Fixed dx,
FT_Fixed dy )
{
FT_Vector v;
if ( dx == 0 && dy == 0 )
return 0;
v.x = dx;
v.y = dy;
ft_trig_prenorm( &v );
ft_trig_pseudo_polarize( &v );
return v.y;
}
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( void )
FT_Vector_Unit( FT_Vector* vec,
FT_Angle angle )
{
vec->x = FT_TRIG_COSCALE >> 2;
vec->y = 0;
ft_trig_pseudo_rotate( vec, angle );
vec->x >>= 12;
vec->y >>= 12;
}
/* these macros return 0 for positive numbers,
and -1 for negative ones */
#define FT_SIGN_LONG( x ) ( (x) >> ( FT_SIZEOF_LONG * 8 - 1 ) )
#define FT_SIGN_INT( x ) ( (x) >> ( FT_SIZEOF_INT * 8 - 1 ) )
#define FT_SIGN_INT32( x ) ( (x) >> 31 )
#define FT_SIGN_INT16( x ) ( (x) >> 15 )
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( void )
FT_Vector_Rotate( FT_Vector* vec,
FT_Angle angle )
{
FT_Int shift;
FT_Vector v;
v.x = vec->x;
v.y = vec->y;
if ( angle && ( v.x != 0 || v.y != 0 ) )
{
shift = ft_trig_prenorm( &v );
ft_trig_pseudo_rotate( &v, angle );
v.x = ft_trig_downscale( v.x );
v.y = ft_trig_downscale( v.y );
if ( shift > 0 )
{
FT_Int32 half = (FT_Int32)1L << ( shift - 1 );
vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift;
vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift;
}
else
{
shift = -shift;
vec->x = v.x << shift;
vec->y = v.y << shift;
}
}
}
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( FT_Fixed )
FT_Vector_Length( FT_Vector* vec )
{
FT_Int shift;
FT_Vector v;
v = *vec;
/* handle trivial cases */
if ( v.x == 0 )
{
return ( v.y >= 0 ) ? v.y : -v.y;
}
else if ( v.y == 0 )
{
return ( v.x >= 0 ) ? v.x : -v.x;
}
/* general case */
shift = ft_trig_prenorm( &v );
ft_trig_pseudo_polarize( &v );
v.x = ft_trig_downscale( v.x );
if ( shift > 0 )
return ( v.x + ( 1 << ( shift - 1 ) ) ) >> shift;
return v.x << -shift;
}
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( void )
FT_Vector_Polarize( FT_Vector* vec,
FT_Fixed *length,
FT_Angle *angle )
{
FT_Int shift;
FT_Vector v;
v = *vec;
if ( v.x == 0 && v.y == 0 )
return;
shift = ft_trig_prenorm( &v );
ft_trig_pseudo_polarize( &v );
v.x = ft_trig_downscale( v.x );
*length = ( shift >= 0 ) ? ( v.x >> shift ) : ( v.x << -shift );
*angle = v.y;
}
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( void )
FT_Vector_From_Polar( FT_Vector* vec,
FT_Fixed length,
FT_Angle angle )
{
vec->x = length;
vec->y = 0;
FT_Vector_Rotate( vec, angle );
}
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( FT_Angle )
FT_Angle_Diff( FT_Angle angle1,
FT_Angle angle2 )
{
FT_Angle delta = angle2 - angle1;
delta %= FT_ANGLE_2PI;
if ( delta < 0 )
delta += FT_ANGLE_2PI;
if ( delta > FT_ANGLE_PI )
delta -= FT_ANGLE_2PI;
return delta;
}
/* END */
+501
View File
@@ -0,0 +1,501 @@
/***************************************************************************/
/* */
/* ftutil.c */
/* */
/* FreeType utility file for memory and list management (body). */
/* */
/* Copyright 2002, 2004, 2005, 2006, 2007 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_MEMORY_H
#include FT_INTERNAL_OBJECTS_H
#include FT_LIST_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_memory
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** *****/
/***** M E M O R Y M A N A G E M E N T *****/
/***** *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
FT_BASE_DEF( FT_Pointer )
ft_mem_alloc( FT_Memory memory,
FT_Long size,
FT_Error *p_error )
{
FT_Error error;
FT_Pointer block = ft_mem_qalloc( memory, size, &error );
if ( !error && size > 0 )
FT_MEM_ZERO( block, size );
*p_error = error;
return block;
}
FT_BASE_DEF( FT_Pointer )
ft_mem_qalloc( FT_Memory memory,
FT_Long size,
FT_Error *p_error )
{
FT_Error error = FT_Err_Ok;
FT_Pointer block = NULL;
if ( size > 0 )
{
block = memory->alloc( memory, size );
if ( block == NULL )
error = FT_Err_Out_Of_Memory;
}
else if ( size < 0 )
{
/* may help catch/prevent security issues */
error = FT_Err_Invalid_Argument;
}
*p_error = error;
return block;
}
FT_BASE_DEF( FT_Pointer )
ft_mem_realloc( FT_Memory memory,
FT_Long item_size,
FT_Long cur_count,
FT_Long new_count,
void* block,
FT_Error *p_error )
{
FT_Error error = FT_Err_Ok;
block = ft_mem_qrealloc( memory, item_size,
cur_count, new_count, block, &error );
if ( !error && new_count > cur_count )
FT_MEM_ZERO( (char*)block + cur_count * item_size,
( new_count - cur_count ) * item_size );
*p_error = error;
return block;
}
FT_BASE_DEF( FT_Pointer )
ft_mem_qrealloc( FT_Memory memory,
FT_Long item_size,
FT_Long cur_count,
FT_Long new_count,
void* block,
FT_Error *p_error )
{
FT_Error error = FT_Err_Ok;
/* Note that we now accept `item_size == 0' as a valid parameter, in
* order to cover very weird cases where an ALLOC_MULT macro would be
* called.
*/
if ( cur_count < 0 || new_count < 0 || item_size < 0 )
{
/* may help catch/prevent nasty security issues */
error = FT_Err_Invalid_Argument;
}
else if ( new_count == 0 || item_size == 0 )
{
ft_mem_free( memory, block );
block = NULL;
}
else if ( new_count > FT_INT_MAX/item_size )
{
error = FT_Err_Array_Too_Large;
}
else if ( cur_count == 0 )
{
FT_ASSERT( block == NULL );
block = ft_mem_alloc( memory, new_count*item_size, &error );
}
else
{
FT_Pointer block2;
FT_Long cur_size = cur_count*item_size;
FT_Long new_size = new_count*item_size;
block2 = memory->realloc( memory, cur_size, new_size, block );
if ( block2 == NULL )
error = FT_Err_Out_Of_Memory;
else
block = block2;
}
*p_error = error;
return block;
}
FT_BASE_DEF( void )
ft_mem_free( FT_Memory memory,
const void *P )
{
if ( P )
memory->free( memory, (void*)P );
}
FT_BASE_DEF( FT_Pointer )
ft_mem_dup( FT_Memory memory,
const void* address,
FT_ULong size,
FT_Error *p_error )
{
FT_Error error;
FT_Pointer p = ft_mem_qalloc( memory, size, &error );
if ( !error && address )
ft_memcpy( p, address, size );
*p_error = error;
return p;
}
FT_BASE_DEF( FT_Pointer )
ft_mem_strdup( FT_Memory memory,
const char* str,
FT_Error *p_error )
{
FT_ULong len = str ? (FT_ULong)ft_strlen( str ) + 1
: 0;
return ft_mem_dup( memory, str, len, p_error );
}
FT_BASE_DEF( FT_Int )
ft_mem_strcpyn( char* dst,
const char* src,
FT_ULong size )
{
while ( size > 1 && *src != 0 )
{
*dst++ = *src++;
size--;
}
*dst = 0; /* always zero-terminate */
return *src != 0;
}
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** *****/
/***** D O U B L Y L I N K E D L I S T S *****/
/***** *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
#undef FT_COMPONENT
#define FT_COMPONENT trace_list
/* documentation is in ftlist.h */
FT_EXPORT_DEF( FT_ListNode )
FT_List_Find( FT_List list,
void* data )
{
FT_ListNode cur;
cur = list->head;
while ( cur )
{
if ( cur->data == data )
return cur;
cur = cur->next;
}
return (FT_ListNode)0;
}
/* documentation is in ftlist.h */
FT_EXPORT_DEF( void )
FT_List_Add( FT_List list,
FT_ListNode node )
{
FT_ListNode before = list->tail;
node->next = 0;
node->prev = before;
if ( before )
before->next = node;
else
list->head = node;
list->tail = node;
}
/* documentation is in ftlist.h */
FT_EXPORT_DEF( void )
FT_List_Insert( FT_List list,
FT_ListNode node )
{
FT_ListNode after = list->head;
node->next = after;
node->prev = 0;
if ( !after )
list->tail = node;
else
after->prev = node;
list->head = node;
}
/* documentation is in ftlist.h */
FT_EXPORT_DEF( void )
FT_List_Remove( FT_List list,
FT_ListNode node )
{
FT_ListNode before, after;
before = node->prev;
after = node->next;
if ( before )
before->next = after;
else
list->head = after;
if ( after )
after->prev = before;
else
list->tail = before;
}
/* documentation is in ftlist.h */
FT_EXPORT_DEF( void )
FT_List_Up( FT_List list,
FT_ListNode node )
{
FT_ListNode before, after;
before = node->prev;
after = node->next;
/* check whether we are already on top of the list */
if ( !before )
return;
before->next = after;
if ( after )
after->prev = before;
else
list->tail = before;
node->prev = 0;
node->next = list->head;
list->head->prev = node;
list->head = node;
}
/* documentation is in ftlist.h */
FT_EXPORT_DEF( FT_Error )
FT_List_Iterate( FT_List list,
FT_List_Iterator iterator,
void* user )
{
FT_ListNode cur = list->head;
FT_Error error = FT_Err_Ok;
while ( cur )
{
FT_ListNode next = cur->next;
error = iterator( cur, user );
if ( error )
break;
cur = next;
}
return error;
}
/* documentation is in ftlist.h */
FT_EXPORT_DEF( void )
FT_List_Finalize( FT_List list,
FT_List_Destructor destroy,
FT_Memory memory,
void* user )
{
FT_ListNode cur;
cur = list->head;
while ( cur )
{
FT_ListNode next = cur->next;
void* data = cur->data;
if ( destroy )
destroy( memory, data, user );
FT_FREE( cur );
cur = next;
}
list->head = 0;
list->tail = 0;
}
FT_BASE_DEF( FT_UInt32 )
ft_highpow2( FT_UInt32 value )
{
FT_UInt32 value2;
/*
* We simply clear the lowest bit in each iteration. When
* we reach 0, we know that the previous value was our result.
*/
for ( ;; )
{
value2 = value & (value - 1); /* clear lowest bit */
if ( value2 == 0 )
break;
value = value2;
}
return value;
}
#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
FT_BASE_DEF( FT_Error )
FT_Alloc( FT_Memory memory,
FT_Long size,
void* *P )
{
FT_Error error;
(void)FT_ALLOC( *P, size );
return error;
}
FT_BASE_DEF( FT_Error )
FT_QAlloc( FT_Memory memory,
FT_Long size,
void* *p )
{
FT_Error error;
(void)FT_QALLOC( *p, size );
return error;
}
FT_BASE_DEF( FT_Error )
FT_Realloc( FT_Memory memory,
FT_Long current,
FT_Long size,
void* *P )
{
FT_Error error;
(void)FT_REALLOC( *P, current, size );
return error;
}
FT_BASE_DEF( FT_Error )
FT_QRealloc( FT_Memory memory,
FT_Long current,
FT_Long size,
void* *p )
{
FT_Error error;
(void)FT_QREALLOC( *p, current, size );
return error;
}
FT_BASE_DEF( void )
FT_Free( FT_Memory memory,
void* *P )
{
if ( *P )
FT_MEM_FREE( *P );
}
#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
/* END */
+29
View File
@@ -0,0 +1,29 @@
# FreeType 2 src/cff Jamfile
#
# Copyright 2001, 2002 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.
SubDir FT2_TOP $(FT2_SRC_DIR) cff ;
{
local _sources ;
if $(FT2_MULTI)
{
_sources = cffdrivr cffgload cffload cffobjs cffparse cffcmap cffpic ;
}
else
{
_sources = cff ;
}
Library $(FT2_LIB) : $(_sources).c ;
}
# end of src/cff Jamfile
+30
View File
@@ -0,0 +1,30 @@
/***************************************************************************/
/* */
/* cff.c */
/* */
/* FreeType OpenType driver component (body only). */
/* */
/* Copyright 1996-2001, 2002 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. */
/* */
/***************************************************************************/
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include <ft2build.h>
#include "cffpic.c"
#include "cffdrivr.c"
#include "cffparse.c"
#include "cffload.c"
#include "cffobjs.c"
#include "cffgload.c"
#include "cffcmap.c"
/* END */
+208
View File
@@ -0,0 +1,208 @@
/***************************************************************************/
/* */
/* cffcmap.c */
/* */
/* CFF character mapping table (cmap) support (body). */
/* */
/* Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2010 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 "cffcmap.h"
#include "cffload.h"
#include "cfferrs.h"
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** CFF STANDARD (AND EXPERT) ENCODING CMAPS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
FT_CALLBACK_DEF( FT_Error )
cff_cmap_encoding_init( CFF_CMapStd cmap )
{
TT_Face face = (TT_Face)FT_CMAP_FACE( cmap );
CFF_Font cff = (CFF_Font)face->extra.data;
CFF_Encoding encoding = &cff->encoding;
cmap->gids = encoding->codes;
return 0;
}
FT_CALLBACK_DEF( void )
cff_cmap_encoding_done( CFF_CMapStd cmap )
{
cmap->gids = NULL;
}
FT_CALLBACK_DEF( FT_UInt )
cff_cmap_encoding_char_index( CFF_CMapStd cmap,
FT_UInt32 char_code )
{
FT_UInt result = 0;
if ( char_code < 256 )
result = cmap->gids[char_code];
return result;
}
FT_CALLBACK_DEF( FT_UInt32 )
cff_cmap_encoding_char_next( CFF_CMapStd cmap,
FT_UInt32 *pchar_code )
{
FT_UInt result = 0;
FT_UInt32 char_code = *pchar_code;
*pchar_code = 0;
if ( char_code < 255 )
{
FT_UInt code = (FT_UInt)(char_code + 1);
for (;;)
{
if ( code >= 256 )
break;
result = cmap->gids[code];
if ( result != 0 )
{
*pchar_code = code;
break;
}
code++;
}
}
return result;
}
FT_DEFINE_CMAP_CLASS(cff_cmap_encoding_class_rec,
sizeof ( CFF_CMapStdRec ),
(FT_CMap_InitFunc) cff_cmap_encoding_init,
(FT_CMap_DoneFunc) cff_cmap_encoding_done,
(FT_CMap_CharIndexFunc)cff_cmap_encoding_char_index,
(FT_CMap_CharNextFunc) cff_cmap_encoding_char_next,
NULL, NULL, NULL, NULL, NULL
)
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** CFF SYNTHETIC UNICODE ENCODING CMAP *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
FT_CALLBACK_DEF( const char* )
cff_sid_to_glyph_name( TT_Face face,
FT_UInt idx )
{
CFF_Font cff = (CFF_Font)face->extra.data;
CFF_Charset charset = &cff->charset;
FT_UInt sid = charset->sids[idx];
return cff_index_get_sid_string( cff, sid );
}
FT_CALLBACK_DEF( FT_Error )
cff_cmap_unicode_init( PS_Unicodes unicodes )
{
TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes );
FT_Memory memory = FT_FACE_MEMORY( face );
CFF_Font cff = (CFF_Font)face->extra.data;
CFF_Charset charset = &cff->charset;
FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames;
/* can't build Unicode map for CID-keyed font */
/* because we don't know glyph names. */
if ( !charset->sids )
return CFF_Err_No_Unicode_Glyph_Name;
return psnames->unicodes_init( memory,
unicodes,
cff->num_glyphs,
(PS_GetGlyphNameFunc)&cff_sid_to_glyph_name,
(PS_FreeGlyphNameFunc)NULL,
(FT_Pointer)face );
}
FT_CALLBACK_DEF( void )
cff_cmap_unicode_done( PS_Unicodes unicodes )
{
FT_Face face = FT_CMAP_FACE( unicodes );
FT_Memory memory = FT_FACE_MEMORY( face );
FT_FREE( unicodes->maps );
unicodes->num_maps = 0;
}
FT_CALLBACK_DEF( FT_UInt )
cff_cmap_unicode_char_index( PS_Unicodes unicodes,
FT_UInt32 char_code )
{
TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes );
CFF_Font cff = (CFF_Font)face->extra.data;
FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames;
return psnames->unicodes_char_index( unicodes, char_code );
}
FT_CALLBACK_DEF( FT_UInt32 )
cff_cmap_unicode_char_next( PS_Unicodes unicodes,
FT_UInt32 *pchar_code )
{
TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes );
CFF_Font cff = (CFF_Font)face->extra.data;
FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames;
return psnames->unicodes_char_next( unicodes, pchar_code );
}
FT_DEFINE_CMAP_CLASS(cff_cmap_unicode_class_rec,
sizeof ( PS_UnicodesRec ),
(FT_CMap_InitFunc) cff_cmap_unicode_init,
(FT_CMap_DoneFunc) cff_cmap_unicode_done,
(FT_CMap_CharIndexFunc)cff_cmap_unicode_char_index,
(FT_CMap_CharNextFunc) cff_cmap_unicode_char_next,
NULL, NULL, NULL, NULL, NULL
)
/* END */
+67
View File
@@ -0,0 +1,67 @@
/***************************************************************************/
/* */
/* cffcmap.h */
/* */
/* CFF character mapping table (cmap) support (specification). */
/* */
/* Copyright 2002, 2003, 2006 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. */
/* */
/***************************************************************************/
#ifndef __CFFCMAP_H__
#define __CFFCMAP_H__
#include "cffobjs.h"
FT_BEGIN_HEADER
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** TYPE1 STANDARD (AND EXPERT) ENCODING CMAPS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* standard (and expert) encoding cmaps */
typedef struct CFF_CMapStdRec_* CFF_CMapStd;
typedef struct CFF_CMapStdRec_
{
FT_CMapRec cmap;
FT_UShort* gids; /* up to 256 elements */
} CFF_CMapStdRec;
FT_DECLARE_CMAP_CLASS(cff_cmap_encoding_class_rec)
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** CFF SYNTHETIC UNICODE ENCODING CMAP *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* unicode (synthetic) cmaps */
FT_DECLARE_CMAP_CLASS(cff_cmap_unicode_class_rec)
FT_END_HEADER
#endif /* __CFFCMAP_H__ */
/* END */
+671
View File
@@ -0,0 +1,671 @@
/***************************************************************************/
/* */
/* cffdrivr.c */
/* */
/* OpenType font driver implementation (body). */
/* */
/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
/* 2010 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_FREETYPE_H
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_SFNT_H
#include FT_SERVICE_CID_H
#include FT_SERVICE_POSTSCRIPT_INFO_H
#include FT_SERVICE_POSTSCRIPT_NAME_H
#include FT_SERVICE_TT_CMAP_H
#include "cffdrivr.h"
#include "cffgload.h"
#include "cffload.h"
#include "cffcmap.h"
#include "cffparse.h"
#include "cfferrs.h"
#include "cffpic.h"
#include FT_SERVICE_XFREE86_NAME_H
#include FT_SERVICE_GLYPH_DICT_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_cffdriver
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** F A C E S ****/
/**** ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
#undef PAIR_TAG
#define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \
(FT_ULong)right )
/*************************************************************************/
/* */
/* <Function> */
/* cff_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. */
/* */
FT_CALLBACK_DEF( FT_Error )
cff_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 CFF_Err_Ok;
}
#undef PAIR_TAG
/*************************************************************************/
/* */
/* <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 */
/* FT_LOAD_??? 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. */
/* */
FT_CALLBACK_DEF( FT_Error )
Load_Glyph( FT_GlyphSlot cffslot, /* CFF_GlyphSlot */
FT_Size cffsize, /* CFF_Size */
FT_UInt glyph_index,
FT_Int32 load_flags )
{
FT_Error error;
CFF_GlyphSlot slot = (CFF_GlyphSlot)cffslot;
CFF_Size size = (CFF_Size)cffsize;
if ( !slot )
return CFF_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;
/* reset the size object if necessary */
if ( load_flags & FT_LOAD_NO_SCALE )
size = NULL;
if ( size )
{
/* these two objects must have the same parent */
if ( cffsize->face != cffslot->face )
return CFF_Err_Invalid_Face_Handle;
}
/* now load the glyph outline if necessary */
error = cff_slot_load( slot, size, glyph_index, load_flags );
/* force drop-out mode to 2 - irrelevant now */
/* slot->outline.dropout_mode = 2; */
return error;
}
FT_CALLBACK_DEF( FT_Error )
cff_get_advances( FT_Face face,
FT_UInt start,
FT_UInt count,
FT_Int32 flags,
FT_Fixed* advances )
{
FT_UInt nn;
FT_Error error = CFF_Err_Ok;
FT_GlyphSlot slot = face->glyph;
flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
for ( nn = 0; nn < count; nn++ )
{
error = Load_Glyph( slot, face->size, start + nn, flags );
if ( error )
break;
advances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
? slot->linearVertAdvance
: slot->linearHoriAdvance;
}
return error;
}
/*
* GLYPH DICT SERVICE
*
*/
static FT_Error
cff_get_glyph_name( CFF_Face face,
FT_UInt glyph_index,
FT_Pointer buffer,
FT_UInt buffer_max )
{
CFF_Font font = (CFF_Font)face->extra.data;
FT_String* gname;
FT_UShort sid;
FT_Error error;
if ( !font->psnames )
{
FT_ERROR(( "cff_get_glyph_name:"
" cannot get glyph name from CFF & CEF fonts\n"
" "
" without the `PSNames' module\n" ));
error = CFF_Err_Unknown_File_Format;
goto Exit;
}
/* first, locate the sid in the charset table */
sid = font->charset.sids[glyph_index];
/* now, lookup the name itself */
gname = cff_index_get_sid_string( font, sid );
if ( gname )
FT_STRCPYN( buffer, gname, buffer_max );
error = CFF_Err_Ok;
Exit:
return error;
}
static FT_UInt
cff_get_name_index( CFF_Face face,
FT_String* glyph_name )
{
CFF_Font cff;
CFF_Charset charset;
FT_Service_PsCMaps psnames;
FT_String* name;
FT_UShort sid;
FT_UInt i;
cff = (CFF_FontRec *)face->extra.data;
charset = &cff->charset;
FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
if ( !psnames )
return 0;
for ( i = 0; i < cff->num_glyphs; i++ )
{
sid = charset->sids[i];
if ( sid > 390 )
name = cff_index_get_string( cff, sid - 391 );
else
name = (FT_String *)psnames->adobe_std_strings( sid );
if ( !name )
continue;
if ( !ft_strcmp( glyph_name, name ) )
return i;
}
return 0;
}
FT_DEFINE_SERVICE_GLYPHDICTREC(cff_service_glyph_dict,
(FT_GlyphDict_GetNameFunc) cff_get_glyph_name,
(FT_GlyphDict_NameIndexFunc)cff_get_name_index
)
/*
* POSTSCRIPT INFO SERVICE
*
*/
static FT_Int
cff_ps_has_glyph_names( FT_Face face )
{
return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0;
}
static FT_Error
cff_ps_get_font_info( CFF_Face face,
PS_FontInfoRec* afont_info )
{
CFF_Font cff = (CFF_Font)face->extra.data;
FT_Error error = CFF_Err_Ok;
if ( cff && cff->font_info == NULL )
{
CFF_FontRecDict dict = &cff->top_font.font_dict;
PS_FontInfoRec *font_info;
FT_Memory memory = face->root.memory;
if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) )
goto Fail;
font_info->version = cff_index_get_sid_string( cff,
dict->version );
font_info->notice = cff_index_get_sid_string( cff,
dict->notice );
font_info->full_name = cff_index_get_sid_string( cff,
dict->full_name );
font_info->family_name = cff_index_get_sid_string( cff,
dict->family_name );
font_info->weight = cff_index_get_sid_string( cff,
dict->weight );
font_info->italic_angle = dict->italic_angle;
font_info->is_fixed_pitch = dict->is_fixed_pitch;
font_info->underline_position = (FT_Short)dict->underline_position;
font_info->underline_thickness = (FT_Short)dict->underline_thickness;
cff->font_info = font_info;
}
if ( cff )
*afont_info = *cff->font_info;
Fail:
return error;
}
FT_DEFINE_SERVICE_PSINFOREC(cff_service_ps_info,
(PS_GetFontInfoFunc) cff_ps_get_font_info,
(PS_GetFontExtraFunc) NULL,
(PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,
(PS_GetFontPrivateFunc)NULL /* unsupported with CFF fonts */
)
/*
* POSTSCRIPT NAME SERVICE
*
*/
static const char*
cff_get_ps_name( CFF_Face face )
{
CFF_Font cff = (CFF_Font)face->extra.data;
return (const char*)cff->font_name;
}
FT_DEFINE_SERVICE_PSFONTNAMEREC(cff_service_ps_name,
(FT_PsName_GetFunc)cff_get_ps_name
)
/*
* TT CMAP INFO
*
* If the charmap is a synthetic Unicode encoding cmap or
* a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO
* service defined in SFNT module.
*
* Otherwise call the service function in the sfnt module.
*
*/
static FT_Error
cff_get_cmap_info( FT_CharMap charmap,
TT_CMapInfo *cmap_info )
{
FT_CMap cmap = FT_CMAP( charmap );
FT_Error error = CFF_Err_Ok;
FT_Face face = FT_CMAP_FACE( cmap );
FT_Library library = FT_FACE_LIBRARY( face );
cmap_info->language = 0;
cmap_info->format = 0;
if ( cmap->clazz != &FT_CFF_CMAP_ENCODING_CLASS_REC_GET &&
cmap->clazz != &FT_CFF_CMAP_UNICODE_CLASS_REC_GET )
{
FT_Module sfnt = FT_Get_Module( library, "sfnt" );
FT_Service_TTCMaps service =
(FT_Service_TTCMaps)ft_module_get_service( sfnt,
FT_SERVICE_ID_TT_CMAP );
if ( service && service->get_cmap_info )
error = service->get_cmap_info( charmap, cmap_info );
}
return error;
}
FT_DEFINE_SERVICE_TTCMAPSREC(cff_service_get_cmap_info,
(TT_CMap_Info_GetFunc)cff_get_cmap_info
)
/*
* CID INFO SERVICE
*
*/
static FT_Error
cff_get_ros( CFF_Face face,
const char* *registry,
const char* *ordering,
FT_Int *supplement )
{
FT_Error error = CFF_Err_Ok;
CFF_Font cff = (CFF_Font)face->extra.data;
if ( cff )
{
CFF_FontRecDict dict = &cff->top_font.font_dict;
if ( dict->cid_registry == 0xFFFFU )
{
error = CFF_Err_Invalid_Argument;
goto Fail;
}
if ( registry )
{
if ( cff->registry == NULL )
cff->registry = cff_index_get_sid_string( cff,
dict->cid_registry );
*registry = cff->registry;
}
if ( ordering )
{
if ( cff->ordering == NULL )
cff->ordering = cff_index_get_sid_string( cff,
dict->cid_ordering );
*ordering = cff->ordering;
}
/*
* XXX: According to Adobe TechNote #5176, the supplement in CFF
* can be a real number. We truncate it to fit public API
* since freetype-2.3.6.
*/
if ( supplement )
{
if ( dict->cid_supplement < FT_INT_MIN ||
dict->cid_supplement > FT_INT_MAX )
FT_TRACE1(( "cff_get_ros: too large supplement %d is truncated\n",
dict->cid_supplement ));
*supplement = (FT_Int)dict->cid_supplement;
}
}
Fail:
return error;
}
static FT_Error
cff_get_is_cid( CFF_Face face,
FT_Bool *is_cid )
{
FT_Error error = CFF_Err_Ok;
CFF_Font cff = (CFF_Font)face->extra.data;
*is_cid = 0;
if ( cff )
{
CFF_FontRecDict dict = &cff->top_font.font_dict;
if ( dict->cid_registry != 0xFFFFU )
*is_cid = 1;
}
return error;
}
static FT_Error
cff_get_cid_from_glyph_index( CFF_Face face,
FT_UInt glyph_index,
FT_UInt *cid )
{
FT_Error error = CFF_Err_Ok;
CFF_Font cff;
cff = (CFF_Font)face->extra.data;
if ( cff )
{
FT_UInt c;
CFF_FontRecDict dict = &cff->top_font.font_dict;
if ( dict->cid_registry == 0xFFFFU )
{
error = CFF_Err_Invalid_Argument;
goto Fail;
}
if ( glyph_index > cff->num_glyphs )
{
error = CFF_Err_Invalid_Argument;
goto Fail;
}
c = cff->charset.sids[glyph_index];
if ( cid )
*cid = c;
}
Fail:
return error;
}
FT_DEFINE_SERVICE_CIDREC(cff_service_cid_info,
(FT_CID_GetRegistryOrderingSupplementFunc)cff_get_ros,
(FT_CID_GetIsInternallyCIDKeyedFunc) cff_get_is_cid,
(FT_CID_GetCIDFromGlyphIndexFunc) cff_get_cid_from_glyph_index
)
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** D R I V E R I N T E R F A C E ****/
/**** ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
FT_DEFINE_SERVICEDESCREC6(cff_services,
FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_CFF,
FT_SERVICE_ID_POSTSCRIPT_INFO, &FT_CFF_SERVICE_PS_INFO_GET,
FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_CFF_SERVICE_PS_NAME_GET,
FT_SERVICE_ID_GLYPH_DICT, &FT_CFF_SERVICE_GLYPH_DICT_GET,
FT_SERVICE_ID_TT_CMAP, &FT_CFF_SERVICE_GET_CMAP_INFO_GET,
FT_SERVICE_ID_CID, &FT_CFF_SERVICE_CID_INFO_GET
)
#else
FT_DEFINE_SERVICEDESCREC5(cff_services,
FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_CFF,
FT_SERVICE_ID_POSTSCRIPT_INFO, &FT_CFF_SERVICE_PS_INFO_GET,
FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_CFF_SERVICE_PS_NAME_GET,
FT_SERVICE_ID_TT_CMAP, &FT_CFF_SERVICE_GET_CMAP_INFO_GET,
FT_SERVICE_ID_CID, &FT_CFF_SERVICE_CID_INFO_GET
)
#endif
FT_CALLBACK_DEF( FT_Module_Interface )
cff_get_interface( FT_Module driver, /* CFF_Driver */
const char* module_interface )
{
FT_Module sfnt;
FT_Module_Interface result;
result = ft_service_list_lookup( FT_CFF_SERVICES_GET, module_interface );
if ( result != NULL )
return result;
if ( !driver )
return NULL;
/* we pass our request to the `sfnt' module */
sfnt = FT_Get_Module( driver->library, "sfnt" );
return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0;
}
/* The FT_DriverInterface structure is defined in ftdriver.h. */
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
#define CFF_SIZE_SELECT cff_size_select
#else
#define CFF_SIZE_SELECT 0
#endif
FT_DEFINE_DRIVER(cff_driver_class,
FT_MODULE_FONT_DRIVER |
FT_MODULE_DRIVER_SCALABLE |
FT_MODULE_DRIVER_HAS_HINTER,
sizeof( CFF_DriverRec ),
"cff",
0x10000L,
0x20000L,
0, /* module-specific interface */
cff_driver_init,
cff_driver_done,
cff_get_interface,
/* now the specific driver fields */
sizeof( TT_FaceRec ),
sizeof( CFF_SizeRec ),
sizeof( CFF_GlyphSlotRec ),
cff_face_init,
cff_face_done,
cff_size_init,
cff_size_done,
cff_slot_init,
cff_slot_done,
ft_stub_set_char_sizes, /* FT_CONFIG_OPTION_OLD_INTERNALS */
ft_stub_set_pixel_sizes, /* FT_CONFIG_OPTION_OLD_INTERNALS */
Load_Glyph,
cff_get_kerning,
0, /* FT_Face_AttachFunc */
cff_get_advances, /* FT_Face_GetAdvancesFunc */
cff_size_request,
CFF_SIZE_SELECT
)
/* END */
+38
View File
@@ -0,0 +1,38 @@
/***************************************************************************/
/* */
/* cffdrivr.h */
/* */
/* High-level OpenType driver interface (specification). */
/* */
/* Copyright 1996-2001, 2002 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. */
/* */
/***************************************************************************/
#ifndef __CFFDRIVER_H__
#define __CFFDRIVER_H__
#include <ft2build.h>
#include FT_INTERNAL_DRIVER_H
FT_BEGIN_HEADER
FT_DECLARE_DRIVER( cff_driver_class )
FT_END_HEADER
#endif /* __CFFDRIVER_H__ */
/* END */
+41
View File
@@ -0,0 +1,41 @@
/***************************************************************************/
/* */
/* cfferrs.h */
/* */
/* CFF error codes (specification only). */
/* */
/* Copyright 2001 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. */
/* */
/***************************************************************************/
/*************************************************************************/
/* */
/* This file is used to define the CFF error enumeration constants. */
/* */
/*************************************************************************/
#ifndef __CFFERRS_H__
#define __CFFERRS_H__
#include FT_MODULE_ERRORS_H
#undef __FTERRORS_H__
#define FT_ERR_PREFIX CFF_Err_
#define FT_ERR_BASE FT_Mod_Err_CFF
#include FT_ERRORS_H
#endif /* __CFFERRS_H__ */
/* END */
File diff suppressed because it is too large Load Diff
+201
View File
@@ -0,0 +1,201 @@
/***************************************************************************/
/* */
/* cffgload.h */
/* */
/* OpenType Glyph Loader (specification). */
/* */
/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009 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. */
/* */
/***************************************************************************/
#ifndef __CFFGLOAD_H__
#define __CFFGLOAD_H__
#include <ft2build.h>
#include FT_FREETYPE_H
#include "cffobjs.h"
FT_BEGIN_HEADER
#define CFF_MAX_OPERANDS 48
#define CFF_MAX_SUBRS_CALLS 32
#define CFF_MAX_TRANS_ELEMENTS 32
/*************************************************************************/
/* */
/* <Structure> */
/* CFF_Builder */
/* */
/* <Description> */
/* A structure used during glyph loading to store its outline. */
/* */
/* <Fields> */
/* memory :: The current memory object. */
/* */
/* face :: The current face object. */
/* */
/* glyph :: The current glyph slot. */
/* */
/* loader :: The current glyph loader. */
/* */
/* base :: The base glyph outline. */
/* */
/* current :: The current glyph outline. */
/* */
/* pos_x :: The horizontal translation (if composite glyph). */
/* */
/* pos_y :: The vertical translation (if composite glyph). */
/* */
/* left_bearing :: The left side bearing point. */
/* */
/* advance :: The horizontal advance vector. */
/* */
/* bbox :: Unused. */
/* */
/* path_begun :: A flag which indicates that a new path has begun. */
/* */
/* load_points :: If this flag is not set, no points are loaded. */
/* */
/* no_recurse :: Set but not used. */
/* */
/* metrics_only :: A boolean indicating that we only want to compute */
/* the metrics of a given glyph, not load all of its */
/* points. */
/* */
/* hints_funcs :: Auxiliary pointer for hinting. */
/* */
/* hints_globals :: Auxiliary pointer for hinting. */
/* */
typedef struct CFF_Builder_
{
FT_Memory memory;
TT_Face face;
CFF_GlyphSlot glyph;
FT_GlyphLoader loader;
FT_Outline* base;
FT_Outline* current;
FT_Pos pos_x;
FT_Pos pos_y;
FT_Vector left_bearing;
FT_Vector advance;
FT_BBox bbox; /* bounding box */
FT_Bool path_begun;
FT_Bool load_points;
FT_Bool no_recurse;
FT_Bool metrics_only;
void* hints_funcs; /* hinter-specific */
void* hints_globals; /* hinter-specific */
} CFF_Builder;
/* execution context charstring zone */
typedef struct CFF_Decoder_Zone_
{
FT_Byte* base;
FT_Byte* limit;
FT_Byte* cursor;
} CFF_Decoder_Zone;
typedef struct CFF_Decoder_
{
CFF_Builder builder;
CFF_Font cff;
FT_Fixed stack[CFF_MAX_OPERANDS + 1];
FT_Fixed* top;
CFF_Decoder_Zone zones[CFF_MAX_SUBRS_CALLS + 1];
CFF_Decoder_Zone* zone;
FT_Int flex_state;
FT_Int num_flex_vectors;
FT_Vector flex_vectors[7];
FT_Pos glyph_width;
FT_Pos nominal_width;
FT_Bool read_width;
FT_Bool width_only;
FT_Int num_hints;
FT_Fixed buildchar[CFF_MAX_TRANS_ELEMENTS];
FT_UInt num_locals;
FT_UInt num_globals;
FT_Int locals_bias;
FT_Int globals_bias;
FT_Byte** locals;
FT_Byte** globals;
FT_Byte** glyph_names; /* for pure CFF fonts only */
FT_UInt num_glyphs; /* number of glyphs in font */
FT_Render_Mode hint_mode;
FT_Bool seac;
} CFF_Decoder;
FT_LOCAL( void )
cff_decoder_init( CFF_Decoder* decoder,
TT_Face face,
CFF_Size size,
CFF_GlyphSlot slot,
FT_Bool hinting,
FT_Render_Mode hint_mode );
FT_LOCAL( FT_Error )
cff_decoder_prepare( CFF_Decoder* decoder,
CFF_Size size,
FT_UInt glyph_index );
#if 0 /* unused until we support pure CFF fonts */
/* Compute the maximum advance width of a font through quick parsing */
FT_LOCAL( FT_Error )
cff_compute_max_advance( TT_Face face,
FT_Int* max_advance );
#endif /* 0 */
FT_LOCAL( FT_Error )
cff_decoder_parse_charstrings( CFF_Decoder* decoder,
FT_Byte* charstring_base,
FT_ULong charstring_len );
FT_LOCAL( FT_Error )
cff_slot_load( CFF_GlyphSlot glyph,
CFF_Size size,
FT_UInt glyph_index,
FT_Int32 load_flags );
FT_END_HEADER
#endif /* __CFFGLOAD_H__ */
/* END */
File diff suppressed because it is too large Load Diff
+83
View File
@@ -0,0 +1,83 @@
/***************************************************************************/
/* */
/* cffload.h */
/* */
/* OpenType & CFF data/program tables loader (specification). */
/* */
/* Copyright 1996-2001, 2002, 2003, 2007, 2008, 2010 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. */
/* */
/***************************************************************************/
#ifndef __CFFLOAD_H__
#define __CFFLOAD_H__
#include <ft2build.h>
#include "cfftypes.h"
FT_BEGIN_HEADER
FT_LOCAL( FT_UShort )
cff_get_standard_encoding( FT_UInt charcode );
FT_LOCAL( FT_String* )
cff_index_get_string( CFF_Font font,
FT_UInt element );
FT_LOCAL( FT_String* )
cff_index_get_sid_string( CFF_Font font,
FT_UInt sid );
FT_LOCAL( FT_Error )
cff_index_access_element( CFF_Index idx,
FT_UInt element,
FT_Byte** pbytes,
FT_ULong* pbyte_len );
FT_LOCAL( void )
cff_index_forget_element( CFF_Index idx,
FT_Byte** pbytes );
FT_LOCAL( FT_String* )
cff_index_get_name( CFF_Font font,
FT_UInt element );
FT_LOCAL( FT_UInt )
cff_charset_cid_to_gindex( CFF_Charset charset,
FT_UInt cid );
FT_LOCAL( FT_Error )
cff_font_load( FT_Library library,
FT_Stream stream,
FT_Int face_index,
CFF_Font font,
FT_Bool pure_cff );
FT_LOCAL( void )
cff_font_done( CFF_Font font );
FT_LOCAL( FT_Byte )
cff_fd_select_get( CFF_FDSelect fdselect,
FT_UInt glyph_index );
FT_END_HEADER
#endif /* __CFFLOAD_H__ */
/* END */
File diff suppressed because it is too large Load Diff
+181
View File
@@ -0,0 +1,181 @@
/***************************************************************************/
/* */
/* cffobjs.h */
/* */
/* OpenType objects manager (specification). */
/* */
/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007, 2008 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. */
/* */
/***************************************************************************/
#ifndef __CFFOBJS_H__
#define __CFFOBJS_H__
#include <ft2build.h>
#include FT_INTERNAL_OBJECTS_H
#include "cfftypes.h"
#include FT_INTERNAL_TRUETYPE_TYPES_H
#include FT_SERVICE_POSTSCRIPT_CMAPS_H
#include FT_INTERNAL_POSTSCRIPT_HINTS_H
FT_BEGIN_HEADER
/*************************************************************************/
/* */
/* <Type> */
/* CFF_Driver */
/* */
/* <Description> */
/* A handle to an OpenType driver object. */
/* */
typedef struct CFF_DriverRec_* CFF_Driver;
typedef TT_Face CFF_Face;
/*************************************************************************/
/* */
/* <Type> */
/* CFF_Size */
/* */
/* <Description> */
/* A handle to an OpenType size object. */
/* */
typedef struct CFF_SizeRec_
{
FT_SizeRec root;
FT_ULong strike_index; /* 0xFFFFFFFF to indicate invalid */
} CFF_SizeRec, *CFF_Size;
/*************************************************************************/
/* */
/* <Type> */
/* CFF_GlyphSlot */
/* */
/* <Description> */
/* A handle to an OpenType glyph slot object. */
/* */
typedef struct CFF_GlyphSlotRec_
{
FT_GlyphSlotRec root;
FT_Bool hint;
FT_Bool scaled;
FT_Fixed x_scale;
FT_Fixed y_scale;
} CFF_GlyphSlotRec, *CFF_GlyphSlot;
/*************************************************************************/
/* */
/* <Type> */
/* CFF_Internal */
/* */
/* <Description> */
/* The interface to the `internal' field of `FT_Size'. */
/* */
typedef struct CFF_InternalRec_
{
PSH_Globals topfont;
PSH_Globals subfonts[CFF_MAX_CID_FONTS];
} CFF_InternalRec, *CFF_Internal;
/*************************************************************************/
/* */
/* Subglyph transformation record. */
/* */
typedef struct CFF_Transform_
{
FT_Fixed xx, xy; /* transformation matrix coefficients */
FT_Fixed yx, yy;
FT_F26Dot6 ox, oy; /* offsets */
} CFF_Transform;
/***********************************************************************/
/* */
/* TrueType driver class. */
/* */
typedef struct CFF_DriverRec_
{
FT_DriverRec root;
void* extension_component;
} CFF_DriverRec;
FT_LOCAL( FT_Error )
cff_size_init( FT_Size size ); /* CFF_Size */
FT_LOCAL( void )
cff_size_done( FT_Size size ); /* CFF_Size */
FT_LOCAL( FT_Error )
cff_size_request( FT_Size size,
FT_Size_Request req );
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
FT_LOCAL( FT_Error )
cff_size_select( FT_Size size,
FT_ULong strike_index );
#endif
FT_LOCAL( void )
cff_slot_done( FT_GlyphSlot slot );
FT_LOCAL( FT_Error )
cff_slot_init( FT_GlyphSlot slot );
/*************************************************************************/
/* */
/* Face functions */
/* */
FT_LOCAL( FT_Error )
cff_face_init( FT_Stream stream,
FT_Face face, /* CFF_Face */
FT_Int face_index,
FT_Int num_params,
FT_Parameter* params );
FT_LOCAL( void )
cff_face_done( FT_Face face ); /* CFF_Face */
/*************************************************************************/
/* */
/* Driver functions */
/* */
FT_LOCAL( FT_Error )
cff_driver_init( FT_Module module );
FT_LOCAL( void )
cff_driver_done( FT_Module module );
FT_END_HEADER
#endif /* __CFFOBJS_H__ */
/* END */
+924
View File
@@ -0,0 +1,924 @@
/***************************************************************************/
/* */
/* cffparse.c */
/* */
/* CFF token stream parser (body) */
/* */
/* Copyright 1996-2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010 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 "cffparse.h"
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_DEBUG_H
#include "cfferrs.h"
#include "cffpic.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_cffparse
FT_LOCAL_DEF( void )
cff_parser_init( CFF_Parser parser,
FT_UInt code,
void* object,
FT_Library library)
{
FT_MEM_ZERO( parser, sizeof ( *parser ) );
parser->top = parser->stack;
parser->object_code = code;
parser->object = object;
parser->library = library;
}
/* read an integer */
static FT_Long
cff_parse_integer( FT_Byte* start,
FT_Byte* limit )
{
FT_Byte* p = start;
FT_Int v = *p++;
FT_Long val = 0;
if ( v == 28 )
{
if ( p + 2 > limit )
goto Bad;
val = (FT_Short)( ( (FT_Int)p[0] << 8 ) | p[1] );
p += 2;
}
else if ( v == 29 )
{
if ( p + 4 > limit )
goto Bad;
val = ( (FT_Long)p[0] << 24 ) |
( (FT_Long)p[1] << 16 ) |
( (FT_Long)p[2] << 8 ) |
p[3];
p += 4;
}
else if ( v < 247 )
{
val = v - 139;
}
else if ( v < 251 )
{
if ( p + 1 > limit )
goto Bad;
val = ( v - 247 ) * 256 + p[0] + 108;
p++;
}
else
{
if ( p + 1 > limit )
goto Bad;
val = -( v - 251 ) * 256 - p[0] - 108;
p++;
}
Exit:
return val;
Bad:
val = 0;
goto Exit;
}
static const FT_Long power_tens[] =
{
1L,
10L,
100L,
1000L,
10000L,
100000L,
1000000L,
10000000L,
100000000L,
1000000000L
};
/* read a real */
static FT_Fixed
cff_parse_real( FT_Byte* start,
FT_Byte* limit,
FT_Long power_ten,
FT_Long* scaling )
{
FT_Byte* p = start;
FT_UInt nib;
FT_UInt phase;
FT_Long result, number, exponent;
FT_Int sign = 0, exponent_sign = 0;
FT_Long exponent_add, integer_length, fraction_length;
if ( scaling )
*scaling = 0;
result = 0;
number = 0;
exponent = 0;
exponent_add = 0;
integer_length = 0;
fraction_length = 0;
/* First of all, read the integer part. */
phase = 4;
for (;;)
{
/* If we entered this iteration with phase == 4, we need to */
/* read a new byte. This also skips past the initial 0x1E. */
if ( phase )
{
p++;
/* Make sure we don't read past the end. */
if ( p >= limit )
goto Exit;
}
/* Get the nibble. */
nib = ( p[0] >> phase ) & 0xF;
phase = 4 - phase;
if ( nib == 0xE )
sign = 1;
else if ( nib > 9 )
break;
else
{
/* Increase exponent if we can't add the digit. */
if ( number >= 0xCCCCCCCL )
exponent_add++;
/* Skip leading zeros. */
else if ( nib || number )
{
integer_length++;
number = number * 10 + nib;
}
}
}
/* Read fraction part, if any. */
if ( nib == 0xa )
for (;;)
{
/* If we entered this iteration with phase == 4, we need */
/* to read a new byte. */
if ( phase )
{
p++;
/* Make sure we don't read past the end. */
if ( p >= limit )
goto Exit;
}
/* Get the nibble. */
nib = ( p[0] >> phase ) & 0xF;
phase = 4 - phase;
if ( nib >= 10 )
break;
/* Skip leading zeros if possible. */
if ( !nib && !number )
exponent_add--;
/* Only add digit if we don't overflow. */
else if ( number < 0xCCCCCCCL && fraction_length < 9 )
{
fraction_length++;
number = number * 10 + nib;
}
}
/* Read exponent, if any. */
if ( nib == 12 )
{
exponent_sign = 1;
nib = 11;
}
if ( nib == 11 )
{
for (;;)
{
/* If we entered this iteration with phase == 4, */
/* we need to read a new byte. */
if ( phase )
{
p++;
/* Make sure we don't read past the end. */
if ( p >= limit )
goto Exit;
}
/* Get the nibble. */
nib = ( p[0] >> phase ) & 0xF;
phase = 4 - phase;
if ( nib >= 10 )
break;
exponent = exponent * 10 + nib;
/* Arbitrarily limit exponent. */
if ( exponent > 1000 )
goto Exit;
}
if ( exponent_sign )
exponent = -exponent;
}
/* We don't check `power_ten' and `exponent_add'. */
exponent += power_ten + exponent_add;
if ( scaling )
{
/* Only use `fraction_length'. */
fraction_length += integer_length;
exponent += integer_length;
if ( fraction_length <= 5 )
{
if ( number > 0x7FFFL )
{
result = FT_DivFix( number, 10 );
*scaling = exponent - fraction_length + 1;
}
else
{
if ( exponent > 0 )
{
FT_Long new_fraction_length, shift;
/* Make `scaling' as small as possible. */
new_fraction_length = FT_MIN( exponent, 5 );
exponent -= new_fraction_length;
shift = new_fraction_length - fraction_length;
number *= power_tens[shift];
if ( number > 0x7FFFL )
{
number /= 10;
exponent += 1;
}
}
else
exponent -= fraction_length;
result = number << 16;
*scaling = exponent;
}
}
else
{
if ( ( number / power_tens[fraction_length - 5] ) > 0x7FFFL )
{
result = FT_DivFix( number, power_tens[fraction_length - 4] );
*scaling = exponent - 4;
}
else
{
result = FT_DivFix( number, power_tens[fraction_length - 5] );
*scaling = exponent - 5;
}
}
}
else
{
integer_length += exponent;
fraction_length -= exponent;
/* Check for overflow and underflow. */
if ( FT_ABS( integer_length ) > 5 )
goto Exit;
/* Remove non-significant digits. */
if ( integer_length < 0 )
{
number /= power_tens[-integer_length];
fraction_length += integer_length;
}
/* this can only happen if exponent was non-zero */
if ( fraction_length == 10 )
{
number /= 10;
fraction_length -= 1;
}
/* Convert into 16.16 format. */
if ( fraction_length > 0 )
{
if ( ( number / power_tens[fraction_length] ) > 0x7FFFL )
goto Exit;
result = FT_DivFix( number, power_tens[fraction_length] );
}
else
{
number *= power_tens[-fraction_length];
if ( number > 0x7FFFL )
goto Exit;
result = number << 16;
}
}
if ( sign )
result = -result;
Exit:
return result;
}
/* read a number, either integer or real */
static FT_Long
cff_parse_num( FT_Byte** d )
{
return **d == 30 ? ( cff_parse_real( d[0], d[1], 0, NULL ) >> 16 )
: cff_parse_integer( d[0], d[1] );
}
/* read a floating point number, either integer or real */
static FT_Fixed
cff_parse_fixed( FT_Byte** d )
{
return **d == 30 ? cff_parse_real( d[0], d[1], 0, NULL )
: cff_parse_integer( d[0], d[1] ) << 16;
}
/* read a floating point number, either integer or real, */
/* but return `10^scaling' times the number read in */
static FT_Fixed
cff_parse_fixed_scaled( FT_Byte** d,
FT_Long scaling )
{
return **d == 30 ? cff_parse_real( d[0], d[1], scaling, NULL )
: ( cff_parse_integer( d[0], d[1] ) *
power_tens[scaling] ) << 16;
}
/* read a floating point number, either integer or real, */
/* and return it as precise as possible -- `scaling' returns */
/* the scaling factor (as a power of 10) */
static FT_Fixed
cff_parse_fixed_dynamic( FT_Byte** d,
FT_Long* scaling )
{
FT_ASSERT( scaling );
if ( **d == 30 )
return cff_parse_real( d[0], d[1], 0, scaling );
else
{
FT_Long number;
FT_Int integer_length;
number = cff_parse_integer( d[0], d[1] );
if ( number > 0x7FFFL )
{
for ( integer_length = 5; integer_length < 10; integer_length++ )
if ( number < power_tens[integer_length] )
break;
if ( ( number / power_tens[integer_length - 5] ) > 0x7FFFL )
{
*scaling = integer_length - 4;
return FT_DivFix( number, power_tens[integer_length - 4] );
}
else
{
*scaling = integer_length - 5;
return FT_DivFix( number, power_tens[integer_length - 5] );
}
}
else
{
*scaling = 0;
return number << 16;
}
}
}
static FT_Error
cff_parse_font_matrix( CFF_Parser parser )
{
CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
FT_Matrix* matrix = &dict->font_matrix;
FT_Vector* offset = &dict->font_offset;
FT_ULong* upm = &dict->units_per_em;
FT_Byte** data = parser->stack;
FT_Error error = CFF_Err_Stack_Underflow;
if ( parser->top >= parser->stack + 6 )
{
FT_Long scaling;
error = CFF_Err_Ok;
/* We expect a well-formed font matrix, this is, the matrix elements */
/* `xx' and `yy' are of approximately the same magnitude. To avoid */
/* loss of precision, we use the magnitude of element `xx' to scale */
/* all other elements. The scaling factor is then contained in the */
/* `units_per_em' value. */
matrix->xx = cff_parse_fixed_dynamic( data++, &scaling );
scaling = -scaling;
if ( scaling < 0 || scaling > 9 )
{
/* Return default matrix in case of unlikely values. */
matrix->xx = 0x10000L;
matrix->yx = 0;
matrix->yx = 0;
matrix->yy = 0x10000L;
offset->x = 0;
offset->y = 0;
*upm = 1;
goto Exit;
}
matrix->yx = cff_parse_fixed_scaled( data++, scaling );
matrix->xy = cff_parse_fixed_scaled( data++, scaling );
matrix->yy = cff_parse_fixed_scaled( data++, scaling );
offset->x = cff_parse_fixed_scaled( data++, scaling );
offset->y = cff_parse_fixed_scaled( data, scaling );
*upm = power_tens[scaling];
}
Exit:
return error;
}
static FT_Error
cff_parse_font_bbox( CFF_Parser parser )
{
CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
FT_BBox* bbox = &dict->font_bbox;
FT_Byte** data = parser->stack;
FT_Error error;
error = CFF_Err_Stack_Underflow;
if ( parser->top >= parser->stack + 4 )
{
bbox->xMin = FT_RoundFix( cff_parse_fixed( data++ ) );
bbox->yMin = FT_RoundFix( cff_parse_fixed( data++ ) );
bbox->xMax = FT_RoundFix( cff_parse_fixed( data++ ) );
bbox->yMax = FT_RoundFix( cff_parse_fixed( data ) );
error = CFF_Err_Ok;
}
return error;
}
static FT_Error
cff_parse_private_dict( CFF_Parser parser )
{
CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
FT_Byte** data = parser->stack;
FT_Error error;
error = CFF_Err_Stack_Underflow;
if ( parser->top >= parser->stack + 2 )
{
dict->private_size = cff_parse_num( data++ );
dict->private_offset = cff_parse_num( data );
error = CFF_Err_Ok;
}
return error;
}
static FT_Error
cff_parse_cid_ros( CFF_Parser parser )
{
CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
FT_Byte** data = parser->stack;
FT_Error error;
error = CFF_Err_Stack_Underflow;
if ( parser->top >= parser->stack + 3 )
{
dict->cid_registry = (FT_UInt)cff_parse_num ( data++ );
dict->cid_ordering = (FT_UInt)cff_parse_num ( data++ );
if ( **data == 30 )
FT_TRACE1(( "cff_parse_cid_ros: real supplement is rounded\n" ));
dict->cid_supplement = cff_parse_num( data );
if ( dict->cid_supplement < 0 )
FT_TRACE1(( "cff_parse_cid_ros: negative supplement %d is found\n",
dict->cid_supplement ));
error = CFF_Err_Ok;
}
return error;
}
#define CFF_FIELD_NUM( code, name ) \
CFF_FIELD( code, name, cff_kind_num )
#define CFF_FIELD_FIXED( code, name ) \
CFF_FIELD( code, name, cff_kind_fixed )
#define CFF_FIELD_FIXED_1000( code, name ) \
CFF_FIELD( code, name, cff_kind_fixed_thousand )
#define CFF_FIELD_STRING( code, name ) \
CFF_FIELD( code, name, cff_kind_string )
#define CFF_FIELD_BOOL( code, name ) \
CFF_FIELD( code, name, cff_kind_bool )
#define CFF_FIELD_DELTA( code, name, max ) \
CFF_FIELD( code, name, cff_kind_delta )
#define CFFCODE_TOPDICT 0x1000
#define CFFCODE_PRIVATE 0x2000
#ifndef FT_CONFIG_OPTION_PIC
#define CFF_FIELD_CALLBACK( code, name ) \
{ \
cff_kind_callback, \
code | CFFCODE, \
0, 0, \
cff_parse_ ## name, \
0, 0 \
},
#undef CFF_FIELD
#define CFF_FIELD( code, name, kind ) \
{ \
kind, \
code | CFFCODE, \
FT_FIELD_OFFSET( name ), \
FT_FIELD_SIZE( name ), \
0, 0, 0 \
},
#undef CFF_FIELD_DELTA
#define CFF_FIELD_DELTA( code, name, max ) \
{ \
cff_kind_delta, \
code | CFFCODE, \
FT_FIELD_OFFSET( name ), \
FT_FIELD_SIZE_DELTA( name ), \
0, \
max, \
FT_FIELD_OFFSET( num_ ## name ) \
},
static const CFF_Field_Handler cff_field_handlers[] =
{
#include "cfftoken.h"
{ 0, 0, 0, 0, 0, 0, 0 }
};
#else /* FT_CONFIG_OPTION_PIC */
void FT_Destroy_Class_cff_field_handlers(FT_Library library, CFF_Field_Handler* clazz)
{
FT_Memory memory = library->memory;
if ( clazz )
FT_FREE( clazz );
}
FT_Error FT_Create_Class_cff_field_handlers(FT_Library library, CFF_Field_Handler** output_class)
{
CFF_Field_Handler* clazz;
FT_Error error;
FT_Memory memory = library->memory;
int i=0;
#undef CFF_FIELD
#undef CFF_FIELD_DELTA
#undef CFF_FIELD_CALLBACK
#define CFF_FIELD_CALLBACK( code, name ) i++;
#define CFF_FIELD( code, name, kind ) i++;
#define CFF_FIELD_DELTA( code, name, max ) i++;
#include "cfftoken.h"
i++;/*{ 0, 0, 0, 0, 0, 0, 0 }*/
if ( FT_ALLOC( clazz, sizeof(CFF_Field_Handler)*i ) )
return error;
i=0;
#undef CFF_FIELD
#undef CFF_FIELD_DELTA
#undef CFF_FIELD_CALLBACK
#define CFF_FIELD_CALLBACK( code_, name_ ) \
clazz[i].kind = cff_kind_callback; \
clazz[i].code = code_ | CFFCODE; \
clazz[i].offset = 0; \
clazz[i].size = 0; \
clazz[i].reader = cff_parse_ ## name_; \
clazz[i].array_max = 0; \
clazz[i].count_offset = 0; \
i++;
#undef CFF_FIELD
#define CFF_FIELD( code_, name_, kind_ ) \
clazz[i].kind = kind_; \
clazz[i].code = code_ | CFFCODE; \
clazz[i].offset = FT_FIELD_OFFSET( name_ ); \
clazz[i].size = FT_FIELD_SIZE( name_ ); \
clazz[i].reader = 0; \
clazz[i].array_max = 0; \
clazz[i].count_offset = 0; \
i++; \
#undef CFF_FIELD_DELTA
#define CFF_FIELD_DELTA( code_, name_, max_ ) \
clazz[i].kind = cff_kind_delta; \
clazz[i].code = code_ | CFFCODE; \
clazz[i].offset = FT_FIELD_OFFSET( name_ ); \
clazz[i].size = FT_FIELD_SIZE_DELTA( name_ ); \
clazz[i].reader = 0; \
clazz[i].array_max = max_; \
clazz[i].count_offset = FT_FIELD_OFFSET( num_ ## name_ ); \
i++;
#include "cfftoken.h"
clazz[i].kind = 0;
clazz[i].code = 0;
clazz[i].offset = 0;
clazz[i].size = 0;
clazz[i].reader = 0;
clazz[i].array_max = 0;
clazz[i].count_offset = 0;
*output_class = clazz;
return CFF_Err_Ok;
}
#endif /* FT_CONFIG_OPTION_PIC */
FT_LOCAL_DEF( FT_Error )
cff_parser_run( CFF_Parser parser,
FT_Byte* start,
FT_Byte* limit )
{
FT_Byte* p = start;
FT_Error error = CFF_Err_Ok;
FT_Library library = parser->library;
FT_UNUSED(library);
parser->top = parser->stack;
parser->start = start;
parser->limit = limit;
parser->cursor = start;
while ( p < limit )
{
FT_UInt v = *p;
if ( v >= 27 && v != 31 )
{
/* it's a number; we will push its position on the stack */
if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH )
goto Stack_Overflow;
*parser->top ++ = p;
/* now, skip it */
if ( v == 30 )
{
/* skip real number */
p++;
for (;;)
{
/* An unterminated floating point number at the */
/* end of a dictionary is invalid but harmless. */
if ( p >= limit )
goto Exit;
v = p[0] >> 4;
if ( v == 15 )
break;
v = p[0] & 0xF;
if ( v == 15 )
break;
p++;
}
}
else if ( v == 28 )
p += 2;
else if ( v == 29 )
p += 4;
else if ( v > 246 )
p += 1;
}
else
{
/* This is not a number, hence it's an operator. Compute its code */
/* and look for it in our current list. */
FT_UInt code;
FT_UInt num_args = (FT_UInt)
( parser->top - parser->stack );
const CFF_Field_Handler* field;
*parser->top = p;
code = v;
if ( v == 12 )
{
/* two byte operator */
p++;
if ( p >= limit )
goto Syntax_Error;
code = 0x100 | p[0];
}
code = code | parser->object_code;
for ( field = FT_CFF_FIELD_HANDLERS_GET; field->kind; field++ )
{
if ( field->code == (FT_Int)code )
{
/* we found our field's handler; read it */
FT_Long val;
FT_Byte* q = (FT_Byte*)parser->object + field->offset;
/* check that we have enough arguments -- except for */
/* delta encoded arrays, which can be empty */
if ( field->kind != cff_kind_delta && num_args < 1 )
goto Stack_Underflow;
switch ( field->kind )
{
case cff_kind_bool:
case cff_kind_string:
case cff_kind_num:
val = cff_parse_num( parser->stack );
goto Store_Number;
case cff_kind_fixed:
val = cff_parse_fixed( parser->stack );
goto Store_Number;
case cff_kind_fixed_thousand:
val = cff_parse_fixed_scaled( parser->stack, 3 );
Store_Number:
switch ( field->size )
{
case (8 / FT_CHAR_BIT):
*(FT_Byte*)q = (FT_Byte)val;
break;
case (16 / FT_CHAR_BIT):
*(FT_Short*)q = (FT_Short)val;
break;
case (32 / FT_CHAR_BIT):
*(FT_Int32*)q = (FT_Int)val;
break;
default: /* for 64-bit systems */
*(FT_Long*)q = val;
}
break;
case cff_kind_delta:
{
FT_Byte* qcount = (FT_Byte*)parser->object +
field->count_offset;
FT_Byte** data = parser->stack;
if ( num_args > field->array_max )
num_args = field->array_max;
/* store count */
*qcount = (FT_Byte)num_args;
val = 0;
while ( num_args > 0 )
{
val += cff_parse_num( data++ );
switch ( field->size )
{
case (8 / FT_CHAR_BIT):
*(FT_Byte*)q = (FT_Byte)val;
break;
case (16 / FT_CHAR_BIT):
*(FT_Short*)q = (FT_Short)val;
break;
case (32 / FT_CHAR_BIT):
*(FT_Int32*)q = (FT_Int)val;
break;
default: /* for 64-bit systems */
*(FT_Long*)q = val;
}
q += field->size;
num_args--;
}
}
break;
default: /* callback */
error = field->reader( parser );
if ( error )
goto Exit;
}
goto Found;
}
}
/* this is an unknown operator, or it is unsupported; */
/* we will ignore it for now. */
Found:
/* clear stack */
parser->top = parser->stack;
}
p++;
}
Exit:
return error;
Stack_Overflow:
error = CFF_Err_Invalid_Argument;
goto Exit;
Stack_Underflow:
error = CFF_Err_Invalid_Argument;
goto Exit;
Syntax_Error:
error = CFF_Err_Invalid_Argument;
goto Exit;
}
/* END */
+102
View File
@@ -0,0 +1,102 @@
/***************************************************************************/
/* */
/* cffparse.h */
/* */
/* CFF token stream parser (specification) */
/* */
/* Copyright 1996-2001, 2002, 2003 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. */
/* */
/***************************************************************************/
#ifndef __CFF_PARSE_H__
#define __CFF_PARSE_H__
#include <ft2build.h>
#include "cfftypes.h"
#include FT_INTERNAL_OBJECTS_H
FT_BEGIN_HEADER
#define CFF_MAX_STACK_DEPTH 96
#define CFF_CODE_TOPDICT 0x1000
#define CFF_CODE_PRIVATE 0x2000
typedef struct CFF_ParserRec_
{
FT_Library library;
FT_Byte* start;
FT_Byte* limit;
FT_Byte* cursor;
FT_Byte* stack[CFF_MAX_STACK_DEPTH + 1];
FT_Byte** top;
FT_UInt object_code;
void* object;
} CFF_ParserRec, *CFF_Parser;
FT_LOCAL( void )
cff_parser_init( CFF_Parser parser,
FT_UInt code,
void* object,
FT_Library library);
FT_LOCAL( FT_Error )
cff_parser_run( CFF_Parser parser,
FT_Byte* start,
FT_Byte* limit );
enum
{
cff_kind_none = 0,
cff_kind_num,
cff_kind_fixed,
cff_kind_fixed_thousand,
cff_kind_string,
cff_kind_bool,
cff_kind_delta,
cff_kind_callback,
cff_kind_max /* do not remove */
};
/* now generate handlers for the most simple fields */
typedef FT_Error (*CFF_Field_Reader)( CFF_Parser parser );
typedef struct CFF_Field_Handler_
{
int kind;
int code;
FT_UInt offset;
FT_Byte size;
CFF_Field_Reader reader;
FT_UInt array_max;
FT_UInt count_offset;
} CFF_Field_Handler;
FT_END_HEADER
#endif /* __CFF_PARSE_H__ */
/* END */
+101
View File
@@ -0,0 +1,101 @@
/***************************************************************************/
/* */
/* cffpic.c */
/* */
/* The FreeType position independent code services for cff module. */
/* */
/* Copyright 2009, 2010 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* 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_FREETYPE_H
#include FT_INTERNAL_OBJECTS_H
#include "cffpic.h"
#ifdef FT_CONFIG_OPTION_PIC
/* forward declaration of PIC init functions from cffdrivr.c */
FT_Error FT_Create_Class_cff_services( FT_Library, FT_ServiceDescRec**);
void FT_Destroy_Class_cff_services( FT_Library, FT_ServiceDescRec*);
void FT_Init_Class_cff_service_ps_info( FT_Library, FT_Service_PsInfoRec*);
void FT_Init_Class_cff_service_glyph_dict( FT_Library, FT_Service_GlyphDictRec*);
void FT_Init_Class_cff_service_ps_name( FT_Library, FT_Service_PsFontNameRec*);
void FT_Init_Class_cff_service_get_cmap_info( FT_Library, FT_Service_TTCMapsRec*);
void FT_Init_Class_cff_service_cid_info( FT_Library, FT_Service_CIDRec*);
/* forward declaration of PIC init functions from cffparse.c */
FT_Error FT_Create_Class_cff_field_handlers( FT_Library, CFF_Field_Handler**);
void FT_Destroy_Class_cff_field_handlers( FT_Library, CFF_Field_Handler*);
/* forward declaration of PIC init functions from cffcmap.c */
void FT_Init_Class_cff_cmap_encoding_class_rec( FT_Library, FT_CMap_ClassRec*);
void FT_Init_Class_cff_cmap_unicode_class_rec( FT_Library, FT_CMap_ClassRec*);
void
cff_driver_class_pic_free( FT_Library library )
{
FT_PIC_Container* pic_container = &library->pic_container;
FT_Memory memory = library->memory;
if ( pic_container->cff )
{
CffModulePIC* container = (CffModulePIC*)pic_container->cff;
if(container->cff_services)
FT_Destroy_Class_cff_services(library, container->cff_services);
container->cff_services = NULL;
if(container->cff_field_handlers)
FT_Destroy_Class_cff_field_handlers(library, container->cff_field_handlers);
container->cff_field_handlers = NULL;
FT_FREE( container );
pic_container->cff = NULL;
}
}
FT_Error
cff_driver_class_pic_init( FT_Library library )
{
FT_PIC_Container* pic_container = &library->pic_container;
FT_Error error = CFF_Err_Ok;
CffModulePIC* container;
FT_Memory memory = library->memory;
/* allocate pointer, clear and set global container pointer */
if ( FT_ALLOC ( container, sizeof ( *container ) ) )
return error;
FT_MEM_SET( container, 0, sizeof ( *container ) );
pic_container->cff = container;
/* initialize pointer table - this is how the module usually expects this data */
error = FT_Create_Class_cff_services(library, &container->cff_services);
if(error)
goto Exit;
error = FT_Create_Class_cff_field_handlers(library, &container->cff_field_handlers);
if(error)
goto Exit;
FT_Init_Class_cff_service_ps_info(library, &container->cff_service_ps_info);
FT_Init_Class_cff_service_glyph_dict(library, &container->cff_service_glyph_dict);
FT_Init_Class_cff_service_ps_name(library, &container->cff_service_ps_name);
FT_Init_Class_cff_service_get_cmap_info(library, &container->cff_service_get_cmap_info);
FT_Init_Class_cff_service_cid_info(library, &container->cff_service_cid_info);
FT_Init_Class_cff_cmap_encoding_class_rec(library, &container->cff_cmap_encoding_class_rec);
FT_Init_Class_cff_cmap_unicode_class_rec(library, &container->cff_cmap_unicode_class_rec);
Exit:
if(error)
cff_driver_class_pic_free(library);
return error;
}
#endif /* FT_CONFIG_OPTION_PIC */
/* END */
+80
View File
@@ -0,0 +1,80 @@
/***************************************************************************/
/* */
/* cffpic.h */
/* */
/* The FreeType position independent code services for cff module. */
/* */
/* Copyright 2009 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* 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. */
/* */
/***************************************************************************/
#ifndef __CFFPIC_H__
#define __CFFPIC_H__
FT_BEGIN_HEADER
#include FT_INTERNAL_PIC_H
#ifndef FT_CONFIG_OPTION_PIC
#define FT_CFF_SERVICE_PS_INFO_GET cff_service_ps_info
#define FT_CFF_SERVICE_GLYPH_DICT_GET cff_service_glyph_dict
#define FT_CFF_SERVICE_PS_NAME_GET cff_service_ps_name
#define FT_CFF_SERVICE_GET_CMAP_INFO_GET cff_service_get_cmap_info
#define FT_CFF_SERVICE_CID_INFO_GET cff_service_cid_info
#define FT_CFF_SERVICES_GET cff_services
#define FT_CFF_CMAP_ENCODING_CLASS_REC_GET cff_cmap_encoding_class_rec
#define FT_CFF_CMAP_UNICODE_CLASS_REC_GET cff_cmap_unicode_class_rec
#define FT_CFF_FIELD_HANDLERS_GET cff_field_handlers
#else /* FT_CONFIG_OPTION_PIC */
#include FT_SERVICE_GLYPH_DICT_H
#include "cffparse.h"
#include FT_SERVICE_POSTSCRIPT_INFO_H
#include FT_SERVICE_POSTSCRIPT_NAME_H
#include FT_SERVICE_TT_CMAP_H
#include FT_SERVICE_CID_H
typedef struct CffModulePIC_
{
FT_ServiceDescRec* cff_services;
CFF_Field_Handler* cff_field_handlers;
FT_Service_PsInfoRec cff_service_ps_info;
FT_Service_GlyphDictRec cff_service_glyph_dict;
FT_Service_PsFontNameRec cff_service_ps_name;
FT_Service_TTCMapsRec cff_service_get_cmap_info;
FT_Service_CIDRec cff_service_cid_info;
FT_CMap_ClassRec cff_cmap_encoding_class_rec;
FT_CMap_ClassRec cff_cmap_unicode_class_rec;
} CffModulePIC;
#define GET_PIC(lib) ((CffModulePIC*)((lib)->pic_container.cff))
#define FT_CFF_SERVICE_PS_INFO_GET (GET_PIC(library)->cff_service_ps_info)
#define FT_CFF_SERVICE_GLYPH_DICT_GET (GET_PIC(library)->cff_service_glyph_dict)
#define FT_CFF_SERVICE_PS_NAME_GET (GET_PIC(library)->cff_service_ps_name)
#define FT_CFF_SERVICE_GET_CMAP_INFO_GET (GET_PIC(library)->cff_service_get_cmap_info)
#define FT_CFF_SERVICE_CID_INFO_GET (GET_PIC(library)->cff_service_cid_info)
#define FT_CFF_SERVICES_GET (GET_PIC(library)->cff_services)
#define FT_CFF_CMAP_ENCODING_CLASS_REC_GET (GET_PIC(library)->cff_cmap_encoding_class_rec)
#define FT_CFF_CMAP_UNICODE_CLASS_REC_GET (GET_PIC(library)->cff_cmap_unicode_class_rec)
#define FT_CFF_FIELD_HANDLERS_GET (GET_PIC(library)->cff_field_handlers)
#endif /* FT_CONFIG_OPTION_PIC */
/* */
FT_END_HEADER
#endif /* __CFFPIC_H__ */
/* END */
+97
View File
@@ -0,0 +1,97 @@
/***************************************************************************/
/* */
/* cfftoken.h */
/* */
/* CFF token definitions (specification only). */
/* */
/* Copyright 1996-2001, 2002, 2003 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. */
/* */
/***************************************************************************/
#undef FT_STRUCTURE
#define FT_STRUCTURE CFF_FontRecDictRec
#undef CFFCODE
#define CFFCODE CFFCODE_TOPDICT
CFF_FIELD_STRING ( 0, version )
CFF_FIELD_STRING ( 1, notice )
CFF_FIELD_STRING ( 0x100, copyright )
CFF_FIELD_STRING ( 2, full_name )
CFF_FIELD_STRING ( 3, family_name )
CFF_FIELD_STRING ( 4, weight )
CFF_FIELD_BOOL ( 0x101, is_fixed_pitch )
CFF_FIELD_FIXED ( 0x102, italic_angle )
CFF_FIELD_FIXED ( 0x103, underline_position )
CFF_FIELD_FIXED ( 0x104, underline_thickness )
CFF_FIELD_NUM ( 0x105, paint_type )
CFF_FIELD_NUM ( 0x106, charstring_type )
CFF_FIELD_CALLBACK( 0x107, font_matrix )
CFF_FIELD_NUM ( 13, unique_id )
CFF_FIELD_CALLBACK( 5, font_bbox )
CFF_FIELD_NUM ( 0x108, stroke_width )
CFF_FIELD_NUM ( 15, charset_offset )
CFF_FIELD_NUM ( 16, encoding_offset )
CFF_FIELD_NUM ( 17, charstrings_offset )
CFF_FIELD_CALLBACK( 18, private_dict )
CFF_FIELD_NUM ( 0x114, synthetic_base )
CFF_FIELD_STRING ( 0x115, embedded_postscript )
#if 0
CFF_FIELD_STRING ( 0x116, base_font_name )
CFF_FIELD_DELTA ( 0x117, base_font_blend, 16 )
CFF_FIELD_CALLBACK( 0x118, multiple_master )
CFF_FIELD_CALLBACK( 0x119, blend_axis_types )
#endif
CFF_FIELD_CALLBACK( 0x11E, cid_ros )
CFF_FIELD_NUM ( 0x11F, cid_font_version )
CFF_FIELD_NUM ( 0x120, cid_font_revision )
CFF_FIELD_NUM ( 0x121, cid_font_type )
CFF_FIELD_NUM ( 0x122, cid_count )
CFF_FIELD_NUM ( 0x123, cid_uid_base )
CFF_FIELD_NUM ( 0x124, cid_fd_array_offset )
CFF_FIELD_NUM ( 0x125, cid_fd_select_offset )
CFF_FIELD_STRING ( 0x126, cid_font_name )
#if 0
CFF_FIELD_NUM ( 0x127, chameleon )
#endif
#undef FT_STRUCTURE
#define FT_STRUCTURE CFF_PrivateRec
#undef CFFCODE
#define CFFCODE CFFCODE_PRIVATE
CFF_FIELD_DELTA ( 6, blue_values, 14 )
CFF_FIELD_DELTA ( 7, other_blues, 10 )
CFF_FIELD_DELTA ( 8, family_blues, 14 )
CFF_FIELD_DELTA ( 9, family_other_blues, 10 )
CFF_FIELD_FIXED_1000( 0x109, blue_scale )
CFF_FIELD_NUM ( 0x10A, blue_shift )
CFF_FIELD_NUM ( 0x10B, blue_fuzz )
CFF_FIELD_NUM ( 10, standard_width )
CFF_FIELD_NUM ( 11, standard_height )
CFF_FIELD_DELTA ( 0x10C, snap_widths, 13 )
CFF_FIELD_DELTA ( 0x10D, snap_heights, 13 )
CFF_FIELD_BOOL ( 0x10E, force_bold )
CFF_FIELD_FIXED ( 0x10F, force_bold_threshold )
CFF_FIELD_NUM ( 0x110, lenIV )
CFF_FIELD_NUM ( 0x111, language_group )
CFF_FIELD_FIXED ( 0x112, expansion_factor )
CFF_FIELD_NUM ( 0x113, initial_random_seed )
CFF_FIELD_NUM ( 19, local_subrs_offset )
CFF_FIELD_NUM ( 20, default_width )
CFF_FIELD_NUM ( 21, nominal_width )
/* END */
+281
View File
@@ -0,0 +1,281 @@
/***************************************************************************/
/* */
/* cfftypes.h */
/* */
/* Basic OpenType/CFF type definitions and interface (specification */
/* only). */
/* */
/* Copyright 1996-2001, 2002, 2003, 2006, 2007, 2008, 2010 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. */
/* */
/***************************************************************************/
#ifndef __CFFTYPES_H__
#define __CFFTYPES_H__
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_TYPE1_TABLES_H
#include FT_INTERNAL_SERVICE_H
#include FT_SERVICE_POSTSCRIPT_CMAPS_H
#include FT_INTERNAL_POSTSCRIPT_HINTS_H
FT_BEGIN_HEADER
/*************************************************************************/
/* */
/* <Struct> */
/* CFF_IndexRec */
/* */
/* <Description> */
/* A structure used to model a CFF Index table. */
/* */
/* <Fields> */
/* stream :: The source input stream. */
/* */
/* start :: The position of the first index byte in the */
/* input stream. */
/* */
/* count :: The number of elements in the index. */
/* */
/* off_size :: The size in bytes of object offsets in index. */
/* */
/* data_offset :: The position of first data byte in the index's */
/* bytes. */
/* */
/* data_size :: The size of the data table in this index. */
/* */
/* offsets :: A table of element offsets in the index. Must be */
/* loaded explicitly. */
/* */
/* bytes :: If the index is loaded in memory, its bytes. */
/* */
typedef struct CFF_IndexRec_
{
FT_Stream stream;
FT_ULong start;
FT_UInt count;
FT_Byte off_size;
FT_ULong data_offset;
FT_ULong data_size;
FT_ULong* offsets;
FT_Byte* bytes;
} CFF_IndexRec, *CFF_Index;
typedef struct CFF_EncodingRec_
{
FT_UInt format;
FT_ULong offset;
FT_UInt count;
FT_UShort sids [256]; /* avoid dynamic allocations */
FT_UShort codes[256];
} CFF_EncodingRec, *CFF_Encoding;
typedef struct CFF_CharsetRec_
{
FT_UInt format;
FT_ULong offset;
FT_UShort* sids;
FT_UShort* cids; /* the inverse mapping of `sids'; only needed */
/* for CID-keyed fonts */
FT_UInt max_cid;
FT_UInt num_glyphs;
} CFF_CharsetRec, *CFF_Charset;
typedef struct CFF_FontRecDictRec_
{
FT_UInt version;
FT_UInt notice;
FT_UInt copyright;
FT_UInt full_name;
FT_UInt family_name;
FT_UInt weight;
FT_Bool is_fixed_pitch;
FT_Fixed italic_angle;
FT_Fixed underline_position;
FT_Fixed underline_thickness;
FT_Int paint_type;
FT_Int charstring_type;
FT_Matrix font_matrix;
FT_ULong units_per_em; /* temporarily used as scaling value also */
FT_Vector font_offset;
FT_ULong unique_id;
FT_BBox font_bbox;
FT_Pos stroke_width;
FT_ULong charset_offset;
FT_ULong encoding_offset;
FT_ULong charstrings_offset;
FT_ULong private_offset;
FT_ULong private_size;
FT_Long synthetic_base;
FT_UInt embedded_postscript;
/* these should only be used for the top-level font dictionary */
FT_UInt cid_registry;
FT_UInt cid_ordering;
FT_Long cid_supplement;
FT_Long cid_font_version;
FT_Long cid_font_revision;
FT_Long cid_font_type;
FT_ULong cid_count;
FT_ULong cid_uid_base;
FT_ULong cid_fd_array_offset;
FT_ULong cid_fd_select_offset;
FT_UInt cid_font_name;
} CFF_FontRecDictRec, *CFF_FontRecDict;
typedef struct CFF_PrivateRec_
{
FT_Byte num_blue_values;
FT_Byte num_other_blues;
FT_Byte num_family_blues;
FT_Byte num_family_other_blues;
FT_Pos blue_values[14];
FT_Pos other_blues[10];
FT_Pos family_blues[14];
FT_Pos family_other_blues[10];
FT_Fixed blue_scale;
FT_Pos blue_shift;
FT_Pos blue_fuzz;
FT_Pos standard_width;
FT_Pos standard_height;
FT_Byte num_snap_widths;
FT_Byte num_snap_heights;
FT_Pos snap_widths[13];
FT_Pos snap_heights[13];
FT_Bool force_bold;
FT_Fixed force_bold_threshold;
FT_Int lenIV;
FT_Int language_group;
FT_Fixed expansion_factor;
FT_Long initial_random_seed;
FT_ULong local_subrs_offset;
FT_Pos default_width;
FT_Pos nominal_width;
} CFF_PrivateRec, *CFF_Private;
typedef struct CFF_FDSelectRec_
{
FT_Byte format;
FT_UInt range_count;
/* that's the table, taken from the file `as is' */
FT_Byte* data;
FT_UInt data_size;
/* small cache for format 3 only */
FT_UInt cache_first;
FT_UInt cache_count;
FT_Byte cache_fd;
} CFF_FDSelectRec, *CFF_FDSelect;
/* A SubFont packs a font dict and a private dict together. They are */
/* needed to support CID-keyed CFF fonts. */
typedef struct CFF_SubFontRec_
{
CFF_FontRecDictRec font_dict;
CFF_PrivateRec private_dict;
CFF_IndexRec local_subrs_index;
FT_Byte** local_subrs; /* array of pointers into Local Subrs INDEX data */
} CFF_SubFontRec, *CFF_SubFont;
/* maximum number of sub-fonts in a CID-keyed file */
#define CFF_MAX_CID_FONTS 32
typedef struct CFF_FontRec_
{
FT_Stream stream;
FT_Memory memory;
FT_UInt num_faces;
FT_UInt num_glyphs;
FT_Byte version_major;
FT_Byte version_minor;
FT_Byte header_size;
FT_Byte absolute_offsize;
CFF_IndexRec name_index;
CFF_IndexRec top_dict_index;
CFF_IndexRec global_subrs_index;
CFF_EncodingRec encoding;
CFF_CharsetRec charset;
CFF_IndexRec charstrings_index;
CFF_IndexRec font_dict_index;
CFF_IndexRec private_index;
CFF_IndexRec local_subrs_index;
FT_String* font_name;
/* array of pointers into Global Subrs INDEX data */
FT_Byte** global_subrs;
/* array of pointers into String INDEX data stored at string_pool */
FT_UInt num_strings;
FT_Byte** strings;
FT_Byte* string_pool;
CFF_SubFontRec top_font;
FT_UInt num_subfonts;
CFF_SubFont subfonts[CFF_MAX_CID_FONTS];
CFF_FDSelectRec fd_select;
/* interface to PostScript hinter */
PSHinter_Service pshinter;
/* interface to Postscript Names service */
FT_Service_PsCMaps psnames;
/* since version 2.3.0 */
PS_FontInfoRec* font_info; /* font info dictionary */
/* since version 2.3.6 */
FT_String* registry;
FT_String* ordering;
} CFF_FontRec, *CFF_Font;
FT_END_HEADER
#endif /* __CFFTYPES_H__ */
/* END */
+23
View File
@@ -0,0 +1,23 @@
#
# FreeType 2 CFF module definition
#
# Copyright 1996-2000, 2006 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.
FTMODULE_H_COMMANDS += CFF_DRIVER
define CFF_DRIVER
$(OPEN_DRIVER) FT_Driver_ClassRec, cff_driver_class $(CLOSE_DRIVER)
$(ECHO_DRIVER)cff $(ECHO_DRIVER_DESC)OpenType fonts with extension *.otf$(ECHO_DRIVER_DONE)
endef
# EOF
+72
View File
@@ -0,0 +1,72 @@
#
# FreeType 2 OpenType/CFF driver configuration rules
#
# Copyright 1996-2000, 2001, 2003 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.
# OpenType driver directory
#
CFF_DIR := $(SRC_DIR)/cff
CFF_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(CFF_DIR))
# CFF driver sources (i.e., C files)
#
CFF_DRV_SRC := $(CFF_DIR)/cffobjs.c \
$(CFF_DIR)/cffload.c \
$(CFF_DIR)/cffgload.c \
$(CFF_DIR)/cffparse.c \
$(CFF_DIR)/cffcmap.c \
$(CFF_DIR)/cffdrivr.c
# CFF driver headers
#
CFF_DRV_H := $(CFF_DRV_SRC:%.c=%.h) \
$(CFF_DIR)/cfftoken.h \
$(CFF_DIR)/cfftypes.h \
$(CFF_DIR)/cfferrs.h
# CFF driver object(s)
#
# CFF_DRV_OBJ_M is used during `multi' builds
# CFF_DRV_OBJ_S is used during `single' builds
#
CFF_DRV_OBJ_M := $(CFF_DRV_SRC:$(CFF_DIR)/%.c=$(OBJ_DIR)/%.$O)
CFF_DRV_OBJ_S := $(OBJ_DIR)/cff.$O
# CFF driver source file for single build
#
CFF_DRV_SRC_S := $(CFF_DIR)/cff.c
# CFF driver - single object
#
$(CFF_DRV_OBJ_S): $(CFF_DRV_SRC_S) $(CFF_DRV_SRC) $(FREETYPE_H) $(CFF_DRV_H)
$(CFF_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(CFF_DRV_SRC_S))
# CFF driver - multiple objects
#
$(OBJ_DIR)/%.$O: $(CFF_DIR)/%.c $(FREETYPE_H) $(CFF_DRV_H)
$(CFF_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<)
# update main driver object lists
#
DRV_OBJS_S += $(CFF_DRV_OBJ_S)
DRV_OBJS_M += $(CFF_DRV_OBJ_M)
# EOF
@@ -0,0 +1,29 @@
# FreeType 2 src/pshinter Jamfile
#
# Copyright 2001, 2003 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.
SubDir FT2_TOP $(FT2_SRC_DIR) pshinter ;
{
local _sources ;
if $(FT2_MULTI)
{
_sources = pshrec pshglob pshalgo pshmod pshpic ;
}
else
{
_sources = pshinter ;
}
Library $(FT2_LIB) : $(_sources).c ;
}
# end of src/pshinter Jamfile
@@ -0,0 +1,23 @@
#
# FreeType 2 PSHinter module definition
#
# Copyright 1996-2001, 2006 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.
FTMODULE_H_COMMANDS += PSHINTER_MODULE
define PSHINTER_MODULE
$(OPEN_DRIVER) FT_Module_Class, pshinter_module_class $(CLOSE_DRIVER)
$(ECHO_DRIVER)pshinter $(ECHO_DRIVER_DESC)Postscript hinter module$(ECHO_DRIVER_DONE)
endef
# EOF
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,255 @@
/***************************************************************************/
/* */
/* pshalgo.h */
/* */
/* PostScript hinting algorithm (specification). */
/* */
/* Copyright 2001, 2002, 2003, 2008 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. */
/* */
/***************************************************************************/
#ifndef __PSHALGO_H__
#define __PSHALGO_H__
#include "pshrec.h"
#include "pshglob.h"
#include FT_TRIGONOMETRY_H
FT_BEGIN_HEADER
/* handle to Hint structure */
typedef struct PSH_HintRec_* PSH_Hint;
/* hint bit-flags */
typedef enum PSH_Hint_Flags_
{
PSH_HINT_GHOST = PS_HINT_FLAG_GHOST,
PSH_HINT_BOTTOM = PS_HINT_FLAG_BOTTOM,
PSH_HINT_ACTIVE = 4,
PSH_HINT_FITTED = 8
} PSH_Hint_Flags;
#define psh_hint_is_active( x ) ( ( (x)->flags & PSH_HINT_ACTIVE ) != 0 )
#define psh_hint_is_ghost( x ) ( ( (x)->flags & PSH_HINT_GHOST ) != 0 )
#define psh_hint_is_fitted( x ) ( ( (x)->flags & PSH_HINT_FITTED ) != 0 )
#define psh_hint_activate( x ) (x)->flags |= PSH_HINT_ACTIVE
#define psh_hint_deactivate( x ) (x)->flags &= ~PSH_HINT_ACTIVE
#define psh_hint_set_fitted( x ) (x)->flags |= PSH_HINT_FITTED
/* hint structure */
typedef struct PSH_HintRec_
{
FT_Int org_pos;
FT_Int org_len;
FT_Pos cur_pos;
FT_Pos cur_len;
FT_UInt flags;
PSH_Hint parent;
FT_Int order;
} PSH_HintRec;
/* this is an interpolation zone used for strong points; */
/* weak points are interpolated according to their strong */
/* neighbours */
typedef struct PSH_ZoneRec_
{
FT_Fixed scale;
FT_Fixed delta;
FT_Pos min;
FT_Pos max;
} PSH_ZoneRec, *PSH_Zone;
typedef struct PSH_Hint_TableRec_
{
FT_UInt max_hints;
FT_UInt num_hints;
PSH_Hint hints;
PSH_Hint* sort;
PSH_Hint* sort_global;
FT_UInt num_zones;
PSH_ZoneRec* zones;
PSH_Zone zone;
PS_Mask_Table hint_masks;
PS_Mask_Table counter_masks;
} PSH_Hint_TableRec, *PSH_Hint_Table;
typedef struct PSH_PointRec_* PSH_Point;
typedef struct PSH_ContourRec_* PSH_Contour;
enum
{
PSH_DIR_NONE = 4,
PSH_DIR_UP = -1,
PSH_DIR_DOWN = 1,
PSH_DIR_LEFT = -2,
PSH_DIR_RIGHT = 2
};
#define PSH_DIR_HORIZONTAL 2
#define PSH_DIR_VERTICAL 1
#define PSH_DIR_COMPARE( d1, d2 ) ( (d1) == (d2) || (d1) == -(d2) )
#define PSH_DIR_IS_HORIZONTAL( d ) PSH_DIR_COMPARE( d, PSH_DIR_HORIZONTAL )
#define PSH_DIR_IS_VERTICAL( d ) PSH_DIR_COMPARE( d, PSH_DIR_VERTICAL )
/* the following bit-flags are computed once by the glyph */
/* analyzer, for both dimensions */
enum
{
PSH_POINT_OFF = 1, /* point is off the curve */
PSH_POINT_SMOOTH = 2, /* point is smooth */
PSH_POINT_INFLEX = 4 /* point is inflection */
};
#define psh_point_is_smooth( p ) ( (p)->flags & PSH_POINT_SMOOTH )
#define psh_point_is_off( p ) ( (p)->flags & PSH_POINT_OFF )
#define psh_point_is_inflex( p ) ( (p)->flags & PSH_POINT_INFLEX )
#define psh_point_set_smooth( p ) (p)->flags |= PSH_POINT_SMOOTH
#define psh_point_set_off( p ) (p)->flags |= PSH_POINT_OFF
#define psh_point_set_inflex( p ) (p)->flags |= PSH_POINT_INFLEX
/* the following bit-flags are re-computed for each dimension */
enum
{
PSH_POINT_STRONG = 16, /* point is strong */
PSH_POINT_FITTED = 32, /* point is already fitted */
PSH_POINT_EXTREMUM = 64, /* point is local extremum */
PSH_POINT_POSITIVE = 128, /* extremum has positive contour flow */
PSH_POINT_NEGATIVE = 256, /* extremum has negative contour flow */
PSH_POINT_EDGE_MIN = 512, /* point is aligned to left/bottom stem edge */
PSH_POINT_EDGE_MAX = 1024 /* point is aligned to top/right stem edge */
};
#define psh_point_is_strong( p ) ( (p)->flags2 & PSH_POINT_STRONG )
#define psh_point_is_fitted( p ) ( (p)->flags2 & PSH_POINT_FITTED )
#define psh_point_is_extremum( p ) ( (p)->flags2 & PSH_POINT_EXTREMUM )
#define psh_point_is_positive( p ) ( (p)->flags2 & PSH_POINT_POSITIVE )
#define psh_point_is_negative( p ) ( (p)->flags2 & PSH_POINT_NEGATIVE )
#define psh_point_is_edge_min( p ) ( (p)->flags2 & PSH_POINT_EDGE_MIN )
#define psh_point_is_edge_max( p ) ( (p)->flags2 & PSH_POINT_EDGE_MAX )
#define psh_point_set_strong( p ) (p)->flags2 |= PSH_POINT_STRONG
#define psh_point_set_fitted( p ) (p)->flags2 |= PSH_POINT_FITTED
#define psh_point_set_extremum( p ) (p)->flags2 |= PSH_POINT_EXTREMUM
#define psh_point_set_positive( p ) (p)->flags2 |= PSH_POINT_POSITIVE
#define psh_point_set_negative( p ) (p)->flags2 |= PSH_POINT_NEGATIVE
#define psh_point_set_edge_min( p ) (p)->flags2 |= PSH_POINT_EDGE_MIN
#define psh_point_set_edge_max( p ) (p)->flags2 |= PSH_POINT_EDGE_MAX
typedef struct PSH_PointRec_
{
PSH_Point prev;
PSH_Point next;
PSH_Contour contour;
FT_UInt flags;
FT_UInt flags2;
FT_Char dir_in;
FT_Char dir_out;
FT_Angle angle_in;
FT_Angle angle_out;
PSH_Hint hint;
FT_Pos org_u;
FT_Pos org_v;
FT_Pos cur_u;
#ifdef DEBUG_HINTER
FT_Pos org_x;
FT_Pos cur_x;
FT_Pos org_y;
FT_Pos cur_y;
FT_UInt flags_x;
FT_UInt flags_y;
#endif
} PSH_PointRec;
#define PSH_POINT_EQUAL_ORG( a, b ) ( (a)->org_u == (b)->org_u && \
(a)->org_v == (b)->org_v )
#define PSH_POINT_ANGLE( a, b ) FT_Atan2( (b)->org_u - (a)->org_u, \
(b)->org_v - (a)->org_v )
typedef struct PSH_ContourRec_
{
PSH_Point start;
FT_UInt count;
} PSH_ContourRec;
typedef struct PSH_GlyphRec_
{
FT_UInt num_points;
FT_UInt num_contours;
PSH_Point points;
PSH_Contour contours;
FT_Memory memory;
FT_Outline* outline;
PSH_Globals globals;
PSH_Hint_TableRec hint_tables[2];
FT_Bool vertical;
FT_Int major_dir;
FT_Int minor_dir;
FT_Bool do_horz_hints;
FT_Bool do_vert_hints;
FT_Bool do_horz_snapping;
FT_Bool do_vert_snapping;
FT_Bool do_stem_adjust;
} PSH_GlyphRec, *PSH_Glyph;
#ifdef DEBUG_HINTER
extern PSH_Hint_Table ps_debug_hint_table;
typedef void
(*PSH_HintFunc)( PSH_Hint hint,
FT_Bool vertical );
extern PSH_HintFunc ps_debug_hint_func;
extern PSH_Glyph ps_debug_glyph;
#endif
extern FT_Error
ps_hints_apply( PS_Hints ps_hints,
FT_Outline* outline,
PSH_Globals globals,
FT_Render_Mode hint_mode );
FT_END_HEADER
#endif /* __PSHALGO_H__ */
/* END */
@@ -0,0 +1,750 @@
/***************************************************************************/
/* */
/* pshglob.c */
/* */
/* PostScript hinter global hinting management (body). */
/* Inspired by the new auto-hinter module. */
/* */
/* Copyright 2001, 2002, 2003, 2004, 2006, 2010 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_FREETYPE_H
#include FT_INTERNAL_OBJECTS_H
#include "pshglob.h"
#ifdef DEBUG_HINTER
PSH_Globals ps_debug_globals = 0;
#endif
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** STANDARD WIDTHS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* scale the widths/heights table */
static void
psh_globals_scale_widths( PSH_Globals globals,
FT_UInt direction )
{
PSH_Dimension dim = &globals->dimension[direction];
PSH_Widths stdw = &dim->stdw;
FT_UInt count = stdw->count;
PSH_Width width = stdw->widths;
PSH_Width stand = width; /* standard width/height */
FT_Fixed scale = dim->scale_mult;
if ( count > 0 )
{
width->cur = FT_MulFix( width->org, scale );
width->fit = FT_PIX_ROUND( width->cur );
width++;
count--;
for ( ; count > 0; count--, width++ )
{
FT_Pos w, dist;
w = FT_MulFix( width->org, scale );
dist = w - stand->cur;
if ( dist < 0 )
dist = -dist;
if ( dist < 128 )
w = stand->cur;
width->cur = w;
width->fit = FT_PIX_ROUND( w );
}
}
}
#if 0
/* org_width is is font units, result in device pixels, 26.6 format */
FT_LOCAL_DEF( FT_Pos )
psh_dimension_snap_width( PSH_Dimension dimension,
FT_Int org_width )
{
FT_UInt n;
FT_Pos width = FT_MulFix( org_width, dimension->scale_mult );
FT_Pos best = 64 + 32 + 2;
FT_Pos reference = width;
for ( n = 0; n < dimension->stdw.count; n++ )
{
FT_Pos w;
FT_Pos dist;
w = dimension->stdw.widths[n].cur;
dist = width - w;
if ( dist < 0 )
dist = -dist;
if ( dist < best )
{
best = dist;
reference = w;
}
}
if ( width >= reference )
{
width -= 0x21;
if ( width < reference )
width = reference;
}
else
{
width += 0x21;
if ( width > reference )
width = reference;
}
return width;
}
#endif /* 0 */
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** BLUE ZONES *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
static void
psh_blues_set_zones_0( PSH_Blues target,
FT_Bool is_others,
FT_UInt read_count,
FT_Short* read,
PSH_Blue_Table top_table,
PSH_Blue_Table bot_table )
{
FT_UInt count_top = top_table->count;
FT_UInt count_bot = bot_table->count;
FT_Bool first = 1;
FT_UNUSED( target );
for ( ; read_count > 1; read_count -= 2 )
{
FT_Int reference, delta;
FT_UInt count;
PSH_Blue_Zone zones, zone;
FT_Bool top;
/* read blue zone entry, and select target top/bottom zone */
top = 0;
if ( first || is_others )
{
reference = read[1];
delta = read[0] - reference;
zones = bot_table->zones;
count = count_bot;
first = 0;
}
else
{
reference = read[0];
delta = read[1] - reference;
zones = top_table->zones;
count = count_top;
top = 1;
}
/* insert into sorted table */
zone = zones;
for ( ; count > 0; count--, zone++ )
{
if ( reference < zone->org_ref )
break;
if ( reference == zone->org_ref )
{
FT_Int delta0 = zone->org_delta;
/* we have two zones on the same reference position -- */
/* only keep the largest one */
if ( delta < 0 )
{
if ( delta < delta0 )
zone->org_delta = delta;
}
else
{
if ( delta > delta0 )
zone->org_delta = delta;
}
goto Skip;
}
}
for ( ; count > 0; count-- )
zone[count] = zone[count-1];
zone->org_ref = reference;
zone->org_delta = delta;
if ( top )
count_top++;
else
count_bot++;
Skip:
read += 2;
}
top_table->count = count_top;
bot_table->count = count_bot;
}
/* Re-read blue zones from the original fonts and store them into out */
/* private structure. This function re-orders, sanitizes and */
/* fuzz-expands the zones as well. */
static void
psh_blues_set_zones( PSH_Blues target,
FT_UInt count,
FT_Short* blues,
FT_UInt count_others,
FT_Short* other_blues,
FT_Int fuzz,
FT_Int family )
{
PSH_Blue_Table top_table, bot_table;
FT_Int count_top, count_bot;
if ( family )
{
top_table = &target->family_top;
bot_table = &target->family_bottom;
}
else
{
top_table = &target->normal_top;
bot_table = &target->normal_bottom;
}
/* read the input blue zones, and build two sorted tables */
/* (one for the top zones, the other for the bottom zones) */
top_table->count = 0;
bot_table->count = 0;
/* first, the blues */
psh_blues_set_zones_0( target, 0,
count, blues, top_table, bot_table );
psh_blues_set_zones_0( target, 1,
count_others, other_blues, top_table, bot_table );
count_top = top_table->count;
count_bot = bot_table->count;
/* sanitize top table */
if ( count_top > 0 )
{
PSH_Blue_Zone zone = top_table->zones;
for ( count = count_top; count > 0; count--, zone++ )
{
FT_Int delta;
if ( count > 1 )
{
delta = zone[1].org_ref - zone[0].org_ref;
if ( zone->org_delta > delta )
zone->org_delta = delta;
}
zone->org_bottom = zone->org_ref;
zone->org_top = zone->org_delta + zone->org_ref;
}
}
/* sanitize bottom table */
if ( count_bot > 0 )
{
PSH_Blue_Zone zone = bot_table->zones;
for ( count = count_bot; count > 0; count--, zone++ )
{
FT_Int delta;
if ( count > 1 )
{
delta = zone[0].org_ref - zone[1].org_ref;
if ( zone->org_delta < delta )
zone->org_delta = delta;
}
zone->org_top = zone->org_ref;
zone->org_bottom = zone->org_delta + zone->org_ref;
}
}
/* expand top and bottom tables with blue fuzz */
{
FT_Int dim, top, bot, delta;
PSH_Blue_Zone zone;
zone = top_table->zones;
count = count_top;
for ( dim = 1; dim >= 0; dim-- )
{
if ( count > 0 )
{
/* expand the bottom of the lowest zone normally */
zone->org_bottom -= fuzz;
/* expand the top and bottom of intermediate zones; */
/* checking that the interval is smaller than the fuzz */
top = zone->org_top;
for ( count--; count > 0; count-- )
{
bot = zone[1].org_bottom;
delta = bot - top;
if ( delta < 2 * fuzz )
zone[0].org_top = zone[1].org_bottom = top + delta / 2;
else
{
zone[0].org_top = top + fuzz;
zone[1].org_bottom = bot - fuzz;
}
zone++;
top = zone->org_top;
}
/* expand the top of the highest zone normally */
zone->org_top = top + fuzz;
}
zone = bot_table->zones;
count = count_bot;
}
}
}
/* reset the blues table when the device transform changes */
static void
psh_blues_scale_zones( PSH_Blues blues,
FT_Fixed scale,
FT_Pos delta )
{
FT_UInt count;
FT_UInt num;
PSH_Blue_Table table = 0;
/* */
/* Determine whether we need to suppress overshoots or */
/* not. We simply need to compare the vertical scale */
/* parameter to the raw bluescale value. Here is why: */
/* */
/* We need to suppress overshoots for all pointsizes. */
/* At 300dpi that satisfies: */
/* */
/* pointsize < 240*bluescale + 0.49 */
/* */
/* This corresponds to: */
/* */
/* pixelsize < 1000*bluescale + 49/24 */
/* */
/* scale*EM_Size < 1000*bluescale + 49/24 */
/* */
/* However, for normal Type 1 fonts, EM_Size is 1000! */
/* We thus only check: */
/* */
/* scale < bluescale + 49/24000 */
/* */
/* which we shorten to */
/* */
/* "scale < bluescale" */
/* */
/* Note that `blue_scale' is stored 1000 times its real */
/* value, and that `scale' converts from font units to */
/* fractional pixels. */
/* */
/* 1000 / 64 = 125 / 8 */
if ( scale >= 0x20C49BAL )
blues->no_overshoots = FT_BOOL( scale < blues->blue_scale * 8 / 125 );
else
blues->no_overshoots = FT_BOOL( scale * 125 < blues->blue_scale * 8 );
/* */
/* The blue threshold is the font units distance under */
/* which overshoots are suppressed due to the BlueShift */
/* even if the scale is greater than BlueScale. */
/* */
/* It is the smallest distance such that */
/* */
/* dist <= BlueShift && dist*scale <= 0.5 pixels */
/* */
{
FT_Int threshold = blues->blue_shift;
while ( threshold > 0 && FT_MulFix( threshold, scale ) > 32 )
threshold--;
blues->blue_threshold = threshold;
}
for ( num = 0; num < 4; num++ )
{
PSH_Blue_Zone zone;
switch ( num )
{
case 0:
table = &blues->normal_top;
break;
case 1:
table = &blues->normal_bottom;
break;
case 2:
table = &blues->family_top;
break;
default:
table = &blues->family_bottom;
break;
}
zone = table->zones;
count = table->count;
for ( ; count > 0; count--, zone++ )
{
zone->cur_top = FT_MulFix( zone->org_top, scale ) + delta;
zone->cur_bottom = FT_MulFix( zone->org_bottom, scale ) + delta;
zone->cur_ref = FT_MulFix( zone->org_ref, scale ) + delta;
zone->cur_delta = FT_MulFix( zone->org_delta, scale );
/* round scaled reference position */
zone->cur_ref = FT_PIX_ROUND( zone->cur_ref );
#if 0
if ( zone->cur_ref > zone->cur_top )
zone->cur_ref -= 64;
else if ( zone->cur_ref < zone->cur_bottom )
zone->cur_ref += 64;
#endif
}
}
/* process the families now */
for ( num = 0; num < 2; num++ )
{
PSH_Blue_Zone zone1, zone2;
FT_UInt count1, count2;
PSH_Blue_Table normal, family;
switch ( num )
{
case 0:
normal = &blues->normal_top;
family = &blues->family_top;
break;
default:
normal = &blues->normal_bottom;
family = &blues->family_bottom;
}
zone1 = normal->zones;
count1 = normal->count;
for ( ; count1 > 0; count1--, zone1++ )
{
/* try to find a family zone whose reference position is less */
/* than 1 pixel far from the current zone */
zone2 = family->zones;
count2 = family->count;
for ( ; count2 > 0; count2--, zone2++ )
{
FT_Pos Delta;
Delta = zone1->org_ref - zone2->org_ref;
if ( Delta < 0 )
Delta = -Delta;
if ( FT_MulFix( Delta, scale ) < 64 )
{
zone1->cur_top = zone2->cur_top;
zone1->cur_bottom = zone2->cur_bottom;
zone1->cur_ref = zone2->cur_ref;
zone1->cur_delta = zone2->cur_delta;
break;
}
}
}
}
}
FT_LOCAL_DEF( void )
psh_blues_snap_stem( PSH_Blues blues,
FT_Int stem_top,
FT_Int stem_bot,
PSH_Alignment alignment )
{
PSH_Blue_Table table;
FT_UInt count;
FT_Pos delta;
PSH_Blue_Zone zone;
FT_Int no_shoots;
alignment->align = PSH_BLUE_ALIGN_NONE;
no_shoots = blues->no_overshoots;
/* look up stem top in top zones table */
table = &blues->normal_top;
count = table->count;
zone = table->zones;
for ( ; count > 0; count--, zone++ )
{
delta = stem_top - zone->org_bottom;
if ( delta < -blues->blue_fuzz )
break;
if ( stem_top <= zone->org_top + blues->blue_fuzz )
{
if ( no_shoots || delta <= blues->blue_threshold )
{
alignment->align |= PSH_BLUE_ALIGN_TOP;
alignment->align_top = zone->cur_ref;
}
break;
}
}
/* look up stem bottom in bottom zones table */
table = &blues->normal_bottom;
count = table->count;
zone = table->zones + count-1;
for ( ; count > 0; count--, zone-- )
{
delta = zone->org_top - stem_bot;
if ( delta < -blues->blue_fuzz )
break;
if ( stem_bot >= zone->org_bottom - blues->blue_fuzz )
{
if ( no_shoots || delta < blues->blue_threshold )
{
alignment->align |= PSH_BLUE_ALIGN_BOT;
alignment->align_bot = zone->cur_ref;
}
break;
}
}
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** GLOBAL HINTS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
static void
psh_globals_destroy( PSH_Globals globals )
{
if ( globals )
{
FT_Memory memory;
memory = globals->memory;
globals->dimension[0].stdw.count = 0;
globals->dimension[1].stdw.count = 0;
globals->blues.normal_top.count = 0;
globals->blues.normal_bottom.count = 0;
globals->blues.family_top.count = 0;
globals->blues.family_bottom.count = 0;
FT_FREE( globals );
#ifdef DEBUG_HINTER
ps_debug_globals = 0;
#endif
}
}
static FT_Error
psh_globals_new( FT_Memory memory,
T1_Private* priv,
PSH_Globals *aglobals )
{
PSH_Globals globals = NULL;
FT_Error error;
if ( !FT_NEW( globals ) )
{
FT_UInt count;
FT_Short* read;
globals->memory = memory;
/* copy standard widths */
{
PSH_Dimension dim = &globals->dimension[1];
PSH_Width write = dim->stdw.widths;
write->org = priv->standard_width[0];
write++;
read = priv->snap_widths;
for ( count = priv->num_snap_widths; count > 0; count-- )
{
write->org = *read;
write++;
read++;
}
dim->stdw.count = priv->num_snap_widths + 1;
}
/* copy standard heights */
{
PSH_Dimension dim = &globals->dimension[0];
PSH_Width write = dim->stdw.widths;
write->org = priv->standard_height[0];
write++;
read = priv->snap_heights;
for ( count = priv->num_snap_heights; count > 0; count-- )
{
write->org = *read;
write++;
read++;
}
dim->stdw.count = priv->num_snap_heights + 1;
}
/* copy blue zones */
psh_blues_set_zones( &globals->blues, priv->num_blue_values,
priv->blue_values, priv->num_other_blues,
priv->other_blues, priv->blue_fuzz, 0 );
psh_blues_set_zones( &globals->blues, priv->num_family_blues,
priv->family_blues, priv->num_family_other_blues,
priv->family_other_blues, priv->blue_fuzz, 1 );
globals->blues.blue_scale = priv->blue_scale;
globals->blues.blue_shift = priv->blue_shift;
globals->blues.blue_fuzz = priv->blue_fuzz;
globals->dimension[0].scale_mult = 0;
globals->dimension[0].scale_delta = 0;
globals->dimension[1].scale_mult = 0;
globals->dimension[1].scale_delta = 0;
#ifdef DEBUG_HINTER
ps_debug_globals = globals;
#endif
}
*aglobals = globals;
return error;
}
FT_LOCAL_DEF( FT_Error )
psh_globals_set_scale( PSH_Globals globals,
FT_Fixed x_scale,
FT_Fixed y_scale,
FT_Fixed x_delta,
FT_Fixed y_delta )
{
PSH_Dimension dim = &globals->dimension[0];
dim = &globals->dimension[0];
if ( x_scale != dim->scale_mult ||
x_delta != dim->scale_delta )
{
dim->scale_mult = x_scale;
dim->scale_delta = x_delta;
psh_globals_scale_widths( globals, 0 );
}
dim = &globals->dimension[1];
if ( y_scale != dim->scale_mult ||
y_delta != dim->scale_delta )
{
dim->scale_mult = y_scale;
dim->scale_delta = y_delta;
psh_globals_scale_widths( globals, 1 );
psh_blues_scale_zones( &globals->blues, y_scale, y_delta );
}
return 0;
}
FT_LOCAL_DEF( void )
psh_globals_funcs_init( PSH_Globals_FuncsRec* funcs )
{
funcs->create = psh_globals_new;
funcs->set_scale = psh_globals_set_scale;
funcs->destroy = psh_globals_destroy;
}
/* END */
@@ -0,0 +1,196 @@
/***************************************************************************/
/* */
/* pshglob.h */
/* */
/* PostScript hinter global hinting management. */
/* */
/* Copyright 2001, 2002, 2003 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. */
/* */
/***************************************************************************/
#ifndef __PSHGLOB_H__
#define __PSHGLOB_H__
#include FT_FREETYPE_H
#include FT_INTERNAL_POSTSCRIPT_HINTS_H
FT_BEGIN_HEADER
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** GLOBAL HINTS INTERNALS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/* */
/* @constant: */
/* PS_GLOBALS_MAX_BLUE_ZONES */
/* */
/* @description: */
/* The maximum number of blue zones in a font global hints structure. */
/* See @PS_Globals_BluesRec. */
/* */
#define PS_GLOBALS_MAX_BLUE_ZONES 16
/*************************************************************************/
/* */
/* @constant: */
/* PS_GLOBALS_MAX_STD_WIDTHS */
/* */
/* @description: */
/* The maximum number of standard and snap widths in either the */
/* horizontal or vertical direction. See @PS_Globals_WidthsRec. */
/* */
#define PS_GLOBALS_MAX_STD_WIDTHS 16
/* standard and snap width */
typedef struct PSH_WidthRec_
{
FT_Int org;
FT_Pos cur;
FT_Pos fit;
} PSH_WidthRec, *PSH_Width;
/* standard and snap widths table */
typedef struct PSH_WidthsRec_
{
FT_UInt count;
PSH_WidthRec widths[PS_GLOBALS_MAX_STD_WIDTHS];
} PSH_WidthsRec, *PSH_Widths;
typedef struct PSH_DimensionRec_
{
PSH_WidthsRec stdw;
FT_Fixed scale_mult;
FT_Fixed scale_delta;
} PSH_DimensionRec, *PSH_Dimension;
/* blue zone descriptor */
typedef struct PSH_Blue_ZoneRec_
{
FT_Int org_ref;
FT_Int org_delta;
FT_Int org_top;
FT_Int org_bottom;
FT_Pos cur_ref;
FT_Pos cur_delta;
FT_Pos cur_bottom;
FT_Pos cur_top;
} PSH_Blue_ZoneRec, *PSH_Blue_Zone;
typedef struct PSH_Blue_TableRec_
{
FT_UInt count;
PSH_Blue_ZoneRec zones[PS_GLOBALS_MAX_BLUE_ZONES];
} PSH_Blue_TableRec, *PSH_Blue_Table;
/* blue zones table */
typedef struct PSH_BluesRec_
{
PSH_Blue_TableRec normal_top;
PSH_Blue_TableRec normal_bottom;
PSH_Blue_TableRec family_top;
PSH_Blue_TableRec family_bottom;
FT_Fixed blue_scale;
FT_Int blue_shift;
FT_Int blue_threshold;
FT_Int blue_fuzz;
FT_Bool no_overshoots;
} PSH_BluesRec, *PSH_Blues;
/* font globals. */
/* dimension 0 => X coordinates + vertical hints/stems */
/* dimension 1 => Y coordinates + horizontal hints/stems */
typedef struct PSH_GlobalsRec_
{
FT_Memory memory;
PSH_DimensionRec dimension[2];
PSH_BluesRec blues;
} PSH_GlobalsRec;
#define PSH_BLUE_ALIGN_NONE 0
#define PSH_BLUE_ALIGN_TOP 1
#define PSH_BLUE_ALIGN_BOT 2
typedef struct PSH_AlignmentRec_
{
int align;
FT_Pos align_top;
FT_Pos align_bot;
} PSH_AlignmentRec, *PSH_Alignment;
FT_LOCAL( void )
psh_globals_funcs_init( PSH_Globals_FuncsRec* funcs );
#if 0
/* snap a stem width to fitter coordinates. `org_width' is in font */
/* units. The result is in device pixels (26.6 format). */
FT_LOCAL( FT_Pos )
psh_dimension_snap_width( PSH_Dimension dimension,
FT_Int org_width );
#endif
FT_LOCAL( FT_Error )
psh_globals_set_scale( PSH_Globals globals,
FT_Fixed x_scale,
FT_Fixed y_scale,
FT_Fixed x_delta,
FT_Fixed y_delta );
/* snap a stem to one or two blue zones */
FT_LOCAL( void )
psh_blues_snap_stem( PSH_Blues blues,
FT_Int stem_top,
FT_Int stem_bot,
PSH_Alignment alignment );
/* */
#ifdef DEBUG_HINTER
extern PSH_Globals ps_debug_globals;
#endif
FT_END_HEADER
#endif /* __PSHGLOB_H__ */
/* END */
@@ -0,0 +1,29 @@
/***************************************************************************/
/* */
/* pshinter.c */
/* */
/* FreeType PostScript Hinting module */
/* */
/* Copyright 2001, 2003 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. */
/* */
/***************************************************************************/
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include <ft2build.h>
#include "pshpic.c"
#include "pshrec.c"
#include "pshglob.c"
#include "pshalgo.c"
#include "pshmod.c"
/* END */
+118
View File
@@ -0,0 +1,118 @@
/***************************************************************************/
/* */
/* pshmod.c */
/* */
/* FreeType PostScript hinter module implementation (body). */
/* */
/* Copyright 2001, 2002, 2007 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_OBJECTS_H
#include "pshrec.h"
#include "pshalgo.h"
#include "pshpic.h"
/* the Postscript Hinter module structure */
typedef struct PS_Hinter_Module_Rec_
{
FT_ModuleRec root;
PS_HintsRec ps_hints;
PSH_Globals_FuncsRec globals_funcs;
T1_Hints_FuncsRec t1_funcs;
T2_Hints_FuncsRec t2_funcs;
} PS_Hinter_ModuleRec, *PS_Hinter_Module;
/* finalize module */
FT_CALLBACK_DEF( void )
ps_hinter_done( PS_Hinter_Module module )
{
module->t1_funcs.hints = NULL;
module->t2_funcs.hints = NULL;
ps_hints_done( &module->ps_hints );
}
/* initialize module, create hints recorder and the interface */
FT_CALLBACK_DEF( FT_Error )
ps_hinter_init( PS_Hinter_Module module )
{
FT_Memory memory = module->root.memory;
void* ph = &module->ps_hints;
ps_hints_init( &module->ps_hints, memory );
psh_globals_funcs_init( &module->globals_funcs );
t1_hints_funcs_init( &module->t1_funcs );
module->t1_funcs.hints = (T1_Hints)ph;
t2_hints_funcs_init( &module->t2_funcs );
module->t2_funcs.hints = (T2_Hints)ph;
return 0;
}
/* returns global hints interface */
FT_CALLBACK_DEF( PSH_Globals_Funcs )
pshinter_get_globals_funcs( FT_Module module )
{
return &((PS_Hinter_Module)module)->globals_funcs;
}
/* return Type 1 hints interface */
FT_CALLBACK_DEF( T1_Hints_Funcs )
pshinter_get_t1_funcs( FT_Module module )
{
return &((PS_Hinter_Module)module)->t1_funcs;
}
/* return Type 2 hints interface */
FT_CALLBACK_DEF( T2_Hints_Funcs )
pshinter_get_t2_funcs( FT_Module module )
{
return &((PS_Hinter_Module)module)->t2_funcs;
}
FT_DEFINE_PSHINTER_INTERFACE(pshinter_interface,
pshinter_get_globals_funcs,
pshinter_get_t1_funcs,
pshinter_get_t2_funcs
)
FT_DEFINE_MODULE(pshinter_module_class,
0,
sizeof ( PS_Hinter_ModuleRec ),
"pshinter",
0x10000L,
0x20000L,
&FTPSHINTER_INTERFACE_GET, /* module-specific interface */
(FT_Module_Constructor)ps_hinter_init,
(FT_Module_Destructor) ps_hinter_done,
(FT_Module_Requester) 0 /* no additional interface for now */
)
/* END */
@@ -0,0 +1,39 @@
/***************************************************************************/
/* */
/* pshmod.h */
/* */
/* PostScript hinter module interface (specification). */
/* */
/* Copyright 2001 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. */
/* */
/***************************************************************************/
#ifndef __PSHMOD_H__
#define __PSHMOD_H__
#include <ft2build.h>
#include FT_MODULE_H
FT_BEGIN_HEADER
FT_DECLARE_MODULE( pshinter_module_class )
FT_END_HEADER
#endif /* __PSHMOD_H__ */
/* END */
@@ -0,0 +1,40 @@
/***************************************************************************/
/* */
/* pshnterr.h */
/* */
/* PS Hinter error codes (specification only). */
/* */
/* Copyright 2003 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. */
/* */
/***************************************************************************/
/*************************************************************************/
/* */
/* This file is used to define the PSHinter error enumeration constants. */
/* */
/*************************************************************************/
#ifndef __PSHNTERR_H__
#define __PSHNTERR_H__
#include FT_MODULE_ERRORS_H
#undef __FTERRORS_H__
#define FT_ERR_PREFIX PSH_Err_
#define FT_ERR_BASE FT_Mod_Err_PShinter
#include FT_ERRORS_H
#endif /* __PSHNTERR_H__ */
/* END */
@@ -0,0 +1,69 @@
/***************************************************************************/
/* */
/* pshpic.c */
/* */
/* The FreeType position independent code services for pshinter module. */
/* */
/* Copyright 2009, 2010 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* 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_FREETYPE_H
#include FT_INTERNAL_OBJECTS_H
#include "pshpic.h"
#ifdef FT_CONFIG_OPTION_PIC
/* forward declaration of PIC init functions from pshmod.c */
void FT_Init_Class_pshinter_interface( FT_Library, PSHinter_Interface*);
void
pshinter_module_class_pic_free( FT_Library library )
{
FT_PIC_Container* pic_container = &library->pic_container;
FT_Memory memory = library->memory;
if ( pic_container->pshinter )
{
FT_FREE( pic_container->pshinter );
pic_container->pshinter = NULL;
}
}
FT_Error
pshinter_module_class_pic_init( FT_Library library )
{
FT_PIC_Container* pic_container = &library->pic_container;
FT_Error error = PSH_Err_Ok;
PSHinterPIC* container;
FT_Memory memory = library->memory;
/* allocate pointer, clear and set global container pointer */
if ( FT_ALLOC ( container, sizeof ( *container ) ) )
return error;
FT_MEM_SET( container, 0, sizeof ( *container ) );
pic_container->pshinter = container;
/* add call to initialization function when you add new scripts */
FT_Init_Class_pshinter_interface(library, &container->pshinter_interface);
/*Exit:*/
if(error)
pshinter_module_class_pic_free(library);
return error;
}
#endif /* FT_CONFIG_OPTION_PIC */
/* END */
@@ -0,0 +1,53 @@
/***************************************************************************/
/* */
/* pshpic.h */
/* */
/* The FreeType position independent code services for pshinter module. */
/* */
/* Copyright 2009 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* 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. */
/* */
/***************************************************************************/
#ifndef __PSHPIC_H__
#define __PSHPIC_H__
FT_BEGIN_HEADER
#include FT_INTERNAL_PIC_H
#ifndef FT_CONFIG_OPTION_PIC
#define FTPSHINTER_INTERFACE_GET pshinter_interface
#else /* FT_CONFIG_OPTION_PIC */
#include FT_INTERNAL_POSTSCRIPT_HINTS_H
typedef struct PSHinterPIC_
{
PSHinter_Interface pshinter_interface;
} PSHinterPIC;
#define GET_PIC(lib) ((PSHinterPIC*)((lib)->pic_container.autofit))
#define FTPSHINTER_INTERFACE_GET (GET_PIC(library)->pshinter_interface)
#endif /* FT_CONFIG_OPTION_PIC */
/* */
FT_END_HEADER
#endif /* __PSHPIC_H__ */
/* END */
File diff suppressed because it is too large Load Diff
+176
View File
@@ -0,0 +1,176 @@
/***************************************************************************/
/* */
/* pshrec.h */
/* */
/* Postscript (Type1/Type2) hints recorder (specification). */
/* */
/* Copyright 2001, 2002, 2003, 2006, 2008 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. */
/* */
/***************************************************************************/
/**************************************************************************/
/* */
/* The functions defined here are called from the Type 1, CID and CFF */
/* font drivers to record the hints of a given character/glyph. */
/* */
/* The hints are recorded in a unified format, and are later processed */
/* by the `optimizer' and `fitter' to adjust the outlines to the pixel */
/* grid. */
/* */
/**************************************************************************/
#ifndef __PSHREC_H__
#define __PSHREC_H__
#include <ft2build.h>
#include FT_INTERNAL_POSTSCRIPT_HINTS_H
#include "pshglob.h"
FT_BEGIN_HEADER
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** GLYPH HINTS RECORDER INTERNALS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* handle to hint record */
typedef struct PS_HintRec_* PS_Hint;
/* hint types */
typedef enum PS_Hint_Type_
{
PS_HINT_TYPE_1 = 1,
PS_HINT_TYPE_2 = 2
} PS_Hint_Type;
/* hint flags */
typedef enum PS_Hint_Flags_
{
PS_HINT_FLAG_GHOST = 1,
PS_HINT_FLAG_BOTTOM = 2
} PS_Hint_Flags;
/* hint descriptor */
typedef struct PS_HintRec_
{
FT_Int pos;
FT_Int len;
FT_UInt flags;
} PS_HintRec;
#define ps_hint_is_active( x ) ( (x)->flags & PS_HINT_FLAG_ACTIVE )
#define ps_hint_is_ghost( x ) ( (x)->flags & PS_HINT_FLAG_GHOST )
#define ps_hint_is_bottom( x ) ( (x)->flags & PS_HINT_FLAG_BOTTOM )
/* hints table descriptor */
typedef struct PS_Hint_TableRec_
{
FT_UInt num_hints;
FT_UInt max_hints;
PS_Hint hints;
} PS_Hint_TableRec, *PS_Hint_Table;
/* hint and counter mask descriptor */
typedef struct PS_MaskRec_
{
FT_UInt num_bits;
FT_UInt max_bits;
FT_Byte* bytes;
FT_UInt end_point;
} PS_MaskRec, *PS_Mask;
/* masks and counters table descriptor */
typedef struct PS_Mask_TableRec_
{
FT_UInt num_masks;
FT_UInt max_masks;
PS_Mask masks;
} PS_Mask_TableRec, *PS_Mask_Table;
/* dimension-specific hints descriptor */
typedef struct PS_DimensionRec_
{
PS_Hint_TableRec hints;
PS_Mask_TableRec masks;
PS_Mask_TableRec counters;
} PS_DimensionRec, *PS_Dimension;
/* glyph hints descriptor */
/* dimension 0 => X coordinates + vertical hints/stems */
/* dimension 1 => Y coordinates + horizontal hints/stems */
typedef struct PS_HintsRec_
{
FT_Memory memory;
FT_Error error;
FT_UInt32 magic;
PS_Hint_Type hint_type;
PS_DimensionRec dimension[2];
} PS_HintsRec, *PS_Hints;
/* */
/* initialize hints recorder */
FT_LOCAL( FT_Error )
ps_hints_init( PS_Hints hints,
FT_Memory memory );
/* finalize hints recorder */
FT_LOCAL( void )
ps_hints_done( PS_Hints hints );
/* initialize Type1 hints recorder interface */
FT_LOCAL( void )
t1_hints_funcs_init( T1_Hints_FuncsRec* funcs );
/* initialize Type2 hints recorder interface */
FT_LOCAL( void )
t2_hints_funcs_init( T2_Hints_FuncsRec* funcs );
#ifdef DEBUG_HINTER
extern PS_Hints ps_debug_hints;
extern int ps_debug_no_horz_hints;
extern int ps_debug_no_vert_hints;
#endif
/* */
FT_END_HEADER
#endif /* __PS_HINTER_RECORD_H__ */
/* END */
@@ -0,0 +1,72 @@
#
# FreeType 2 PSHinter driver configuration rules
#
# Copyright 2001, 2003 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.
# PSHINTER driver directory
#
PSHINTER_DIR := $(SRC_DIR)/pshinter
# compilation flags for the driver
#
PSHINTER_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(PSHINTER_DIR))
# PSHINTER driver sources (i.e., C files)
#
PSHINTER_DRV_SRC := $(PSHINTER_DIR)/pshrec.c \
$(PSHINTER_DIR)/pshglob.c \
$(PSHINTER_DIR)/pshmod.c \
$(PSHINTER_DIR)/pshalgo.c
# PSHINTER driver headers
#
PSHINTER_DRV_H := $(PSHINTER_DRV_SRC:%c=%h) \
$(PSHINTER_DIR)/pshnterr.h
# PSHINTER driver object(s)
#
# PSHINTER_DRV_OBJ_M is used during `multi' builds.
# PSHINTER_DRV_OBJ_S is used during `single' builds.
#
PSHINTER_DRV_OBJ_M := $(PSHINTER_DRV_SRC:$(PSHINTER_DIR)/%.c=$(OBJ_DIR)/%.$O)
PSHINTER_DRV_OBJ_S := $(OBJ_DIR)/pshinter.$O
# PSHINTER driver source file for single build
#
PSHINTER_DRV_SRC_S := $(PSHINTER_DIR)/pshinter.c
# PSHINTER driver - single object
#
$(PSHINTER_DRV_OBJ_S): $(PSHINTER_DRV_SRC_S) $(PSHINTER_DRV_SRC) \
$(FREETYPE_H) $(PSHINTER_DRV_H)
$(PSHINTER_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(PSHINTER_DRV_SRC_S))
# PSHINTER driver - multiple objects
#
$(OBJ_DIR)/%.$O: $(PSHINTER_DIR)/%.c $(FREETYPE_H) $(PSHINTER_DRV_H)
$(PSHINTER_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<)
# update main driver object lists
#
DRV_OBJS_S += $(PSHINTER_DRV_OBJ_S)
DRV_OBJS_M += $(PSHINTER_DRV_OBJ_M)
# EOF
+29
View File
@@ -0,0 +1,29 @@
# FreeType 2 src/psnames Jamfile
#
# Copyright 2001 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.
SubDir FT2_TOP $(FT2_SRC_DIR) psnames ;
{
local _sources ;
if $(FT2_MULTI)
{
_sources = psmodule pspic ;
}
else
{
_sources = psnames ;
}
Library $(FT2_LIB) : $(_sources).c ;
}
# end of src/psnames Jamfile
@@ -0,0 +1,23 @@
#
# FreeType 2 PSnames module definition
#
# Copyright 1996-2000, 2006 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.
FTMODULE_H_COMMANDS += PSNAMES_MODULE
define PSNAMES_MODULE
$(OPEN_DRIVER) FT_Module_Class, psnames_module_class $(CLOSE_DRIVER)
$(ECHO_DRIVER)psnames $(ECHO_DRIVER_DESC)Postscript & Unicode Glyph name handling$(ECHO_DRIVER_DONE)
endef
# EOF
@@ -0,0 +1,597 @@
/***************************************************************************/
/* */
/* psmodule.c */
/* */
/* PSNames module implementation (body). */
/* */
/* Copyright 1996-2001, 2002, 2003, 2005, 2006, 2007, 2008 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_OBJECTS_H
#include FT_SERVICE_POSTSCRIPT_CMAPS_H
#include "psmodule.h"
#include "pstables.h"
#include "psnamerr.h"
#include "pspic.h"
#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
#define VARIANT_BIT 0x80000000UL
#define BASE_GLYPH( code ) ( (FT_UInt32)( (code) & ~VARIANT_BIT ) )
/* Return the Unicode value corresponding to a given glyph. Note that */
/* we do deal with glyph variants by detecting a non-initial dot in */
/* the name, as in `A.swash' or `e.final'; in this case, the */
/* VARIANT_BIT is set in the return value. */
/* */
static FT_UInt32
ps_unicode_value( const char* glyph_name )
{
/* If the name begins with `uni', then the glyph name may be a */
/* hard-coded unicode character code. */
if ( glyph_name[0] == 'u' &&
glyph_name[1] == 'n' &&
glyph_name[2] == 'i' )
{
/* determine whether the next four characters following are */
/* hexadecimal. */
/* XXX: Add code to deal with ligatures, i.e. glyph names like */
/* `uniXXXXYYYYZZZZ'... */
FT_Int count;
FT_UInt32 value = 0;
const char* p = glyph_name + 3;
for ( count = 4; count > 0; count--, p++ )
{
char c = *p;
unsigned int d;
d = (unsigned char)c - '0';
if ( d >= 10 )
{
d = (unsigned char)c - 'A';
if ( d >= 6 )
d = 16;
else
d += 10;
}
/* Exit if a non-uppercase hexadecimal character was found */
/* -- this also catches character codes below `0' since such */
/* negative numbers cast to `unsigned int' are far too big. */
if ( d >= 16 )
break;
value = ( value << 4 ) + d;
}
/* there must be exactly four hex digits */
if ( count == 0 )
{
if ( *p == '\0' )
return value;
if ( *p == '.' )
return (FT_UInt32)( value | VARIANT_BIT );
}
}
/* If the name begins with `u', followed by four to six uppercase */
/* hexadecimal digits, it is a hard-coded unicode character code. */
if ( glyph_name[0] == 'u' )
{
FT_Int count;
FT_UInt32 value = 0;
const char* p = glyph_name + 1;
for ( count = 6; count > 0; count--, p++ )
{
char c = *p;
unsigned int d;
d = (unsigned char)c - '0';
if ( d >= 10 )
{
d = (unsigned char)c - 'A';
if ( d >= 6 )
d = 16;
else
d += 10;
}
if ( d >= 16 )
break;
value = ( value << 4 ) + d;
}
if ( count <= 2 )
{
if ( *p == '\0' )
return value;
if ( *p == '.' )
return (FT_UInt32)( value | VARIANT_BIT );
}
}
/* Look for a non-initial dot in the glyph name in order to */
/* find variants like `A.swash', `e.final', etc. */
{
const char* p = glyph_name;
const char* dot = NULL;
for ( ; *p; p++ )
{
if ( *p == '.' && p > glyph_name )
{
dot = p;
break;
}
}
/* now look up the glyph in the Adobe Glyph List */
if ( !dot )
return (FT_UInt32)ft_get_adobe_glyph_index( glyph_name, p );
else
return (FT_UInt32)( ft_get_adobe_glyph_index( glyph_name, dot ) |
VARIANT_BIT );
}
}
/* ft_qsort callback to sort the unicode map */
FT_CALLBACK_DEF( int )
compare_uni_maps( const void* a,
const void* b )
{
PS_UniMap* map1 = (PS_UniMap*)a;
PS_UniMap* map2 = (PS_UniMap*)b;
FT_UInt32 unicode1 = BASE_GLYPH( map1->unicode );
FT_UInt32 unicode2 = BASE_GLYPH( map2->unicode );
/* sort base glyphs before glyph variants */
if ( unicode1 == unicode2 )
{
if ( map1->unicode > map2->unicode )
return 1;
else if ( map1->unicode < map2->unicode )
return -1;
else
return 0;
}
else
{
if ( unicode1 > unicode2 )
return 1;
else if ( unicode1 < unicode2 )
return -1;
else
return 0;
}
}
/* support for extra glyphs not handled (well) in AGL; */
/* we add extra mappings for them if necessary */
#define EXTRA_GLYPH_LIST_SIZE 10
static const FT_UInt32 ft_extra_glyph_unicodes[EXTRA_GLYPH_LIST_SIZE] =
{
/* WGL 4 */
0x0394,
0x03A9,
0x2215,
0x00AD,
0x02C9,
0x03BC,
0x2219,
0x00A0,
/* Romanian */
0x021A,
0x021B
};
static const char ft_extra_glyph_names[] =
{
'D','e','l','t','a',0,
'O','m','e','g','a',0,
'f','r','a','c','t','i','o','n',0,
'h','y','p','h','e','n',0,
'm','a','c','r','o','n',0,
'm','u',0,
'p','e','r','i','o','d','c','e','n','t','e','r','e','d',0,
's','p','a','c','e',0,
'T','c','o','m','m','a','a','c','c','e','n','t',0,
't','c','o','m','m','a','a','c','c','e','n','t',0
};
static const FT_Int
ft_extra_glyph_name_offsets[EXTRA_GLYPH_LIST_SIZE] =
{
0,
6,
12,
21,
28,
35,
38,
53,
59,
72
};
static void
ps_check_extra_glyph_name( const char* gname,
FT_UInt glyph,
FT_UInt* extra_glyphs,
FT_UInt *states )
{
FT_UInt n;
for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
{
if ( ft_strcmp( ft_extra_glyph_names +
ft_extra_glyph_name_offsets[n], gname ) == 0 )
{
if ( states[n] == 0 )
{
/* mark this extra glyph as a candidate for the cmap */
states[n] = 1;
extra_glyphs[n] = glyph;
}
return;
}
}
}
static void
ps_check_extra_glyph_unicode( FT_UInt32 uni_char,
FT_UInt *states )
{
FT_UInt n;
for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
{
if ( uni_char == ft_extra_glyph_unicodes[n] )
{
/* disable this extra glyph from being added to the cmap */
states[n] = 2;
return;
}
}
}
/* Build a table that maps Unicode values to glyph indices. */
static FT_Error
ps_unicodes_init( FT_Memory memory,
PS_Unicodes table,
FT_UInt num_glyphs,
PS_GetGlyphNameFunc get_glyph_name,
PS_FreeGlyphNameFunc free_glyph_name,
FT_Pointer glyph_data )
{
FT_Error error;
FT_UInt extra_glyph_list_states[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
FT_UInt extra_glyphs[EXTRA_GLYPH_LIST_SIZE];
/* we first allocate the table */
table->num_maps = 0;
table->maps = 0;
if ( !FT_NEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) )
{
FT_UInt n;
FT_UInt count;
PS_UniMap* map;
FT_UInt32 uni_char;
map = table->maps;
for ( n = 0; n < num_glyphs; n++ )
{
const char* gname = get_glyph_name( glyph_data, n );
if ( gname )
{
ps_check_extra_glyph_name( gname, n,
extra_glyphs, extra_glyph_list_states );
uni_char = ps_unicode_value( gname );
if ( BASE_GLYPH( uni_char ) != 0 )
{
ps_check_extra_glyph_unicode( uni_char,
extra_glyph_list_states );
map->unicode = uni_char;
map->glyph_index = n;
map++;
}
if ( free_glyph_name )
free_glyph_name( glyph_data, gname );
}
}
for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
{
if ( extra_glyph_list_states[n] == 1 )
{
/* This glyph name has an additional representation. */
/* Add it to the cmap. */
map->unicode = ft_extra_glyph_unicodes[n];
map->glyph_index = extra_glyphs[n];
map++;
}
}
/* now compress the table a bit */
count = (FT_UInt)( map - table->maps );
if ( count == 0 )
{
/* No unicode chars here! */
FT_FREE( table->maps );
if ( !error )
error = PSnames_Err_No_Unicode_Glyph_Name;
}
else
{
/* Reallocate if the number of used entries is much smaller. */
if ( count < num_glyphs / 2 )
{
(void)FT_RENEW_ARRAY( table->maps, num_glyphs, count );
error = PSnames_Err_Ok;
}
/* Sort the table in increasing order of unicode values, */
/* taking care of glyph variants. */
ft_qsort( table->maps, count, sizeof ( PS_UniMap ),
compare_uni_maps );
}
table->num_maps = count;
}
return error;
}
static FT_UInt
ps_unicodes_char_index( PS_Unicodes table,
FT_UInt32 unicode )
{
PS_UniMap *min, *max, *mid, *result = NULL;
/* Perform a binary search on the table. */
min = table->maps;
max = min + table->num_maps - 1;
while ( min <= max )
{
FT_UInt32 base_glyph;
mid = min + ( ( max - min ) >> 1 );
if ( mid->unicode == unicode )
{
result = mid;
break;
}
base_glyph = BASE_GLYPH( mid->unicode );
if ( base_glyph == unicode )
result = mid; /* remember match but continue search for base glyph */
if ( min == max )
break;
if ( base_glyph < unicode )
min = mid + 1;
else
max = mid - 1;
}
if ( result )
return result->glyph_index;
else
return 0;
}
static FT_UInt32
ps_unicodes_char_next( PS_Unicodes table,
FT_UInt32 *unicode )
{
FT_UInt result = 0;
FT_UInt32 char_code = *unicode + 1;
{
FT_UInt min = 0;
FT_UInt max = table->num_maps;
FT_UInt mid;
PS_UniMap* map;
FT_UInt32 base_glyph;
while ( min < max )
{
mid = min + ( ( max - min ) >> 1 );
map = table->maps + mid;
if ( map->unicode == char_code )
{
result = map->glyph_index;
goto Exit;
}
base_glyph = BASE_GLYPH( map->unicode );
if ( base_glyph == char_code )
result = map->glyph_index;
if ( base_glyph < char_code )
min = mid + 1;
else
max = mid;
}
if ( result )
goto Exit; /* we have a variant glyph */
/* we didn't find it; check whether we have a map just above it */
char_code = 0;
if ( min < table->num_maps )
{
map = table->maps + min;
result = map->glyph_index;
char_code = BASE_GLYPH( map->unicode );
}
}
Exit:
*unicode = char_code;
return result;
}
#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
static const char*
ps_get_macintosh_name( FT_UInt name_index )
{
if ( name_index >= FT_NUM_MAC_NAMES )
name_index = 0;
return ft_standard_glyph_names + ft_mac_names[name_index];
}
static const char*
ps_get_standard_strings( FT_UInt sid )
{
if ( sid >= FT_NUM_SID_NAMES )
return 0;
return ft_standard_glyph_names + ft_sid_names[sid];
}
#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
FT_DEFINE_SERVICE_PSCMAPSREC(pscmaps_interface,
(PS_Unicode_ValueFunc) ps_unicode_value,
(PS_Unicodes_InitFunc) ps_unicodes_init,
(PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,
(PS_Unicodes_CharNextFunc) ps_unicodes_char_next,
(PS_Macintosh_NameFunc) ps_get_macintosh_name,
(PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
t1_standard_encoding,
t1_expert_encoding
)
#else
FT_DEFINE_SERVICE_PSCMAPSREC(pscmaps_interface,
0,
0,
0,
0,
(PS_Macintosh_NameFunc) ps_get_macintosh_name,
(PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
t1_standard_encoding,
t1_expert_encoding
)
#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
FT_DEFINE_SERVICEDESCREC1(pscmaps_services,
FT_SERVICE_ID_POSTSCRIPT_CMAPS, &FT_PSCMAPS_INTERFACE_GET
)
static FT_Pointer
psnames_get_service( FT_Module module,
const char* service_id )
{
FT_UNUSED( module );
return ft_service_list_lookup( FT_PSCMAPS_SERVICES_GET, service_id );
}
#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
#ifndef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
#define PUT_PS_NAMES_SERVICE(a) 0
#else
#define PUT_PS_NAMES_SERVICE(a) a
#endif
FT_DEFINE_MODULE(psnames_module_class,
0, /* this is not a font driver, nor a renderer */
sizeof ( FT_ModuleRec ),
"psnames", /* driver name */
0x10000L, /* driver version */
0x20000L, /* driver requires FreeType 2 or above */
PUT_PS_NAMES_SERVICE((void*)&FT_PSCMAPS_INTERFACE_GET), /* module specific interface */
(FT_Module_Constructor)0,
(FT_Module_Destructor) 0,
(FT_Module_Requester) PUT_PS_NAMES_SERVICE(psnames_get_service)
)
/* END */
@@ -0,0 +1,38 @@
/***************************************************************************/
/* */
/* psmodule.h */
/* */
/* High-level PSNames module interface (specification). */
/* */
/* Copyright 1996-2001 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. */
/* */
/***************************************************************************/
#ifndef __PSMODULE_H__
#define __PSMODULE_H__
#include <ft2build.h>
#include FT_MODULE_H
FT_BEGIN_HEADER
FT_DECLARE_MODULE( psnames_module_class )
FT_END_HEADER
#endif /* __PSMODULE_H__ */
/* END */
@@ -0,0 +1,41 @@
/***************************************************************************/
/* */
/* psnamerr.h */
/* */
/* PS names module error codes (specification only). */
/* */
/* Copyright 2001 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. */
/* */
/***************************************************************************/
/*************************************************************************/
/* */
/* This file is used to define the PS names module error enumeration */
/* constants. */
/* */
/*************************************************************************/
#ifndef __PSNAMERR_H__
#define __PSNAMERR_H__
#include FT_MODULE_ERRORS_H
#undef __FTERRORS_H__
#define FT_ERR_PREFIX PSnames_Err_
#define FT_ERR_BASE FT_Mod_Err_PSnames
#include FT_ERRORS_H
#endif /* __PSNAMERR_H__ */
/* END */
@@ -0,0 +1,26 @@
/***************************************************************************/
/* */
/* psnames.c */
/* */
/* FreeType PSNames module component (body only). */
/* */
/* Copyright 1996-2001 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. */
/* */
/***************************************************************************/
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include <ft2build.h>
#include "pspic.c"
#include "psmodule.c"
/* END */
+79
View File
@@ -0,0 +1,79 @@
/***************************************************************************/
/* */
/* pspic.c */
/* */
/* The FreeType position independent code services for psnames module. */
/* */
/* Copyright 2009, 2010 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* 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_FREETYPE_H
#include FT_INTERNAL_OBJECTS_H
#include "pspic.h"
#ifdef FT_CONFIG_OPTION_PIC
/* forward declaration of PIC init functions from psmodule.c */
FT_Error FT_Create_Class_pscmaps_services( FT_Library, FT_ServiceDescRec**);
void FT_Destroy_Class_pscmaps_services( FT_Library, FT_ServiceDescRec*);
void FT_Init_Class_pscmaps_interface( FT_Library, FT_Service_PsCMapsRec*);
void
psnames_module_class_pic_free( FT_Library library )
{
FT_PIC_Container* pic_container = &library->pic_container;
FT_Memory memory = library->memory;
if ( pic_container->psnames )
{
PSModulePIC* container = (PSModulePIC*)pic_container->psnames;
if(container->pscmaps_services)
FT_Destroy_Class_pscmaps_services(library, container->pscmaps_services);
container->pscmaps_services = NULL;
FT_FREE( container );
pic_container->psnames = NULL;
}
}
FT_Error
psnames_module_class_pic_init( FT_Library library )
{
FT_PIC_Container* pic_container = &library->pic_container;
FT_Error error = PSnames_Err_Ok;
PSModulePIC* container;
FT_Memory memory = library->memory;
/* allocate pointer, clear and set global container pointer */
if ( FT_ALLOC ( container, sizeof ( *container ) ) )
return error;
FT_MEM_SET( container, 0, sizeof(*container) );
pic_container->psnames = container;
/* initialize pointer table - this is how the module usually expects this data */
error = FT_Create_Class_pscmaps_services(library, &container->pscmaps_services);
if(error)
goto Exit;
FT_Init_Class_pscmaps_interface(library, &container->pscmaps_interface);
Exit:
if(error)
psnames_module_class_pic_free(library);
return error;
}
#endif /* FT_CONFIG_OPTION_PIC */
/* END */
+54
View File
@@ -0,0 +1,54 @@
/***************************************************************************/
/* */
/* pspic.h */
/* */
/* The FreeType position independent code services for psnames module. */
/* */
/* Copyright 2009 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* 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. */
/* */
/***************************************************************************/
#ifndef __PSPIC_H__
#define __PSPIC_H__
FT_BEGIN_HEADER
#include FT_INTERNAL_PIC_H
#ifndef FT_CONFIG_OPTION_PIC
#define FT_PSCMAPS_SERVICES_GET pscmaps_services
#define FT_PSCMAPS_INTERFACE_GET pscmaps_interface
#else /* FT_CONFIG_OPTION_PIC */
#include FT_SERVICE_POSTSCRIPT_CMAPS_H
typedef struct PSModulePIC_
{
FT_ServiceDescRec* pscmaps_services;
FT_Service_PsCMapsRec pscmaps_interface;
} PSModulePIC;
#define GET_PIC(lib) ((PSModulePIC*)((lib)->pic_container.psnames))
#define FT_PSCMAPS_SERVICES_GET (GET_PIC(library)->pscmaps_services)
#define FT_PSCMAPS_INTERFACE_GET (GET_PIC(library)->pscmaps_interface)
#endif /* FT_CONFIG_OPTION_PIC */
/* */
FT_END_HEADER
#endif /* __PSPIC_H__ */
/* END */
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More