Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 3917 → Rev 3918

/programs/develop/libraries/freetype/src/base/Jamfile
0,0 → 1,60
# FreeType 2 src/base Jamfile
#
# Copyright 2001, 2002, 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.
 
SubDir FT2_TOP $(FT2_SRC_DIR) base ;
 
 
{
local _sources ;
 
if $(FT2_MULTI)
{
_sources = ftadvanc ftcalc ftdbgmem ftgloadr
ftobjs ftoutln ftrfork ftsnames
ftstream fttrigon ftutil
basepic ftpic
;
}
else
{
_sources = ftbase ;
}
 
Library $(FT2_LIB) : $(_sources).c ;
}
 
# Add the optional/replaceable files.
#
{
local _sources = bbox bdf bitmap debug gasp
glyph gxval init lcdfil mm
otval pfr stroke synth system
type1 winfnt xf86 patent
;
 
Library $(FT2_LIB) : ft$(_sources).c ;
}
 
# Add Macintosh-specific file to the library when necessary.
#
if $(MAC)
{
Library $(FT2_LIB) : ftmac.c ;
}
else if $(OS) = MACOSX
{
if $(FT2_MULTI)
{
Library $(FT2_LIB) : ftmac.c ;
}
}
 
# end of src/base Jamfile
/programs/develop/libraries/freetype/src/base/basepic.c
0,0 → 1,108
/***************************************************************************/
/* */
/* basepic.c */
/* */
/* The FreeType position independent code services for base. */
/* */
/* Copyright 2009, 2012 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* clazz );
 
void
FT_Init_Class_ft_bitmap_glyph_class( FT_Glyph_Class* clazz );
 
#ifdef FT_CONFIG_OPTION_MAC_FONTS
/* forward declaration of PIC init function from ftrfork.c */
/* (not modularized) */
void
FT_Init_Table_raccess_guess_table( ft_raccess_guess_rec* record );
#endif
 
/* forward declaration of PIC init functions from ftinit.c */
FT_Error
ft_create_default_module_classes( FT_Library library );
 
void
ft_destroy_default_module_classes( FT_Library 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 = NULL;
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 );
#ifdef FT_CONFIG_OPTION_MAC_FONTS
FT_Init_Table_raccess_guess_table(
(ft_raccess_guess_rec*)&container->ft_raccess_guess_table );
#endif
 
Exit:
if ( error )
ft_base_pic_free( library );
return error;
}
 
#endif /* FT_CONFIG_OPTION_PIC */
 
 
/* END */
/programs/develop/libraries/freetype/src/base/basepic.h
0,0 → 1,90
/***************************************************************************/
/* */
/* 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
 
#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
#define FT_RACCESS_GUESS_TABLE_GET ft_raccess_guess_table
#endif
 
#else /* FT_CONFIG_OPTION_PIC */
 
#include FT_GLYPH_H
 
#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
#include FT_INTERNAL_RFORK_H
#endif
 
 
typedef struct BasePIC_
{
FT_Module_Class** default_module_classes;
FT_Glyph_Class ft_outline_glyph_class;
FT_Glyph_Class ft_bitmap_glyph_class;
 
#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
ft_raccess_guess_rec ft_raccess_guess_table[FT_RACCESS_N_RULES];
#endif
 
} 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 )
 
#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
#define FT_RACCESS_GUESS_TABLE_GET \
( GET_PIC( library )->ft_raccess_guess_table )
#endif
 
 
/* see basepic.c for the implementation */
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 */
/programs/develop/libraries/freetype/src/base/ftadvanc.c
0,0 → 1,162
/***************************************************************************/
/* */
/* ftadvanc.c */
/* */
/* Quick computation of advance widths (body). */
/* */
/* Copyright 2008, 2009, 2011, 2013 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_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_THROW( 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_THROW( Invalid_Face_Handle );
 
if ( gindex >= (FT_UInt)face->num_glyphs )
return FT_THROW( 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 ( FT_ERR_NEQ( error, 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_THROW( Invalid_Face_Handle );
 
num = (FT_UInt)face->num_glyphs;
end = start + count;
if ( start >= num || end < start || end > num )
return FT_THROW( 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 )
return _ft_face_scale_advances( face, padvances, count, flags );
 
if ( FT_ERR_NEQ( error, Unimplemented_Feature ) )
return error;
}
 
error = FT_Err_Ok;
 
if ( flags & FT_ADVANCE_FLAG_FAST_ONLY )
return FT_THROW( 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;
 
/* scale from 26.6 to 16.16 */
padvances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
? face->glyph->advance.y << 10
: face->glyph->advance.x << 10;
}
 
return error;
}
 
 
/* END */
/programs/develop/libraries/freetype/src/base/ftapi.c
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 */
/programs/develop/libraries/freetype/src/base/ftbase.c
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"
 
#ifdef FT_MACINTOSH
#include "ftmac.c"
#endif
 
/* END */
/programs/develop/libraries/freetype/src/base/ftbase.h
0,0 → 1,69
/***************************************************************************/
/* */
/* 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 );
 
 
#if defined( FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK ) && \
!defined( FT_MACINTOSH )
/* 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 )
ft_raccess_rule_by_darwin_vfs( FT_Library library, FT_UInt rule_index );
#endif
 
 
FT_END_HEADER
 
#endif /* __FTBASE_H__ */
 
 
/* END */
/programs/develop/libraries/freetype/src/base/ftbbox.c
0,0 → 1,649
/***************************************************************************/
/* */
/* ftbbox.c */
/* */
/* FreeType bbox computation (body). */
/* */
/* Copyright 1996-2002, 2004, 2006, 2010, 2013 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_INTERNAL_DEBUG_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 q1, q2, q3, q4;
 
 
q1 = p1;
q2 = p2;
q3 = p3;
q4 = p4;
 
/* for a conic segment to possibly reach new maximum */
/* one of its off-points must be above the current value */
while ( q2 > *max || q3 > *max )
{
/* determine which half contains the maximum and split */
if ( q1 + q2 > q3 + q4 ) /* first half */
{
q4 = q4 + q3;
q3 = q3 + q2;
q2 = q2 + q1;
q4 = q4 + q3;
q3 = q3 + q2;
q4 = ( q4 + q3 ) / 8;
q3 = q3 / 4;
q2 = q2 / 2;
}
else /* second half */
{
q1 = q1 + q2;
q2 = q2 + q3;
q3 = q3 + q4;
q1 = q1 + q2;
q2 = q2 + q3;
q1 = ( q1 + q2 ) / 8;
q2 = q2 / 4;
q3 = q3 / 2;
}
 
/* check if either end reached the maximum */
if ( q1 == q2 && q1 >= q3 )
{
*max = q1;
break;
}
if ( q3 == q4 && q2 <= q4 )
{
*max = q4;
break;
}
}
 
q1 = p1;
q2 = p2;
q3 = p3;
q4 = p4;
 
/* for a conic segment to possibly reach new minimum */
/* one of its off-points must be below the current value */
while ( q2 < *min || q3 < *min )
{
/* determine which half contains the minimum and split */
if ( q1 + q2 < q3 + q4 ) /* first half */
{
q4 = q4 + q3;
q3 = q3 + q2;
q2 = q2 + q1;
q4 = q4 + q3;
q3 = q3 + q2;
q4 = ( q4 + q3 ) / 8;
q3 = q3 / 4;
q2 = q2 / 2;
}
else /* second half */
{
q1 = q1 + q2;
q2 = q2 + q3;
q3 = q3 + q4;
q1 = q1 + q2;
q2 = q2 + q3;
q1 = ( q1 + q2 ) / 8;
q2 = q2 / 4;
q3 = q3 / 2;
}
 
/* check if either end reached the minimum */
if ( q1 == q2 && q1 <= q3 )
{
*min = q1;
break;
}
if ( q3 == q4 && q2 >= q4 )
{
*min = q4;
break;
}
}
}
 
#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. */
/* We already made sure that a, b, and c below cannot be all zero. */
{
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;
FT_Int shift;
 
 
/* 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-point values to ensure */
/* that their product is held in a `16.16' value including the sign. */
/* Necessarily, we need to shift `a', `b', and `c' so that the most */
/* significant bit of their absolute values is at position 22. */
/* */
/* This also means that we are using 23 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). */
 
shift = FT_MSB( FT_ABS( a ) | FT_ABS( b ) | FT_ABS( c ) );
 
if ( shift > 22 )
{
shift -= 22;
 
/* this loses some bits of precision, but we use 23 of them */
/* for the computation anyway */
a >>= shift;
b >>= shift;
c >>= shift;
}
else
{
shift = 22 - shift;
 
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_THROW( Invalid_Argument );
 
if ( !outline )
return FT_THROW( 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 */
/programs/develop/libraries/freetype/src/base/ftbdf.c
0,0 → 1,88
/***************************************************************************/
/* */
/* ftbdf.c */
/* */
/* FreeType API for accessing BDF-specific strings (body). */
/* */
/* Copyright 2002-2004, 2013 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_BDF_H
 
 
/* documentation is in ftbdf.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Get_BDF_Charset_ID( FT_Face face,
const char* *acharset_encoding,
const char* *acharset_registry )
{
FT_Error error;
const char* encoding = NULL;
const char* registry = NULL;
 
 
error = FT_ERR( Invalid_Argument );
 
if ( face )
{
FT_Service_BDF service;
 
 
FT_FACE_FIND_SERVICE( face, service, BDF );
 
if ( service && service->get_charset_id )
error = service->get_charset_id( face, &encoding, &registry );
}
 
if ( acharset_encoding )
*acharset_encoding = encoding;
 
if ( acharset_registry )
*acharset_registry = registry;
 
return error;
}
 
 
/* documentation is in ftbdf.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Get_BDF_Property( FT_Face face,
const char* prop_name,
BDF_PropertyRec *aproperty )
{
FT_Error error;
 
 
error = FT_ERR( Invalid_Argument );
 
aproperty->type = BDF_PROPERTY_TYPE_NONE;
 
if ( face )
{
FT_Service_BDF service;
 
 
FT_FACE_FIND_SERVICE( face, service, BDF );
 
if ( service && service->get_property )
error = service->get_property( face, prop_name, aproperty );
}
 
return error;
}
 
 
/* END */
/programs/develop/libraries/freetype/src/base/ftbitmap.c
0,0 → 1,758
/***************************************************************************/
/* */
/* ftbitmap.c */
/* */
/* FreeType utility functions for bitmaps (body). */
/* */
/* Copyright 2004-2009, 2011, 2013 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_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 = NULL;
 
 
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_THROW( 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_THROW( Invalid_Library_Handle );
 
if ( !bitmap || !bitmap->buffer )
return FT_THROW( Invalid_Argument );
 
if ( ( ( FT_PIX_ROUND( xStrength ) >> 6 ) > FT_INT_MAX ) ||
( ( FT_PIX_ROUND( yStrength ) >> 6 ) > FT_INT_MAX ) )
return FT_THROW( 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_THROW( 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;
 
case FT_PIXEL_MODE_BGRA:
/* We don't embolden color glyphs. */
return FT_Err_Ok;
}
 
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;
}
 
 
FT_Byte
ft_gray_for_premultiplied_srgb_bgra( const FT_Byte* bgra )
{
FT_Long a = bgra[3];
FT_Long b = bgra[0];
FT_Long g = bgra[1];
FT_Long r = bgra[2];
FT_Long l;
 
 
/*
* Luminosity for sRGB is defined using ~0.2126,0.7152,0.0722
* coefficients for RGB channels *on the linear colors*.
* A gamma of 2.2 is fair to assume. And then, we need to
* undo the premultiplication too.
*
* http://accessibility.kde.org/hsl-adjusted.php
*
* We do the computation with integers only.
*/
 
/* Undo premultification, get the number in a 16.16 form. */
b = FT_MulDiv( b, 65536, a );
g = FT_MulDiv( g, 65536, a );
r = FT_MulDiv( r, 65536, a );
a = a * 256;
 
/* Apply gamma of 2.0 instead of 2.2. */
b = FT_MulFix( b, b );
g = FT_MulFix( g, g );
r = FT_MulFix( r, r );
 
/* Apply coefficients. */
b = FT_MulFix( b, 4731 /* 0.0722 * 65536 */ );
g = FT_MulFix( g, 46871 /* 0.7152 * 65536 */ );
r = FT_MulFix( r, 13933 /* 0.2126 * 65536 */ );
 
l = r + g + b;
 
/*
* Final transparency can be determined this way:
*
* - If alpha is zero, we want 0.
* - If alpha is zero and luminosity is zero, we want 255.
* - If alpha is zero and luminosity is one, we want 0.
*
* So the formula is a * (1 - l).
*/
 
return (FT_Byte)( FT_MulFix( 65535 - l, a ) >> 8 );
}
 
 
/* 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_THROW( 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:
case FT_PIXEL_MODE_BGRA:
{
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->pitch > 0 &&
(FT_ULong)target->rows > FT_ULONG_MAX / target->pitch )
return FT_THROW( Invalid_Argument );
 
if ( target->rows * target->pitch > old_size &&
FT_QREALLOC( target->buffer,
old_size, target->rows * target->pitch ) )
return error;
}
break;
 
default:
error = FT_THROW( 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;
 
case FT_PIXEL_MODE_BGRA:
{
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_Byte* ss = s;
FT_Byte* tt = t;
FT_Int j;
 
 
for ( j = source->width; j > 0; j-- )
{
tt[0] = ft_gray_for_premultiplied_srgb_bgra( ss );
 
ss += 4;
tt += 1;
}
 
s += s_pitch;
t += t_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_THROW( Invalid_Library_Handle );
 
if ( !bitmap )
return FT_THROW( Invalid_Argument );
 
memory = library->memory;
 
FT_FREE( bitmap->buffer );
*bitmap = null_bitmap;
 
return FT_Err_Ok;
}
 
 
/* END */
/programs/develop/libraries/freetype/src/base/ftcalc.c
0,0 → 1,974
/***************************************************************************/
/* */
/* ftcalc.c */
/* */
/* Arithmetic computations (body). */
/* */
/* Copyright 1996-2006, 2008, 2012-2013 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_TRIGONOMETRY_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 emulate a 64-bit data type if a real one isn't available */
 
#ifndef FT_LONG64
 
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 );
}
 
 
FT_BASE_DEF ( FT_Int )
FT_MSB( FT_UInt32 z )
{
FT_Int shift = 0;
 
/* 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;
}
 
return shift;
}
 
 
/* documentation is in ftcalc.h */
 
FT_BASE_DEF( FT_Fixed )
FT_Hypot( FT_Fixed x,
FT_Fixed y )
{
FT_Vector v;
 
 
v.x = x;
v.y = y;
 
return FT_Vector_Length( &v );
}
 
 
#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;
}
 
 
/* 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;
}
 
 
/* 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_UInt64)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 >= 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 ( (FT_Int32)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 );
}
 
 
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 ( (FT_Int32)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 );
}
 
 
/* 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 ( (FT_UInt32)b == 0 )
{
/* check for division by 0 */
q = (FT_UInt32)0x7FFFFFFFL;
}
else if ( ( a >> 16 ) == 0 )
{
/* compute result directly */
q = (FT_UInt32)( ( (FT_ULong)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_THROW( Invalid_Argument );
 
/* compute discriminant */
delta = FT_MulFix( matrix->xx, matrix->yy ) -
FT_MulFix( matrix->xy, matrix->yx );
 
if ( !delta )
return FT_THROW( 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 */
/programs/develop/libraries/freetype/src/base/ftcid.c
0,0 → 1,117
/***************************************************************************/
/* */
/* ftcid.c */
/* */
/* FreeType API for accessing CID font information. */
/* */
/* Copyright 2007, 2009, 2013 by Derek Clegg, Michael Toftdal. */
/* */
/* 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_CID_H
#include FT_INTERNAL_OBJECTS_H
#include FT_SERVICE_CID_H
 
 
/* documentation is in ftcid.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Get_CID_Registry_Ordering_Supplement( FT_Face face,
const char* *registry,
const char* *ordering,
FT_Int *supplement)
{
FT_Error error;
const char* r = NULL;
const char* o = NULL;
FT_Int s = 0;
 
 
error = FT_ERR( Invalid_Argument );
 
if ( face )
{
FT_Service_CID service;
 
 
FT_FACE_FIND_SERVICE( face, service, CID );
 
if ( service && service->get_ros )
error = service->get_ros( face, &r, &o, &s );
}
 
if ( registry )
*registry = r;
 
if ( ordering )
*ordering = o;
 
if ( supplement )
*supplement = s;
 
return error;
}
 
 
FT_EXPORT_DEF( FT_Error )
FT_Get_CID_Is_Internally_CID_Keyed( FT_Face face,
FT_Bool *is_cid )
{
FT_Error error = FT_ERR( Invalid_Argument );
FT_Bool ic = 0;
 
 
if ( face )
{
FT_Service_CID service;
 
 
FT_FACE_FIND_SERVICE( face, service, CID );
 
if ( service && service->get_is_cid )
error = service->get_is_cid( face, &ic);
}
 
if ( is_cid )
*is_cid = ic;
 
return error;
}
 
 
FT_EXPORT_DEF( FT_Error )
FT_Get_CID_From_Glyph_Index( FT_Face face,
FT_UInt glyph_index,
FT_UInt *cid )
{
FT_Error error = FT_ERR( Invalid_Argument );
FT_UInt c = 0;
 
 
if ( face )
{
FT_Service_CID service;
 
 
FT_FACE_FIND_SERVICE( face, service, CID );
 
if ( service && service->get_cid_from_glyph_index )
error = service->get_cid_from_glyph_index( face, glyph_index, &c);
}
 
if ( cid )
*cid = c;
 
return error;
}
 
 
/* END */
/programs/develop/libraries/freetype/src/base/ftdbgmem.c
0,0 → 1,992
/***************************************************************************/
/* */
/* ftdbgmem.c */
/* */
/* Memory debugger (body). */
/* */
/* Copyright 2001-2006, 2009, 2013 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_Long leak_count = 0;
FT_ULong leaks = 0;
 
 
FT_DumpMemory( table->memory );
 
/* remove all blocks from the table, revealing leaked ones */
for ( i = 0; i < table->size; i++ )
{
FT_MemNode *pnode = table->buckets + i, next, node = *pnode;
 
 
while ( node )
{
next = node->link;
node->link = 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 */
/programs/develop/libraries/freetype/src/base/ftdebug.c
0,0 → 1,266
/***************************************************************************/
/* */
/* ftdebug.c */
/* */
/* Debugging and logging component (body). */
/* */
/* Copyright 1996-2001, 2002, 2004, 2008, 2013 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 );
}
 
 
/* documentation is in ftdebug.h */
 
FT_BASE_DEF( int )
FT_Throw( FT_Error error,
int line,
const char* file )
{
FT_UNUSED( error );
FT_UNUSED( line );
FT_UNUSED( file );
 
return 0;
}
 
#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 )
break;
 
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 */
/programs/develop/libraries/freetype/src/base/ftfstype.c
0,0 → 1,62
/***************************************************************************/
/* */
/* ftfstype.c */
/* */
/* FreeType utility file to access FSType data (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_TYPE1_TABLES_H
#include FT_TRUETYPE_TABLES_H
#include FT_INTERNAL_SERVICE_H
#include FT_SERVICE_POSTSCRIPT_INFO_H
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_UShort )
FT_Get_FSType_Flags( FT_Face face )
{
TT_OS2* os2;
 
 
/* first, try to get the fs_type directly from the font */
if ( face )
{
FT_Service_PsInfo service = NULL;
 
 
FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
 
if ( service && service->ps_get_font_extra )
{
PS_FontExtraRec extra;
 
 
if ( !service->ps_get_font_extra( face, &extra ) &&
extra.fs_type != 0 )
return extra.fs_type;
}
}
 
/* look at FSType before fsType for Type42 */
 
if ( ( os2 = (TT_OS2*)FT_Get_Sfnt_Table( face, ft_sfnt_os2 ) ) != NULL &&
os2->version != 0xFFFFU )
return os2->fsType;
 
return 0;
}
 
 
/* END */
/programs/develop/libraries/freetype/src/base/ftgasp.c
0,0 → 1,61
/***************************************************************************/
/* */
/* ftgasp.c */
/* */
/* Access of TrueType's `gasp' table (body). */
/* */
/* Copyright 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_GASP_H
#include FT_INTERNAL_TRUETYPE_TYPES_H
 
 
FT_EXPORT_DEF( FT_Int )
FT_Get_Gasp( FT_Face face,
FT_UInt ppem )
{
FT_Int result = FT_GASP_NO_TABLE;
 
 
if ( face && FT_IS_SFNT( face ) )
{
TT_Face ttface = (TT_Face)face;
 
 
if ( ttface->gasp.numRanges > 0 )
{
TT_GaspRange range = ttface->gasp.gaspRanges;
TT_GaspRange range_end = range + ttface->gasp.numRanges;
 
 
while ( ppem > range->maxPPEM )
{
range++;
if ( range >= range_end )
goto Exit;
}
 
result = range->gaspFlag;
 
/* ensure that we don't have spurious bits */
if ( ttface->gasp.version == 0 )
result &= 3;
}
}
Exit:
return result;
}
 
 
/* END */
/programs/develop/libraries/freetype/src/base/ftgloadr.c
0,0 → 1,405
/***************************************************************************/
/* */
/* ftgloadr.c */
/* */
/* The FreeType glyph loader (body). */
/* */
/* Copyright 2002-2006, 2010, 2013 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_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_THROW( 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_THROW( 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:
if ( error )
FT_GlyphLoader_Reset( loader );
 
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 */
/programs/develop/libraries/freetype/src/base/ftglyph.c
0,0 → 1,629
/***************************************************************************/
/* */
/* ftglyph.c */
/* */
/* FreeType convenience functions to handle glyphs (body). */
/* */
/* Copyright 1996-2005, 2007, 2008, 2010, 2012, 2013 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_INTERNAL_DEBUG_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_THROW( 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_THROW( 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_THROW( Invalid_Argument );
goto Exit;
}
 
*target = 0;
 
if ( !source || !source->clazz )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
 
clazz = source->clazz;
error = ft_new_glyph( source->library, clazz, &copy );
if ( error )
goto Exit;
 
copy->advance = source->advance;
copy->format = source->format;
 
if ( clazz->glyph_copy )
error = clazz->glyph_copy( source, copy );
 
if ( error )
FT_Done_Glyph( copy );
else
*target = copy;
 
Exit:
return error;
}
 
 
/* documentation is in ftglyph.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Get_Glyph( FT_GlyphSlot slot,
FT_Glyph *aglyph )
{
FT_Library library;
FT_Error error;
FT_Glyph glyph;
 
const FT_Glyph_Class* clazz = 0;
 
 
if ( !slot )
return FT_THROW( Invalid_Slot_Handle );
 
library = slot->library;
 
if ( !aglyph )
return FT_THROW( 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_THROW( 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_THROW( 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_THROW( 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 b, glyph;
FT_BitmapGlyph bitmap = NULL;
const FT_Glyph_Class* clazz;
 
/* FT_BITMAP_GLYPH_CLASS_GET derefers `library' in PIC mode */
FT_Library library;
 
 
/* check argument */
if ( !the_glyph )
goto Bad;
glyph = *the_glyph;
if ( !glyph )
goto Bad;
 
clazz = glyph->clazz;
library = glyph->library;
if ( !library || !clazz )
goto Bad;
 
/* when called with a bitmap glyph, do nothing and return successfully */
if ( clazz == FT_BITMAP_GLYPH_CLASS_GET )
goto Exit;
 
if ( !clazz->glyph_prepare )
goto Bad;
 
/* we render the glyph into a glyph bitmap using a `dummy' glyph slot */
/* then calling FT_Render_Glyph_Internal() */
 
FT_MEM_ZERO( &dummy, sizeof ( dummy ) );
FT_MEM_ZERO( &dummy_internal, sizeof ( dummy_internal ) );
dummy.internal = &dummy_internal;
dummy.library = library;
dummy.format = clazz->glyph_format;
 
/* create result bitmap glyph */
error = ft_new_glyph( library, FT_BITMAP_GLYPH_CLASS_GET, &b );
if ( error )
goto Exit;
bitmap = (FT_BitmapGlyph)b;
 
#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_THROW( 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 */
/programs/develop/libraries/freetype/src/base/ftgxval.c
0,0 → 1,142
/***************************************************************************/
/* */
/* ftgxval.c */
/* */
/* FreeType API for validating TrueTyepGX/AAT tables (body). */
/* */
/* Copyright 2004-2006, 2010, 2013 by */
/* Masatake YAMATO, Redhat K.K, */
/* 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. */
/* */
/***************************************************************************/
 
/***************************************************************************/
/* */
/* gxvalid is derived from both gxlayout module and otvalid module. */
/* Development of gxlayout is supported by the Information-technology */
/* Promotion Agency(IPA), Japan. */
/* */
/***************************************************************************/
 
 
#include <ft2build.h>
#include FT_INTERNAL_DEBUG_H
 
#include FT_INTERNAL_OBJECTS_H
#include FT_SERVICE_GX_VALIDATE_H
 
 
/* documentation is in ftgxval.h */
 
FT_EXPORT_DEF( FT_Error )
FT_TrueTypeGX_Validate( FT_Face face,
FT_UInt validation_flags,
FT_Bytes tables[FT_VALIDATE_GX_LENGTH],
FT_UInt table_length )
{
FT_Service_GXvalidate service;
FT_Error error;
 
 
if ( !face )
{
error = FT_THROW( Invalid_Face_Handle );
goto Exit;
}
 
if ( tables == NULL )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
 
FT_FACE_FIND_GLOBAL_SERVICE( face, service, GX_VALIDATE );
 
if ( service )
error = service->validate( face,
validation_flags,
tables,
table_length );
else
error = FT_THROW( Unimplemented_Feature );
 
Exit:
return error;
}
 
 
FT_EXPORT_DEF( void )
FT_TrueTypeGX_Free( FT_Face face,
FT_Bytes table )
{
FT_Memory memory;
 
 
if ( !face )
return;
 
memory = FT_FACE_MEMORY( face );
 
FT_FREE( table );
}
 
 
FT_EXPORT_DEF( FT_Error )
FT_ClassicKern_Validate( FT_Face face,
FT_UInt validation_flags,
FT_Bytes *ckern_table )
{
FT_Service_CKERNvalidate service;
FT_Error error;
 
 
if ( !face )
{
error = FT_THROW( Invalid_Face_Handle );
goto Exit;
}
 
if ( ckern_table == NULL )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
 
FT_FACE_FIND_GLOBAL_SERVICE( face, service, CLASSICKERN_VALIDATE );
 
if ( service )
error = service->validate( face,
validation_flags,
ckern_table );
else
error = FT_THROW( Unimplemented_Feature );
 
Exit:
return error;
}
 
 
FT_EXPORT_DEF( void )
FT_ClassicKern_Free( FT_Face face,
FT_Bytes table )
{
FT_Memory memory;
 
 
if ( !face )
return;
 
memory = FT_FACE_MEMORY( face );
 
 
FT_FREE( table );
}
 
 
/* END */
/programs/develop/libraries/freetype/src/base/ftinit.c
0,0 → 1,282
/***************************************************************************/
/* */
/* ftinit.c */
/* */
/* FreeType initialization layer (body). */
/* */
/* Copyright 1996-2002, 2005, 2007, 2009, 2012, 2013 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 = NULL;
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;
 
 
/* FT_DEFAULT_MODULES_GET dereferences `library' in PIC mode */
#ifdef FT_CONFIG_OPTION_PIC
if ( !library )
return;
#endif
 
/* GCC 4.6 warns the type difference:
* FT_Module_Class** != const FT_Module_Class* const*
*/
cur = (const FT_Module_Class* const*)FT_DEFAULT_MODULES_GET;
 
/* test for valid `library' delayed to FT_Add_Module() */
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_THROW( Unimplemented_Feature );
}
 
/* build a library out of it, then fill it with the set of */
/* default drivers. */
 
error = FT_New_Library( memory, alibrary );
if ( error )
FT_Done_Memory( memory );
else
FT_Add_Default_Modules( *alibrary );
 
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 */
/programs/develop/libraries/freetype/src/base/ftlcdfil.c
0,0 → 1,378
/***************************************************************************/
/* */
/* ftlcdfil.c */
/* */
/* FreeType API for color filtering of subpixel bitmap glyphs (body). */
/* */
/* Copyright 2006, 2008-2010, 2013 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_LCD_FILTER_H
#include FT_IMAGE_H
#include FT_INTERNAL_OBJECTS_H
 
 
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
 
/* define USE_LEGACY to implement the legacy filter */
#define USE_LEGACY
 
/* FIR filter used by the default and light filters */
static void
_ft_lcd_filter_fir( FT_Bitmap* bitmap,
FT_Render_Mode mode,
FT_Library library )
{
FT_Byte* weights = library->lcd_weights;
FT_UInt width = (FT_UInt)bitmap->width;
FT_UInt height = (FT_UInt)bitmap->rows;
 
 
/* horizontal in-place FIR filter */
if ( mode == FT_RENDER_MODE_LCD && width >= 4 )
{
FT_Byte* line = bitmap->buffer;
 
 
for ( ; height > 0; height--, line += bitmap->pitch )
{
FT_UInt fir[5];
FT_UInt val1, xx;
 
 
val1 = line[0];
fir[0] = weights[2] * val1;
fir[1] = weights[3] * val1;
fir[2] = weights[4] * val1;
fir[3] = 0;
fir[4] = 0;
 
val1 = line[1];
fir[0] += weights[1] * val1;
fir[1] += weights[2] * val1;
fir[2] += weights[3] * val1;
fir[3] += weights[4] * val1;
 
for ( xx = 2; xx < width; xx++ )
{
FT_UInt val, pix;
 
 
val = line[xx];
pix = fir[0] + weights[0] * val;
fir[0] = fir[1] + weights[1] * val;
fir[1] = fir[2] + weights[2] * val;
fir[2] = fir[3] + weights[3] * val;
fir[3] = weights[4] * val;
 
pix >>= 8;
pix |= -( pix >> 8 );
line[xx - 2] = (FT_Byte)pix;
}
 
{
FT_UInt pix;
 
 
pix = fir[0] >> 8;
pix |= -( pix >> 8 );
line[xx - 2] = (FT_Byte)pix;
 
pix = fir[1] >> 8;
pix |= -( pix >> 8 );
line[xx - 1] = (FT_Byte)pix;
}
}
}
 
/* vertical in-place FIR filter */
else if ( mode == FT_RENDER_MODE_LCD_V && height >= 4 )
{
FT_Byte* column = bitmap->buffer;
FT_Int pitch = bitmap->pitch;
 
 
for ( ; width > 0; width--, column++ )
{
FT_Byte* col = column;
FT_UInt fir[5];
FT_UInt val1, yy;
 
 
val1 = col[0];
fir[0] = weights[2] * val1;
fir[1] = weights[3] * val1;
fir[2] = weights[4] * val1;
fir[3] = 0;
fir[4] = 0;
col += pitch;
 
val1 = col[0];
fir[0] += weights[1] * val1;
fir[1] += weights[2] * val1;
fir[2] += weights[3] * val1;
fir[3] += weights[4] * val1;
col += pitch;
 
for ( yy = 2; yy < height; yy++ )
{
FT_UInt val, pix;
 
 
val = col[0];
pix = fir[0] + weights[0] * val;
fir[0] = fir[1] + weights[1] * val;
fir[1] = fir[2] + weights[2] * val;
fir[2] = fir[3] + weights[3] * val;
fir[3] = weights[4] * val;
 
pix >>= 8;
pix |= -( pix >> 8 );
col[-2 * pitch] = (FT_Byte)pix;
col += pitch;
}
 
{
FT_UInt pix;
 
 
pix = fir[0] >> 8;
pix |= -( pix >> 8 );
col[-2 * pitch] = (FT_Byte)pix;
 
pix = fir[1] >> 8;
pix |= -( pix >> 8 );
col[-pitch] = (FT_Byte)pix;
}
}
}
}
 
 
#ifdef USE_LEGACY
 
/* intra-pixel filter used by the legacy filter */
static void
_ft_lcd_filter_legacy( FT_Bitmap* bitmap,
FT_Render_Mode mode,
FT_Library library )
{
FT_UInt width = (FT_UInt)bitmap->width;
FT_UInt height = (FT_UInt)bitmap->rows;
FT_Int pitch = bitmap->pitch;
 
static const int filters[3][3] =
{
{ 65538 * 9/13, 65538 * 1/6, 65538 * 1/13 },
{ 65538 * 3/13, 65538 * 4/6, 65538 * 3/13 },
{ 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 }
};
 
FT_UNUSED( library );
 
 
/* horizontal in-place intra-pixel filter */
if ( mode == FT_RENDER_MODE_LCD && width >= 3 )
{
FT_Byte* line = bitmap->buffer;
 
 
for ( ; height > 0; height--, line += pitch )
{
FT_UInt xx;
 
 
for ( xx = 0; xx < width; xx += 3 )
{
FT_UInt r = 0;
FT_UInt g = 0;
FT_UInt b = 0;
FT_UInt p;
 
 
p = line[xx];
r += filters[0][0] * p;
g += filters[0][1] * p;
b += filters[0][2] * p;
 
p = line[xx + 1];
r += filters[1][0] * p;
g += filters[1][1] * p;
b += filters[1][2] * p;
 
p = line[xx + 2];
r += filters[2][0] * p;
g += filters[2][1] * p;
b += filters[2][2] * p;
 
line[xx] = (FT_Byte)( r / 65536 );
line[xx + 1] = (FT_Byte)( g / 65536 );
line[xx + 2] = (FT_Byte)( b / 65536 );
}
}
}
else if ( mode == FT_RENDER_MODE_LCD_V && height >= 3 )
{
FT_Byte* column = bitmap->buffer;
 
 
for ( ; width > 0; width--, column++ )
{
FT_Byte* col = column;
FT_Byte* col_end = col + height * pitch;
 
 
for ( ; col < col_end; col += 3 * pitch )
{
FT_UInt r = 0;
FT_UInt g = 0;
FT_UInt b = 0;
FT_UInt p;
 
 
p = col[0];
r += filters[0][0] * p;
g += filters[0][1] * p;
b += filters[0][2] * p;
 
p = col[pitch];
r += filters[1][0] * p;
g += filters[1][1] * p;
b += filters[1][2] * p;
 
p = col[pitch * 2];
r += filters[2][0] * p;
g += filters[2][1] * p;
b += filters[2][2] * p;
 
col[0] = (FT_Byte)( r / 65536 );
col[pitch] = (FT_Byte)( g / 65536 );
col[2 * pitch] = (FT_Byte)( b / 65536 );
}
}
}
}
 
#endif /* USE_LEGACY */
 
 
FT_EXPORT_DEF( FT_Error )
FT_Library_SetLcdFilterWeights( FT_Library library,
unsigned char *weights )
{
if ( !library || !weights )
return FT_THROW( Invalid_Argument );
 
ft_memcpy( library->lcd_weights, weights, 5 );
 
return FT_Err_Ok;
}
 
 
FT_EXPORT_DEF( FT_Error )
FT_Library_SetLcdFilter( FT_Library library,
FT_LcdFilter filter )
{
static const FT_Byte light_filter[5] =
{ 0x00, 0x55, 0x56, 0x55, 0x00 };
/* the values here sum up to a value larger than 256, */
/* providing a cheap gamma correction */
static const FT_Byte default_filter[5] =
{ 0x10, 0x40, 0x70, 0x40, 0x10 };
 
 
if ( !library )
return FT_THROW( Invalid_Argument );
 
switch ( filter )
{
case FT_LCD_FILTER_NONE:
library->lcd_filter_func = NULL;
library->lcd_extra = 0;
break;
 
case FT_LCD_FILTER_DEFAULT:
#if defined( FT_FORCE_LEGACY_LCD_FILTER )
 
library->lcd_filter_func = _ft_lcd_filter_legacy;
library->lcd_extra = 0;
 
#elif defined( FT_FORCE_LIGHT_LCD_FILTER )
 
ft_memcpy( library->lcd_weights, light_filter, 5 );
library->lcd_filter_func = _ft_lcd_filter_fir;
library->lcd_extra = 2;
 
#else
 
ft_memcpy( library->lcd_weights, default_filter, 5 );
library->lcd_filter_func = _ft_lcd_filter_fir;
library->lcd_extra = 2;
 
#endif
 
break;
 
case FT_LCD_FILTER_LIGHT:
ft_memcpy( library->lcd_weights, light_filter, 5 );
library->lcd_filter_func = _ft_lcd_filter_fir;
library->lcd_extra = 2;
break;
 
#ifdef USE_LEGACY
 
case FT_LCD_FILTER_LEGACY:
library->lcd_filter_func = _ft_lcd_filter_legacy;
library->lcd_extra = 0;
break;
 
#endif
 
default:
return FT_THROW( Invalid_Argument );
}
 
library->lcd_filter = filter;
 
return FT_Err_Ok;
}
 
#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
 
FT_EXPORT_DEF( FT_Error )
FT_Library_SetLcdFilterWeights( FT_Library library,
unsigned char *weights )
{
FT_UNUSED( library );
FT_UNUSED( weights );
 
return FT_THROW( Unimplemented_Feature );
}
 
 
FT_EXPORT_DEF( FT_Error )
FT_Library_SetLcdFilter( FT_Library library,
FT_LcdFilter filter )
{
FT_UNUSED( library );
FT_UNUSED( filter );
 
return FT_THROW( Unimplemented_Feature );
}
 
#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
 
 
/* END */
/programs/develop/libraries/freetype/src/base/ftmac.c
0,0 → 1,1061
/***************************************************************************/
/* */
/* ftmac.c */
/* */
/* Mac FOND support. Written by just@letterror.com. */
/* Heavily modified by mpsuzuki, George Williams, and Sean McBride. */
/* */
/* This file is for Mac OS X only; see builds/mac/ftoldmac.c for */
/* classic platforms built by MPW. */
/* */
/* Copyright 1996-2009, 2013 by */
/* Just van Rossum, 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. */
/* */
/***************************************************************************/
 
 
/*
Notes
 
Mac suitcase files can (and often do!) contain multiple fonts. To
support this I use the face_index argument of FT_(Open|New)_Face()
functions, and pretend the suitcase file is a collection.
 
Warning: fbit and NFNT bitmap resources are not supported yet. In old
sfnt fonts, bitmap glyph data for each size is stored in each `NFNT'
resources instead of the `bdat' table in the sfnt resource. Therefore,
face->num_fixed_sizes is set to 0, because bitmap data in `NFNT'
resource is unavailable at present.
 
The Mac FOND support works roughly like this:
 
- Check whether the offered stream points to a Mac suitcase file. This
is done by checking the file type: it has to be 'FFIL' or 'tfil'. The
stream that gets passed to our init_face() routine is a stdio stream,
which isn't usable for us, since the FOND resources live in the
resource fork. So we just grab the stream->pathname field.
 
- Read the FOND resource into memory, then check whether there is a
TrueType font and/or(!) a Type 1 font available.
 
- If there is a Type 1 font available (as a separate `LWFN' file), read
its data into memory, massage it slightly so it becomes PFB data, wrap
it into a memory stream, load the Type 1 driver and delegate the rest
of the work to it by calling FT_Open_Face(). (XXX TODO: after this
has been done, the kerning data from the FOND resource should be
appended to the face: On the Mac there are usually no AFM files
available. However, this is tricky since we need to map Mac char
codes to ps glyph names to glyph ID's...)
 
- If there is a TrueType font (an `sfnt' resource), read it into memory,
wrap it into a memory stream, load the TrueType driver and delegate
the rest of the work to it, by calling FT_Open_Face().
 
- Some suitcase fonts (notably Onyx) might point the `LWFN' file to
itself, even though it doesn't contains `POST' resources. To handle
this special case without opening the file an extra time, we just
ignore errors from the `LWFN' and fallback to the `sfnt' if both are
available.
*/
 
 
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_TRUETYPE_TAGS_H
#include FT_INTERNAL_STREAM_H
#include "ftbase.h"
 
/* This is for Mac OS X. Without redefinition, OS_INLINE */
/* expands to `static inline' which doesn't survive the */
/* -ansi compilation flag of GCC. */
#if !HAVE_ANSI_OS_INLINE
#undef OS_INLINE
#define OS_INLINE static __inline__
#endif
 
/* `configure' checks the availability of `ResourceIndex' strictly */
/* and sets HAVE_TYPE_RESOURCE_INDEX 1 or 0 always. If it is */
/* not set (e.g., a build without `configure'), the availability */
/* is guessed from the SDK version. */
#ifndef HAVE_TYPE_RESOURCE_INDEX
#if !defined( MAC_OS_X_VERSION_10_5 ) || \
( MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 )
#define HAVE_TYPE_RESOURCE_INDEX 0
#else
#define HAVE_TYPE_RESOURCE_INDEX 1
#endif
#endif /* !HAVE_TYPE_RESOURCE_INDEX */
 
#if ( HAVE_TYPE_RESOURCE_INDEX == 0 )
typedef short ResourceIndex;
#endif
 
#include <CoreServices/CoreServices.h>
#include <ApplicationServices/ApplicationServices.h>
#include <sys/syslimits.h> /* PATH_MAX */
 
/* Don't want warnings about our own use of deprecated functions. */
#define FT_DEPRECATED_ATTRIBUTE
 
#include FT_MAC_H
 
#ifndef kATSOptionFlagsUnRestrictedScope /* since Mac OS X 10.1 */
#define kATSOptionFlagsUnRestrictedScope kATSOptionFlagsDefault
#endif
 
 
/* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
TrueType in case *both* are available (this is not common,
but it *is* possible). */
#ifndef PREFER_LWFN
#define PREFER_LWFN 1
#endif
 
 
#ifdef FT_MACINTOSH
 
/* This function is deprecated because FSSpec is deprecated in Mac OS X */
FT_EXPORT_DEF( FT_Error )
FT_GetFile_From_Mac_Name( const char* fontName,
FSSpec* pathSpec,
FT_Long* face_index )
{
FT_UNUSED( fontName );
FT_UNUSED( pathSpec );
FT_UNUSED( face_index );
 
return FT_THROW( Unimplemented_Feature );
}
 
 
/* Private function. */
/* The FSSpec type has been discouraged for a long time, */
/* unfortunately an FSRef replacement API for */
/* ATSFontGetFileSpecification() is only available in */
/* Mac OS X 10.5 and later. */
static OSStatus
FT_ATSFontGetFileReference( ATSFontRef ats_font_id,
FSRef* ats_font_ref )
{
#if defined( MAC_OS_X_VERSION_10_5 ) && \
( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
 
OSStatus err;
 
err = ATSFontGetFileReference( ats_font_id, ats_font_ref );
 
return err;
#elif __LP64__ /* No 64bit Carbon API on legacy platforms */
FT_UNUSED( ats_font_id );
FT_UNUSED( ats_font_ref );
 
 
return fnfErr;
#else /* 32bit Carbon API on legacy platforms */
OSStatus err;
FSSpec spec;
 
 
err = ATSFontGetFileSpecification( ats_font_id, &spec );
if ( noErr == err )
err = FSpMakeFSRef( &spec, ats_font_ref );
 
return err;
#endif
}
 
 
static FT_Error
FT_GetFileRef_From_Mac_ATS_Name( const char* fontName,
FSRef* ats_font_ref,
FT_Long* face_index )
{
CFStringRef cf_fontName;
ATSFontRef ats_font_id;
 
 
*face_index = 0;
 
cf_fontName = CFStringCreateWithCString( NULL, fontName,
kCFStringEncodingMacRoman );
ats_font_id = ATSFontFindFromName( cf_fontName,
kATSOptionFlagsUnRestrictedScope );
CFRelease( cf_fontName );
 
if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL )
return FT_THROW( Unknown_File_Format );
 
if ( noErr != FT_ATSFontGetFileReference( ats_font_id, ats_font_ref ) )
return FT_THROW( Unknown_File_Format );
 
/* face_index calculation by searching preceding fontIDs */
/* with same FSRef */
{
ATSFontRef id2 = ats_font_id - 1;
FSRef ref2;
 
 
while ( id2 > 0 )
{
if ( noErr != FT_ATSFontGetFileReference( id2, &ref2 ) )
break;
if ( noErr != FSCompareFSRefs( ats_font_ref, &ref2 ) )
break;
 
id2 --;
}
*face_index = ats_font_id - ( id2 + 1 );
}
 
return FT_Err_Ok;
}
 
 
FT_EXPORT_DEF( FT_Error )
FT_GetFilePath_From_Mac_ATS_Name( const char* fontName,
UInt8* path,
UInt32 maxPathSize,
FT_Long* face_index )
{
FSRef ref;
FT_Error err;
 
 
err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
if ( err )
return err;
 
if ( noErr != FSRefMakePath( &ref, path, maxPathSize ) )
return FT_THROW( Unknown_File_Format );
 
return FT_Err_Ok;
}
 
 
/* This function is deprecated because FSSpec is deprecated in Mac OS X */
FT_EXPORT_DEF( FT_Error )
FT_GetFile_From_Mac_ATS_Name( const char* fontName,
FSSpec* pathSpec,
FT_Long* face_index )
{
#if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
FT_UNUSED( fontName );
FT_UNUSED( pathSpec );
FT_UNUSED( face_index );
 
return FT_THROW( Unimplemented_Feature );
#else
FSRef ref;
FT_Error err;
 
 
err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
if ( err )
return err;
 
if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL,
pathSpec, NULL ) )
return FT_THROW( Unknown_File_Format );
 
return FT_Err_Ok;
#endif
}
 
 
static OSErr
FT_FSPathMakeRes( const UInt8* pathname,
ResFileRefNum* res )
{
OSErr err;
FSRef ref;
 
 
if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
return FT_THROW( Cannot_Open_Resource );
 
/* at present, no support for dfont format */
err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res );
if ( noErr == err )
return err;
 
/* fallback to original resource-fork font */
*res = FSOpenResFile( &ref, fsRdPerm );
err = ResError();
 
return err;
}
 
 
/* Return the file type for given pathname */
static OSType
get_file_type_from_path( const UInt8* pathname )
{
FSRef ref;
FSCatalogInfo info;
 
 
if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
return ( OSType ) 0;
 
if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoFinderInfo, &info,
NULL, NULL, NULL ) )
return ( OSType ) 0;
 
return ((FInfo *)(info.finderInfo))->fdType;
}
 
 
/* Given a PostScript font name, create the Macintosh LWFN file name. */
static void
create_lwfn_name( char* ps_name,
Str255 lwfn_file_name )
{
int max = 5, count = 0;
FT_Byte* p = lwfn_file_name;
FT_Byte* q = (FT_Byte*)ps_name;
 
 
lwfn_file_name[0] = 0;
 
while ( *q )
{
if ( ft_isupper( *q ) )
{
if ( count )
max = 3;
count = 0;
}
if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) )
{
*++p = *q;
lwfn_file_name[0]++;
count++;
}
q++;
}
}
 
 
static short
count_faces_sfnt( char* fond_data )
{
/* The count is 1 greater than the value in the FOND. */
/* Isn't that cute? :-) */
 
return EndianS16_BtoN( *( (short*)( fond_data +
sizeof ( FamRec ) ) ) ) + 1;
}
 
 
static short
count_faces_scalable( char* fond_data )
{
AsscEntry* assoc;
short i, face, face_all;
 
 
face_all = EndianS16_BtoN( *( (short *)( fond_data +
sizeof ( FamRec ) ) ) ) + 1;
assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
face = 0;
 
for ( i = 0; i < face_all; i++ )
{
if ( 0 == EndianS16_BtoN( assoc[i].fontSize ) )
face++;
}
return face;
}
 
 
/* Look inside the FOND data, answer whether there should be an SFNT
resource, and answer the name of a possible LWFN Type 1 file.
 
Thanks to Paul Miller (paulm@profoundeffects.com) for the fix
to load a face OTHER than the first one in the FOND!
*/
 
 
static void
parse_fond( char* fond_data,
short* have_sfnt,
ResID* sfnt_id,
Str255 lwfn_file_name,
short face_index )
{
AsscEntry* assoc;
AsscEntry* base_assoc;
FamRec* fond;
 
 
*sfnt_id = 0;
*have_sfnt = 0;
lwfn_file_name[0] = 0;
 
fond = (FamRec*)fond_data;
assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
base_assoc = assoc;
 
/* the maximum faces in a FOND is 48, size of StyleTable.indexes[] */
if ( 47 < face_index )
return;
 
/* Let's do a little range checking before we get too excited here */
if ( face_index < count_faces_sfnt( fond_data ) )
{
assoc += face_index; /* add on the face_index! */
 
/* if the face at this index is not scalable,
fall back to the first one (old behavior) */
if ( EndianS16_BtoN( assoc->fontSize ) == 0 )
{
*have_sfnt = 1;
*sfnt_id = EndianS16_BtoN( assoc->fontID );
}
else if ( base_assoc->fontSize == 0 )
{
*have_sfnt = 1;
*sfnt_id = EndianS16_BtoN( base_assoc->fontID );
}
}
 
if ( EndianS32_BtoN( fond->ffStylOff ) )
{
unsigned char* p = (unsigned char*)fond_data;
StyleTable* style;
unsigned short string_count;
char ps_name[256];
unsigned char* names[64];
int i;
 
 
p += EndianS32_BtoN( fond->ffStylOff );
style = (StyleTable*)p;
p += sizeof ( StyleTable );
string_count = EndianS16_BtoN( *(short*)(p) );
p += sizeof ( short );
 
for ( i = 0; i < string_count && i < 64; i++ )
{
names[i] = p;
p += names[i][0];
p++;
}
 
{
size_t ps_name_len = (size_t)names[0][0];
 
 
if ( ps_name_len != 0 )
{
ft_memcpy(ps_name, names[0] + 1, ps_name_len);
ps_name[ps_name_len] = 0;
}
if ( style->indexes[face_index] > 1 &&
style->indexes[face_index] <= FT_MIN( string_count, 64 ) )
{
unsigned char* suffixes = names[style->indexes[face_index] - 1];
 
 
for ( i = 1; i <= suffixes[0]; i++ )
{
unsigned char* s;
size_t j = suffixes[i] - 1;
 
 
if ( j < string_count && ( s = names[j] ) != NULL )
{
size_t s_len = (size_t)s[0];
 
 
if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) )
{
ft_memcpy( ps_name + ps_name_len, s + 1, s_len );
ps_name_len += s_len;
ps_name[ps_name_len] = 0;
}
}
}
}
}
 
create_lwfn_name( ps_name, lwfn_file_name );
}
}
 
 
static FT_Error
lookup_lwfn_by_fond( const UInt8* path_fond,
ConstStr255Param base_lwfn,
UInt8* path_lwfn,
size_t path_size )
{
FSRef ref, par_ref;
size_t dirname_len;
 
 
/* Pathname for FSRef can be in various formats: HFS, HFS+, and POSIX. */
/* We should not extract parent directory by string manipulation. */
 
if ( noErr != FSPathMakeRef( path_fond, &ref, FALSE ) )
return FT_THROW( Invalid_Argument );
 
if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
NULL, NULL, NULL, &par_ref ) )
return FT_THROW( Invalid_Argument );
 
if ( noErr != FSRefMakePath( &par_ref, path_lwfn, path_size ) )
return FT_THROW( Invalid_Argument );
 
if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size )
return FT_THROW( Invalid_Argument );
 
/* now we have absolute dirname in path_lwfn */
ft_strcat( (char *)path_lwfn, "/" );
dirname_len = ft_strlen( (char *)path_lwfn );
ft_strcat( (char *)path_lwfn, (char *)base_lwfn + 1 );
path_lwfn[dirname_len + base_lwfn[0]] = '\0';
 
if ( noErr != FSPathMakeRef( path_lwfn, &ref, FALSE ) )
return FT_THROW( Cannot_Open_Resource );
 
if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
NULL, NULL, NULL, NULL ) )
return FT_THROW( Cannot_Open_Resource );
 
return FT_Err_Ok;
}
 
 
static short
count_faces( Handle fond,
const UInt8* pathname )
{
ResID sfnt_id;
short have_sfnt, have_lwfn;
Str255 lwfn_file_name;
UInt8 buff[PATH_MAX];
FT_Error err;
short num_faces;
 
 
have_sfnt = have_lwfn = 0;
 
parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 );
 
if ( lwfn_file_name[0] )
{
err = lookup_lwfn_by_fond( pathname, lwfn_file_name,
buff, sizeof ( buff ) );
if ( !err )
have_lwfn = 1;
}
 
if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
num_faces = 1;
else
num_faces = count_faces_scalable( *fond );
 
return num_faces;
}
 
 
/* Read Type 1 data from the POST resources inside the LWFN file,
return a PFB buffer. This is somewhat convoluted because the FT2
PFB parser wants the ASCII header as one chunk, and the LWFN
chunks are often not organized that way, so we glue chunks
of the same type together. */
static FT_Error
read_lwfn( FT_Memory memory,
ResFileRefNum res,
FT_Byte** pfb_data,
FT_ULong* size )
{
FT_Error error = FT_Err_Ok;
ResID res_id;
unsigned char *buffer, *p, *size_p = NULL;
FT_ULong total_size = 0;
FT_ULong old_total_size = 0;
FT_ULong post_size, pfb_chunk_size;
Handle post_data;
char code, last_code;
 
 
UseResFile( res );
 
/* First pass: load all POST resources, and determine the size of */
/* the output buffer. */
res_id = 501;
last_code = -1;
 
for (;;)
{
post_data = Get1Resource( TTAG_POST, res_id++ );
if ( post_data == NULL )
break; /* we are done */
 
code = (*post_data)[0];
 
if ( code != last_code )
{
if ( code == 5 )
total_size += 2; /* just the end code */
else
total_size += 6; /* code + 4 bytes chunk length */
}
 
total_size += GetHandleSize( post_data ) - 2;
last_code = code;
 
/* detect integer overflows */
if ( total_size < old_total_size )
{
error = FT_THROW( Array_Too_Large );
goto Error;
}
 
old_total_size = total_size;
}
 
if ( FT_ALLOC( buffer, (FT_Long)total_size ) )
goto Error;
 
/* Second pass: append all POST data to the buffer, add PFB fields. */
/* Glue all consecutive chunks of the same type together. */
p = buffer;
res_id = 501;
last_code = -1;
pfb_chunk_size = 0;
 
for (;;)
{
post_data = Get1Resource( TTAG_POST, res_id++ );
if ( post_data == NULL )
break; /* we are done */
 
post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
code = (*post_data)[0];
 
if ( code != last_code )
{
if ( last_code != -1 )
{
/* we are done adding a chunk, fill in the size field */
if ( size_p != NULL )
{
*size_p++ = (FT_Byte)( pfb_chunk_size & 0xFF );
*size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8 ) & 0xFF );
*size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF );
*size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF );
}
pfb_chunk_size = 0;
}
 
*p++ = 0x80;
if ( code == 5 )
*p++ = 0x03; /* the end */
else if ( code == 2 )
*p++ = 0x02; /* binary segment */
else
*p++ = 0x01; /* ASCII segment */
 
if ( code != 5 )
{
size_p = p; /* save for later */
p += 4; /* make space for size field */
}
}
 
ft_memcpy( p, *post_data + 2, post_size );
pfb_chunk_size += post_size;
p += post_size;
last_code = code;
}
 
*pfb_data = buffer;
*size = total_size;
 
Error:
CloseResFile( res );
return error;
}
 
 
/* Create a new FT_Face from a file path to an LWFN file. */
static FT_Error
FT_New_Face_From_LWFN( FT_Library library,
const UInt8* pathname,
FT_Long face_index,
FT_Face* aface )
{
FT_Byte* pfb_data;
FT_ULong pfb_size;
FT_Error error;
ResFileRefNum res;
 
 
if ( noErr != FT_FSPathMakeRes( pathname, &res ) )
return FT_THROW( Cannot_Open_Resource );
 
pfb_data = NULL;
pfb_size = 0;
error = read_lwfn( library->memory, res, &pfb_data, &pfb_size );
CloseResFile( res ); /* PFB is already loaded, useless anymore */
if ( error )
return error;
 
return open_face_from_buffer( library,
pfb_data,
pfb_size,
face_index,
"type1",
aface );
}
 
 
/* Create a new FT_Face from an SFNT resource, specified by res ID. */
static FT_Error
FT_New_Face_From_SFNT( FT_Library library,
ResID sfnt_id,
FT_Long face_index,
FT_Face* aface )
{
Handle sfnt = NULL;
FT_Byte* sfnt_data;
size_t sfnt_size;
FT_Error error = FT_Err_Ok;
FT_Memory memory = library->memory;
int is_cff, is_sfnt_ps;
 
 
sfnt = GetResource( TTAG_sfnt, sfnt_id );
if ( sfnt == NULL )
return FT_THROW( Invalid_Handle );
 
sfnt_size = (FT_ULong)GetHandleSize( sfnt );
if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
{
ReleaseResource( sfnt );
return error;
}
 
ft_memcpy( sfnt_data, *sfnt, sfnt_size );
ReleaseResource( sfnt );
 
is_cff = sfnt_size > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
is_sfnt_ps = sfnt_size > 4 && !ft_memcmp( sfnt_data, "typ1", 4 );
 
if ( is_sfnt_ps )
{
FT_Stream stream;
 
 
if ( FT_NEW( stream ) )
goto Try_OpenType;
 
FT_Stream_OpenMemory( stream, sfnt_data, sfnt_size );
if ( !open_face_PS_from_sfnt_stream( library,
stream,
face_index,
0, NULL,
aface ) )
{
FT_Stream_Close( stream );
FT_FREE( stream );
FT_FREE( sfnt_data );
goto Exit;
}
 
FT_FREE( stream );
}
Try_OpenType:
error = open_face_from_buffer( library,
sfnt_data,
sfnt_size,
face_index,
is_cff ? "cff" : "truetype",
aface );
Exit:
return error;
}
 
 
/* Create a new FT_Face from a file path to a suitcase file. */
static FT_Error
FT_New_Face_From_Suitcase( FT_Library library,
const UInt8* pathname,
FT_Long face_index,
FT_Face* aface )
{
FT_Error error = FT_ERR( Cannot_Open_Resource );
ResFileRefNum res_ref;
ResourceIndex res_index;
Handle fond;
short num_faces_in_res;
 
 
if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )
return FT_THROW( Cannot_Open_Resource );
 
UseResFile( res_ref );
if ( ResError() )
return FT_THROW( Cannot_Open_Resource );
 
num_faces_in_res = 0;
for ( res_index = 1; ; ++res_index )
{
short num_faces_in_fond;
 
 
fond = Get1IndResource( TTAG_FOND, res_index );
if ( ResError() )
break;
 
num_faces_in_fond = count_faces( fond, pathname );
num_faces_in_res += num_faces_in_fond;
 
if ( 0 <= face_index && face_index < num_faces_in_fond && error )
error = FT_New_Face_From_FOND( library, fond, face_index, aface );
 
face_index -= num_faces_in_fond;
}
 
CloseResFile( res_ref );
if ( !error && aface && *aface )
(*aface)->num_faces = num_faces_in_res;
return error;
}
 
 
/* documentation is in ftmac.h */
 
FT_EXPORT_DEF( FT_Error )
FT_New_Face_From_FOND( FT_Library library,
Handle fond,
FT_Long face_index,
FT_Face* aface )
{
short have_sfnt, have_lwfn = 0;
ResID sfnt_id, fond_id;
OSType fond_type;
Str255 fond_name;
Str255 lwfn_file_name;
UInt8 path_lwfn[PATH_MAX];
OSErr err;
FT_Error error = FT_Err_Ok;
 
 
GetResInfo( fond, &fond_id, &fond_type, fond_name );
if ( ResError() != noErr || fond_type != TTAG_FOND )
return FT_THROW( Invalid_File_Format );
 
parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, face_index );
 
if ( lwfn_file_name[0] )
{
ResFileRefNum res;
 
 
res = HomeResFile( fond );
if ( noErr != ResError() )
goto found_no_lwfn_file;
 
{
UInt8 path_fond[PATH_MAX];
FSRef ref;
 
 
err = FSGetForkCBInfo( res, kFSInvalidVolumeRefNum,
NULL, NULL, NULL, &ref, NULL );
if ( noErr != err )
goto found_no_lwfn_file;
 
err = FSRefMakePath( &ref, path_fond, sizeof ( path_fond ) );
if ( noErr != err )
goto found_no_lwfn_file;
 
error = lookup_lwfn_by_fond( path_fond, lwfn_file_name,
path_lwfn, sizeof ( path_lwfn ) );
if ( !error )
have_lwfn = 1;
}
}
 
if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
error = FT_New_Face_From_LWFN( library,
path_lwfn,
face_index,
aface );
else
error = FT_THROW( Unknown_File_Format );
 
found_no_lwfn_file:
if ( have_sfnt && error )
error = FT_New_Face_From_SFNT( library,
sfnt_id,
face_index,
aface );
 
return error;
}
 
 
/* Common function to load a new FT_Face from a resource file. */
static FT_Error
FT_New_Face_From_Resource( FT_Library library,
const UInt8* pathname,
FT_Long face_index,
FT_Face* aface )
{
OSType file_type;
FT_Error error;
 
 
/* LWFN is a (very) specific file format, check for it explicitly */
file_type = get_file_type_from_path( pathname );
if ( file_type == TTAG_LWFN )
return FT_New_Face_From_LWFN( library, pathname, face_index, aface );
 
/* Otherwise the file type doesn't matter (there are more than */
/* `FFIL' and `tfil'). Just try opening it as a font suitcase; */
/* if it works, fine. */
 
error = FT_New_Face_From_Suitcase( library, pathname, face_index, aface );
if ( error == 0 )
return error;
 
/* let it fall through to normal loader (.ttf, .otf, etc.); */
/* we signal this by returning no error and no FT_Face */
*aface = NULL;
return 0;
}
 
 
/*************************************************************************/
/* */
/* <Function> */
/* FT_New_Face */
/* */
/* <Description> */
/* This is the Mac-specific implementation of FT_New_Face. In */
/* addition to the standard FT_New_Face() functionality, it also */
/* accepts pathnames to Mac suitcase files. For further */
/* documentation see the original FT_New_Face() in freetype.h. */
/* */
FT_EXPORT_DEF( FT_Error )
FT_New_Face( FT_Library library,
const char* pathname,
FT_Long face_index,
FT_Face* aface )
{
FT_Open_Args args;
FT_Error error;
 
 
/* test for valid `library' and `aface' delayed to FT_Open_Face() */
if ( !pathname )
return FT_THROW( Invalid_Argument );
 
error = FT_Err_Ok;
*aface = NULL;
 
/* try resourcefork based font: LWFN, FFIL */
error = FT_New_Face_From_Resource( library, (UInt8 *)pathname,
face_index, aface );
if ( error != 0 || *aface != NULL )
return error;
 
/* let it fall through to normal loader (.ttf, .otf, etc.) */
args.flags = FT_OPEN_PATHNAME;
args.pathname = (char*)pathname;
return FT_Open_Face( library, &args, face_index, aface );
}
 
 
/*************************************************************************/
/* */
/* <Function> */
/* FT_New_Face_From_FSRef */
/* */
/* <Description> */
/* FT_New_Face_From_FSRef is identical to FT_New_Face except it */
/* accepts an FSRef instead of a path. */
/* */
/* This function is deprecated because Carbon data types (FSRef) */
/* are not cross-platform, and thus not suitable for the freetype API. */
FT_EXPORT_DEF( FT_Error )
FT_New_Face_From_FSRef( FT_Library library,
const FSRef* ref,
FT_Long face_index,
FT_Face* aface )
{
FT_Error error;
FT_Open_Args args;
OSErr err;
UInt8 pathname[PATH_MAX];
 
 
if ( !ref )
return FT_THROW( Invalid_Argument );
 
err = FSRefMakePath( ref, pathname, sizeof ( pathname ) );
if ( err )
error = FT_THROW( Cannot_Open_Resource );
 
error = FT_New_Face_From_Resource( library, pathname, face_index, aface );
if ( error != 0 || *aface != NULL )
return error;
 
/* fallback to datafork font */
args.flags = FT_OPEN_PATHNAME;
args.pathname = (char*)pathname;
return FT_Open_Face( library, &args, face_index, aface );
}
 
 
/*************************************************************************/
/* */
/* <Function> */
/* FT_New_Face_From_FSSpec */
/* */
/* <Description> */
/* FT_New_Face_From_FSSpec is identical to FT_New_Face except it */
/* accepts an FSSpec instead of a path. */
/* */
/* This function is deprecated because FSSpec is deprecated in Mac OS X */
FT_EXPORT_DEF( FT_Error )
FT_New_Face_From_FSSpec( FT_Library library,
const FSSpec* spec,
FT_Long face_index,
FT_Face* aface )
{
#if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
FT_UNUSED( library );
FT_UNUSED( spec );
FT_UNUSED( face_index );
FT_UNUSED( aface );
 
return FT_THROW( Unimplemented_Feature );
#else
FSRef ref;
 
 
if ( !spec || FSpMakeFSRef( spec, &ref ) != noErr )
return FT_THROW( Invalid_Argument );
else
return FT_New_Face_From_FSRef( library, &ref, face_index, aface );
#endif
}
 
#endif /* FT_MACINTOSH */
 
 
/* END */
/programs/develop/libraries/freetype/src/base/ftmm.c
0,0 → 1,204
/***************************************************************************/
/* */
/* ftmm.c */
/* */
/* Multiple Master font support (body). */
/* */
/* Copyright 1996-2001, 2003, 2004, 2009, 2013 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_MULTIPLE_MASTERS_H
#include FT_INTERNAL_OBJECTS_H
#include FT_SERVICE_MULTIPLE_MASTERS_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_mm
 
 
static FT_Error
ft_face_get_mm_service( FT_Face face,
FT_Service_MultiMasters *aservice )
{
FT_Error error;
 
 
*aservice = NULL;
 
if ( !face )
return FT_THROW( Invalid_Face_Handle );
 
error = FT_ERR( Invalid_Argument );
 
if ( FT_HAS_MULTIPLE_MASTERS( face ) )
{
FT_FACE_LOOKUP_SERVICE( face,
*aservice,
MULTI_MASTERS );
 
if ( *aservice )
error = FT_Err_Ok;
}
 
return error;
}
 
 
/* documentation is in ftmm.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Get_Multi_Master( FT_Face face,
FT_Multi_Master *amaster )
{
FT_Error error;
FT_Service_MultiMasters service;
 
 
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
error = FT_ERR( Invalid_Argument );
if ( service->get_mm )
error = service->get_mm( face, amaster );
}
 
return error;
}
 
 
/* documentation is in ftmm.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Get_MM_Var( FT_Face face,
FT_MM_Var* *amaster )
{
FT_Error error;
FT_Service_MultiMasters service;
 
 
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
error = FT_ERR( Invalid_Argument );
if ( service->get_mm_var )
error = service->get_mm_var( face, amaster );
}
 
return error;
}
 
 
/* documentation is in ftmm.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Set_MM_Design_Coordinates( FT_Face face,
FT_UInt num_coords,
FT_Long* coords )
{
FT_Error error;
FT_Service_MultiMasters service;
 
 
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
error = FT_ERR( Invalid_Argument );
if ( service->set_mm_design )
error = service->set_mm_design( face, num_coords, coords );
}
 
return error;
}
 
 
/* documentation is in ftmm.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Set_Var_Design_Coordinates( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords )
{
FT_Error error;
FT_Service_MultiMasters service;
 
 
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
error = FT_ERR( Invalid_Argument );
if ( service->set_var_design )
error = service->set_var_design( face, num_coords, coords );
}
 
return error;
}
 
 
/* documentation is in ftmm.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Set_MM_Blend_Coordinates( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords )
{
FT_Error error;
FT_Service_MultiMasters service;
 
 
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
error = FT_ERR( Invalid_Argument );
if ( service->set_mm_blend )
error = service->set_mm_blend( face, num_coords, coords );
}
 
return error;
}
 
 
/* documentation is in ftmm.h */
 
/* This is exactly the same as the previous function. It exists for */
/* orthogonality. */
 
FT_EXPORT_DEF( FT_Error )
FT_Set_Var_Blend_Coordinates( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords )
{
FT_Error error;
FT_Service_MultiMasters service;
 
 
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
error = FT_ERR( Invalid_Argument );
if ( service->set_mm_blend )
error = service->set_mm_blend( face, num_coords, coords );
}
 
return error;
}
 
 
/* END */
/programs/develop/libraries/freetype/src/base/ftobjs.c
0,0 → 1,4870
/***************************************************************************/
/* */
/* ftobjs.c */
/* */
/* The FreeType private base classes (body). */
/* */
/* Copyright 1996-2013 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_VALIDATE_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_RFORK_H
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_SFNT_H /* for SFNT_Load_Table_Func */
#include FT_TRUETYPE_TABLES_H
#include FT_TRUETYPE_TAGS_H
#include FT_TRUETYPE_IDS_H
 
#include FT_SERVICE_PROPERTIES_H
#include FT_SERVICE_SFNT_H
#include FT_SERVICE_POSTSCRIPT_NAME_H
#include FT_SERVICE_GLYPH_DICT_H
#include FT_SERVICE_TT_CMAP_H
#include FT_SERVICE_KERNING_H
#include FT_SERVICE_TRUETYPE_ENGINE_H
 
#ifdef FT_CONFIG_OPTION_MAC_FONTS
#include "ftbase.h"
#endif
 
 
#ifdef FT_DEBUG_LEVEL_TRACE
 
#include FT_BITMAP_H
 
#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */
/* We disable the warning `conversion from XXX to YYY, */
/* possible loss of data' in order to compile cleanly with */
/* the maximum level of warnings: `md5.c' is non-FreeType */
/* code, and it gets used during development builds only. */
#pragma warning( push )
#pragma warning( disable : 4244 )
#endif /* _MSC_VER */
 
/* it's easiest to include `md5.c' directly */
#define free md5_free /* suppress a shadow warning */
#include "md5.c"
#undef free
 
#if defined( _MSC_VER )
#pragma warning( pop )
#endif
 
#endif /* FT_DEBUG_LEVEL_TRACE */
 
 
#define GRID_FIT_METRICS
 
 
FT_BASE_DEF( FT_Pointer )
ft_service_list_lookup( FT_ServiceDesc service_descriptors,
const char* service_id )
{
FT_Pointer result = NULL;
FT_ServiceDesc desc = service_descriptors;
 
 
if ( desc && service_id )
{
for ( ; desc->serv_id != NULL; desc++ )
{
if ( ft_strcmp( desc->serv_id, service_id ) == 0 )
{
result = (FT_Pointer)desc->serv_data;
break;
}
}
}
 
return result;
}
 
 
FT_BASE_DEF( void )
ft_validator_init( FT_Validator valid,
const FT_Byte* base,
const FT_Byte* limit,
FT_ValidationLevel level )
{
valid->base = base;
valid->limit = limit;
valid->level = level;
valid->error = FT_Err_Ok;
}
 
 
FT_BASE_DEF( FT_Int )
ft_validator_run( FT_Validator valid )
{
/* This function doesn't work! None should call it. */
FT_UNUSED( valid );
 
return -1;
}
 
 
FT_BASE_DEF( void )
ft_validator_error( FT_Validator valid,
FT_Error error )
{
/* since the cast below also disables the compiler's */
/* type check, we introduce a dummy variable, which */
/* will be optimized away */
volatile ft_jmp_buf* jump_buffer = &valid->jump_buffer;
 
 
valid->error = error;
 
/* throw away volatileness; use `jump_buffer' or the */
/* compiler may warn about an unused local variable */
ft_longjmp( *(ft_jmp_buf*) jump_buffer, 1 );
}
 
 
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** S T R E A M ****/
/**** ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
 
 
/* create a new input stream from an FT_Open_Args structure */
/* */
FT_BASE_DEF( FT_Error )
FT_Stream_New( FT_Library library,
const FT_Open_Args* args,
FT_Stream *astream )
{
FT_Error error;
FT_Memory memory;
FT_Stream stream = NULL;
 
 
*astream = 0;
 
if ( !library )
return FT_THROW( Invalid_Library_Handle );
 
if ( !args )
return FT_THROW( Invalid_Argument );
 
memory = library->memory;
 
if ( FT_NEW( stream ) )
goto Exit;
 
stream->memory = memory;
 
if ( args->flags & FT_OPEN_MEMORY )
{
/* create a memory-based stream */
FT_Stream_OpenMemory( stream,
(const FT_Byte*)args->memory_base,
args->memory_size );
}
 
#ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT
 
else if ( args->flags & FT_OPEN_PATHNAME )
{
/* create a normal system stream */
error = FT_Stream_Open( stream, args->pathname );
stream->pathname.pointer = args->pathname;
}
else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream )
{
/* use an existing, user-provided stream */
 
/* in this case, we do not need to allocate a new stream object */
/* since the caller is responsible for closing it himself */
FT_FREE( stream );
stream = args->stream;
}
 
#endif
 
else
error = FT_THROW( Invalid_Argument );
 
if ( error )
FT_FREE( stream );
else
stream->memory = memory; /* just to be certain */
 
*astream = stream;
 
Exit:
return error;
}
 
 
FT_BASE_DEF( void )
FT_Stream_Free( FT_Stream stream,
FT_Int external )
{
if ( stream )
{
FT_Memory memory = stream->memory;
 
 
FT_Stream_Close( stream );
 
if ( !external )
FT_FREE( stream );
}
}
 
 
/*************************************************************************/
/* */
/* 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_objs
 
 
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** FACE, SIZE & GLYPH SLOT OBJECTS ****/
/**** ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
 
 
static FT_Error
ft_glyphslot_init( FT_GlyphSlot slot )
{
FT_Driver driver = slot->face->driver;
FT_Driver_Class clazz = driver->clazz;
FT_Memory memory = driver->root.memory;
FT_Error error = FT_Err_Ok;
FT_Slot_Internal internal = NULL;
 
 
slot->library = driver->root.library;
 
if ( FT_NEW( internal ) )
goto Exit;
 
slot->internal = internal;
 
if ( FT_DRIVER_USES_OUTLINES( driver ) )
error = FT_GlyphLoader_New( memory, &internal->loader );
 
if ( !error && clazz->init_slot )
error = clazz->init_slot( slot );
 
Exit:
return error;
}
 
 
FT_BASE_DEF( void )
ft_glyphslot_free_bitmap( FT_GlyphSlot slot )
{
if ( slot->internal && ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
{
FT_Memory memory = FT_FACE_MEMORY( slot->face );
 
 
FT_FREE( slot->bitmap.buffer );
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
}
else
{
/* assume that the bitmap buffer was stolen or not */
/* allocated from the heap */
slot->bitmap.buffer = NULL;
}
}
 
 
FT_BASE_DEF( void )
ft_glyphslot_set_bitmap( FT_GlyphSlot slot,
FT_Byte* buffer )
{
ft_glyphslot_free_bitmap( slot );
 
slot->bitmap.buffer = buffer;
 
FT_ASSERT( (slot->internal->flags & FT_GLYPH_OWN_BITMAP) == 0 );
}
 
 
FT_BASE_DEF( FT_Error )
ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot,
FT_ULong size )
{
FT_Memory memory = FT_FACE_MEMORY( slot->face );
FT_Error error;
 
 
if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
FT_FREE( slot->bitmap.buffer );
else
slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
 
(void)FT_ALLOC( slot->bitmap.buffer, size );
return error;
}
 
 
static void
ft_glyphslot_clear( FT_GlyphSlot slot )
{
/* free bitmap if needed */
ft_glyphslot_free_bitmap( slot );
 
/* clear all public fields in the glyph slot */
FT_ZERO( &slot->metrics );
FT_ZERO( &slot->outline );
 
slot->bitmap.width = 0;
slot->bitmap.rows = 0;
slot->bitmap.pitch = 0;
slot->bitmap.pixel_mode = 0;
/* `slot->bitmap.buffer' has been handled by ft_glyphslot_free_bitmap */
 
slot->bitmap_left = 0;
slot->bitmap_top = 0;
slot->num_subglyphs = 0;
slot->subglyphs = 0;
slot->control_data = 0;
slot->control_len = 0;
slot->other = 0;
slot->format = FT_GLYPH_FORMAT_NONE;
 
slot->linearHoriAdvance = 0;
slot->linearVertAdvance = 0;
slot->lsb_delta = 0;
slot->rsb_delta = 0;
}
 
 
static void
ft_glyphslot_done( FT_GlyphSlot slot )
{
FT_Driver driver = slot->face->driver;
FT_Driver_Class clazz = driver->clazz;
FT_Memory memory = driver->root.memory;
 
 
if ( clazz->done_slot )
clazz->done_slot( slot );
 
/* free bitmap buffer if needed */
ft_glyphslot_free_bitmap( slot );
 
/* slot->internal might be NULL in out-of-memory situations */
if ( slot->internal )
{
/* free glyph loader */
if ( FT_DRIVER_USES_OUTLINES( driver ) )
{
FT_GlyphLoader_Done( slot->internal->loader );
slot->internal->loader = 0;
}
 
FT_FREE( slot->internal );
}
}
 
 
/* documentation is in ftobjs.h */
 
FT_BASE_DEF( FT_Error )
FT_New_GlyphSlot( FT_Face face,
FT_GlyphSlot *aslot )
{
FT_Error error;
FT_Driver driver;
FT_Driver_Class clazz;
FT_Memory memory;
FT_GlyphSlot slot = NULL;
 
 
if ( !face || !face->driver )
return FT_THROW( Invalid_Argument );
 
driver = face->driver;
clazz = driver->clazz;
memory = driver->root.memory;
 
FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
if ( !FT_ALLOC( slot, clazz->slot_object_size ) )
{
slot->face = face;
 
error = ft_glyphslot_init( slot );
if ( error )
{
ft_glyphslot_done( slot );
FT_FREE( slot );
goto Exit;
}
 
slot->next = face->glyph;
face->glyph = slot;
 
if ( aslot )
*aslot = slot;
}
else if ( aslot )
*aslot = 0;
 
 
Exit:
FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
return error;
}
 
 
/* documentation is in ftobjs.h */
 
FT_BASE_DEF( void )
FT_Done_GlyphSlot( FT_GlyphSlot slot )
{
if ( slot )
{
FT_Driver driver = slot->face->driver;
FT_Memory memory = driver->root.memory;
FT_GlyphSlot prev;
FT_GlyphSlot cur;
 
 
/* Remove slot from its parent face's list */
prev = NULL;
cur = slot->face->glyph;
 
while ( cur )
{
if ( cur == slot )
{
if ( !prev )
slot->face->glyph = cur->next;
else
prev->next = cur->next;
 
/* finalize client-specific data */
if ( slot->generic.finalizer )
slot->generic.finalizer( slot );
 
ft_glyphslot_done( slot );
FT_FREE( slot );
break;
}
prev = cur;
cur = cur->next;
}
}
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( void )
FT_Set_Transform( FT_Face face,
FT_Matrix* matrix,
FT_Vector* delta )
{
FT_Face_Internal internal;
 
 
if ( !face )
return;
 
internal = face->internal;
 
internal->transform_flags = 0;
 
if ( !matrix )
{
internal->transform_matrix.xx = 0x10000L;
internal->transform_matrix.xy = 0;
internal->transform_matrix.yx = 0;
internal->transform_matrix.yy = 0x10000L;
matrix = &internal->transform_matrix;
}
else
internal->transform_matrix = *matrix;
 
/* set transform_flags bit flag 0 if `matrix' isn't the identity */
if ( ( matrix->xy | matrix->yx ) ||
matrix->xx != 0x10000L ||
matrix->yy != 0x10000L )
internal->transform_flags |= 1;
 
if ( !delta )
{
internal->transform_delta.x = 0;
internal->transform_delta.y = 0;
delta = &internal->transform_delta;
}
else
internal->transform_delta = *delta;
 
/* set transform_flags bit flag 1 if `delta' isn't the null vector */
if ( delta->x | delta->y )
internal->transform_flags |= 2;
}
 
 
static FT_Renderer
ft_lookup_glyph_renderer( FT_GlyphSlot slot );
 
 
#ifdef GRID_FIT_METRICS
static void
ft_glyphslot_grid_fit_metrics( FT_GlyphSlot slot,
FT_Bool vertical )
{
FT_Glyph_Metrics* metrics = &slot->metrics;
FT_Pos right, bottom;
 
 
if ( vertical )
{
metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
 
right = FT_PIX_CEIL( metrics->vertBearingX + metrics->width );
bottom = FT_PIX_CEIL( metrics->vertBearingY + metrics->height );
 
metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
 
metrics->width = right - metrics->vertBearingX;
metrics->height = bottom - metrics->vertBearingY;
}
else
{
metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
 
right = FT_PIX_CEIL ( metrics->horiBearingX + metrics->width );
bottom = FT_PIX_FLOOR( metrics->horiBearingY - metrics->height );
 
metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
 
metrics->width = right - metrics->horiBearingX;
metrics->height = metrics->horiBearingY - bottom;
}
 
metrics->horiAdvance = FT_PIX_ROUND( metrics->horiAdvance );
metrics->vertAdvance = FT_PIX_ROUND( metrics->vertAdvance );
}
#endif /* GRID_FIT_METRICS */
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Load_Glyph( FT_Face face,
FT_UInt glyph_index,
FT_Int32 load_flags )
{
FT_Error error;
FT_Driver driver;
FT_GlyphSlot slot;
FT_Library library;
FT_Bool autohint = FALSE;
FT_Module hinter;
TT_Face ttface = (TT_Face)face;
 
 
if ( !face || !face->size || !face->glyph )
return FT_THROW( Invalid_Face_Handle );
 
/* The validity test for `glyph_index' is performed by the */
/* font drivers. */
 
slot = face->glyph;
ft_glyphslot_clear( slot );
 
driver = face->driver;
library = driver->root.library;
hinter = library->auto_hinter;
 
/* resolve load flags dependencies */
 
if ( load_flags & FT_LOAD_NO_RECURSE )
load_flags |= FT_LOAD_NO_SCALE |
FT_LOAD_IGNORE_TRANSFORM;
 
if ( load_flags & FT_LOAD_NO_SCALE )
{
load_flags |= FT_LOAD_NO_HINTING |
FT_LOAD_NO_BITMAP;
 
load_flags &= ~FT_LOAD_RENDER;
}
 
/*
* Determine whether we need to auto-hint or not.
* The general rules are:
*
* - Do only auto-hinting if we have a hinter module, a scalable font
* format dealing with outlines, and no transforms except simple
* slants and/or rotations by integer multiples of 90 degrees.
*
* - Then, auto-hint if FT_LOAD_FORCE_AUTOHINT is set or if we don't
* have a native font hinter.
*
* - Otherwise, auto-hint for LIGHT hinting mode or if there isn't
* any hinting bytecode in the TrueType/OpenType font.
*
* - Exception: The font is `tricky' and requires the native hinter to
* load properly.
*/
 
if ( hinter &&
!( load_flags & FT_LOAD_NO_HINTING ) &&
!( load_flags & FT_LOAD_NO_AUTOHINT ) &&
FT_DRIVER_IS_SCALABLE( driver ) &&
FT_DRIVER_USES_OUTLINES( driver ) &&
!FT_IS_TRICKY( face ) &&
( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) ||
( face->internal->transform_matrix.yx == 0 &&
face->internal->transform_matrix.xx != 0 ) ||
( face->internal->transform_matrix.xx == 0 &&
face->internal->transform_matrix.yx != 0 ) ) )
{
if ( ( load_flags & FT_LOAD_FORCE_AUTOHINT ) ||
!FT_DRIVER_HAS_HINTER( driver ) )
autohint = TRUE;
else
{
FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
 
 
/* the check for `num_locations' assures that we actually */
/* test for instructions in a TTF and not in a CFF-based OTF */
if ( mode == FT_RENDER_MODE_LIGHT ||
face->internal->ignore_unpatented_hinter ||
( FT_IS_SFNT( face ) &&
ttface->num_locations &&
ttface->max_profile.maxSizeOfInstructions == 0 ) )
autohint = TRUE;
}
}
 
if ( autohint )
{
FT_AutoHinter_Interface hinting;
 
 
/* try to load embedded bitmaps first if available */
/* */
/* XXX: This is really a temporary hack that should disappear */
/* promptly with FreeType 2.1! */
/* */
if ( FT_HAS_FIXED_SIZES( face ) &&
( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
{
error = driver->clazz->load_glyph( slot, face->size,
glyph_index,
load_flags | FT_LOAD_SBITS_ONLY );
 
if ( !error && slot->format == FT_GLYPH_FORMAT_BITMAP )
goto Load_Ok;
}
 
{
FT_Face_Internal internal = face->internal;
FT_Int transform_flags = internal->transform_flags;
 
 
/* since the auto-hinter calls FT_Load_Glyph by itself, */
/* make sure that glyphs aren't transformed */
internal->transform_flags = 0;
 
/* load auto-hinted outline */
hinting = (FT_AutoHinter_Interface)hinter->clazz->module_interface;
 
error = hinting->load_glyph( (FT_AutoHinter)hinter,
slot, face->size,
glyph_index, load_flags );
 
internal->transform_flags = transform_flags;
}
}
else
{
error = driver->clazz->load_glyph( slot,
face->size,
glyph_index,
load_flags );
if ( error )
goto Exit;
 
if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
{
/* check that the loaded outline is correct */
error = FT_Outline_Check( &slot->outline );
if ( error )
goto Exit;
 
#ifdef GRID_FIT_METRICS
if ( !( load_flags & FT_LOAD_NO_HINTING ) )
ft_glyphslot_grid_fit_metrics( slot,
FT_BOOL( load_flags & FT_LOAD_VERTICAL_LAYOUT ) );
#endif
}
}
 
Load_Ok:
/* compute the advance */
if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
{
slot->advance.x = 0;
slot->advance.y = slot->metrics.vertAdvance;
}
else
{
slot->advance.x = slot->metrics.horiAdvance;
slot->advance.y = 0;
}
 
/* compute the linear advance in 16.16 pixels */
if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 &&
( FT_IS_SCALABLE( face ) ) )
{
FT_Size_Metrics* metrics = &face->size->metrics;
 
 
/* it's tricky! */
slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance,
metrics->x_scale, 64 );
 
slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance,
metrics->y_scale, 64 );
}
 
if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 )
{
FT_Face_Internal internal = face->internal;
 
 
/* now, transform the glyph image if needed */
if ( internal->transform_flags )
{
/* get renderer */
FT_Renderer renderer = ft_lookup_glyph_renderer( slot );
 
 
if ( renderer )
error = renderer->clazz->transform_glyph(
renderer, slot,
&internal->transform_matrix,
&internal->transform_delta );
else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
{
/* apply `standard' transformation if no renderer is available */
if ( internal->transform_flags & 1 )
FT_Outline_Transform( &slot->outline,
&internal->transform_matrix );
 
if ( internal->transform_flags & 2 )
FT_Outline_Translate( &slot->outline,
internal->transform_delta.x,
internal->transform_delta.y );
}
 
/* transform advance */
FT_Vector_Transform( &slot->advance, &internal->transform_matrix );
}
}
 
FT_TRACE5(( " x advance: %d\n" , slot->advance.x ));
FT_TRACE5(( " y advance: %d\n" , slot->advance.y ));
 
FT_TRACE5(( " linear x advance: %d\n" , slot->linearHoriAdvance ));
FT_TRACE5(( " linear y advance: %d\n" , slot->linearVertAdvance ));
 
/* do we need to render the image now? */
if ( !error &&
slot->format != FT_GLYPH_FORMAT_BITMAP &&
slot->format != FT_GLYPH_FORMAT_COMPOSITE &&
load_flags & FT_LOAD_RENDER )
{
FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
 
 
if ( mode == FT_RENDER_MODE_NORMAL &&
(load_flags & FT_LOAD_MONOCHROME ) )
mode = FT_RENDER_MODE_MONO;
 
error = FT_Render_Glyph( slot, mode );
}
 
Exit:
return error;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Load_Char( FT_Face face,
FT_ULong char_code,
FT_Int32 load_flags )
{
FT_UInt glyph_index;
 
 
if ( !face )
return FT_THROW( Invalid_Face_Handle );
 
glyph_index = (FT_UInt)char_code;
if ( face->charmap )
glyph_index = FT_Get_Char_Index( face, char_code );
 
return FT_Load_Glyph( face, glyph_index, load_flags );
}
 
 
/* destructor for sizes list */
static void
destroy_size( FT_Memory memory,
FT_Size size,
FT_Driver driver )
{
/* finalize client-specific data */
if ( size->generic.finalizer )
size->generic.finalizer( size );
 
/* finalize format-specific stuff */
if ( driver->clazz->done_size )
driver->clazz->done_size( size );
 
FT_FREE( size->internal );
FT_FREE( size );
}
 
 
static void
ft_cmap_done_internal( FT_CMap cmap );
 
 
static void
destroy_charmaps( FT_Face face,
FT_Memory memory )
{
FT_Int n;
 
 
if ( !face )
return;
 
for ( n = 0; n < face->num_charmaps; n++ )
{
FT_CMap cmap = FT_CMAP( face->charmaps[n] );
 
 
ft_cmap_done_internal( cmap );
 
face->charmaps[n] = NULL;
}
 
FT_FREE( face->charmaps );
face->num_charmaps = 0;
}
 
 
/* destructor for faces list */
static void
destroy_face( FT_Memory memory,
FT_Face face,
FT_Driver driver )
{
FT_Driver_Class clazz = driver->clazz;
 
 
/* discard auto-hinting data */
if ( face->autohint.finalizer )
face->autohint.finalizer( face->autohint.data );
 
/* Discard glyph slots for this face. */
/* Beware! FT_Done_GlyphSlot() changes the field `face->glyph' */
while ( face->glyph )
FT_Done_GlyphSlot( face->glyph );
 
/* discard all sizes for this face */
FT_List_Finalize( &face->sizes_list,
(FT_List_Destructor)destroy_size,
memory,
driver );
face->size = 0;
 
/* now discard client data */
if ( face->generic.finalizer )
face->generic.finalizer( face );
 
/* discard charmaps */
destroy_charmaps( face, memory );
 
/* finalize format-specific stuff */
if ( clazz->done_face )
clazz->done_face( face );
 
/* close the stream for this face if needed */
FT_Stream_Free(
face->stream,
( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
 
face->stream = 0;
 
/* get rid of it */
if ( face->internal )
{
FT_FREE( face->internal );
}
FT_FREE( face );
}
 
 
static void
Destroy_Driver( FT_Driver driver )
{
FT_List_Finalize( &driver->faces_list,
(FT_List_Destructor)destroy_face,
driver->root.memory,
driver );
 
/* check whether we need to drop the driver's glyph loader */
if ( FT_DRIVER_USES_OUTLINES( driver ) )
FT_GlyphLoader_Done( driver->glyph_loader );
}
 
 
/*************************************************************************/
/* */
/* <Function> */
/* find_unicode_charmap */
/* */
/* <Description> */
/* This function finds a Unicode charmap, if there is one. */
/* And if there is more than one, it tries to favour the more */
/* extensive one, i.e., one that supports UCS-4 against those which */
/* are limited to the BMP (said UCS-2 encoding.) */
/* */
/* This function is called from open_face() (just below), and also */
/* from FT_Select_Charmap( ..., FT_ENCODING_UNICODE ). */
/* */
static FT_Error
find_unicode_charmap( FT_Face face )
{
FT_CharMap* first;
FT_CharMap* cur;
 
 
/* caller should have already checked that `face' is valid */
FT_ASSERT( face );
 
first = face->charmaps;
 
if ( !first )
return FT_THROW( Invalid_CharMap_Handle );
 
/*
* The original TrueType specification(s) only specified charmap
* formats that are capable of mapping 8 or 16 bit character codes to
* glyph indices.
*
* However, recent updates to the Apple and OpenType specifications
* introduced new formats that are capable of mapping 32-bit character
* codes as well. And these are already used on some fonts, mainly to
* map non-BMP Asian ideographs as defined in Unicode.
*
* For compatibility purposes, these fonts generally come with
* *several* Unicode charmaps:
*
* - One of them in the "old" 16-bit format, that cannot access
* all glyphs in the font.
*
* - Another one in the "new" 32-bit format, that can access all
* the glyphs.
*
* This function has been written to always favor a 32-bit charmap
* when found. Otherwise, a 16-bit one is returned when found.
*/
 
/* Since the `interesting' table, with IDs (3,10), is normally the */
/* last one, we loop backwards. This loses with type1 fonts with */
/* non-BMP characters (<.0001%), this wins with .ttf with non-BMP */
/* chars (.01% ?), and this is the same about 99.99% of the time! */
 
cur = first + face->num_charmaps; /* points after the last one */
 
for ( ; --cur >= first; )
{
if ( cur[0]->encoding == FT_ENCODING_UNICODE )
{
/* XXX If some new encodings to represent UCS-4 are added, */
/* they should be added here. */
if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT &&
cur[0]->encoding_id == TT_MS_ID_UCS_4 ) ||
( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) )
{
#ifdef FT_MAX_CHARMAP_CACHEABLE
if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
{
FT_ERROR(( "find_unicode_charmap: UCS-4 cmap is found "
"at too late position (%d)\n", cur - first ));
continue;
}
#endif
face->charmap = cur[0];
return FT_Err_Ok;
}
}
}
 
/* We do not have any UCS-4 charmap. */
/* Do the loop again and search for UCS-2 charmaps. */
cur = first + face->num_charmaps;
 
for ( ; --cur >= first; )
{
if ( cur[0]->encoding == FT_ENCODING_UNICODE )
{
#ifdef FT_MAX_CHARMAP_CACHEABLE
if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
{
FT_ERROR(( "find_unicode_charmap: UCS-2 cmap is found "
"at too late position (%d)\n", cur - first ));
continue;
}
#endif
face->charmap = cur[0];
return FT_Err_Ok;
}
}
 
return FT_THROW( Invalid_CharMap_Handle );
}
 
 
/*************************************************************************/
/* */
/* <Function> */
/* find_variant_selector_charmap */
/* */
/* <Description> */
/* This function finds the variant selector charmap, if there is one. */
/* There can only be one (platform=0, specific=5, format=14). */
/* */
static FT_CharMap
find_variant_selector_charmap( FT_Face face )
{
FT_CharMap* first;
FT_CharMap* end;
FT_CharMap* cur;
 
 
/* caller should have already checked that `face' is valid */
FT_ASSERT( face );
 
first = face->charmaps;
 
if ( !first )
return NULL;
 
end = first + face->num_charmaps; /* points after the last one */
 
for ( cur = first; cur < end; ++cur )
{
if ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
cur[0]->encoding_id == TT_APPLE_ID_VARIANT_SELECTOR &&
FT_Get_CMap_Format( cur[0] ) == 14 )
{
#ifdef FT_MAX_CHARMAP_CACHEABLE
if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
{
FT_ERROR(( "find_unicode_charmap: UVS cmap is found "
"at too late position (%d)\n", cur - first ));
continue;
}
#endif
return cur[0];
}
}
 
return NULL;
}
 
 
/*************************************************************************/
/* */
/* <Function> */
/* open_face */
/* */
/* <Description> */
/* This function does some work for FT_Open_Face(). */
/* */
static FT_Error
open_face( FT_Driver driver,
FT_Stream stream,
FT_Long face_index,
FT_Int num_params,
FT_Parameter* params,
FT_Face *aface )
{
FT_Memory memory;
FT_Driver_Class clazz;
FT_Face face = 0;
FT_Error error, error2;
FT_Face_Internal internal = NULL;
 
 
clazz = driver->clazz;
memory = driver->root.memory;
 
/* allocate the face object and perform basic initialization */
if ( FT_ALLOC( face, clazz->face_object_size ) )
goto Fail;
 
face->driver = driver;
face->memory = memory;
face->stream = stream;
 
if ( FT_NEW( internal ) )
goto Fail;
 
face->internal = internal;
 
#ifdef FT_CONFIG_OPTION_INCREMENTAL
{
int i;
 
 
face->internal->incremental_interface = 0;
for ( i = 0; i < num_params && !face->internal->incremental_interface;
i++ )
if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL )
face->internal->incremental_interface =
(FT_Incremental_Interface)params[i].data;
}
#endif
 
if ( clazz->init_face )
error = clazz->init_face( stream,
face,
(FT_Int)face_index,
num_params,
params );
if ( error )
goto Fail;
 
/* select Unicode charmap by default */
error2 = find_unicode_charmap( face );
 
/* if no Unicode charmap can be found, FT_Err_Invalid_CharMap_Handle */
/* is returned. */
 
/* no error should happen, but we want to play safe */
if ( error2 && FT_ERR_NEQ( error2, Invalid_CharMap_Handle ) )
{
error = error2;
goto Fail;
}
 
*aface = face;
 
Fail:
if ( error )
{
destroy_charmaps( face, memory );
if ( clazz->done_face )
clazz->done_face( face );
FT_FREE( internal );
FT_FREE( face );
*aface = 0;
}
 
return error;
}
 
 
/* there's a Mac-specific extended implementation of FT_New_Face() */
/* in src/base/ftmac.c */
 
#ifndef FT_MACINTOSH
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Error )
FT_New_Face( FT_Library library,
const char* pathname,
FT_Long face_index,
FT_Face *aface )
{
FT_Open_Args args;
 
 
/* test for valid `library' and `aface' delayed to FT_Open_Face() */
if ( !pathname )
return FT_THROW( Invalid_Argument );
 
args.flags = FT_OPEN_PATHNAME;
args.pathname = (char*)pathname;
args.stream = NULL;
 
return FT_Open_Face( library, &args, face_index, aface );
}
 
#endif
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Error )
FT_New_Memory_Face( FT_Library library,
const FT_Byte* file_base,
FT_Long file_size,
FT_Long face_index,
FT_Face *aface )
{
FT_Open_Args args;
 
 
/* test for valid `library' and `face' delayed to FT_Open_Face() */
if ( !file_base )
return FT_THROW( Invalid_Argument );
 
args.flags = FT_OPEN_MEMORY;
args.memory_base = file_base;
args.memory_size = file_size;
args.stream = NULL;
 
return FT_Open_Face( library, &args, face_index, aface );
}
 
 
#ifdef FT_CONFIG_OPTION_MAC_FONTS
 
/* The behavior here is very similar to that in base/ftmac.c, but it */
/* is designed to work on non-mac systems, so no mac specific calls. */
/* */
/* We look at the file and determine if it is a mac dfont file or a mac */
/* resource file, or a macbinary file containing a mac resource file. */
/* */
/* Unlike ftmac I'm not going to look at a `FOND'. I don't really see */
/* the point, especially since there may be multiple `FOND' resources. */
/* Instead I'll just look for `sfnt' and `POST' resources, ordered as */
/* they occur in the file. */
/* */
/* Note that multiple `POST' resources do not mean multiple postscript */
/* fonts; they all get jammed together to make what is essentially a */
/* pfb file. */
/* */
/* We aren't interested in `NFNT' or `FONT' bitmap resources. */
/* */
/* As soon as we get an `sfnt' load it into memory and pass it off to */
/* FT_Open_Face. */
/* */
/* If we have a (set of) `POST' resources, massage them into a (memory) */
/* pfb file and pass that to FT_Open_Face. (As with ftmac.c I'm not */
/* going to try to save the kerning info. After all that lives in the */
/* `FOND' which isn't in the file containing the `POST' resources so */
/* we don't really have access to it. */
 
 
/* Finalizer for a memory stream; gets called by FT_Done_Face(). */
/* It frees the memory it uses. */
/* From ftmac.c. */
static void
memory_stream_close( FT_Stream stream )
{
FT_Memory memory = stream->memory;
 
 
FT_FREE( stream->base );
 
stream->size = 0;
stream->base = 0;
stream->close = 0;
}
 
 
/* Create a new memory stream from a buffer and a size. */
/* From ftmac.c. */
static FT_Error
new_memory_stream( FT_Library library,
FT_Byte* base,
FT_ULong size,
FT_Stream_CloseFunc close,
FT_Stream *astream )
{
FT_Error error;
FT_Memory memory;
FT_Stream stream = NULL;
 
 
if ( !library )
return FT_THROW( Invalid_Library_Handle );
 
if ( !base )
return FT_THROW( Invalid_Argument );
 
*astream = 0;
memory = library->memory;
if ( FT_NEW( stream ) )
goto Exit;
 
FT_Stream_OpenMemory( stream, base, size );
 
stream->close = close;
 
*astream = stream;
 
Exit:
return error;
}
 
 
/* Create a new FT_Face given a buffer and a driver name. */
/* from ftmac.c */
FT_LOCAL_DEF( 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 )
{
FT_Open_Args args;
FT_Error error;
FT_Stream stream = NULL;
FT_Memory memory = library->memory;
 
 
error = new_memory_stream( library,
base,
size,
memory_stream_close,
&stream );
if ( error )
{
FT_FREE( base );
return error;
}
 
args.flags = FT_OPEN_STREAM;
args.stream = stream;
if ( driver_name )
{
args.flags = args.flags | FT_OPEN_DRIVER;
args.driver = FT_Get_Module( library, driver_name );
}
 
#ifdef FT_MACINTOSH
/* At this point, face_index has served its purpose; */
/* whoever calls this function has already used it to */
/* locate the correct font data. We should not propagate */
/* this index to FT_Open_Face() (unless it is negative). */
 
if ( face_index > 0 )
face_index = 0;
#endif
 
error = FT_Open_Face( library, &args, face_index, aface );
 
if ( error == FT_Err_Ok )
(*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
else
#ifdef FT_MACINTOSH
FT_Stream_Free( stream, 0 );
#else
{
FT_Stream_Close( stream );
FT_FREE( stream );
}
#endif
 
return error;
}
 
 
/* Look up `TYP1' or `CID ' table from sfnt table directory. */
/* `offset' and `length' must exclude the binary header in tables. */
 
/* Type 1 and CID-keyed font drivers should recognize sfnt-wrapped */
/* format too. Here, since we can't expect that the TrueType font */
/* driver is loaded unconditially, we must parse the font by */
/* ourselves. We are only interested in the name of the table and */
/* the offset. */
 
static FT_Error
ft_lookup_PS_in_sfnt_stream( FT_Stream stream,
FT_Long face_index,
FT_ULong* offset,
FT_ULong* length,
FT_Bool* is_sfnt_cid )
{
FT_Error error;
FT_UShort numTables;
FT_Long pstable_index;
FT_ULong tag;
int i;
 
 
*offset = 0;
*length = 0;
*is_sfnt_cid = FALSE;
 
/* TODO: support for sfnt-wrapped PS/CID in TTC format */
 
/* version check for 'typ1' (should be ignored?) */
if ( FT_READ_ULONG( tag ) )
return error;
if ( tag != TTAG_typ1 )
return FT_THROW( Unknown_File_Format );
 
if ( FT_READ_USHORT( numTables ) )
return error;
if ( FT_STREAM_SKIP( 2 * 3 ) ) /* skip binary search header */
return error;
 
pstable_index = -1;
*is_sfnt_cid = FALSE;
 
for ( i = 0; i < numTables; i++ )
{
if ( FT_READ_ULONG( tag ) || FT_STREAM_SKIP( 4 ) ||
FT_READ_ULONG( *offset ) || FT_READ_ULONG( *length ) )
return error;
 
if ( tag == TTAG_CID )
{
pstable_index++;
*offset += 22;
*length -= 22;
*is_sfnt_cid = TRUE;
if ( face_index < 0 )
return FT_Err_Ok;
}
else if ( tag == TTAG_TYP1 )
{
pstable_index++;
*offset += 24;
*length -= 24;
*is_sfnt_cid = FALSE;
if ( face_index < 0 )
return FT_Err_Ok;
}
if ( face_index >= 0 && pstable_index == face_index )
return FT_Err_Ok;
}
return FT_THROW( Table_Missing );
}
 
 
FT_LOCAL_DEF( 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 )
{
FT_Error error;
FT_Memory memory = library->memory;
FT_ULong offset, length;
FT_Long pos;
FT_Bool is_sfnt_cid;
FT_Byte* sfnt_ps = NULL;
 
FT_UNUSED( num_params );
FT_UNUSED( params );
 
 
pos = FT_Stream_Pos( stream );
 
error = ft_lookup_PS_in_sfnt_stream( stream,
face_index,
&offset,
&length,
&is_sfnt_cid );
if ( error )
goto Exit;
 
if ( FT_Stream_Seek( stream, pos + offset ) )
goto Exit;
 
if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) )
goto Exit;
 
error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length );
if ( error )
goto Exit;
 
error = open_face_from_buffer( library,
sfnt_ps,
length,
FT_MIN( face_index, 0 ),
is_sfnt_cid ? "cid" : "type1",
aface );
Exit:
{
FT_Error error1;
 
 
if ( FT_ERR_EQ( error, Unknown_File_Format ) )
{
error1 = FT_Stream_Seek( stream, pos );
if ( error1 )
return error1;
}
 
return error;
}
}
 
 
#ifndef FT_MACINTOSH
 
/* The resource header says we've got resource_cnt `POST' (type1) */
/* resources in this file. They all need to be coalesced into */
/* one lump which gets passed on to the type1 driver. */
/* Here can be only one PostScript font in a file so face_index */
/* must be 0 (or -1). */
/* */
static FT_Error
Mac_Read_POST_Resource( FT_Library library,
FT_Stream stream,
FT_Long *offsets,
FT_Long resource_cnt,
FT_Long face_index,
FT_Face *aface )
{
FT_Error error = FT_ERR( Cannot_Open_Resource );
FT_Memory memory = library->memory;
FT_Byte* pfb_data = NULL;
int i, type, flags;
FT_Long len;
FT_Long pfb_len, pfb_pos, pfb_lenpos;
FT_Long rlen, temp;
 
 
if ( face_index == -1 )
face_index = 0;
if ( face_index != 0 )
return error;
 
/* Find the length of all the POST resources, concatenated. Assume */
/* worst case (each resource in its own section). */
pfb_len = 0;
for ( i = 0; i < resource_cnt; ++i )
{
error = FT_Stream_Seek( stream, offsets[i] );
if ( error )
goto Exit;
if ( FT_READ_LONG( temp ) )
goto Exit;
pfb_len += temp + 6;
}
 
if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) )
goto Exit;
 
pfb_data[0] = 0x80;
pfb_data[1] = 1; /* Ascii section */
pfb_data[2] = 0; /* 4-byte length, fill in later */
pfb_data[3] = 0;
pfb_data[4] = 0;
pfb_data[5] = 0;
pfb_pos = 6;
pfb_lenpos = 2;
 
len = 0;
type = 1;
for ( i = 0; i < resource_cnt; ++i )
{
error = FT_Stream_Seek( stream, offsets[i] );
if ( error )
goto Exit2;
if ( FT_READ_LONG( rlen ) )
goto Exit;
if ( FT_READ_USHORT( flags ) )
goto Exit;
FT_TRACE3(( "POST fragment[%d]: offsets=0x%08x, rlen=0x%08x, flags=0x%04x\n",
i, offsets[i], rlen, flags ));
 
/* postpone the check of rlen longer than buffer until FT_Stream_Read() */
if ( ( flags >> 8 ) == 0 ) /* Comment, should not be loaded */
continue;
 
/* the flags are part of the resource, so rlen >= 2. */
/* but some fonts declare rlen = 0 for empty fragment */
if ( rlen > 2 )
rlen -= 2;
else
rlen = 0;
 
if ( ( flags >> 8 ) == type )
len += rlen;
else
{
if ( pfb_lenpos + 3 > pfb_len + 2 )
goto Exit2;
pfb_data[pfb_lenpos ] = (FT_Byte)( len );
pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
 
if ( ( flags >> 8 ) == 5 ) /* End of font mark */
break;
 
if ( pfb_pos + 6 > pfb_len + 2 )
goto Exit2;
pfb_data[pfb_pos++] = 0x80;
 
type = flags >> 8;
len = rlen;
 
pfb_data[pfb_pos++] = (FT_Byte)type;
pfb_lenpos = pfb_pos;
pfb_data[pfb_pos++] = 0; /* 4-byte length, fill in later */
pfb_data[pfb_pos++] = 0;
pfb_data[pfb_pos++] = 0;
pfb_data[pfb_pos++] = 0;
}
 
error = FT_ERR( Cannot_Open_Resource );
if ( pfb_pos > pfb_len || pfb_pos + rlen > pfb_len )
goto Exit2;
 
error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen );
if ( error )
goto Exit2;
pfb_pos += rlen;
}
 
if ( pfb_pos + 2 > pfb_len + 2 )
goto Exit2;
pfb_data[pfb_pos++] = 0x80;
pfb_data[pfb_pos++] = 3;
 
if ( pfb_lenpos + 3 > pfb_len + 2 )
goto Exit2;
pfb_data[pfb_lenpos ] = (FT_Byte)( len );
pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );
 
return open_face_from_buffer( library,
pfb_data,
pfb_pos,
face_index,
"type1",
aface );
 
Exit2:
FT_FREE( pfb_data );
 
Exit:
return error;
}
 
 
/* The resource header says we've got resource_cnt `sfnt' */
/* (TrueType/OpenType) resources in this file. Look through */
/* them for the one indicated by face_index, load it into mem, */
/* pass it on the the truetype driver and return it. */
/* */
static FT_Error
Mac_Read_sfnt_Resource( FT_Library library,
FT_Stream stream,
FT_Long *offsets,
FT_Long resource_cnt,
FT_Long face_index,
FT_Face *aface )
{
FT_Memory memory = library->memory;
FT_Byte* sfnt_data = NULL;
FT_Error error;
FT_Long flag_offset;
FT_Long rlen;
int is_cff;
FT_Long face_index_in_resource = 0;
 
 
if ( face_index == -1 )
face_index = 0;
if ( face_index >= resource_cnt )
return FT_THROW( Cannot_Open_Resource );
 
flag_offset = offsets[face_index];
error = FT_Stream_Seek( stream, flag_offset );
if ( error )
goto Exit;
 
if ( FT_READ_LONG( rlen ) )
goto Exit;
if ( rlen == -1 )
return FT_THROW( Cannot_Open_Resource );
 
error = open_face_PS_from_sfnt_stream( library,
stream,
face_index,
0, NULL,
aface );
if ( !error )
goto Exit;
 
/* rewind sfnt stream before open_face_PS_from_sfnt_stream() */
if ( FT_Stream_Seek( stream, flag_offset + 4 ) )
goto Exit;
 
if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) )
return error;
error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen );
if ( error )
goto Exit;
 
is_cff = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
error = open_face_from_buffer( library,
sfnt_data,
rlen,
face_index_in_resource,
is_cff ? "cff" : "truetype",
aface );
 
Exit:
return error;
}
 
 
/* Check for a valid resource fork header, or a valid dfont */
/* header. In a resource fork the first 16 bytes are repeated */
/* at the location specified by bytes 4-7. In a dfont bytes */
/* 4-7 point to 16 bytes of zeroes instead. */
/* */
static FT_Error
IsMacResource( FT_Library library,
FT_Stream stream,
FT_Long resource_offset,
FT_Long face_index,
FT_Face *aface )
{
FT_Memory memory = library->memory;
FT_Error error;
FT_Long map_offset, rdara_pos;
FT_Long *data_offsets;
FT_Long count;
 
 
error = FT_Raccess_Get_HeaderInfo( library, stream, resource_offset,
&map_offset, &rdara_pos );
if ( error )
return error;
 
error = FT_Raccess_Get_DataOffsets( library, stream,
map_offset, rdara_pos,
TTAG_POST,
&data_offsets, &count );
if ( !error )
{
error = Mac_Read_POST_Resource( library, stream, data_offsets, count,
face_index, aface );
FT_FREE( data_offsets );
/* POST exists in an LWFN providing a single face */
if ( !error )
(*aface)->num_faces = 1;
return error;
}
 
error = FT_Raccess_Get_DataOffsets( library, stream,
map_offset, rdara_pos,
TTAG_sfnt,
&data_offsets, &count );
if ( !error )
{
FT_Long face_index_internal = face_index % count;
 
 
error = Mac_Read_sfnt_Resource( library, stream, data_offsets, count,
face_index_internal, aface );
FT_FREE( data_offsets );
if ( !error )
(*aface)->num_faces = count;
}
 
return error;
}
 
 
/* Check for a valid macbinary header, and if we find one */
/* check that the (flattened) resource fork in it is valid. */
/* */
static FT_Error
IsMacBinary( FT_Library library,
FT_Stream stream,
FT_Long face_index,
FT_Face *aface )
{
unsigned char header[128];
FT_Error error;
FT_Long dlen, offset;
 
 
if ( NULL == stream )
return FT_THROW( Invalid_Stream_Operation );
 
error = FT_Stream_Seek( stream, 0 );
if ( error )
goto Exit;
 
error = FT_Stream_Read( stream, (FT_Byte*)header, 128 );
if ( error )
goto Exit;
 
if ( header[ 0] != 0 ||
header[74] != 0 ||
header[82] != 0 ||
header[ 1] == 0 ||
header[ 1] > 33 ||
header[63] != 0 ||
header[2 + header[1]] != 0 )
return FT_THROW( Unknown_File_Format );
 
dlen = ( header[0x53] << 24 ) |
( header[0x54] << 16 ) |
( header[0x55] << 8 ) |
header[0x56];
#if 0
rlen = ( header[0x57] << 24 ) |
( header[0x58] << 16 ) |
( header[0x59] << 8 ) |
header[0x5a];
#endif /* 0 */
offset = 128 + ( ( dlen + 127 ) & ~127 );
 
return IsMacResource( library, stream, offset, face_index, aface );
 
Exit:
return error;
}
 
 
static FT_Error
load_face_in_embedded_rfork( FT_Library library,
FT_Stream stream,
FT_Long face_index,
FT_Face *aface,
const FT_Open_Args *args )
{
 
#undef FT_COMPONENT
#define FT_COMPONENT trace_raccess
 
FT_Memory memory = library->memory;
FT_Error error = FT_ERR( Unknown_File_Format );
int i;
 
char * file_names[FT_RACCESS_N_RULES];
FT_Long offsets[FT_RACCESS_N_RULES];
FT_Error errors[FT_RACCESS_N_RULES];
FT_Bool is_darwin_vfs, vfs_rfork_has_no_font = FALSE; /* not tested */
 
FT_Open_Args args2;
FT_Stream stream2 = 0;
 
 
FT_Raccess_Guess( library, stream,
args->pathname, file_names, offsets, errors );
 
for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
{
is_darwin_vfs = ft_raccess_rule_by_darwin_vfs( library, i );
if ( is_darwin_vfs && vfs_rfork_has_no_font )
{
FT_TRACE3(( "Skip rule %d: darwin vfs resource fork"
" is already checked and"
" no font is found\n", i ));
continue;
}
 
if ( errors[i] )
{
FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors[i], i ));
continue;
}
 
args2.flags = FT_OPEN_PATHNAME;
args2.pathname = file_names[i] ? file_names[i] : args->pathname;
 
FT_TRACE3(( "Try rule %d: %s (offset=%d) ...",
i, args2.pathname, offsets[i] ));
 
error = FT_Stream_New( library, &args2, &stream2 );
if ( is_darwin_vfs && FT_ERR_EQ( error, Cannot_Open_Stream ) )
vfs_rfork_has_no_font = TRUE;
 
if ( error )
{
FT_TRACE3(( "failed\n" ));
continue;
}
 
error = IsMacResource( library, stream2, offsets[i],
face_index, aface );
FT_Stream_Free( stream2, 0 );
 
FT_TRACE3(( "%s\n", error ? "failed": "successful" ));
 
if ( !error )
break;
else if ( is_darwin_vfs )
vfs_rfork_has_no_font = TRUE;
}
 
for (i = 0; i < FT_RACCESS_N_RULES; i++)
{
if ( file_names[i] )
FT_FREE( file_names[i] );
}
 
/* Caller (load_mac_face) requires FT_Err_Unknown_File_Format. */
if ( error )
error = FT_ERR( Unknown_File_Format );
 
return error;
 
#undef FT_COMPONENT
#define FT_COMPONENT trace_objs
 
}
 
 
/* Check for some macintosh formats without Carbon framework. */
/* Is this a macbinary file? If so look at the resource fork. */
/* Is this a mac dfont file? */
/* Is this an old style resource fork? (in data) */
/* Else call load_face_in_embedded_rfork to try extra rules */
/* (defined in `ftrfork.c'). */
/* */
static FT_Error
load_mac_face( FT_Library library,
FT_Stream stream,
FT_Long face_index,
FT_Face *aface,
const FT_Open_Args *args )
{
FT_Error error;
FT_UNUSED( args );
 
 
error = IsMacBinary( library, stream, face_index, aface );
if ( FT_ERR_EQ( error, Unknown_File_Format ) )
{
 
#undef FT_COMPONENT
#define FT_COMPONENT trace_raccess
 
FT_TRACE3(( "Try as dfont: %s ...", args->pathname ));
 
error = IsMacResource( library, stream, 0, face_index, aface );
 
FT_TRACE3(( "%s\n", error ? "failed" : "successful" ));
 
#undef FT_COMPONENT
#define FT_COMPONENT trace_objs
 
}
 
if ( ( FT_ERR_EQ( error, Unknown_File_Format ) ||
FT_ERR_EQ( error, Invalid_Stream_Operation ) ) &&
( args->flags & FT_OPEN_PATHNAME ) )
error = load_face_in_embedded_rfork( library, stream,
face_index, aface, args );
return error;
}
#endif
 
#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Open_Face( FT_Library library,
const FT_Open_Args* args,
FT_Long face_index,
FT_Face *aface )
{
FT_Error error;
FT_Driver driver = NULL;
FT_Memory memory = NULL;
FT_Stream stream = NULL;
FT_Face face = NULL;
FT_ListNode node = NULL;
FT_Bool external_stream;
FT_Module* cur;
FT_Module* limit;
 
 
/* test for valid `library' delayed to */
/* FT_Stream_New() */
 
if ( ( !aface && face_index >= 0 ) || !args )
return FT_THROW( Invalid_Argument );
 
external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) &&
args->stream );
 
/* create input stream */
error = FT_Stream_New( library, args, &stream );
if ( error )
goto Fail3;
 
memory = library->memory;
 
/* If the font driver is specified in the `args' structure, use */
/* it. Otherwise, we scan the list of registered drivers. */
if ( ( args->flags & FT_OPEN_DRIVER ) && args->driver )
{
driver = FT_DRIVER( args->driver );
 
/* not all modules are drivers, so check... */
if ( FT_MODULE_IS_DRIVER( driver ) )
{
FT_Int num_params = 0;
FT_Parameter* params = 0;
 
 
if ( args->flags & FT_OPEN_PARAMS )
{
num_params = args->num_params;
params = args->params;
}
 
error = open_face( driver, stream, face_index,
num_params, params, &face );
if ( !error )
goto Success;
}
else
error = FT_THROW( Invalid_Handle );
 
FT_Stream_Free( stream, external_stream );
goto Fail;
}
else
{
error = FT_ERR( Missing_Module );
 
/* check each font driver for an appropriate format */
cur = library->modules;
limit = cur + library->num_modules;
 
for ( ; cur < limit; cur++ )
{
/* not all modules are font drivers, so check... */
if ( FT_MODULE_IS_DRIVER( cur[0] ) )
{
FT_Int num_params = 0;
FT_Parameter* params = 0;
 
 
driver = FT_DRIVER( cur[0] );
 
if ( args->flags & FT_OPEN_PARAMS )
{
num_params = args->num_params;
params = args->params;
}
 
error = open_face( driver, stream, face_index,
num_params, params, &face );
if ( !error )
goto Success;
 
#ifdef FT_CONFIG_OPTION_MAC_FONTS
if ( ft_strcmp( cur[0]->clazz->module_name, "truetype" ) == 0 &&
FT_ERR_EQ( error, Table_Missing ) )
{
/* TrueType but essential tables are missing */
if ( FT_Stream_Seek( stream, 0 ) )
break;
 
error = open_face_PS_from_sfnt_stream( library,
stream,
face_index,
num_params,
params,
aface );
if ( !error )
{
FT_Stream_Free( stream, external_stream );
return error;
}
}
#endif
 
if ( FT_ERR_NEQ( error, Unknown_File_Format ) )
goto Fail3;
}
}
 
Fail3:
/* If we are on the mac, and we get an */
/* FT_Err_Invalid_Stream_Operation it may be because we have an */
/* empty data fork, so we need to check the resource fork. */
if ( FT_ERR_NEQ( error, Cannot_Open_Stream ) &&
FT_ERR_NEQ( error, Unknown_File_Format ) &&
FT_ERR_NEQ( error, Invalid_Stream_Operation ) )
goto Fail2;
 
#if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS )
error = load_mac_face( library, stream, face_index, aface, args );
if ( !error )
{
/* We don't want to go to Success here. We've already done that. */
/* On the other hand, if we succeeded we still need to close this */
/* stream (we opened a different stream which extracted the */
/* interesting information out of this stream here. That stream */
/* will still be open and the face will point to it). */
FT_Stream_Free( stream, external_stream );
return error;
}
 
if ( FT_ERR_NEQ( error, Unknown_File_Format ) )
goto Fail2;
#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
 
/* no driver is able to handle this format */
error = FT_THROW( Unknown_File_Format );
 
Fail2:
FT_Stream_Free( stream, external_stream );
goto Fail;
}
 
Success:
FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));
 
/* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
if ( external_stream )
face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
 
/* add the face object to its driver's list */
if ( FT_NEW( node ) )
goto Fail;
 
node->data = face;
/* don't assume driver is the same as face->driver, so use */
/* face->driver instead. */
FT_List_Add( &face->driver->faces_list, node );
 
/* now allocate a glyph slot object for the face */
FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
 
if ( face_index >= 0 )
{
error = FT_New_GlyphSlot( face, NULL );
if ( error )
goto Fail;
 
/* finally, allocate a size object for the face */
{
FT_Size size;
 
 
FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
 
error = FT_New_Size( face, &size );
if ( error )
goto Fail;
 
face->size = size;
}
}
 
/* some checks */
 
if ( FT_IS_SCALABLE( face ) )
{
if ( face->height < 0 )
face->height = (FT_Short)-face->height;
 
if ( !FT_HAS_VERTICAL( face ) )
face->max_advance_height = (FT_Short)face->height;
}
 
if ( FT_HAS_FIXED_SIZES( face ) )
{
FT_Int i;
 
 
for ( i = 0; i < face->num_fixed_sizes; i++ )
{
FT_Bitmap_Size* bsize = face->available_sizes + i;
 
 
if ( bsize->height < 0 )
bsize->height = (FT_Short)-bsize->height;
if ( bsize->x_ppem < 0 )
bsize->x_ppem = (FT_Short)-bsize->x_ppem;
if ( bsize->y_ppem < 0 )
bsize->y_ppem = -bsize->y_ppem;
}
}
 
/* initialize internal face data */
{
FT_Face_Internal internal = face->internal;
 
 
internal->transform_matrix.xx = 0x10000L;
internal->transform_matrix.xy = 0;
internal->transform_matrix.yx = 0;
internal->transform_matrix.yy = 0x10000L;
 
internal->transform_delta.x = 0;
internal->transform_delta.y = 0;
 
internal->refcount = 1;
}
 
if ( aface )
*aface = face;
else
FT_Done_Face( face );
 
goto Exit;
 
Fail:
if ( node )
FT_Done_Face( face ); /* face must be in the driver's list */
else if ( face )
destroy_face( memory, face, driver );
 
Exit:
FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
 
return error;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Attach_File( FT_Face face,
const char* filepathname )
{
FT_Open_Args open;
 
 
/* test for valid `face' delayed to FT_Attach_Stream() */
 
if ( !filepathname )
return FT_THROW( Invalid_Argument );
 
open.stream = NULL;
open.flags = FT_OPEN_PATHNAME;
open.pathname = (char*)filepathname;
 
return FT_Attach_Stream( face, &open );
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Attach_Stream( FT_Face face,
FT_Open_Args* parameters )
{
FT_Stream stream;
FT_Error error;
FT_Driver driver;
 
FT_Driver_Class clazz;
 
 
/* test for valid `parameters' delayed to FT_Stream_New() */
 
if ( !face )
return FT_THROW( Invalid_Face_Handle );
 
driver = face->driver;
if ( !driver )
return FT_THROW( Invalid_Driver_Handle );
 
error = FT_Stream_New( driver->root.library, parameters, &stream );
if ( error )
goto Exit;
 
/* we implement FT_Attach_Stream in each driver through the */
/* `attach_file' interface */
 
error = FT_ERR( Unimplemented_Feature );
clazz = driver->clazz;
if ( clazz->attach_file )
error = clazz->attach_file( face, stream );
 
/* close the attached stream */
FT_Stream_Free( stream,
(FT_Bool)( parameters->stream &&
( parameters->flags & FT_OPEN_STREAM ) ) );
 
Exit:
return error;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Reference_Face( FT_Face face )
{
face->internal->refcount++;
 
return FT_Err_Ok;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Done_Face( FT_Face face )
{
FT_Error error;
FT_Driver driver;
FT_Memory memory;
FT_ListNode node;
 
 
error = FT_ERR( Invalid_Face_Handle );
if ( face && face->driver )
{
face->internal->refcount--;
if ( face->internal->refcount > 0 )
error = FT_Err_Ok;
else
{
driver = face->driver;
memory = driver->root.memory;
 
/* find face in driver's list */
node = FT_List_Find( &driver->faces_list, face );
if ( node )
{
/* remove face object from the driver's list */
FT_List_Remove( &driver->faces_list, node );
FT_FREE( node );
 
/* now destroy the object proper */
destroy_face( memory, face, driver );
error = FT_Err_Ok;
}
}
}
 
return error;
}
 
 
/* documentation is in ftobjs.h */
 
FT_EXPORT_DEF( FT_Error )
FT_New_Size( FT_Face face,
FT_Size *asize )
{
FT_Error error;
FT_Memory memory;
FT_Driver driver;
FT_Driver_Class clazz;
 
FT_Size size = 0;
FT_ListNode node = 0;
 
 
if ( !face )
return FT_THROW( Invalid_Face_Handle );
 
if ( !asize )
return FT_THROW( Invalid_Size_Handle );
 
if ( !face->driver )
return FT_THROW( Invalid_Driver_Handle );
 
*asize = 0;
 
driver = face->driver;
clazz = driver->clazz;
memory = face->memory;
 
/* Allocate new size object and perform basic initialisation */
if ( FT_ALLOC( size, clazz->size_object_size ) || FT_NEW( node ) )
goto Exit;
 
size->face = face;
 
/* for now, do not use any internal fields in size objects */
size->internal = 0;
 
if ( clazz->init_size )
error = clazz->init_size( size );
 
/* in case of success, add to the face's list */
if ( !error )
{
*asize = size;
node->data = size;
FT_List_Add( &face->sizes_list, node );
}
 
Exit:
if ( error )
{
FT_FREE( node );
FT_FREE( size );
}
 
return error;
}
 
 
/* documentation is in ftobjs.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Done_Size( FT_Size size )
{
FT_Error error;
FT_Driver driver;
FT_Memory memory;
FT_Face face;
FT_ListNode node;
 
 
if ( !size )
return FT_THROW( Invalid_Size_Handle );
 
face = size->face;
if ( !face )
return FT_THROW( Invalid_Face_Handle );
 
driver = face->driver;
if ( !driver )
return FT_THROW( Invalid_Driver_Handle );
 
memory = driver->root.memory;
 
error = FT_Err_Ok;
node = FT_List_Find( &face->sizes_list, size );
if ( node )
{
FT_List_Remove( &face->sizes_list, node );
FT_FREE( node );
 
if ( face->size == size )
{
face->size = 0;
if ( face->sizes_list.head )
face->size = (FT_Size)(face->sizes_list.head->data);
}
 
destroy_size( memory, size, driver );
}
else
error = FT_THROW( Invalid_Size_Handle );
 
return error;
}
 
 
/* documentation is in ftobjs.h */
 
FT_BASE_DEF( FT_Error )
FT_Match_Size( FT_Face face,
FT_Size_Request req,
FT_Bool ignore_width,
FT_ULong* size_index )
{
FT_Int i;
FT_Long w, h;
 
 
if ( !FT_HAS_FIXED_SIZES( face ) )
return FT_THROW( Invalid_Face_Handle );
 
/* FT_Bitmap_Size doesn't provide enough info... */
if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
return FT_THROW( Unimplemented_Feature );
 
w = FT_REQUEST_WIDTH ( req );
h = FT_REQUEST_HEIGHT( req );
 
if ( req->width && !req->height )
h = w;
else if ( !req->width && req->height )
w = h;
 
w = FT_PIX_ROUND( w );
h = FT_PIX_ROUND( h );
 
for ( i = 0; i < face->num_fixed_sizes; i++ )
{
FT_Bitmap_Size* bsize = face->available_sizes + i;
 
 
if ( h != FT_PIX_ROUND( bsize->y_ppem ) )
continue;
 
if ( w == FT_PIX_ROUND( bsize->x_ppem ) || ignore_width )
{
FT_TRACE3(( "FT_Match_Size: bitmap strike %d matches\n", i ));
 
if ( size_index )
*size_index = (FT_ULong)i;
 
return FT_Err_Ok;
}
}
 
return FT_THROW( Invalid_Pixel_Size );
}
 
 
/* documentation is in ftobjs.h */
 
FT_BASE_DEF( void )
ft_synthesize_vertical_metrics( FT_Glyph_Metrics* metrics,
FT_Pos advance )
{
FT_Pos height = metrics->height;
 
 
/* compensate for glyph with bbox above/below the baseline */
if ( metrics->horiBearingY < 0 )
{
if ( height < metrics->horiBearingY )
height = metrics->horiBearingY;
}
else if ( metrics->horiBearingY > 0 )
height -= metrics->horiBearingY;
 
/* the factor 1.2 is a heuristical value */
if ( !advance )
advance = height * 12 / 10;
 
metrics->vertBearingX = metrics->horiBearingX - metrics->horiAdvance / 2;
metrics->vertBearingY = ( advance - height ) / 2;
metrics->vertAdvance = advance;
}
 
 
static void
ft_recompute_scaled_metrics( FT_Face face,
FT_Size_Metrics* metrics )
{
/* Compute root ascender, descender, test height, and max_advance */
 
#ifdef GRID_FIT_METRICS
metrics->ascender = FT_PIX_CEIL( FT_MulFix( face->ascender,
metrics->y_scale ) );
 
metrics->descender = FT_PIX_FLOOR( FT_MulFix( face->descender,
metrics->y_scale ) );
 
metrics->height = FT_PIX_ROUND( FT_MulFix( face->height,
metrics->y_scale ) );
 
metrics->max_advance = FT_PIX_ROUND( FT_MulFix( face->max_advance_width,
metrics->x_scale ) );
#else /* !GRID_FIT_METRICS */
metrics->ascender = FT_MulFix( face->ascender,
metrics->y_scale );
 
metrics->descender = FT_MulFix( face->descender,
metrics->y_scale );
 
metrics->height = FT_MulFix( face->height,
metrics->y_scale );
 
metrics->max_advance = FT_MulFix( face->max_advance_width,
metrics->x_scale );
#endif /* !GRID_FIT_METRICS */
}
 
 
FT_BASE_DEF( void )
FT_Select_Metrics( FT_Face face,
FT_ULong strike_index )
{
FT_Size_Metrics* metrics;
FT_Bitmap_Size* bsize;
 
 
metrics = &face->size->metrics;
bsize = face->available_sizes + strike_index;
 
metrics->x_ppem = (FT_UShort)( ( bsize->x_ppem + 32 ) >> 6 );
metrics->y_ppem = (FT_UShort)( ( bsize->y_ppem + 32 ) >> 6 );
 
if ( FT_IS_SCALABLE( face ) )
{
metrics->x_scale = FT_DivFix( bsize->x_ppem,
face->units_per_EM );
metrics->y_scale = FT_DivFix( bsize->y_ppem,
face->units_per_EM );
 
ft_recompute_scaled_metrics( face, metrics );
}
else
{
metrics->x_scale = 1L << 16;
metrics->y_scale = 1L << 16;
metrics->ascender = bsize->y_ppem;
metrics->descender = 0;
metrics->height = bsize->height << 6;
metrics->max_advance = bsize->x_ppem;
}
 
FT_TRACE5(( "FT_Select_Metrics:\n" ));
FT_TRACE5(( " x scale: %d (%f)\n",
metrics->x_scale, metrics->x_scale / 65536.0 ));
FT_TRACE5(( " y scale: %d (%f)\n",
metrics->y_scale, metrics->y_scale / 65536.0 ));
FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 ));
FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 ));
FT_TRACE5(( " height: %f\n", metrics->height / 64.0 ));
FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 ));
FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem ));
FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem ));
}
 
 
FT_BASE_DEF( void )
FT_Request_Metrics( FT_Face face,
FT_Size_Request req )
{
FT_Size_Metrics* metrics;
 
 
metrics = &face->size->metrics;
 
if ( FT_IS_SCALABLE( face ) )
{
FT_Long w = 0, h = 0, scaled_w = 0, scaled_h = 0;
 
 
switch ( req->type )
{
case FT_SIZE_REQUEST_TYPE_NOMINAL:
w = h = face->units_per_EM;
break;
 
case FT_SIZE_REQUEST_TYPE_REAL_DIM:
w = h = face->ascender - face->descender;
break;
 
case FT_SIZE_REQUEST_TYPE_BBOX:
w = face->bbox.xMax - face->bbox.xMin;
h = face->bbox.yMax - face->bbox.yMin;
break;
 
case FT_SIZE_REQUEST_TYPE_CELL:
w = face->max_advance_width;
h = face->ascender - face->descender;
break;
 
case FT_SIZE_REQUEST_TYPE_SCALES:
metrics->x_scale = (FT_Fixed)req->width;
metrics->y_scale = (FT_Fixed)req->height;
if ( !metrics->x_scale )
metrics->x_scale = metrics->y_scale;
else if ( !metrics->y_scale )
metrics->y_scale = metrics->x_scale;
goto Calculate_Ppem;
 
case FT_SIZE_REQUEST_TYPE_MAX:
break;
}
 
/* to be on the safe side */
if ( w < 0 )
w = -w;
 
if ( h < 0 )
h = -h;
 
scaled_w = FT_REQUEST_WIDTH ( req );
scaled_h = FT_REQUEST_HEIGHT( req );
 
/* determine scales */
if ( req->width )
{
metrics->x_scale = FT_DivFix( scaled_w, w );
 
if ( req->height )
{
metrics->y_scale = FT_DivFix( scaled_h, h );
 
if ( req->type == FT_SIZE_REQUEST_TYPE_CELL )
{
if ( metrics->y_scale > metrics->x_scale )
metrics->y_scale = metrics->x_scale;
else
metrics->x_scale = metrics->y_scale;
}
}
else
{
metrics->y_scale = metrics->x_scale;
scaled_h = FT_MulDiv( scaled_w, h, w );
}
}
else
{
metrics->x_scale = metrics->y_scale = FT_DivFix( scaled_h, h );
scaled_w = FT_MulDiv( scaled_h, w, h );
}
 
Calculate_Ppem:
/* calculate the ppems */
if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
{
scaled_w = FT_MulFix( face->units_per_EM, metrics->x_scale );
scaled_h = FT_MulFix( face->units_per_EM, metrics->y_scale );
}
 
metrics->x_ppem = (FT_UShort)( ( scaled_w + 32 ) >> 6 );
metrics->y_ppem = (FT_UShort)( ( scaled_h + 32 ) >> 6 );
 
ft_recompute_scaled_metrics( face, metrics );
}
else
{
FT_ZERO( metrics );
metrics->x_scale = 1L << 16;
metrics->y_scale = 1L << 16;
}
 
FT_TRACE5(( "FT_Request_Metrics:\n" ));
FT_TRACE5(( " x scale: %d (%f)\n",
metrics->x_scale, metrics->x_scale / 65536.0 ));
FT_TRACE5(( " y scale: %d (%f)\n",
metrics->y_scale, metrics->y_scale / 65536.0 ));
FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 ));
FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 ));
FT_TRACE5(( " height: %f\n", metrics->height / 64.0 ));
FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 ));
FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem ));
FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem ));
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Select_Size( FT_Face face,
FT_Int strike_index )
{
FT_Driver_Class clazz;
 
 
if ( !face || !FT_HAS_FIXED_SIZES( face ) )
return FT_THROW( Invalid_Face_Handle );
 
if ( strike_index < 0 || strike_index >= face->num_fixed_sizes )
return FT_THROW( Invalid_Argument );
 
clazz = face->driver->clazz;
 
if ( clazz->select_size )
{
FT_Error error;
 
 
error = clazz->select_size( face->size, (FT_ULong)strike_index );
 
#ifdef FT_DEBUG_LEVEL_TRACE
{
FT_Size_Metrics* metrics = &face->size->metrics;
 
 
FT_TRACE5(( "FT_Select_Size (font driver's `select_size'):\n" ));
FT_TRACE5(( " x scale: %d (%f)\n",
metrics->x_scale, metrics->x_scale / 65536.0 ));
FT_TRACE5(( " y scale: %d (%f)\n",
metrics->y_scale, metrics->y_scale / 65536.0 ));
FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 ));
FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 ));
FT_TRACE5(( " height: %f\n", metrics->height / 64.0 ));
FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 ));
FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem ));
FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem ));
}
#endif
 
return error;
}
 
FT_Select_Metrics( face, (FT_ULong)strike_index );
 
return FT_Err_Ok;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Request_Size( FT_Face face,
FT_Size_Request req )
{
FT_Driver_Class clazz;
FT_ULong strike_index;
 
 
if ( !face )
return FT_THROW( Invalid_Face_Handle );
 
if ( !req || req->width < 0 || req->height < 0 ||
req->type >= FT_SIZE_REQUEST_TYPE_MAX )
return FT_THROW( Invalid_Argument );
 
clazz = face->driver->clazz;
 
if ( clazz->request_size )
{
FT_Error error;
 
 
error = clazz->request_size( face->size, req );
 
#ifdef FT_DEBUG_LEVEL_TRACE
{
FT_Size_Metrics* metrics = &face->size->metrics;
 
 
FT_TRACE5(( "FT_Request_Size (font driver's `request_size'):\n" ));
FT_TRACE5(( " x scale: %d (%f)\n",
metrics->x_scale, metrics->x_scale / 65536.0 ));
FT_TRACE5(( " y scale: %d (%f)\n",
metrics->y_scale, metrics->y_scale / 65536.0 ));
FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 ));
FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 ));
FT_TRACE5(( " height: %f\n", metrics->height / 64.0 ));
FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 ));
FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem ));
FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem ));
}
#endif
 
return error;
}
 
/*
* The reason that a driver doesn't have `request_size' defined is
* either that the scaling here suffices or that the supported formats
* are bitmap-only and size matching is not implemented.
*
* In the latter case, a simple size matching is done.
*/
if ( !FT_IS_SCALABLE( face ) && FT_HAS_FIXED_SIZES( face ) )
{
FT_Error error;
 
 
error = FT_Match_Size( face, req, 0, &strike_index );
if ( error )
return error;
 
return FT_Select_Size( face, (FT_Int)strike_index );
}
 
FT_Request_Metrics( face, req );
 
return FT_Err_Ok;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Set_Char_Size( FT_Face face,
FT_F26Dot6 char_width,
FT_F26Dot6 char_height,
FT_UInt horz_resolution,
FT_UInt vert_resolution )
{
FT_Size_RequestRec req;
 
 
if ( !char_width )
char_width = char_height;
else if ( !char_height )
char_height = char_width;
 
if ( !horz_resolution )
horz_resolution = vert_resolution;
else if ( !vert_resolution )
vert_resolution = horz_resolution;
 
if ( char_width < 1 * 64 )
char_width = 1 * 64;
if ( char_height < 1 * 64 )
char_height = 1 * 64;
 
if ( !horz_resolution )
horz_resolution = vert_resolution = 72;
 
req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
req.width = char_width;
req.height = char_height;
req.horiResolution = horz_resolution;
req.vertResolution = vert_resolution;
 
return FT_Request_Size( face, &req );
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Set_Pixel_Sizes( FT_Face face,
FT_UInt pixel_width,
FT_UInt pixel_height )
{
FT_Size_RequestRec req;
 
 
if ( pixel_width == 0 )
pixel_width = pixel_height;
else if ( pixel_height == 0 )
pixel_height = pixel_width;
 
if ( pixel_width < 1 )
pixel_width = 1;
if ( pixel_height < 1 )
pixel_height = 1;
 
/* use `>=' to avoid potential compiler warning on 16bit platforms */
if ( pixel_width >= 0xFFFFU )
pixel_width = 0xFFFFU;
if ( pixel_height >= 0xFFFFU )
pixel_height = 0xFFFFU;
 
req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
req.width = pixel_width << 6;
req.height = pixel_height << 6;
req.horiResolution = 0;
req.vertResolution = 0;
 
return FT_Request_Size( face, &req );
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Get_Kerning( FT_Face face,
FT_UInt left_glyph,
FT_UInt right_glyph,
FT_UInt kern_mode,
FT_Vector *akerning )
{
FT_Error error = FT_Err_Ok;
FT_Driver driver;
 
 
if ( !face )
return FT_THROW( Invalid_Face_Handle );
 
if ( !akerning )
return FT_THROW( Invalid_Argument );
 
driver = face->driver;
 
akerning->x = 0;
akerning->y = 0;
 
if ( driver->clazz->get_kerning )
{
error = driver->clazz->get_kerning( face,
left_glyph,
right_glyph,
akerning );
if ( !error )
{
if ( kern_mode != FT_KERNING_UNSCALED )
{
akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale );
akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale );
 
if ( kern_mode != FT_KERNING_UNFITTED )
{
/* we scale down kerning values for small ppem values */
/* to avoid that rounding makes them too big. */
/* `25' has been determined heuristically. */
if ( face->size->metrics.x_ppem < 25 )
akerning->x = FT_MulDiv( akerning->x,
face->size->metrics.x_ppem, 25 );
if ( face->size->metrics.y_ppem < 25 )
akerning->y = FT_MulDiv( akerning->y,
face->size->metrics.y_ppem, 25 );
 
akerning->x = FT_PIX_ROUND( akerning->x );
akerning->y = FT_PIX_ROUND( akerning->y );
}
}
}
}
 
return error;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Get_Track_Kerning( FT_Face face,
FT_Fixed point_size,
FT_Int degree,
FT_Fixed* akerning )
{
FT_Service_Kerning service;
FT_Error error = FT_Err_Ok;
 
 
if ( !face )
return FT_THROW( Invalid_Face_Handle );
 
if ( !akerning )
return FT_THROW( Invalid_Argument );
 
FT_FACE_FIND_SERVICE( face, service, KERNING );
if ( !service )
return FT_THROW( Unimplemented_Feature );
 
error = service->get_track( face,
point_size,
degree,
akerning );
 
return error;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Select_Charmap( FT_Face face,
FT_Encoding encoding )
{
FT_CharMap* cur;
FT_CharMap* limit;
 
 
if ( !face )
return FT_THROW( Invalid_Face_Handle );
 
if ( encoding == FT_ENCODING_NONE )
return FT_THROW( Invalid_Argument );
 
/* FT_ENCODING_UNICODE is special. We try to find the `best' Unicode */
/* charmap available, i.e., one with UCS-4 characters, if possible. */
/* */
/* This is done by find_unicode_charmap() above, to share code. */
if ( encoding == FT_ENCODING_UNICODE )
return find_unicode_charmap( face );
 
cur = face->charmaps;
if ( !cur )
return FT_THROW( Invalid_CharMap_Handle );
 
limit = cur + face->num_charmaps;
 
for ( ; cur < limit; cur++ )
{
if ( cur[0]->encoding == encoding )
{
#ifdef FT_MAX_CHARMAP_CACHEABLE
if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE )
{
FT_ERROR(( "FT_Select_Charmap: requested charmap is found (%d), "
"but in too late position to cache\n",
cur - face->charmaps ));
continue;
}
#endif
face->charmap = cur[0];
return 0;
}
}
 
return FT_THROW( Invalid_Argument );
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Set_Charmap( FT_Face face,
FT_CharMap charmap )
{
FT_CharMap* cur;
FT_CharMap* limit;
 
 
if ( !face )
return FT_THROW( Invalid_Face_Handle );
 
cur = face->charmaps;
if ( !cur )
return FT_THROW( Invalid_CharMap_Handle );
if ( FT_Get_CMap_Format( charmap ) == 14 )
return FT_THROW( Invalid_Argument );
 
limit = cur + face->num_charmaps;
 
for ( ; cur < limit; cur++ )
{
if ( cur[0] == charmap )
{
#ifdef FT_MAX_CHARMAP_CACHEABLE
if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE )
{
FT_ERROR(( "FT_Set_Charmap: requested charmap is found (%d), "
"but in too late position to cache\n",
cur - face->charmaps ));
continue;
}
#endif
face->charmap = cur[0];
return 0;
}
}
return FT_THROW( Invalid_Argument );
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Int )
FT_Get_Charmap_Index( FT_CharMap charmap )
{
FT_Int i;
 
 
if ( !charmap || !charmap->face )
return -1;
 
for ( i = 0; i < charmap->face->num_charmaps; i++ )
if ( charmap->face->charmaps[i] == charmap )
break;
 
FT_ASSERT( i < charmap->face->num_charmaps );
 
#ifdef FT_MAX_CHARMAP_CACHEABLE
if ( i > FT_MAX_CHARMAP_CACHEABLE )
{
FT_ERROR(( "FT_Get_Charmap_Index: requested charmap is found (%d), "
"but in too late position to cache\n",
i ));
return -i;
}
#endif
return i;
}
 
 
static void
ft_cmap_done_internal( FT_CMap cmap )
{
FT_CMap_Class clazz = cmap->clazz;
FT_Face face = cmap->charmap.face;
FT_Memory memory = FT_FACE_MEMORY( face );
 
 
if ( clazz->done )
clazz->done( cmap );
 
FT_FREE( cmap );
}
 
 
FT_BASE_DEF( void )
FT_CMap_Done( FT_CMap cmap )
{
if ( cmap )
{
FT_Face face = cmap->charmap.face;
FT_Memory memory = FT_FACE_MEMORY( face );
FT_Error error;
FT_Int i, j;
 
 
for ( i = 0; i < face->num_charmaps; i++ )
{
if ( (FT_CMap)face->charmaps[i] == cmap )
{
FT_CharMap last_charmap = face->charmaps[face->num_charmaps - 1];
 
 
if ( FT_RENEW_ARRAY( face->charmaps,
face->num_charmaps,
face->num_charmaps - 1 ) )
return;
 
/* remove it from our list of charmaps */
for ( j = i + 1; j < face->num_charmaps; j++ )
{
if ( j == face->num_charmaps - 1 )
face->charmaps[j - 1] = last_charmap;
else
face->charmaps[j - 1] = face->charmaps[j];
}
 
face->num_charmaps--;
 
if ( (FT_CMap)face->charmap == cmap )
face->charmap = NULL;
 
ft_cmap_done_internal( cmap );
 
break;
}
}
}
}
 
 
FT_BASE_DEF( FT_Error )
FT_CMap_New( FT_CMap_Class clazz,
FT_Pointer init_data,
FT_CharMap charmap,
FT_CMap *acmap )
{
FT_Error error = FT_Err_Ok;
FT_Face face;
FT_Memory memory;
FT_CMap cmap = NULL;
 
 
if ( clazz == NULL || charmap == NULL || charmap->face == NULL )
return FT_THROW( Invalid_Argument );
 
face = charmap->face;
memory = FT_FACE_MEMORY( face );
 
if ( !FT_ALLOC( cmap, clazz->size ) )
{
cmap->charmap = *charmap;
cmap->clazz = clazz;
 
if ( clazz->init )
{
error = clazz->init( cmap, init_data );
if ( error )
goto Fail;
}
 
/* add it to our list of charmaps */
if ( FT_RENEW_ARRAY( face->charmaps,
face->num_charmaps,
face->num_charmaps + 1 ) )
goto Fail;
 
face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap;
}
 
Exit:
if ( acmap )
*acmap = cmap;
 
return error;
 
Fail:
ft_cmap_done_internal( cmap );
cmap = NULL;
goto Exit;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_UInt )
FT_Get_Char_Index( FT_Face face,
FT_ULong charcode )
{
FT_UInt result = 0;
 
 
if ( face && face->charmap )
{
FT_CMap cmap = FT_CMAP( face->charmap );
 
 
if ( charcode > 0xFFFFFFFFUL )
{
FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
FT_TRACE1(( " 0x%x is truncated\n", charcode ));
}
result = cmap->clazz->char_index( cmap, (FT_UInt32)charcode );
}
return result;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_ULong )
FT_Get_First_Char( FT_Face face,
FT_UInt *agindex )
{
FT_ULong result = 0;
FT_UInt gindex = 0;
 
 
if ( face && face->charmap && face->num_glyphs )
{
gindex = FT_Get_Char_Index( face, 0 );
if ( gindex == 0 || gindex >= (FT_UInt)face->num_glyphs )
result = FT_Get_Next_Char( face, 0, &gindex );
}
 
if ( agindex )
*agindex = gindex;
 
return result;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_ULong )
FT_Get_Next_Char( FT_Face face,
FT_ULong charcode,
FT_UInt *agindex )
{
FT_ULong result = 0;
FT_UInt gindex = 0;
 
 
if ( face && face->charmap && face->num_glyphs )
{
FT_UInt32 code = (FT_UInt32)charcode;
FT_CMap cmap = FT_CMAP( face->charmap );
 
 
do {
gindex = cmap->clazz->char_next( cmap, &code );
} while ( gindex >= (FT_UInt)face->num_glyphs );
 
result = ( gindex == 0 ) ? 0 : code;
}
 
if ( agindex )
*agindex = gindex;
 
return result;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_UInt )
FT_Face_GetCharVariantIndex( FT_Face face,
FT_ULong charcode,
FT_ULong variantSelector )
{
FT_UInt result = 0;
 
 
if ( face && face->charmap &&
face->charmap->encoding == FT_ENCODING_UNICODE )
{
FT_CharMap charmap = find_variant_selector_charmap( face );
FT_CMap ucmap = FT_CMAP( face->charmap );
 
 
if ( charmap != NULL )
{
FT_CMap vcmap = FT_CMAP( charmap );
 
 
if ( charcode > 0xFFFFFFFFUL )
{
FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
FT_TRACE1(( " 0x%x is truncated\n", charcode ));
}
if ( variantSelector > 0xFFFFFFFFUL )
{
FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" ));
FT_TRACE1(( " 0x%x is truncated\n", variantSelector ));
}
 
result = vcmap->clazz->char_var_index( vcmap, ucmap,
(FT_UInt32)charcode,
(FT_UInt32)variantSelector );
}
}
 
return result;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Int )
FT_Face_GetCharVariantIsDefault( FT_Face face,
FT_ULong charcode,
FT_ULong variantSelector )
{
FT_Int result = -1;
 
 
if ( face )
{
FT_CharMap charmap = find_variant_selector_charmap( face );
 
 
if ( charmap != NULL )
{
FT_CMap vcmap = FT_CMAP( charmap );
 
 
if ( charcode > 0xFFFFFFFFUL )
{
FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
FT_TRACE1(( " 0x%x is truncated\n", charcode ));
}
if ( variantSelector > 0xFFFFFFFFUL )
{
FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" ));
FT_TRACE1(( " 0x%x is truncated\n", variantSelector ));
}
 
result = vcmap->clazz->char_var_default( vcmap,
(FT_UInt32)charcode,
(FT_UInt32)variantSelector );
}
}
 
return result;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_UInt32* )
FT_Face_GetVariantSelectors( FT_Face face )
{
FT_UInt32 *result = NULL;
 
 
if ( face )
{
FT_CharMap charmap = find_variant_selector_charmap( face );
 
 
if ( charmap != NULL )
{
FT_CMap vcmap = FT_CMAP( charmap );
FT_Memory memory = FT_FACE_MEMORY( face );
 
 
result = vcmap->clazz->variant_list( vcmap, memory );
}
}
 
return result;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_UInt32* )
FT_Face_GetVariantsOfChar( FT_Face face,
FT_ULong charcode )
{
FT_UInt32 *result = NULL;
 
 
if ( face )
{
FT_CharMap charmap = find_variant_selector_charmap( face );
 
 
if ( charmap != NULL )
{
FT_CMap vcmap = FT_CMAP( charmap );
FT_Memory memory = FT_FACE_MEMORY( face );
 
 
if ( charcode > 0xFFFFFFFFUL )
{
FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
FT_TRACE1(( " 0x%x is truncated\n", charcode ));
}
 
result = vcmap->clazz->charvariant_list( vcmap, memory,
(FT_UInt32)charcode );
}
}
return result;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_UInt32* )
FT_Face_GetCharsOfVariant( FT_Face face,
FT_ULong variantSelector )
{
FT_UInt32 *result = NULL;
 
 
if ( face )
{
FT_CharMap charmap = find_variant_selector_charmap( face );
 
 
if ( charmap != NULL )
{
FT_CMap vcmap = FT_CMAP( charmap );
FT_Memory memory = FT_FACE_MEMORY( face );
 
 
if ( variantSelector > 0xFFFFFFFFUL )
{
FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" ));
FT_TRACE1(( " 0x%x is truncated\n", variantSelector ));
}
 
result = vcmap->clazz->variantchar_list( vcmap, memory,
(FT_UInt32)variantSelector );
}
}
 
return result;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_UInt )
FT_Get_Name_Index( FT_Face face,
FT_String* glyph_name )
{
FT_UInt result = 0;
 
 
if ( face && FT_HAS_GLYPH_NAMES( face ) )
{
FT_Service_GlyphDict service;
 
 
FT_FACE_LOOKUP_SERVICE( face,
service,
GLYPH_DICT );
 
if ( service && service->name_index )
result = service->name_index( face, glyph_name );
}
 
return result;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Get_Glyph_Name( FT_Face face,
FT_UInt glyph_index,
FT_Pointer buffer,
FT_UInt buffer_max )
{
FT_Error error = FT_ERR( Invalid_Argument );
 
 
/* clean up buffer */
if ( buffer && buffer_max > 0 )
((FT_Byte*)buffer)[0] = 0;
 
if ( face &&
(FT_Long)glyph_index <= face->num_glyphs &&
FT_HAS_GLYPH_NAMES( face ) )
{
FT_Service_GlyphDict service;
 
 
FT_FACE_LOOKUP_SERVICE( face,
service,
GLYPH_DICT );
 
if ( service && service->get_name )
error = service->get_name( face, glyph_index, buffer, buffer_max );
}
 
return error;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( const char* )
FT_Get_Postscript_Name( FT_Face face )
{
const char* result = NULL;
 
 
if ( !face )
goto Exit;
 
if ( !result )
{
FT_Service_PsFontName service;
 
 
FT_FACE_LOOKUP_SERVICE( face,
service,
POSTSCRIPT_FONT_NAME );
 
if ( service && service->get_ps_font_name )
result = service->get_ps_font_name( face );
}
 
Exit:
return result;
}
 
 
/* documentation is in tttables.h */
 
FT_EXPORT_DEF( void* )
FT_Get_Sfnt_Table( FT_Face face,
FT_Sfnt_Tag tag )
{
void* table = 0;
FT_Service_SFNT_Table service;
 
 
if ( face && FT_IS_SFNT( face ) )
{
FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
if ( service != NULL )
table = service->get_table( face, tag );
}
 
return table;
}
 
 
/* documentation is in tttables.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Load_Sfnt_Table( FT_Face face,
FT_ULong tag,
FT_Long offset,
FT_Byte* buffer,
FT_ULong* length )
{
FT_Service_SFNT_Table service;
 
 
if ( !face || !FT_IS_SFNT( face ) )
return FT_THROW( Invalid_Face_Handle );
 
FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
if ( service == NULL )
return FT_THROW( Unimplemented_Feature );
 
return service->load_table( face, tag, offset, buffer, length );
}
 
 
/* documentation is in tttables.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Sfnt_Table_Info( FT_Face face,
FT_UInt table_index,
FT_ULong *tag,
FT_ULong *length )
{
FT_Service_SFNT_Table service;
FT_ULong offset;
 
 
if ( !face || !FT_IS_SFNT( face ) )
return FT_THROW( Invalid_Face_Handle );
 
FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
if ( service == NULL )
return FT_THROW( Unimplemented_Feature );
 
return service->table_info( face, table_index, tag, &offset, length );
}
 
 
/* documentation is in tttables.h */
 
FT_EXPORT_DEF( FT_ULong )
FT_Get_CMap_Language_ID( FT_CharMap charmap )
{
FT_Service_TTCMaps service;
FT_Face face;
TT_CMapInfo cmap_info;
 
 
if ( !charmap || !charmap->face )
return 0;
 
face = charmap->face;
FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
if ( service == NULL )
return 0;
if ( service->get_cmap_info( charmap, &cmap_info ))
return 0;
 
return cmap_info.language;
}
 
 
/* documentation is in tttables.h */
 
FT_EXPORT_DEF( FT_Long )
FT_Get_CMap_Format( FT_CharMap charmap )
{
FT_Service_TTCMaps service;
FT_Face face;
TT_CMapInfo cmap_info;
 
 
if ( !charmap || !charmap->face )
return -1;
 
face = charmap->face;
FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
if ( service == NULL )
return -1;
if ( service->get_cmap_info( charmap, &cmap_info ))
return -1;
 
return cmap_info.format;
}
 
 
/* documentation is in ftsizes.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Activate_Size( FT_Size size )
{
FT_Face face;
 
 
if ( size == NULL )
return FT_THROW( Invalid_Argument );
 
face = size->face;
if ( face == NULL || face->driver == NULL )
return FT_THROW( Invalid_Argument );
 
/* we don't need anything more complex than that; all size objects */
/* are already listed by the face */
face->size = size;
 
return FT_Err_Ok;
}
 
 
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** R E N D E R E R S ****/
/**** ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
 
/* lookup a renderer by glyph format in the library's list */
FT_BASE_DEF( FT_Renderer )
FT_Lookup_Renderer( FT_Library library,
FT_Glyph_Format format,
FT_ListNode* node )
{
FT_ListNode cur;
FT_Renderer result = 0;
 
 
if ( !library )
goto Exit;
 
cur = library->renderers.head;
 
if ( node )
{
if ( *node )
cur = (*node)->next;
*node = 0;
}
 
while ( cur )
{
FT_Renderer renderer = FT_RENDERER( cur->data );
 
 
if ( renderer->glyph_format == format )
{
if ( node )
*node = cur;
 
result = renderer;
break;
}
cur = cur->next;
}
 
Exit:
return result;
}
 
 
static FT_Renderer
ft_lookup_glyph_renderer( FT_GlyphSlot slot )
{
FT_Face face = slot->face;
FT_Library library = FT_FACE_LIBRARY( face );
FT_Renderer result = library->cur_renderer;
 
 
if ( !result || result->glyph_format != slot->format )
result = FT_Lookup_Renderer( library, slot->format, 0 );
 
return result;
}
 
 
static void
ft_set_current_renderer( FT_Library library )
{
FT_Renderer renderer;
 
 
renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 0 );
library->cur_renderer = renderer;
}
 
 
static FT_Error
ft_add_renderer( FT_Module module )
{
FT_Library library = module->library;
FT_Memory memory = library->memory;
FT_Error error;
FT_ListNode node = NULL;
 
 
if ( FT_NEW( node ) )
goto Exit;
 
{
FT_Renderer render = FT_RENDERER( module );
FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz;
 
 
render->clazz = clazz;
render->glyph_format = clazz->glyph_format;
 
/* allocate raster object if needed */
if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
clazz->raster_class->raster_new )
{
error = clazz->raster_class->raster_new( memory, &render->raster );
if ( error )
goto Fail;
 
render->raster_render = clazz->raster_class->raster_render;
render->render = clazz->render_glyph;
}
 
/* add to list */
node->data = module;
FT_List_Add( &library->renderers, node );
 
ft_set_current_renderer( library );
}
 
Fail:
if ( error )
FT_FREE( node );
 
Exit:
return error;
}
 
 
static void
ft_remove_renderer( FT_Module module )
{
FT_Library library = module->library;
FT_Memory memory = library->memory;
FT_ListNode node;
 
 
node = FT_List_Find( &library->renderers, module );
if ( node )
{
FT_Renderer render = FT_RENDERER( module );
 
 
/* release raster object, if any */
if ( render->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
render->raster )
render->clazz->raster_class->raster_done( render->raster );
 
/* remove from list */
FT_List_Remove( &library->renderers, node );
FT_FREE( node );
 
ft_set_current_renderer( library );
}
}
 
 
/* documentation is in ftrender.h */
 
FT_EXPORT_DEF( FT_Renderer )
FT_Get_Renderer( FT_Library library,
FT_Glyph_Format format )
{
/* test for valid `library' delayed to FT_Lookup_Renderer() */
 
return FT_Lookup_Renderer( library, format, 0 );
}
 
 
/* documentation is in ftrender.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Set_Renderer( FT_Library library,
FT_Renderer renderer,
FT_UInt num_params,
FT_Parameter* parameters )
{
FT_ListNode node;
FT_Error error = FT_Err_Ok;
 
 
if ( !library )
return FT_THROW( Invalid_Library_Handle );
 
if ( !renderer )
return FT_THROW( Invalid_Argument );
 
node = FT_List_Find( &library->renderers, renderer );
if ( !node )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
 
FT_List_Up( &library->renderers, node );
 
if ( renderer->glyph_format == FT_GLYPH_FORMAT_OUTLINE )
library->cur_renderer = renderer;
 
if ( num_params > 0 )
{
FT_Renderer_SetModeFunc set_mode = renderer->clazz->set_mode;
 
 
for ( ; num_params > 0; num_params-- )
{
error = set_mode( renderer, parameters->tag, parameters->data );
if ( error )
break;
parameters++;
}
}
 
Exit:
return error;
}
 
 
FT_BASE_DEF( FT_Error )
FT_Render_Glyph_Internal( FT_Library library,
FT_GlyphSlot slot,
FT_Render_Mode render_mode )
{
FT_Error error = FT_Err_Ok;
FT_Renderer renderer;
 
 
/* if it is already a bitmap, no need to do anything */
switch ( slot->format )
{
case FT_GLYPH_FORMAT_BITMAP: /* already a bitmap, don't do anything */
break;
 
default:
{
FT_ListNode node = 0;
FT_Bool update = 0;
 
 
/* small shortcut for the very common case */
if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
{
renderer = library->cur_renderer;
node = library->renderers.head;
}
else
renderer = FT_Lookup_Renderer( library, slot->format, &node );
 
error = FT_ERR( Unimplemented_Feature );
while ( renderer )
{
error = renderer->render( renderer, slot, render_mode, NULL );
if ( !error ||
FT_ERR_NEQ( error, Cannot_Render_Glyph ) )
break;
 
/* FT_Err_Cannot_Render_Glyph is returned if the render mode */
/* is unsupported by the current renderer for this glyph image */
/* format. */
 
/* now, look for another renderer that supports the same */
/* format. */
renderer = FT_Lookup_Renderer( library, slot->format, &node );
update = 1;
}
 
/* if we changed the current renderer for the glyph image format */
/* we need to select it as the next current one */
if ( !error && update && renderer )
FT_Set_Renderer( library, renderer, 0, 0 );
}
}
 
#ifdef FT_DEBUG_LEVEL_TRACE
 
#undef FT_COMPONENT
#define FT_COMPONENT trace_bitmap
 
/* we convert to a single bitmap format for computing the checksum */
{
FT_Bitmap bitmap;
FT_Error err;
 
 
FT_Bitmap_New( &bitmap );
 
err = FT_Bitmap_Convert( library, &slot->bitmap, &bitmap, 1 );
if ( !err )
{
MD5_CTX ctx;
unsigned char md5[16];
int i;
 
 
MD5_Init( &ctx);
MD5_Update( &ctx, bitmap.buffer, bitmap.rows * bitmap.pitch );
MD5_Final( md5, &ctx );
 
FT_TRACE3(( "MD5 checksum for %dx%d bitmap:\n"
" ",
bitmap.rows, bitmap.pitch ));
for ( i = 0; i < 16; i++ )
FT_TRACE3(( "%02X", md5[i] ));
FT_TRACE3(( "\n" ));
}
 
FT_Bitmap_Done( library, &bitmap );
}
 
#undef FT_COMPONENT
#define FT_COMPONENT trace_objs
 
#endif /* FT_DEBUG_LEVEL_TRACE */
 
return error;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Render_Glyph( FT_GlyphSlot slot,
FT_Render_Mode render_mode )
{
FT_Library library;
 
 
if ( !slot || !slot->face )
return FT_THROW( Invalid_Argument );
 
library = FT_FACE_LIBRARY( slot->face );
 
return FT_Render_Glyph_Internal( library, slot, render_mode );
}
 
 
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** M O D U L E S ****/
/**** ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
 
 
/*************************************************************************/
/* */
/* <Function> */
/* Destroy_Module */
/* */
/* <Description> */
/* Destroys a given module object. For drivers, this also destroys */
/* all child faces. */
/* */
/* <InOut> */
/* module :: A handle to the target driver object. */
/* */
/* <Note> */
/* The driver _must_ be LOCKED! */
/* */
static void
Destroy_Module( FT_Module module )
{
FT_Memory memory = module->memory;
FT_Module_Class* clazz = module->clazz;
FT_Library library = module->library;
 
 
if ( library && library->auto_hinter == module )
library->auto_hinter = 0;
 
/* if the module is a renderer */
if ( FT_MODULE_IS_RENDERER( module ) )
ft_remove_renderer( module );
 
/* if the module is a font driver, add some steps */
if ( FT_MODULE_IS_DRIVER( module ) )
Destroy_Driver( FT_DRIVER( module ) );
 
/* finalize the module object */
if ( clazz->module_done )
clazz->module_done( module );
 
/* discard it */
FT_FREE( module );
}
 
 
/* documentation is in ftmodapi.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Add_Module( FT_Library library,
const FT_Module_Class* clazz )
{
FT_Error error;
FT_Memory memory;
FT_Module module;
FT_UInt nn;
 
 
#define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
FREETYPE_MINOR )
 
if ( !library )
return FT_THROW( Invalid_Library_Handle );
 
if ( !clazz )
return FT_THROW( Invalid_Argument );
 
/* check freetype version */
if ( clazz->module_requires > FREETYPE_VER_FIXED )
return FT_THROW( Invalid_Version );
 
/* look for a module with the same name in the library's table */
for ( nn = 0; nn < library->num_modules; nn++ )
{
module = library->modules[nn];
if ( ft_strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
{
/* this installed module has the same name, compare their versions */
if ( clazz->module_version <= module->clazz->module_version )
return FT_THROW( Lower_Module_Version );
 
/* remove the module from our list, then exit the loop to replace */
/* it by our new version.. */
FT_Remove_Module( library, module );
break;
}
}
 
memory = library->memory;
error = FT_Err_Ok;
 
if ( library->num_modules >= FT_MAX_MODULES )
{
error = FT_THROW( Too_Many_Drivers );
goto Exit;
}
 
/* allocate module object */
if ( FT_ALLOC( module, clazz->module_size ) )
goto Exit;
 
/* base initialization */
module->library = library;
module->memory = memory;
module->clazz = (FT_Module_Class*)clazz;
 
/* check whether the module is a renderer - this must be performed */
/* before the normal module initialization */
if ( FT_MODULE_IS_RENDERER( module ) )
{
/* add to the renderers list */
error = ft_add_renderer( module );
if ( error )
goto Fail;
}
 
/* is the module a auto-hinter? */
if ( FT_MODULE_IS_HINTER( module ) )
library->auto_hinter = module;
 
/* if the module is a font driver */
if ( FT_MODULE_IS_DRIVER( module ) )
{
/* allocate glyph loader if needed */
FT_Driver driver = FT_DRIVER( module );
 
 
driver->clazz = (FT_Driver_Class)module->clazz;
if ( FT_DRIVER_USES_OUTLINES( driver ) )
{
error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
if ( error )
goto Fail;
}
}
 
if ( clazz->module_init )
{
error = clazz->module_init( module );
if ( error )
goto Fail;
}
 
/* add module to the library's table */
library->modules[library->num_modules++] = module;
 
Exit:
return error;
 
Fail:
if ( FT_MODULE_IS_DRIVER( module ) )
{
FT_Driver driver = FT_DRIVER( module );
 
 
if ( FT_DRIVER_USES_OUTLINES( driver ) )
FT_GlyphLoader_Done( driver->glyph_loader );
}
 
if ( FT_MODULE_IS_RENDERER( module ) )
{
FT_Renderer renderer = FT_RENDERER( module );
 
 
if ( renderer->clazz &&
renderer->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
renderer->raster )
renderer->clazz->raster_class->raster_done( renderer->raster );
}
 
FT_FREE( module );
goto Exit;
}
 
 
/* documentation is in ftmodapi.h */
 
FT_EXPORT_DEF( FT_Module )
FT_Get_Module( FT_Library library,
const char* module_name )
{
FT_Module result = 0;
FT_Module* cur;
FT_Module* limit;
 
 
if ( !library || !module_name )
return result;
 
cur = library->modules;
limit = cur + library->num_modules;
 
for ( ; cur < limit; cur++ )
if ( ft_strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
{
result = cur[0];
break;
}
 
return result;
}
 
 
/* documentation is in ftobjs.h */
 
FT_BASE_DEF( const void* )
FT_Get_Module_Interface( FT_Library library,
const char* mod_name )
{
FT_Module module;
 
 
/* test for valid `library' delayed to FT_Get_Module() */
 
module = FT_Get_Module( library, mod_name );
 
return module ? module->clazz->module_interface : 0;
}
 
 
FT_BASE_DEF( FT_Pointer )
ft_module_get_service( FT_Module module,
const char* service_id )
{
FT_Pointer result = NULL;
 
 
if ( module )
{
FT_ASSERT( module->clazz && module->clazz->get_interface );
 
/* first, look for the service in the module */
if ( module->clazz->get_interface )
result = module->clazz->get_interface( module, service_id );
 
if ( result == NULL )
{
/* we didn't find it, look in all other modules then */
FT_Library library = module->library;
FT_Module* cur = library->modules;
FT_Module* limit = cur + library->num_modules;
 
 
for ( ; cur < limit; cur++ )
{
if ( cur[0] != module )
{
FT_ASSERT( cur[0]->clazz );
 
if ( cur[0]->clazz->get_interface )
{
result = cur[0]->clazz->get_interface( cur[0], service_id );
if ( result != NULL )
break;
}
}
}
}
}
 
return result;
}
 
 
/* documentation is in ftmodapi.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Remove_Module( FT_Library library,
FT_Module module )
{
/* try to find the module from the table, then remove it from there */
 
if ( !library )
return FT_THROW( Invalid_Library_Handle );
 
if ( module )
{
FT_Module* cur = library->modules;
FT_Module* limit = cur + library->num_modules;
 
 
for ( ; cur < limit; cur++ )
{
if ( cur[0] == module )
{
/* remove it from the table */
library->num_modules--;
limit--;
while ( cur < limit )
{
cur[0] = cur[1];
cur++;
}
limit[0] = 0;
 
/* destroy the module */
Destroy_Module( module );
 
return FT_Err_Ok;
}
}
}
return FT_THROW( Invalid_Driver_Handle );
}
 
 
FT_Error
ft_property_do( FT_Library library,
const FT_String* module_name,
const FT_String* property_name,
void* value,
FT_Bool set )
{
FT_Module* cur;
FT_Module* limit;
FT_Module_Interface interface;
 
FT_Service_Properties service;
 
#ifdef FT_DEBUG_LEVEL_ERROR
const FT_String* set_name = "FT_Property_Set";
const FT_String* get_name = "FT_Property_Get";
const FT_String* func_name = set ? set_name : get_name;
#endif
 
FT_Bool missing_func;
 
 
if ( !library )
return FT_THROW( Invalid_Library_Handle );
 
if ( !module_name || !property_name || !value )
return FT_THROW( Invalid_Argument );
 
cur = library->modules;
limit = cur + library->num_modules;
 
/* search module */
for ( ; cur < limit; cur++ )
if ( !ft_strcmp( cur[0]->clazz->module_name, module_name ) )
break;
 
if ( cur == limit )
{
FT_ERROR(( "%s: can't find module `%s'\n",
func_name, module_name ));
return FT_THROW( Missing_Module );
}
 
/* check whether we have a service interface */
if ( !cur[0]->clazz->get_interface )
{
FT_ERROR(( "%s: module `%s' doesn't support properties\n",
func_name, module_name ));
return FT_THROW( Unimplemented_Feature );
}
 
/* search property service */
interface = cur[0]->clazz->get_interface( cur[0],
FT_SERVICE_ID_PROPERTIES );
if ( !interface )
{
FT_ERROR(( "%s: module `%s' doesn't support properties\n",
func_name, module_name ));
return FT_THROW( Unimplemented_Feature );
}
 
service = (FT_Service_Properties)interface;
 
if ( set )
missing_func = (FT_Bool)( !service->set_property );
else
missing_func = (FT_Bool)( !service->get_property );
 
if ( missing_func )
{
FT_ERROR(( "%s: property service of module `%s' is broken\n",
func_name, module_name ));
return FT_THROW( Unimplemented_Feature );
}
 
return set ? service->set_property( cur[0], property_name, value )
: service->get_property( cur[0], property_name, value );
}
 
 
/* documentation is in ftmodapi.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Property_Set( FT_Library library,
const FT_String* module_name,
const FT_String* property_name,
const void* value )
{
return ft_property_do( library,
module_name,
property_name,
(void*)value,
TRUE );
}
 
 
/* documentation is in ftmodapi.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Property_Get( FT_Library library,
const FT_String* module_name,
const FT_String* property_name,
void* value )
{
return ft_property_do( library,
module_name,
property_name,
value,
FALSE );
}
 
 
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** L I B R A R Y ****/
/**** ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
 
 
/* documentation is in ftmodapi.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Reference_Library( FT_Library library )
{
library->refcount++;
 
return FT_Err_Ok;
}
 
 
/* documentation is in ftmodapi.h */
 
FT_EXPORT_DEF( FT_Error )
FT_New_Library( FT_Memory memory,
FT_Library *alibrary )
{
FT_Library library = NULL;
FT_Error error;
 
 
if ( !memory )
return FT_THROW( Invalid_Argument );
 
#ifdef FT_DEBUG_LEVEL_ERROR
/* init debugging support */
ft_debug_init();
#endif
 
/* first of all, allocate the library object */
if ( FT_NEW( library ) )
return error;
 
library->memory = memory;
 
#ifdef FT_CONFIG_OPTION_PIC
/* initialize position independent code containers */
error = ft_pic_container_init( library );
if ( error )
goto Fail;
#endif
 
/* allocate the render pool */
library->raster_pool_size = FT_RENDER_POOL_SIZE;
#if FT_RENDER_POOL_SIZE > 0
if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
goto Fail;
#endif
 
library->version_major = FREETYPE_MAJOR;
library->version_minor = FREETYPE_MINOR;
library->version_patch = FREETYPE_PATCH;
 
library->refcount = 1;
 
/* That's ok now */
*alibrary = library;
 
return FT_Err_Ok;
 
Fail:
#ifdef FT_CONFIG_OPTION_PIC
ft_pic_container_destroy( library );
#endif
FT_FREE( library );
return error;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( void )
FT_Library_Version( FT_Library library,
FT_Int *amajor,
FT_Int *aminor,
FT_Int *apatch )
{
FT_Int major = 0;
FT_Int minor = 0;
FT_Int patch = 0;
 
 
if ( library )
{
major = library->version_major;
minor = library->version_minor;
patch = library->version_patch;
}
 
if ( amajor )
*amajor = major;
 
if ( aminor )
*aminor = minor;
 
if ( apatch )
*apatch = patch;
}
 
 
/* documentation is in ftmodapi.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Done_Library( FT_Library library )
{
FT_Memory memory;
 
 
if ( !library )
return FT_THROW( Invalid_Library_Handle );
 
library->refcount--;
if ( library->refcount > 0 )
goto Exit;
 
memory = library->memory;
 
/*
* Close all faces in the library. If we don't do this, we can have
* some subtle memory leaks.
*
* Example:
*
* - the cff font driver uses the pshinter module in cff_size_done
* - if the pshinter module is destroyed before the cff font driver,
* opened FT_Face objects managed by the driver are not properly
* destroyed, resulting in a memory leak
*
* Some faces are dependent on other faces, like Type42 faces that
* depend on TrueType faces synthesized internally.
*
* The order of drivers should be specified in driver_name[].
*/
{
FT_UInt m, n;
const char* driver_name[] = { "type42", NULL };
 
 
for ( m = 0;
m < sizeof ( driver_name ) / sizeof ( driver_name[0] );
m++ )
{
for ( n = 0; n < library->num_modules; n++ )
{
FT_Module module = library->modules[n];
const char* module_name = module->clazz->module_name;
FT_List faces;
 
 
if ( driver_name[m] &&
ft_strcmp( module_name, driver_name[m] ) != 0 )
continue;
 
if ( ( module->clazz->module_flags & FT_MODULE_FONT_DRIVER ) == 0 )
continue;
 
FT_TRACE7(( "FT_Done_Library: close faces for %s\n", module_name ));
 
faces = &FT_DRIVER( module )->faces_list;
while ( faces->head )
{
FT_Done_Face( FT_FACE( faces->head->data ) );
if ( faces->head )
FT_TRACE0(( "FT_Done_Library: failed to free some faces\n" ));
}
}
}
}
 
/* Close all other modules in the library */
#if 1
/* XXX Modules are removed in the reversed order so that */
/* type42 module is removed before truetype module. This */
/* avoids double free in some occasions. It is a hack. */
while ( library->num_modules > 0 )
FT_Remove_Module( library,
library->modules[library->num_modules - 1] );
#else
{
FT_UInt n;
 
 
for ( n = 0; n < library->num_modules; n++ )
{
FT_Module module = library->modules[n];
 
 
if ( module )
{
Destroy_Module( module );
library->modules[n] = 0;
}
}
}
#endif
 
/* Destroy raster objects */
FT_FREE( library->raster_pool );
library->raster_pool_size = 0;
 
#ifdef FT_CONFIG_OPTION_PIC
/* Destroy pic container contents */
ft_pic_container_destroy( library );
#endif
 
FT_FREE( library );
 
Exit:
return FT_Err_Ok;
}
 
 
/* documentation is in ftmodapi.h */
 
FT_EXPORT_DEF( void )
FT_Set_Debug_Hook( FT_Library library,
FT_UInt hook_index,
FT_DebugHook_Func debug_hook )
{
if ( library && debug_hook &&
hook_index <
( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
library->debug_hooks[hook_index] = debug_hook;
}
 
 
/* documentation is in ftmodapi.h */
 
FT_EXPORT_DEF( FT_TrueTypeEngineType )
FT_Get_TrueType_Engine_Type( FT_Library library )
{
FT_TrueTypeEngineType result = FT_TRUETYPE_ENGINE_TYPE_NONE;
 
 
if ( library )
{
FT_Module module = FT_Get_Module( library, "truetype" );
 
 
if ( module )
{
FT_Service_TrueTypeEngine service;
 
 
service = (FT_Service_TrueTypeEngine)
ft_module_get_service( module,
FT_SERVICE_ID_TRUETYPE_ENGINE );
if ( service )
result = service->engine_type;
}
}
 
return result;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Get_SubGlyph_Info( FT_GlyphSlot glyph,
FT_UInt sub_index,
FT_Int *p_index,
FT_UInt *p_flags,
FT_Int *p_arg1,
FT_Int *p_arg2,
FT_Matrix *p_transform )
{
FT_Error error = FT_ERR( Invalid_Argument );
 
 
if ( glyph &&
glyph->subglyphs &&
glyph->format == FT_GLYPH_FORMAT_COMPOSITE &&
sub_index < glyph->num_subglyphs )
{
FT_SubGlyph subg = glyph->subglyphs + sub_index;
 
 
*p_index = subg->index;
*p_flags = subg->flags;
*p_arg1 = subg->arg1;
*p_arg2 = subg->arg2;
*p_transform = subg->transform;
}
 
return error;
}
 
 
/* END */
/programs/develop/libraries/freetype/src/base/ftotval.c
0,0 → 1,91
/***************************************************************************/
/* */
/* ftotval.c */
/* */
/* FreeType API for validating OpenType tables (body). */
/* */
/* Copyright 2004, 2006, 2008, 2010, 2013 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_OBJECTS_H
#include FT_SERVICE_OPENTYPE_VALIDATE_H
#include FT_OPENTYPE_VALIDATE_H
 
 
/* documentation is in ftotval.h */
 
FT_EXPORT_DEF( FT_Error )
FT_OpenType_Validate( FT_Face face,
FT_UInt validation_flags,
FT_Bytes *BASE_table,
FT_Bytes *GDEF_table,
FT_Bytes *GPOS_table,
FT_Bytes *GSUB_table,
FT_Bytes *JSTF_table )
{
FT_Service_OTvalidate service;
FT_Error error;
 
 
if ( !face )
{
error = FT_THROW( Invalid_Face_Handle );
goto Exit;
}
 
if ( !( BASE_table &&
GDEF_table &&
GPOS_table &&
GSUB_table &&
JSTF_table ) )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
 
FT_FACE_FIND_GLOBAL_SERVICE( face, service, OPENTYPE_VALIDATE );
 
if ( service )
error = service->validate( face,
validation_flags,
BASE_table,
GDEF_table,
GPOS_table,
GSUB_table,
JSTF_table );
else
error = FT_THROW( Unimplemented_Feature );
 
Exit:
return error;
}
 
 
FT_EXPORT_DEF( void )
FT_OpenType_Free( FT_Face face,
FT_Bytes table )
{
FT_Memory memory;
 
 
if ( !face )
return;
 
memory = FT_FACE_MEMORY( face );
 
FT_FREE( table );
}
 
 
/* END */
/programs/develop/libraries/freetype/src/base/ftoutln.c
0,0 → 1,1081
/***************************************************************************/
/* */
/* ftoutln.c */
/* */
/* FreeType outline management (body). */
/* */
/* Copyright 1996-2008, 2010, 2012-2013 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. */
/* */
/***************************************************************************/
 
 
/*************************************************************************/
/* */
/* All functions are declared in freetype.h. */
/* */
/*************************************************************************/
 
 
#include <ft2build.h>
#include FT_OUTLINE_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_CALC_H
#include FT_INTERNAL_DEBUG_H
#include FT_TRIGONOMETRY_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_outline
 
 
static
const FT_Outline null_outline = { 0, 0, 0, 0, 0, 0 };
 
 
/* documentation is in ftoutln.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Outline_Decompose( FT_Outline* outline,
const FT_Outline_Funcs* func_interface,
void* user )
{
#undef SCALED
#define SCALED( x ) ( ( (x) << shift ) - delta )
 
FT_Vector v_last;
FT_Vector v_control;
FT_Vector v_start;
 
FT_Vector* point;
FT_Vector* limit;
char* tags;
 
FT_Error error;
 
FT_Int n; /* index of contour in outline */
FT_UInt first; /* index of first point in contour */
FT_Int tag; /* current point's state */
 
FT_Int shift;
FT_Pos delta;
 
 
if ( !outline || !func_interface )
return FT_THROW( Invalid_Argument );
 
shift = func_interface->shift;
delta = func_interface->delta;
first = 0;
 
for ( n = 0; n < outline->n_contours; n++ )
{
FT_Int last; /* index of last point in contour */
 
 
FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n ));
 
last = outline->contours[n];
if ( last < 0 )
goto Invalid_Outline;
limit = outline->points + last;
 
v_start = outline->points[first];
v_start.x = SCALED( v_start.x );
v_start.y = SCALED( v_start.y );
 
v_last = outline->points[last];
v_last.x = SCALED( v_last.x );
v_last.y = SCALED( v_last.y );
 
v_control = v_start;
 
point = outline->points + first;
tags = outline->tags + first;
tag = FT_CURVE_TAG( tags[0] );
 
/* A contour cannot start with a cubic control point! */
if ( tag == FT_CURVE_TAG_CUBIC )
goto Invalid_Outline;
 
/* check first point to determine origin */
if ( tag == FT_CURVE_TAG_CONIC )
{
/* first point is conic control. Yes, this happens. */
if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )
{
/* start at last point if it is on the curve */
v_start = v_last;
limit--;
}
else
{
/* if both first and last points are conic, */
/* start at their middle and record its position */
/* for closure */
v_start.x = ( v_start.x + v_last.x ) / 2;
v_start.y = ( v_start.y + v_last.y ) / 2;
 
v_last = v_start;
}
point--;
tags--;
}
 
FT_TRACE5(( " move to (%.2f, %.2f)\n",
v_start.x / 64.0, v_start.y / 64.0 ));
error = func_interface->move_to( &v_start, user );
if ( error )
goto Exit;
 
while ( point < limit )
{
point++;
tags++;
 
tag = FT_CURVE_TAG( tags[0] );
switch ( tag )
{
case FT_CURVE_TAG_ON: /* emit a single line_to */
{
FT_Vector vec;
 
 
vec.x = SCALED( point->x );
vec.y = SCALED( point->y );
 
FT_TRACE5(( " line to (%.2f, %.2f)\n",
vec.x / 64.0, vec.y / 64.0 ));
error = func_interface->line_to( &vec, user );
if ( error )
goto Exit;
continue;
}
 
case FT_CURVE_TAG_CONIC: /* consume conic arcs */
v_control.x = SCALED( point->x );
v_control.y = SCALED( point->y );
 
Do_Conic:
if ( point < limit )
{
FT_Vector vec;
FT_Vector v_middle;
 
 
point++;
tags++;
tag = FT_CURVE_TAG( tags[0] );
 
vec.x = SCALED( point->x );
vec.y = SCALED( point->y );
 
if ( tag == FT_CURVE_TAG_ON )
{
FT_TRACE5(( " conic to (%.2f, %.2f)"
" with control (%.2f, %.2f)\n",
vec.x / 64.0, vec.y / 64.0,
v_control.x / 64.0, v_control.y / 64.0 ));
error = func_interface->conic_to( &v_control, &vec, user );
if ( error )
goto Exit;
continue;
}
 
if ( tag != FT_CURVE_TAG_CONIC )
goto Invalid_Outline;
 
v_middle.x = ( v_control.x + vec.x ) / 2;
v_middle.y = ( v_control.y + vec.y ) / 2;
 
FT_TRACE5(( " conic to (%.2f, %.2f)"
" with control (%.2f, %.2f)\n",
v_middle.x / 64.0, v_middle.y / 64.0,
v_control.x / 64.0, v_control.y / 64.0 ));
error = func_interface->conic_to( &v_control, &v_middle, user );
if ( error )
goto Exit;
 
v_control = vec;
goto Do_Conic;
}
 
FT_TRACE5(( " conic to (%.2f, %.2f)"
" with control (%.2f, %.2f)\n",
v_start.x / 64.0, v_start.y / 64.0,
v_control.x / 64.0, v_control.y / 64.0 ));
error = func_interface->conic_to( &v_control, &v_start, user );
goto Close;
 
default: /* FT_CURVE_TAG_CUBIC */
{
FT_Vector vec1, vec2;
 
 
if ( point + 1 > limit ||
FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
goto Invalid_Outline;
 
point += 2;
tags += 2;
 
vec1.x = SCALED( point[-2].x );
vec1.y = SCALED( point[-2].y );
 
vec2.x = SCALED( point[-1].x );
vec2.y = SCALED( point[-1].y );
 
if ( point <= limit )
{
FT_Vector vec;
 
 
vec.x = SCALED( point->x );
vec.y = SCALED( point->y );
 
FT_TRACE5(( " cubic to (%.2f, %.2f)"
" with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
vec.x / 64.0, vec.y / 64.0,
vec1.x / 64.0, vec1.y / 64.0,
vec2.x / 64.0, vec2.y / 64.0 ));
error = func_interface->cubic_to( &vec1, &vec2, &vec, user );
if ( error )
goto Exit;
continue;
}
 
FT_TRACE5(( " cubic to (%.2f, %.2f)"
" with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
v_start.x / 64.0, v_start.y / 64.0,
vec1.x / 64.0, vec1.y / 64.0,
vec2.x / 64.0, vec2.y / 64.0 ));
error = func_interface->cubic_to( &vec1, &vec2, &v_start, user );
goto Close;
}
}
}
 
/* close the contour with a line segment */
FT_TRACE5(( " line to (%.2f, %.2f)\n",
v_start.x / 64.0, v_start.y / 64.0 ));
error = func_interface->line_to( &v_start, user );
 
Close:
if ( error )
goto Exit;
 
first = last + 1;
}
 
FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));
return FT_Err_Ok;
 
Exit:
FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error ));
return error;
 
Invalid_Outline:
return FT_THROW( Invalid_Outline );
}
 
 
FT_EXPORT_DEF( FT_Error )
FT_Outline_New_Internal( FT_Memory memory,
FT_UInt numPoints,
FT_Int numContours,
FT_Outline *anoutline )
{
FT_Error error;
 
 
if ( !anoutline || !memory )
return FT_THROW( Invalid_Argument );
 
*anoutline = null_outline;
 
if ( numContours < 0 ||
(FT_UInt)numContours > numPoints )
return FT_THROW( Invalid_Argument );
 
if ( numPoints > FT_OUTLINE_POINTS_MAX )
return FT_THROW( Array_Too_Large );
 
if ( FT_NEW_ARRAY( anoutline->points, numPoints ) ||
FT_NEW_ARRAY( anoutline->tags, numPoints ) ||
FT_NEW_ARRAY( anoutline->contours, numContours ) )
goto Fail;
 
anoutline->n_points = (FT_UShort)numPoints;
anoutline->n_contours = (FT_Short)numContours;
anoutline->flags |= FT_OUTLINE_OWNER;
 
return FT_Err_Ok;
 
Fail:
anoutline->flags |= FT_OUTLINE_OWNER;
FT_Outline_Done_Internal( memory, anoutline );
 
return error;
}
 
 
/* documentation is in ftoutln.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Outline_New( FT_Library library,
FT_UInt numPoints,
FT_Int numContours,
FT_Outline *anoutline )
{
if ( !library )
return FT_THROW( Invalid_Library_Handle );
 
return FT_Outline_New_Internal( library->memory, numPoints,
numContours, anoutline );
}
 
 
/* documentation is in ftoutln.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Outline_Check( FT_Outline* outline )
{
if ( outline )
{
FT_Int n_points = outline->n_points;
FT_Int n_contours = outline->n_contours;
FT_Int end0, end;
FT_Int n;
 
 
/* empty glyph? */
if ( n_points == 0 && n_contours == 0 )
return 0;
 
/* check point and contour counts */
if ( n_points <= 0 || n_contours <= 0 )
goto Bad;
 
end0 = end = -1;
for ( n = 0; n < n_contours; n++ )
{
end = outline->contours[n];
 
/* note that we don't accept empty contours */
if ( end <= end0 || end >= n_points )
goto Bad;
 
end0 = end;
}
 
if ( end != n_points - 1 )
goto Bad;
 
/* XXX: check the tags array */
return 0;
}
 
Bad:
return FT_THROW( Invalid_Argument );
}
 
 
/* documentation is in ftoutln.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Outline_Copy( const FT_Outline* source,
FT_Outline *target )
{
FT_Int is_owner;
 
 
if ( !source || !target ||
source->n_points != target->n_points ||
source->n_contours != target->n_contours )
return FT_THROW( Invalid_Argument );
 
if ( source == target )
return FT_Err_Ok;
 
FT_ARRAY_COPY( target->points, source->points, source->n_points );
 
FT_ARRAY_COPY( target->tags, source->tags, source->n_points );
 
FT_ARRAY_COPY( target->contours, source->contours, source->n_contours );
 
/* copy all flags, except the `FT_OUTLINE_OWNER' one */
is_owner = target->flags & FT_OUTLINE_OWNER;
target->flags = source->flags;
 
target->flags &= ~FT_OUTLINE_OWNER;
target->flags |= is_owner;
 
return FT_Err_Ok;
}
 
 
FT_EXPORT_DEF( FT_Error )
FT_Outline_Done_Internal( FT_Memory memory,
FT_Outline* outline )
{
if ( memory && outline )
{
if ( outline->flags & FT_OUTLINE_OWNER )
{
FT_FREE( outline->points );
FT_FREE( outline->tags );
FT_FREE( outline->contours );
}
*outline = null_outline;
 
return FT_Err_Ok;
}
else
return FT_THROW( Invalid_Argument );
}
 
 
/* documentation is in ftoutln.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Outline_Done( FT_Library library,
FT_Outline* outline )
{
/* check for valid `outline' in FT_Outline_Done_Internal() */
 
if ( !library )
return FT_THROW( Invalid_Library_Handle );
 
return FT_Outline_Done_Internal( library->memory, outline );
}
 
 
/* documentation is in ftoutln.h */
 
FT_EXPORT_DEF( void )
FT_Outline_Get_CBox( const FT_Outline* outline,
FT_BBox *acbox )
{
FT_Pos xMin, yMin, xMax, yMax;
 
 
if ( outline && acbox )
{
if ( outline->n_points == 0 )
{
xMin = 0;
yMin = 0;
xMax = 0;
yMax = 0;
}
else
{
FT_Vector* vec = outline->points;
FT_Vector* limit = vec + outline->n_points;
 
 
xMin = xMax = vec->x;
yMin = yMax = vec->y;
vec++;
 
for ( ; vec < limit; vec++ )
{
FT_Pos x, y;
 
 
x = vec->x;
if ( x < xMin ) xMin = x;
if ( x > xMax ) xMax = x;
 
y = vec->y;
if ( y < yMin ) yMin = y;
if ( y > yMax ) yMax = y;
}
}
acbox->xMin = xMin;
acbox->xMax = xMax;
acbox->yMin = yMin;
acbox->yMax = yMax;
}
}
 
 
/* documentation is in ftoutln.h */
 
FT_EXPORT_DEF( void )
FT_Outline_Translate( const FT_Outline* outline,
FT_Pos xOffset,
FT_Pos yOffset )
{
FT_UShort n;
FT_Vector* vec;
 
 
if ( !outline )
return;
 
vec = outline->points;
 
for ( n = 0; n < outline->n_points; n++ )
{
vec->x += xOffset;
vec->y += yOffset;
vec++;
}
}
 
 
/* documentation is in ftoutln.h */
 
FT_EXPORT_DEF( void )
FT_Outline_Reverse( FT_Outline* outline )
{
FT_UShort n;
FT_Int first, last;
 
 
if ( !outline )
return;
 
first = 0;
 
for ( n = 0; n < outline->n_contours; n++ )
{
last = outline->contours[n];
 
/* reverse point table */
{
FT_Vector* p = outline->points + first;
FT_Vector* q = outline->points + last;
FT_Vector swap;
 
 
while ( p < q )
{
swap = *p;
*p = *q;
*q = swap;
p++;
q--;
}
}
 
/* reverse tags table */
{
char* p = outline->tags + first;
char* q = outline->tags + last;
char swap;
 
 
while ( p < q )
{
swap = *p;
*p = *q;
*q = swap;
p++;
q--;
}
}
 
first = last + 1;
}
 
outline->flags ^= FT_OUTLINE_REVERSE_FILL;
}
 
 
/* documentation is in ftoutln.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Outline_Render( FT_Library library,
FT_Outline* outline,
FT_Raster_Params* params )
{
FT_Error error;
FT_Bool update = FALSE;
FT_Renderer renderer;
FT_ListNode node;
 
 
if ( !library )
return FT_THROW( Invalid_Library_Handle );
 
if ( !outline || !params )
return FT_THROW( Invalid_Argument );
 
renderer = library->cur_renderer;
node = library->renderers.head;
 
params->source = (void*)outline;
 
error = FT_ERR( Cannot_Render_Glyph );
while ( renderer )
{
error = renderer->raster_render( renderer->raster, params );
if ( !error || FT_ERR_NEQ( error, Cannot_Render_Glyph ) )
break;
 
/* FT_Err_Cannot_Render_Glyph is returned if the render mode */
/* is unsupported by the current renderer for this glyph image */
/* format */
 
/* now, look for another renderer that supports the same */
/* format */
renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE,
&node );
update = TRUE;
}
 
/* if we changed the current renderer for the glyph image format */
/* we need to select it as the next current one */
if ( !error && update && renderer )
FT_Set_Renderer( library, renderer, 0, 0 );
 
return error;
}
 
 
/* documentation is in ftoutln.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Outline_Get_Bitmap( FT_Library library,
FT_Outline* outline,
const FT_Bitmap *abitmap )
{
FT_Raster_Params params;
 
 
if ( !abitmap )
return FT_THROW( Invalid_Argument );
 
/* other checks are delayed to FT_Outline_Render() */
 
params.target = abitmap;
params.flags = 0;
 
if ( abitmap->pixel_mode == FT_PIXEL_MODE_GRAY ||
abitmap->pixel_mode == FT_PIXEL_MODE_LCD ||
abitmap->pixel_mode == FT_PIXEL_MODE_LCD_V )
params.flags |= FT_RASTER_FLAG_AA;
 
return FT_Outline_Render( library, outline, &params );
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( void )
FT_Vector_Transform( FT_Vector* vector,
const FT_Matrix* matrix )
{
FT_Pos xz, yz;
 
 
if ( !vector || !matrix )
return;
 
xz = FT_MulFix( vector->x, matrix->xx ) +
FT_MulFix( vector->y, matrix->xy );
 
yz = FT_MulFix( vector->x, matrix->yx ) +
FT_MulFix( vector->y, matrix->yy );
 
vector->x = xz;
vector->y = yz;
}
 
 
/* documentation is in ftoutln.h */
 
FT_EXPORT_DEF( void )
FT_Outline_Transform( const FT_Outline* outline,
const FT_Matrix* matrix )
{
FT_Vector* vec;
FT_Vector* limit;
 
 
if ( !outline || !matrix )
return;
 
vec = outline->points;
limit = vec + outline->n_points;
 
for ( ; vec < limit; vec++ )
FT_Vector_Transform( vec, matrix );
}
 
 
#if 0
 
#define FT_OUTLINE_GET_CONTOUR( outline, c, first, last ) \
do { \
(first) = ( c > 0 ) ? (outline)->points + \
(outline)->contours[c - 1] + 1 \
: (outline)->points; \
(last) = (outline)->points + (outline)->contours[c]; \
} while ( 0 )
 
 
/* Is a point in some contour? */
/* */
/* We treat every point of the contour as if it */
/* it were ON. That is, we allow false positives, */
/* but disallow false negatives. (XXX really?) */
static FT_Bool
ft_contour_has( FT_Outline* outline,
FT_Short c,
FT_Vector* point )
{
FT_Vector* first;
FT_Vector* last;
FT_Vector* a;
FT_Vector* b;
FT_UInt n = 0;
 
 
FT_OUTLINE_GET_CONTOUR( outline, c, first, last );
 
for ( a = first; a <= last; a++ )
{
FT_Pos x;
FT_Int intersect;
 
 
b = ( a == last ) ? first : a + 1;
 
intersect = ( a->y - point->y ) ^ ( b->y - point->y );
 
/* a and b are on the same side */
if ( intersect >= 0 )
{
if ( intersect == 0 && a->y == point->y )
{
if ( ( a->x <= point->x && b->x >= point->x ) ||
( a->x >= point->x && b->x <= point->x ) )
return 1;
}
 
continue;
}
 
x = a->x + ( b->x - a->x ) * (point->y - a->y ) / ( b->y - a->y );
 
if ( x < point->x )
n++;
else if ( x == point->x )
return 1;
}
 
return n & 1;
}
 
 
static FT_Bool
ft_contour_enclosed( FT_Outline* outline,
FT_UShort c )
{
FT_Vector* first;
FT_Vector* last;
FT_Short i;
 
 
FT_OUTLINE_GET_CONTOUR( outline, c, first, last );
 
for ( i = 0; i < outline->n_contours; i++ )
{
if ( i != c && ft_contour_has( outline, i, first ) )
{
FT_Vector* pt;
 
 
for ( pt = first + 1; pt <= last; pt++ )
if ( !ft_contour_has( outline, i, pt ) )
return 0;
 
return 1;
}
}
 
return 0;
}
 
 
/* This version differs from the public one in that each */
/* part (contour not enclosed in another contour) of the */
/* outline is checked for orientation. This is */
/* necessary for some buggy CJK fonts. */
static FT_Orientation
ft_outline_get_orientation( FT_Outline* outline )
{
FT_Short i;
FT_Vector* first;
FT_Vector* last;
FT_Orientation orient = FT_ORIENTATION_NONE;
 
 
first = outline->points;
for ( i = 0; i < outline->n_contours; i++, first = last + 1 )
{
FT_Vector* point;
FT_Vector* xmin_point;
FT_Pos xmin;
 
 
last = outline->points + outline->contours[i];
 
/* skip degenerate contours */
if ( last < first + 2 )
continue;
 
if ( ft_contour_enclosed( outline, i ) )
continue;
 
xmin = first->x;
xmin_point = first;
 
for ( point = first + 1; point <= last; point++ )
{
if ( point->x < xmin )
{
xmin = point->x;
xmin_point = point;
}
}
 
/* check the orientation of the contour */
{
FT_Vector* prev;
FT_Vector* next;
FT_Orientation o;
 
 
prev = ( xmin_point == first ) ? last : xmin_point - 1;
next = ( xmin_point == last ) ? first : xmin_point + 1;
 
if ( FT_Atan2( prev->x - xmin_point->x, prev->y - xmin_point->y ) >
FT_Atan2( next->x - xmin_point->x, next->y - xmin_point->y ) )
o = FT_ORIENTATION_POSTSCRIPT;
else
o = FT_ORIENTATION_TRUETYPE;
 
if ( orient == FT_ORIENTATION_NONE )
orient = o;
else if ( orient != o )
return FT_ORIENTATION_NONE;
}
}
 
return orient;
}
 
#endif /* 0 */
 
 
/* documentation is in ftoutln.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Outline_Embolden( FT_Outline* outline,
FT_Pos strength )
{
return FT_Outline_EmboldenXY( outline, strength, strength );
}
 
 
/* documentation is in ftoutln.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Outline_EmboldenXY( FT_Outline* outline,
FT_Pos xstrength,
FT_Pos ystrength )
{
FT_Vector* points;
FT_Vector v_prev, v_first, v_next, v_cur;
FT_Int c, n, first;
FT_Int orientation;
 
 
if ( !outline )
return FT_THROW( Invalid_Argument );
 
xstrength /= 2;
ystrength /= 2;
if ( xstrength == 0 && ystrength == 0 )
return FT_Err_Ok;
 
orientation = FT_Outline_Get_Orientation( outline );
if ( orientation == FT_ORIENTATION_NONE )
{
if ( outline->n_contours )
return FT_THROW( Invalid_Argument );
else
return FT_Err_Ok;
}
 
points = outline->points;
 
first = 0;
for ( c = 0; c < outline->n_contours; c++ )
{
FT_Vector in, out, shift;
FT_Fixed l_in, l_out, l, q, d;
int last = outline->contours[c];
 
 
v_first = points[first];
v_prev = points[last];
v_cur = v_first;
 
/* compute incoming normalized vector */
in.x = v_cur.x - v_prev.x;
in.y = v_cur.y - v_prev.y;
l_in = FT_Vector_Length( &in );
if ( l_in )
{
in.x = FT_DivFix( in.x, l_in );
in.y = FT_DivFix( in.y, l_in );
}
 
for ( n = first; n <= last; n++ )
{
if ( n < last )
v_next = points[n + 1];
else
v_next = v_first;
 
/* compute outgoing normalized vector */
out.x = v_next.x - v_cur.x;
out.y = v_next.y - v_cur.y;
l_out = FT_Vector_Length( &out );
if ( l_out )
{
out.x = FT_DivFix( out.x, l_out );
out.y = FT_DivFix( out.y, l_out );
}
 
d = FT_MulFix( in.x, out.x ) + FT_MulFix( in.y, out.y );
 
/* shift only if turn is less than ~160 degrees */
if ( d > -0xF000L )
{
d = d + 0x10000L;
 
/* shift components are aligned along lateral bisector */
/* and directed according to the outline orientation. */
shift.x = in.y + out.y;
shift.y = in.x + out.x;
 
if ( orientation == FT_ORIENTATION_TRUETYPE )
shift.x = -shift.x;
else
shift.y = -shift.y;
 
/* restrict shift magnitude to better handle collapsing segments */
q = FT_MulFix( out.x, in.y ) - FT_MulFix( out.y, in.x );
if ( orientation == FT_ORIENTATION_TRUETYPE )
q = -q;
 
l = FT_MIN( l_in, l_out );
 
/* non-strict inequalities avoid divide-by-zero when q == l == 0 */
if ( FT_MulFix( xstrength, q ) <= FT_MulFix( d, l ) )
shift.x = FT_MulDiv( shift.x, xstrength, d );
else
shift.x = FT_MulDiv( shift.x, l, q );
 
 
if ( FT_MulFix( ystrength, q ) <= FT_MulFix( d, l ) )
shift.y = FT_MulDiv( shift.y, ystrength, d );
else
shift.y = FT_MulDiv( shift.y, l, q );
}
else
shift.x = shift.y = 0;
 
outline->points[n].x = v_cur.x + xstrength + shift.x;
outline->points[n].y = v_cur.y + ystrength + shift.y;
 
in = out;
l_in = l_out;
v_cur = v_next;
}
 
first = last + 1;
}
 
return FT_Err_Ok;
}
 
 
/* documentation is in ftoutln.h */
 
FT_EXPORT_DEF( FT_Orientation )
FT_Outline_Get_Orientation( FT_Outline* outline )
{
FT_BBox cbox;
FT_Int xshift, yshift;
FT_Vector* points;
FT_Vector v_prev, v_cur;
FT_Int c, n, first;
FT_Pos area = 0;
 
 
if ( !outline || outline->n_points <= 0 )
return FT_ORIENTATION_TRUETYPE;
 
/* We use the nonzero winding rule to find the orientation. */
/* Since glyph outlines behave much more `regular' than arbitrary */
/* cubic or quadratic curves, this test deals with the polygon */
/* only which is spanned up by the control points. */
 
FT_Outline_Get_CBox( outline, &cbox );
 
xshift = FT_MSB( FT_ABS( cbox.xMax ) | FT_ABS( cbox.xMin ) ) - 14;
xshift = FT_MAX( xshift, 0 );
 
yshift = FT_MSB( cbox.yMax - cbox.yMin ) - 14;
yshift = FT_MAX( yshift, 0 );
 
points = outline->points;
 
first = 0;
for ( c = 0; c < outline->n_contours; c++ )
{
FT_Int last = outline->contours[c];
 
 
v_prev = points[last];
 
for ( n = first; n <= last; n++ )
{
v_cur = points[n];
area += ( ( v_cur.y - v_prev.y ) >> yshift ) *
( ( v_cur.x + v_prev.x ) >> xshift );
v_prev = v_cur;
}
 
first = last + 1;
}
 
if ( area > 0 )
return FT_ORIENTATION_POSTSCRIPT;
else if ( area < 0 )
return FT_ORIENTATION_TRUETYPE;
else
return FT_ORIENTATION_NONE;
}
 
 
/* END */
/programs/develop/libraries/freetype/src/base/ftpatent.c
0,0 → 1,286
/***************************************************************************/
/* */
/* ftpatent.c */
/* */
/* FreeType API for checking patented TrueType bytecode instructions */
/* (body). */
/* */
/* Copyright 2007, 2008, 2010 by David Turner. */
/* */
/* 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_TRUETYPE_TAGS_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_STREAM_H
#include FT_SERVICE_SFNT_H
#include FT_SERVICE_TRUETYPE_GLYF_H
 
 
static FT_Bool
_tt_check_patents_in_range( FT_Stream stream,
FT_ULong size )
{
FT_Bool result = FALSE;
FT_Error error;
FT_Bytes p, end;
 
 
if ( FT_FRAME_ENTER( size ) )
return 0;
 
p = stream->cursor;
end = p + size;
 
while ( p < end )
{
switch (p[0])
{
case 0x06: /* SPvTL // */
case 0x07: /* SPvTL + */
case 0x08: /* SFvTL // */
case 0x09: /* SFvTL + */
case 0x0A: /* SPvFS */
case 0x0B: /* SFvFS */
result = TRUE;
goto Exit;
 
case 0x40:
if ( p + 1 >= end )
goto Exit;
 
p += p[1] + 2;
break;
 
case 0x41:
if ( p + 1 >= end )
goto Exit;
 
p += p[1] * 2 + 2;
break;
 
case 0x71: /* DELTAP2 */
case 0x72: /* DELTAP3 */
case 0x73: /* DELTAC0 */
case 0x74: /* DELTAC1 */
case 0x75: /* DELTAC2 */
result = TRUE;
goto Exit;
 
case 0xB0:
case 0xB1:
case 0xB2:
case 0xB3:
case 0xB4:
case 0xB5:
case 0xB6:
case 0xB7:
p += ( p[0] - 0xB0 ) + 2;
break;
 
case 0xB8:
case 0xB9:
case 0xBA:
case 0xBB:
case 0xBC:
case 0xBD:
case 0xBE:
case 0xBF:
p += ( p[0] - 0xB8 ) * 2 + 3;
break;
 
default:
p += 1;
break;
}
}
 
Exit:
FT_UNUSED( error );
FT_FRAME_EXIT();
return result;
}
 
 
static FT_Bool
_tt_check_patents_in_table( FT_Face face,
FT_ULong tag )
{
FT_Stream stream = face->stream;
FT_Error error = FT_Err_Ok;
FT_Service_SFNT_Table service;
FT_Bool result = FALSE;
 
 
FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
 
if ( service )
{
FT_UInt i = 0;
FT_ULong tag_i = 0, offset_i = 0, length_i = 0;
 
 
for ( i = 0; !error && tag_i != tag ; i++ )
error = service->table_info( face, i,
&tag_i, &offset_i, &length_i );
 
if ( error ||
FT_STREAM_SEEK( offset_i ) )
goto Exit;
 
result = _tt_check_patents_in_range( stream, length_i );
}
 
Exit:
return result;
}
 
 
static FT_Bool
_tt_face_check_patents( FT_Face face )
{
FT_Stream stream = face->stream;
FT_UInt gindex;
FT_Error error;
FT_Bool result;
 
FT_Service_TTGlyf service;
 
 
result = _tt_check_patents_in_table( face, TTAG_fpgm );
if ( result )
goto Exit;
 
result = _tt_check_patents_in_table( face, TTAG_prep );
if ( result )
goto Exit;
 
FT_FACE_FIND_SERVICE( face, service, TT_GLYF );
if ( service == NULL )
goto Exit;
 
for ( gindex = 0; gindex < (FT_UInt)face->num_glyphs; gindex++ )
{
FT_ULong offset, num_ins, size;
FT_Int num_contours;
 
 
offset = service->get_location( face, gindex, &size );
if ( size == 0 )
continue;
 
if ( FT_STREAM_SEEK( offset ) ||
FT_READ_SHORT( num_contours ) )
continue;
 
if ( num_contours >= 0 ) /* simple glyph */
{
if ( FT_STREAM_SKIP( 8 + num_contours * 2 ) )
continue;
}
else /* compound glyph */
{
FT_Bool has_instr = 0;
 
 
if ( FT_STREAM_SKIP( 8 ) )
continue;
 
/* now read each component */
for (;;)
{
FT_UInt flags, toskip;
 
 
if( FT_READ_USHORT( flags ) )
break;
 
toskip = 2 + 1 + 1;
 
if ( ( flags & ( 1 << 0 ) ) != 0 ) /* ARGS_ARE_WORDS */
toskip += 2;
 
if ( ( flags & ( 1 << 3 ) ) != 0 ) /* WE_HAVE_A_SCALE */
toskip += 2;
else if ( ( flags & ( 1 << 6 ) ) != 0 ) /* WE_HAVE_X_Y_SCALE */
toskip += 4;
else if ( ( flags & ( 1 << 7 ) ) != 0 ) /* WE_HAVE_A_2x2 */
toskip += 8;
 
if ( ( flags & ( 1 << 8 ) ) != 0 ) /* WE_HAVE_INSTRUCTIONS */
has_instr = 1;
 
if ( FT_STREAM_SKIP( toskip ) )
goto NextGlyph;
 
if ( ( flags & ( 1 << 5 ) ) == 0 ) /* MORE_COMPONENTS */
break;
}
 
if ( !has_instr )
goto NextGlyph;
}
 
if ( FT_READ_USHORT( num_ins ) )
continue;
 
result = _tt_check_patents_in_range( stream, num_ins );
if ( result )
goto Exit;
 
NextGlyph:
;
}
 
Exit:
return result;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Bool )
FT_Face_CheckTrueTypePatents( FT_Face face )
{
FT_Bool result = FALSE;
 
 
if ( face && FT_IS_SFNT( face ) )
result = _tt_face_check_patents( face );
 
return result;
}
 
 
/* documentation is in freetype.h */
 
FT_EXPORT_DEF( FT_Bool )
FT_Face_SetUnpatentedHinting( FT_Face face,
FT_Bool value )
{
FT_Bool result = FALSE;
 
 
#if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \
!defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER )
if ( face && FT_IS_SFNT( face ) )
{
result = !face->internal->ignore_unpatented_hinter;
face->internal->ignore_unpatented_hinter = !value;
}
#else
FT_UNUSED( face );
FT_UNUSED( value );
#endif
 
return result;
}
 
/* END */
/programs/develop/libraries/freetype/src/base/ftpfr.c
0,0 → 1,146
/***************************************************************************/
/* */
/* ftpfr.c */
/* */
/* FreeType API for accessing PFR-specific data (body). */
/* */
/* Copyright 2002-2004, 2008, 2010, 2013 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_OBJECTS_H
#include FT_SERVICE_PFR_H
 
 
/* check the format */
static FT_Service_PfrMetrics
ft_pfr_check( FT_Face face )
{
FT_Service_PfrMetrics service = NULL;
 
 
if ( face )
FT_FACE_LOOKUP_SERVICE( face, service, PFR_METRICS );
 
return service;
}
 
 
/* documentation is in ftpfr.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Get_PFR_Metrics( FT_Face face,
FT_UInt *aoutline_resolution,
FT_UInt *ametrics_resolution,
FT_Fixed *ametrics_x_scale,
FT_Fixed *ametrics_y_scale )
{
FT_Error error = FT_Err_Ok;
FT_Service_PfrMetrics service;
 
 
if ( !face )
return FT_THROW( Invalid_Argument );
 
service = ft_pfr_check( face );
if ( service )
{
error = service->get_metrics( face,
aoutline_resolution,
ametrics_resolution,
ametrics_x_scale,
ametrics_y_scale );
}
else
{
FT_Fixed x_scale, y_scale;
 
 
/* this is not a PFR font */
if ( aoutline_resolution )
*aoutline_resolution = face->units_per_EM;
 
if ( ametrics_resolution )
*ametrics_resolution = face->units_per_EM;
 
x_scale = y_scale = 0x10000L;
if ( face->size )
{
x_scale = face->size->metrics.x_scale;
y_scale = face->size->metrics.y_scale;
}
 
if ( ametrics_x_scale )
*ametrics_x_scale = x_scale;
 
if ( ametrics_y_scale )
*ametrics_y_scale = y_scale;
 
error = FT_THROW( Unknown_File_Format );
}
 
return error;
}
 
 
/* documentation is in ftpfr.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Get_PFR_Kerning( FT_Face face,
FT_UInt left,
FT_UInt right,
FT_Vector *avector )
{
FT_Error error;
FT_Service_PfrMetrics service;
 
 
if ( !face )
return FT_THROW( Invalid_Argument );
 
service = ft_pfr_check( face );
if ( service )
error = service->get_kerning( face, left, right, avector );
else
error = FT_Get_Kerning( face, left, right,
FT_KERNING_UNSCALED, avector );
 
return error;
}
 
 
/* documentation is in ftpfr.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Get_PFR_Advance( FT_Face face,
FT_UInt gindex,
FT_Pos *aadvance )
{
FT_Error error;
FT_Service_PfrMetrics service;
 
 
service = ft_pfr_check( face );
if ( service )
{
error = service->get_advance( face, gindex, aadvance );
}
else
/* XXX: TODO: PROVIDE ADVANCE-LOADING METHOD TO ALL FONT DRIVERS */
error = FT_THROW( Invalid_Argument );
 
return error;
}
 
 
/* END */
/programs/develop/libraries/freetype/src/base/ftpic.c
0,0 → 1,55
/***************************************************************************/
/* */
/* 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 */
/programs/develop/libraries/freetype/src/base/ftrfork.c
0,0 → 1,849
/***************************************************************************/
/* */
/* ftrfork.c */
/* */
/* Embedded resource forks accessor (body). */
/* */
/* Copyright 2004-2010, 2013 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
#include "basepic.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_THROW( 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_THROW( 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_THROW( 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 = NULL;
FT_RFork_Ref *ref = NULL;
 
 
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_THROW( 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. ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
 
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 );
 
 
CONST_FT_RFORK_RULE_ARRAY_BEGIN(ft_raccess_guess_table,
ft_raccess_guess_rec)
CONST_FT_RFORK_RULE_ARRAY_ENTRY(apple_double, apple_double)
CONST_FT_RFORK_RULE_ARRAY_ENTRY(apple_single, apple_single)
CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_ufs_export, darwin_ufs_export)
CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_newvfs, darwin_newvfs)
CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_hfsplus, darwin_hfsplus)
CONST_FT_RFORK_RULE_ARRAY_ENTRY(vfat, vfat)
CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_cap, linux_cap)
CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_double, linux_double)
CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_netatalk, linux_netatalk)
CONST_FT_RFORK_RULE_ARRAY_END
 
 
/*************************************************************************/
/**** ****/
/**** 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 );
 
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_Int 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] = (FT_RACCESS_GUESS_TABLE_GET[i].func)( library,
stream, base_name,
&(new_names[i]),
&(offsets[i]) );
}
 
return;
}
 
 
#ifndef FT_MACINTOSH
static FT_RFork_Rule
raccess_get_rule_type_from_rule_index( FT_Library library,
FT_UInt rule_index )
{
FT_UNUSED( library );
 
if ( rule_index >= FT_RACCESS_N_RULES )
return FT_RFork_Rule_invalid;
 
return FT_RACCESS_GUESS_TABLE_GET[rule_index].type;
}
 
 
/*
* For this function, refer ftbase.h.
*/
FT_LOCAL_DEF( FT_Bool )
ft_raccess_rule_by_darwin_vfs( FT_Library library,
FT_UInt rule_index )
{
switch( raccess_get_rule_type_from_rule_index( library, rule_index ) )
{
case FT_RFork_Rule_darwin_newvfs:
case FT_RFork_Rule_darwin_hfsplus:
return TRUE;
 
default:
return FALSE;
}
}
#endif
 
 
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_THROW( 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_THROW( 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_THROW( 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 = NULL;
FT_Memory memory;
FT_Long base_file_len = (FT_Long)ft_strlen( base_file_name );
 
FT_UNUSED( stream );
 
 
memory = library->memory;
 
if ( base_file_len + 6 > FT_INT_MAX )
return FT_THROW( 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 = NULL;
FT_Memory memory;
FT_Long base_file_len = (FT_Long)ft_strlen( base_file_name );
 
FT_UNUSED( stream );
 
 
memory = library->memory;
 
if ( base_file_len + 18 > FT_INT_MAX )
return FT_THROW( 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_THROW( 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_THROW( 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_THROW( 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_THROW( 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_THROW( 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_THROW( 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_THROW( 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 )
{
FT_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 */
/programs/develop/libraries/freetype/src/base/ftsnames.c
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 */
/programs/develop/libraries/freetype/src/base/ftstream.c
0,0 → 1,865
/***************************************************************************/
/* */
/* ftstream.c */
/* */
/* I/O stream support (body). */
/* */
/* Copyright 2000-2002, 2004-2006, 2008-2011, 2013 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_THROW( 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_THROW( 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_THROW( 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_THROW( 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_THROW( 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_THROW( 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_THROW( 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_THROW( 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_UShort )
FT_Stream_GetUShort( 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_USHORT( p );
stream->cursor = p;
 
return result;
}
 
 
FT_BASE_DEF( FT_UShort )
FT_Stream_GetUShortLE( 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_USHORT_LE( p );
stream->cursor = p;
 
return result;
}
 
 
FT_BASE_DEF( FT_ULong )
FT_Stream_GetUOffset( 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_UOFF3( p );
stream->cursor = p;
return result;
}
 
 
FT_BASE_DEF( FT_ULong )
FT_Stream_GetULong( 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_ULONG( p );
stream->cursor = p;
return result;
}
 
 
FT_BASE_DEF( FT_ULong )
FT_Stream_GetULongLE( 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_ULONG_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_THROW( 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_UShort )
FT_Stream_ReadUShort( 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_USHORT( p );
}
else
goto Fail;
 
stream->pos += 2;
 
return result;
 
Fail:
*error = FT_THROW( Invalid_Stream_Operation );
FT_ERROR(( "FT_Stream_ReadUShort:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
 
return 0;
}
 
 
FT_BASE_DEF( FT_UShort )
FT_Stream_ReadUShortLE( 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_USHORT_LE( p );
}
else
goto Fail;
 
stream->pos += 2;
 
return result;
 
Fail:
*error = FT_THROW( Invalid_Stream_Operation );
FT_ERROR(( "FT_Stream_ReadUShortLE:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
 
return 0;
}
 
 
FT_BASE_DEF( FT_ULong )
FT_Stream_ReadUOffset( 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_UOFF3( p );
}
else
goto Fail;
 
stream->pos += 3;
 
return result;
 
Fail:
*error = FT_THROW( Invalid_Stream_Operation );
FT_ERROR(( "FT_Stream_ReadUOffset:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
 
return 0;
}
 
 
FT_BASE_DEF( FT_ULong )
FT_Stream_ReadULong( 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_ULONG( p );
}
else
goto Fail;
 
stream->pos += 4;
 
return result;
 
Fail:
*error = FT_THROW( Invalid_Stream_Operation );
FT_ERROR(( "FT_Stream_ReadULong:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
 
return 0;
}
 
 
FT_BASE_DEF( FT_ULong )
FT_Stream_ReadULongLE( 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_ULONG_LE( p );
}
else
goto Fail;
 
stream->pos += 4;
 
return result;
 
Fail:
*error = FT_THROW( Invalid_Stream_Operation );
FT_ERROR(( "FT_Stream_ReadULongLE:"
" 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_THROW( 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_THROW( 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 */
/programs/develop/libraries/freetype/src/base/ftstroke.c
0,0 → 1,2418
/***************************************************************************/
/* */
/* ftstroke.c */
/* */
/* FreeType path stroker (body). */
/* */
/* Copyright 2002-2006, 2008-2011, 2013 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_STROKER_H
#include FT_TRIGONOMETRY_H
#include FT_OUTLINE_H
#include FT_INTERNAL_MEMORY_H
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_OBJECTS_H
 
 
/* documentation is in ftstroke.h */
 
FT_EXPORT_DEF( FT_StrokerBorder )
FT_Outline_GetInsideBorder( FT_Outline* outline )
{
FT_Orientation o = FT_Outline_Get_Orientation( outline );
 
 
return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_RIGHT
: FT_STROKER_BORDER_LEFT;
}
 
 
/* documentation is in ftstroke.h */
 
FT_EXPORT_DEF( FT_StrokerBorder )
FT_Outline_GetOutsideBorder( FT_Outline* outline )
{
FT_Orientation o = FT_Outline_Get_Orientation( outline );
 
 
return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_LEFT
: FT_STROKER_BORDER_RIGHT;
}
 
 
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** BEZIER COMPUTATIONS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
 
#define FT_SMALL_CONIC_THRESHOLD ( FT_ANGLE_PI / 6 )
#define FT_SMALL_CUBIC_THRESHOLD ( FT_ANGLE_PI / 8 )
 
#define FT_EPSILON 2
 
#define FT_IS_SMALL( x ) ( (x) > -FT_EPSILON && (x) < FT_EPSILON )
 
 
static FT_Pos
ft_pos_abs( FT_Pos x )
{
return x >= 0 ? x : -x;
}
 
 
static void
ft_conic_split( FT_Vector* base )
{
FT_Pos a, b;
 
 
base[4].x = base[2].x;
b = base[1].x;
a = base[3].x = ( base[2].x + b ) / 2;
b = base[1].x = ( base[0].x + b ) / 2;
base[2].x = ( a + b ) / 2;
 
base[4].y = base[2].y;
b = base[1].y;
a = base[3].y = ( base[2].y + b ) / 2;
b = base[1].y = ( base[0].y + b ) / 2;
base[2].y = ( a + b ) / 2;
}
 
 
static FT_Bool
ft_conic_is_small_enough( FT_Vector* base,
FT_Angle *angle_in,
FT_Angle *angle_out )
{
FT_Vector d1, d2;
FT_Angle theta;
FT_Int close1, close2;
 
 
d1.x = base[1].x - base[2].x;
d1.y = base[1].y - base[2].y;
d2.x = base[0].x - base[1].x;
d2.y = base[0].y - base[1].y;
 
close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y );
close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y );
 
if ( close1 )
{
if ( close2 )
{
/* basically a point; */
/* do nothing to retain original direction */
}
else
{
*angle_in =
*angle_out = FT_Atan2( d2.x, d2.y );
}
}
else /* !close1 */
{
if ( close2 )
{
*angle_in =
*angle_out = FT_Atan2( d1.x, d1.y );
}
else
{
*angle_in = FT_Atan2( d1.x, d1.y );
*angle_out = FT_Atan2( d2.x, d2.y );
}
}
 
theta = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_out ) );
 
return FT_BOOL( theta < FT_SMALL_CONIC_THRESHOLD );
}
 
 
static void
ft_cubic_split( FT_Vector* base )
{
FT_Pos a, b, c, d;
 
 
base[6].x = base[3].x;
c = base[1].x;
d = base[2].x;
base[1].x = a = ( base[0].x + c ) / 2;
base[5].x = b = ( base[3].x + d ) / 2;
c = ( c + d ) / 2;
base[2].x = a = ( a + c ) / 2;
base[4].x = b = ( b + c ) / 2;
base[3].x = ( a + b ) / 2;
 
base[6].y = base[3].y;
c = base[1].y;
d = base[2].y;
base[1].y = a = ( base[0].y + c ) / 2;
base[5].y = b = ( base[3].y + d ) / 2;
c = ( c + d ) / 2;
base[2].y = a = ( a + c ) / 2;
base[4].y = b = ( b + c ) / 2;
base[3].y = ( a + b ) / 2;
}
 
 
/* Return the average of `angle1' and `angle2'. */
/* This gives correct result even if `angle1' and `angle2' */
/* have opposite signs. */
static FT_Angle
ft_angle_mean( FT_Angle angle1,
FT_Angle angle2 )
{
return angle1 + FT_Angle_Diff( angle1, angle2 ) / 2;
}
 
 
static FT_Bool
ft_cubic_is_small_enough( FT_Vector* base,
FT_Angle *angle_in,
FT_Angle *angle_mid,
FT_Angle *angle_out )
{
FT_Vector d1, d2, d3;
FT_Angle theta1, theta2;
FT_Int close1, close2, close3;
 
 
d1.x = base[2].x - base[3].x;
d1.y = base[2].y - base[3].y;
d2.x = base[1].x - base[2].x;
d2.y = base[1].y - base[2].y;
d3.x = base[0].x - base[1].x;
d3.y = base[0].y - base[1].y;
 
close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y );
close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y );
close3 = FT_IS_SMALL( d3.x ) && FT_IS_SMALL( d3.y );
 
if ( close1 )
{
if ( close2 )
{
if ( close3 )
{
/* basically a point; */
/* do nothing to retain original direction */
}
else /* !close3 */
{
*angle_in =
*angle_mid =
*angle_out = FT_Atan2( d3.x, d3.y );
}
}
else /* !close2 */
{
if ( close3 )
{
*angle_in =
*angle_mid =
*angle_out = FT_Atan2( d2.x, d2.y );
}
else /* !close3 */
{
*angle_in =
*angle_mid = FT_Atan2( d2.x, d2.y );
*angle_out = FT_Atan2( d3.x, d3.y );
}
}
}
else /* !close1 */
{
if ( close2 )
{
if ( close3 )
{
*angle_in =
*angle_mid =
*angle_out = FT_Atan2( d1.x, d1.y );
}
else /* !close3 */
{
*angle_in = FT_Atan2( d1.x, d1.y );
*angle_out = FT_Atan2( d3.x, d3.y );
*angle_mid = ft_angle_mean( *angle_in, *angle_out );
}
}
else /* !close2 */
{
if ( close3 )
{
*angle_in = FT_Atan2( d1.x, d1.y );
*angle_mid =
*angle_out = FT_Atan2( d2.x, d2.y );
}
else /* !close3 */
{
*angle_in = FT_Atan2( d1.x, d1.y );
*angle_mid = FT_Atan2( d2.x, d2.y );
*angle_out = FT_Atan2( d3.x, d3.y );
}
}
}
 
theta1 = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_mid ) );
theta2 = ft_pos_abs( FT_Angle_Diff( *angle_mid, *angle_out ) );
 
return FT_BOOL( theta1 < FT_SMALL_CUBIC_THRESHOLD &&
theta2 < FT_SMALL_CUBIC_THRESHOLD );
}
 
 
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** STROKE BORDERS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
 
typedef enum FT_StrokeTags_
{
FT_STROKE_TAG_ON = 1, /* on-curve point */
FT_STROKE_TAG_CUBIC = 2, /* cubic off-point */
FT_STROKE_TAG_BEGIN = 4, /* sub-path start */
FT_STROKE_TAG_END = 8 /* sub-path end */
 
} FT_StrokeTags;
 
#define FT_STROKE_TAG_BEGIN_END ( FT_STROKE_TAG_BEGIN | FT_STROKE_TAG_END )
 
typedef struct FT_StrokeBorderRec_
{
FT_UInt num_points;
FT_UInt max_points;
FT_Vector* points;
FT_Byte* tags;
FT_Bool movable; /* TRUE for ends of lineto borders */
FT_Int start; /* index of current sub-path start point */
FT_Memory memory;
FT_Bool valid;
 
} FT_StrokeBorderRec, *FT_StrokeBorder;
 
 
static FT_Error
ft_stroke_border_grow( FT_StrokeBorder border,
FT_UInt new_points )
{
FT_UInt old_max = border->max_points;
FT_UInt new_max = border->num_points + new_points;
FT_Error error = FT_Err_Ok;
 
 
if ( new_max > old_max )
{
FT_UInt cur_max = old_max;
FT_Memory memory = border->memory;
 
 
while ( cur_max < new_max )
cur_max += ( cur_max >> 1 ) + 16;
 
if ( FT_RENEW_ARRAY( border->points, old_max, cur_max ) ||
FT_RENEW_ARRAY( border->tags, old_max, cur_max ) )
goto Exit;
 
border->max_points = cur_max;
}
 
Exit:
return error;
}
 
 
static void
ft_stroke_border_close( FT_StrokeBorder border,
FT_Bool reverse )
{
FT_UInt start = border->start;
FT_UInt count = border->num_points;
 
 
FT_ASSERT( border->start >= 0 );
 
/* don't record empty paths! */
if ( count <= start + 1U )
border->num_points = start;
else
{
/* copy the last point to the start of this sub-path, since */
/* it contains the `adjusted' starting coordinates */
border->num_points = --count;
border->points[start] = border->points[count];
 
if ( reverse )
{
/* reverse the points */
{
FT_Vector* vec1 = border->points + start + 1;
FT_Vector* vec2 = border->points + count - 1;
 
 
for ( ; vec1 < vec2; vec1++, vec2-- )
{
FT_Vector tmp;
 
 
tmp = *vec1;
*vec1 = *vec2;
*vec2 = tmp;
}
}
 
/* then the tags */
{
FT_Byte* tag1 = border->tags + start + 1;
FT_Byte* tag2 = border->tags + count - 1;
 
 
for ( ; tag1 < tag2; tag1++, tag2-- )
{
FT_Byte tmp;
 
 
tmp = *tag1;
*tag1 = *tag2;
*tag2 = tmp;
}
}
}
 
border->tags[start ] |= FT_STROKE_TAG_BEGIN;
border->tags[count - 1] |= FT_STROKE_TAG_END;
}
 
border->start = -1;
border->movable = FALSE;
}
 
 
static FT_Error
ft_stroke_border_lineto( FT_StrokeBorder border,
FT_Vector* to,
FT_Bool movable )
{
FT_Error error = FT_Err_Ok;
 
 
FT_ASSERT( border->start >= 0 );
 
if ( border->movable )
{
/* move last point */
border->points[border->num_points - 1] = *to;
}
else
{
/* don't add zero-length lineto */
if ( border->num_points > 0 &&
FT_IS_SMALL( border->points[border->num_points - 1].x - to->x ) &&
FT_IS_SMALL( border->points[border->num_points - 1].y - to->y ) )
return error;
 
/* add one point */
error = ft_stroke_border_grow( border, 1 );
if ( !error )
{
FT_Vector* vec = border->points + border->num_points;
FT_Byte* tag = border->tags + border->num_points;
 
 
vec[0] = *to;
tag[0] = FT_STROKE_TAG_ON;
 
border->num_points += 1;
}
}
border->movable = movable;
return error;
}
 
 
static FT_Error
ft_stroke_border_conicto( FT_StrokeBorder border,
FT_Vector* control,
FT_Vector* to )
{
FT_Error error;
 
 
FT_ASSERT( border->start >= 0 );
 
error = ft_stroke_border_grow( border, 2 );
if ( !error )
{
FT_Vector* vec = border->points + border->num_points;
FT_Byte* tag = border->tags + border->num_points;
 
 
vec[0] = *control;
vec[1] = *to;
 
tag[0] = 0;
tag[1] = FT_STROKE_TAG_ON;
 
border->num_points += 2;
}
 
border->movable = FALSE;
 
return error;
}
 
 
static FT_Error
ft_stroke_border_cubicto( FT_StrokeBorder border,
FT_Vector* control1,
FT_Vector* control2,
FT_Vector* to )
{
FT_Error error;
 
 
FT_ASSERT( border->start >= 0 );
 
error = ft_stroke_border_grow( border, 3 );
if ( !error )
{
FT_Vector* vec = border->points + border->num_points;
FT_Byte* tag = border->tags + border->num_points;
 
 
vec[0] = *control1;
vec[1] = *control2;
vec[2] = *to;
 
tag[0] = FT_STROKE_TAG_CUBIC;
tag[1] = FT_STROKE_TAG_CUBIC;
tag[2] = FT_STROKE_TAG_ON;
 
border->num_points += 3;
}
 
border->movable = FALSE;
 
return error;
}
 
 
#define FT_ARC_CUBIC_ANGLE ( FT_ANGLE_PI / 2 )
 
 
static FT_Error
ft_stroke_border_arcto( FT_StrokeBorder border,
FT_Vector* center,
FT_Fixed radius,
FT_Angle angle_start,
FT_Angle angle_diff )
{
FT_Angle total, angle, step, rotate, next, theta;
FT_Vector a, b, a2, b2;
FT_Fixed length;
FT_Error error = FT_Err_Ok;
 
 
/* compute start point */
FT_Vector_From_Polar( &a, radius, angle_start );
a.x += center->x;
a.y += center->y;
 
total = angle_diff;
angle = angle_start;
rotate = ( angle_diff >= 0 ) ? FT_ANGLE_PI2 : -FT_ANGLE_PI2;
 
while ( total != 0 )
{
step = total;
if ( step > FT_ARC_CUBIC_ANGLE )
step = FT_ARC_CUBIC_ANGLE;
 
else if ( step < -FT_ARC_CUBIC_ANGLE )
step = -FT_ARC_CUBIC_ANGLE;
 
next = angle + step;
theta = step;
if ( theta < 0 )
theta = -theta;
 
theta >>= 1;
 
/* compute end point */
FT_Vector_From_Polar( &b, radius, next );
b.x += center->x;
b.y += center->y;
 
/* compute first and second control points */
length = FT_MulDiv( radius, FT_Sin( theta ) * 4,
( 0x10000L + FT_Cos( theta ) ) * 3 );
 
FT_Vector_From_Polar( &a2, length, angle + rotate );
a2.x += a.x;
a2.y += a.y;
 
FT_Vector_From_Polar( &b2, length, next - rotate );
b2.x += b.x;
b2.y += b.y;
 
/* add cubic arc */
error = ft_stroke_border_cubicto( border, &a2, &b2, &b );
if ( error )
break;
 
/* process the rest of the arc ?? */
a = b;
total -= step;
angle = next;
}
 
return error;
}
 
 
static FT_Error
ft_stroke_border_moveto( FT_StrokeBorder border,
FT_Vector* to )
{
/* close current open path if any ? */
if ( border->start >= 0 )
ft_stroke_border_close( border, FALSE );
 
border->start = border->num_points;
border->movable = FALSE;
 
return ft_stroke_border_lineto( border, to, FALSE );
}
 
 
static void
ft_stroke_border_init( FT_StrokeBorder border,
FT_Memory memory )
{
border->memory = memory;
border->points = NULL;
border->tags = NULL;
 
border->num_points = 0;
border->max_points = 0;
border->start = -1;
border->valid = FALSE;
}
 
 
static void
ft_stroke_border_reset( FT_StrokeBorder border )
{
border->num_points = 0;
border->start = -1;
border->valid = FALSE;
}
 
 
static void
ft_stroke_border_done( FT_StrokeBorder border )
{
FT_Memory memory = border->memory;
 
 
FT_FREE( border->points );
FT_FREE( border->tags );
 
border->num_points = 0;
border->max_points = 0;
border->start = -1;
border->valid = FALSE;
}
 
 
static FT_Error
ft_stroke_border_get_counts( FT_StrokeBorder border,
FT_UInt *anum_points,
FT_UInt *anum_contours )
{
FT_Error error = FT_Err_Ok;
FT_UInt num_points = 0;
FT_UInt num_contours = 0;
 
FT_UInt count = border->num_points;
FT_Vector* point = border->points;
FT_Byte* tags = border->tags;
FT_Int in_contour = 0;
 
 
for ( ; count > 0; count--, num_points++, point++, tags++ )
{
if ( tags[0] & FT_STROKE_TAG_BEGIN )
{
if ( in_contour != 0 )
goto Fail;
 
in_contour = 1;
}
else if ( in_contour == 0 )
goto Fail;
 
if ( tags[0] & FT_STROKE_TAG_END )
{
in_contour = 0;
num_contours++;
}
}
 
if ( in_contour != 0 )
goto Fail;
 
border->valid = TRUE;
 
Exit:
*anum_points = num_points;
*anum_contours = num_contours;
return error;
 
Fail:
num_points = 0;
num_contours = 0;
goto Exit;
}
 
 
static void
ft_stroke_border_export( FT_StrokeBorder border,
FT_Outline* outline )
{
/* copy point locations */
FT_ARRAY_COPY( outline->points + outline->n_points,
border->points,
border->num_points );
 
/* copy tags */
{
FT_UInt count = border->num_points;
FT_Byte* read = border->tags;
FT_Byte* write = (FT_Byte*)outline->tags + outline->n_points;
 
 
for ( ; count > 0; count--, read++, write++ )
{
if ( *read & FT_STROKE_TAG_ON )
*write = FT_CURVE_TAG_ON;
else if ( *read & FT_STROKE_TAG_CUBIC )
*write = FT_CURVE_TAG_CUBIC;
else
*write = FT_CURVE_TAG_CONIC;
}
}
 
/* copy contours */
{
FT_UInt count = border->num_points;
FT_Byte* tags = border->tags;
FT_Short* write = outline->contours + outline->n_contours;
FT_Short idx = (FT_Short)outline->n_points;
 
 
for ( ; count > 0; count--, tags++, idx++ )
{
if ( *tags & FT_STROKE_TAG_END )
{
*write++ = idx;
outline->n_contours++;
}
}
}
 
outline->n_points = (short)( outline->n_points + border->num_points );
 
FT_ASSERT( FT_Outline_Check( outline ) == 0 );
}
 
 
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** STROKER *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
 
#define FT_SIDE_TO_ROTATE( s ) ( FT_ANGLE_PI2 - (s) * FT_ANGLE_PI )
 
typedef struct FT_StrokerRec_
{
FT_Angle angle_in; /* direction into curr join */
FT_Angle angle_out; /* direction out of join */
FT_Vector center; /* current position */
FT_Fixed line_length; /* length of last lineto */
FT_Bool first_point; /* is this the start? */
FT_Bool subpath_open; /* is the subpath open? */
FT_Angle subpath_angle; /* subpath start direction */
FT_Vector subpath_start; /* subpath start position */
FT_Fixed subpath_line_length; /* subpath start lineto len */
FT_Bool handle_wide_strokes; /* use wide strokes logic? */
 
FT_Stroker_LineCap line_cap;
FT_Stroker_LineJoin line_join;
FT_Stroker_LineJoin line_join_saved;
FT_Fixed miter_limit;
FT_Fixed radius;
 
FT_StrokeBorderRec borders[2];
FT_Library library;
 
} FT_StrokerRec;
 
 
/* documentation is in ftstroke.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Stroker_New( FT_Library library,
FT_Stroker *astroker )
{
FT_Error error; /* assigned in FT_NEW */
FT_Memory memory;
FT_Stroker stroker = NULL;
 
 
if ( !library )
return FT_THROW( Invalid_Argument );
 
memory = library->memory;
 
if ( !FT_NEW( stroker ) )
{
stroker->library = library;
 
ft_stroke_border_init( &stroker->borders[0], memory );
ft_stroke_border_init( &stroker->borders[1], memory );
}
 
*astroker = stroker;
 
return error;
}
 
 
/* documentation is in ftstroke.h */
 
FT_EXPORT_DEF( void )
FT_Stroker_Set( FT_Stroker stroker,
FT_Fixed radius,
FT_Stroker_LineCap line_cap,
FT_Stroker_LineJoin line_join,
FT_Fixed miter_limit )
{
stroker->radius = radius;
stroker->line_cap = line_cap;
stroker->line_join = line_join;
stroker->miter_limit = miter_limit;
 
/* ensure miter limit has sensible value */
if ( stroker->miter_limit < 0x10000 )
stroker->miter_limit = 0x10000;
 
/* save line join style: */
/* line join style can be temporarily changed when stroking curves */
stroker->line_join_saved = line_join;
 
FT_Stroker_Rewind( stroker );
}
 
 
/* documentation is in ftstroke.h */
 
FT_EXPORT_DEF( void )
FT_Stroker_Rewind( FT_Stroker stroker )
{
if ( stroker )
{
ft_stroke_border_reset( &stroker->borders[0] );
ft_stroke_border_reset( &stroker->borders[1] );
}
}
 
 
/* documentation is in ftstroke.h */
 
FT_EXPORT_DEF( void )
FT_Stroker_Done( FT_Stroker stroker )
{
if ( stroker )
{
FT_Memory memory = stroker->library->memory;
 
 
ft_stroke_border_done( &stroker->borders[0] );
ft_stroke_border_done( &stroker->borders[1] );
 
stroker->library = NULL;
FT_FREE( stroker );
}
}
 
 
/* create a circular arc at a corner or cap */
static FT_Error
ft_stroker_arcto( FT_Stroker stroker,
FT_Int side )
{
FT_Angle total, rotate;
FT_Fixed radius = stroker->radius;
FT_Error error = FT_Err_Ok;
FT_StrokeBorder border = stroker->borders + side;
 
 
rotate = FT_SIDE_TO_ROTATE( side );
 
total = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
if ( total == FT_ANGLE_PI )
total = -rotate * 2;
 
error = ft_stroke_border_arcto( border,
&stroker->center,
radius,
stroker->angle_in + rotate,
total );
border->movable = FALSE;
return error;
}
 
 
/* add a cap at the end of an opened path */
static FT_Error
ft_stroker_cap( FT_Stroker stroker,
FT_Angle angle,
FT_Int side )
{
FT_Error error = FT_Err_Ok;
 
 
if ( stroker->line_cap == FT_STROKER_LINECAP_ROUND )
{
/* add a round cap */
stroker->angle_in = angle;
stroker->angle_out = angle + FT_ANGLE_PI;
 
error = ft_stroker_arcto( stroker, side );
}
else if ( stroker->line_cap == FT_STROKER_LINECAP_SQUARE )
{
/* add a square cap */
FT_Vector delta, delta2;
FT_Angle rotate = FT_SIDE_TO_ROTATE( side );
FT_Fixed radius = stroker->radius;
FT_StrokeBorder border = stroker->borders + side;
 
 
FT_Vector_From_Polar( &delta2, radius, angle + rotate );
FT_Vector_From_Polar( &delta, radius, angle );
 
delta.x += stroker->center.x + delta2.x;
delta.y += stroker->center.y + delta2.y;
 
error = ft_stroke_border_lineto( border, &delta, FALSE );
if ( error )
goto Exit;
 
FT_Vector_From_Polar( &delta2, radius, angle - rotate );
FT_Vector_From_Polar( &delta, radius, angle );
 
delta.x += delta2.x + stroker->center.x;
delta.y += delta2.y + stroker->center.y;
 
error = ft_stroke_border_lineto( border, &delta, FALSE );
}
else if ( stroker->line_cap == FT_STROKER_LINECAP_BUTT )
{
/* add a butt ending */
FT_Vector delta;
FT_Angle rotate = FT_SIDE_TO_ROTATE( side );
FT_Fixed radius = stroker->radius;
FT_StrokeBorder border = stroker->borders + side;
 
 
FT_Vector_From_Polar( &delta, radius, angle + rotate );
 
delta.x += stroker->center.x;
delta.y += stroker->center.y;
 
error = ft_stroke_border_lineto( border, &delta, FALSE );
if ( error )
goto Exit;
 
FT_Vector_From_Polar( &delta, radius, angle - rotate );
 
delta.x += stroker->center.x;
delta.y += stroker->center.y;
 
error = ft_stroke_border_lineto( border, &delta, FALSE );
}
 
Exit:
return error;
}
 
 
/* process an inside corner, i.e. compute intersection */
static FT_Error
ft_stroker_inside( FT_Stroker stroker,
FT_Int side,
FT_Fixed line_length )
{
FT_StrokeBorder border = stroker->borders + side;
FT_Angle phi, theta, rotate;
FT_Fixed length, thcos;
FT_Vector delta;
FT_Error error = FT_Err_Ok;
FT_Bool intersect; /* use intersection of lines? */
 
 
rotate = FT_SIDE_TO_ROTATE( side );
 
theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ) / 2;
 
/* Only intersect borders if between two lineto's and both */
/* lines are long enough (line_length is zero for curves). */
if ( !border->movable || line_length == 0 )
intersect = FALSE;
else
{
/* compute minimum required length of lines */
FT_Fixed min_length = ft_pos_abs( FT_MulFix( stroker->radius,
FT_Tan( theta ) ) );
 
 
intersect = FT_BOOL( stroker->line_length >= min_length &&
line_length >= min_length );
}
 
if ( !intersect )
{
FT_Vector_From_Polar( &delta, stroker->radius,
stroker->angle_out + rotate );
delta.x += stroker->center.x;
delta.y += stroker->center.y;
 
border->movable = FALSE;
}
else
{
/* compute median angle */
phi = stroker->angle_in + theta;
 
thcos = FT_Cos( theta );
 
length = FT_DivFix( stroker->radius, thcos );
 
FT_Vector_From_Polar( &delta, length, phi + rotate );
delta.x += stroker->center.x;
delta.y += stroker->center.y;
}
 
error = ft_stroke_border_lineto( border, &delta, FALSE );
 
return error;
}
 
 
/* process an outside corner, i.e. compute bevel/miter/round */
static FT_Error
ft_stroker_outside( FT_Stroker stroker,
FT_Int side,
FT_Fixed line_length )
{
FT_StrokeBorder border = stroker->borders + side;
FT_Error error;
FT_Angle rotate;
 
 
if ( stroker->line_join == FT_STROKER_LINEJOIN_ROUND )
error = ft_stroker_arcto( stroker, side );
else
{
/* this is a mitered (pointed) or beveled (truncated) corner */
FT_Fixed sigma = 0, radius = stroker->radius;
FT_Angle theta = 0, phi = 0;
FT_Fixed thcos = 0;
FT_Bool bevel, fixed_bevel;
 
 
rotate = FT_SIDE_TO_ROTATE( side );
 
bevel =
FT_BOOL( stroker->line_join == FT_STROKER_LINEJOIN_BEVEL );
 
fixed_bevel =
FT_BOOL( stroker->line_join != FT_STROKER_LINEJOIN_MITER_VARIABLE );
 
if ( !bevel )
{
theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
 
if ( theta == FT_ANGLE_PI )
{
theta = rotate;
phi = stroker->angle_in;
}
else
{
theta /= 2;
phi = stroker->angle_in + theta + rotate;
}
 
thcos = FT_Cos( theta );
sigma = FT_MulFix( stroker->miter_limit, thcos );
 
/* is miter limit exceeded? */
if ( sigma < 0x10000L )
{
/* don't create variable bevels for very small deviations; */
/* FT_Sin(x) = 0 for x <= 57 */
if ( fixed_bevel || ft_pos_abs( theta ) > 57 )
bevel = TRUE;
}
}
 
if ( bevel ) /* this is a bevel (broken angle) */
{
if ( fixed_bevel )
{
/* the outer corners are simply joined together */
FT_Vector delta;
 
 
/* add bevel */
FT_Vector_From_Polar( &delta,
radius,
stroker->angle_out + rotate );
delta.x += stroker->center.x;
delta.y += stroker->center.y;
 
border->movable = FALSE;
error = ft_stroke_border_lineto( border, &delta, FALSE );
}
else /* variable bevel */
{
/* the miter is truncated */
FT_Vector middle, delta;
FT_Fixed length;
 
 
/* compute middle point */
FT_Vector_From_Polar( &middle,
FT_MulFix( radius, stroker->miter_limit ),
phi );
middle.x += stroker->center.x;
middle.y += stroker->center.y;
 
/* compute first angle point */
length = FT_MulDiv( radius, 0x10000L - sigma,
ft_pos_abs( FT_Sin( theta ) ) );
 
FT_Vector_From_Polar( &delta, length, phi + rotate );
delta.x += middle.x;
delta.y += middle.y;
 
error = ft_stroke_border_lineto( border, &delta, FALSE );
if ( error )
goto Exit;
 
/* compute second angle point */
FT_Vector_From_Polar( &delta, length, phi - rotate );
delta.x += middle.x;
delta.y += middle.y;
 
error = ft_stroke_border_lineto( border, &delta, FALSE );
if ( error )
goto Exit;
 
/* finally, add an end point; only needed if not lineto */
/* (line_length is zero for curves) */
if ( line_length == 0 )
{
FT_Vector_From_Polar( &delta,
radius,
stroker->angle_out + rotate );
 
delta.x += stroker->center.x;
delta.y += stroker->center.y;
 
error = ft_stroke_border_lineto( border, &delta, FALSE );
}
}
}
else /* this is a miter (intersection) */
{
FT_Fixed length;
FT_Vector delta;
 
 
length = FT_DivFix( stroker->radius, thcos );
 
FT_Vector_From_Polar( &delta, length, phi );
delta.x += stroker->center.x;
delta.y += stroker->center.y;
 
error = ft_stroke_border_lineto( border, &delta, FALSE );
if ( error )
goto Exit;
 
/* now add an end point; only needed if not lineto */
/* (line_length is zero for curves) */
if ( line_length == 0 )
{
FT_Vector_From_Polar( &delta,
stroker->radius,
stroker->angle_out + rotate );
delta.x += stroker->center.x;
delta.y += stroker->center.y;
 
error = ft_stroke_border_lineto( border, &delta, FALSE );
}
}
}
 
Exit:
return error;
}
 
 
static FT_Error
ft_stroker_process_corner( FT_Stroker stroker,
FT_Fixed line_length )
{
FT_Error error = FT_Err_Ok;
FT_Angle turn;
FT_Int inside_side;
 
 
turn = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
 
/* no specific corner processing is required if the turn is 0 */
if ( turn == 0 )
goto Exit;
 
/* when we turn to the right, the inside side is 0 */
inside_side = 0;
 
/* otherwise, the inside side is 1 */
if ( turn < 0 )
inside_side = 1;
 
/* process the inside side */
error = ft_stroker_inside( stroker, inside_side, line_length );
if ( error )
goto Exit;
 
/* process the outside side */
error = ft_stroker_outside( stroker, 1 - inside_side, line_length );
 
Exit:
return error;
}
 
 
/* add two points to the left and right borders corresponding to the */
/* start of the subpath */
static FT_Error
ft_stroker_subpath_start( FT_Stroker stroker,
FT_Angle start_angle,
FT_Fixed line_length )
{
FT_Vector delta;
FT_Vector point;
FT_Error error;
FT_StrokeBorder border;
 
 
FT_Vector_From_Polar( &delta, stroker->radius,
start_angle + FT_ANGLE_PI2 );
 
point.x = stroker->center.x + delta.x;
point.y = stroker->center.y + delta.y;
 
border = stroker->borders;
error = ft_stroke_border_moveto( border, &point );
if ( error )
goto Exit;
 
point.x = stroker->center.x - delta.x;
point.y = stroker->center.y - delta.y;
 
border++;
error = ft_stroke_border_moveto( border, &point );
 
/* save angle, position, and line length for last join */
/* (line_length is zero for curves) */
stroker->subpath_angle = start_angle;
stroker->first_point = FALSE;
stroker->subpath_line_length = line_length;
 
Exit:
return error;
}
 
 
/* documentation is in ftstroke.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Stroker_LineTo( FT_Stroker stroker,
FT_Vector* to )
{
FT_Error error = FT_Err_Ok;
FT_StrokeBorder border;
FT_Vector delta;
FT_Angle angle;
FT_Int side;
FT_Fixed line_length;
 
 
delta.x = to->x - stroker->center.x;
delta.y = to->y - stroker->center.y;
 
/* a zero-length lineto is a no-op; avoid creating a spurious corner */
if ( delta.x == 0 && delta.y == 0 )
goto Exit;
 
/* compute length of line */
line_length = FT_Vector_Length( &delta );
 
angle = FT_Atan2( delta.x, delta.y );
FT_Vector_From_Polar( &delta, stroker->radius, angle + FT_ANGLE_PI2 );
 
/* process corner if necessary */
if ( stroker->first_point )
{
/* This is the first segment of a subpath. We need to */
/* add a point to each border at their respective starting */
/* point locations. */
error = ft_stroker_subpath_start( stroker, angle, line_length );
if ( error )
goto Exit;
}
else
{
/* process the current corner */
stroker->angle_out = angle;
error = ft_stroker_process_corner( stroker, line_length );
if ( error )
goto Exit;
}
 
/* now add a line segment to both the `inside' and `outside' paths */
for ( border = stroker->borders, side = 1; side >= 0; side--, border++ )
{
FT_Vector point;
 
 
point.x = to->x + delta.x;
point.y = to->y + delta.y;
 
/* the ends of lineto borders are movable */
error = ft_stroke_border_lineto( border, &point, TRUE );
if ( error )
goto Exit;
 
delta.x = -delta.x;
delta.y = -delta.y;
}
 
stroker->angle_in = angle;
stroker->center = *to;
stroker->line_length = line_length;
 
Exit:
return error;
}
 
 
/* documentation is in ftstroke.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Stroker_ConicTo( FT_Stroker stroker,
FT_Vector* control,
FT_Vector* to )
{
FT_Error error = FT_Err_Ok;
FT_Vector bez_stack[34];
FT_Vector* arc;
FT_Vector* limit = bez_stack + 30;
FT_Bool first_arc = TRUE;
 
 
/* if all control points are coincident, this is a no-op; */
/* avoid creating a spurious corner */
if ( FT_IS_SMALL( stroker->center.x - control->x ) &&
FT_IS_SMALL( stroker->center.y - control->y ) &&
FT_IS_SMALL( control->x - to->x ) &&
FT_IS_SMALL( control->y - to->y ) )
{
stroker->center = *to;
goto Exit;
}
 
arc = bez_stack;
arc[0] = *to;
arc[1] = *control;
arc[2] = stroker->center;
 
while ( arc >= bez_stack )
{
FT_Angle angle_in, angle_out;
 
 
/* initialize with current direction */
angle_in = angle_out = stroker->angle_in;
 
if ( arc < limit &&
!ft_conic_is_small_enough( arc, &angle_in, &angle_out ) )
{
if ( stroker->first_point )
stroker->angle_in = angle_in;
 
ft_conic_split( arc );
arc += 2;
continue;
}
 
if ( first_arc )
{
first_arc = FALSE;
 
/* process corner if necessary */
if ( stroker->first_point )
error = ft_stroker_subpath_start( stroker, angle_in, 0 );
else
{
stroker->angle_out = angle_in;
error = ft_stroker_process_corner( stroker, 0 );
}
}
else if ( ft_pos_abs( FT_Angle_Diff( stroker->angle_in, angle_in ) ) >
FT_SMALL_CONIC_THRESHOLD / 4 )
{
/* if the deviation from one arc to the next is too great, */
/* add a round corner */
stroker->center = arc[2];
stroker->angle_out = angle_in;
stroker->line_join = FT_STROKER_LINEJOIN_ROUND;
 
error = ft_stroker_process_corner( stroker, 0 );
 
/* reinstate line join style */
stroker->line_join = stroker->line_join_saved;
}
 
if ( error )
goto Exit;
 
/* the arc's angle is small enough; we can add it directly to each */
/* border */
{
FT_Vector ctrl, end;
FT_Angle theta, phi, rotate, alpha0 = 0;
FT_Fixed length;
FT_StrokeBorder border;
FT_Int side;
 
 
theta = FT_Angle_Diff( angle_in, angle_out ) / 2;
phi = angle_in + theta;
length = FT_DivFix( stroker->radius, FT_Cos( theta ) );
 
/* compute direction of original arc */
if ( stroker->handle_wide_strokes )
alpha0 = FT_Atan2( arc[0].x - arc[2].x, arc[0].y - arc[2].y );
 
for ( border = stroker->borders, side = 0;
side <= 1;
side++, border++ )
{
rotate = FT_SIDE_TO_ROTATE( side );
 
/* compute control point */
FT_Vector_From_Polar( &ctrl, length, phi + rotate );
ctrl.x += arc[1].x;
ctrl.y += arc[1].y;
 
/* compute end point */
FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate );
end.x += arc[0].x;
end.y += arc[0].y;
 
if ( stroker->handle_wide_strokes )
{
FT_Vector start;
FT_Angle alpha1;
 
 
/* determine whether the border radius is greater than the */
/* radius of curvature of the original arc */
start = border->points[border->num_points - 1];
 
alpha1 = FT_Atan2( end.x - start.x, end.y - start.y );
 
/* is the direction of the border arc opposite to */
/* that of the original arc? */
if ( ft_pos_abs( FT_Angle_Diff( alpha0, alpha1 ) ) >
FT_ANGLE_PI / 2 )
{
FT_Angle beta, gamma;
FT_Vector bvec, delta;
FT_Fixed blen, sinA, sinB, alen;
 
 
/* use the sine rule to find the intersection point */
beta = FT_Atan2( arc[2].x - start.x, arc[2].y - start.y );
gamma = FT_Atan2( arc[0].x - end.x, arc[0].y - end.y );
 
bvec.x = end.x - start.x;
bvec.y = end.y - start.y;
 
blen = FT_Vector_Length( &bvec );
 
sinA = ft_pos_abs( FT_Sin( alpha1 - gamma ) );
sinB = ft_pos_abs( FT_Sin( beta - gamma ) );
 
alen = FT_MulDiv( blen, sinA, sinB );
 
FT_Vector_From_Polar( &delta, alen, beta );
delta.x += start.x;
delta.y += start.y;
 
/* circumnavigate the negative sector backwards */
border->movable = FALSE;
error = ft_stroke_border_lineto( border, &delta, FALSE );
if ( error )
goto Exit;
error = ft_stroke_border_lineto( border, &end, FALSE );
if ( error )
goto Exit;
error = ft_stroke_border_conicto( border, &ctrl, &start );
if ( error )
goto Exit;
/* and then move to the endpoint */
error = ft_stroke_border_lineto( border, &end, FALSE );
if ( error )
goto Exit;
 
continue;
}
 
/* else fall through */
}
 
/* simply add an arc */
error = ft_stroke_border_conicto( border, &ctrl, &end );
if ( error )
goto Exit;
}
}
 
arc -= 2;
 
stroker->angle_in = angle_out;
}
 
stroker->center = *to;
 
Exit:
return error;
}
 
 
/* documentation is in ftstroke.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Stroker_CubicTo( FT_Stroker stroker,
FT_Vector* control1,
FT_Vector* control2,
FT_Vector* to )
{
FT_Error error = FT_Err_Ok;
FT_Vector bez_stack[37];
FT_Vector* arc;
FT_Vector* limit = bez_stack + 32;
FT_Bool first_arc = TRUE;
 
 
/* if all control points are coincident, this is a no-op; */
/* avoid creating a spurious corner */
if ( FT_IS_SMALL( stroker->center.x - control1->x ) &&
FT_IS_SMALL( stroker->center.y - control1->y ) &&
FT_IS_SMALL( control1->x - control2->x ) &&
FT_IS_SMALL( control1->y - control2->y ) &&
FT_IS_SMALL( control2->x - to->x ) &&
FT_IS_SMALL( control2->y - to->y ) )
{
stroker->center = *to;
goto Exit;
}
 
arc = bez_stack;
arc[0] = *to;
arc[1] = *control2;
arc[2] = *control1;
arc[3] = stroker->center;
 
while ( arc >= bez_stack )
{
FT_Angle angle_in, angle_mid, angle_out;
 
 
/* initialize with current direction */
angle_in = angle_out = angle_mid = stroker->angle_in;
 
if ( arc < limit &&
!ft_cubic_is_small_enough( arc, &angle_in,
&angle_mid, &angle_out ) )
{
if ( stroker->first_point )
stroker->angle_in = angle_in;
 
ft_cubic_split( arc );
arc += 3;
continue;
}
 
if ( first_arc )
{
first_arc = FALSE;
 
/* process corner if necessary */
if ( stroker->first_point )
error = ft_stroker_subpath_start( stroker, angle_in, 0 );
else
{
stroker->angle_out = angle_in;
error = ft_stroker_process_corner( stroker, 0 );
}
}
else if ( ft_pos_abs( FT_Angle_Diff( stroker->angle_in, angle_in ) ) >
FT_SMALL_CUBIC_THRESHOLD / 4 )
{
/* if the deviation from one arc to the next is too great, */
/* add a round corner */
stroker->center = arc[3];
stroker->angle_out = angle_in;
stroker->line_join = FT_STROKER_LINEJOIN_ROUND;
 
error = ft_stroker_process_corner( stroker, 0 );
 
/* reinstate line join style */
stroker->line_join = stroker->line_join_saved;
}
 
if ( error )
goto Exit;
 
/* the arc's angle is small enough; we can add it directly to each */
/* border */
{
FT_Vector ctrl1, ctrl2, end;
FT_Angle theta1, phi1, theta2, phi2, rotate, alpha0 = 0;
FT_Fixed length1, length2;
FT_StrokeBorder border;
FT_Int side;
 
 
theta1 = FT_Angle_Diff( angle_in, angle_mid ) / 2;
theta2 = FT_Angle_Diff( angle_mid, angle_out ) / 2;
phi1 = ft_angle_mean( angle_in, angle_mid );
phi2 = ft_angle_mean( angle_mid, angle_out );
length1 = FT_DivFix( stroker->radius, FT_Cos( theta1 ) );
length2 = FT_DivFix( stroker->radius, FT_Cos( theta2 ) );
 
/* compute direction of original arc */
if ( stroker->handle_wide_strokes )
alpha0 = FT_Atan2( arc[0].x - arc[3].x, arc[0].y - arc[3].y );
 
for ( border = stroker->borders, side = 0;
side <= 1;
side++, border++ )
{
rotate = FT_SIDE_TO_ROTATE( side );
 
/* compute control points */
FT_Vector_From_Polar( &ctrl1, length1, phi1 + rotate );
ctrl1.x += arc[2].x;
ctrl1.y += arc[2].y;
 
FT_Vector_From_Polar( &ctrl2, length2, phi2 + rotate );
ctrl2.x += arc[1].x;
ctrl2.y += arc[1].y;
 
/* compute end point */
FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate );
end.x += arc[0].x;
end.y += arc[0].y;
 
if ( stroker->handle_wide_strokes )
{
FT_Vector start;
FT_Angle alpha1;
 
 
/* determine whether the border radius is greater than the */
/* radius of curvature of the original arc */
start = border->points[border->num_points - 1];
 
alpha1 = FT_Atan2( end.x - start.x, end.y - start.y );
 
/* is the direction of the border arc opposite to */
/* that of the original arc? */
if ( ft_pos_abs( FT_Angle_Diff( alpha0, alpha1 ) ) >
FT_ANGLE_PI / 2 )
{
FT_Angle beta, gamma;
FT_Vector bvec, delta;
FT_Fixed blen, sinA, sinB, alen;
 
 
/* use the sine rule to find the intersection point */
beta = FT_Atan2( arc[3].x - start.x, arc[3].y - start.y );
gamma = FT_Atan2( arc[0].x - end.x, arc[0].y - end.y );
 
bvec.x = end.x - start.x;
bvec.y = end.y - start.y;
 
blen = FT_Vector_Length( &bvec );
 
sinA = ft_pos_abs( FT_Sin( alpha1 - gamma ) );
sinB = ft_pos_abs( FT_Sin( beta - gamma ) );
 
alen = FT_MulDiv( blen, sinA, sinB );
 
FT_Vector_From_Polar( &delta, alen, beta );
delta.x += start.x;
delta.y += start.y;
 
/* circumnavigate the negative sector backwards */
border->movable = FALSE;
error = ft_stroke_border_lineto( border, &delta, FALSE );
if ( error )
goto Exit;
error = ft_stroke_border_lineto( border, &end, FALSE );
if ( error )
goto Exit;
error = ft_stroke_border_cubicto( border,
&ctrl2,
&ctrl1,
&start );
if ( error )
goto Exit;
/* and then move to the endpoint */
error = ft_stroke_border_lineto( border, &end, FALSE );
if ( error )
goto Exit;
 
continue;
}
 
/* else fall through */
}
 
/* simply add an arc */
error = ft_stroke_border_cubicto( border, &ctrl1, &ctrl2, &end );
if ( error )
goto Exit;
}
}
 
arc -= 3;
 
stroker->angle_in = angle_out;
}
 
stroker->center = *to;
 
Exit:
return error;
}
 
 
/* documentation is in ftstroke.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Stroker_BeginSubPath( FT_Stroker stroker,
FT_Vector* to,
FT_Bool open )
{
/* We cannot process the first point, because there is not enough */
/* information regarding its corner/cap. The latter will be processed */
/* in the `FT_Stroker_EndSubPath' routine. */
/* */
stroker->first_point = TRUE;
stroker->center = *to;
stroker->subpath_open = open;
 
/* Determine if we need to check whether the border radius is greater */
/* than the radius of curvature of a curve, to handle this case */
/* specially. This is only required if bevel joins or butt caps may */
/* be created, because round & miter joins and round & square caps */
/* cover the negative sector created with wide strokes. */
stroker->handle_wide_strokes =
FT_BOOL( stroker->line_join != FT_STROKER_LINEJOIN_ROUND ||
( stroker->subpath_open &&
stroker->line_cap == FT_STROKER_LINECAP_BUTT ) );
 
/* record the subpath start point for each border */
stroker->subpath_start = *to;
 
stroker->angle_in = 0;
 
return FT_Err_Ok;
}
 
 
static FT_Error
ft_stroker_add_reverse_left( FT_Stroker stroker,
FT_Bool open )
{
FT_StrokeBorder right = stroker->borders + 0;
FT_StrokeBorder left = stroker->borders + 1;
FT_Int new_points;
FT_Error error = FT_Err_Ok;
 
 
FT_ASSERT( left->start >= 0 );
 
new_points = left->num_points - left->start;
if ( new_points > 0 )
{
error = ft_stroke_border_grow( right, (FT_UInt)new_points );
if ( error )
goto Exit;
 
{
FT_Vector* dst_point = right->points + right->num_points;
FT_Byte* dst_tag = right->tags + right->num_points;
FT_Vector* src_point = left->points + left->num_points - 1;
FT_Byte* src_tag = left->tags + left->num_points - 1;
 
 
while ( src_point >= left->points + left->start )
{
*dst_point = *src_point;
*dst_tag = *src_tag;
 
if ( open )
dst_tag[0] &= ~FT_STROKE_TAG_BEGIN_END;
else
{
FT_Byte ttag =
(FT_Byte)( dst_tag[0] & FT_STROKE_TAG_BEGIN_END );
 
 
/* switch begin/end tags if necessary */
if ( ttag == FT_STROKE_TAG_BEGIN ||
ttag == FT_STROKE_TAG_END )
dst_tag[0] ^= FT_STROKE_TAG_BEGIN_END;
}
 
src_point--;
src_tag--;
dst_point++;
dst_tag++;
}
}
 
left->num_points = left->start;
right->num_points += new_points;
 
right->movable = FALSE;
left->movable = FALSE;
}
 
Exit:
return error;
}
 
 
/* documentation is in ftstroke.h */
 
/* there's a lot of magic in this function! */
FT_EXPORT_DEF( FT_Error )
FT_Stroker_EndSubPath( FT_Stroker stroker )
{
FT_Error error = FT_Err_Ok;
 
 
if ( stroker->subpath_open )
{
FT_StrokeBorder right = stroker->borders;
 
 
/* All right, this is an opened path, we need to add a cap between */
/* right & left, add the reverse of left, then add a final cap */
/* between left & right. */
error = ft_stroker_cap( stroker, stroker->angle_in, 0 );
if ( error )
goto Exit;
 
/* add reversed points from `left' to `right' */
error = ft_stroker_add_reverse_left( stroker, TRUE );
if ( error )
goto Exit;
 
/* now add the final cap */
stroker->center = stroker->subpath_start;
error = ft_stroker_cap( stroker,
stroker->subpath_angle + FT_ANGLE_PI, 0 );
if ( error )
goto Exit;
 
/* Now end the right subpath accordingly. The left one is */
/* rewind and doesn't need further processing. */
ft_stroke_border_close( right, FALSE );
}
else
{
FT_Angle turn;
FT_Int inside_side;
 
 
/* close the path if needed */
if ( stroker->center.x != stroker->subpath_start.x ||
stroker->center.y != stroker->subpath_start.y )
{
error = FT_Stroker_LineTo( stroker, &stroker->subpath_start );
if ( error )
goto Exit;
}
 
/* process the corner */
stroker->angle_out = stroker->subpath_angle;
turn = FT_Angle_Diff( stroker->angle_in,
stroker->angle_out );
 
/* no specific corner processing is required if the turn is 0 */
if ( turn != 0 )
{
/* when we turn to the right, the inside side is 0 */
inside_side = 0;
 
/* otherwise, the inside side is 1 */
if ( turn < 0 )
inside_side = 1;
 
error = ft_stroker_inside( stroker,
inside_side,
stroker->subpath_line_length );
if ( error )
goto Exit;
 
/* process the outside side */
error = ft_stroker_outside( stroker,
1 - inside_side,
stroker->subpath_line_length );
if ( error )
goto Exit;
}
 
/* then end our two subpaths */
ft_stroke_border_close( stroker->borders + 0, FALSE );
ft_stroke_border_close( stroker->borders + 1, TRUE );
}
 
Exit:
return error;
}
 
 
/* documentation is in ftstroke.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Stroker_GetBorderCounts( FT_Stroker stroker,
FT_StrokerBorder border,
FT_UInt *anum_points,
FT_UInt *anum_contours )
{
FT_UInt num_points = 0, num_contours = 0;
FT_Error error;
 
 
if ( !stroker || border > 1 )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
 
error = ft_stroke_border_get_counts( stroker->borders + border,
&num_points, &num_contours );
Exit:
if ( anum_points )
*anum_points = num_points;
 
if ( anum_contours )
*anum_contours = num_contours;
 
return error;
}
 
 
/* documentation is in ftstroke.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Stroker_GetCounts( FT_Stroker stroker,
FT_UInt *anum_points,
FT_UInt *anum_contours )
{
FT_UInt count1, count2, num_points = 0;
FT_UInt count3, count4, num_contours = 0;
FT_Error error;
 
 
error = ft_stroke_border_get_counts( stroker->borders + 0,
&count1, &count2 );
if ( error )
goto Exit;
 
error = ft_stroke_border_get_counts( stroker->borders + 1,
&count3, &count4 );
if ( error )
goto Exit;
 
num_points = count1 + count3;
num_contours = count2 + count4;
 
Exit:
*anum_points = num_points;
*anum_contours = num_contours;
return error;
}
 
 
/* documentation is in ftstroke.h */
 
FT_EXPORT_DEF( void )
FT_Stroker_ExportBorder( FT_Stroker stroker,
FT_StrokerBorder border,
FT_Outline* outline )
{
if ( border == FT_STROKER_BORDER_LEFT ||
border == FT_STROKER_BORDER_RIGHT )
{
FT_StrokeBorder sborder = & stroker->borders[border];
 
 
if ( sborder->valid )
ft_stroke_border_export( sborder, outline );
}
}
 
 
/* documentation is in ftstroke.h */
 
FT_EXPORT_DEF( void )
FT_Stroker_Export( FT_Stroker stroker,
FT_Outline* outline )
{
FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_LEFT, outline );
FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_RIGHT, outline );
}
 
 
/* documentation is in ftstroke.h */
 
/*
* The following is very similar to FT_Outline_Decompose, except
* that we do support opened paths, and do not scale the outline.
*/
FT_EXPORT_DEF( FT_Error )
FT_Stroker_ParseOutline( FT_Stroker stroker,
FT_Outline* outline,
FT_Bool opened )
{
FT_Vector v_last;
FT_Vector v_control;
FT_Vector v_start;
 
FT_Vector* point;
FT_Vector* limit;
char* tags;
 
FT_Error error;
 
FT_Int n; /* index of contour in outline */
FT_UInt first; /* index of first point in contour */
FT_Int tag; /* current point's state */
 
 
if ( !outline || !stroker )
return FT_THROW( Invalid_Argument );
 
FT_Stroker_Rewind( stroker );
 
first = 0;
 
for ( n = 0; n < outline->n_contours; n++ )
{
FT_UInt last; /* index of last point in contour */
 
 
last = outline->contours[n];
limit = outline->points + last;
 
/* skip empty points; we don't stroke these */
if ( last <= first )
{
first = last + 1;
continue;
}
 
v_start = outline->points[first];
v_last = outline->points[last];
 
v_control = v_start;
 
point = outline->points + first;
tags = outline->tags + first;
tag = FT_CURVE_TAG( tags[0] );
 
/* A contour cannot start with a cubic control point! */
if ( tag == FT_CURVE_TAG_CUBIC )
goto Invalid_Outline;
 
/* check first point to determine origin */
if ( tag == FT_CURVE_TAG_CONIC )
{
/* First point is conic control. Yes, this happens. */
if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )
{
/* start at last point if it is on the curve */
v_start = v_last;
limit--;
}
else
{
/* if both first and last points are conic, */
/* start at their middle */
v_start.x = ( v_start.x + v_last.x ) / 2;
v_start.y = ( v_start.y + v_last.y ) / 2;
}
point--;
tags--;
}
 
error = FT_Stroker_BeginSubPath( stroker, &v_start, opened );
if ( error )
goto Exit;
 
while ( point < limit )
{
point++;
tags++;
 
tag = FT_CURVE_TAG( tags[0] );
switch ( tag )
{
case FT_CURVE_TAG_ON: /* emit a single line_to */
{
FT_Vector vec;
 
 
vec.x = point->x;
vec.y = point->y;
 
error = FT_Stroker_LineTo( stroker, &vec );
if ( error )
goto Exit;
continue;
}
 
case FT_CURVE_TAG_CONIC: /* consume conic arcs */
v_control.x = point->x;
v_control.y = point->y;
 
Do_Conic:
if ( point < limit )
{
FT_Vector vec;
FT_Vector v_middle;
 
 
point++;
tags++;
tag = FT_CURVE_TAG( tags[0] );
 
vec = point[0];
 
if ( tag == FT_CURVE_TAG_ON )
{
error = FT_Stroker_ConicTo( stroker, &v_control, &vec );
if ( error )
goto Exit;
continue;
}
 
if ( tag != FT_CURVE_TAG_CONIC )
goto Invalid_Outline;
 
v_middle.x = ( v_control.x + vec.x ) / 2;
v_middle.y = ( v_control.y + vec.y ) / 2;
 
error = FT_Stroker_ConicTo( stroker, &v_control, &v_middle );
if ( error )
goto Exit;
 
v_control = vec;
goto Do_Conic;
}
 
error = FT_Stroker_ConicTo( stroker, &v_control, &v_start );
goto Close;
 
default: /* FT_CURVE_TAG_CUBIC */
{
FT_Vector vec1, vec2;
 
 
if ( point + 1 > limit ||
FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
goto Invalid_Outline;
 
point += 2;
tags += 2;
 
vec1 = point[-2];
vec2 = point[-1];
 
if ( point <= limit )
{
FT_Vector vec;
 
 
vec = point[0];
 
error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &vec );
if ( error )
goto Exit;
continue;
}
 
error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &v_start );
goto Close;
}
}
}
 
Close:
if ( error )
goto Exit;
 
/* don't try to end the path if no segments have been generated */
if ( !stroker->first_point )
{
error = FT_Stroker_EndSubPath( stroker );
if ( error )
goto Exit;
}
 
first = last + 1;
}
 
return FT_Err_Ok;
 
Exit:
return error;
 
Invalid_Outline:
return FT_THROW( Invalid_Outline );
}
 
 
/* declare an extern to access `ft_outline_glyph_class' globally */
/* allocated in `ftglyph.c', and use the FT_OUTLINE_GLYPH_CLASS_GET */
/* macro to access it when FT_CONFIG_OPTION_PIC is defined */
#ifndef FT_CONFIG_OPTION_PIC
extern const FT_Glyph_Class ft_outline_glyph_class;
#endif
#include "basepic.h"
 
 
/* documentation is in ftstroke.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Glyph_Stroke( FT_Glyph *pglyph,
FT_Stroker stroker,
FT_Bool destroy )
{
FT_Error error = FT_ERR( Invalid_Argument );
FT_Glyph glyph = NULL;
FT_Library library = stroker->library;
 
FT_UNUSED( library );
 
 
if ( pglyph == NULL )
goto Exit;
 
glyph = *pglyph;
if ( glyph == NULL || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET )
goto Exit;
 
{
FT_Glyph copy;
 
 
error = FT_Glyph_Copy( glyph, &copy );
if ( error )
goto Exit;
 
glyph = copy;
}
 
{
FT_OutlineGlyph oglyph = (FT_OutlineGlyph)glyph;
FT_Outline* outline = &oglyph->outline;
FT_UInt num_points, num_contours;
 
 
error = FT_Stroker_ParseOutline( stroker, outline, FALSE );
if ( error )
goto Fail;
 
(void)FT_Stroker_GetCounts( stroker, &num_points, &num_contours );
 
FT_Outline_Done( glyph->library, outline );
 
error = FT_Outline_New( glyph->library,
num_points, num_contours, outline );
if ( error )
goto Fail;
 
outline->n_points = 0;
outline->n_contours = 0;
 
FT_Stroker_Export( stroker, outline );
}
 
if ( destroy )
FT_Done_Glyph( *pglyph );
 
*pglyph = glyph;
goto Exit;
 
Fail:
FT_Done_Glyph( glyph );
glyph = NULL;
 
if ( !destroy )
*pglyph = NULL;
 
Exit:
return error;
}
 
 
/* documentation is in ftstroke.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Glyph_StrokeBorder( FT_Glyph *pglyph,
FT_Stroker stroker,
FT_Bool inside,
FT_Bool destroy )
{
FT_Error error = FT_ERR( Invalid_Argument );
FT_Glyph glyph = NULL;
FT_Library library = stroker->library;
 
FT_UNUSED( library );
 
 
if ( pglyph == NULL )
goto Exit;
 
glyph = *pglyph;
if ( glyph == NULL || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET )
goto Exit;
 
{
FT_Glyph copy;
 
 
error = FT_Glyph_Copy( glyph, &copy );
if ( error )
goto Exit;
 
glyph = copy;
}
 
{
FT_OutlineGlyph oglyph = (FT_OutlineGlyph)glyph;
FT_StrokerBorder border;
FT_Outline* outline = &oglyph->outline;
FT_UInt num_points, num_contours;
 
 
border = FT_Outline_GetOutsideBorder( outline );
if ( inside )
{
if ( border == FT_STROKER_BORDER_LEFT )
border = FT_STROKER_BORDER_RIGHT;
else
border = FT_STROKER_BORDER_LEFT;
}
 
error = FT_Stroker_ParseOutline( stroker, outline, FALSE );
if ( error )
goto Fail;
 
(void)FT_Stroker_GetBorderCounts( stroker, border,
&num_points, &num_contours );
 
FT_Outline_Done( glyph->library, outline );
 
error = FT_Outline_New( glyph->library,
num_points,
num_contours,
outline );
if ( error )
goto Fail;
 
outline->n_points = 0;
outline->n_contours = 0;
 
FT_Stroker_ExportBorder( stroker, border, outline );
}
 
if ( destroy )
FT_Done_Glyph( *pglyph );
 
*pglyph = glyph;
goto Exit;
 
Fail:
FT_Done_Glyph( glyph );
glyph = NULL;
 
if ( !destroy )
*pglyph = NULL;
 
Exit:
return error;
}
 
 
/* END */
/programs/develop/libraries/freetype/src/base/ftsynth.c
0,0 → 1,153
/***************************************************************************/
/* */
/* ftsynth.c */
/* */
/* FreeType synthesizing code for emboldening and slanting (body). */
/* */
/* Copyright 2000-2006, 2010, 2012 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 = 0x0366AL;
transform.yy = 0x10000L;
 
FT_Outline_Transform( outline, &transform );
}
 
 
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** EXPERIMENTAL EMBOLDENING 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_EmboldenXY( &slot->outline, xstr, ystr );
}
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.horiAdvance += xstr;
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 */
/programs/develop/libraries/freetype/src/base/ftsystem.c
0,0 → 1,320
/***************************************************************************/
/* */
/* ftsystem.c */
/* */
/* ANSI-specific FreeType low-level system interface (body). */
/* */
/* Copyright 1996-2002, 2006, 2008-2011, 2013 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 */
/* */
/*************************************************************************/
 
#ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT
 
/*************************************************************************/
/* */
/* 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_THROW( 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_THROW( 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_THROW( 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;
}
 
#endif /* !FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT */
 
#ifdef FT_DEBUG_MEMORY
 
extern FT_Int
ft_mem_debug_init( FT_Memory memory );
 
extern void
ft_mem_debug_done( FT_Memory memory );
 
#endif
 
 
/* documentation is in ftobjs.h */
 
FT_BASE_DEF( FT_Memory )
FT_New_Memory( void )
{
FT_Memory memory;
 
 
memory = (FT_Memory)ft_smalloc( sizeof ( *memory ) );
if ( memory )
{
memory->user = 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 */
/programs/develop/libraries/freetype/src/base/fttrigon.c
0,0 → 1,492
/***************************************************************************/
/* */
/* fttrigon.c */
/* */
/* FreeType trigonometric functions (body). */
/* */
/* Copyright 2001-2005, 2012-2013 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 is a fixed-point CORDIC implementation of trigonometric */
/* functions as well as transformations between Cartesian and polar */
/* coordinates. The angles are represented as 16.16 fixed-point values */
/* in degrees, i.e., the angular resolution is 2^-16 degrees. Note that */
/* only vectors longer than 2^16*180/pi (or at least 22 bits) on a */
/* discrete Cartesian grid can have the same or better angular */
/* resolution. Therefore, to maintain this precision, some functions */
/* require an interim upscaling of the vectors, whereas others operate */
/* with 24-bit long vectors directly. */
/* */
/*************************************************************************/
 
#include <ft2build.h>
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_CALC_H
#include FT_TRIGONOMETRY_H
 
 
/* the Cordic shrink factor 0.858785336480436 * 2^32 */
#define FT_TRIG_SCALE 0xDBD95B16UL
 
/* the highest bit in overflow-safe vector components, */
/* MSB of 0.858785336480436 * sqrt(0.5) * 2^30 */
#define FT_TRIG_SAFE_MSB 29
 
/* 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[] =
{
1740967L, 919879L, 466945L, 234379L, 117304L, 58666L, 29335L,
14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L,
57L, 29L, 14L, 7L, 4L, 2L, 1L
};
 
 
#ifdef FT_LONG64
 
/* 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 = FT_ABS( val );
 
v = ( val * (FT_Int64)FT_TRIG_SCALE ) + 0x100000000UL;
val = (FT_Fixed)( v >> 32 );
 
return ( s >= 0 ) ? val : -val;
}
 
#else /* !FT_LONG64 */
 
/* 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 = FT_ABS( 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 = FT_MAX( 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_LONG64 */
 
 
static FT_Int
ft_trig_prenorm( FT_Vector* vec )
{
FT_Pos x, y;
FT_Int shift;
 
 
x = vec->x;
y = vec->y;
 
shift = FT_MSB( FT_ABS( x ) | FT_ABS( y ) );
 
if ( shift <= FT_TRIG_SAFE_MSB )
{
shift = FT_TRIG_SAFE_MSB - shift;
vec->x = (FT_Pos)( (FT_ULong)x << shift );
vec->y = (FT_Pos)( (FT_ULong)y << shift );
}
else
{
shift -= FT_TRIG_SAFE_MSB;
vec->x = x >> shift;
vec->y = y >> shift;
shift = -shift;
}
 
return shift;
}
 
 
static void
ft_trig_pseudo_rotate( FT_Vector* vec,
FT_Angle theta )
{
FT_Int i;
FT_Fixed x, y, xtemp, b;
const FT_Fixed *arctanptr;
 
 
x = vec->x;
y = vec->y;
 
/* Rotate inside [-PI/4,PI/4] sector */
while ( theta < -FT_ANGLE_PI4 )
{
xtemp = y;
y = -x;
x = xtemp;
theta += FT_ANGLE_PI2;
}
 
while ( theta > FT_ANGLE_PI4 )
{
xtemp = -y;
y = x;
x = xtemp;
theta -= FT_ANGLE_PI2;
}
 
arctanptr = ft_trig_arctan_table;
 
/* Pseudorotations, with right shifts */
for ( i = 1, b = 1; i < FT_TRIG_MAX_ITERS; b <<= 1, i++ )
{
if ( theta < 0 )
{
xtemp = x + ( ( y + b ) >> i );
y = y - ( ( x + b ) >> i );
x = xtemp;
theta += *arctanptr++;
}
else
{
xtemp = x - ( ( y + b ) >> i );
y = y + ( ( x + b ) >> i );
x = xtemp;
theta -= *arctanptr++;
}
}
 
vec->x = x;
vec->y = y;
}
 
 
static void
ft_trig_pseudo_polarize( FT_Vector* vec )
{
FT_Angle theta;
FT_Int i;
FT_Fixed x, y, xtemp, b;
const FT_Fixed *arctanptr;
 
 
x = vec->x;
y = vec->y;
 
/* Get the vector into [-PI/4,PI/4] sector */
if ( y > x )
{
if ( y > -x )
{
theta = FT_ANGLE_PI2;
xtemp = y;
y = -x;
x = xtemp;
}
else
{
theta = y > 0 ? FT_ANGLE_PI : -FT_ANGLE_PI;
x = -x;
y = -y;
}
}
else
{
if ( y < -x )
{
theta = -FT_ANGLE_PI2;
xtemp = -y;
y = x;
x = xtemp;
}
else
{
theta = 0;
}
}
 
arctanptr = ft_trig_arctan_table;
 
/* Pseudorotations, with right shifts */
for ( i = 1, b = 1; i < FT_TRIG_MAX_ITERS; b <<= 1, i++ )
{
if ( y > 0 )
{
xtemp = x + ( ( y + b ) >> i );
y = y - ( ( x + b ) >> i );
x = xtemp;
theta += *arctanptr++;
}
else
{
xtemp = x - ( ( y + b ) >> i );
y = y + ( ( x + b ) >> i );
x = xtemp;
theta -= *arctanptr++;
}
}
 
/* 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_SCALE >> 8;
v.y = 0;
ft_trig_pseudo_rotate( &v, angle );
 
return ( v.x + 0x80L ) >> 8;
}
 
 
/* 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_SCALE >> 8;
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_SCALE >> 8;
vec->y = 0;
ft_trig_pseudo_rotate( vec, angle );
vec->x = ( vec->x + 0x80L ) >> 8;
vec->y = ( vec->y + 0x80L ) >> 8;
}
 
 
/* 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 = (FT_Pos)( (FT_ULong)v.x << shift );
vec->y = (FT_Pos)( (FT_ULong)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 FT_ABS( v.y );
}
else if ( v.y == 0 )
{
return FT_ABS( 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 (FT_Fixed)( (FT_UInt32)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 )
: (FT_Fixed)( (FT_UInt32)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 */
/programs/develop/libraries/freetype/src/base/fttype1.c
0,0 → 1,120
/***************************************************************************/
/* */
/* fttype1.c */
/* */
/* FreeType utility file for PS names support (body). */
/* */
/* Copyright 2002-2004, 2011 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_INTERNAL_SERVICE_H
#include FT_SERVICE_POSTSCRIPT_INFO_H
 
 
/* documentation is in t1tables.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Get_PS_Font_Info( FT_Face face,
PS_FontInfoRec* afont_info )
{
FT_Error error = FT_ERR( Invalid_Argument );
 
 
if ( face )
{
FT_Service_PsInfo service = NULL;
 
 
FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
 
if ( service && service->ps_get_font_info )
error = service->ps_get_font_info( face, afont_info );
}
 
return error;
}
 
 
/* documentation is in t1tables.h */
 
FT_EXPORT_DEF( FT_Int )
FT_Has_PS_Glyph_Names( FT_Face face )
{
FT_Int result = 0;
FT_Service_PsInfo service = NULL;
 
 
if ( face )
{
FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
 
if ( service && service->ps_has_glyph_names )
result = service->ps_has_glyph_names( face );
}
 
return result;
}
 
 
/* documentation is in t1tables.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Get_PS_Font_Private( FT_Face face,
PS_PrivateRec* afont_private )
{
FT_Error error = FT_ERR( Invalid_Argument );
 
 
if ( face )
{
FT_Service_PsInfo service = NULL;
 
 
FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
 
if ( service && service->ps_get_font_private )
error = service->ps_get_font_private( face, afont_private );
}
 
return error;
}
 
 
/* documentation is in t1tables.h */
 
FT_EXPORT_DEF( FT_Long )
FT_Get_PS_Font_Value( FT_Face face,
PS_Dict_Keys key,
FT_UInt idx,
void *value,
FT_Long value_len )
{
FT_Int result = 0;
FT_Service_PsInfo service = NULL;
 
 
if ( face )
{
FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
 
if ( service && service->ps_get_font_value )
result = service->ps_get_font_value( face, key, idx,
value, value_len );
}
 
return result;
}
 
 
/* END */
/programs/develop/libraries/freetype/src/base/ftutil.c
0,0 → 1,436
/***************************************************************************/
/* */
/* ftutil.c */
/* */
/* FreeType utility file for memory and list management (body). */
/* */
/* Copyright 2002, 2004-2007, 2013 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_THROW( Out_Of_Memory );
}
else if ( size < 0 )
{
/* may help catch/prevent security issues */
error = FT_THROW( 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_THROW( 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_THROW( 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_THROW( 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;
}
 
 
/* END */
/programs/develop/libraries/freetype/src/base/ftwinfnt.c
0,0 → 1,51
/***************************************************************************/
/* */
/* ftwinfnt.c */
/* */
/* FreeType API for accessing Windows FNT specific info (body). */
/* */
/* Copyright 2003, 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
 
 
#include <ft2build.h>
#include FT_WINFONTS_H
#include FT_INTERNAL_OBJECTS_H
#include FT_SERVICE_WINFNT_H
 
 
/* documentation is in ftwinfnt.h */
 
FT_EXPORT_DEF( FT_Error )
FT_Get_WinFNT_Header( FT_Face face,
FT_WinFNT_HeaderRec *header )
{
FT_Service_WinFnt service;
FT_Error error;
 
 
error = FT_ERR( Invalid_Argument );
 
if ( face != NULL )
{
FT_FACE_LOOKUP_SERVICE( face, service, WINFNT );
 
if ( service != NULL )
{
error = service->get_header( face, header );
}
}
 
return error;
}
 
 
/* END */
/programs/develop/libraries/freetype/src/base/ftxf86.c
0,0 → 1,40
/***************************************************************************/
/* */
/* ftxf86.c */
/* */
/* FreeType utility file for X11 support (body). */
/* */
/* Copyright 2002, 2003, 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
 
 
#include <ft2build.h>
#include FT_XFREE86_H
#include FT_INTERNAL_OBJECTS_H
#include FT_SERVICE_XFREE86_NAME_H
 
 
/* documentation is in ftxf86.h */
 
FT_EXPORT_DEF( const char* )
FT_Get_X11_Font_Format( FT_Face face )
{
const char* result = NULL;
 
 
if ( face )
FT_FACE_FIND_SERVICE( face, result, XF86_NAME );
 
return result;
}
 
 
/* END */
/programs/develop/libraries/freetype/src/base/md5.c
0,0 → 1,295
/*
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
* MD5 Message-Digest Algorithm (RFC 1321).
*
* Homepage:
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
* This software was written by Alexander Peslyak in 2001. No copyright is
* claimed, and the software is hereby placed in the public domain.
* In case this attempt to disclaim copyright and place the software in the
* public domain is deemed null and void, then the software is
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
* general public under the following terms:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* There's ABSOLUTELY NO WARRANTY, express or implied.
*
* (This is a heavily cut-down "BSD license".)
*
* This differs from Colin Plumb's older public domain implementation in that
* no exactly 32-bit integer data type is required (any 32-bit or wider
* unsigned integer data type will do), there's no compile-time endianness
* configuration, and the function prototypes match OpenSSL's. No code from
* Colin Plumb's implementation has been reused; this comment merely compares
* the properties of the two independent implementations.
*
* The primary goals of this implementation are portability and ease of use.
* It is meant to be fast, but not as fast as possible. Some known
* optimizations are not included to reduce source code size and avoid
* compile-time configuration.
*/
 
#ifndef HAVE_OPENSSL
 
#include <string.h>
 
#include "md5.h"
 
/*
* The basic MD5 functions.
*
* F and G are optimized compared to their RFC 1321 definitions for
* architectures that lack an AND-NOT instruction, just like in Colin Plumb's
* implementation.
*/
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
 
/*
* The MD5 transformation for all four rounds.
*/
#define STEP(f, a, b, c, d, x, t, s) \
(a) += f((b), (c), (d)) + (x) + (t); \
(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
(a) += (b);
 
/*
* SET reads 4 input bytes in little-endian byte order and stores them
* in a properly aligned word in host byte order.
*
* The check for little-endian architectures that tolerate unaligned
* memory accesses is just an optimization. Nothing will break if it
* doesn't work.
*/
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
#define SET(n) \
(*(MD5_u32plus *)&ptr[(n) * 4])
#define GET(n) \
SET(n)
#else
#define SET(n) \
(ctx->block[(n)] = \
(MD5_u32plus)ptr[(n) * 4] | \
((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
#define GET(n) \
(ctx->block[(n)])
#endif
 
/*
* This processes one or more 64-byte data blocks, but does NOT update
* the bit counters. There are no alignment requirements.
*/
static void *body(MD5_CTX *ctx, void *data, unsigned long size)
{
unsigned char *ptr;
MD5_u32plus a, b, c, d;
MD5_u32plus saved_a, saved_b, saved_c, saved_d;
 
ptr = (unsigned char *)data;
 
a = ctx->a;
b = ctx->b;
c = ctx->c;
d = ctx->d;
 
do {
saved_a = a;
saved_b = b;
saved_c = c;
saved_d = d;
 
/* Round 1 */
STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
 
/* Round 2 */
STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
 
/* Round 3 */
STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
 
/* Round 4 */
STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
 
a += saved_a;
b += saved_b;
c += saved_c;
d += saved_d;
 
ptr += 64;
} while (size -= 64);
 
ctx->a = a;
ctx->b = b;
ctx->c = c;
ctx->d = d;
 
return ptr;
}
 
void MD5_Init(MD5_CTX *ctx)
{
ctx->a = 0x67452301;
ctx->b = 0xefcdab89;
ctx->c = 0x98badcfe;
ctx->d = 0x10325476;
 
ctx->lo = 0;
ctx->hi = 0;
}
 
void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size)
{
MD5_u32plus saved_lo;
unsigned long used, free;
 
saved_lo = ctx->lo;
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
ctx->hi++;
ctx->hi += size >> 29;
 
used = saved_lo & 0x3f;
 
if (used) {
free = 64 - used;
 
if (size < free) {
memcpy(&ctx->buffer[used], data, size);
return;
}
 
memcpy(&ctx->buffer[used], data, free);
data = (unsigned char *)data + free;
size -= free;
body(ctx, ctx->buffer, 64);
}
 
if (size >= 64) {
data = body(ctx, data, size & ~(unsigned long)0x3f);
size &= 0x3f;
}
 
memcpy(ctx->buffer, data, size);
}
 
void MD5_Final(unsigned char *result, MD5_CTX *ctx)
{
unsigned long used, free;
 
used = ctx->lo & 0x3f;
 
ctx->buffer[used++] = 0x80;
 
free = 64 - used;
 
if (free < 8) {
memset(&ctx->buffer[used], 0, free);
body(ctx, ctx->buffer, 64);
used = 0;
free = 64;
}
 
memset(&ctx->buffer[used], 0, free - 8);
 
ctx->lo <<= 3;
ctx->buffer[56] = ctx->lo;
ctx->buffer[57] = ctx->lo >> 8;
ctx->buffer[58] = ctx->lo >> 16;
ctx->buffer[59] = ctx->lo >> 24;
ctx->buffer[60] = ctx->hi;
ctx->buffer[61] = ctx->hi >> 8;
ctx->buffer[62] = ctx->hi >> 16;
ctx->buffer[63] = ctx->hi >> 24;
 
body(ctx, ctx->buffer, 64);
 
result[0] = ctx->a;
result[1] = ctx->a >> 8;
result[2] = ctx->a >> 16;
result[3] = ctx->a >> 24;
result[4] = ctx->b;
result[5] = ctx->b >> 8;
result[6] = ctx->b >> 16;
result[7] = ctx->b >> 24;
result[8] = ctx->c;
result[9] = ctx->c >> 8;
result[10] = ctx->c >> 16;
result[11] = ctx->c >> 24;
result[12] = ctx->d;
result[13] = ctx->d >> 8;
result[14] = ctx->d >> 16;
result[15] = ctx->d >> 24;
 
memset(ctx, 0, sizeof(*ctx));
}
 
#endif
/programs/develop/libraries/freetype/src/base/md5.h
0,0 → 1,45
/*
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
* MD5 Message-Digest Algorithm (RFC 1321).
*
* Homepage:
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
* This software was written by Alexander Peslyak in 2001. No copyright is
* claimed, and the software is hereby placed in the public domain.
* In case this attempt to disclaim copyright and place the software in the
* public domain is deemed null and void, then the software is
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
* general public under the following terms:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* There's ABSOLUTELY NO WARRANTY, express or implied.
*
* See md5.c for more information.
*/
 
#ifdef HAVE_OPENSSL
#include <openssl/md5.h>
#elif !defined(_MD5_H)
#define _MD5_H
 
/* Any 32-bit or wider unsigned integer data type will do */
typedef unsigned int MD5_u32plus;
 
typedef struct {
MD5_u32plus lo, hi;
MD5_u32plus a, b, c, d;
unsigned char buffer[64];
MD5_u32plus block[16];
} MD5_CTX;
 
extern void MD5_Init(MD5_CTX *ctx);
extern void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size);
extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
 
#endif
/programs/develop/libraries/freetype/src/base/rules.mk
0,0 → 1,99
#
# FreeType 2 base layer configuration rules
#
 
 
# Copyright 1996-2000, 2002-2009, 2013 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.
 
 
# It sets the following variables which are used by the master Makefile
# after the call:
#
# BASE_OBJ_S: The single-object base layer.
# BASE_OBJ_M: A list of all objects for a multiple-objects build.
# BASE_EXT_OBJ: A list of base layer extensions, i.e., components found
# in `freetype/src/base' which are not compiled within the
# base layer proper.
 
 
BASE_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(SRC_DIR)/base)
 
 
# Base layer sources
#
# ftsystem, ftinit, and ftdebug are handled by freetype.mk
#
# All files listed here should be included in `ftbase.c' (for a `single'
# build).
#
BASE_SRC := $(BASE_DIR)/ftadvanc.c \
$(BASE_DIR)/ftcalc.c \
$(BASE_DIR)/ftdbgmem.c \
$(BASE_DIR)/ftgloadr.c \
$(BASE_DIR)/ftobjs.c \
$(BASE_DIR)/ftoutln.c \
$(BASE_DIR)/ftrfork.c \
$(BASE_DIR)/ftsnames.c \
$(BASE_DIR)/ftstream.c \
$(BASE_DIR)/fttrigon.c \
$(BASE_DIR)/ftutil.c
 
 
ifneq ($(ftmac_c),)
BASE_SRC += $(BASE_DIR)/$(ftmac_c)
endif
 
# for simplicity, we also handle `md5.c' (which gets included by `ftobjs.h')
BASE_H := $(BASE_DIR)/ftbase.h \
$(BASE_DIR)/md5.c \
$(BASE_DIR)/md5.h
 
# Base layer `extensions' sources
#
# An extension is added to the library file as a separate object. It is
# then linked to the final executable only if one of its symbols is used by
# the application.
#
BASE_EXT_SRC := $(patsubst %,$(BASE_DIR)/%,$(BASE_EXTENSIONS))
 
# Default extensions objects
#
BASE_EXT_OBJ := $(BASE_EXT_SRC:$(BASE_DIR)/%.c=$(OBJ_DIR)/%.$O)
 
 
# Base layer object(s)
#
# BASE_OBJ_M is used during `multi' builds (each base source file compiles
# to a single object file).
#
# BASE_OBJ_S is used during `single' builds (the whole base layer is
# compiled as a single object file using ftbase.c).
#
BASE_OBJ_M := $(BASE_SRC:$(BASE_DIR)/%.c=$(OBJ_DIR)/%.$O)
BASE_OBJ_S := $(OBJ_DIR)/ftbase.$O
 
# Base layer root source file for single build
#
BASE_SRC_S := $(BASE_DIR)/ftbase.c
 
 
# Base layer - single object build
#
$(BASE_OBJ_S): $(BASE_SRC_S) $(BASE_SRC) $(FREETYPE_H) $(BASE_H)
$(BASE_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(BASE_SRC_S))
 
 
# Multiple objects build + extensions
#
$(OBJ_DIR)/%.$O: $(BASE_DIR)/%.c $(FREETYPE_H) $(BASE_H)
$(BASE_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<)
 
 
# EOF
/programs/develop/libraries/freetype/src/base/.
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property