📄 pshalgo.c
字号:
if ( parent ) { FT_Pos par_org_center, par_cur_center; FT_Pos cur_org_center, cur_delta; /* ensure that parent is already fitted */ if ( !psh_hint_is_fitted( parent ) ) psh_hint_align( parent, globals, dimension, glyph ); par_org_center = parent->org_pos + ( parent->org_len >> 1 ); par_cur_center = parent->cur_pos + ( parent->cur_len >> 1 ); cur_org_center = hint->org_pos + ( hint->org_len >> 1 ); cur_delta = FT_MulFix( cur_org_center - par_org_center, scale ); pos = par_cur_center + cur_delta - ( len >> 1 ); } hint->cur_pos = pos; hint->cur_len = fit_len; /* Stem adjustment tries to snap stem widths to standard * ones. This is important to prevent unpleasant rounding * artefacts. */ if ( glyph->do_stem_adjust ) { if ( len <= 64 ) { /* the stem is less than one pixel; we will center it * around the nearest pixel center */#if 1 pos = ( pos + ( len >> 1 ) ) & -64;#else /* this seems to be a bug! */ pos = ( pos + ( ( len >> 1 ) & -64 ) );#endif len = 64; } else { len = psh_dimension_quantize_len( dim, len, 0 ); } } /* now that we have a good hinted stem width, try to position */ /* the stem along a pixel grid integer coordinate */ hint->cur_pos = pos + psh_hint_snap_stem_side_delta( pos, len ); hint->cur_len = len; } } if ( do_snapping ) { pos = hint->cur_pos; len = hint->cur_len; if ( len < 64 ) len = 64; else len = ( len + 32 ) & -64; switch ( align.align ) { case PSH_BLUE_ALIGN_TOP: hint->cur_pos = align.align_top - len; hint->cur_len = len; break; case PSH_BLUE_ALIGN_BOT: hint->cur_len = len; break; case PSH_BLUE_ALIGN_BOT | PSH_BLUE_ALIGN_TOP: /* don't touch */ break; default: hint->cur_len = len; if ( len & 64 ) pos = ( ( pos + ( len >> 1 ) ) & -64 ) + 32; else pos = ( pos + ( len >> 1 ) + 32 ) & -64; hint->cur_pos = pos - ( len >> 1 ); hint->cur_len = len; } } psh_hint_set_fitted( hint );#ifdef DEBUG_HINTER if ( ps_debug_hint_func ) ps_debug_hint_func( hint, dimension );#endif } }#if 0 /* not used for now, experimental */ /* * A variant to perform "light" hinting (i.e. FT_RENDER_MODE_LIGHT) * of stems */ static void psh_hint_align_light( PSH_Hint hint, PSH_Globals globals, FT_Int dimension, PSH_Glyph glyph ) { PSH_Dimension dim = &globals->dimension[dimension]; FT_Fixed scale = dim->scale_mult; FT_Fixed delta = dim->scale_delta; if ( !psh_hint_is_fitted( hint ) ) { FT_Pos pos = FT_MulFix( hint->org_pos, scale ) + delta; FT_Pos len = FT_MulFix( hint->org_len, scale ); FT_Pos fit_len; PSH_AlignmentRec align; /* ignore stem alignments when requested through the hint flags */ if ( ( dimension == 0 && !glyph->do_horz_hints ) || ( dimension == 1 && !glyph->do_vert_hints ) ) { hint->cur_pos = pos; hint->cur_len = len; psh_hint_set_fitted( hint ); return; } fit_len = len; hint->cur_len = fit_len; /* check blue zones for horizontal stems */ align.align = PSH_BLUE_ALIGN_NONE; align.align_bot = align.align_top = 0; if ( dimension == 1 ) psh_blues_snap_stem( &globals->blues, hint->org_pos + hint->org_len, hint->org_pos, &align ); switch ( align.align ) { case PSH_BLUE_ALIGN_TOP: /* the top of the stem is aligned against a blue zone */ hint->cur_pos = align.align_top - fit_len; break; case PSH_BLUE_ALIGN_BOT: /* the bottom of the stem is aligned against a blue zone */ hint->cur_pos = align.align_bot; break; case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT: /* both edges of the stem are aligned against blue zones */ hint->cur_pos = align.align_bot; hint->cur_len = align.align_top - align.align_bot; break; default: { PSH_Hint parent = hint->parent; if ( parent ) { FT_Pos par_org_center, par_cur_center; FT_Pos cur_org_center, cur_delta; /* ensure that parent is already fitted */ if ( !psh_hint_is_fitted( parent ) ) psh_hint_align_light( parent, globals, dimension, glyph ); par_org_center = parent->org_pos + ( parent->org_len / 2 ); par_cur_center = parent->cur_pos + ( parent->cur_len / 2 ); cur_org_center = hint->org_pos + ( hint->org_len / 2 ); cur_delta = FT_MulFix( cur_org_center - par_org_center, scale ); pos = par_cur_center + cur_delta - ( len >> 1 ); } /* Stems less than one pixel wide are easy -- we want to * make them as dark as possible, so they must fall within * one pixel. If the stem is split between two pixels * then snap the edge that is nearer to the pixel boundary * to the pixel boundary. */ if ( len <= 64 ) { if ( ( pos + len + 63 ) / 64 != pos / 64 + 1 ) pos += psh_hint_snap_stem_side_delta ( pos, len ); } /* Position stems other to minimize the amount of mid-grays. * There are, in general, two positions that do this, * illustrated as A) and B) below. * * + + + + * * A) |--------------------------------| * B) |--------------------------------| * C) |--------------------------------| * * Position A) (split the excess stem equally) should be better * for stems of width N + f where f < 0.5. * * Position B) (split the deficiency equally) should be better * for stems of width N + f where f > 0.5. * * It turns out though that minimizing the total number of lit * pixels is also important, so position C), with one edge * aligned with a pixel boundary is actually preferable * to A). There are also more possibile positions for C) than * for A) or B), so it involves less distortion of the overall * character shape. */ else /* len > 64 */ { FT_Fixed frac_len = len & 63; FT_Fixed center = pos + ( len >> 1 ); FT_Fixed delta_a, delta_b; if ( ( len / 64 ) & 1 ) { delta_a = ( center & -64 ) + 32 - center; delta_b = ( ( center + 32 ) & - 64 ) - center; } else { delta_a = ( ( center + 32 ) & - 64 ) - center; delta_b = ( center & -64 ) + 32 - center; } /* We choose between B) and C) above based on the amount * of fractinal stem width; for small amounts, choose * C) always, for large amounts, B) always, and inbetween, * pick whichever one involves less stem movement. */ if ( frac_len < 32 ) { pos += psh_hint_snap_stem_side_delta ( pos, len ); } else if ( frac_len < 48 ) { FT_Fixed side_delta = psh_hint_snap_stem_side_delta ( pos, len ); if ( ABS( side_delta ) < ABS( delta_b ) ) pos += side_delta; else pos += delta_b; } else { pos += delta_b; } } hint->cur_pos = pos; } } /* switch */ psh_hint_set_fitted( hint );#ifdef DEBUG_HINTER if ( ps_debug_hint_func ) ps_debug_hint_func( hint, dimension );#endif } }#endif /* 0 */ static void psh_hint_table_align_hints( PSH_Hint_Table table, PSH_Globals globals, FT_Int dimension, PSH_Glyph glyph ) { PSH_Hint hint; FT_UInt count;#ifdef DEBUG_HINTER PSH_Dimension dim = &globals->dimension[dimension]; FT_Fixed scale = dim->scale_mult; FT_Fixed delta = dim->scale_delta; if ( ps_debug_no_vert_hints && dimension == 0 ) { ps_simple_scale( table, scale, delta, dimension ); return; } if ( ps_debug_no_horz_hints && dimension == 1 ) { ps_simple_scale( table, scale, delta, dimension ); return; }#endif /* DEBUG_HINTER*/ hint = table->hints; count = table->max_hints; for ( ; count > 0; count--, hint++ ) psh_hint_align( hint, globals, dimension, glyph ); } /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** POINTS INTERPOLATION ROUTINES *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/#define PSH_ZONE_MIN -3200000L#define PSH_ZONE_MAX +3200000L#define xxDEBUG_ZONES#ifdef DEBUG_ZONES#include <stdio.h> static void psh_print_zone( PSH_Zone zone ) { printf( "zone [scale,delta,min,max] = [%.3f,%.3f,%d,%d]\n", zone->scale / 65536.0, zone->delta / 64.0, zone->min, zone->max ); }#else#define psh_print_zone( x ) do { } while ( 0 )#endif /* DEBUG_ZONES */ /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** HINTER GLYPH MANAGEMENT *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/#ifdef COMPUTE_INFLEXS /* compute all inflex points in a given glyph */ static void psh_glyph_compute_inflections( PSH_Glyph glyph ) { FT_UInt n; for ( n = 0; n < glyph->num_contours; n++ ) { PSH_Point first, start, end, before, after; FT_Angle angle_in, angle_seg, angle_out; FT_Angle diff_in, diff_out; FT_Int finished = 0; /* we need at least 4 points to create an inflection point */ if ( glyph->contours[n].count < 4 ) continue; /* compute first segment in contour */ first = glyph->contours[n].start; start = end = first; do { end = end->next; if ( end == first ) goto Skip; } while ( PSH_POINT_EQUAL_ORG( end, first ) ); angle_seg = PSH_POINT_ANGLE( start, end ); /* extend the segment start whenever possible */ before = start; do { do { start = before; before = before->prev; if ( before == first ) goto Skip; } while ( PSH_POINT_EQUAL_ORG( before, start ) ); angle_in = PSH_POINT_ANGLE( before, start ); } while ( angle_in == angle_seg ); first = start; diff_in = FT_Angle_Diff( angle_in, angle_seg ); /* 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; } while ( PSH_POINT_EQUAL_ORG( end, after ) ); angle_out = PSH_POINT_ANGLE( end, after ); } while ( angle_out == angle_seg ); diff_out = FT_Angle_Diff( angle_seg, angle_out ); if ( ( diff_in ^ diff_out ) < 0 ) { /* diff_in and diff_out have different signs, we have */ /* inflection points here... */ do { psh_point_set_inflex( start ); start = start->next; } while ( start != end ); psh_point_set_inflex( start ); } start = end; end = after; angle_seg = angle_out; diff_in = diff_out; } while ( !finished ); Skip: ; } }#endif /* COMPUTE_INFLEXS */ static void psh_glyph_done( PSH_Glyph glyph ) { FT_Memory memory = glyph->memory; psh_hint_table_done( &glyph->hint_tables[1], memory ); psh_hint_table_done( &glyph->hint_tables[0], memory ); FT_FREE( glyph->points ); FT_FREE( glyph->contours ); glyph->num_points = 0; glyph->num_contours = 0; glyph->memory = 0; } static int psh_compute_dir( FT_Pos dx, FT_Pos dy )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -