📄 cffgload.c
字号:
/***************************************************************************/
/* */
/* cffgload.c */
/* */
/* OpenType Glyph Loader (body). */
/* */
/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 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 <ft2build.h>
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_CALC_H
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_SFNT_H
#include FT_OUTLINE_H
#include FT_TRUETYPE_TAGS_H
#include FT_INTERNAL_POSTSCRIPT_HINTS_H
#include "cffobjs.h"
#include "cffload.h"
#include "cffgload.h"
#include "cfferrs.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_cffgload
typedef enum CFF_Operator_
{
cff_op_unknown = 0,
cff_op_rmoveto,
cff_op_hmoveto,
cff_op_vmoveto,
cff_op_rlineto,
cff_op_hlineto,
cff_op_vlineto,
cff_op_rrcurveto,
cff_op_hhcurveto,
cff_op_hvcurveto,
cff_op_rcurveline,
cff_op_rlinecurve,
cff_op_vhcurveto,
cff_op_vvcurveto,
cff_op_flex,
cff_op_hflex,
cff_op_hflex1,
cff_op_flex1,
cff_op_endchar,
cff_op_hstem,
cff_op_vstem,
cff_op_hstemhm,
cff_op_vstemhm,
cff_op_hintmask,
cff_op_cntrmask,
cff_op_dotsection, /* deprecated, acts as no-op */
cff_op_abs,
cff_op_add,
cff_op_sub,
cff_op_div,
cff_op_neg,
cff_op_random,
cff_op_mul,
cff_op_sqrt,
cff_op_blend,
cff_op_drop,
cff_op_exch,
cff_op_index,
cff_op_roll,
cff_op_dup,
cff_op_put,
cff_op_get,
cff_op_store,
cff_op_load,
cff_op_and,
cff_op_or,
cff_op_not,
cff_op_eq,
cff_op_ifelse,
cff_op_callsubr,
cff_op_callgsubr,
cff_op_return,
/* do not remove */
cff_op_max
} CFF_Operator;
#define CFF_COUNT_CHECK_WIDTH 0x80
#define CFF_COUNT_EXACT 0x40
#define CFF_COUNT_CLEAR_STACK 0x20
static const FT_Byte cff_argument_counts[] =
{
0, /* unknown */
2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */
1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
0 | CFF_COUNT_CLEAR_STACK, /* rlineto */
0 | CFF_COUNT_CLEAR_STACK,
0 | CFF_COUNT_CLEAR_STACK,
0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */
0 | CFF_COUNT_CLEAR_STACK,
0 | CFF_COUNT_CLEAR_STACK,
0 | CFF_COUNT_CLEAR_STACK,
0 | CFF_COUNT_CLEAR_STACK,
0 | CFF_COUNT_CLEAR_STACK,
0 | CFF_COUNT_CLEAR_STACK,
13, /* flex */
7,
9,
11,
0 | CFF_COUNT_CHECK_WIDTH, /* endchar */
2 | CFF_COUNT_CHECK_WIDTH, /* hstem */
2 | CFF_COUNT_CHECK_WIDTH,
2 | CFF_COUNT_CHECK_WIDTH,
2 | CFF_COUNT_CHECK_WIDTH,
0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */
0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */
0, /* dotsection */
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> */
/* cff_builder_init */
/* */
/* <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
cff_builder_init( CFF_Builder* builder,
TT_Face face,
CFF_Size size,
CFF_GlyphSlot glyph,
FT_Bool hinting )
{
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 );
builder->hints_globals = 0;
builder->hints_funcs = 0;
if ( hinting && size )
{
builder->hints_globals = size->root.internal;
builder->hints_funcs = glyph->root.internal->glyph_hints;
}
}
if ( size )
{
builder->scale_x = size->root.metrics.x_scale;
builder->scale_y = size->root.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> */
/* cff_builder_done */
/* */
/* <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
cff_builder_done( CFF_Builder* builder )
{
CFF_GlyphSlot glyph = builder->glyph;
if ( glyph )
glyph->root.outline = *builder->base;
}
/*************************************************************************/
/* */
/* <Function> */
/* cff_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
cff_compute_bias( FT_UInt num_subrs )
{
FT_Int result;
if ( num_subrs < 1240 )
result = 107;
else if ( num_subrs < 33900U )
result = 1131;
else
result = 32768U;
return result;
}
/*************************************************************************/
/* */
/* <Function> */
/* cff_decoder_init */
/* */
/* <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 )
cff_decoder_init( CFF_Decoder* decoder,
TT_Face face,
CFF_Size size,
CFF_GlyphSlot slot,
FT_Bool hinting,
FT_Render_Mode hint_mode )
{
CFF_Font cff = (CFF_Font)face->extra.data;
/* clear everything */
FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
/* initialize builder */
cff_builder_init( &decoder->builder, face, size, slot, hinting );
/* initialize Type2 decoder */
decoder->num_globals = cff->num_global_subrs;
decoder->globals = cff->global_subrs;
decoder->globals_bias = cff_compute_bias( decoder->num_globals );
decoder->hint_mode = hint_mode;
}
/* this function is used to select the locals subrs array */
FT_LOCAL_DEF( void )
cff_decoder_prepare( CFF_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_fd_select_get( &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 = cff_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 space for `count' more points */
static FT_Error
check_points( CFF_Builder* builder,
FT_Int count )
{
return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
}
/* add a new point, do not check space */
static void
cff_builder_add_point( CFF_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 = (FT_Byte)( 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
cff_builder_add_point1( CFF_Builder* builder,
FT_Pos x,
FT_Pos y )
{
FT_Error error;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -