📄 t1gload.c
字号:
goto Syntax_Error; } break; case op_callsubr: { T1_Int index = top[0]; if ( index < 0 || index >= num_subrs ) { FT_ERROR(( "T1.Parse_CharStrings : invalid subrs index\n" )); goto Syntax_Error; } if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS ) { FT_ERROR(( "T1.Parse_CharStrings : too many nested subrs\n" )); goto Syntax_Error; } zone->cursor = ip; /* save current instruction pointer */ zone++; zone->base = subrs_base[index]; zone->limit = zone->base + subrs_len[index]; zone->cursor = zone->base; if (!zone->base) { FT_ERROR(( "T1.Parse_CharStrings : invoking empty subrs !!\n" )); goto Syntax_Error; } decoder->zone = zone; ip = zone->base; limit = zone->limit; } break; case op_pop: FT_ERROR(( "T1.Parse_CharStrings : unexpected POP\n" )); goto Syntax_Error; case op_return: if ( zone <= decoder->zones ) { FT_ERROR(( "T1.Parse_CharStrings : unexpected return\n" )); goto Syntax_Error; } zone--; ip = zone->cursor; limit = zone->limit; decoder->zone = zone; break; case op_setcurrentpoint: FT_ERROR(( "T1.Parse_CharStrings : unexpected SETCURRENTPOINT\n" )); goto Syntax_Error; break; default: FT_ERROR(( "T1.Parse_CharStrings : unhandled opcode %d\n", op )); goto Syntax_Error; } decoder->top = top; } } return error; Syntax_Error: return T1_Err_Syntax_Error; Stack_Underflow: return T1_Err_Stack_Underflow; }/*************************************************************************//* *//* <Function> T1_Add_Points *//* *//* <Description> *//* Checks that there is enough room in the current load glyph outline *//* to accept "num_points" additional outline points. If not, this *//* function grows the load outline's arrays accordingly.. *//* *//* <Input> *//* builder :: pointer to glyph builder object *//* num_points :: number of points that will be added later *//* *//* <Return> *//* Type1 error code. 0 means success *//* *//* <Note> *//* This function does NOT update the points count in the glyph builder*//* This must be done by the caller itself, after this function is *//* invoked.. *//* */ LOCAL_FUNC T1_Error T1_Add_Points( T1_Builder* builder, T1_Int num_points ) { T1_Int new_points; new_points = builder->base.n_points + builder->current.n_points + num_points; if ( new_points > builder->max_points ) { FT_Memory memory = builder->memory; T1_Error error; T1_Int increment = builder->current.points - builder->base.points; T1_Int current = builder->max_points; while ( builder->max_points < new_points ) builder->max_points += 16; if ( REALLOC_ARRAY( builder->base.points, current, builder->max_points, T1_Vector ) || REALLOC_ARRAY( builder->base.tags, current, builder->max_points, T1_Byte ) ) return error; builder->current.points = builder->base.points + increment; builder->current.tags = builder->base.tags + increment; } return T1_Err_Ok; }/*************************************************************************//* *//* <Function> T1_Add_Contours *//* *//* <Description> *//* Checks that there is enough room in the current load glyph outline *//* to accept "num_contours" additional contours. If not, this func *//* the load outline's arrays accordingly.. *//* *//* <Input> *//* builder :: pointer to glyph builder object *//* num_contours :: number of contours that will be added later *//* *//* <Return> *//* Type1 error code. 0 means success *//* *//* <Note> *//* This function does NOT update the contours count in the load glyph *//* This must be done by the caller itself, after this function is *//* invoked.. *//* */ LOCAL_FUNC T1_Error T1_Add_Contours( T1_Builder* builder, T1_Int num_contours ) { T1_Int new_contours; new_contours = builder->base.n_contours + builder->current.n_contours + num_contours; if ( new_contours > builder->max_contours && builder->load_points ) { T1_Error error; FT_Memory memory = builder->memory; T1_Int increment = builder->current.contours - builder->base.contours; T1_Int current = builder->max_contours; while ( builder->max_contours < new_contours ) builder->max_contours += 4; if ( REALLOC_ARRAY( builder->base.contours, current, builder->max_contours, T1_Short ) ) return error; builder->current.contours = builder->base.contours + increment; } return T1_Err_Ok; } /**********************************************************************/ /**********************************************************************/ /**********************************************************************/ /********** *********/ /********** *********/ /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ /********** *********/ /********** The following code is in charge of computing *********/ /********** the maximum advance width of the font. It *********/ /********** quickly process each glyph charstring to *********/ /********** extract the value from either a "sbw" or "seac" *********/ /********** operator. *********/ /********** *********/ /**********************************************************************/ /**********************************************************************/ /**********************************************************************/ static T1_Error maxadv_sbw( T1_Decoder* decoder, T1_Pos sbx, T1_Pos sby, T1_Pos wx, T1_Pos wy ) { if (wx > decoder->builder.advance.x) decoder->builder.advance.x = wx; (void)sbx; (void)sby; (void)wy; return -1; /* return an error code to exit the Type 1 parser */ /* immediately. */ } static T1_Int maxadv_error( void ) { /* we should never reach this code, unless with a buggy font */ return -2; } /* the maxadv_gbuilder_interface is used when computing the maximum */ /* advance width of all glyphs in a given font. We only process the */ /* 'sbw' operator here, and return an error for all others.. */ /* Note that "seac" is processed by the T1_Decoder */ static const T1_Builder_Funcs maxadv_builder_interface = { (T1_Builder_EndChar) maxadv_error, (T1_Builder_Sbw) maxadv_sbw, (T1_Builder_ClosePath) maxadv_error, (T1_Builder_RLineTo) maxadv_error, (T1_Builder_RMoveTo) maxadv_error, (T1_Builder_RCurveTo) maxadv_error }; /* the maxadv_interface is used when computing the maximum advance */ /* with of the set of glyphs in a given font file. We only process */ /* the "seac" operator and return immediately.. */ static const T1_Hinter_Funcs maxadv_hinter_interface = { (T1_Hinter_DotSection) maxadv_error, (T1_Hinter_ChangeHints) maxadv_error, (T1_Hinter_Stem) maxadv_error, (T1_Hinter_Stem3) maxadv_error, }; LOCAL_FUNC T1_Error T1_Compute_Max_Advance( T1_Face face, T1_Int *max_advance ) { T1_Error error; T1_Decoder decoder; T1_Int glyph_index; T1_Font* type1 = &face->type1; *max_advance = 0; /* Initialise load decoder */ T1_Init_Decoder( &decoder, &maxadv_hinter_interface ); T1_Init_Builder( &decoder.builder, face, 0, 0, &maxadv_builder_interface ); /* For each glyph, parse the glyph charstring and extract */ /* the advance width.. */ for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ ) { /* now get load the unscaled outline */ error = T1_Parse_CharStrings( &decoder, type1->charstrings [glyph_index], type1->charstrings_len[glyph_index], type1->num_subrs, type1->subrs, type1->subrs_len ); /* ignore the error if one occured - skip to next glyph */ (void)error; } *max_advance = decoder.builder.advance.x; return T1_Err_Ok; } /**********************************************************************/ /**********************************************************************/ /**********************************************************************/ /********** *********/ /********** *********/ /********** UNHINTED GLYPH LOADER *********/ /********** *********/ /********** The following code is in charge of loading a *********/ /********** single outline. It completely ignores hinting *********/ /********** and is used when FT_LOAD_NO_HINTING is set. *********/ /********** *********/ /********** The Type 1 hinter is located in "t1hint.c" *********/ /********** *********/ /**********************************************************************/ /**********************************************************************/ /**********************************************************************/ static T1_Error close_open_path( T1_Builder* builder ) { T1_Error error; FT_Outline* cur = &builder->current; T1_Int num_points; T1_Int first_point; /* Some fonts, like Hershey, are made of "open paths" which are */ /* now managed directly by FreeType. In this case, it is necessary */ /* to close the path by duplicating its points in reverse order, */ /* which is precisely the purpose of this function */ /* first compute the number of points to duplicate.. */ if (cur->n_contours > 1) first_point = cur->contours[ cur->n_contours-2 ]+1; else first_point = 0; num_points = cur->n_points - first_point - 2; if ( num_points > 0 ) { T1_Vector* source_point; char* source_tags; T1_Vector* point; char* tags; error = T1_Add_Points( builder, num_points ); if (error) return error; point = cur->points + cur->n_points; tags = cur->tags + cur->n_points; source_point = point - 2; source_tags = tags - 2; cur->n_points += num_points; if ( builder->load_points ) do { *point++ = *source_point--; *tags++ = *source_tags--; num_points--; } while (num_points > 0); } builder->path_begun = 0; return T1_Err_Ok; } static T1_Error gload_closepath( T1_Builder* builder ) { FT_Outline* cur = &builder->current; /* save current contour, if any */ if ( cur->n_contours > 0 ) cur->contours[cur->n_contours-1] = cur->n_points-1;#ifndef T1_CONFIG_OPTION_DISABLE_HINTER /* hint latest points if needed - this is not strictly required */ /* there, but it helps for debugging, and doesn't affect performance */ if ( builder->pass == 1 ) T1_Hint_Points( builder );#endif builder->path_begun = 0; return T1_Err_Ok; } static T1_Error gload_endchar( T1_Builder* builder ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -