ttgload.c

来自「Qt/Embedded是一个多平台的C++图形用户界面应用程序框架」· C语言 代码 · 共 1,332 行 · 第 1/3 页

C
1,332
字号
/***************************************************************************//*                                                                         *//*  ttgload.c                                                              *//*                                                                         *//*    TrueType Glyph Loader (body).                                        *//*                                                                         *//*  Copyright 1996-1999 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.                                        *//*                                                                         *//***************************************************************************/#include <freetype.h>#include <ftdebug.h>#include <ftcalc.h>#include <ftstream.h>#include <sfnt.h>#include <ttgload.h>#include <tttags.h>#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER#include <ttinterp.h>#endif  /* required for the tracing mode */#undef  FT_COMPONENT#define FT_COMPONENT  trace_ttgload  /*************************************************************************/  /*                                                                       */  /* Composite font flags.                                                 */  /*                                                                       */#define ARGS_ARE_WORDS       0x001#define ARGS_ARE_XY_VALUES   0x002#define ROUND_XY_TO_GRID     0x004#define WE_HAVE_A_SCALE      0x008/* reserved                  0x010 */#define MORE_COMPONENTS      0x020#define WE_HAVE_AN_XY_SCALE  0x040#define WE_HAVE_A_2X2        0x080#define WE_HAVE_INSTR        0x100#define USE_MY_METRICS       0x200  /*************************************************************************/  /*    Returns the horizontal or vertical metrics in font units for a     */  /*    given glyph.  The metrics are the left side bearing (resp. top     */  /*    side bearing) and advance width (resp. advance height).            */  /*                                                                       */  LOCAL_FUNC  void  TT_Get_Metrics( TT_HoriHeader*  header,                        TT_UInt       index,                        TT_Short*       bearing,                        TT_UShort*      advance )  {    TT_LongMetrics*  longs_m;    TT_UShort        k = header->number_Of_HMetrics;    if ( index < k )    {      longs_m  = (TT_LongMetrics*)header->long_metrics + index;      *bearing = longs_m->bearing;      *advance = longs_m->advance;    }    else    {      *bearing = ((TT_ShortMetrics*)header->short_metrics)[index - k];      *advance = ((TT_LongMetrics*)header->long_metrics)[k - 1].advance;    }  }  /*************************************************************************/  /*    Returns the horizontal metrics in font units for a given glyph.    */  /*    If `check' is true, take care of monospaced fonts by returning the */  /*    advance width maximum.                                             */  /*                                                                       */  static  void Get_HMetrics( TT_Face     face,                     TT_UInt     index,                     TT_Bool     check,                     TT_Short*   lsb,                     TT_UShort*  aw )  {    TT_Get_Metrics( &face->horizontal, index, lsb, aw );    if ( check && face->postscript.isFixedPitch )      *aw = face->horizontal.advance_Width_Max;  }  /*************************************************************************/  /*    Returns the advance width table for a given pixel size if it is    */  /*    found in the font's `hdmx' table (if any).                         */  /*                                                                       */  static  TT_Byte*  Get_Advance_Widths( TT_Face    face,                                TT_UShort  ppem )  {    TT_UShort  n;    for ( n = 0; n < face->hdmx.num_records; n++ )      if ( face->hdmx.records[n].ppem == ppem )        return face->hdmx.records[n].widths;    return NULL;  }#define cur_to_org( n, zone )  \          MEM_Copy( (zone)->org, (zone)->cur, n * sizeof ( TT_Vector ) )#define org_to_cur( n, zone )  \          MEM_Copy( (zone)->cur, (zone)->org, n * sizeof ( TT_Vector ) )  /*************************************************************************/  /*    Translates an array of coordinates.                                */  /*                                                                       */  static  void  translate_array( TT_UInt     n,                         TT_Vector*  coords,                         TT_Pos      delta_x,                         TT_Pos      delta_y )  {    TT_UInt  k;    if ( delta_x )      for ( k = 0; k < n; k++ )        coords[k].x += delta_x;    if ( delta_y )      for ( k = 0; k < n; k++ )        coords[k].y += delta_y;  }  /*************************************************************************/  /*    Mounts one glyph zone on top of another.  This is needed to        */  /*    assemble composite glyphs.                                         */  /*                                                                       */  static  void  mount_zone( FT_GlyphZone*  source,                    FT_GlyphZone*  target )  {    TT_UInt  np;    TT_Int   nc;    np = source->n_points;    nc = source->n_contours;    target->org   = source->org + np;    target->cur   = source->cur + np;    target->tags = source->tags + np;    target->contours = source->contours + nc;    target->n_points   = 0;    target->n_contours = 0;  }#undef  IS_HINTED#define IS_HINTED(flags)  ((flags & FT_LOAD_NO_HINTING) == 0)  /*************************************************************************/  /*                                                                       */  /* <Function>                                                            */  /*    Load_Simple_Glyph                                                  */  /*                                                                       */  /* <Description>                                                         */  /*    Loads a simple (i.e, non-composite) glyph.  This function is used  */  /*    for the `Load_Simple' state of TT_Load_Glyph().  All composite     */  /*    glyphs elements will be loaded with routine.                       */  /*                                                                       */  static  TT_Error  Load_Simple( TT_Loader*       load,                         TT_UInt          byte_count,                         TT_Int           n_contours,                         TT_Bool          debug )  {    TT_Error       error;    FT_Stream      stream = load->stream;    FT_GlyphZone*  zone   = &load->zone;    TT_Face        face = load->face;    TT_UShort      n_ins;    TT_Int         n, n_points;            /*********************************************************************/    /* simple check                                                      */        if ( n_contours > load->left_contours )    {      FT_TRACE0(( "ERROR: Glyph index %ld has %d contours > left %d\n",                   load->glyph_index,                   n_contours,                   load->left_contours ));      return TT_Err_Too_Many_Contours;    }    /* preparing the execution context */    mount_zone( &load->base, zone );    /*********************************************************************/    /* reading the contours endpoints                                    */        if ( ACCESS_Frame( byte_count ) )      return error;    for ( n = 0; n < n_contours; n++ )      zone->contours[n] = GET_UShort();    n_points = 0;    if ( n_contours > 0 )      n_points = zone->contours[n_contours - 1] + 1;    /*********************************************************************/    /* reading the bytecode instructions                                 */        n_ins = GET_UShort();    if ( n_points > load->left_points )    {      FT_TRACE0(( "ERROR: Too many points in glyph %ld\n", load->glyph_index ));      error = TT_Err_Too_Many_Points;      goto Fail;    }    FT_TRACE4(( "Instructions size : %d\n", n_ins ));    if ( n_ins > face->max_profile.maxSizeOfInstructions )    {      FT_TRACE0(( "ERROR: Too many instructions!\n" ));      error = TT_Err_Too_Many_Ins;      goto Fail;    }    if (stream->cursor + n_ins > stream->limit)    {      FT_TRACE0(( "ERROR: Instruction count mismatch!\n" ));      error = TT_Err_Too_Many_Ins;      goto Fail;    }#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER    if ( (load->load_flags & (FT_LOAD_NO_SCALE|FT_LOAD_NO_HINTING))==0 )    {      MEM_Copy( load->exec->glyphIns, stream->cursor, n_ins );      error = TT_Set_CodeRange( load->exec, tt_coderange_glyph,                                load->exec->glyphIns, n_ins );      if (error) goto Fail;    }#endif    stream->cursor += n_ins;        /*********************************************************************/    /* reading the point tags                                           */    {          TT_Byte*  flag  = load->zone.tags;      TT_Byte*  limit = flag + n_points;      TT_Byte   c, count;            for (; flag < limit; flag++)      {        *flag = c = GET_Byte();        if ( c & 8 )        {          for ( count = GET_Byte(); count > 0; count-- )            *++flag = c;        }      }    }    /*********************************************************************/    /* reading the X coordinates                                         */        {      TT_Vector*  vec   = zone->org;      TT_Vector*  limit = vec + n_points;      TT_Byte*    flag  = zone->tags;      TT_Pos      x     = 0;            for ( ; vec < limit; vec++, flag++ )      {        TT_Pos  y = 0;                if ( *flag & 2 )        {          y = GET_Byte();          if ((*flag & 16) == 0) y = -y;        }        else if ((*flag & 16) == 0)          y = GET_Short();                  x     += y;        vec->x = x;      }    }    /*********************************************************************/    /* reading the Y coordinates                                         */    {      TT_Vector*  vec   = zone->org;      TT_Vector*  limit = vec + n_points;      TT_Byte*    flag  = zone->tags;      TT_Pos      x     = 0;            for ( ; vec < limit; vec++, flag++ )      {        TT_Pos  y = 0;                if ( *flag & 4 )        {          y = GET_Byte();          if ((*flag & 32) == 0) y = -y;        }        else if ((*flag & 32) == 0)          y = GET_Short();                  x     += y;        vec->y = x;      }    }    FORGET_Frame();    /*********************************************************************/    /* Add shadow points                                                  */        /* Now add the two shadow points at n and n + 1.    */    /* We need the left side bearing and advance width. */    {      TT_Vector*  pp1;      TT_Vector*  pp2;            /* pp1 = xMin - lsb */      pp1    = zone->org + n_points;      pp1->x = load->bbox.xMin - load->left_bearing;      pp1->y = 0;        /* pp2 = pp1 + aw */      pp2    = pp1 + 1;      pp2->x = pp1->x + load->advance;      pp2->y = 0;              /* clear the touch tags */      for ( n = 0; n < n_points; n++ )        zone->tags[n] &= FT_Curve_Tag_On;      zone->tags[n_points    ] = 0;      zone->tags[n_points + 1] = 0;    }    /* Note that we return two more points that are not */    /* part of the glyph outline.                       */    zone->n_points   = n_points;    zone->n_contours = n_contours;    n_points        += 2;    /*******************************************/    /* now eventually scale and hint the glyph */    if (load->load_flags & FT_LOAD_NO_SCALE)    {      /* no scaling, just copy the orig arrays into the cur ones */      org_to_cur( n_points, zone );    }    else    {      TT_Vector*  vec = zone->org;      TT_Vector*  limit = vec + n_points;      TT_Fixed    x_scale = load->size->root.metrics.x_scale;      TT_Fixed    y_scale = load->size->root.metrics.y_scale;      /* first scale the glyph points */      for (; vec < limit; vec++)      {        vec->x = FT_MulFix( vec->x, x_scale );        vec->y = FT_MulFix( vec->y, y_scale );      }      /* if hinting, round pp1, and shift the glyph accordingly */      if ( !IS_HINTED(load->load_flags) )      {        org_to_cur( n_points, zone );      }      else      {        TT_Pos  x = zone->org[n_points-2].x;        x = ((x + 32) & -64) - x;        translate_array( n_points, zone->org, x, 0 );        org_to_cur( n_points, zone );        zone->cur[n_points-1].x = (zone->cur[n_points-1].x + 32) & -64;#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER        /* now consider hinting */        if ( n_ins > 0 )        {          load->exec->is_composite     = FALSE;          load->exec->pedantic_hinting = (TT_Bool)(load->load_flags & FT_LOAD_PEDANTIC);          load->exec->pts              = *zone;          load->exec->pts.n_points    += 2;          error = TT_Run_Context( load->exec, debug );          if ( error && load->exec->pedantic_hinting )            return error;        }#endif      }    }    /* save glyph phantom points */    if ( !load->preserve_pps )    {      load->pp1 = zone->cur[n_points - 2];      load->pp2 = zone->cur[n_points - 1];    }    return TT_Err_Ok;      Fail:    FORGET_Frame();

⌨️ 快捷键说明

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