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

📄 ftstring.c

📁 Ftee type Demo for Linux open source
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************/
/*                                                                          */
/*  The FreeType project -- a free and portable quality TrueType renderer.  */
/*                                                                          */
/*  Copyright 1996-2002, 2003, 2004 by                                      */
/*  D. Turner, R.Wilhelm, and W. Lemberg                                    */
/*                                                                          */
/*                                                                          */
/*  ftstring.c - simple text string display                                 */
/*                                                                          */
/****************************************************************************/

#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include "common.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <math.h>

#include "graph.h"
#include "grfont.h"

#define DIM_X  500
#define DIM_Y  400

#define CENTER_X  ( bit.width / 2 )
#define CENTER_Y  ( bit.rows  / 2 )

#define MAXPTSIZE  500                 /* dtp */

  static char   Header[128];
  static char*  new_header = 0;

  static char*  Text = (char *)"The quick brown fox jumps over the lazy dog";

  static FT_Library   library;      /* the FreeType library            */
  static FT_Face      face;         /* the font face                   */
  static FT_Error     error;        /* error returned by FreeType?     */

  static FT_Encoding  encoding = FT_ENCODING_UNICODE;

  static grSurface*   surface;      /* current display surface         */
  static grBitmap     bit;          /* current display bitmap          */

  static int  ptsize;               /* current point size */
  static int  Num;
  static int  Rotation = 0;
  static int  Fail;

  static int  hinted    = 1;        /* is glyph hinting active?        */
  static int  antialias = 1;        /* is anti-aliasing active?        */
  static int  use_sbits = 0;        /* do we use embedded bitmaps?     */
  static int  kerning   = 2;        /* 0: no kerning;                  */
                                    /* 1: `kern' values                */
                                    /* 2: `kern' + side bearing errors */
  static int  autohint  = 0;        /* is forced hinting active?       */
  static int  use_gamma = 0;

  static int  res = 72;             /* default resolution in dpi */

  static grColor  fore_color = { 255 };

  static int  graph_init  = 0;

  static FT_Matrix  trans_matrix;
  static int        transform = 0;

  static FT_Vector  string_center;

  typedef struct  TGlyph_
  {
    FT_UInt    glyph_index;         /* glyph index in face      */
    FT_Vector  pos;                 /* position of glyph origin */
    FT_Glyph   image;               /* glyph image              */

  } TGlyph, *PGlyph;


#define FLOOR( x )  ( (x) & -64 )
#define CEIL( x )   ( ( (x) + 63 ) & -64 )
#define TRUNC ( x)  ( (x) >> 6 )



/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
/****                                                                    ****/
/****                 U T I L I T Y   F U N C T I O N S                  ****/
/****                                                                    ****/
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/

#define DEBUGxxx

#ifdef DEBUG
#define LOG( x )  LogMessage##x
#else
#define LOG( x )  /* empty */
#endif

#ifdef DEBUG
  static void
  LogMessage( const char*  fmt, ... )
  {
    va_list  ap;


    va_start( ap, fmt );
    vfprintf( stderr, fmt, ap );
    va_end( ap );
  }
#endif

  /* PanicZ */
  static void
  PanicZ( const char* message )
  {
    fprintf( stderr, "%s\n  error = 0x%04x\n", message, error );
    exit( 1 );
  }


  static unsigned long
  make_tag( 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 l;
  }


/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
/****                                                                    ****/
/****                D I S P L A Y   M A N A G E M E N T                 ****/
/****                                                                    ****/
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/

#define MAX_GLYPHS 512

  /*************************************************************************/
  /*                                                                       */
  /*  The following arrays are used to store the glyph set that makes      */
  /*  up a string of text.                                                 */
  /*                                                                       */
  /*                                                                       */
  static TGlyph  glyphs[MAX_GLYPHS];
  static int     num_glyphs;

  /*************************************************************************/
  /*                                                                       */
  /* Gamma correction.                                                     */
  /*                                                                       */
  /*                                                                       */
  static double  gamma_value = 2.0f;
  static FT_Byte gamma_ramp[256];

  static void
  init_gamma( void )
  {
    int i;
    double gamma_inv = 1.0f / gamma_value;

    for (i = 0; i < 256; i++)
      gamma_ramp[i] = (FT_Byte)( pow((double)i / 255.0f, gamma_inv) * 255.0f );
  }

  static void
  apply_gamma( grBitmap* bmp )
  {
    int       i, j;
    FT_Byte*  buffer = (FT_Byte*) bmp->buffer;

    for (i = 0; i < bmp->rows; i++)
    {
      for (j = 0; j < bmp->width; j++)
        buffer[j] = (FT_Byte) gamma_ramp[buffer[j]];

      buffer += bmp->pitch;
    }
  }

  static void
  draw_gamma_ramp( void )
  {
    int   i, x, y;
    long  pitch = bit.pitch;
    long  start = 0;

    if ( pitch < 0 )
      start = -pitch*(bit.rows-1);

    x = (bit.width - 256) / 2;
    y = (bit.rows + 256) / 2;
    for (i = 0; i < 256; i++, x++)
    {
      bit.buffer[start + pitch*(y - gamma_ramp[i]) + x ] = 80;
    }
  }


  /*************************************************************************/
  /*                                                                       */
  /* Initialize the display surface.                                       */
  /*                                                                       */
  /*                                                                       */
  static int
  init_display( void )
  {
    grInitDevices();

    bit.mode  = gr_pixel_mode_gray;
    bit.width = DIM_X;
    bit.rows  = DIM_Y;
    bit.grays = 256;

    surface = grNewSurface( 0, &bit );
    if ( !surface )
      PanicZ( "could not allocate display surface\n" );

    graph_init = 1;
    return 0;
  }


  /*************************************************************************/
  /*                                                                       */
  /*  Clear the display surface.                                           */
  /*                                                                       */
  /*                                                                       */
  static void
  clear_display( void )
  {
    long  size = (long)bit.pitch * bit.rows;


    if ( size < 0 )
      size = -size;
    memset( bit.buffer, 0, size );
  }


  static void
  reset_scale( int  pointSize )
  {
    (void)FT_Set_Char_Size( face,
                            pointSize << 6,
                            pointSize << 6,
                            res,
                            res );
  }


  /*************************************************************************/
  /*                                                                       */
  /*  Layout a string of glyphs.  The glyphs are untransformed.            */
  /*                                                                       */
  /*                                                                       */
  static void
  layout_glyphs( void )
  {
    PGlyph     glyph = glyphs;
    int        n;
    FT_Vector  origin;
    FT_Pos     origin_x       = 0;
    FT_UInt    load_flags;
    FT_UInt    prev_index     = 0;
    FT_Pos     prev_rsb_delta = 0;


    load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
    if ( !hinted )
      load_flags |= FT_LOAD_NO_HINTING;
    if ( !use_sbits )
      load_flags |= FT_LOAD_NO_BITMAP;
    if ( autohint )
      load_flags |= FT_LOAD_FORCE_AUTOHINT;

    for ( n = 0; n < num_glyphs; n++, glyph++ )
    {
      /* compute glyph origin */
      if ( kerning )
      {
        if ( prev_index )
        {
          FT_Vector  kern;


          FT_Get_Kerning( face, prev_index, glyph->glyph_index,
                          hinted ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED,
                          &kern );

          origin_x += kern.x;
        }
        prev_index = glyph->glyph_index;
      }

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

      /* load the glyph image (in its native format) */
      error = FT_Load_Glyph( face, glyph->glyph_index, load_flags );
      if ( error )
        continue;

      if ( n && kerning > 1 )
      {
        if ( prev_rsb_delta - face->glyph->lsb_delta >= 32 )
          origin_x -= 64;

        else if ( prev_rsb_delta - face->glyph->lsb_delta < -32 )
          origin_x += 64;
      }

      origin.x = origin_x;
      origin.y = 0;

      prev_rsb_delta = face->glyph->rsb_delta;

      error = FT_Get_Glyph( face->glyph, &glyph->image );
      if ( error )
        continue;

      glyph->pos = origin;

      origin_x += face->glyph->advance.x;
    }

    string_center.x = ( origin_x / 2 ) & -64;
    string_center.y = 0;

    if ( transform && FT_IS_SCALABLE( face ) )
      FT_Vector_Transform( &string_center, &trans_matrix );
  }


  /*************************************************************************/
  /*                                                                       */
  /* Render a given glyph vector set.                                      */
  /*                                                                       */
  /*                                                                       */
  static void
  render_string( FT_Pos  x, FT_Pos  y )
  {
    PGlyph     glyph = glyphs;
    grBitmap   bit3;
    int        n;
    FT_Vector  delta;


    /* first of all, we must compute the general delta for the glyph set */
    delta.x = ( x << 6 ) - string_center.x;
    delta.y = ( ( bit.rows - y ) << 6 ) - string_center.y;

    for ( n = 0; n < num_glyphs; n++, glyph++ )
    {
      FT_Glyph   image;
      FT_Vector  vec;


      if ( !glyph->image )
        continue;

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

      /* transform it */
      vec = glyph->pos;
      if ( FT_IS_SCALABLE( face ) )
        FT_Vector_Transform( &vec, &trans_matrix );
      vec.x += delta.x;
      vec.y += delta.y;
      if ( FT_IS_SCALABLE( face ) )
        error = FT_Glyph_Transform( image, &trans_matrix, &vec );
      if ( !error )
      {
        FT_BBox  bbox;


        /* check bounding box; if it is not within the display surface, */
        /* we don't need to render it                                   */

        FT_Glyph_Get_CBox( image, FT_GLYPH_BBOX_PIXELS, &bbox );
        if ( !FT_IS_SCALABLE( face ) )
        {
          vec.x = vec.x >> 6;
          vec.y = vec.y >> 6;

          bbox.xMin += vec.x;
          bbox.xMax += vec.x;
          bbox.yMin += vec.y;
          bbox.yMax += vec.y;
        }

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

        if ( bbox.xMax > 0         && bbox.yMax > 0        &&
             bbox.xMin < bit.width && bbox.yMin < bit.rows )
        {
          /* convert to a bitmap -- destroy native image */
          error = FT_Glyph_To_Bitmap( &image,
                                      antialias ? FT_RENDER_MODE_NORMAL
                                                : FT_RENDER_MODE_MONO,
                                      0, 1 );
          if ( !error )
          {
            FT_BitmapGlyph  bitmap = (FT_BitmapGlyph)image;
            FT_Bitmap*      source = &bitmap->bitmap;
            FT_Pos          x_top, y_top;

#if 0
            if ( n == 0 )
            {
              fprintf( stderr, "bearing = [%d %d] dims = [%d %d]\n",
                       bitmap->left, bitmap->top, source->width, source->rows );
            }
#endif

            bit3.rows   = source->rows;
            bit3.width  = source->width;
            bit3.pitch  = source->pitch;
            bit3.buffer = source->buffer;

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

            case FT_PIXEL_MODE_GRAY:
              bit3.mode  = gr_pixel_mode_gray;
              bit3.grays = source->num_grays;
              if (use_gamma)
                apply_gamma(&bit3);
              break;

            default:
              continue;
            }

            /* now render the bitmap into the display surface */
            if ( FT_IS_SCALABLE( face ) )
            {
              x_top = bitmap->left;
              y_top = bit.rows - bitmap->top;
            }
            else
            {
              x_top = vec.x - bitmap->left;
              y_top = vec.y - bitmap->top;
            }
            grBlitGlyphToBitmap( &bit, &bit3, x_top, y_top, fore_color );
          }
        }
      }
      FT_Done_Glyph( image );
    }
  }


  /*************************************************************************/
  /*                                                                       */
  /*  Convert a string of text into a glyph vector.                        */
  /*                                                                       */
  /*  XXX: For now, we perform a trivial conversion.                       */
  /*                                                                       */
  /*                                                                       */
  static void
  prepare_text( const unsigned char*  string )
  {
    const unsigned char*  p     = (const unsigned char*)string;
    PGlyph                glyph = glyphs;
    FT_UInt               glyph_index;
    unsigned char         in_code;
    unsigned long         codepoint = 0;
    int                   expect;


    if ( encoding )
    {
      error = FT_Select_Charmap( face, encoding );
      if ( error )
        PanicZ( "invalid charmap\n" );
    }

⌨️ 快捷键说明

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