📄 afhints.c
字号:
/***************************************************************************//* *//* afhints.c *//* *//* Auto-fitter hinting routines (body). *//* *//* Copyright 2003, 2004, 2005, 2006, 2007 by *//* David Turner, Robert Wilhelm, and Werner Lemberg. *//* *//* This file is part of the FreeType project, and may only be used, *//* modified, and distributed under the terms of the FreeType project *//* license, LICENSE.TXT. By continuing to use, modify, or distribute *//* this file you indicate that you have read the license and *//* understand and accept it fully. *//* *//***************************************************************************/#include "afhints.h"#include "aferrors.h"#include FT_INTERNAL_CALC_H FT_LOCAL_DEF( FT_Error ) af_axis_hints_new_segment( AF_AxisHints axis, FT_Memory memory, AF_Segment *asegment ) { FT_Error error = AF_Err_Ok; AF_Segment segment = NULL; if ( axis->num_segments >= axis->max_segments ) { FT_Int old_max = axis->max_segments; FT_Int new_max = old_max; FT_Int big_max = FT_INT_MAX / sizeof ( *segment ); if ( old_max >= big_max ) { error = AF_Err_Out_Of_Memory; goto Exit; } new_max += ( new_max >> 2 ) + 4; if ( new_max < old_max || new_max > big_max ) new_max = big_max; if ( FT_RENEW_ARRAY( axis->segments, old_max, new_max ) ) goto Exit; axis->max_segments = new_max; } segment = axis->segments + axis->num_segments++;#if 0 FT_ZERO( segment );#endif Exit: *asegment = segment; return error; } FT_LOCAL( FT_Error ) af_axis_hints_new_edge( AF_AxisHints axis, FT_Int fpos, FT_Memory memory, AF_Edge *aedge ) { FT_Error error = AF_Err_Ok; AF_Edge edge = NULL; AF_Edge edges; if ( axis->num_edges >= axis->max_edges ) { FT_Int old_max = axis->max_edges; FT_Int new_max = old_max; FT_Int big_max = FT_INT_MAX / sizeof ( *edge ); if ( old_max >= big_max ) { error = AF_Err_Out_Of_Memory; goto Exit; } new_max += ( new_max >> 2 ) + 4; if ( new_max < old_max || new_max > big_max ) new_max = big_max; if ( FT_RENEW_ARRAY( axis->edges, old_max, new_max ) ) goto Exit; axis->max_edges = new_max; } edges = axis->edges; edge = edges + axis->num_edges; while ( edge > edges && edge[-1].fpos > fpos ) { edge[0] = edge[-1]; edge--; } axis->num_edges++; FT_ZERO( edge ); edge->fpos = (FT_Short)fpos; Exit: *aedge = edge; return error; }#ifdef AF_DEBUG#include <stdio.h> 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( ptr, base ) ( (ptr) ? ( (ptr) - (base) ) : -1 ) void af_glyph_hints_dump_points( AF_GlyphHints hints ) { AF_Point points = hints->points; AF_Point limit = points + hints->num_points; AF_Point point; printf( "Table of points:\n" ); printf( " [ index | xorg | yorg | xscale | yscale " "| xfit | yfit | flags ]\n" ); for ( point = points; point < limit; point++ ) { printf( " [ %5d | %5d | %5d | %-5.2f | %-5.2f " "| %-5.2f | %-5.2f | %c%c%c%c%c%c ]\n", point - points, point->fx, point->fy, point->ox/64.0, point->oy/64.0, point->x/64.0, point->y/64.0, ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ? 'w' : ' ', ( point->flags & AF_FLAG_INFLECTION ) ? 'i' : ' ', ( point->flags & AF_FLAG_EXTREMA_X ) ? '<' : ' ', ( point->flags & AF_FLAG_EXTREMA_Y ) ? 'v' : ' ', ( point->flags & AF_FLAG_ROUND_X ) ? '(' : ' ', ( point->flags & AF_FLAG_ROUND_Y ) ? 'u' : ' '); } printf( "\n" ); } /* A function to dump the array of linked segments. */ void af_glyph_hints_dump_segments( AF_GlyphHints hints ) { FT_Int dimension; for ( dimension = 1; dimension >= 0; dimension-- ) { AF_AxisHints axis = &hints->axis[dimension]; AF_Segment segments = axis->segments; AF_Segment limit = segments + axis->num_segments; AF_Segment seg; printf ( "Table of %s segments:\n", dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ); printf ( " [ index | pos | dir | link | serif |" " height | extra ]\n" ); for ( seg = segments; seg < limit; seg++ ) { printf ( " [ %5d | %4d | %5s | %4d | %5d | %5d | %5d ]\n", seg - segments, (int)seg->pos, af_dir_str( (AF_Direction)seg->dir ), AF_INDEX_NUM( seg->link, segments ), AF_INDEX_NUM( seg->serif, segments ), seg->height, seg->height - ( seg->max_coord - seg->min_coord ) ); } printf( "\n" ); } } void af_glyph_hints_dump_edges( AF_GlyphHints hints ) { 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; /* * note: AF_DIMENSION_HORZ corresponds to _vertical_ edges * since they have constant a X coordinate. */ printf ( "Table of %s edges:\n", dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ); printf ( " [ index | pos | dir | link |" " serif | blue | opos | pos ]\n" ); for ( edge = edges; edge < limit; edge++ ) { printf ( " [ %5d | %4d | %5s | %4d |" " %5d | %c | %5.2f | %5.2f ]\n", edge - edges, (int)edge->fpos, af_dir_str( (AF_Direction)edge->dir ), AF_INDEX_NUM( edge->link, edges ), AF_INDEX_NUM( edge->serif, edges ), edge->blue_edge ? 'y' : 'n', edge->opos / 64.0, edge->pos / 64.0 ); } printf( "\n" ); } }#else /* !AF_DEBUG */ /* these empty stubs are only used to link the `ftgrid' test program */ /* when debugging is disabled */ void af_glyph_hints_dump_points( AF_GlyphHints hints ) { FT_UNUSED( hints ); } void af_glyph_hints_dump_segments( AF_GlyphHints hints ) { FT_UNUSED( hints ); } void af_glyph_hints_dump_edges( AF_GlyphHints hints ) { FT_UNUSED( hints ); }#endif /* !AF_DEBUG */ /* compute the direction value of a given vector */ FT_LOCAL_DEF( AF_Direction ) af_direction_compute( FT_Pos dx, FT_Pos dy ) {#if 1 FT_Pos ll, ss; /* long and short arm lengths */ AF_Direction dir; /* candidate direction */ if ( dy >= dx ) { if ( dy >= -dx ) { dir = AF_DIR_UP; ll = dy; ss = dx; } else { dir = AF_DIR_LEFT; ll = -dx; ss = dy; } } else /* dy < dx */ { if ( dy >= -dx ) { dir = AF_DIR_RIGHT; ll = dx; ss = dy; } else { dir = AF_DIR_DOWN; ll = dy; ss = dx; } } ss *= 12; if ( FT_ABS(ll) <= FT_ABS(ss) ) dir = AF_DIR_NONE; return dir;#else /* 0 */ AF_Direction dir; FT_Pos ax = FT_ABS( dx ); FT_Pos ay = FT_ABS( dy ); dir = AF_DIR_NONE; /* atan(1/12) == 4.7 degrees */ /* test for vertical direction */ if ( ax * 12 < ay ) { dir = dy > 0 ? AF_DIR_UP : AF_DIR_DOWN; } /* test for horizontal direction */ else if ( ay * 12 < ax ) { dir = dx > 0 ? AF_DIR_RIGHT : AF_DIR_LEFT; } return dir;#endif /* 0 */ } /* compute all inflex points in a given glyph */#if 1 static void af_glyph_hints_compute_inflections( AF_GlyphHints hints ) { AF_Point* contour = hints->contours; AF_Point* contour_limit = contour + hints->num_contours; /* do each contour separately */ for ( ; contour < contour_limit; contour++ ) { AF_Point point = contour[0]; AF_Point first = point; AF_Point start = point; AF_Point end = point; AF_Point before; AF_Point after; FT_Pos in_x, in_y, out_x, out_y; AF_Angle orient_prev, orient_cur; FT_Int finished = 0; /* compute first segment in contour */ first = point; start = end = first; do { end = end->next; if ( end == first ) goto Skip; in_x = end->fx - start->fx; in_y = end->fy - start->fy; } while ( in_x == 0 && in_y == 0 ); /* extend the segment start whenever possible */ before = start; do { do { start = before; before = before->prev; if ( before == first ) goto Skip; out_x = start->fx - before->fx; out_y = start->fy - before->fy; } while ( out_x == 0 && out_y == 0 ); orient_prev = ft_corner_orientation( in_x, in_y, out_x, out_y ); } while ( orient_prev == 0 ); first = start; in_x = out_x; in_y = out_y; /* now process all segments in the contour */ do { /* first, extend current segment's end whenever possible */ after = end; do {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -