ttsbit0.c

来自「奇趣公司比较新的qt/emd版本」· C语言 代码 · 共 968 行 · 第 1/2 页

C
968
字号
/***************************************************************************//*                                                                         *//*  ttsbit0.c                                                              *//*                                                                         *//*    TrueType and OpenType embedded bitmap support (body).                *//*    This is a heap-optimized version.                                    *//*                                                                         *//*  Copyright 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.                                        *//*                                                                         *//***************************************************************************//* This file is included by ttsbit.c */#include <ft2build.h>#include FT_INTERNAL_DEBUG_H#include FT_INTERNAL_STREAM_H#include FT_TRUETYPE_TAGS_H#include "ttsbit.h"#include "sferrors.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_ttsbit    static const FT_Frame_Field  tt_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  tt_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  tt_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    };  FT_LOCAL_DEF( FT_Error )  tt_face_load_eblc( TT_Face    face,                     FT_Stream  stream )  {    FT_Error   error  = SFNT_Err_Ok;    FT_Fixed   version;    FT_ULong   num_strikes, table_size;    FT_Byte*   p;    FT_Byte*   p_limit;    FT_UInt    count;    face->sbit_num_strikes = 0;    /* this table is optional */    error = face->goto_table( face, TTAG_EBLC, stream, &table_size );    if ( error )      error = face->goto_table( face, TTAG_bloc, stream, &table_size );    if ( error )      goto Exit;    if ( table_size < 8 )    {      FT_ERROR(( "%s: table too short!\n", "tt_face_load_sbit_strikes" ));      error = SFNT_Err_Invalid_File_Format;      goto Exit;    }    if ( FT_FRAME_EXTRACT( table_size, face->sbit_table ) )      goto Exit;    face->sbit_table_size = table_size;    p       = face->sbit_table;    p_limit = p + table_size;    version     = FT_NEXT_ULONG( p );    num_strikes = FT_NEXT_ULONG( p );    if ( version != 0x00020000UL || num_strikes >= 0x10000UL )    {      FT_ERROR(( "%s: invalid table version!\n",                 "tt_face_load_sbit_strikes" ));      error = SFNT_Err_Invalid_File_Format;      goto Fail;    }    /*     *  Count the number of strikes available in the table.  We are a bit     *  paranoid there and don't trust the data.     */    count = (FT_UInt)num_strikes;    if ( 8 + 48UL * count > table_size )      count = (FT_UInt)( ( p_limit - p ) / 48 );    face->sbit_num_strikes = count;    FT_TRACE3(( "sbit_num_strikes: %u\n", count ));  Exit:    return error;  Fail:    FT_FRAME_RELEASE( face->sbit_table );    face->sbit_table_size = 0;    goto Exit;  }  FT_LOCAL_DEF( void )  tt_face_free_eblc( TT_Face  face )  {    FT_Stream  stream = face->root.stream;    FT_FRAME_RELEASE( face->sbit_table );    face->sbit_table_size  = 0;    face->sbit_num_strikes = 0;  }  FT_LOCAL_DEF( FT_Error )  tt_face_set_sbit_strike( TT_Face          face,                           FT_Size_Request  req,                           FT_ULong*        astrike_index )  {    return FT_Match_Size( (FT_Face)face, req, 0, astrike_index );  }  FT_LOCAL_DEF( FT_Error )  tt_face_load_strike_metrics( TT_Face           face,                               FT_ULong          strike_index,                               FT_Size_Metrics*  metrics )  {    FT_Byte*         strike;    if ( strike_index >= (FT_ULong)face->sbit_num_strikes )      return SFNT_Err_Invalid_Argument;    strike = face->sbit_table + 8 + strike_index * 48;    metrics->x_ppem = (FT_UShort)strike[44];    metrics->y_ppem = (FT_UShort)strike[45];    metrics->ascender  = (FT_Char)strike[16] << 6;  /* hori.ascender  */    metrics->descender = (FT_Char)strike[17] << 6;  /* hori.descender */    metrics->height    = metrics->ascender - metrics->descender;    /* XXX: Is this correct? */    metrics->max_advance = ( (FT_Char)strike[22] + /* min_origin_SB  */                                      strike[18] + /* max_width      */                             (FT_Char)strike[23]   /* min_advance_SB */                                                 ) << 6;    return SFNT_Err_Ok;  }  typedef struct  {    TT_Face          face;    FT_Stream        stream;    FT_Bitmap*       bitmap;    TT_SBit_Metrics  metrics;    FT_Bool          metrics_loaded;    FT_Bool          bitmap_allocated;    FT_Byte          bit_depth;    FT_ULong         ebdt_start;    FT_ULong         ebdt_size;    FT_ULong         strike_index_array;    FT_ULong         strike_index_count;    FT_Byte*         eblc_base;    FT_Byte*         eblc_limit;  } TT_SBitDecoderRec, *TT_SBitDecoder;  static FT_Error  tt_sbit_decoder_init( TT_SBitDecoder       decoder,                        TT_Face              face,                        FT_ULong             strike_index,                        TT_SBit_MetricsRec*  metrics )  {    FT_Error   error;    FT_Stream  stream     = face->root.stream;    FT_ULong   ebdt_size;    error = face->goto_table( face, TTAG_EBDT, stream, &ebdt_size );    if ( error )      error = face->goto_table( face, TTAG_bdat, stream, &ebdt_size );    if ( error )      goto Exit;    decoder->face    = face;    decoder->stream  = stream;    decoder->bitmap  = &face->root.glyph->bitmap;    decoder->metrics = metrics;    decoder->metrics_loaded   = 0;    decoder->bitmap_allocated = 0;    decoder->ebdt_start = FT_STREAM_POS();    decoder->ebdt_size  = ebdt_size;    decoder->eblc_base  = face->sbit_table;    decoder->eblc_limit = face->sbit_table + face->sbit_table_size;    /* now find the strike corresponding to the index */    {      FT_Byte*  p = decoder->eblc_base + 8 + 48 * strike_index;      decoder->strike_index_array = FT_NEXT_ULONG( p );      p                          += 4;      decoder->strike_index_count = FT_NEXT_ULONG( p );      p                          += 34;      decoder->bit_depth          = *p;    }  Exit:    return error;  }  static void  tt_sbit_decoder_done( TT_SBitDecoder  decoder )  {    FT_UNUSED( decoder );  }  static FT_Error  tt_sbit_decoder_alloc_bitmap( TT_SBitDecoder  decoder )  {    FT_Error    error = SFNT_Err_Ok;    FT_UInt     width, height;    FT_Bitmap*  map = decoder->bitmap;    FT_Long     size;    if ( !decoder->metrics_loaded )    {      error = SFNT_Err_Invalid_Argument;      goto Exit;    }    width  = decoder->metrics->width;    height = decoder->metrics->height;    map->width = (int)width;    map->rows  = (int)height;    switch ( decoder->bit_depth )    {    case 1:      map->pixel_mode = FT_PIXEL_MODE_MONO;      map->pitch      = ( map->width + 7 ) >> 3;      break;    case 2:      map->pixel_mode = FT_PIXEL_MODE_GRAY2;      map->pitch      = ( map->width + 3 ) >> 2;      break;    case 4:      map->pixel_mode = FT_PIXEL_MODE_GRAY4;      map->pitch      = ( map->width + 1 ) >> 1;      break;    case 8:      map->pixel_mode = FT_PIXEL_MODE_GRAY;      map->pitch      = map->width;      break;    default:      error = SFNT_Err_Invalid_File_Format;      goto Exit;    }    size = map->rows * map->pitch;    /* check that there is no empty image */    if ( size == 0 )      goto Exit;     /* exit successfully! */    error = ft_glyphslot_alloc_bitmap( decoder->face->root.glyph, size );    if ( error )      goto Exit;    decoder->bitmap_allocated = 1;  Exit:    return error;  }  static FT_Error  tt_sbit_decoder_load_metrics( TT_SBitDecoder  decoder,                                FT_Byte*       *pp,                                FT_Byte*        limit,                                FT_Bool         big )  {    FT_Byte*         p       = *pp;    TT_SBit_Metrics  metrics = decoder->metrics;    if ( p + 5 > limit )      goto Fail;    if ( !decoder->metrics_loaded )    {      metrics->height       = p[0];      metrics->width        = p[1];      metrics->horiBearingX = (FT_Char)p[2];      metrics->horiBearingY = (FT_Char)p[3];      metrics->horiAdvance  = p[4];    }    p += 5;    if ( big )    {      if ( p + 3 > limit )        goto Fail;      if ( !decoder->metrics_loaded )      {        metrics->vertBearingX = (FT_Char)p[0];        metrics->vertBearingY = (FT_Char)p[1];        metrics->vertAdvance  = p[2];      }      p += 3;    }    decoder->metrics_loaded = 1;    *pp = p;    return 0;  Fail:    return SFNT_Err_Invalid_Argument;  }  /* forward declaration */  static FT_Error  tt_sbit_decoder_load_image( TT_SBitDecoder  decoder,                              FT_UInt         glyph_index,                              FT_Int          x_pos,                              FT_Int          y_pos );  typedef FT_Error  (*TT_SBitDecoder_LoadFunc)( TT_SBitDecoder  decoder,                                                FT_Byte*        p,                                                FT_Byte*        plimit,                                                FT_Int          x_pos,                                                FT_Int          y_pos );  static FT_Error  tt_sbit_decoder_load_byte_aligned( TT_SBitDecoder  decoder,                                     FT_Byte*        p,                                     FT_Byte*        limit,                                     FT_Int          x_pos,                                     FT_Int          y_pos )  {    FT_Error    error = SFNT_Err_Ok;    FT_Byte*    line;    FT_Int      bit_height, bit_width, pitch, width, height, h;    FT_Bitmap*  bitmap;    if ( !decoder->bitmap_allocated )    {      error = tt_sbit_decoder_alloc_bitmap( decoder );      if ( error )        goto Exit;    }    /* check that we can write the glyph into the bitmap */    bitmap     = decoder->bitmap;    bit_width  = bitmap->width;    bit_height = bitmap->rows;    pitch      = bitmap->pitch;    line       = bitmap->buffer;    width  = decoder->metrics->width;    height = decoder->metrics->height;    if ( x_pos < 0 || x_pos + width > bit_width   ||         y_pos < 0 || y_pos + height > bit_height )    {      error = SFNT_Err_Invalid_File_Format;      goto Exit;    }    if ( p + ( ( width + 7 ) >> 3 ) * height > limit )    {      error = SFNT_Err_Invalid_File_Format;      goto Exit;    }    /* now do the blit */    line  += y_pos * pitch + ( x_pos >> 3 );    x_pos &= 7;    if ( x_pos == 0 )  /* the easy one */    {      for ( h = height; h > 0; h--, line += pitch )      {        FT_Byte*  write = line;        FT_Int    w;        for ( w = width; w >= 8; w -= 8 )        {          write[0] = (FT_Byte)( write[0] | *p++ );          write   += 1;        }        if ( w > 0 )          write[0] = (FT_Byte)( write[0] | ( *p++ & ( 0xFF00U >> w ) ) );      }    }    else  /* x_pos > 0 */    {      for ( h = height; h > 0; h--, line += pitch )      {        FT_Byte*  write = line;        FT_Int    w;        FT_UInt   wval = 0;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?