ttgload.c

来自「一个类似windows」· C语言 代码 · 共 1,925 行 · 第 1/5 页

C
1,925
字号
  {
    FT_GlyphLoader  gloader  = load->gloader;
    FT_Outline*     outline  = &gloader->current.outline;
    FT_UInt         n_points = outline->n_points;
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
    FT_UInt         n_ins;
#endif
    TT_GlyphZone    zone     = &load->zone;
    FT_Error        error    = TT_Err_Ok;

    FT_UNUSED( debug );  /* used by truetype interpreter only */


#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
    n_ins = load->glyph->control_len;
#endif

    /* add shadow points */

    /* Add two horizontal shadow points at n and n+1.   */
    /* We need the left side bearing and advance width. */
    /* Add two vertical shadow points at n+2 and n+3.   */
    /* We need the top side bearing and advance height. */

    {
      FT_Vector*  pp1;
      FT_Vector*  pp2;
      FT_Vector*  pp3;
      FT_Vector*  pp4;


      /* pp1 = xMin - lsb */
      pp1    = outline->points + 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;

      /* pp3 = top side bearing */
      pp3    = pp1 + 2;
      pp3->x = 0;
      pp3->y = load->top_bearing + load->bbox.yMax;

      /* pp4 = pp3 - ah */
      pp4    = pp1 + 3;
      pp4->x = 0;
      pp4->y = pp3->y - load->vadvance;

      outline->tags[n_points    ] = 0;
      outline->tags[n_points + 1] = 0;
      outline->tags[n_points + 2] = 0;
      outline->tags[n_points + 3] = 0;
    }

    /* Note that we return four more points that are not */
    /* part of the glyph outline.                        */

    n_points += 4;

#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT

    if ( ((TT_Face)load->face)->doblend )
    {
      /* Deltas apply to the unscaled data. */
      FT_Vector*    deltas;
      FT_Memory     memory       = load->face->memory;
      FT_StreamRec  saved_stream = *(load->stream);
      FT_UInt       i;


      /* TT_Vary_Get_Glyph_Deltas uses a frame, thus we have to save */
      /* (and restore) the current one                               */
      load->stream->cursor = 0;
      load->stream->limit  = 0;

      error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(load->face),
                                        load->glyph_index,
                                        &deltas,
                                        n_points );

      *(load->stream) = saved_stream;

      if ( error )
        goto Exit;

      for ( i = 0; i < n_points; ++i )
      {
        outline->points[i].x += deltas[i].x;
        outline->points[i].y += deltas[i].y;
      }

      FT_FREE( deltas );
    }

#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */

    /* set up zone for hinting */
    tt_prepare_zone( zone, &gloader->current, 0, 0 );

    /* eventually scale the glyph */
    if ( !( load->load_flags & FT_LOAD_NO_SCALE ) )
    {
      FT_Vector*  vec     = zone->cur;
      FT_Vector*  limit   = vec + n_points;
      FT_Fixed    x_scale = ((TT_Size)load->size)->metrics.x_scale;
      FT_Fixed    y_scale = ((TT_Size)load->size)->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 );
      }
    }

    cur_to_org( n_points, zone );

    /* eventually hint the glyph */
    if ( IS_HINTED( load->load_flags ) )
    {
      FT_Pos  x = zone->org[n_points-4].x;


      x = FT_PIX_ROUND( x ) - x;
      translate_array( n_points, zone->org, x, 0 );

      org_to_cur( n_points, zone );

      zone->cur[n_points - 3].x = FT_PIX_ROUND( zone->cur[n_points - 3].x );
      zone->cur[n_points - 1].y = FT_PIX_ROUND( zone->cur[n_points - 1].y );

#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER

      /* now consider hinting */
      if ( n_ins > 0 )
      {
        error = TT_Set_CodeRange( load->exec, tt_coderange_glyph,
                                  load->exec->glyphIns, n_ins );
        if ( error )
          goto Exit;

        load->exec->is_composite     = FALSE;
        load->exec->pts              = *zone;
        load->exec->pts.n_points    += 4;

        error = TT_Run_Context( load->exec, debug );
        if ( error && load->exec->pedantic_hinting )
          goto Exit;

        error = TT_Err_Ok;  /* ignore bytecode errors in non-pedantic mode */
      }

#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */

    }

    /* save glyph phantom points */
    if ( !load->preserve_pps )
    {
      load->pp1 = zone->cur[n_points - 4];
      load->pp2 = zone->cur[n_points - 3];
      load->pp3 = zone->cur[n_points - 2];
      load->pp4 = zone->cur[n_points - 1];
    }

#if defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER ) || \
    defined( TT_CONFIG_OPTION_GX_VAR_SUPPORT )
  Exit:
#endif

    return error;
  }


  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
  /*    load_truetype_glyph                                                */
  /*                                                                       */
  /* <Description>                                                         */
  /*    Loads a given truetype glyph.  Handles composites and uses a       */
  /*    TT_Loader object.                                                  */
  /*                                                                       */
  static FT_Error
  load_truetype_glyph( TT_Loader  loader,
                       FT_UInt    glyph_index,
                       FT_UInt    recurse_count )
  {

#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
    FT_Stream       stream = loader->stream;
#endif

    FT_Error        error;
    TT_Face         face = (TT_Face)loader->face;
    FT_ULong        offset;
    FT_Int          contours_count;
    FT_UInt         num_points, count;
    FT_Fixed        x_scale, y_scale;
    FT_GlyphLoader  gloader = loader->gloader;
    FT_Bool         opened_frame = 0;

#ifdef FT_CONFIG_OPTION_INCREMENTAL
    FT_StreamRec    inc_stream;
    FT_Data         glyph_data;
    FT_Bool         glyph_data_loaded = 0;
#endif

#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    FT_Vector      *deltas;
#endif


    if ( recurse_count >= TT_MAX_COMPOSITE_RECURSE )
    {
      error = TT_Err_Invalid_Composite;
      goto Exit;
    }

    /* check glyph index */
    if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
    {
      error = TT_Err_Invalid_Glyph_Index;
      goto Exit;
    }

    loader->glyph_index = glyph_index;
    num_points          = 0;

    x_scale = 0x10000L;
    y_scale = 0x10000L;
    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
    {
      x_scale = ((TT_Size)loader->size)->metrics.x_scale;
      y_scale = ((TT_Size)loader->size)->metrics.y_scale;
    }

    /* get metrics, horizontal and vertical */
    {
      FT_Short   left_bearing = 0, top_bearing = 0;
      FT_UShort  advance_width = 0, advance_height = 0;


      Get_HMetrics( face, glyph_index,
                    (FT_Bool)!( loader->load_flags &
                                FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
                    &left_bearing,
                    &advance_width );
      Get_VMetrics( face, glyph_index,
                    (FT_Bool)!( loader->load_flags &
                                FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
                    &top_bearing,
                    &advance_height );

#ifdef FT_CONFIG_OPTION_INCREMENTAL

      /* If this is an incrementally loaded font see if there are */
      /* overriding metrics for this glyph.                       */
      if ( face->root.internal->incremental_interface &&
           face->root.internal->incremental_interface->funcs->get_glyph_metrics )
      {
        FT_Incremental_MetricsRec  metrics;


        metrics.bearing_x = left_bearing;
        metrics.bearing_y = 0;
        metrics.advance = advance_width;
        error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
                  face->root.internal->incremental_interface->object,
                  glyph_index, FALSE, &metrics );
        if ( error )
          goto Exit;
        left_bearing  = (FT_Short)metrics.bearing_x;
        advance_width = (FT_UShort)metrics.advance;
      }

# if 0
      /* GWW: Do I do the same for vertical metrics ??? */
      if ( face->root.internal->incremental_interface &&
           face->root.internal->incremental_interface->funcs->get_glyph_metrics )
      {
        FT_Incremental_MetricsRec  metrics;


        metrics.bearing_x = 0;
        metrics.bearing_y = top_bearing;
        metrics.advance = advance_height;
        error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
                  face->root.internal->incremental_interface->object,
                  glyph_index, TRUE, &metrics );
        if ( error )
          goto Exit;
        top_bearing  = (FT_Short)metrics.bearing_y;
        advance_height = (FT_UShort)metrics.advance;
      }
# endif

#endif /* FT_CONFIG_OPTION_INCREMENTAL */

      loader->left_bearing = left_bearing;
      loader->advance      = advance_width;
      loader->top_bearing  = top_bearing;
      loader->vadvance     = advance_height;

      if ( !loader->linear_def )
      {
        loader->linear_def = 1;
        loader->linear     = advance_width;
      }
    }

#ifdef FT_CONFIG_OPTION_INCREMENTAL

    /* Set `offset' to the start of the glyph program relative to the  */
    /* start of the 'glyf' table, and `count' to the length of the     */
    /* glyph program in bytes.                                         */
    /*                                                                 */
    /* If we are loading glyph data via the incremental interface, set */
    /* the loader stream to a memory stream reading the data returned  */
    /* by the interface.                                               */

    if ( face->root.internal->incremental_interface )
    {
      error = face->root.internal->incremental_interface->funcs->get_glyph_data(
                face->root.internal->incremental_interface->object,
                glyph_index, &glyph_data );
      if ( error )
        goto Exit;

      glyph_data_loaded = 1;
      offset            = 0;
      count             = glyph_data.length;

      FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) );
      FT_Stream_OpenMemory( &inc_stream,
                            glyph_data.pointer, glyph_data.length );

      loader->stream = &inc_stream;
    }
    else

#endif /* FT_CONFIG_OPTION_INCREMENTAL */

    offset = tt_face_get_location( face, glyph_index, &count );

    if ( count == 0 )
    {
      /* as described by Frederic Loyer, these are spaces, and */
      /* not the unknown glyph.                                */
      loader->bbox.xMin = 0;
      loader->bbox.xMax = 0;
      loader->bbox.yMin = 0;
      loader->bbox.yMax = 0;

      loader->pp1.x = 0;
      loader->pp2.x = loader->advance;
      loader->pp3.y = 0;
      loader->pp4.y = loader->pp3.y-loader->vadvance;

#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
      if ( ((TT_Face)(loader->face))->doblend )
      {
        /* this must be done before scaling */
        FT_Memory  memory = loader->face->memory;


        error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
                                          glyph_index, &deltas, 4 );
        if ( error )
          goto Exit;

        loader->pp1.x += deltas[0].x; loader->pp1.y += deltas[0].y;
        loader->pp2.x += deltas[1].x; loader->pp2.y += deltas[1].y;
        loader->pp3.x += deltas[2].x; loader->pp3.y += deltas[2].y;
        loader->pp4.x += deltas[3].x; loader->pp4.y += deltas[3].y;

        FT_FREE( deltas );
      }
#endif

      if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
      {

⌨️ 快捷键说明

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