ttgload.c

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

C
1,925
字号

        /* we have finished loading all sub-glyphs; now, look for */
        /* instructions for this composite!                       */

#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER

        if ( num_subglyphs > 0               &&
             loader->exec                    &&
             ins_pos > 0                     &&
             subglyph->flags & WE_HAVE_INSTR )
        {
          FT_UShort       n_ins;
          TT_ExecContext  exec = loader->exec;
          TT_GlyphZone    pts;
          FT_Vector*      pp1;


          /* read size of instructions */
          if ( FT_STREAM_SEEK( ins_pos ) ||
               FT_READ_USHORT( n_ins ) )
            goto Fail;
          FT_TRACE5(( "  Instructions size = %d\n", n_ins ));

          /* in some fonts? */
          if ( n_ins == 0xFFFFU )
            n_ins = 0;

          /* check it */
          if ( n_ins > face->max_profile.maxSizeOfInstructions )
          {
            FT_TRACE0(( "Too many instructions (%d) in composite glyph %ld\n",
                        n_ins, subglyph->index ));
            error = TT_Err_Too_Many_Hints;
            goto Fail;
          }

          /* read the instructions */
          if ( FT_STREAM_READ( exec->glyphIns, n_ins ) )
            goto Fail;

          glyph->control_data = exec->glyphIns;
          glyph->control_len  = n_ins;

          error = TT_Set_CodeRange( exec,
                                    tt_coderange_glyph,
                                    exec->glyphIns,
                                    n_ins );
          if ( error )
            goto Fail;

          error = FT_GlyphLoader_CheckPoints( gloader, num_points + 4, 0 );
          if ( error )
            goto Fail;

          /* prepare the execution context */
          tt_prepare_zone( &exec->pts, &gloader->base,
                           start_point, start_contour );
          pts = &exec->pts;

          pts->n_points   = (short)( num_points + 4 );
          pts->n_contours = gloader->base.outline.n_contours;

          /* add phantom points */
          pp1    = pts->cur + num_points;
          pp1[0] = loader->pp1;
          pp1[1] = loader->pp2;
          pp1[2] = loader->pp3;
          pp1[3] = loader->pp4;

          pts->tags[num_points    ] = 0;
          pts->tags[num_points + 1] = 0;
          pts->tags[num_points + 2] = 0;
          pts->tags[num_points + 3] = 0;

          /* if hinting, round the phantom points */
          if ( IS_HINTED( loader->load_flags ) )
          {
            pp1[0].x = FT_PIX_ROUND( loader->pp1.x );
            pp1[1].x = FT_PIX_ROUND( loader->pp2.x );
            pp1[2].y = FT_PIX_ROUND( loader->pp3.y );
            pp1[3].y = FT_PIX_ROUND( loader->pp4.y );
          }

          {
            FT_UInt  k;


            for ( k = 0; k < num_points; k++ )
              pts->tags[k] &= FT_CURVE_TAG_ON;
          }

          cur_to_org( num_points + 4, pts );

          /* now consider hinting */
          if ( IS_HINTED( loader->load_flags ) && n_ins > 0 )
          {
            exec->is_composite     = TRUE;
            error = TT_Run_Context( exec, ((TT_Size)loader->size)->debug );
            if ( error && exec->pedantic_hinting )
              goto Fail;
          }

          /* save glyph origin and advance points */
          loader->pp1 = pp1[0];
          loader->pp2 = pp1[1];
          loader->pp3 = pp1[2];
          loader->pp4 = pp1[3];
        }

#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */

      }
      /* end of composite loading */
    }
    else
    {
      /* invalid composite count ( negative but not -1 ) */
      error = TT_Err_Invalid_Outline;
      goto Fail;
    }

    /***********************************************************************/
    /***********************************************************************/
    /***********************************************************************/

  Fail:
    if ( opened_frame )
      face->forget_glyph_frame( loader );

  Exit:

#ifdef FT_CONFIG_OPTION_INCREMENTAL
    if ( glyph_data_loaded )
      face->root.internal->incremental_interface->funcs->free_glyph_data(
        face->root.internal->incremental_interface->object,
        &glyph_data );
#endif

    return error;
  }


  static FT_Error
  compute_glyph_metrics( TT_Loader   loader,
                         FT_UInt     glyph_index )
  {
    FT_BBox       bbox;
    TT_Face       face = (TT_Face)loader->face;
    FT_Fixed      y_scale;
    TT_GlyphSlot  glyph = loader->glyph;
    TT_Size       size = (TT_Size)loader->size;


    y_scale = 0x10000L;
    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
      y_scale = size->root.metrics.y_scale;

    if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
    {
      glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;

      /* copy outline to our glyph slot */
      FT_GlyphLoader_CopyPoints( glyph->internal->loader, loader->gloader );
      glyph->outline = glyph->internal->loader->base.outline;

      /* translate array so that (0,0) is the glyph's origin */
      FT_Outline_Translate( &glyph->outline, -loader->pp1.x, 0 );

      FT_Outline_Get_CBox( &glyph->outline, &bbox );

      if ( IS_HINTED( loader->load_flags ) )
      {
        /* grid-fit the bounding box */
        bbox.xMin = FT_PIX_FLOOR( bbox.xMin );
        bbox.yMin = FT_PIX_FLOOR( bbox.yMin );
        bbox.xMax = FT_PIX_CEIL( bbox.xMax );
        bbox.yMax = FT_PIX_CEIL( bbox.yMax );
      }
    }
    else
      bbox = loader->bbox;

    /* get the device-independent horizontal advance.  It is scaled later */
    /* by the base layer.                                                 */
    {
      FT_Pos  advance = loader->linear;


      /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
      /* correctly support DynaLab fonts, which have an incorrect       */
      /* `advance_Width_Max' field!  It is used, to my knowledge,       */
      /* exclusively in the X-TrueType font server.                     */
      /*                                                                */
      if ( face->postscript.isFixedPitch                                     &&
           ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
        advance = face->horizontal.advance_Width_Max;

      /* we need to return the advance in font units in linearHoriAdvance, */
      /* it will be scaled later by the base layer.                        */
      glyph->linearHoriAdvance = advance;
    }

    glyph->metrics.horiBearingX = bbox.xMin;
    glyph->metrics.horiBearingY = bbox.yMax;
    glyph->metrics.horiAdvance  = loader->pp2.x - loader->pp1.x;

    /* don't forget to hint the advance when we need to */
    if ( IS_HINTED( loader->load_flags ) )
      glyph->metrics.horiAdvance = FT_PIX_ROUND( glyph->metrics.horiAdvance );

    /* Now take care of vertical metrics.  In the case where there is    */
    /* no vertical information within the font (relatively common), make */
    /* up some metrics by `hand'...                                      */

    {
      FT_Short   top_bearing;    /* vertical top side bearing (EM units) */
      FT_UShort  advance_height; /* vertical advance height   (EM units) */

      FT_Pos     left;     /* scaled vertical left side bearing */
      FT_Pos     top;      /* scaled vertical top side bearing  */
      FT_Pos     advance;  /* scaled vertical advance height    */


      /* Get the unscaled top bearing and advance height. */
      if ( face->vertical_info &&
           face->vertical.number_Of_VMetrics > 0 )
      {
        advance_height = (FT_UShort)( loader->pp4.y - loader->pp3.y );
        top_bearing    = (FT_Short)( loader->pp3.y - bbox.yMax );
      }
      else
      {
        /* Make up the distances from the horizontal header.   */

        /* NOTE: The OS/2 values are the only `portable' ones, */
        /*       which is why we use them, if there is an OS/2 */
        /*       table in the font.  Otherwise, we use the     */
        /*       values defined in the horizontal header.      */
        /*                                                     */
        /* NOTE2: The sTypoDescender is negative, which is why */
        /*        we compute the baseline-to-baseline distance */
        /*        here with:                                   */
        /*             ascender - descender + linegap          */
        /*                                                     */
        /* NOTE3: This is different from what MS's rasterizer  */
        /*        appears to do when getting default values    */
        /*        for the vertical phantom points.  We leave   */
        /*        the old code untouched, but relying on       */
        /*        phantom points alone might be reasonable     */
        /*        (i.e., removing the `if' above).             */
        if ( face->os2.version != 0xFFFFU )
        {
          top_bearing    = (FT_Short)( face->os2.sTypoLineGap / 2 );
          advance_height = (FT_UShort)( face->os2.sTypoAscender -
                                        face->os2.sTypoDescender +
                                        face->os2.sTypoLineGap );
        }
        else
        {
          top_bearing    = (FT_Short)( face->horizontal.Line_Gap / 2 );
          advance_height = (FT_UShort)( face->horizontal.Ascender  +
                                        face->horizontal.Descender +
                                        face->horizontal.Line_Gap );
        }
      }

#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;
        FT_Error                   error = TT_Err_Ok;


        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 )
          return error;

        top_bearing    = (FT_Short)metrics.bearing_y;
        advance_height = (FT_UShort)metrics.advance;
      }

      /* GWW: Do vertical metrics get loaded incrementally too? */

#endif /* FT_CONFIG_OPTION_INCREMENTAL */

      /* We must adjust the top_bearing value from the bounding box given */
      /* in the glyph header to the bounding box calculated with          */
      /* FT_Get_Outline_CBox().                                           */

      /* scale the metrics */
      if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
      {
        top     = FT_MulFix( top_bearing + loader->bbox.yMax, y_scale )
                    - bbox.yMax;
        advance = FT_MulFix( advance_height, y_scale );
      }
      else
      {
        top     = top_bearing + loader->bbox.yMax - bbox.yMax;
        advance = advance_height;
      }

      /* set the advance height in design units.  It is scaled later by */
      /* the base layer.                                                */
      glyph->linearVertAdvance = advance_height;

      /* XXX: for now, we have no better algorithm for the lsb, but it */
      /*      should work fine.                                        */
      /*                                                               */
      left = ( bbox.xMin - bbox.xMax ) / 2;

      /* grid-fit them if necessary */
      if ( IS_HINTED( loader->load_flags ) )
      {
        left    = FT_PIX_FLOOR( left );
        top     = FT_PIX_CEIL( top );
        advance = FT_PIX_ROUND( advance );
      }

      glyph->metrics.vertBearingX = left;
      glyph->metrics.vertBearingY = top;
      glyph->metrics.vertAdvance  = advance;
    }

    /* adjust advance width to the value contained in the hdmx table */
    if ( !face->postscript.isFixedPitch && size &&
         IS_HINTED( loader->load_flags )        )
    {
      FT_Byte*  widthp = Get_Advance_WidthPtr( face,
                                               size->root.metrics.x_ppem,
                                               glyph_index );


      if ( widthp )
        glyph->metrics.horiAdvance = *widthp << 6;
    }

    /* set glyph dimensions */
    glyph->metrics.width  = bbox.xMax - bbox.xMin;
    glyph->metrics.height = bbox.yMax - bbox.yMin;

    return 0;
  }


  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
  /*    TT_Load_Glyph                                                      */
  /*                                                                       */
  /* <Description>                                                         */
  /*    A function used to load a single glyph within a given glyph slot,  */
  /*    for a given size.                                                  */
  /*                                                                       */
  /* <Input>                                                               */
  /*    glyph       :: A handle to a target slot object where the glyph    */
  /*                   will be loaded.                                     */
  /*                                                                       */
  /*    size        :: A handle to the source face size at which the glyph */
  /*                   must be scaled/loaded.                              */
  /*                                                                       */
  /*    glyph_index :: The index of the glyph in the font file.            */
  /*                                                                       */
  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
  /*                   FT_LOAD_XXX constants can be used to control the    */
  /*                   glyph loading process (e.g., whether the outline    */
  /*                   should be scaled, whether to load bitmaps or not,   */
  /*                   whether to hint the outline, etc).                  */
  /*                                                                       */
  /* <Return>                                                              */
  /*    FreeType error code.  0 means success.                             */
  /*                                                                       */
  FT_LOCAL_DEF( FT_Error )
  TT_

⌨️ 快捷键说明

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