#include "afhints.h"
#include "aferrors.h"
#include <freetype/internal/ftcalc.h>
#include <freetype/internal/ftdebug.h>
#undef FT_COMPONENT
#define FT_COMPONENT …
FT_LOCAL_DEF( void )
af_sort_pos( FT_UInt count,
FT_Pos* table )
{ … }
FT_LOCAL_DEF( void )
af_sort_and_quantize_widths( FT_UInt* count,
AF_Width table,
FT_Pos threshold )
{ … }
FT_LOCAL_DEF( FT_Error )
af_axis_hints_new_segment( AF_AxisHints axis,
FT_Memory memory,
AF_Segment *asegment )
{ … }
FT_LOCAL_DEF( FT_Error )
af_axis_hints_new_edge( AF_AxisHints axis,
FT_Int fpos,
AF_Direction dir,
FT_Bool top_to_bottom_hinting,
FT_Memory memory,
AF_Edge *anedge )
{ … }
#ifdef FT_DEBUG_AUTOFIT
#include FT_CONFIG_STANDARD_LIBRARY_H
#define AF_DUMP …
static const char*
af_dir_str( AF_Direction dir )
{
const char* result;
switch ( dir )
{
case AF_DIR_UP:
result = "up";
break;
case AF_DIR_DOWN:
result = "down";
break;
case AF_DIR_LEFT:
result = "left";
break;
case AF_DIR_RIGHT:
result = "right";
break;
default:
result = "none";
}
return result;
}
#define AF_INDEX_NUM …
static char*
af_print_idx( char* p,
size_t n,
int idx )
{
if ( idx == -1 )
{
p[0] = '-';
p[1] = '-';
p[2] = '\0';
}
else
ft_snprintf( p, n, "%d", idx );
return p;
}
static int
af_get_segment_index( AF_GlyphHints hints,
int point_idx,
int dimension )
{
AF_AxisHints axis = &hints->axis[dimension];
AF_Point point = hints->points + point_idx;
AF_Segment segments = axis->segments;
AF_Segment limit = segments + axis->num_segments;
AF_Segment segment;
for ( segment = segments; segment < limit; segment++ )
{
if ( segment->first <= segment->last )
{
if ( point >= segment->first && point <= segment->last )
break;
}
else
{
AF_Point p = segment->first;
for (;;)
{
if ( point == p )
goto Exit;
if ( p == segment->last )
break;
p = p->next;
}
}
}
Exit:
if ( segment == limit )
return -1;
return (int)( segment - segments );
}
static int
af_get_edge_index( AF_GlyphHints hints,
int segment_idx,
int dimension )
{
AF_AxisHints axis = &hints->axis[dimension];
AF_Edge edges = axis->edges;
AF_Segment segment = axis->segments + segment_idx;
return segment_idx == -1 ? -1 : AF_INDEX_NUM( segment->edge, edges );
}
static int
af_get_strong_edge_index( AF_GlyphHints hints,
AF_Edge* strong_edges,
int dimension )
{
AF_AxisHints axis = &hints->axis[dimension];
AF_Edge edges = axis->edges;
return AF_INDEX_NUM( strong_edges[dimension], edges );
}
#ifdef __cplusplus
extern "C" {
#endif
void
af_glyph_hints_dump_points( AF_GlyphHints hints,
FT_Bool to_stdout )
{
AF_Point points = hints->points;
AF_Point limit = points + hints->num_points;
AF_Point* contour = hints->contours;
AF_Point* climit = contour + hints->num_contours;
AF_Point point;
AF_DUMP(( "Table of points:\n" ));
if ( hints->num_points )
{
AF_DUMP(( " index hedge hseg vedge vseg flags "
" xorg yorg xscale yscale xfit yfit "
" hbef haft vbef vaft" ));
}
else
AF_DUMP(( " (none)\n" ));
for ( point = points; point < limit; point++ )
{
int point_idx = AF_INDEX_NUM( point, points );
int segment_idx_0 = af_get_segment_index( hints, point_idx, 0 );
int segment_idx_1 = af_get_segment_index( hints, point_idx, 1 );
char buf1[16], buf2[16], buf3[16], buf4[16];
char buf5[16], buf6[16], buf7[16], buf8[16];
if ( contour < climit && *contour == point )
{
AF_DUMP(( "\n" ));
contour++;
}
AF_DUMP(( " %5d %5s %5s %5s %5s %s"
" %5d %5d %7.2f %7.2f %7.2f %7.2f"
" %5s %5s %5s %5s\n",
point_idx,
af_print_idx( buf1, 16,
af_get_edge_index( hints, segment_idx_1, 1 ) ),
af_print_idx( buf2, 16, segment_idx_1 ),
af_print_idx( buf3, 16,
af_get_edge_index( hints, segment_idx_0, 0 ) ),
af_print_idx( buf4, 16, segment_idx_0 ),
( point->flags & AF_FLAG_NEAR )
? " near "
: ( point->flags & AF_FLAG_WEAK_INTERPOLATION )
? " weak "
: "strong",
point->fx,
point->fy,
(double)point->ox / 64,
(double)point->oy / 64,
(double)point->x / 64,
(double)point->y / 64,
af_print_idx( buf5, 16,
af_get_strong_edge_index( hints,
point->before,
1 ) ),
af_print_idx( buf6, 16,
af_get_strong_edge_index( hints,
point->after,
1 ) ),
af_print_idx( buf7, 16,
af_get_strong_edge_index( hints,
point->before,
0 ) ),
af_print_idx( buf8, 16,
af_get_strong_edge_index( hints,
point->after,
0 ) ) ));
}
AF_DUMP(( "\n" ));
}
#ifdef __cplusplus
}
#endif
static const char*
af_edge_flags_to_string( FT_UInt flags )
{
static char temp[32];
int pos = 0;
if ( flags & AF_EDGE_ROUND )
{
ft_memcpy( temp + pos, "round", 5 );
pos += 5;
}
if ( flags & AF_EDGE_SERIF )
{
if ( pos > 0 )
temp[pos++] = ' ';
ft_memcpy( temp + pos, "serif", 5 );
pos += 5;
}
if ( pos == 0 )
return "normal";
temp[pos] = '\0';
return temp;
}
#ifdef __cplusplus
extern "C" {
#endif
void
af_glyph_hints_dump_segments( AF_GlyphHints hints,
FT_Bool to_stdout )
{
FT_Int dimension;
for ( dimension = 1; dimension >= 0; dimension-- )
{
AF_AxisHints axis = &hints->axis[dimension];
AF_Point points = hints->points;
AF_Edge edges = axis->edges;
AF_Segment segments = axis->segments;
AF_Segment limit = segments + axis->num_segments;
AF_Segment seg;
char buf1[16], buf2[16], buf3[16];
AF_DUMP(( "Table of %s segments:\n",
dimension == AF_DIMENSION_HORZ ? "vertical"
: "horizontal" ));
if ( axis->num_segments )
{
AF_DUMP(( " index pos delta dir from to "
" link serif edge"
" height extra flags\n" ));
}
else
AF_DUMP(( " (none)\n" ));
for ( seg = segments; seg < limit; seg++ )
AF_DUMP(( " %5d %5d %5d %5s %4d %4d"
" %4s %5s %4s"
" %6d %5d %11s\n",
AF_INDEX_NUM( seg, segments ),
seg->pos,
seg->delta,
af_dir_str( (AF_Direction)seg->dir ),
AF_INDEX_NUM( seg->first, points ),
AF_INDEX_NUM( seg->last, points ),
af_print_idx( buf1, 16,
AF_INDEX_NUM( seg->link, segments ) ),
af_print_idx( buf2, 16,
AF_INDEX_NUM( seg->serif, segments ) ),
af_print_idx( buf3, 16,
AF_INDEX_NUM( seg->edge, edges ) ),
seg->height,
seg->height - ( seg->max_coord - seg->min_coord ),
af_edge_flags_to_string( seg->flags ) ));
AF_DUMP(( "\n" ));
}
}
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
extern "C" {
#endif
FT_Error
af_glyph_hints_get_num_segments( AF_GlyphHints hints,
FT_Int dimension,
FT_UInt* num_segments )
{
AF_Dimension dim;
AF_AxisHints axis;
dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT;
axis = &hints->axis[dim];
*num_segments = axis->num_segments;
return FT_Err_Ok;
}
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
extern "C" {
#endif
FT_Error
af_glyph_hints_get_segment_offset( AF_GlyphHints hints,
FT_Int dimension,
FT_UInt idx,
FT_Pos *offset,
FT_Bool *is_blue,
FT_Pos *blue_offset )
{
AF_Dimension dim;
AF_AxisHints axis;
AF_Segment seg;
if ( !offset )
return FT_THROW( Invalid_Argument );
dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT;
axis = &hints->axis[dim];
if ( idx >= axis->num_segments )
return FT_THROW( Invalid_Argument );
seg = &axis->segments[idx];
*offset = ( dim == AF_DIMENSION_HORZ ) ? seg->first->fx
: seg->first->fy;
if ( seg->edge )
*is_blue = FT_BOOL( seg->edge->blue_edge );
else
*is_blue = FALSE;
if ( *is_blue )
*blue_offset = seg->edge->blue_edge->org;
else
*blue_offset = 0;
return FT_Err_Ok;
}
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
extern "C" {
#endif
void
af_glyph_hints_dump_edges( AF_GlyphHints hints,
FT_Bool to_stdout )
{
FT_Int dimension;
for ( dimension = 1; dimension >= 0; dimension-- )
{
AF_AxisHints axis = &hints->axis[dimension];
AF_Edge edges = axis->edges;
AF_Edge limit = edges + axis->num_edges;
AF_Edge edge;
char buf1[16], buf2[16];
if ( dimension == AF_DIMENSION_HORZ )
AF_DUMP(( "Table of %s edges (1px=%.2fu, 10u=%.2fpx):\n",
"vertical",
65536 * 64 / (double)hints->x_scale,
10 * (double)hints->x_scale / 65536 / 64 ));
else
AF_DUMP(( "Table of %s edges (1px=%.2fu, 10u=%.2fpx):\n",
"horizontal",
65536 * 64 / (double)hints->y_scale,
10 * (double)hints->y_scale / 65536 / 64 ));
if ( axis->num_edges )
{
AF_DUMP(( " index pos dir link serif"
" blue opos pos flags\n" ));
}
else
AF_DUMP(( " (none)\n" ));
for ( edge = edges; edge < limit; edge++ )
AF_DUMP(( " %5d %7.2f %5s %4s %5s"
" %c %7.2f %7.2f %11s\n",
AF_INDEX_NUM( edge, edges ),
(double)(int)edge->opos / 64,
af_dir_str( (AF_Direction)edge->dir ),
af_print_idx( buf1, 16,
AF_INDEX_NUM( edge->link, edges ) ),
af_print_idx( buf2, 16,
AF_INDEX_NUM( edge->serif, edges ) ),
edge->blue_edge ? 'y' : 'n',
(double)edge->opos / 64,
(double)edge->pos / 64,
af_edge_flags_to_string( edge->flags ) ));
AF_DUMP(( "\n" ));
}
}
#ifdef __cplusplus
}
#endif
#undef AF_DUMP
#endif
FT_LOCAL_DEF( AF_Direction )
af_direction_compute( FT_Pos dx,
FT_Pos dy )
{ … }
FT_LOCAL_DEF( void )
af_glyph_hints_init( AF_GlyphHints hints,
FT_Memory memory )
{ … }
FT_LOCAL_DEF( void )
af_glyph_hints_done( AF_GlyphHints hints )
{ … }
FT_LOCAL_DEF( void )
af_glyph_hints_rescale( AF_GlyphHints hints,
AF_StyleMetrics metrics )
{ … }
FT_LOCAL_DEF( FT_Error )
af_glyph_hints_reload( AF_GlyphHints hints,
FT_Outline* outline )
{ … }
FT_LOCAL_DEF( void )
af_glyph_hints_save( AF_GlyphHints hints,
FT_Outline* outline )
{ … }
FT_LOCAL_DEF( void )
af_glyph_hints_align_edge_points( AF_GlyphHints hints,
AF_Dimension dim )
{ … }
FT_LOCAL_DEF( void )
af_glyph_hints_align_strong_points( AF_GlyphHints hints,
AF_Dimension dim )
{ … }
static void
af_iup_shift( AF_Point p1,
AF_Point p2,
AF_Point ref )
{ … }
static void
af_iup_interp( AF_Point p1,
AF_Point p2,
AF_Point ref1,
AF_Point ref2 )
{ … }
FT_LOCAL_DEF( void )
af_glyph_hints_align_weak_points( AF_GlyphHints hints,
AF_Dimension dim )
{ … }