📄 ttsbit.c
字号:
break;
default:
error = SFNT_Err_Invalid_File_Format;
}
Exit:
return error;
}
/*************************************************************************/
/* */
/* <Function> */
/* tt_face_load_sbit_strikes */
/* */
/* <Description> */
/* Loads the table of embedded bitmap sizes for this face. */
/* */
/* <Input> */
/* face :: The target face object. */
/* */
/* stream :: The input stream. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
tt_face_load_sbit_strikes( TT_Face face,
FT_Stream stream )
{
FT_Error error = 0;
FT_Memory memory = stream->memory;
FT_Fixed version;
FT_ULong num_strikes;
FT_ULong table_base;
static const FT_Frame_Field sbit_line_metrics_fields[] =
{
#undef FT_STRUCTURE
#define FT_STRUCTURE TT_SBit_LineMetricsRec
/* no FT_FRAME_START */
FT_FRAME_CHAR( ascender ),
FT_FRAME_CHAR( descender ),
FT_FRAME_BYTE( max_width ),
FT_FRAME_CHAR( caret_slope_numerator ),
FT_FRAME_CHAR( caret_slope_denominator ),
FT_FRAME_CHAR( caret_offset ),
FT_FRAME_CHAR( min_origin_SB ),
FT_FRAME_CHAR( min_advance_SB ),
FT_FRAME_CHAR( max_before_BL ),
FT_FRAME_CHAR( min_after_BL ),
FT_FRAME_CHAR( pads[0] ),
FT_FRAME_CHAR( pads[1] ),
FT_FRAME_END
};
static const FT_Frame_Field strike_start_fields[] =
{
#undef FT_STRUCTURE
#define FT_STRUCTURE TT_SBit_StrikeRec
/* no FT_FRAME_START */
FT_FRAME_ULONG( ranges_offset ),
FT_FRAME_SKIP_LONG,
FT_FRAME_ULONG( num_ranges ),
FT_FRAME_ULONG( color_ref ),
FT_FRAME_END
};
static const FT_Frame_Field strike_end_fields[] =
{
/* no FT_FRAME_START */
FT_FRAME_USHORT( start_glyph ),
FT_FRAME_USHORT( end_glyph ),
FT_FRAME_BYTE ( x_ppem ),
FT_FRAME_BYTE ( y_ppem ),
FT_FRAME_BYTE ( bit_depth ),
FT_FRAME_CHAR ( flags ),
FT_FRAME_END
};
face->num_sbit_strikes = 0;
/* this table is optional */
error = face->goto_table( face, TTAG_EBLC, stream, 0 );
if ( error )
error = face->goto_table( face, TTAG_bloc, stream, 0 );
if ( error )
goto Exit;
table_base = FT_STREAM_POS();
if ( FT_FRAME_ENTER( 8L ) )
goto Exit;
version = FT_GET_LONG();
num_strikes = FT_GET_ULONG();
FT_FRAME_EXIT();
/* check version number and strike count */
if ( version != 0x00020000L ||
num_strikes >= 0x10000L )
{
FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version!\n" ));
error = SFNT_Err_Invalid_File_Format;
goto Exit;
}
/* allocate the strikes table */
if ( FT_NEW_ARRAY( face->sbit_strikes, num_strikes ) )
goto Exit;
face->num_sbit_strikes = num_strikes;
/* now read each strike table separately */
{
TT_SBit_Strike strike = face->sbit_strikes;
FT_ULong count = num_strikes;
if ( FT_FRAME_ENTER( 48L * num_strikes ) )
goto Exit;
while ( count > 0 )
{
if ( FT_STREAM_READ_FIELDS( strike_start_fields, strike ) ||
FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->hori ) ||
FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->vert ) ||
FT_STREAM_READ_FIELDS( strike_end_fields, strike ) )
break;
count--;
strike++;
}
FT_FRAME_EXIT();
}
/* allocate the index ranges for each strike table */
{
TT_SBit_Strike strike = face->sbit_strikes;
FT_ULong count = num_strikes;
while ( count > 0 )
{
TT_SBit_Range range;
FT_ULong count2 = strike->num_ranges;
/* read each range */
if ( FT_STREAM_SEEK( table_base + strike->ranges_offset ) ||
FT_FRAME_ENTER( strike->num_ranges * 8L ) )
goto Exit;
if ( FT_NEW_ARRAY( strike->sbit_ranges, strike->num_ranges ) )
goto Exit;
range = strike->sbit_ranges;
while ( count2 > 0 )
{
range->first_glyph = FT_GET_USHORT();
range->last_glyph = FT_GET_USHORT();
range->table_offset = table_base + strike->ranges_offset +
FT_GET_ULONG();
count2--;
range++;
}
FT_FRAME_EXIT();
/* Now, read each index table */
count2 = strike->num_ranges;
range = strike->sbit_ranges;
while ( count2 > 0 )
{
/* Read the header */
if ( FT_STREAM_SEEK( range->table_offset ) ||
FT_FRAME_ENTER( 8L ) )
goto Exit;
range->index_format = FT_GET_USHORT();
range->image_format = FT_GET_USHORT();
range->image_offset = FT_GET_ULONG();
FT_FRAME_EXIT();
error = Load_SBit_Range( range, stream );
if ( error )
goto Exit;
count2--;
range++;
}
count--;
strike++;
}
}
/* now set up the root fields to indicate the strikes */
if ( face->num_sbit_strikes )
{
FT_ULong n;
FT_Face root = FT_FACE( face );
if ( FT_NEW_ARRAY( root->available_sizes, face->num_sbit_strikes ) )
goto Exit;
for ( n = 0 ; n < face->num_sbit_strikes ; n++ )
{
FT_Bitmap_Size* bsize = root->available_sizes + n;
TT_SBit_Strike strike = face->sbit_strikes + n;
FT_UShort fupem = face->header.Units_Per_EM;
FT_Short height = (FT_Short)( face->horizontal.Ascender -
face->horizontal.Descender +
face->horizontal.Line_Gap );
FT_Short avg = face->os2.xAvgCharWidth;
/* assume 72dpi */
bsize->height =
(FT_Short)( ( height * strike->y_ppem + fupem / 2 ) / fupem );
bsize->width =
(FT_Short)( ( avg * strike->y_ppem + fupem / 2 ) / fupem );
bsize->size = strike->y_ppem << 6;
bsize->x_ppem = strike->x_ppem << 6;
bsize->y_ppem = strike->y_ppem << 6;
}
root->face_flags |= FT_FACE_FLAG_FIXED_SIZES;
root->num_fixed_sizes = (FT_Int)face->num_sbit_strikes;
}
Exit:
return error;
}
/*************************************************************************/
/* */
/* <Function> */
/* tt_face_free_sbit_strikes */
/* */
/* <Description> */
/* Releases the embedded bitmap tables. */
/* */
/* <Input> */
/* face :: The target face object. */
/* */
FT_LOCAL_DEF( void )
tt_face_free_sbit_strikes( TT_Face face )
{
FT_Memory memory = face->root.memory;
TT_SBit_Strike strike = face->sbit_strikes;
TT_SBit_Strike strike_limit = strike + face->num_sbit_strikes;
if ( strike )
{
for ( ; strike < strike_limit; strike++ )
{
TT_SBit_Range range = strike->sbit_ranges;
TT_SBit_Range range_limit = range + strike->num_ranges;
if ( range )
{
for ( ; range < range_limit; range++ )
{
/* release the glyph offsets and codes tables */
/* where appropriate */
FT_FREE( range->glyph_offsets );
FT_FREE( range->glyph_codes );
}
}
FT_FREE( strike->sbit_ranges );
strike->num_ranges = 0;
}
FT_FREE( face->sbit_strikes );
}
face->num_sbit_strikes = 0;
}
FT_LOCAL_DEF( FT_Error )
tt_face_set_sbit_strike( TT_Face face,
FT_UInt x_ppem,
FT_UInt y_ppem,
FT_ULong *astrike_index )
{
FT_ULong i;
if ( x_ppem > 255 ||
y_ppem < 1 || y_ppem > 255 )
return SFNT_Err_Invalid_PPem;
for ( i = 0; i < face->num_sbit_strikes; i++ )
{
if ( ( (FT_UInt)face->sbit_strikes[i].y_ppem == y_ppem ) &&
( ( x_ppem == 0 ) ||
( (FT_UInt)face->sbit_strikes[i].x_ppem == x_ppem ) ) )
{
*astrike_index = i;
return SFNT_Err_Ok;
}
}
return SFNT_Err_Invalid_PPem;
}
/*************************************************************************/
/* */
/* <Function> */
/* find_sbit_range */
/* */
/* <Description> */
/* Scans a given strike's ranges and return, for a given glyph */
/* index, the corresponding sbit range, and `EBDT' offset. */
/* */
/* <Input> */
/* glyph_index :: The glyph index. */
/* */
/* strike :: The source/current sbit strike. */
/* */
/* <Output> */
/* arange :: The sbit range containing the glyph index. */
/* */
/* aglyph_offset :: The offset of the glyph data in `EBDT' table. */
/* */
/* <Return> */
/* FreeType error code. 0 means the glyph index was found. */
/* */
static FT_Error
find_sbit_range( FT_UInt glyph_index,
TT_SBit_Strike strike,
TT_SBit_Range *arange,
FT_ULong *aglyph_offset )
{
TT_SBit_RangeRec *range, *range_limit;
/* check whether the glyph index is within this strike's */
/* glyph range */
if ( glyph_index < (FT_UInt)strike->start_glyph ||
glyph_index > (FT_UInt)strike->end_glyph )
goto Fail;
/* scan all ranges in strike */
range = strike->sbit_ranges;
range_limit = range + strike->num_ranges;
if ( !range )
goto Fail;
for ( ; range < range_limit; range++ )
{
if ( glyph_index >= (FT_UInt)range->first_glyph &&
glyph_index <= (FT_UInt)range->last_glyph )
{
FT_UShort delta = (FT_UShort)( glyph_index - range->first_glyph );
switch ( range->index_format )
{
case 1:
case 3:
*aglyph_offset = range->glyph_offsets[delta];
break;
case 2:
*aglyph_offset = range->image_offset +
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -