winfnt.c.svn-base

来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· SVN-BASE 代码 · 共 1,131 行 · 第 1/3 页

SVN-BASE
1,131
字号

        stream->cursor += 8;

        FT_FRAME_EXIT();

        error = fnt_font_load( face->font, stream );
      }
      else if ( ne_header.magic == WINFNT_PE_MAGIC )
      {
        WinPE32_HeaderRec       pe32_header;
        WinPE32_SectionRec      pe32_section;
        WinPE_RsrcDirRec        root_dir, name_dir, lang_dir;
        WinPE_RsrcDirEntryRec   dir_entry1, dir_entry2, dir_entry3;
        WinPE_RsrcDataEntryRec  data_entry;

        FT_Long    root_dir_offset, name_dir_offset, lang_dir_offset;
        FT_UShort  i, j, k;


        FT_TRACE2(( "PE signature found\n" ));

        if ( FT_STREAM_SEEK( mz_header.lfanew )                           ||
             FT_STREAM_READ_FIELDS( winpe32_header_fields, &pe32_header ) )
          goto Exit;

        FT_TRACE2(( "magic %04lx, machine %02x, number_of_sections %u, "
                    "size_of_optional_header %02x\n"
                    "magic32 %02x, rsrc_virtual_address %04lx, "
                    "rsrc_size %04lx\n",
                    pe32_header.magic, pe32_header.machine,
                    pe32_header.number_of_sections,
                    pe32_header.size_of_optional_header,
                    pe32_header.magic32, pe32_header.rsrc_virtual_address,
                    pe32_header.rsrc_size ));

        if ( pe32_header.magic != WINFNT_PE_MAGIC /* check full signature */ ||
             pe32_header.machine != 0x014c /* i386 */                        ||
             pe32_header.size_of_optional_header != 0xe0 /* FIXME */         ||
             pe32_header.magic32 != 0x10b                                    )
        {
          FT_TRACE2(( "this file has an invalid PE header\n" ));
          error = FNT_Err_Invalid_File_Format;
          goto Exit;
        }

        face->root.num_faces = 0;

        for ( i = 0; i < pe32_header.number_of_sections; i++ )
        {
          if ( FT_STREAM_READ_FIELDS( winpe32_section_fields,
                                      &pe32_section ) )
            goto Exit;

          FT_TRACE2(( "name %.8s, va %04lx, size %04lx, offset %04lx\n",
                      pe32_section.name, pe32_section.virtual_address,
                      pe32_section.size_of_raw_data,
                      pe32_section.pointer_to_raw_data ));

          if ( pe32_header.rsrc_virtual_address ==
                 pe32_section.virtual_address )
            goto Found_rsrc_section;
        }

        FT_TRACE2(( "this file doesn't contain any resources\n" ));
        error = FNT_Err_Invalid_File_Format;
        goto Exit;

      Found_rsrc_section:
        FT_TRACE2(( "found resources section %.8s\n", pe32_section.name ));

        if ( FT_STREAM_SEEK( pe32_section.pointer_to_raw_data )        ||
             FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields, &root_dir ) )
          goto Exit;

        root_dir_offset = pe32_section.pointer_to_raw_data;

        for ( i = 0; i < root_dir.number_of_named_entries +
                           root_dir.number_of_id_entries; i++ )
        {
          if ( FT_STREAM_SEEK( root_dir_offset + 16 + i * 8 )      ||
               FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields,
                                      &dir_entry1 )                )
            goto Exit;

          if ( !(dir_entry1.offset & 0x80000000UL ) /* DataIsDirectory */ )
          {
            error = FNT_Err_Invalid_File_Format;
            goto Exit;
          }

          dir_entry1.offset &= ~0x80000000UL;

          name_dir_offset = pe32_section.pointer_to_raw_data +
                            dir_entry1.offset;

          if ( FT_STREAM_SEEK( pe32_section.pointer_to_raw_data +
                               dir_entry1.offset )                       ||
               FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields, &name_dir ) )
            goto Exit;

          for ( j = 0; j < name_dir.number_of_named_entries +
                             name_dir.number_of_id_entries; j++ )
          {
            if ( FT_STREAM_SEEK( name_dir_offset + 16 + j * 8 )      ||
                 FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields,
                                        &dir_entry2 )                )
              goto Exit;

            if ( !(dir_entry2.offset & 0x80000000UL ) /* DataIsDirectory */ )
            {
              error = FNT_Err_Invalid_File_Format;
              goto Exit;
            }

            dir_entry2.offset &= ~0x80000000UL;

            lang_dir_offset = pe32_section.pointer_to_raw_data +
                                dir_entry2.offset;

            if ( FT_STREAM_SEEK( pe32_section.pointer_to_raw_data +
                                   dir_entry2.offset )                     ||
                 FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields, &lang_dir ) )
              goto Exit;

            for ( k = 0; k < lang_dir.number_of_named_entries +
                               lang_dir.number_of_id_entries; k++ )
            {
              if ( FT_STREAM_SEEK( lang_dir_offset + 16 + k * 8 )      ||
                   FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields,
                                          &dir_entry3 )                )
                goto Exit;

              if ( dir_entry2.offset & 0x80000000UL /* DataIsDirectory */ )
              {
                error = FNT_Err_Invalid_File_Format;
                goto Exit;
              }

              if ( dir_entry1.name == 8 /* RT_FONT */ )
              {
                if ( FT_STREAM_SEEK( root_dir_offset + dir_entry3.offset ) ||
                     FT_STREAM_READ_FIELDS( winpe_rsrc_data_entry_fields,
                                            &data_entry )                  )
                  goto Exit;

                FT_TRACE2(( "found font #%lu, offset %04lx, "
                            "size %04lx, cp %lu\n",
                            dir_entry2.name,
                            pe32_section.pointer_to_raw_data +
                              data_entry.offset_to_data -
                              pe32_section.virtual_address,
                            data_entry.size, data_entry.code_page ));

                if ( face_index == face->root.num_faces )
                {
                  if ( FT_NEW( face->font ) )
                    goto Exit;

                  face->font->offset   = pe32_section.pointer_to_raw_data +
                                           data_entry.offset_to_data -
                                           pe32_section.virtual_address;
                  face->font->fnt_size = data_entry.size;

                  error = fnt_font_load( face->font, stream );
                  if ( error )
                  {
                    FT_TRACE2(( "font #%lu load error %d\n",
                                dir_entry2.name, error ));
                    goto Fail;
                  }
                  else
                    FT_TRACE2(( "font #%lu successfully loaded\n",
                                dir_entry2.name ));
                }

                face->root.num_faces++;
              }
            }
          }
        }
      }

      if ( !face->root.num_faces )
      {
        FT_TRACE2(( "this file doesn't contain any RT_FONT resources\n" ));
        error = FNT_Err_Invalid_File_Format;
        goto Exit;
      }

      if ( face_index >= face->root.num_faces )
      {
        error = FNT_Err_Bad_Argument;
        goto Exit;
      }
    }

  Fail:
    if ( error )
      fnt_font_done( face );

  Exit:
    return error;
  }


  typedef struct  FNT_CMapRec_
  {
    FT_CMapRec  cmap;
    FT_UInt32   first;
    FT_UInt32   count;

  } FNT_CMapRec, *FNT_CMap;


  static FT_Error
  fnt_cmap_init( FNT_CMap  cmap )
  {
    FNT_Face  face = (FNT_Face)FT_CMAP_FACE( cmap );
    FNT_Font  font = face->font;


    cmap->first = (FT_UInt32)  font->header.first_char;
    cmap->count = (FT_UInt32)( font->header.last_char - cmap->first + 1 );

    return 0;
  }


  static FT_UInt
  fnt_cmap_char_index( FNT_CMap   cmap,
                       FT_UInt32  char_code )
  {
    FT_UInt  gindex = 0;


    char_code -= cmap->first;
    if ( char_code < cmap->count )
      gindex = char_code + 1; /* we artificially increase the glyph index; */
                              /* FNT_Load_Glyph reverts to the right one   */
    return gindex;
  }


  static FT_UInt
  fnt_cmap_char_next( FNT_CMap    cmap,
                      FT_UInt32  *pchar_code )
  {
    FT_UInt    gindex = 0;
    FT_UInt32  result = 0;
    FT_UInt32  char_code = *pchar_code + 1;


    if ( char_code <= cmap->first )
    {
      result = cmap->first;
      gindex = 1;
    }
    else
    {
      char_code -= cmap->first;
      if ( char_code < cmap->count )
      {
        result = cmap->first + char_code;
        gindex = char_code + 1;
      }
    }

    *pchar_code = result;
    return gindex;
  }


  static const FT_CMap_ClassRec  fnt_cmap_class_rec =
  {
    sizeof ( FNT_CMapRec ),

    (FT_CMap_InitFunc)     fnt_cmap_init,
    (FT_CMap_DoneFunc)     NULL,
    (FT_CMap_CharIndexFunc)fnt_cmap_char_index,
    (FT_CMap_CharNextFunc) fnt_cmap_char_next,

    NULL, NULL, NULL, NULL, NULL
  };

  static FT_CMap_Class const  fnt_cmap_class = &fnt_cmap_class_rec;


  static void
  FNT_Face_Done( FNT_Face  face )
  {
    if ( face )
    {
      FT_Memory  memory = FT_FACE_MEMORY( face );


      fnt_font_done( face );

      FT_FREE( face->root.available_sizes );
      face->root.num_fixed_sizes = 0;
    }
  }


  static FT_Error
  FNT_Face_Init( FT_Stream      stream,
                 FNT_Face       face,
                 FT_Int         face_index,
                 FT_Int         num_params,
                 FT_Parameter*  params )
  {
    FT_Error   error;
    FT_Memory  memory = FT_FACE_MEMORY( face );

    FT_UNUSED( num_params );
    FT_UNUSED( params );


    /* try to load font from a DLL */
    error = fnt_face_get_dll_font( face, face_index );
    if ( !error && face_index < 0 )
      goto Exit;

    if ( error == FNT_Err_Unknown_File_Format )
    {
      /* this didn't work; try to load a single FNT font */
      FNT_Font  font;

      if ( FT_NEW( face->font ) )
        goto Exit;

      face->root.num_faces = 1;

      font           = face->font;
      font->offset   = 0;
      font->fnt_size = stream->size;

      error = fnt_font_load( font, stream );

      if ( !error )
      {
        if ( face_index > 0 )
          error = FNT_Err_Bad_Argument;
        else if ( face_index < 0 )
          goto Exit;
      }
    }

    if ( error )
      goto Fail;

    /* we now need to fill the root FT_Face fields */
    /* with relevant information                   */
    {
      FT_Face     root = FT_FACE( face );
      FNT_Font    font = face->font;
      FT_PtrDist  family_size;


      root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
                         FT_FACE_FLAG_HORIZONTAL;

      if ( font->header.avg_width == font->header.max_width )
        root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;

      if ( font->header.italic )
        root->style_flags |= FT_STYLE_FLAG_ITALIC;

      if ( font->header.weight >= 800 )
        root->style_flags |= FT_STYLE_FLAG_BOLD;

      /* set up the `fixed_sizes' array */
      if ( FT_NEW_ARRAY( root->available_sizes, 1 ) )
        goto Fail;

      root->num_fixed_sizes = 1;

      {

⌨️ 快捷键说明

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