📄 pfrgload.c
字号:
/***************************************************************************/
/* */
/* pfrgload.c */
/* */
/* FreeType PFR glyph loader (body). */
/* */
/* Copyright 2002, 2003, 2005 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_CHECK_POINTS( 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_CHECK_POINTS( 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_CHECK_POINTS( 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 + -