📄 ahhint.c
字号:
if ( point == seg->last ) break; point = point->next; } seg = seg->edge_next; } while ( seg != edge->first ); } edges = outline->vert_edges; edge_limit = edges + outline->num_vedges; } } /* hint the strong points -- this is equivalent to the TrueType `IP' */ static void ah_hinter_align_strong_points( AH_Hinter* hinter ) { AH_Outline* outline = hinter->glyph; FT_Int dimension; AH_Edge* edges; AH_Edge* edge_limit; AH_Point* points; AH_Point* point_limit; AH_Flags touch_flag; points = outline->points; point_limit = points + outline->num_points; edges = outline->horz_edges; edge_limit = edges + outline->num_hedges; touch_flag = ah_flah_touch_y; for ( dimension = 1; dimension >= 0; dimension-- ) { AH_Point* point; AH_Edge* edge; if ( edges < edge_limit ) for ( point = points; point < point_limit; point++ ) { FT_Pos u, ou, fu; /* point position */ FT_Pos delta; if ( point->flags & touch_flag ) continue;#ifndef AH_OPTION_NO_WEAK_INTERPOLATION /* if this point is candidate to weak interpolation, we will */ /* interpolate it after all strong points have been processed */ if ( point->flags & ah_flah_weak_interpolation ) continue;#endif if ( dimension ) { 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; } /* 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; } /* assert( before && after && before != after ) */ u = before->pos + FT_MulDiv( fu - before->fpos, after->pos - before->pos, after->fpos - before->fpos ); } 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_flah_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' */ static void ah_hinter_align_weak_points( AH_Hinter* hinter ) { AH_Outline* outline = hinter->glyph; FT_Int dimension; AH_Edge* edges; AH_Edge* edge_limit; 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 */ edges = outline->horz_edges; edge_limit = edges + outline->num_hedges; touch_flag = ah_flah_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_flah_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 ); /* 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; 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 ( ALLOC( hinter, sizeof ( *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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -