📄 t2gload.c
字号:
/***************************************************************************//* *//* t2gload.c *//* *//* OpenType Glyph Loader (body). *//* *//* Copyright 1996-2000 by *//* David Turner, Robert Wilhelm, and Werner Lemberg. *//* *//* This file is part of the FreeType project, and may only be used, *//* modified, and distributed under the terms of the FreeType project *//* license, LICENSE.TXT. By continuing to use, modify, or distribute *//* this file you indicate that you have read the license and *//* understand and accept it fully. *//* *//***************************************************************************/#include <freetype/internal/ftdebug.h>#include <freetype/internal/ftcalc.h>#include <freetype/internal/ftstream.h>#include <freetype/internal/sfnt.h>#include <freetype/ftoutln.h>#include <freetype/tttags.h>#ifdef FT_FLAT_COMPILE#include "t2load.h"#include "t2gload.h"#else#include <cff/t2load.h>#include <cff/t2gload.h>#endif#include <freetype/internal/t2errors.h> /*************************************************************************/ /* */ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ /* messages during execution. */ /* */#undef FT_COMPONENT#define FT_COMPONENT trace_t2gload typedef enum T2_Operator_ { t2_op_unknown = 0, t2_op_rmoveto, t2_op_hmoveto, t2_op_vmoveto, t2_op_rlineto, t2_op_hlineto, t2_op_vlineto, t2_op_rrcurveto, t2_op_hhcurveto, t2_op_hvcurveto, t2_op_rcurveline, t2_op_rlinecurve, t2_op_vhcurveto, t2_op_vvcurveto, t2_op_flex, t2_op_hflex, t2_op_hflex1, t2_op_flex1, t2_op_endchar, t2_op_hstem, t2_op_vstem, t2_op_hstemhm, t2_op_vstemhm, t2_op_hintmask, t2_op_cntrmask, t2_op_abs, t2_op_add, t2_op_sub, t2_op_div, t2_op_neg, t2_op_random, t2_op_mul, t2_op_sqrt, t2_op_blend, t2_op_drop, t2_op_exch, t2_op_index, t2_op_roll, t2_op_dup, t2_op_put, t2_op_get, t2_op_store, t2_op_load, t2_op_and, t2_op_or, t2_op_not, t2_op_eq, t2_op_ifelse, t2_op_callsubr, t2_op_callgsubr, t2_op_return, /* do not remove */ t2_op_max } T2_Operator;#define T2_COUNT_CHECK_WIDTH 0x80#define T2_COUNT_EXACT 0x40#define T2_COUNT_CLEAR_STACK 0x20 static const FT_Byte t2_argument_counts[] = { 0, /* unknown */ 2 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT, /* rmoveto */ 1 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT, 1 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT, 0 | T2_COUNT_CLEAR_STACK, /* rlineto */ 0 | T2_COUNT_CLEAR_STACK, 0 | T2_COUNT_CLEAR_STACK, 0 | T2_COUNT_CLEAR_STACK, /* rrcurveto */ 0 | T2_COUNT_CLEAR_STACK, 0 | T2_COUNT_CLEAR_STACK, 0 | T2_COUNT_CLEAR_STACK, 0 | T2_COUNT_CLEAR_STACK, 0 | T2_COUNT_CLEAR_STACK, 0 | T2_COUNT_CLEAR_STACK, 13, /* flex */ 7, 9, 11, 0 | T2_COUNT_CHECK_WIDTH, /* endchar */ 2 | T2_COUNT_CHECK_WIDTH, /* hstem */ 2 | T2_COUNT_CHECK_WIDTH, 2 | T2_COUNT_CHECK_WIDTH, 2 | T2_COUNT_CHECK_WIDTH, 0, /* hintmask */ 0, /* cntrmask */ 1, /* abs */ 2, 2, 2, 1, 0, 2, 1, 1, /* blend */ 1, /* drop */ 2, 1, 2, 1, 2, /* put */ 1, 4, 3, 2, /* and */ 2, 1, 2, 4, 1, /* callsubr */ 1, 0 }; /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /********** *********/ /********** *********/ /********** GENERIC CHARSTRING PARSING *********/ /********** *********/ /********** *********/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* */ /* <Function> */ /* T2_Init_Builder */ /* */ /* <Description> */ /* Initializes a given glyph builder. */ /* */ /* <InOut> */ /* builder :: A pointer to the glyph builder to initialize. */ /* */ /* <Input> */ /* face :: The current face object. */ /* */ /* size :: The current size object. */ /* */ /* glyph :: The current glyph object. */ /* */ static void T2_Init_Builder( T2_Builder* builder, TT_Face face, T2_Size size, T2_GlyphSlot glyph ) { builder->path_begun = 0; builder->load_points = 1; builder->face = face; builder->glyph = glyph; builder->memory = face->root.memory; if ( glyph ) { FT_GlyphLoader* loader = glyph->root.internal->loader; builder->loader = loader; builder->base = &loader->base.outline; builder->current = &loader->current.outline; FT_GlyphLoader_Rewind( loader ); } if ( size ) { builder->scale_x = size->metrics.x_scale; builder->scale_y = size->metrics.y_scale; } builder->pos_x = 0; builder->pos_y = 0; builder->left_bearing.x = 0; builder->left_bearing.y = 0; builder->advance.x = 0; builder->advance.y = 0; } /*************************************************************************/ /* */ /* <Function> */ /* T2_Done_Builder */ /* */ /* <Description> */ /* Finalizes a given glyph builder. Its contents can still be used */ /* after the call, but the function saves important information */ /* within the corresponding glyph slot. */ /* */ /* <Input> */ /* builder :: A pointer to the glyph builder to finalize. */ /* */ static void T2_Done_Builder( T2_Builder* builder ) { T2_GlyphSlot glyph = builder->glyph; if ( glyph ) glyph->root.outline = *builder->base; } /*************************************************************************/ /* */ /* <Function> */ /* t2_compute_bias */ /* */ /* <Description> */ /* Computes the bias value in dependence of the number of glyph */ /* subroutines. */ /* */ /* <Input> */ /* num_subrs :: The number of glyph subroutines. */ /* */ /* <Return> */ /* The bias value. */ static FT_Int t2_compute_bias( FT_UInt num_subrs ) { FT_Int result; if ( num_subrs < 1240 ) result = 107; else if ( num_subrs < 33900 ) result = 1131; else result = 32768; return result; } /*************************************************************************/ /* */ /* <Function> */ /* T2_Init_Decoder */ /* */ /* <Description> */ /* Initializes a given glyph decoder. */ /* */ /* <InOut> */ /* decoder :: A pointer to the glyph builder to initialize. */ /* */ /* <Input> */ /* face :: The current face object. */ /* */ /* size :: The current size object. */ /* */ /* slot :: The current glyph object. */ /* */ FT_LOCAL_DEF void T2_Init_Decoder( T2_Decoder* decoder, TT_Face face, T2_Size size, T2_GlyphSlot slot ) { CFF_Font* cff = (CFF_Font*)face->extra.data; /* clear everything */ MEM_Set( decoder, 0, sizeof ( *decoder ) ); /* initialize builder */ T2_Init_Builder( &decoder->builder, face, size, slot ); /* initialize Type2 decoder */ decoder->num_globals = cff->num_global_subrs; decoder->globals = cff->global_subrs; decoder->globals_bias = t2_compute_bias( decoder->num_globals ); } /* this function is used to select the locals subrs array */ FT_LOCAL_DEF void T2_Prepare_Decoder( T2_Decoder* decoder, FT_UInt glyph_index ) { CFF_Font* cff = (CFF_Font*)decoder->builder.face->extra.data; CFF_SubFont* sub = &cff->top_font; /* manage CID fonts */ if ( cff->num_subfonts >= 1 ) { FT_Byte fd_index = CFF_Get_FD( &cff->fd_select, glyph_index ); sub = cff->subfonts[fd_index]; } decoder->num_locals = sub->num_local_subrs; decoder->locals = sub->local_subrs; decoder->locals_bias = t2_compute_bias( decoder->num_locals ); decoder->glyph_width = sub->private_dict.default_width; decoder->nominal_width = sub->private_dict.nominal_width; } /* check that there is enough room for `count' more points */ static FT_Error check_points( T2_Builder* builder, FT_Int count ) { return FT_GlyphLoader_Check_Points( builder->loader, count, 0 ); } /* add a new point, do not check space */ static void add_point( T2_Builder* builder, FT_Pos x, FT_Pos y, FT_Byte flag ) { FT_Outline* outline = builder->current; if ( builder->load_points ) { FT_Vector* point = outline->points + outline->n_points; FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; point->x = x >> 16; point->y = y >> 16; *control = flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic; builder->last = *point; } outline->n_points++; } /* check space for a new on-curve point, then add it */ static FT_Error add_point1( T2_Builder* builder, FT_Pos x, FT_Pos y ) { FT_Error error; error = check_points( builder, 1 ); if ( !error ) add_point( builder, x, y, 1 ); return error; } /* check room for a new contour, then add it */ static FT_Error add_contour( T2_Builder* builder ) { FT_Outline* outline = builder->current; FT_Error error; if ( !builder->load_points ) { outline->n_contours++; return T2_Err_Ok; } error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 ); if ( !error ) { if ( outline->n_contours > 0 ) outline->contours[outline->n_contours - 1] = outline->n_points - 1; outline->n_contours++; } return error; } /* if a path was begun, add its first on-curve point */ static FT_Error start_point( T2_Builder* builder, FT_Pos x, FT_Pos y ) { FT_Error error = 0; /* test whether we are building a new contour */ if ( !builder->path_begun ) { builder->path_begun = 1; error = add_contour( builder ); if ( !error ) error = add_point1( builder, x, y ); } return error; } /* close the current contour */ static void close_contour( T2_Builder* builder ) { FT_Outline* outline = builder->current; /* XXXX: We must not include the last point in the path if it */ /* is located on the first point. */ if ( outline->n_points > 1 ) { FT_Int first = 0; FT_Vector* p1 = outline->points + first; FT_Vector* p2 = outline->points + outline->n_points - 1; FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; if ( outline->n_contours > 1 ) { first = outline->contours[outline->n_contours - 2] + 1; p1 = outline->points + first; } /* `delete' last point only if it coincides with the first */ /* point and it is not a control point (which can happen). */ if ( p1->x == p2->x && p1->y == p2->y ) if ( *control == FT_Curve_Tag_On ) outline->n_points--; } if ( outline->n_contours > 0 ) outline->contours[outline->n_contours - 1] = outline->n_points - 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -