📄 ttsbit.c
字号:
{ if ( (FT_UInt)range->glyph_codes[n] == glyph_index ) { if ( range->index_format == 4 ) *aglyph_offset = range->glyph_offsets[n]; else *aglyph_offset = range->image_offset + n * range->image_size; goto Found; } } } /* fall-through */ default: goto Fail; } Found: /* return successfully! */ *arange = range; return 0; } } Fail: *arange = 0; *aglyph_offset = 0; return SFNT_Err_Invalid_Argument; } /*************************************************************************/ /* */ /* <Function> */ /* tt_find_sbit_image */ /* */ /* <Description> */ /* Checks whether an embedded bitmap (an `sbit') exists for a given */ /* glyph, at a given strike. */ /* */ /* <Input> */ /* face :: The target face object. */ /* */ /* glyph_index :: The glyph index. */ /* */ /* strike_index :: The current strike index. */ /* */ /* <Output> */ /* arange :: The SBit range containing the glyph index. */ /* */ /* astrike :: The SBit strike containing the glyph index. */ /* */ /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */ /* */ /* <Return> */ /* FreeType error code. 0 means success. Returns */ /* SFNT_Err_Invalid_Argument if no sbit exists for the requested */ /* glyph. */ /* */ FT_LOCAL( FT_Error ) tt_find_sbit_image( TT_Face face, FT_UInt glyph_index, FT_ULong strike_index, TT_SBit_Range *arange, TT_SBit_Strike *astrike, FT_ULong *aglyph_offset ) { FT_Error error; TT_SBit_Strike strike; if ( !face->sbit_strikes || ( face->num_sbit_strikes <= strike_index ) ) goto Fail; strike = &face->sbit_strikes[strike_index]; error = find_sbit_range( glyph_index, strike, arange, aglyph_offset ); if ( error ) goto Fail; *astrike = strike; return SFNT_Err_Ok; Fail: /* no embedded bitmap for this glyph in face */ *arange = 0; *astrike = 0; *aglyph_offset = 0; return SFNT_Err_Invalid_Argument; } /*************************************************************************/ /* */ /* <Function> */ /* tt_load_sbit_metrics */ /* */ /* <Description> */ /* Gets the big metrics for a given SBit. */ /* */ /* <Input> */ /* stream :: The input stream. */ /* */ /* range :: The SBit range containing the glyph. */ /* */ /* <Output> */ /* big_metrics :: A big SBit metrics structure for the glyph. */ /* */ /* <Return> */ /* FreeType error code. 0 means success. */ /* */ /* <Note> */ /* The stream cursor must be positioned at the glyph's offset within */ /* the `EBDT' table before the call. */ /* */ /* If the image format uses variable metrics, the stream cursor is */ /* positioned just after the metrics header in the `EBDT' table on */ /* function exit. */ /* */ FT_LOCAL( FT_Error ) tt_load_sbit_metrics( FT_Stream stream, TT_SBit_Range range, TT_SBit_Metrics metrics ) { FT_Error error = SFNT_Err_Ok; switch ( range->image_format ) { case 1: case 2: case 8: /* variable small metrics */ { TT_SBit_SmallMetricsRec smetrics; static const FT_Frame_Field sbit_small_metrics_fields[] = {#undef FT_STRUCTURE#define FT_STRUCTURE TT_SBit_SmallMetricsRec FT_FRAME_START( 5 ), FT_FRAME_BYTE( height ), FT_FRAME_BYTE( width ), FT_FRAME_CHAR( bearingX ), FT_FRAME_CHAR( bearingY ), FT_FRAME_BYTE( advance ), FT_FRAME_END }; /* read small metrics */ if ( FT_STREAM_READ_FIELDS( sbit_small_metrics_fields, &smetrics ) ) goto Exit; /* convert it to a big metrics */ metrics->height = smetrics.height; metrics->width = smetrics.width; metrics->horiBearingX = smetrics.bearingX; metrics->horiBearingY = smetrics.bearingY; metrics->horiAdvance = smetrics.advance; /* these metrics are made up at a higher level when */ /* needed. */ metrics->vertBearingX = 0; metrics->vertBearingY = 0; metrics->vertAdvance = 0; } break; case 6: case 7: case 9: /* variable big metrics */ if ( FT_STREAM_READ_FIELDS( sbit_metrics_fields, metrics ) ) goto Exit; break; case 5: default: /* constant metrics */ if ( range->index_format == 2 || range->index_format == 5 ) *metrics = range->metrics; else return SFNT_Err_Invalid_File_Format; } Exit: return error; } /*************************************************************************/ /* */ /* <Function> */ /* crop_bitmap */ /* */ /* <Description> */ /* Crops a bitmap to its tightest bounding box, and adjusts its */ /* metrics. */ /* */ /* <InOut> */ /* map :: The bitmap. */ /* */ /* metrics :: The corresponding metrics structure. */ /* */ static void crop_bitmap( FT_Bitmap* map, TT_SBit_Metrics metrics ) { /***********************************************************************/ /* */ /* In this situation, some bounding boxes of embedded bitmaps are too */ /* large. We need to crop it to a reasonable size. */ /* */ /* --------- */ /* | | ----- */ /* | *** | |***| */ /* | * | | * | */ /* | * | ------> | * | */ /* | * | | * | */ /* | * | | * | */ /* | *** | |***| */ /* --------- ----- */ /* */ /***********************************************************************/ FT_Int rows, count; FT_Long line_len; FT_Byte* line; /***********************************************************************/ /* */ /* first of all, check the top-most lines of the bitmap, and remove */ /* them if they're empty. */ /* */ { line = (FT_Byte*)map->buffer; rows = map->rows; line_len = map->pitch; for ( count = 0; count < rows; count++ ) { FT_Byte* cur = line; FT_Byte* limit = line + line_len; for ( ; cur < limit; cur++ ) if ( cur[0] ) goto Found_Top; /* the current line was empty - skip to next one */ line = limit; } Found_Top: /* check that we have at least one filled line */ if ( count >= rows ) goto Empty_Bitmap; /* now, crop the empty upper lines */ if ( count > 0 ) { line = (FT_Byte*)map->buffer; FT_MEM_MOVE( line, line + count * line_len, ( rows - count ) * line_len ); metrics->height = (FT_Byte)( metrics->height - count ); metrics->horiBearingY = (FT_Char)( metrics->horiBearingY - count ); metrics->vertBearingY = (FT_Char)( metrics->vertBearingY - count ); map->rows -= count; rows -= count; } } /***********************************************************************/ /* */ /* second, crop the lower lines */ /* */ { line = (FT_Byte*)map->buffer + ( rows - 1 ) * line_len; for ( count = 0; count < rows; count++ ) { FT_Byte* cur = line; FT_Byte* limit = line + line_len; for ( ; cur < limit; cur++ ) if ( cur[0] ) goto Found_Bottom; /* the current line was empty - skip to previous one */ line -= line_len; } Found_Bottom: if ( count > 0 ) { metrics->height = (FT_Byte)( metrics->height - count ); rows -= count; map->rows -= count; } } /***********************************************************************/ /* */ /* third, get rid of the space on the left side of the glyph */ /* */ do { FT_Byte* limit; line = (FT_Byte*)map->buffer; limit = line + rows * line_len; for ( ; line < limit; line += line_len ) if ( line[0] & 0x80 ) goto Found_Left; /* shift the whole glyph one pixel to the left */ line = (FT_Byte*)map->buffer; limit = line + rows * line_len; for ( ; line < limit; line += line_len ) { FT_Int n, width = map->width; FT_Byte old; FT_Byte* cur = line; old = (FT_Byte)(cur[0] << 1); for ( n = 8; n < width; n += 8 ) { FT_Byte val; val = cur[1]; cur[0] = (FT_Byte)( old | ( val >> 7 ) ); old = (FT_Byte)( val << 1 ); cur++; } cur[0] = old; } map->width--; metrics->horiBearingX++; metrics->vertBearingX++; metrics->width--; } while ( map->width > 0 ); Found_Left: /***********************************************************************/ /* */ /* finally, crop the bitmap width to get rid of the space on the right */ /* side of the glyph. */ /* */ do { FT_Int right = map->width - 1; FT_Byte* limit; FT_Byte mask;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -