static FT_Error af_dummy_hints_apply( AF_GlyphHints hints, FT_Outline* outline ) { FT_Error error; error = af_glyph_hints_reload( hints, outline ); if ( !error ) af_glyph_hints_save( hints, outline ); return error; }
af_cjk_hints_apply( AF_GlyphHints hints, FT_Outline* outline, AF_LatinMetrics metrics ) { FT_Error error; int dim; FT_UNUSED( metrics ); error = af_glyph_hints_reload( hints, outline, 0 ); if ( error ) goto Exit; /* analyze glyph outline */ if ( AF_HINTS_DO_HORIZONTAL( hints ) ) { error = af_cjk_hints_detect_features( hints, AF_DIMENSION_HORZ ); if ( error ) goto Exit; } if ( AF_HINTS_DO_VERTICAL( hints ) ) { error = af_cjk_hints_detect_features( hints, AF_DIMENSION_VERT ); if ( error ) goto Exit; } /* grid-fit the outline */ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) { if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) || ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) ) { #ifdef AF_USE_WARPER if ( dim == AF_DIMENSION_HORZ && metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL ) { AF_WarperRec warper; FT_Fixed scale; FT_Pos delta; af_warper_compute( &warper, hints, dim, &scale, &delta ); af_glyph_hints_scale_dim( hints, dim, scale, delta ); continue; } #endif /* AF_USE_WARPER */ af_cjk_hint_edges( hints, (AF_Dimension)dim ); af_cjk_align_edge_points( hints, (AF_Dimension)dim ); af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim ); af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim ); } } #if 0 af_glyph_hints_dump_points( hints ); af_glyph_hints_dump_segments( hints ); af_glyph_hints_dump_edges( hints ); #endif af_glyph_hints_save( hints, outline ); Exit: return error; }
af_latin_metrics_init_widths( AF_LatinMetrics metrics, FT_Face face, FT_ULong charcode ) { /* scan the array of segments in each direction */ AF_GlyphHintsRec hints[1]; af_glyph_hints_init( hints, face->memory ); metrics->axis[AF_DIMENSION_HORZ].width_count = 0; metrics->axis[AF_DIMENSION_VERT].width_count = 0; { FT_Error error; FT_UInt glyph_index; int dim; AF_LatinMetricsRec dummy[1]; AF_Scaler scaler = &dummy->root.scaler; glyph_index = FT_Get_Char_Index( face, charcode ); if ( glyph_index == 0 ) goto Exit; error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); if ( error || face->glyph->outline.n_points <= 0 ) goto Exit; FT_ZERO( dummy ); dummy->units_per_em = metrics->units_per_em; scaler->x_scale = scaler->y_scale = 0x10000L; scaler->x_delta = scaler->y_delta = 0; scaler->face = face; scaler->render_mode = FT_RENDER_MODE_NORMAL; scaler->flags = 0; af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy ); error = af_glyph_hints_reload( hints, &face->glyph->outline, 0 ); if ( error ) goto Exit; for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) { AF_LatinAxis axis = &metrics->axis[dim]; AF_AxisHints axhints = &hints->axis[dim]; AF_Segment seg, limit, link; FT_UInt num_widths = 0; error = af_latin_hints_compute_segments( hints, (AF_Dimension)dim ); if ( error ) goto Exit; af_latin_hints_link_segments( hints, (AF_Dimension)dim ); seg = axhints->segments; limit = seg + axhints->num_segments; for ( ; seg < limit; seg++ ) { link = seg->link; /* we only consider stem segments there! */ if ( link && link->link == seg && link > seg ) { FT_Pos dist; dist = seg->pos - link->pos; if ( dist < 0 ) dist = -dist; if ( num_widths < AF_LATIN_MAX_WIDTHS ) axis->widths[ num_widths++ ].org = dist; } } af_sort_widths( num_widths, axis->widths ); axis->width_count = num_widths; } Exit: for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) { AF_LatinAxis axis = &metrics->axis[dim]; FT_Pos stdw; stdw = ( axis->width_count > 0 ) ? axis->widths[0].org : AF_LATIN_CONSTANT( metrics, 50 ); /* let's try 20% of the smallest width */ axis->edge_distance_threshold = stdw / 5; axis->standard_width = stdw; axis->extra_light = 0; } } af_glyph_hints_done( hints ); }