📄 t1hinter.c
字号:
* face object. * scale :: the 16.16 scale used to convert outline * units to 26.6 pixels * * <Note> * For now, all stems are hinted independently from each other. * It might be necessary, for better performance, to introduce * the notion of "controlled" hints describing things like * counter-stems, stem3 as well as overlapping stems control. * ************************************************************************/ static void t1_hint_horizontal_stems( T1_Stem_Table* table, T1_Size_Hints* hints, T1_Pos blueShift, T1_Fixed scale ) { T1_Stem_Hint* stem = table->stems; T1_Stem_Hint* limit = stem + table->num_stems; /* first of all, scale the blueShift */ blueShift = SCALE(blueShift); /* then scan the horizontal stem table */ for ( ; stem < limit; stem++ ) { T1_Pos bottom_orus = stem->min_edge.orus; T1_Pos top_orus = stem->max_edge.orus; T1_Pos top_pix = SCALE( top_orus ); T1_Pos bottom_pix = SCALE( bottom_orus ); T1_Pos width_pix = top_pix - bottom_pix; T1_Pos bottom = bottom_pix; T1_Pos top = top_pix; T1_Int align = T1_ALIGN_NONE; /******************************************************************/ /* Snap pixel width if in stem snap range */ { T1_Snap_Zone* zone = hints->snap_heights; T1_Snap_Zone* zone_limit = zone + hints->num_snap_heights; for ( ; zone < zone_limit; zone++ ) { if ( width_pix < zone->min ) break; if ( width_pix <= zone->max ) { width_pix = zone->pix; break; } } } /******************************************************************/ /* round width - minimum 1 pixel if this isn't a ghost stem */ if ( width_pix > 0 ) width_pix = ( width_pix < ONE_PIXEL ? ONE_PIXEL : ROUND(width_pix) ); /******************************************************************/ /* Now check for bottom blue zones alignement */ { T1_Int num_blues = hints->num_bottom_zones; T1_Snap_Zone* blue = hints->blue_zones; T1_Snap_Zone* blue_limit = blue + num_blues; for ( ; blue < blue_limit; blue++ ) { if ( bottom_pix < blue->min ) break; if ( bottom_pix <= blue->max ) { align = T1_ALIGN_BOTTOM; bottom = ROUND( blue->pix ); /* implements blue shift */ if (!hints->supress_overshoots) { T1_Pos delta = blue->pix - bottom_pix; delta = ( delta < blueShift ? 0 : ROUND( delta ) ); bottom -= delta; } } } } /******************************************************************/ /* Check for top blue zones alignement */ { T1_Int num_blues = hints->num_blue_zones - hints->num_bottom_zones; T1_Snap_Zone* blue = hints->blue_zones + hints->num_bottom_zones; T1_Snap_Zone* blue_limit = blue + num_blues; for ( ; blue < blue_limit; blue++ ) { if ( top_pix < blue->min ) break; if ( top_pix <= blue->max ) { align |= T1_ALIGN_TOP; top = ROUND( blue->pix ); /* implements blue shift */ if (!hints->supress_overshoots) { T1_Pos delta = top - blue->pix; delta = ( delta < blueShift ? 0 : ROUND( delta ) ); top += delta; } } } } /******************************************************************/ /* compute the hinted stem position, according to its alignment */ switch (align) { case T1_ALIGN_BOTTOM: /* bottom zone alignement */ bottom_pix = bottom; top_pix = bottom + width_pix; break; case T1_ALIGN_TOP: /* top zone alignement */ top_pix = top; bottom_pix = top - width_pix; break; case T1_ALIGN_BOTH: /* bottom+top zone alignement */ bottom_pix = bottom; top_pix = top; break; default: /* no alignement */ /* XXXX : TODO : Add management of controlled stems */ bottom = ( SCALE(bottom_orus+top_orus) - width_pix )/2; bottom_pix = ROUND(bottom); top_pix = bottom_pix + width_pix; } stem->min_edge.pix = bottom_pix; stem->max_edge.pix = top_pix; } }/************************************************************************ * * <Function> * t1_hint_vertical_stems * * <Description> * Compute the location of each scaled vertical stem hint. * This takes care of the vertical stem snap table * * <Input> * table :: the vertical stem hints table * hints :: the current size's hint structure * scale :: the 16.16 scale used to convert outline * units to 26.6 pixels * * <Note> * For now, all stems are hinted independently from each other. * It might be necessary, for better performance, to introduce * the notion of "controlled" hints describing things like * counter-stems, stem3 as well as overlapping stems control. * ************************************************************************/ /* compute the location of each scaled vertical stem hint. */ /* Take care of blue zones and stem snap table */ static void t1_hint_vertical_stems( T1_Stem_Table* table, T1_Size_Hints* hints, T1_Fixed scale ) { T1_Stem_Hint* stem = table->stems; T1_Stem_Hint* limit = stem + table->num_stems; for ( ; stem < limit; stem++ ) { T1_Pos stem_left = stem->min_edge.orus; T1_Pos stem_right = stem->max_edge.orus; T1_Pos width_pix, left; width_pix = SCALE( stem_right - stem_left ); /* Snap pixel width if in stem snap range */ { T1_Snap_Zone* zone = hints->snap_widths; T1_Snap_Zone* zone_limit = zone + hints->num_snap_widths; for ( ; zone < zone_limit; zone++ ) { if ( width_pix < zone->min ) break; if ( width_pix <= zone->max ) { width_pix = zone->pix; break; } } } /* round width - minimum 1 pixel if this isn't a ghost stem */ if ( width_pix > 0 ) width_pix = ( width_pix < ONE_PIXEL ? ONE_PIXEL : ROUND( width_pix ) ); /* now place the snapped and rounded stem */ /* XXXX : TODO : implement controlled stems for the overlapping */ /* cases.. */ left = ( SCALE(stem_left+stem_right) - width_pix )/2; stem->min_edge.pix = ROUND(left); stem->max_edge.pix = stem->min_edge.pix + width_pix; } }/************************************************************************ * * <Function> * t1_hint_point * * <Description> * Grid-fit a coordinate with regards to a given stem hints table * * <Input> * table :: the source stem hints table * coord :: original coordinate, expressed in font units * scale :: the 16.16 scale used to convert font units into * 26.6 pixels * * <Return> * the hinted/scaled value in 26.6 pixels * * <Note> * For now, all stems are hinted independently from each other. * It might be necessary, for better performance, to introduce * the notion of "controlled" hints describing things like * counter-stems, stem3 as well as overlapping stems control. * ************************************************************************/ static T1_Pos t1_hint_point( T1_Stem_Table* table, T1_Pos coord, T1_Fixed scale ) { T1_Int num_active = table->num_active; T1_Int n; T1_Stem_Hint* prev = 0; T1_Stem_Hint* cur = 0; T1_Edge* min; T1_Edge* max; T1_Pos delta; /* only hint when there is at least one stem defined */ if (num_active <= 0) return SCALE(coord); /* scan the stem table to determine placement of coordinate */ /* relative to the list of sorted and stems */ for ( n = 0; n < num_active; n++, prev = cur ) { cur = table->stems + table->sort[n]; /* is it on the left of the current edge ? */ delta = cur->min_edge.orus - coord; if ( delta == 0 ) return cur->min_edge.pix; if (delta > 0) { /* if this is the left of the first edge, simply shift */ if (!prev) return cur->min_edge.pix - SCALE(delta); /* otherwise, interpolate between the maximum of the */ /* previous stem, and the minimum of the current one */ min = &prev->max_edge; max = &cur->min_edge; goto Interpolate; } /* is it within the current edge ? */ delta = cur->max_edge.orus - coord; if ( delta == 0 ) return cur->max_edge.pix; if (delta > 0) { /* interpolate within the stem */ min = &cur->min_edge; max = &cur->max_edge; goto Interpolate; } } /* apparently, this coordinate is on the right of the last stem */ delta = coord - cur->max_edge.orus; return cur->max_edge.pix + SCALE(delta); Interpolate: return min->pix + FT_MulDiv( coord - min->orus, max->pix - min->pix, max->orus - min->orus ); }#if 1/************************************************************************ * * <Function> * T1_Hint_Points * * <Description> * this function grid-fits several points in a given Type 1 builder * at once. * * <Input> * builder :: handle to target Type 1 builder * first :: first point to hint in builder's current outline * last :: last point to hint in builder's current outline * ************************************************************************/ LOCAL_FUNC void T1_Hint_Points( T1_Builder* builder ) { T1_Int first = builder->hint_point; T1_Int last = builder->current.n_points-1; T1_Size size = builder->size; T1_Fixed scale_x = size->root.metrics.x_scale; T1_Fixed scale_y = size->root.metrics.y_scale; T1_Glyph_Hints* hints = builder->glyph->hints; T1_Stem_Table* hori_stems = &hints->hori_stems; T1_Stem_Table* vert_stems = &hints->vert_stems; T1_Vector* cur = builder->current.points + first; T1_Vector* limit = cur + last - first + 1; /* first of all, sort the active stem hints */ t1_sort_hints( hori_stems ); t1_sort_hints( vert_stems ); for ( ; cur < limit; cur++ ) { cur->x = t1_hint_point( vert_stems, cur->x, scale_x ); cur->y = t1_hint_point( hori_stems, cur->y, scale_y ); } builder->hint_point = builder->current.n_points; }/************************************************************************ * * <Function> * T1_Hint_Stems * * <Description> * This function is used to compute the location of each stem hint * between the first and second passes of the glyph loader on the * charstring. * * <Input> * builder :: handle to target builder * ************************************************************************/ LOCAL_FUNC void T1_Hint_Stems( T1_Builder* builder ) { T1_Glyph_Hints* hints = builder->glyph->hints; T1_Font* priv = &builder->face->type1; T1_Size size = builder->size; T1_Fixed scale_x = size->root.metrics.x_scale; T1_Fixed scale_y = size->root.metrics.y_scale; t1_hint_horizontal_stems( &hints->hori_stems, builder->size->hints, priv->blue_shift, scale_y ); t1_hint_vertical_stems( &hints->vert_stems, builder->size->hints, scale_x ); }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -