📄 ahhint.c
字号:
{ /* we are on the edge */ u = edge->pos; goto Store_Point; } } { AH_Edge before = edges + min - 1; AH_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 ); } }#else /* !0 */ /* otherwise, interpolate the point in between */ { AH_Edge before = 0; AH_Edge after = 0; for ( edge = edges; edge < edge_limit; edge++ ) { if ( u == edge->fpos ) { u = edge->pos; goto Store_Point; } if ( u < edge->fpos ) break; before = edge; } for ( edge = edge_limit - 1; edge >= edges; edge-- ) { if ( u == edge->fpos ) { u = edge->pos; goto Store_Point; } if ( u > edge->fpos ) break; after = edge; } 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 ); }#endif /* !0 */ Store_Point: /* save the point position */ if ( dimension ) point->y = u; else point->x = u; point->flags |= touch_flag; } edges = outline->vert_edges; edge_limit = edges + outline->num_vedges; touch_flag = AH_FLAG_TOUCH_X; } }#ifndef AH_OPTION_NO_WEAK_INTERPOLATION static void ah_iup_shift( AH_Point p1, AH_Point p2, AH_Point ref ) { AH_Point p; FT_Pos delta = ref->u - ref->v; 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 ah_iup_interp( AH_Point p1, AH_Point p2, AH_Point ref1, AH_Point ref2 ) { AH_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; } } } /* interpolate weak points -- this is equivalent to the TrueType `IUP' */ /* hinting instruction */ static void ah_hinter_align_weak_points( AH_Hinter hinter ) { AH_Outline outline = hinter->glyph; FT_Int dimension; AH_Point points; AH_Point point_limit; AH_Point* contour_limit; AH_Flags touch_flag; points = outline->points; point_limit = points + outline->num_points; /* PASS 1: Move segment points to edge positions */ touch_flag = AH_FLAG_TOUCH_Y; contour_limit = outline->contours + outline->num_contours; ah_setup_uv( outline, AH_UV_OY ); for ( dimension = 1; dimension >= 0; dimension-- ) { AH_Point point; AH_Point end_point; AH_Point first_point; AH_Point* contour; point = points; contour = outline->contours; for ( ; contour < contour_limit; contour++ ) { point = *contour; end_point = point->prev; first_point = point; while ( point <= end_point && !( point->flags & touch_flag ) ) point++; if ( point <= end_point ) { AH_Point first_touched = point; AH_Point cur_touched = point; point++; while ( point <= end_point ) { if ( point->flags & touch_flag ) { /* we found two successive touched points; we interpolate */ /* all contour points between them */ ah_iup_interp( cur_touched + 1, point - 1, cur_touched, point ); cur_touched = point; } point++; } if ( cur_touched == first_touched ) { /* this is a special case: only one point was touched in the */ /* contour; we thus simply shift the whole contour */ ah_iup_shift( first_point, end_point, cur_touched ); } else { /* now interpolate after the last touched point to the end */ /* of the contour */ ah_iup_interp( cur_touched + 1, end_point, cur_touched, first_touched ); /* if the first contour point isn't touched, interpolate */ /* from the contour start to the first touched point */ if ( first_touched > points ) ah_iup_interp( first_point, first_touched - 1, cur_touched, first_touched ); } } } /* now save the interpolated values back to x/y */ if ( dimension ) { for ( point = points; point < point_limit; point++ ) point->y = point->u; touch_flag = AH_FLAG_TOUCH_X; ah_setup_uv( outline, AH_UV_OX ); } else { for ( point = points; point < point_limit; point++ ) point->x = point->u; break; /* exit loop */ } } }#endif /* !AH_OPTION_NO_WEAK_INTERPOLATION */ FT_LOCAL_DEF( void ) ah_hinter_align_points( AH_Hinter hinter ) { ah_hinter_align_edge_points( hinter );#ifndef AH_OPTION_NO_STRONG_INTERPOLATION ah_hinter_align_strong_points( hinter );#endif#ifndef AH_OPTION_NO_WEAK_INTERPOLATION ah_hinter_align_weak_points( hinter );#endif } /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /**** ****/ /**** H I N T E R O B J E C T M E T H O D S ****/ /**** ****/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* scale and fit the global metrics */ static void ah_hinter_scale_globals( AH_Hinter hinter, FT_Fixed x_scale, FT_Fixed y_scale ) { FT_Int n; AH_Face_Globals globals = hinter->globals; AH_Globals design = &globals->design; AH_Globals scaled = &globals->scaled; /* copy content */ *scaled = *design; /* scale the standard widths & heights */ for ( n = 0; n < design->num_widths; n++ ) scaled->widths[n] = FT_MulFix( design->widths[n], x_scale ); for ( n = 0; n < design->num_heights; n++ ) scaled->heights[n] = FT_MulFix( design->heights[n], y_scale ); scaled->stds[0] = ( design->num_widths > 0 ) ? scaled->widths[0] : 32000; scaled->stds[1] = ( design->num_heights > 0 ) ? scaled->heights[0] : 32000; /* scale the blue zones */ for ( n = 0; n < AH_BLUE_MAX; n++ ) { FT_Pos delta, delta2; delta = design->blue_shoots[n] - design->blue_refs[n]; delta2 = delta; if ( delta < 0 ) delta2 = -delta2; delta2 = FT_MulFix( delta2, y_scale ); if ( delta2 < 32 ) delta2 = 0; else if ( delta2 < 64 ) delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & -32 ); else delta2 = ( delta2 + 32 ) & -64; if ( delta < 0 ) delta2 = -delta2; scaled->blue_refs[n] = ( FT_MulFix( design->blue_refs[n], y_scale ) + 32 ) & -64; scaled->blue_shoots[n] = scaled->blue_refs[n] + delta2; } globals->x_scale = x_scale; globals->y_scale = y_scale; } static void ah_hinter_align( AH_Hinter hinter ) { ah_hinter_align_edge_points( hinter ); ah_hinter_align_points( hinter ); } /* finalize a hinter object */ FT_LOCAL_DEF( void ) ah_hinter_done( AH_Hinter hinter ) { if ( hinter ) { FT_Memory memory = hinter->memory; ah_loader_done( hinter->loader ); ah_outline_done( hinter->glyph ); /* note: the `globals' pointer is _not_ owned by the hinter */ /* but by the current face object; we don't need to */ /* release it */ hinter->globals = 0; hinter->face = 0; FT_FREE( hinter ); } } /* create a new empty hinter object */ FT_LOCAL_DEF( FT_Error ) ah_hinter_new( FT_Library library, AH_Hinter *ahinter ) { AH_Hinter hinter = 0; FT_Memory memory = library->memory; FT_Error error; *ahinter = 0; /* allocate object */ if ( FT_NEW( hinter ) ) goto Exit; hinter->memory = memory; hinter->flags = 0; /* allocate outline and loader */ error = ah_outline_new( memory, &hinter->glyph ) || ah_loader_new ( memory, &hinter->loader ) || ah_loader_create_extra( hinter->loader ); if ( error ) goto Exit; *ahinter = hinter; Exit: if ( error ) ah_hinter_done( hinter ); return error; } /* create a face's autohint globals */ FT_LOCAL_DEF( FT_Error ) ah_hinter_new_face_globals( AH_Hinter hinter, FT_Face face, AH_Globals globals ) { FT_Error error; FT_Memory memory = hinter->memory; AH_Face_Globals face_globals; if ( FT_NEW( face_globals ) ) goto Exit; hinter->face = face; hinter->globals = face_globals; if ( globals ) face_globals->design = *globals; else ah_hinter_compute_globals( hinter ); face->autohint.data = face_globals; face->autohint.finalizer = (FT_Generic_Finalizer) ah_hinter_done_face_globals; face_globals->face = face; Exit: return error; } /* discard a face's autohint globals */ FT_LOCAL_DEF( void ) ah_hinter_done_face_globals( AH_Face_Globals globals ) { FT_Face face = globals->face; FT_Memory memory = face->memory; FT_FREE( globals ); } static FT_Error ah_hinter_load( AH_Hinter hinter, FT_UInt glyph_index, FT_Int32 load_flags, FT_UInt depth ) { FT_Face face = hinter->face; FT_GlyphSlot slot = face->glyph;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -