📄 ahhint.c
字号:
FT_Slot_Internal internal = slot->internal; FT_Fixed x_scale = hinter->globals->x_scale; FT_Fixed y_scale = hinter->globals->y_scale; FT_Error error; AH_Outline outline = hinter->glyph; AH_Loader gloader = hinter->loader; /* load the glyph */ error = FT_Load_Glyph( face, glyph_index, load_flags ); if ( error ) goto Exit; /* Set `hinter->transformed' after loading with FT_LOAD_NO_RECURSE. */ hinter->transformed = internal->glyph_transformed; if ( hinter->transformed ) { FT_Matrix imatrix; imatrix = internal->glyph_matrix; hinter->trans_delta = internal->glyph_delta; hinter->trans_matrix = imatrix; FT_Matrix_Invert( &imatrix ); FT_Vector_Transform( &hinter->trans_delta, &imatrix ); } /* set linear horizontal metrics */ slot->linearHoriAdvance = slot->metrics.horiAdvance; slot->linearVertAdvance = slot->metrics.vertAdvance; switch ( slot->format ) { case FT_GLYPH_FORMAT_OUTLINE: /* translate glyph outline if we need to */ if ( hinter->transformed ) { FT_UInt n = slot->outline.n_points; FT_Vector* point = slot->outline.points; for ( ; n > 0; point++, n-- ) { point->x += hinter->trans_delta.x; point->y += hinter->trans_delta.y; } } /* copy the outline points in the loader's current */ /* extra points which is used to keep original glyph coordinates */ error = ah_loader_check_points( gloader, slot->outline.n_points + 2, slot->outline.n_contours ); if ( error ) goto Exit; FT_MEM_COPY( gloader->current.extra_points, slot->outline.points, slot->outline.n_points * sizeof ( FT_Vector ) ); FT_MEM_COPY( gloader->current.outline.contours, slot->outline.contours, slot->outline.n_contours * sizeof ( short ) ); FT_MEM_COPY( gloader->current.outline.tags, slot->outline.tags, slot->outline.n_points * sizeof ( char ) ); gloader->current.outline.n_points = slot->outline.n_points; gloader->current.outline.n_contours = slot->outline.n_contours; /* compute original phantom points */ hinter->pp1.x = 0; hinter->pp1.y = 0; hinter->pp2.x = FT_MulFix( slot->metrics.horiAdvance, x_scale ); hinter->pp2.y = 0; /* be sure to check for spacing glyphs */ if ( slot->outline.n_points == 0 ) goto Hint_Metrics; /* now load the slot image into the auto-outline and run the */ /* automatic hinting process */ error = ah_outline_load( outline, x_scale, y_scale, face ); if ( error ) goto Exit; /* perform feature detection */ ah_outline_detect_features( outline ); if ( hinter->do_vert_hints ) { ah_outline_compute_blue_edges( outline, hinter->globals ); ah_outline_scale_blue_edges( outline, hinter->globals ); } /* perform alignment control */ ah_hinter_hint_edges( hinter ); ah_hinter_align( hinter ); /* now save the current outline into the loader's current table */ ah_outline_save( outline, gloader ); /* we now need to hint the metrics according to the change in */ /* width/positioning that occured during the hinting process */ { FT_Pos old_advance, old_rsb, old_lsb, new_lsb; AH_Edge edge1 = outline->vert_edges; /* leftmost edge */ AH_Edge edge2 = edge1 + outline->num_vedges - 1; /* rightmost edge */ old_advance = hinter->pp2.x; old_rsb = old_advance - edge2->opos; old_lsb = edge1->opos; new_lsb = edge1->pos; hinter->pp1.x = ( ( new_lsb - old_lsb ) + 32 ) & -64; hinter->pp2.x = ( ( edge2->pos + old_rsb ) + 32 ) & -64;#if 0 /* try to fix certain bad advance computations */ if ( hinter->pp2.x + hinter->pp1.x == edge2->pos && old_rsb > 4 ) hinter->pp2.x += 64;#endif } /* good, we simply add the glyph to our loader's base */ ah_loader_add( gloader ); break; case FT_GLYPH_FORMAT_COMPOSITE: { FT_UInt nn, num_subglyphs = slot->num_subglyphs; FT_UInt num_base_subgs, start_point; FT_SubGlyph subglyph; start_point = gloader->base.outline.n_points; /* first of all, copy the subglyph descriptors in the glyph loader */ error = ah_loader_check_subglyphs( gloader, num_subglyphs ); if ( error ) goto Exit; FT_MEM_COPY( gloader->current.subglyphs, slot->subglyphs, num_subglyphs * sizeof ( FT_SubGlyph ) ); gloader->current.num_subglyphs = num_subglyphs; num_base_subgs = gloader->base.num_subglyphs; /* now, read each subglyph independently */ for ( nn = 0; nn < num_subglyphs; nn++ ) { FT_Vector pp1, pp2; FT_Pos x, y; FT_UInt num_points, num_new_points, num_base_points; /* gloader.current.subglyphs can change during glyph loading due */ /* to re-allocation -- we must recompute the current subglyph on */ /* each iteration */ subglyph = gloader->base.subglyphs + num_base_subgs + nn; pp1 = hinter->pp1; pp2 = hinter->pp2; num_base_points = gloader->base.outline.n_points; error = ah_hinter_load( hinter, subglyph->index, load_flags, depth + 1 ); if ( error ) goto Exit; /* recompute subglyph pointer */ subglyph = gloader->base.subglyphs + num_base_subgs + nn; if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS ) { pp1 = hinter->pp1; pp2 = hinter->pp2; } else { hinter->pp1 = pp1; hinter->pp2 = pp2; } num_points = gloader->base.outline.n_points; num_new_points = num_points - num_base_points; /* now perform the transform required for this subglyph */ if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE | FT_SUBGLYPH_FLAG_XY_SCALE | FT_SUBGLYPH_FLAG_2X2 ) ) { FT_Vector* cur = gloader->base.outline.points + num_base_points; FT_Vector* org = gloader->base.extra_points + num_base_points; FT_Vector* limit = cur + num_new_points; for ( ; cur < limit; cur++, org++ ) { FT_Vector_Transform( cur, &subglyph->transform ); FT_Vector_Transform( org, &subglyph->transform ); } } /* apply offset */ if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) ) { FT_Int k = subglyph->arg1; FT_UInt l = subglyph->arg2; FT_Vector* p1; FT_Vector* p2; if ( start_point + k >= num_base_points || l >= (FT_UInt)num_new_points ) { error = AH_Err_Invalid_Composite; goto Exit; } l += num_base_points; /* for now, only use the current point coordinates; */ /* we may consider another approach in the near future */ p1 = gloader->base.outline.points + start_point + k; p2 = gloader->base.outline.points + start_point + l; x = p1->x - p2->x; y = p1->y - p2->y; } else { x = FT_MulFix( subglyph->arg1, x_scale ); y = FT_MulFix( subglyph->arg2, y_scale ); x = ( x + 32 ) & -64; y = ( y + 32 ) & -64; } { FT_Outline dummy = gloader->base.outline; dummy.points += num_base_points; dummy.n_points = (short)num_new_points; FT_Outline_Translate( &dummy, x, y ); } } } break; default: /* we don't support other formats (yet?) */ error = AH_Err_Unimplemented_Feature; } Hint_Metrics: if ( depth == 0 ) { FT_BBox bbox; /* transform the hinted outline if needed */ if ( hinter->transformed ) FT_Outline_Transform( &gloader->base.outline, &hinter->trans_matrix ); /* we must translate our final outline by -pp1.x and compute */ /* the new metrics */ if ( hinter->pp1.x ) FT_Outline_Translate( &gloader->base.outline, -hinter->pp1.x, 0 ); FT_Outline_Get_CBox( &gloader->base.outline, &bbox ); bbox.xMin &= -64; bbox.yMin &= -64; bbox.xMax = ( bbox.xMax + 63 ) & -64; bbox.yMax = ( bbox.yMax + 63 ) & -64; slot->metrics.width = bbox.xMax - bbox.xMin; slot->metrics.height = bbox.yMax - bbox.yMin; slot->metrics.horiBearingX = bbox.xMin; slot->metrics.horiBearingY = bbox.yMax; /* for mono-width fonts (like Andale, Courier, etc.) we need */ /* to keep the original rounded advance width */ if ( !FT_IS_FIXED_WIDTH( slot->face ) ) slot->metrics.horiAdvance = hinter->pp2.x - hinter->pp1.x; else slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance, x_scale ); slot->metrics.horiAdvance = ( slot->metrics.horiAdvance + 32 ) & -64; /* now copy outline into glyph slot */ ah_loader_rewind( slot->internal->loader ); error = ah_loader_copy_points( slot->internal->loader, gloader ); if ( error ) goto Exit; slot->outline = slot->internal->loader->base.outline; slot->format = FT_GLYPH_FORMAT_OUTLINE; }#ifdef DEBUG_HINTER ah_debug_hinter = hinter;#endif Exit: return error; } /* load and hint a given glyph */ FT_LOCAL_DEF( FT_Error ) ah_hinter_load_glyph( AH_Hinter hinter, FT_GlyphSlot slot, FT_Size size, FT_UInt glyph_index, FT_Int32 load_flags ) { FT_Face face = slot->face; FT_Error error; FT_Fixed x_scale = size->metrics.x_scale; FT_Fixed y_scale = size->metrics.y_scale; AH_Face_Globals face_globals = FACE_GLOBALS( face ); FT_Render_Mode hint_mode = FT_LOAD_TARGET_MODE( load_flags ); /* first of all, we need to check that we're using the correct face and */ /* global hints to load the glyph */ if ( hinter->face != face || hinter->globals != face_globals ) { hinter->face = face; if ( !face_globals ) { error = ah_hinter_new_face_globals( hinter, face, 0 ); if ( error ) goto Exit; } hinter->globals = FACE_GLOBALS( face ); face_globals = FACE_GLOBALS( face ); }#ifdef FT_CONFIG_CHESTER_BLUE_SCALE /* try to optimize the y_scale so that the top of non-capital letters * is aligned on a pixel boundary whenever possible */ { AH_Globals design = &face_globals->design; FT_Pos shoot = design->blue_shoots[AH_BLUE_SMALL_TOP]; /* the value of 'shoot' will be -1000 if the font doesn't have */ /* small latin letters; we simply check the sign here... */ if ( shoot > 0 ) { FT_Pos scaled = FT_MulFix( shoot, y_scale ); FT_Pos fitted = ( scaled + 32 ) & -64; if ( scaled != fitted ) { /* adjust y_scale */ y_scale = FT_MulDiv( y_scale, fitted, scaled ); /* adust x_scale */ if ( fitted < scaled ) x_scale -= x_scale / 50; /* x_scale*0.98 with integers */ } } }#endif /* FT_CONFIG_CHESTER_BLUE_SCALE */ /* now, we must check the current character pixel size to see if we */ /* need to rescale the global metrics */ if ( face_globals->x_scale != x_scale || face_globals->y_scale != y_scale ) ah_hinter_scale_globals( hinter, x_scale, y_scale ); ah_loader_rewind( hinter->loader ); /* reset hinting flags according to load flags and current render target */ hinter->do_horz_hints = FT_BOOL( !(load_flags & FT_LOAD_NO_AUTOHINT) ); hinter->do_vert_hints = FT_BOOL( !(load_flags & FT_LOAD_NO_AUTOHINT) );#ifdef DEBUG_HINTER hinter->do_horz_hints = !ah_debug_disable_vert; /* not a bug, the meaning */ hinter->do_vert_hints = !ah_debug_disable_horz; /* of h/v is inverted! */#endif /* we snap the width of vertical stems for the monochrome and */ /* horizontal LCD rendering targets only. Corresponds to X snapping. */ hinter->do_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO || hint_mode == FT_RENDER_MODE_LCD ); /* we snap the width of horizontal stems for the monochrome and */ /* vertical LCD rendering targets only. Corresponds to Y snapping. */ hinter->do_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO || hint_mode == FT_RENDER_MODE_LCD_V ); hinter->do_stem_adjust = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT ); load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM ; error = ah_hinter_load( hinter, glyph_index, load_flags, 0 ); Exit: return error; } /* retrieve a face's autohint globals for client applications */ FT_LOCAL_DEF( void ) ah_hinter_get_global_hints( AH_Hinter hinter, FT_Face face, void** global_hints, long* global_len ) { AH_Globals globals = 0; FT_Memory memory = hinter->memory; FT_Error error; /* allocate new master globals */ if ( FT_NEW( globals ) ) goto Fail; /* compute face globals if needed */ if ( !FACE_GLOBALS( face ) ) { error = ah_hinter_new_face_globals( hinter, face, 0 ); if ( error ) goto Fail; } *globals = FACE_GLOBALS( face )->design; *global_hints = globals; *global_len = sizeof( *globals ); return; Fail: FT_FREE( globals ); *global_hints = 0; *global_len = 0; } FT_LOCAL_DEF( void ) ah_hinter_done_global_hints( AH_Hinter hinter, void* global_hints ) { FT_Memory memory = hinter->memory; FT_FREE( global_hints ); }/* END */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -