mirror of
https://github.com/love2d/love-android.git
synced 2026-08-19 04:05:22 +02:00
added dependencies and build files (loosely inspired by Sebastian Dorda's love-native-android)
This commit is contained in:
@@ -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
@@ -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
@@ -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 */
|
||||
@@ -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
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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, © );
|
||||
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 */
|
||||
@@ -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
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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
Reference in New Issue
Block a user