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

📄 ftcommon.c

📁 Demo for Free type 2.2.1
💻 C
📖 第 1 页 / 共 3 页
字号:
    *pen_x += x_advance + 1;

    return FT_Err_Ok;
  }


  FT_Error
  FTDemo_Draw_Slot( FTDemo_Handle*   handle,
                    FTDemo_Display*  display,
                    FT_GlyphSlot     slot,
                    int*             pen_x,
                    int*             pen_y )
  {
    FT_Glyph   glyph;


    error = FT_Get_Glyph( slot, &glyph );
    if ( error )
      return error;

    error = FTDemo_Draw_Glyph( handle, display, glyph, pen_x, pen_y );

    FT_Done_Glyph( glyph );

    return error;
  }


  void
  FTDemo_String_Set( FTDemo_Handle*        handle,
                     const unsigned char*  string )
  {
    const unsigned char*  p = string;
    unsigned long         codepoint;
    unsigned char         in_code;
    int                   expect;
    PGlyph                glyph = handle->string;


    handle->string_length = 0;
    codepoint = expect = 0;

    while ( *p )
    {
      in_code = *p++ ;

      if ( in_code >= 0xC0 )
      {
        if ( in_code < 0xE0 )           /*  U+0080 - U+07FF   */
        {
          expect = 1;
          codepoint = in_code & 0x1F;
        }
        else if ( in_code < 0xF0 )      /*  U+0800 - U+FFFF   */
        {
          expect = 2;
          codepoint = in_code & 0x0F;
        }
        else if ( in_code < 0xF8 )      /* U+10000 - U+10FFFF */
        {
          expect = 3;
          codepoint = in_code & 0x07;
        }
        continue;
      }
      else if ( in_code >= 0x80 )
      {
        --expect;

        if ( expect >= 0 )
        {
          codepoint <<= 6;
          codepoint  += in_code & 0x3F;
        }
        if ( expect >  0 )
          continue;

        expect = 0;
      }
      else                              /* ASCII, U+0000 - U+007F */
        codepoint = in_code;

      if ( handle->encoding != FT_ENCODING_NONE )
        glyph->glyph_index = FTDemo_Get_Index( handle, codepoint );
      else
        glyph->glyph_index = codepoint;

      glyph++;
      handle->string_length++;

      if ( handle->string_length >= MAX_GLYPHS )
        break;
    }

    handle->string_reload = 1;
  }


  static FT_Error
  string_load( FTDemo_Handle*  handle )
  {
    int        n;
    FT_Size    size;
    FT_Face    face;
    FT_Pos     prev_rsb_delta = 0;


    error = FTDemo_Get_Size( handle, &size );
    if ( error )
      return error;

    face = size->face;

    for ( n = 0; n < handle->string_length; n++ )
    {
      PGlyph  glyph = handle->string + n;


      /* clear existing image if there is one */
      if ( glyph->image )
      {
        FT_Done_Glyph( glyph->image );
        glyph->image = NULL;
      }

      /* load the glyph and get the image */
      if ( !FT_Load_Glyph( face, glyph->glyph_index,
                           handle->image_type.flags )  &&
           !FT_Get_Glyph( face->glyph, &glyph->image ) )
      {
        FT_Glyph_Metrics*  metrics = &face->glyph->metrics;


        /* note that in vertical layout, y-positive goes downwards */

        glyph->vvector.x  = metrics->vertBearingX - metrics->horiBearingX;
        glyph->vvector.y  = -metrics->vertBearingY - metrics->horiBearingY;

        glyph->vadvance.x = 0;
        glyph->vadvance.y = -metrics->vertAdvance;

        if ( prev_rsb_delta - face->glyph->lsb_delta >= 32 )
          glyph->delta = -1 << 6;
        else if ( prev_rsb_delta - face->glyph->lsb_delta < -32 )
          glyph->delta = 1 << 6;
        else
          glyph->delta = 0;
      }
    }

    return FT_Err_Ok;
  }


  FT_Error
  string_render_prepare( FTDemo_Handle*          handle,
                         FTDemo_String_Context*  sc,
                         FT_Vector*              advances )
  {
    FT_Face     face;
    FT_Size     size;
    PGlyph      glyph;
    FT_Pos      track_kern   = 0;
    FT_UInt     prev_index   = 0;
    FT_Vector*  prev_advance = NULL;
    FT_Vector   extent       = {0, 0};
    FT_Int      i;


    error = FTDemo_Get_Size( handle, &size );
    if ( error )
      return error;

    face = size->face;

    if ( !sc->vertical && sc->kerning_degree )
    {
      FT_Fixed  ptsize;


      ptsize = FT_MulFix( face->units_per_EM, face->size->metrics.x_scale );

      if ( FT_Get_Track_Kerning( face, ptsize << 10,
                                 -sc->kerning_degree,
                                 &track_kern ) )
        track_kern = 0;
      else
        track_kern >>= 10;
    }

    for ( i = 0; i < handle->string_length; i++ )
    {
      glyph = handle->string + i;

      if ( !glyph->image )
        continue;

      if ( sc->vertical )
        advances[i] = glyph->vadvance;
      else
      {
        advances[i] = glyph->image->advance;
        advances[i].x >>= 10;
        advances[i].y >>= 10;

        if ( prev_advance )
        {
          prev_advance->x += track_kern;

          if ( sc->kerning_mode )
          {
            FT_Vector  kern;


            FT_Get_Kerning( face, prev_index, glyph->glyph_index,
                FT_KERNING_UNFITTED, &kern );

            prev_advance->x += kern.x;
            prev_advance->y += kern.y;

            if ( sc->kerning_mode > KERNING_MODE_NORMAL )
              prev_advance->x += glyph->delta;
          }
        }
      }

      if ( prev_advance )
      {
        if ( handle->hinted )
        {
          prev_advance->x = ROUND( prev_advance->x );
          prev_advance->y = ROUND( prev_advance->y );
        }

        extent.x += prev_advance->x;
        extent.y += prev_advance->y;
      }

      prev_index   = glyph->glyph_index;
      prev_advance = advances + i;
    }

    if ( prev_advance )
    {
      if ( handle->hinted )
      {
        prev_advance->x = ROUND( prev_advance->x );
        prev_advance->y = ROUND( prev_advance->y );
      }

      extent.x += prev_advance->x;
      extent.y += prev_advance->y;

      /*store the extent in the last slot */
      i = handle->string_length - 1;
      advances[i] = extent;
    }

    return FT_Err_Ok;
  }


  static void
  gamma_ramp_apply( FT_Byte    gamma_ramp[256],
                    grBitmap*  bitmap )
  {
    int       i, j;
    FT_Byte*  p = (FT_Byte*)bitmap->buffer;

    if ( bitmap->pitch < 0 )
      p += -bitmap->pitch * ( bitmap->rows - 1 );

    for ( i = 0; i < bitmap->rows; i++ )
    {
      for ( j = 0; j < bitmap->width; j++ )
        p[j] = gamma_ramp[p[j]];

      p += bitmap->pitch;
    }
  }


  FT_Error
  FTDemo_String_Draw( FTDemo_Handle*          handle,
                      FTDemo_Display*         display,
                      FTDemo_String_Context*  sc,
                      int                     x,
                      int                     y )
  {
    int        n;
    FT_Vector  pen, advances[MAX_GLYPHS];
    FT_Size    size;
    FT_Face    face;


    if ( !sc                        ||
         x < 0                      ||
         y < 0                      ||
         x > display->bitmap->width ||
         y > display->bitmap->rows  )
      return FT_Err_Invalid_Argument;

    error = FTDemo_Get_Size( handle, &size );
    if ( error )
      return error;

    face = size->face;

    if ( handle->string_reload )
    {
      error = string_load( handle );
      if ( error )
        return error;

      handle->string_reload = 0;
    }

    error = string_render_prepare( handle, sc, advances );
    if ( error )
      return error;

    /* change to Cartesian coordinates */
    y = display->bitmap->rows - y;

    /* get the extent, which we store in the last slot */
    pen = advances[handle->string_length - 1];

    pen.x = FT_MulFix( pen.x, sc->center );
    pen.y = FT_MulFix( pen.y, sc->center );

    /* XXX sbits */
    /* get pen position */
    if ( sc->matrix && FT_IS_SCALABLE( face ) )
    {
      FT_Vector_Transform( &pen, sc->matrix );
      pen.x = ( x << 6 ) - pen.x;
      pen.y = ( y << 6 ) - pen.y;
    }
    else
    {
      pen.x = ROUND( ( x << 6 ) - pen.x );
      pen.y = ROUND( ( y << 6 ) - pen.y );
    }

    for ( n = 0; n < handle->string_length; n++ )
    {
      PGlyph    glyph = handle->string + n;
      FT_Glyph  image;
      FT_BBox   bbox;


      if ( !glyph->image )
        continue;

      /* copy image */
      error = FT_Glyph_Copy( glyph->image, &image );
      if ( error )
        continue;

      if ( image->format != FT_GLYPH_FORMAT_BITMAP )
      {
        if ( sc->vertical )
          error = FT_Glyph_Transform( image, NULL, &glyph->vvector );

        if ( !error )
          error = FT_Glyph_Transform( image, sc->matrix, &pen );

        if ( error )
        {
          FT_Done_Glyph( image );
          continue;
        }
      }
      else
      {
        FT_BitmapGlyph  bitmap = (FT_BitmapGlyph)image;


        if ( sc->vertical )
        {
          bitmap->left += ( glyph->vvector.x + pen.x ) >> 6;
          bitmap->top  += ( glyph->vvector.x + pen.y ) >> 6;
        }
        else
        {
          bitmap->left += pen.x >> 6;
          bitmap->top  += pen.y >> 6;
        }
      }

      if ( sc->matrix )
        FT_Vector_Transform( advances + n, sc->matrix );

      pen.x += advances[n].x;
      pen.y += advances[n].y;

      FT_Glyph_Get_CBox( image, FT_GLYPH_BBOX_PIXELS, &bbox );

#if 0
      if ( n == 0 )
      {
        fprintf( stderr, "bbox = [%ld %ld %ld %ld]\n",
            bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax );
      }
#endif

      /* check bounding box; if it is completely outside the */
      /* display surface, we don't need to render it         */
      if ( bbox.xMax > 0                      &&
           bbox.yMax > 0                      &&
           bbox.xMin < display->bitmap->width &&
           bbox.yMin < display->bitmap->rows  )
      {
        int       left, top, dummy1, dummy2;
        grBitmap  bit3;
        FT_Glyph  glyf;


        error = FTDemo_Glyph_To_Bitmap( handle, image, &bit3, &left, &top,
                                        &dummy1, &dummy2, &glyf );
        if ( !error )
        {
          if ( sc->gamma_ramp )
            gamma_ramp_apply( sc->gamma_ramp, &bit3 );

          /* change back to the usual coordinates */
          top = display->bitmap->rows - top;

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

          if ( glyf )
            FT_Done_Glyph( glyf );
        }
      }

      FT_Done_Glyph( image );
    }

    return error;
  }


  FT_Encoding
  FTDemo_Make_Encoding_Tag( const char*  s )
  {
    int            i;
    unsigned long  l = 0;


    for ( i = 0; i < 4; i++ )
    {
      if ( !s[i] )
        break;
      l <<= 8;
      l  += (unsigned long)s[i];
    }

    return (FT_Encoding)l;
  }


/* End */

⌨️ 快捷键说明

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