summaryrefslogtreecommitdiffstats
path: root/src/autofit/afhints.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/autofit/afhints.c')
-rw-r--r--src/autofit/afhints.c1264
1 files changed, 0 insertions, 1264 deletions
diff --git a/src/autofit/afhints.c b/src/autofit/afhints.c
deleted file mode 100644
index 4828706..0000000
--- a/src/autofit/afhints.c
+++ /dev/null
@@ -1,1264 +0,0 @@
-/***************************************************************************/
-/* */
-/* 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++;
-
- Exit:
- *asegment = segment;
- return error;
- }
-
-
- FT_LOCAL( FT_Error )
- af_axis_hints_new_edge( AF_AxisHints axis,
- FT_Int fpos,
- AF_Direction dir,
- 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 )
- {
- if ( edge[-1].fpos < fpos )
- break;
-
- /* we want the edge with same position and minor direction */
- /* to appear before those in the major one in the list */
- if ( edge[-1].fpos == fpos && dir == axis->major_dir )
- break;
-
- edge[0] = edge[-1];
- edge--;
- }
-
- axis->num_edges++;
-
- FT_ZERO( edge );
- edge->fpos = (FT_Short)fpos;
- edge->dir = (FT_Char)dir;
-
- 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" );
- }
-
-
- static const char*
- af_edge_flags_to_string( AF_Edge_Flags flags )
- {
- static char temp[32];
- int pos = 0;
-
-
- if ( flags & AF_EDGE_ROUND )
- {
- memcpy( temp + pos, "round", 5 );
- pos += 5;
- }
- if ( flags & AF_EDGE_SERIF )
- {
- if ( pos > 0 )
- temp[pos++] = ' ';
- memcpy( temp + pos, "serif", 5 );
- pos += 5;
- }
- if ( pos == 0 )
- return "normal";
-
- temp[pos] = 0;
-
- return temp;
- }
-
-
- /* 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 | flags ]\n" );
-
- for ( seg = segments; seg < limit; seg++ )
- {
- printf ( " [ %5d | %5.2g | %5s | %4d | %5d | %5d | %5d | %s ]\n",
- seg - segments,
- dimension == AF_DIMENSION_HORZ ? (int)seg->first->ox / 64.0
- : (int)seg->first->oy / 64.0,
- 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 ),
- af_edge_flags_to_string( seg->flags ) );
- }
- 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 | flags ]\n" );
-
- for ( edge = edges; edge < limit; edge++ )
- {
- printf ( " [ %5d | %5.2g | %5s | %4d |"
- " %5d | %c | %5.2f | %5.2f | %s ]\n",
- edge - edges,
- (int)edge->opos / 64.0,
- 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,
- af_edge_flags_to_string( edge->flags ) );
- }
- 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 )
- {
- 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 *= 14;
- if ( FT_ABS( ll ) <= FT_ABS( ss ) )
- dir = AF_DIR_NONE;
-
- return dir;
- }
-
-
- /* compute all inflex points in a given glyph */
-
- 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
- {
- do
- {
- end = after;
- after = after->next;
- if ( after == first )
- finished = 1;
-
- out_x = after->fx - end->fx;
- out_y = after->fy - end->fy;
-
- } while ( out_x == 0 && out_y == 0 );
-
- orient_cur = ft_corner_orientation( in_x, in_y, out_x, out_y );
-
- } while ( orient_cur == 0 );
-
- if ( ( orient_prev + orient_cur ) == 0 )
- {
- /* we have an inflection point here */
- do
- {
- start->flags |= AF_FLAG_INFLECTION;
- start = start->next;
-
- } while ( start != end );
-
- start->flags |= AF_FLAG_INFLECTION;
- }
-
- start = end;
- end = after;
-
- orient_prev = orient_cur;
- in_x = out_x;
- in_y = out_y;
-
- } while ( !finished );
-
- Skip:
- ;
- }
- }
-
-
- FT_LOCAL_DEF( void )
- af_glyph_hints_init( AF_GlyphHints hints,
- FT_Memory memory )
- {
- FT_ZERO( hints );
- hints->memory = memory;
- }
-
-
- FT_LOCAL_DEF( void )
- af_glyph_hints_done( AF_GlyphHints hints )
- {
- if ( hints && hints->memory )
- {
- FT_Memory memory = hints->memory;
- int dim;
-
-
- /*
- * note that we don't need to free the segment and edge
- * buffers, since they are really within the hints->points array
- */
- for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
- {
- AF_AxisHints axis = &hints->axis[dim];
-
-
- axis->num_segments = 0;
- axis->max_segments = 0;
- FT_FREE( axis->segments );
-
- axis->num_edges = 0;
- axis->max_edges = 0;
- FT_FREE( axis->edges );
- }
-
- FT_FREE( hints->contours );
- hints->max_contours = 0;
- hints->num_contours = 0;
-
- FT_FREE( hints->points );
- hints->num_points = 0;
- hints->max_points = 0;
-
- hints->memory = NULL;
- }
- }
-
-
- FT_LOCAL_DEF( void )
- af_glyph_hints_rescale( AF_GlyphHints hints,
- AF_ScriptMetrics metrics )
- {
- hints->metrics = metrics;
- hints->scaler_flags = metrics->scaler.flags;
- }
-
-
- FT_LOCAL_DEF( FT_Error )
- af_glyph_hints_reload( AF_GlyphHints hints,
- FT_Outline* outline,
- FT_Bool get_inflections )
- {
- FT_Error error = AF_Err_Ok;
- AF_Point points;
- FT_UInt old_max, new_max;
- FT_Fixed x_scale = hints->x_scale;
- FT_Fixed y_scale = hints->y_scale;
- FT_Pos x_delta = hints->x_delta;
- FT_Pos y_delta = hints->y_delta;
- FT_Memory memory = hints->memory;
-
-
- hints->num_points = 0;
- hints->num_contours = 0;
-
- hints->axis[0].num_segments = 0;
- hints->axis[0].num_edges = 0;
- hints->axis[1].num_segments = 0;
- hints->axis[1].num_edges = 0;
-
- /* first of all, reallocate the contours array when necessary */
- new_max = (FT_UInt)outline->n_contours;
- old_max = hints->max_contours;
- if ( new_max > old_max )
- {
- new_max = ( new_max + 3 ) & ~3;
-
- if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
- goto Exit;
-
- hints->max_contours = new_max;
- }
-
- /*
- * then reallocate the points arrays if necessary --
- * note that we reserve two additional point positions, used to
- * hint metrics appropriately
- */
- new_max = (FT_UInt)( outline->n_points + 2 );
- old_max = hints->max_points;
- if ( new_max > old_max )
- {
- new_max = ( new_max + 2 + 7 ) & ~7;
-
- if ( FT_RENEW_ARRAY( hints->points, old_max, new_max ) )
- goto Exit;
-
- hints->max_points = new_max;
- }
-
- hints->num_points = outline->n_points;
- hints->num_contours = outline->n_contours;
-
- /* We can't rely on the value of `FT_Outline.flags' to know the fill */
- /* direction used for a glyph, given that some fonts are broken (e.g., */
- /* the Arphic ones). We thus recompute it each time we need to. */
- /* */
- hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_UP;
- hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_LEFT;
-
- if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_POSTSCRIPT )
- {
- hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_DOWN;
- hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_RIGHT;
- }
-
- hints->x_scale = x_scale;
- hints->y_scale = y_scale;
- hints->x_delta = x_delta;
- hints->y_delta = y_delta;
-
- hints->xmin_delta = 0;
- hints->xmax_delta = 0;
-
- points = hints->points;
- if ( hints->num_points == 0 )
- goto Exit;
-
- {
- AF_Point point;
- AF_Point point_limit = points + hints->num_points;
-
-
- /* compute coordinates & Bezier flags, next and prev */
- {
- FT_Vector* vec = outline->points;
- char* tag = outline->tags;
- AF_Point first = points;
- AF_Point end = points + outline->contours[0];
- AF_Point prev = end;
- FT_Int contour_index = 0;
-
-
- for ( point = points; point < point_limit; point++, vec++, tag++ )
- {
- point->fx = (FT_Short)vec->x;
- point->fy = (FT_Short)vec->y;
- point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta;
- point->oy = point->y = FT_MulFix( vec->y, y_scale ) + y_delta;
-
- switch ( FT_CURVE_TAG( *tag ) )
- {
- case FT_CURVE_TAG_CONIC:
- point->flags = AF_FLAG_CONIC;
- break;
- case FT_CURVE_TAG_CUBIC:
- point->flags = AF_FLAG_CUBIC;
- break;
- default:
- point->flags = 0;
- }
-
- point->prev = prev;
- prev->next = point;
- prev = point;
-
- if ( point == end )
- {
- if ( ++contour_index < outline->n_contours )
- {
- first = point + 1;
- end = points + outline->contours[contour_index];
- prev = end;
- }
- }
- }
- }
-
- /* set-up the contours array */
- {
- AF_Point* contour = hints->contours;
- AF_Point* contour_limit = contour + hints->num_contours;
- short* end = outline->contours;
- short idx = 0;
-
-
- for ( ; contour < contour_limit; contour++, end++ )
- {
- contour[0] = points + idx;
- idx = (short)( end[0] + 1 );
- }
- }
-
- /* compute directions of in & out vectors */
- {
- AF_Point first = points;
- AF_Point prev = NULL;
- FT_Pos in_x = 0;
- FT_Pos in_y = 0;
- AF_Direction in_dir = AF_DIR_NONE;
-
-
- for ( point = points; point < point_limit; point++ )
- {
- AF_Point next;
- FT_Pos out_x, out_y;
-
-
- if ( point == first )
- {
- prev = first->prev;
- in_x = first->fx - prev->fx;
- in_y = first->fy - prev->fy;
- in_dir = af_direction_compute( in_x, in_y );
- first = prev + 1;
- }
-
- point->in_dir = (FT_Char)in_dir;
-
- next = point->next;
- out_x = next->fx - point->fx;
- out_y = next->fy - point->fy;
-
- in_dir = af_direction_compute( out_x, out_y );
- point->out_dir = (FT_Char)in_dir;
-
- if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) )
- {
- Is_Weak_Point:
- point->flags |= AF_FLAG_WEAK_INTERPOLATION;
- }
- else if ( point->out_dir == point->in_dir )
- {
- if ( point->out_dir != AF_DIR_NONE )
- goto Is_Weak_Point;
-
- if ( ft_corner_is_flat( in_x, in_y, out_x, out_y ) )
- goto Is_Weak_Point;
- }
- else if ( point->in_dir == -point->out_dir )
- goto Is_Weak_Point;
-
- in_x = out_x;
- in_y = out_y;
- prev = point;
- }
- }
- }
-
- /* compute inflection points -- */
- /* disabled due to no longer perceived benefits */
- if ( 0 && get_inflections )
- af_glyph_hints_compute_inflections( hints );
-
- Exit:
- return error;
- }
-
-
- FT_LOCAL_DEF( void )
- af_glyph_hints_save( AF_GlyphHints hints,
- FT_Outline* outline )
- {
- AF_Point point = hints->points;
- AF_Point limit = point + hints->num_points;
- FT_Vector* vec = outline->points;
- char* tag = outline->tags;
-
-
- for ( ; point < limit; point++, vec++, tag++ )
- {
- vec->x = point->x;
- vec->y = point->y;
-
- if ( point->flags & AF_FLAG_CONIC )
- tag[0] = FT_CURVE_TAG_CONIC;
- else if ( point->flags & AF_FLAG_CUBIC )
- tag[0] = FT_CURVE_TAG_CUBIC;
- else
- tag[0] = FT_CURVE_TAG_ON;
- }
- }
-
-
- /****************************************************************
- *
- * EDGE POINT GRID-FITTING
- *
- ****************************************************************/
-
-
- FT_LOCAL_DEF( void )
- af_glyph_hints_align_edge_points( AF_GlyphHints hints,
- AF_Dimension dim )
- {
- AF_AxisHints axis = & hints->axis[dim];
- AF_Segment segments = axis->segments;
- AF_Segment segment_limit = segments + axis->num_segments;
- AF_Segment seg;
-
-
- if ( dim == AF_DIMENSION_HORZ )
- {
- for ( seg = segments; seg < segment_limit; seg++ )
- {
- AF_Edge edge = seg->edge;
- AF_Point point, first, last;
-
-
- if ( edge == NULL )
- continue;
-
- first = seg->first;
- last = seg->last;
- point = first;
- for (;;)
- {
- point->x = edge->pos;
- point->flags |= AF_FLAG_TOUCH_X;
-
- if ( point == last )
- break;
-
- point = point->next;
-
- }
- }
- }
- else
- {
- for ( seg = segments; seg < segment_limit; seg++ )
- {
- AF_Edge edge = seg->edge;
- AF_Point point, first, last;
-
-
- if ( edge == NULL )
- continue;
-
- first = seg->first;
- last = seg->last;
- point = first;
- for (;;)
- {
- point->y = edge->pos;
- point->flags |= AF_FLAG_TOUCH_Y;
-
- if ( point == last )
- break;
-
- point = point->next;
- }
- }
- }
- }
-
-
- /****************************************************************
- *
- * STRONG POINT INTERPOLATION
- *
- ****************************************************************/
-
-
- /* hint the strong points -- this is equivalent to the TrueType `IP' */
- /* hinting instruction */
-
- FT_LOCAL_DEF( void )
- af_glyph_hints_align_strong_points( AF_GlyphHints hints,
- AF_Dimension dim )
- {
- AF_Point points = hints->points;
- AF_Point point_limit = points + hints->num_points;
- AF_AxisHints axis = &hints->axis[dim];
- AF_Edge edges = axis->edges;
- AF_Edge edge_limit = edges + axis->num_edges;
- AF_Flags touch_flag;
-
-
- if ( dim == AF_DIMENSION_HORZ )
- touch_flag = AF_FLAG_TOUCH_X;
- else
- touch_flag = AF_FLAG_TOUCH_Y;
-
- if ( edges < edge_limit )
- {
- AF_Point point;
- AF_Edge edge;
-
-
- for ( point = points; point < point_limit; point++ )
- {
- FT_Pos u, ou, fu; /* point position */
- FT_Pos delta;
-
-
- if ( point->flags & touch_flag )
- continue;
-
- /* if this point is candidate to weak interpolation, we */
- /* interpolate it after all strong points have been processed */
-
- if ( ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) &&
- !( point->flags & AF_FLAG_INFLECTION ) )
- continue;
-
- if ( dim == AF_DIMENSION_VERT )
- {
- u = point->fy;
- ou = point->oy;
- }
- else
- {
- u = point->fx;
- ou = point->ox;
- }
-
- fu = u;
-
- /* is the point before the first edge? */
- edge = edges;
- delta = edge->fpos - u;
- if ( delta >= 0 )
- {
- u = edge->pos - ( edge->opos - ou );
- goto Store_Point;
- }
-
- /* is the point after the last edge? */
- edge = edge_limit - 1;
- delta = u - edge->fpos;
- if ( delta >= 0 )
- {
- u = edge->pos + ( ou - edge->opos );
- goto Store_Point;
- }
-
- {
- FT_UInt min, max, mid;
- FT_Pos fpos;
-
-
- /* find enclosing edges */
- min = 0;
- max = edge_limit - edges;
-
-#if 1
- /* for small edge counts, a linear search is better */
- if ( max <= 8 )
- {
- FT_UInt nn;
-
- for ( nn = 0; nn < max; nn++ )
- if ( edges[nn].fpos >= u )
- break;
-
- if ( edges[nn].fpos == u )
- {
- u = edges[nn].pos;
- goto Store_Point;
- }
- min = nn;
- }
- else
-#endif
- while ( min < max )
- {
- mid = ( max + min ) >> 1;
- edge = edges + mid;
- fpos = edge->fpos;
-
- if ( u < fpos )
- max = mid;
- else if ( u > fpos )
- min = mid + 1;
- else
- {
- /* we are on the edge */
- u = edge->pos;
- goto Store_Point;
- }
- }
-
- {
- AF_Edge before = edges + min - 1;
- AF_Edge after = edges + min + 0;
-
-
- /* assert( before && after && before != after ) */
- if ( before->scale == 0 )
- before->scale = FT_DivFix( after->pos - before->pos,
- after->fpos - before->fpos );
-
- u = before->pos + FT_MulFix( fu - before->fpos,
- before->scale );
- }
- }
-
- Store_Point:
- /* save the point position */
- if ( dim == AF_DIMENSION_HORZ )
- point->x = u;
- else
- point->y = u;
-
- point->flags |= touch_flag;
- }
- }
- }
-
-
- /****************************************************************
- *
- * WEAK POINT INTERPOLATION
- *
- ****************************************************************/
-
-
- static void
- af_iup_shift( AF_Point p1,
- AF_Point p2,
- AF_Point ref )
- {
- AF_Point p;
- FT_Pos delta = ref->u - ref->v;
-
- if ( delta == 0 )
- return;
-
- for ( p = p1; p < ref; p++ )
- p->u = p->v + delta;
-
- for ( p = ref + 1; p <= p2; p++ )
- p->u = p->v + delta;
- }
-
-
- static void
- af_iup_interp( AF_Point p1,
- AF_Point p2,
- AF_Point ref1,
- AF_Point ref2 )
- {
- AF_Point p;
- FT_Pos u;
- FT_Pos v1 = ref1->v;
- FT_Pos v2 = ref2->v;
- FT_Pos d1 = ref1->u - v1;
- FT_Pos d2 = ref2->u - v2;
-
-
- if ( p1 > p2 )
- return;
-
- if ( v1 == v2 )
- {
- for ( p = p1; p <= p2; p++ )
- {
- u = p->v;
-
- if ( u <= v1 )
- u += d1;
- else
- u += d2;
-
- p->u = u;
- }
- return;
- }
-
- if ( v1 < v2 )
- {
- for ( p = p1; p <= p2; p++ )
- {
- u = p->v;
-
- if ( u <= v1 )
- u += d1;
- else if ( u >= v2 )
- u += d2;
- else
- u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
-
- p->u = u;
- }
- }
- else
- {
- for ( p = p1; p <= p2; p++ )
- {
- u = p->v;
-
- if ( u <= v2 )
- u += d2;
- else if ( u >= v1 )
- u += d1;
- else
- u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
-
- p->u = u;
- }
- }
- }
-
-
- FT_LOCAL_DEF( void )
- af_glyph_hints_align_weak_points( AF_GlyphHints hints,
- AF_Dimension dim )
- {
- AF_Point points = hints->points;
- AF_Point point_limit = points + hints->num_points;
- AF_Point* contour = hints->contours;
- AF_Point* contour_limit = contour + hints->num_contours;
- AF_Flags touch_flag;
- AF_Point point;
- AF_Point end_point;
- AF_Point first_point;
-
-
- /* PASS 1: Move segment points to edge positions */
-
- if ( dim == AF_DIMENSION_HORZ )
- {
- touch_flag = AF_FLAG_TOUCH_X;
-
- for ( point = points; point < point_limit; point++ )
- {
- point->u = point->x;
- point->v = point->ox;
- }
- }
- else
- {
- touch_flag = AF_FLAG_TOUCH_Y;
-
- for ( point = points; point < point_limit; point++ )
- {
- point->u = point->y;
- point->v = point->oy;
- }
- }
-
- point = points;
-
- for ( ; contour < contour_limit; contour++ )
- {
- AF_Point first_touched, last_touched;
-
-
- point = *contour;
- end_point = point->prev;
- first_point = point;
-
- /* find first touched point */
- for (;;)
- {
- if ( point > end_point ) /* no touched point in contour */
- goto NextContour;
-
- if ( point->flags & touch_flag )
- break;
-
- point++;
- }
-
- first_touched = point;
- last_touched = point;
-
- for (;;)
- {
- FT_ASSERT( point <= end_point &&
- ( point->flags & touch_flag ) != 0 );
-
- /* skip any touched neighbhours */
- while ( point < end_point && ( point[1].flags & touch_flag ) != 0 )
- point++;
-
- last_touched = point;
-
- /* find the next touched point, if any */
- point ++;
- for (;;)
- {
- if ( point > end_point )
- goto EndContour;
-
- if ( ( point->flags & touch_flag ) != 0 )
- break;
-
- point++;
- }
-
- /* interpolate between last_touched and point */
- af_iup_interp( last_touched + 1, point - 1,
- last_touched, point );
- }
-
- EndContour:
- /* special case: only one point was touched */
- if ( last_touched == first_touched )
- {
- af_iup_shift( first_point, end_point, first_touched );
- }
- else /* interpolate the last part */
- {
- if ( last_touched < end_point )
- af_iup_interp( last_touched + 1, end_point,
- last_touched, first_touched );
-
- if ( first_touched > points )
- af_iup_interp( first_point, first_touched - 1,
- last_touched, first_touched );
- }
-
- NextContour:
- ;
- }
-
- /* now save the interpolated values back to x/y */
- if ( dim == AF_DIMENSION_HORZ )
- {
- for ( point = points; point < point_limit; point++ )
- point->x = point->u;
- }
- else
- {
- for ( point = points; point < point_limit; point++ )
- point->y = point->u;
- }
- }
-
-
-#ifdef AF_USE_WARPER
-
- FT_LOCAL_DEF( void )
- af_glyph_hints_scale_dim( AF_GlyphHints hints,
- AF_Dimension dim,
- FT_Fixed scale,
- FT_Pos delta )
- {
- AF_Point points = hints->points;
- AF_Point points_limit = points + hints->num_points;
- AF_Point point;
-
-
- if ( dim == AF_DIMENSION_HORZ )
- {
- for ( point = points; point < points_limit; point++ )
- point->x = FT_MulFix( point->fx, scale ) + delta;
- }
- else
- {
- for ( point = points; point < points_limit; point++ )
- point->y = FT_MulFix( point->fy, scale ) + delta;
- }
- }
-
-#endif /* AF_USE_WARPER */
-
-/* END */