📄 pfrgload.c
字号:
/***************************************************************************//* *//* pfrgload.c *//* *//* FreeType PFR glyph loader (body). *//* *//* Copyright 2002, 2003 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 "pfrgload.h"#include "pfrsbit.h"#include "pfrload.h" /* for macro definitions */#include FT_INTERNAL_DEBUG_H#include "pfrerror.h"#undef FT_COMPONENT#define FT_COMPONENT trace_pfr /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** PFR GLYPH BUILDER *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ FT_LOCAL_DEF( void ) pfr_glyph_init( PFR_Glyph glyph, FT_GlyphLoader loader ) { FT_ZERO( glyph ); glyph->loader = loader; glyph->path_begun = 0; FT_GlyphLoader_Rewind( loader ); } FT_LOCAL_DEF( void ) pfr_glyph_done( PFR_Glyph glyph ) { FT_Memory memory = glyph->loader->memory; FT_FREE( glyph->x_control ); glyph->y_control = NULL; glyph->max_xy_control = 0; glyph->num_x_control = 0; glyph->num_y_control = 0; FT_FREE( glyph->subs ); glyph->max_subs = 0; glyph->num_subs = 0; glyph->loader = NULL; glyph->path_begun = 0; } /* close current contour, if any */ static void pfr_glyph_close_contour( PFR_Glyph glyph ) { FT_GlyphLoader loader = glyph->loader; FT_Outline* outline = &loader->current.outline; FT_Int last, first; if ( !glyph->path_begun ) return; /* compute first and last point indices in current glyph outline */ last = outline->n_points - 1; first = 0; if ( outline->n_contours > 0 ) first = outline->contours[outline->n_contours - 1]; /* if the last point falls on the same location than the first one */ /* we need to delete it */ if ( last > first ) { FT_Vector* p1 = outline->points + first; FT_Vector* p2 = outline->points + last; if ( p1->x == p2->x && p1->y == p2->y ) { outline->n_points--; last--; } } /* don't add empty contours */ if ( last >= first ) outline->contours[outline->n_contours++] = (short)last; glyph->path_begun = 0; } /* reset glyph to start the loading of a new glyph */ static void pfr_glyph_start( PFR_Glyph glyph ) { glyph->path_begun = 0; } static FT_Error pfr_glyph_line_to( PFR_Glyph glyph, FT_Vector* to ) { FT_GlyphLoader loader = glyph->loader; FT_Outline* outline = &loader->current.outline; FT_Error error; /* check that we have begun a new path */ FT_ASSERT( glyph->path_begun != 0 ); error = FT_GlyphLoader_CheckPoints( loader, 1, 0 ); if ( !error ) { FT_UInt n = outline->n_points; outline->points[n] = *to; outline->tags [n] = FT_CURVE_TAG_ON; outline->n_points++; } return error; } static FT_Error pfr_glyph_curve_to( PFR_Glyph glyph, FT_Vector* control1, FT_Vector* control2, FT_Vector* to ) { FT_GlyphLoader loader = glyph->loader; FT_Outline* outline = &loader->current.outline; FT_Error error; /* check that we have begun a new path */ FT_ASSERT( glyph->path_begun != 0 ); error = FT_GlyphLoader_CheckPoints( loader, 3, 0 ); if ( !error ) { FT_Vector* vec = outline->points + outline->n_points; FT_Byte* tag = (FT_Byte*)outline->tags + outline->n_points; vec[0] = *control1; vec[1] = *control2; vec[2] = *to; tag[0] = FT_CURVE_TAG_CUBIC; tag[1] = FT_CURVE_TAG_CUBIC; tag[2] = FT_CURVE_TAG_ON; outline->n_points = (FT_Short)( outline->n_points + 3 ); } return error; } static FT_Error pfr_glyph_move_to( PFR_Glyph glyph, FT_Vector* to ) { FT_GlyphLoader loader = glyph->loader; FT_Error error; /* close current contour if any */ pfr_glyph_close_contour( glyph ); /* indicate that a new contour has started */ glyph->path_begun = 1; /* check that there is space for a new contour and a new point */ error = FT_GlyphLoader_CheckPoints( loader, 1, 1 ); if ( !error ) /* add new start point */ error = pfr_glyph_line_to( glyph, to ); return error; } static void pfr_glyph_end( PFR_Glyph glyph ) { /* close current contour if any */ pfr_glyph_close_contour( glyph ); /* merge the current glyph into the stack */ FT_GlyphLoader_Add( glyph->loader ); } /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** PFR GLYPH LOADER *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /* load a simple glyph */ static FT_Error pfr_glyph_load_simple( PFR_Glyph glyph, FT_Byte* p, FT_Byte* limit ) { FT_Error error = 0; FT_Memory memory = glyph->loader->memory; FT_UInt flags, x_count, y_count, i, count, mask; FT_Int x; PFR_CHECK( 1 ); flags = PFR_NEXT_BYTE( p ); /* test for composite glyphs */ FT_ASSERT( ( flags & PFR_GLYPH_IS_COMPOUND ) == 0 ); x_count = 0; y_count = 0; if ( flags & PFR_GLYPH_1BYTE_XYCOUNT ) { PFR_CHECK( 1 ); count = PFR_NEXT_BYTE( p ); x_count = ( count & 15 ); y_count = ( count >> 4 ); } else { if ( flags & PFR_GLYPH_XCOUNT ) { PFR_CHECK( 1 ); x_count = PFR_NEXT_BYTE( p ); } if ( flags & PFR_GLYPH_YCOUNT ) { PFR_CHECK( 1 ); y_count = PFR_NEXT_BYTE( p ); } } count = x_count + y_count; /* re-allocate array when necessary */ if ( count > glyph->max_xy_control ) { FT_UInt new_max = FT_PAD_CEIL( count, 8 ); if ( FT_RENEW_ARRAY( glyph->x_control, glyph->max_xy_control, new_max ) ) goto Exit; glyph->max_xy_control = new_max; } glyph->y_control = glyph->x_control + x_count; mask = 0; x = 0; for ( i = 0; i < count; i++ ) { if ( ( i & 7 ) == 0 ) { PFR_CHECK( 1 ); mask = PFR_NEXT_BYTE( p ); } if ( mask & 1 ) { PFR_CHECK( 2 ); x = PFR_NEXT_SHORT( p ); } else { PFR_CHECK( 1 ); x += PFR_NEXT_BYTE( p ); } glyph->x_control[i] = x; mask >>= 1; } /* XXX: for now we ignore the secondary stroke and edge definitions */ /* since we don't want to support native PFR hinting */ /* */ if ( flags & PFR_GLYPH_EXTRA_ITEMS ) { error = pfr_extra_items_skip( &p, limit ); if ( error ) goto Exit; } pfr_glyph_start( glyph ); /* now load a simple glyph */ { FT_Vector pos[4]; FT_Vector* cur; pos[0].x = pos[0].y = 0; pos[3] = pos[0]; for (;;) { FT_Int format, args_format = 0, args_count, n; /***************************************************************/ /* read instruction */ /* */ PFR_CHECK( 1 ); format = PFR_NEXT_BYTE( p ); switch ( format >> 4 ) { case 0: /* end glyph */ FT_TRACE6(( "- end glyph" )); args_count = 0; break; case 1: /* general line operation */ FT_TRACE6(( "- general line" )); goto Line1; case 4: /* move to inside contour */ FT_TRACE6(( "- move to inside" )); goto Line1; case 5: /* move to outside contour */ FT_TRACE6(( "- move to outside" )); Line1: args_format = format & 15; args_count = 1; break; case 2: /* horizontal line to */ FT_TRACE6(( "- horizontal line to cx.%d", format & 15 )); pos[0].y = pos[3].y; pos[0].x = glyph->x_control[format & 15]; pos[3] = pos[0]; args_count = 0; break; case 3: /* vertical line to */ FT_TRACE6(( "- vertical line to cy.%d", format & 15 )); pos[0].x = pos[3].x; pos[0].y = glyph->y_control[format & 15]; pos[3] = pos[0]; args_count = 0; break; case 6: /* horizontal to vertical curve */ FT_TRACE6(( "- hv curve " )); args_format = 0xB8E; args_count = 3; break; case 7: /* vertical to horizontal curve */ FT_TRACE6(( "- vh curve" )); args_format = 0xE2B; args_count = 3; break; default: /* general curve to */ FT_TRACE6(( "- general curve" ));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -