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

📄 pshalgo.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
          point->cur_u = hint->cur_pos + hint->cur_len;

        else
        {
          delta = point->org_u - hint->org_pos;

          if ( delta <= 0 )
            point->cur_u = hint->cur_pos + FT_MulFix( delta, scale );

          else if ( delta >= hint->org_len )
            point->cur_u = hint->cur_pos + hint->cur_len +
                             FT_MulFix( delta - hint->org_len, scale );

          else if ( hint->org_len > 0 )
            point->cur_u = hint->cur_pos +
                             FT_MulDiv( delta, hint->cur_len,
                                        hint->org_len );
          else
            point->cur_u = hint->cur_pos;
        }
        psh_point_set_fitted( point );
      }
    }
  }


#define  PSH_MAX_STRONG_INTERNAL  16

  static void
  psh_glyph_interpolate_normal_points( PSH_Glyph  glyph,
                                       FT_Int     dimension )
  {

#if 1
    /* first technique: a point is strong if it is a local extremum */

    PSH_Dimension  dim    = &glyph->globals->dimension[dimension];
    FT_Fixed       scale  = dim->scale_mult;
    FT_Memory      memory = glyph->memory;

    PSH_Point*     strongs     = NULL;
    PSH_Point      strongs_0[PSH_MAX_STRONG_INTERNAL];
    FT_UInt        num_strongs = 0;

    PSH_Point      points = glyph->points;
    PSH_Point      points_end = points + glyph->num_points;
    PSH_Point      point;


    /* first count the number of strong points */
    for ( point = points; point < points_end; point++ )
    {
      if ( psh_point_is_strong( point ) )
        num_strongs++;
    }

    if ( num_strongs == 0 )  /* nothing to do here */
      return;

    /* allocate an array to store a list of points, */
    /* stored in increasing org_u order             */
    if ( num_strongs <= PSH_MAX_STRONG_INTERNAL )
      strongs = strongs_0;
    else
    {
      FT_Error  error;


      if ( FT_NEW_ARRAY( strongs, num_strongs ) )
        return;
    }

    num_strongs = 0;
    for ( point = points; point < points_end; point++ )
    {
      PSH_Point*  insert;


      if ( !psh_point_is_strong( point ) )
        continue;

      for ( insert = strongs + num_strongs; insert > strongs; insert-- )
      {
        if ( insert[-1]->org_u <= point->org_u )
          break;

        insert[0] = insert[-1];
      }
      insert[0] = point;
      num_strongs++;
    }

    /* now try to interpolate all normal points */
    for ( point = points; point < points_end; point++ )
    {
      if ( psh_point_is_strong( point ) )
        continue;

      /* sometimes, some local extrema are smooth points */
      if ( psh_point_is_smooth( point ) )
      {
        if ( point->dir_in == PSH_DIR_NONE   ||
             point->dir_in != point->dir_out )
          continue;

        if ( !psh_point_is_extremum( point ) &&
             !psh_point_is_inflex( point )   )
          continue;

        point->flags &= ~PSH_POINT_SMOOTH;
      }

      /* find best enclosing point coordinates then interpolate */
      {
        PSH_Point   before, after;
        FT_UInt     nn;


        for ( nn = 0; nn < num_strongs; nn++ )
          if ( strongs[nn]->org_u > point->org_u )
            break;

        if ( nn == 0 )  /* point before the first strong point */
        {
          after = strongs[0];

          point->cur_u = after->cur_u +
                           FT_MulFix( point->org_u - after->org_u,
                                      scale );
        }
        else
        {
          before = strongs[nn - 1];

          for ( nn = num_strongs; nn > 0; nn-- )
            if ( strongs[nn - 1]->org_u < point->org_u )
              break;

          if ( nn == num_strongs )  /* point is after last strong point */
          {
            before = strongs[nn - 1];

            point->cur_u = before->cur_u +
                             FT_MulFix( point->org_u - before->org_u,
                                        scale );
          }
          else
          {
            FT_Pos  u;


            after = strongs[nn];

            /* now interpolate point between before and after */
            u = point->org_u;

            if ( u == before->org_u )
              point->cur_u = before->cur_u;

            else if ( u == after->org_u )
              point->cur_u = after->cur_u;

            else
              point->cur_u = before->cur_u +
                               FT_MulDiv( u - before->org_u,
                                          after->cur_u - before->cur_u,
                                          after->org_u - before->org_u );
          }
        }
        psh_point_set_fitted( point );
      }
    }

    if ( strongs != strongs_0 )
      FT_FREE( strongs );

#endif /* 1 */

  }


  /* interpolate other points */
  static void
  psh_glyph_interpolate_other_points( PSH_Glyph  glyph,
                                      FT_Int     dimension )
  {
    PSH_Dimension  dim          = &glyph->globals->dimension[dimension];
    FT_Fixed       scale        = dim->scale_mult;
    FT_Fixed       delta        = dim->scale_delta;
    PSH_Contour    contour      = glyph->contours;
    FT_UInt        num_contours = glyph->num_contours;


    for ( ; num_contours > 0; num_contours--, contour++ )
    {
      PSH_Point  start = contour->start;
      PSH_Point  first, next, point;
      FT_UInt    fit_count;


      /* count the number of strong points in this contour */
      next      = start + contour->count;
      fit_count = 0;
      first     = 0;

      for ( point = start; point < next; point++ )
        if ( psh_point_is_fitted( point ) )
        {
          if ( !first )
            first = point;

          fit_count++;
        }

      /* if there are less than 2 fitted points in the contour, we */
      /* simply scale and eventually translate the contour points  */
      if ( fit_count < 2 )
      {
        if ( fit_count == 1 )
          delta = first->cur_u - FT_MulFix( first->org_u, scale );

        for ( point = start; point < next; point++ )
          if ( point != first )
            point->cur_u = FT_MulFix( point->org_u, scale ) + delta;

        goto Next_Contour;
      }

      /* there are more than 2 strong points in this contour; we */
      /* need to interpolate weak points between them            */
      start = first;
      do
      {
        point = first;

        /* skip consecutive fitted points */
        for (;;)
        {
          next = first->next;
          if ( next == start )
            goto Next_Contour;

          if ( !psh_point_is_fitted( next ) )
            break;

          first = next;
        }

        /* find next fitted point after unfitted one */
        for (;;)
        {
          next = next->next;
          if ( psh_point_is_fitted( next ) )
            break;
        }

        /* now interpolate between them */
        {
          FT_Pos    org_a, org_ab, cur_a, cur_ab;
          FT_Pos    org_c, org_ac, cur_c;
          FT_Fixed  scale_ab;


          if ( first->org_u <= next->org_u )
          {
            org_a  = first->org_u;
            cur_a  = first->cur_u;
            org_ab = next->org_u - org_a;
            cur_ab = next->cur_u - cur_a;
          }
          else
          {
            org_a  = next->org_u;
            cur_a  = next->cur_u;
            org_ab = first->org_u - org_a;
            cur_ab = first->cur_u - cur_a;
          }

          scale_ab = 0x10000L;
          if ( org_ab > 0 )
            scale_ab = FT_DivFix( cur_ab, org_ab );

          point = first->next;
          do
          {
            org_c  = point->org_u;
            org_ac = org_c - org_a;

            if ( org_ac <= 0 )
            {
              /* on the left of the interpolation zone */
              cur_c = cur_a + FT_MulFix( org_ac, scale );
            }
            else if ( org_ac >= org_ab )
            {
              /* on the right on the interpolation zone */
              cur_c = cur_a + cur_ab + FT_MulFix( org_ac - org_ab, scale );
            }
            else
            {
              /* within the interpolation zone */
              cur_c = cur_a + FT_MulFix( org_ac, scale_ab );
            }

            point->cur_u = cur_c;

            point = point->next;

          } while ( point != next );
        }

        /* keep going until all points in the contours have been processed */
        first = next;

      } while ( first != start );

    Next_Contour:
      ;
    }
  }


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                     HIGH-LEVEL INTERFACE                      *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  FT_Error
  ps_hints_apply( PS_Hints        ps_hints,
                  FT_Outline*     outline,
                  PSH_Globals     globals,
                  FT_Render_Mode  hint_mode )
  {
    PSH_GlyphRec  glyphrec;
    PSH_Glyph     glyph = &glyphrec;
    FT_Error      error;
#ifdef DEBUG_HINTER
    FT_Memory     memory;
#endif
    FT_Int        dimension;


    /* something to do? */
    if ( outline->n_points == 0 || outline->n_contours == 0 )
      return PSH_Err_Ok;

#ifdef DEBUG_HINTER

    memory = globals->memory;

    if ( ps_debug_glyph )
    {
      psh_glyph_done( ps_debug_glyph );
      FT_FREE( ps_debug_glyph );
    }

    if ( FT_NEW( glyph ) )
      return error;

    ps_debug_glyph = glyph;

#endif /* DEBUG_HINTER */

    error = psh_glyph_init( glyph, outline, ps_hints, globals );
    if ( error )
      goto Exit;

    /* try to optimize the y_scale so that the top of non-capital letters
     * is aligned on a pixel boundary whenever possible
     */
    {
      PSH_Dimension  dim_x = &glyph->globals->dimension[0];
      PSH_Dimension  dim_y = &glyph->globals->dimension[1];

      FT_Fixed x_scale = dim_x->scale_mult;
      FT_Fixed y_scale = dim_y->scale_mult;

      FT_Fixed scaled;
      FT_Fixed fitted;


      scaled = FT_MulFix( globals->blues.normal_top.zones->org_ref, y_scale );
      fitted = FT_PIX_ROUND( scaled );

      if ( fitted != 0 && scaled != fitted )
      {
        y_scale = FT_MulDiv( y_scale, fitted, scaled );

        if ( fitted < scaled )
          x_scale -= x_scale / 50;

        psh_globals_set_scale( glyph->globals, x_scale, y_scale, 0, 0 );
      }
    }

    glyph->do_horz_hints = 1;
    glyph->do_vert_hints = 1;

    glyph->do_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO ||
                                       hint_mode == FT_RENDER_MODE_LCD  );

    glyph->do_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO  ||
                                       hint_mode == FT_RENDER_MODE_LCD_V );

    glyph->do_stem_adjust   = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT );

    for ( dimension = 0; dimension < 2; dimension++ )
    {
      /* load outline coordinates into glyph */
      psh_glyph_load_points( glyph, dimension );

      /* compute local extrema */
      psh_glyph_compute_extrema( glyph );

      /* compute aligned stem/hints positions */
      psh_hint_table_align_hints( &glyph->hint_tables[dimension],
                                  glyph->globals,
                                  dimension,
                                  glyph );

      /* find strong points, align them, then interpolate others */
      psh_glyph_find_strong_points( glyph, dimension );
      if ( dimension == 1 )
        psh_glyph_find_blue_points( &globals->blues, glyph );
      psh_glyph_interpolate_strong_points( glyph, dimension );
      psh_glyph_interpolate_normal_points( glyph, dimension );
      psh_glyph_interpolate_other_points( glyph, dimension );

      /* save hinted coordinates back to outline */
      psh_glyph_save_points( glyph, dimension );
    }

  Exit:

#ifndef DEBUG_HINTER
    psh_glyph_done( glyph );
#endif

    return error;
  }


/* END */

⌨️ 快捷键说明

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