⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftcommon.c

📁 Demo for Free type 2.2.1
💻 C
📖 第 1 页 / 共 3 页
字号:
      case FT_ENCODING_ADOBE_CUSTOM:
      case FT_ENCODING_APPLE_ROMAN:
        font->num_indices = 0x100L;
        break;

      default:
        font->num_indices = 0x10000L;
      }

      FT_Done_Face( face );
      face = NULL;

      if ( handle->max_fonts == 0 )
      {
        handle->max_fonts = 16;
        handle->fonts     = (PFont*)calloc( handle->max_fonts,
                                            sizeof ( PFont ) );
      }
      else if ( handle->num_fonts >= handle->max_fonts )
      {
        handle->max_fonts *= 2;
        handle->fonts      = (PFont*)realloc( handle->fonts,
                                              handle->max_fonts *
                                                sizeof ( PFont ) );

        memset( &handle->fonts[handle->num_fonts], 0,
                ( handle->max_fonts - handle->num_fonts ) *
                  sizeof ( PFont ) );
      }

      handle->fonts[handle->num_fonts++] = font;
    }

    return FT_Err_Ok;
  }


  void
  FTDemo_Set_Current_Font( FTDemo_Handle*  handle,
                           PFont           font )
  {
    handle->current_font = font;
    handle->image_type.face_id = (FTC_FaceID)font;

    handle->string_reload = 1;
  }


  void
  FTDemo_Set_Current_Size( FTDemo_Handle*  handle,
                           int             pixel_size )
  {
    if ( pixel_size > 0xFFFF )
      pixel_size = 0xFFFF;

    handle->image_type.width  = (FT_UShort)pixel_size;
    handle->image_type.height = (FT_UShort)pixel_size;

    handle->string_reload = 1;
  }

  void
  FTDemo_Set_Preload( FTDemo_Handle*  handle,
                      int             preload )
  {
    handle->preload = !!preload;
  }

  void
  FTDemo_Set_Current_Pointsize( FTDemo_Handle*  handle,
                                int             point_size,
                                int             res )
  {
    FTDemo_Set_Current_Size( handle, ( point_size * res + 36 ) / 72 );
  }


  void
  FTDemo_Update_Current_Flags( FTDemo_Handle*  handle )
  {
    FT_UInt32   flags, target;

    flags = FT_LOAD_DEFAULT;  /* really 0 */

    flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;

    if ( handle->autohint )
      flags |= FT_LOAD_FORCE_AUTOHINT;

    if ( !handle->use_sbits )
      flags |= FT_LOAD_NO_BITMAP;

    if ( handle->hinted )
    {
      target = 0;

      if ( handle->antialias )
      {
        switch ( handle->lcd_mode )
        {
          case LCD_MODE_LIGHT:
            target = FT_LOAD_TARGET_LIGHT;
            break;

          case LCD_MODE_RGB:
          case LCD_MODE_BGR:
            target = FT_LOAD_TARGET_LCD;
            break;

          case LCD_MODE_VRGB:
          case LCD_MODE_VBGR:
            target = FT_LOAD_TARGET_LCD_V;
            break;

          default:
            target = FT_LOAD_TARGET_NORMAL;
        }
      }
      else
        target = FT_LOAD_TARGET_MONO;

      flags |= target;
    }
    else
      flags |= FT_LOAD_NO_HINTING;

    handle->image_type.flags = flags;
    handle->string_reload    = 1;
  }


  FT_UInt
  FTDemo_Get_Index( FTDemo_Handle*  handle,
                    FT_UInt32       charcode )
  {
    FTC_FaceID  face_id = handle->image_type.face_id;
    PFont       font    = handle->current_font;


    return FTC_CMapCache_Lookup( handle->cmap_cache, face_id,
                                 font->cmap_index, charcode );
  }


  FT_Error
  FTDemo_Get_Size( FTDemo_Handle*  handle,
                   FT_Size*        asize )
  {
    FTC_ScalerRec  scaler;
    FT_Size        size;


    scaler.face_id = handle->image_type.face_id;
    scaler.width   = handle->image_type.width;
    scaler.height  = handle->image_type.height;
    scaler.pixel   = 1;

    error = FTC_Manager_LookupSize( handle->cache_manager, &scaler, &size );

    if ( !error )
      *asize = size;

    return error;
  }


  FT_Error
  FTDemo_Glyph_To_Bitmap( FTDemo_Handle*  handle,
                          FT_Glyph        glyf,
                          grBitmap*       target,
                          int*            left,
                          int*            top,
                          int*            x_advance,
                          int*            y_advance,
                          FT_Glyph*       aglyf )
  {
    FT_BitmapGlyph  bitmap;
    FT_Bitmap*      source;


    *aglyf = NULL;

    error = FT_Err_Ok;

    if ( glyf->format == FT_GLYPH_FORMAT_OUTLINE )
    {
      FT_Render_Mode  render_mode = FT_RENDER_MODE_MONO;


      if ( handle->antialias )
      {
        if ( handle->lcd_mode == 0 )
          render_mode = FT_RENDER_MODE_NORMAL;
        else if ( handle->lcd_mode == 1 )
          render_mode = FT_RENDER_MODE_LIGHT;
        else if ( handle->lcd_mode <= 3 )
          render_mode = FT_RENDER_MODE_LCD;
        else
          render_mode = FT_RENDER_MODE_LCD_V;
      }

      /* render the glyph to a bitmap, don't destroy original */
      error = FT_Glyph_To_Bitmap( &glyf, render_mode, NULL, 0 );
      if ( error )
        return error;

      *aglyf = glyf;
    }

    if ( glyf->format != FT_GLYPH_FORMAT_BITMAP )
      PanicZ( "invalid glyph format returned!" );

    bitmap = (FT_BitmapGlyph)glyf;
    source = &bitmap->bitmap;

    target->rows   = source->rows;
    target->width  = source->width;
    target->pitch  = source->pitch;
    target->buffer = source->buffer;
    target->grays  = source->num_grays;

    switch ( source->pixel_mode )
    {
    case FT_PIXEL_MODE_MONO:
      target->mode = gr_pixel_mode_mono;
      break;

    case FT_PIXEL_MODE_GRAY:
      target->mode  = gr_pixel_mode_gray;
      target->grays = source->num_grays;
      break;

    case FT_PIXEL_MODE_GRAY2:
    case FT_PIXEL_MODE_GRAY4:
      (void)FT_Bitmap_Convert( handle->library, source, &handle->bitmap, 1 );
      target->pitch  = handle->bitmap.pitch;
      target->buffer = handle->bitmap.buffer;
      target->mode   = gr_pixel_mode_gray;
      target->grays  = handle->bitmap.num_grays;
      break;

    case FT_PIXEL_MODE_LCD:
      target->mode  = handle->lcd_mode == 2 ? gr_pixel_mode_lcd
                                            : gr_pixel_mode_lcd2;
      target->grays = source->num_grays;
      break;

    case FT_PIXEL_MODE_LCD_V:
      target->mode  = handle->lcd_mode == 4 ? gr_pixel_mode_lcdv
                                            : gr_pixel_mode_lcdv2;
      target->grays = source->num_grays;
      break;

    default:
      return FT_Err_Invalid_Glyph_Format;
    }

    *left = bitmap->left;
    *top  = bitmap->top;

    *x_advance = ( glyf->advance.x + 0x8000 ) >> 16;
    *y_advance = ( glyf->advance.y + 0x8000 ) >> 16;

    return error;
  }


  FT_Error
  FTDemo_Index_To_Bitmap( FTDemo_Handle*  handle,
                          FT_ULong        Index,
                          grBitmap*       target,
                          int*            left,
                          int*            top,
                          int*            x_advance,
                          int*            y_advance,
                          FT_Glyph*       aglyf )
  {
    int   cached_bitmap = 1;

    *aglyf = NULL;

    /* use the SBits cache to store small glyph bitmaps; this is a lot */
    /* more memory-efficient                                           */
    /*                                                                 */
    if ( handle->use_sbits_cache        &&
         handle->image_type.width  < 48 &&
         handle->image_type.height < 48 )
    {
      FTC_SBit   sbit;
      FT_Bitmap  source;


      error = FTC_SBitCache_Lookup( handle->sbits_cache,
                                    &handle->image_type,
                                    Index,
                                    &sbit,
                                    NULL );
      if ( error )
        goto Exit;

      if ( sbit->buffer )
      {
        target->rows   = sbit->height;
        target->width  = sbit->width;
        target->pitch  = sbit->pitch;
        target->buffer = sbit->buffer;
        target->grays  = sbit->max_grays + 1;

        switch ( sbit->format )
        {
        case FT_PIXEL_MODE_MONO:
          target->mode = gr_pixel_mode_mono;
          break;

        case FT_PIXEL_MODE_GRAY:
          target->mode  = gr_pixel_mode_gray;
          target->grays = sbit->max_grays + 1;
          break;

        case FT_PIXEL_MODE_GRAY2:
        case FT_PIXEL_MODE_GRAY4:
          source.rows       = sbit->height;
          source.width      = sbit->width;
          source.pitch      = sbit->pitch;
          source.buffer     = sbit->buffer;
          source.pixel_mode = sbit->format;

          (void)FT_Bitmap_Convert( handle->library, &source,
                                   &handle->bitmap, 1 );

          target->pitch  = handle->bitmap.pitch;
          target->buffer = handle->bitmap.buffer;
          target->mode   = gr_pixel_mode_gray;
          target->grays  = handle->bitmap.num_grays;

          cached_bitmap = 0;
          break;

        case FT_PIXEL_MODE_LCD:
          target->mode  = handle->lcd_mode == 2 ? gr_pixel_mode_lcd
                                                : gr_pixel_mode_lcd2;
          target->grays = sbit->max_grays + 1;
          break;

        case FT_PIXEL_MODE_LCD_V:
          target->mode  = handle->lcd_mode == 4 ? gr_pixel_mode_lcdv
                                                : gr_pixel_mode_lcdv2;
          target->grays = sbit->max_grays + 1;
          break;

        default:
          return FT_Err_Invalid_Glyph_Format;
        }


        *left      = sbit->left;
        *top       = sbit->top;
        *x_advance = sbit->xadvance;
        *y_advance = sbit->yadvance;

        goto Exit;
      }
    }

    /* otherwise, use an image cache to store glyph outlines, and render */
    /* them on demand. we can thus support very large sizes easily..     */
    {
      FT_Glyph   glyf;

      error = FTC_ImageCache_Lookup( handle->image_cache,
                                     &handle->image_type,
                                     Index,
                                     &glyf,
                                     NULL );

      if ( !error )
        error = FTDemo_Glyph_To_Bitmap( handle, glyf, target, left, top,
                                        x_advance, y_advance, aglyf );
    }

  Exit:

#ifdef FT_RGB_FILTER_H
   /* note that we apply the RGB filter to each cached glyph, which is
    * a performance killer, but that's better than modifying the cache
    * at the moment
    */
    if ( !error )
    {
      if ( target->mode == gr_pixel_mode_lcd  ||
           target->mode == gr_pixel_mode_lcdv )
      {
       /* copy the bitmap before filtering it, we don't want to touch
        * the content of cache nodes at all
        */
        {
        }
      }
    }

#endif /* FT_RGB_FILTER_H */

    /* don't accept a `missing' character with zero or negative width */
    if ( Index == 0 && *x_advance <= 0 )
      *x_advance = 1;

    return error;
  }


  FT_Error
  FTDemo_Draw_Index( FTDemo_Handle*   handle,
                     FTDemo_Display*  display,
                     int              gindex,
                     int*             pen_x,
                     int*             pen_y )
  {
    int       left, top, x_advance, y_advance;
    grBitmap  bit3;
    FT_Glyph  glyf;

    error = FTDemo_Index_To_Bitmap( handle, gindex, &bit3, &left, &top,
                                    &x_advance, &y_advance, &glyf );
    if ( error )
      return error;

    /* now render the bitmap into the display surface */
    grBlitGlyphToBitmap( display->bitmap, &bit3, *pen_x + left,
                         *pen_y - top, display->fore_color );

    if ( glyf )
      FT_Done_Glyph( glyf );

    *pen_x += x_advance + 1;

    return FT_Err_Ok;
  }


  FT_Error
  FTDemo_Draw_Glyph( FTDemo_Handle*   handle,
                     FTDemo_Display*  display,
                     FT_Glyph         glyph,
                     int*             pen_x,
                     int*             pen_y )
  {
    int       left, top, x_advance, y_advance;
    grBitmap  bit3;
    FT_Glyph  glyf;


    error = FTDemo_Glyph_To_Bitmap( handle, glyph, &bit3, &left, &top,
                                    &x_advance, &y_advance, &glyf );
    if ( error )
    {
      FT_Done_Glyph( glyph );

      return error;
    }

    /* now render the bitmap into the display surface */
    grBlitGlyphToBitmap( display->bitmap, &bit3, *pen_x + left,
                         *pen_y - top, display->fore_color );

    if ( glyf )
      FT_Done_Glyph( glyf );

⌨️ 快捷键说明

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