📄 aflatin.c
字号:
{ scale = scaler->x_scale; delta = scaler->x_delta; } else { scale = scaler->y_scale; delta = scaler->y_delta; } axis = &metrics->axis[dim]; if ( axis->org_scale == scale && axis->org_delta == delta ) return; axis->org_scale = scale; axis->org_delta = delta; /* * correct X and Y scale to optimize the alignment of the top of small * letters to the pixel grid */ { AF_LatinAxis Axis = &metrics->axis[AF_DIMENSION_VERT]; AF_LatinBlue blue = NULL; for ( nn = 0; nn < Axis->blue_count; nn++ ) { if ( Axis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT ) { blue = &Axis->blues[nn]; break; } } if ( blue ) { FT_Pos scaled = FT_MulFix( blue->shoot.org, scaler->y_scale ); FT_Pos fitted = ( scaled + 40 ) & ~63; if ( scaled != fitted ) { if ( dim == AF_DIMENSION_HORZ ) { if ( fitted < scaled ) scale -= scale / 50; /* scale *= 0.98 */ } else { scale = FT_MulDiv( scale, fitted, scaled ); } } } } axis->scale = scale; axis->delta = delta; if ( dim == AF_DIMENSION_HORZ ) { metrics->root.scaler.x_scale = scale; metrics->root.scaler.x_delta = delta; } else { metrics->root.scaler.y_scale = scale; metrics->root.scaler.y_delta = delta; } /* scale the standard widths */ for ( nn = 0; nn < axis->width_count; nn++ ) { AF_Width width = axis->widths + nn; width->cur = FT_MulFix( width->org, scale ); width->fit = width->cur; } /* an extra-light axis corresponds to a standard width that is */ /* smaller than 0.75 pixels */ axis->extra_light = FT_MulFix( axis->standard_width, scale ) < 32 + 8; if ( dim == AF_DIMENSION_VERT ) { /* scale the blue zones */ for ( nn = 0; nn < axis->blue_count; nn++ ) { AF_LatinBlue blue = &axis->blues[nn]; FT_Pos dist; blue->ref.cur = FT_MulFix( blue->ref.org, scale ) + delta; blue->ref.fit = blue->ref.cur; blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta; blue->shoot.fit = blue->shoot.cur; blue->flags &= ~AF_LATIN_BLUE_ACTIVE; /* a blue zone is only active if it is less than 3/4 pixels tall */ dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale ); if ( dist <= 48 && dist >= -48 ) { FT_Pos delta1, delta2; delta1 = blue->shoot.org - blue->ref.org; delta2 = delta1; if ( delta1 < 0 ) delta2 = -delta2; delta2 = FT_MulFix( delta2, scale ); if ( delta2 < 32 ) delta2 = 0; else if ( delta2 < 64 ) delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 ); else delta2 = FT_PIX_ROUND( delta2 ); if ( delta1 < 0 ) delta2 = -delta2; blue->ref.fit = FT_PIX_ROUND( blue->ref.cur ); blue->shoot.fit = blue->ref.fit + delta2; blue->flags |= AF_LATIN_BLUE_ACTIVE; } } } } FT_LOCAL_DEF( void ) af_latin_metrics_scale( AF_LatinMetrics metrics, AF_Scaler scaler ) { metrics->root.scaler.render_mode = scaler->render_mode; metrics->root.scaler.face = scaler->face; af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ ); af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT ); } /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** L A T I N G L Y P H A N A L Y S I S *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ FT_LOCAL_DEF( FT_Error ) af_latin_hints_compute_segments( AF_GlyphHints hints, AF_Dimension dim ) { AF_AxisHints axis = &hints->axis[dim]; FT_Memory memory = hints->memory; FT_Error error = AF_Err_Ok; AF_Segment segment = NULL; AF_SegmentRec seg0; AF_Point* contour = hints->contours; AF_Point* contour_limit = contour + hints->num_contours; AF_Direction major_dir, segment_dir;#ifdef AF_HINT_METRICS AF_Point min_point = 0; AF_Point max_point = 0; FT_Pos min_coord = 32000; FT_Pos max_coord = -32000;#endif FT_ZERO( &seg0 ); seg0.score = 32000; seg0.flags = AF_EDGE_NORMAL; major_dir = (AF_Direction)FT_ABS( axis->major_dir ); segment_dir = major_dir; axis->num_segments = 0; /* set up (u,v) in each point */ if ( dim == AF_DIMENSION_HORZ ) { AF_Point point = hints->points; AF_Point limit = point + hints->num_points; for ( ; point < limit; point++ ) { point->u = point->fx; point->v = point->fy; } } else { AF_Point point = hints->points; AF_Point limit = point + hints->num_points; for ( ; point < limit; point++ ) { point->u = point->fy; point->v = point->fx; } } /* do each contour separately */ for ( ; contour < contour_limit; contour++ ) { AF_Point point = contour[0]; AF_Point last = point->prev; int on_edge = 0; FT_Pos min_pos = 32000; /* minimum segment pos != min_coord */ FT_Pos max_pos = -32000; /* maximum segment pos != max_coord */ FT_Bool passed;#ifdef AF_HINT_METRICS if ( point->u < min_coord ) { min_coord = point->u; min_point = point; } if ( point->u > max_coord ) { max_coord = point->u; max_point = point; }#endif if ( point == last ) /* skip singletons -- just in case */ continue; if ( FT_ABS( last->out_dir ) == major_dir && FT_ABS( point->out_dir ) == major_dir ) { /* we are already on an edge, try to locate its start */ last = point; for (;;) { point = point->prev; if ( FT_ABS( point->out_dir ) != major_dir ) { point = point->next; break; } if ( point == last ) break; } } last = point; passed = 0; for (;;) { FT_Pos u, v; if ( on_edge ) { u = point->u; if ( u < min_pos ) min_pos = u; if ( u > max_pos ) max_pos = u; if ( point->out_dir != segment_dir || point == last ) { /* we are just leaving an edge; record a new segment! */ segment->last = point; segment->pos = (FT_Short)( ( min_pos + max_pos ) >> 1 ); /* a segment is round if either its first or last point */ /* is a control point */ if ( ( segment->first->flags | point->flags ) & AF_FLAG_CONTROL ) segment->flags |= AF_EDGE_ROUND; /* compute segment size */ min_pos = max_pos = point->v; v = segment->first->v; if ( v < min_pos ) min_pos = v; if ( v > max_pos ) max_pos = v; segment->min_coord = (FT_Short)min_pos; segment->max_coord = (FT_Short)max_pos; segment->height = (FT_Short)( segment->max_coord - segment->min_coord ); on_edge = 0; segment = NULL; /* fallthrough */ } } /* now exit if we are at the start/end point */ if ( point == last ) { if ( passed ) break; passed = 1; } if ( !on_edge && FT_ABS( point->out_dir ) == major_dir ) { /* this is the start of a new segment! */ segment_dir = (AF_Direction)point->out_dir; /* clear all segment fields */ error = af_axis_hints_new_segment( axis, memory, &segment ); if ( error ) goto Exit; segment[0] = seg0; segment->dir = (FT_Char)segment_dir; min_pos = max_pos = point->u; segment->first = point; segment->last = point; segment->contour = contour; on_edge = 1;#ifdef AF_HINT_METRICS if ( point == max_point ) max_point = 0; if ( point == min_point ) min_point = 0;#endif } point = point->next; } } /* contours */ /* now slightly increase the height of segments when this makes */ /* sense -- this is used to better detect and ignore serifs */ { AF_Segment segments = axis->segments; AF_Segment segments_end = segments + axis->num_segments; for ( segment = segments; segment < segments_end; segment++ ) { AF_Point first = segment->first; AF_Point last = segment->last; FT_Pos first_v = first->v; FT_Pos last_v = last->v; if ( first == last ) continue; if ( first_v < last_v ) { AF_Point p; p = first->prev; if ( p->v < first_v ) segment->height = (FT_Short)( segment->height + ( ( first_v - p->v ) >> 1 ) ); p = last->next; if ( p->v > last_v ) segment->height = (FT_Short)( segment->height + ( ( p->v - last_v ) >> 1 ) ); } else { AF_Point p; p = first->prev; if ( p->v > first_v ) segment->height = (FT_Short)( segment->height + ( ( p->v - first_v ) >> 1 ) ); p = last->next; if ( p->v < last_v ) segment->height = (FT_Short)( segment->height + ( ( last_v - p->v ) >> 1 ) ); } } }#ifdef AF_HINT_METRICS /* we need to ensure that there are edges on the left-most and */ /* right-most points of the glyph in order to hint the metrics; */ /* we do this by inserting fake segments when needed */ if ( dim == AF_DIMENSION_HORZ ) { AF_Point point = hints->points; AF_Point point_limit = point + hints->num_points; FT_Pos min_pos = 32000; FT_Pos max_pos = -32000; min_point = 0; max_point = 0; /* compute minimum and maximum points */ for ( ; point < point_limit; point++ ) { FT_Pos x = point->fx; if ( x < min_pos ) { min_pos = x; min_point = point; } if ( x > max_pos ) { max_pos = x; max_point = point; } } /* insert minimum segment */ if ( min_point ) { /* clear all segment fields */ error = af_axis_hints_new_segment( axis, memory, &segment ); if ( error ) goto Exit; segment[0] = seg0; segment->dir = segment_dir; segment->first = min_point; segment->last = min_point; segment->pos = min_pos; segment = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -