📄 t1gload.c
字号:
FT_Outline* cur = &builder->current; T1_Error error; /* close path if needed */ if (builder->path_begun) { error = close_open_path( builder ); if (error) return error; } error = gload_closepath( builder ); builder->base.n_points += cur->n_points; builder->base.n_contours += cur->n_contours; return error; } static T1_Error gload_sbw( T1_Builder* builder, T1_Pos sbx, T1_Pos sby, T1_Pos wx, T1_Pos wy ) { builder->left_bearing.x += sbx; builder->left_bearing.y += sby; builder->advance.x = wx; builder->advance.y = wy; builder->last.x = sbx; builder->last.y = sby; return 0; } static T1_Error gload_rlineto( T1_Builder* builder, T1_Pos dx, T1_Pos dy ) { T1_Error error; FT_Outline* cur = &builder->current; T1_Vector vec; /* grow buffer if necessary */ error = T1_Add_Points ( builder, 1 ); if (error) return error; if ( builder->load_points ) { /* save point */ vec.x = builder->last.x + dx; vec.y = builder->last.y + dy; cur->points[cur->n_points] = vec; cur->tags [cur->n_points] = FT_Curve_Tag_On; builder->last = vec; } cur->n_points++; builder->path_begun = 1; return T1_Err_Ok; } static T1_Error gload_rmoveto( T1_Builder* builder, T1_Pos dx, T1_Pos dy ) { T1_Error error; FT_Outline* cur = &builder->current; T1_Vector vec; /* in the case where "path_begun" is set, we have a rmoveto */ /* after some normal path definition. When the face's paint */ /* type is set to 1, this means that we have an "open path", */ /* also called a 'stroke'. The FreeType raster doesn't support */ /* opened path, so we'll close it explicitely there.. */ if ( builder->path_begun && builder->face->type1.paint_type == 1 ) { if ( builder->face->type1.paint_type == 1 ) { error = close_open_path( builder ); if (error) return error; } } /* grow buffer if necessary */ error = T1_Add_Contours( builder, 1 ) || T1_Add_Points ( builder, 1 ); if (error) return error; /* save current contour, if any */ if ( cur->n_contours > 0 ) cur->contours[cur->n_contours-1] = cur->n_points-1; if ( builder->load_points ) { /* save point */ vec.x = builder->last.x + dx; vec.y = builder->last.y + dy; cur->points[cur->n_points] = vec; cur->tags [cur->n_points] = FT_Curve_Tag_On; builder->last = vec; } cur->n_contours++; cur->n_points++; return T1_Err_Ok; } static T1_Error gload_rrcurveto( T1_Builder* builder, T1_Pos dx1, T1_Pos dy1, T1_Pos dx2, T1_Pos dy2, T1_Pos dx3, T1_Pos dy3 ) { T1_Error error; FT_Outline* cur = &builder->current; T1_Vector vec; T1_Vector* points; char* tags; /* grow buffer if necessary */ error = T1_Add_Points ( builder, 3 ); if (error) return error; if ( builder->load_points ) { /* save point */ points = cur->points + cur->n_points; tags = cur->tags + cur->n_points; vec.x = builder->last.x + dx1; vec.y = builder->last.y + dy1; points[0] = vec; tags[0] = FT_Curve_Tag_Cubic; vec.x += dx2; vec.y += dy2; points[1] = vec; tags[1] = FT_Curve_Tag_Cubic; vec.x += dx3; vec.y += dy3; points[2] = vec; tags[2] = FT_Curve_Tag_On; builder->last = vec; } cur->n_points += 3; builder->path_begun = 1; return T1_Err_Ok; } static T1_Error gload_ignore( void ) { return 0; } static const T1_Builder_Funcs gload_builder_interface = { gload_endchar, gload_sbw, gload_closepath, gload_rlineto, gload_rmoveto, gload_rrcurveto }; static const T1_Builder_Funcs gload_builder_interface_null = { (T1_Builder_EndChar) gload_ignore, (T1_Builder_Sbw) gload_sbw, /* record left bearing */ (T1_Builder_ClosePath) gload_ignore, (T1_Builder_RLineTo) gload_ignore, (T1_Builder_RMoveTo) gload_ignore, (T1_Builder_RCurveTo) gload_ignore }; static const T1_Hinter_Funcs gload_hinter_interface = { (T1_Hinter_DotSection) gload_ignore, /* dotsection */ (T1_Hinter_ChangeHints) gload_ignore, /* changehints */ (T1_Hinter_Stem) gload_ignore, /* hstem & vstem */ (T1_Hinter_Stem3) gload_ignore, /* hstem3 & vestem3 */ }; LOCAL_FUNC T1_Error T1_Load_Glyph( T1_GlyphSlot glyph, T1_Size size, T1_Int glyph_index, T1_Int load_flags ) { T1_Error error; T1_Decoder decoder; T1_Face face = (T1_Face)glyph->root.face; T1_Bool hinting; T1_Font* type1 = &face->type1; glyph->x_scale = size->root.metrics.x_scale; glyph->y_scale = size->root.metrics.y_scale; glyph->root.outline.n_points = 0; glyph->root.outline.n_contours = 0; glyph->root.format = ft_glyph_format_none; hinting = 0;#ifndef T1_CONFIG_OPTION_DISABLE_HINTER /*****************************************************************/ /* */ /* Hinter overview : */ /* */ /* This is a two-pass hinter. On the first pass, the hints */ /* are all recorded by the hinter, and no point is loaded */ /* in the outline. */ /* */ /* When the first pass is finished, all stems hints are */ /* grid-fitted at once. */ /* */ /* Then, a second pass is performed to load the outline */ /* points as well as hint/scale them correctly. */ /* */ hinting = (load_flags & (FT_LOAD_NO_SCALE|FT_LOAD_NO_HINTING)) == 0; if ( hinting ) { /* Pass 1 - don't record points, simply stem hints */ T1_Init_Decoder( &decoder, &t1_hinter_funcs ); T1_Init_Builder( &decoder.builder, face, size, glyph, &gload_builder_interface_null ); glyph->hints->hori_stems.num_stems = 0; glyph->hints->vert_stems.num_stems = 0; error = T1_Parse_CharStrings( &decoder, type1->charstrings [glyph_index], type1->charstrings_len[glyph_index], type1->num_subrs, type1->subrs, type1->subrs_len ); /* All right, pass 1 is finished, now grid-fit all stem hints */ T1_Hint_Stems( &decoder.builder ); /* Pass 2 - record and scale/hint the points */ T1_Init_Decoder( &decoder, &t1_hinter_funcs ); T1_Init_Builder( &decoder.builder, face, size, glyph, &gload_builder_interface ); decoder.builder.pass = 1; error = T1_Parse_CharStrings( &decoder, type1->charstrings [glyph_index], type1->charstrings_len[glyph_index], type1->num_subrs, type1->subrs, type1->subrs_len ); /* save new glyph tables */ T1_Done_Builder( &decoder.builder ); } else#endif { T1_Init_Decoder( &decoder, &gload_hinter_interface ); T1_Init_Builder( &decoder.builder, face, size, glyph, &gload_builder_interface ); /* now 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 ); /* save new glyph tables */ T1_Done_Builder( &decoder.builder ); } /* Now, set the metrics.. - this is rather simple, as : */ /* the left side bearing is the xMin, and the top side */ /* bearing the yMax.. */ if (!error) { FT_BBox cbox; FT_Glyph_Metrics* metrics = &glyph->root.metrics; FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); /* grid fit the bounding box if necessary */ if (hinting) { cbox.xMin &= -64; cbox.yMin &= -64; cbox.xMax = ( cbox.xMax+63 ) & -64; cbox.yMax = ( cbox.yMax+63 ) & -64; } metrics->width = cbox.xMax - cbox.xMin; metrics->height = cbox.yMax - cbox.yMin; metrics->horiBearingX = cbox.xMin; metrics->horiBearingY = cbox.yMax; /* copy the _unscaled_ advance width */ metrics->horiAdvance = decoder.builder.advance.x; /* make up vertical metrics */ metrics->vertBearingX = 0; metrics->vertBearingY = 0; metrics->vertAdvance = 0; glyph->root.format = ft_glyph_format_outline; glyph->root.outline.flags &= ft_outline_owner; if ( size->root.metrics.y_ppem < 24 ) glyph->root.outline.flags |= ft_outline_high_precision; /* glyph->root.outline.second_pass = TRUE; glyph->root.outline.high_precision = ( size->root.metrics.y_ppem < 24 ); glyph->root.outline.dropout_mode = 2; */ if ( hinting ) { /* adjust the advance width */ /* XXX : TODO : consider stem hints grid-fit */ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, glyph->x_scale ); } else if ( (load_flags & FT_LOAD_NO_SCALE) == 0 ) { /* scale the outline and the metrics */ T1_Int n; FT_Outline* cur = &decoder.builder.base; T1_Vector* vec = cur->points; T1_Fixed x_scale = glyph->x_scale; T1_Fixed y_scale = glyph->y_scale; /* First of all, scale the points */ for ( n = cur->n_points; n > 0; n--, vec++ ) { vec->x = FT_MulFix( vec->x, x_scale ); vec->y = FT_MulFix( vec->y, y_scale ); } /* Then scale the metrics */ metrics->width = FT_MulFix( metrics->width, x_scale ); metrics->height = FT_MulFix( metrics->height, y_scale ); metrics->horiBearingX = FT_MulFix( metrics->horiBearingX, x_scale ); metrics->horiBearingY = FT_MulFix( metrics->horiBearingY, y_scale ); metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale ); metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale ); metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, x_scale ); } } return error; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -