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

📄 ahhint.c

📁 qt-embedded-2.3.8.tar.gz源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************************************************//*                                                                         *//*  ahhint.c                                                               *//*                                                                         *//*    Glyph hinter (body).                                                 *//*                                                                         *//*  Copyright 2000 Catharon Productions Inc.                               *//*  Author: David Turner                                                   *//*                                                                         *//*  This file is part of the Catharon Typography Project and shall only    *//*  be used, modified, and distributed under the terms of the Catharon     *//*  Open Source License that should come with this file under the name     *//*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    *//*  this file you indicate that you have read the license and              *//*  understand and accept it fully.                                        *//*                                                                         *//*  Note that this license is compatible with the FreeType license.        *//*                                                                         *//***************************************************************************/#ifdef FT_FLAT_COMPILE#include "ahhint.h"#include "ahglyph.h"#include "ahangles.h"#else#include <autohint/ahhint.h>#include <autohint/ahglyph.h>#include <autohint/ahangles.h>#endif#include <freetype/ftoutln.h>#define FACE_GLOBALS( face )  ((AH_Face_Globals*)(face)->autohint.data)#define AH_USE_IUP  /*************************************************************************/  /*************************************************************************/  /****                                                                 ****/  /****   Hinting routines                                              ****/  /****                                                                 ****/  /*************************************************************************/  /*************************************************************************/  static int  disable_horz_edges = 0;  static int  disable_vert_edges = 0;  /* snap a given width in scaled coordinates to one of the */  /* current standard widths                                */  static  FT_Pos  ah_snap_width( FT_Pos*  widths,                         FT_Int   count,                         FT_Pos   width )  {    int     n;    FT_Pos  best      = 64 + 32 + 2;    FT_Pos  reference = width;    for ( n = 0; n < count; n++ )    {      FT_Pos  w;      FT_Pos  dist;      w = widths[n];      dist = width - w;      if ( dist < 0 )        dist = -dist;      if ( dist < best )      {        best      = dist;        reference = w;      }    }    if ( width >= reference )    {      width -= 0x21;      if ( width < reference )        width = reference;    }    else    {      width += 0x21;      if ( width > reference )        width = reference;    }    return width;  }  /* align one stem edge relative to the previous stem edge */  static  void  ah_align_linked_edge( AH_Hinter*  hinter,                              AH_Edge*    base_edge,                              AH_Edge*    stem_edge,                              int         vertical )  {    FT_Pos       dist    = stem_edge->opos - base_edge->opos;    AH_Globals*  globals = &hinter->globals->scaled;    FT_Pos       sign    = 1;    if ( dist < 0 )    {      dist = -dist;      sign = -1;    }    if ( vertical )    {      dist = ah_snap_width( globals->heights, globals->num_heights, dist );      /* in the case of vertical hinting, always round */      /* the stem heights to integer pixels            */      if ( dist >= 64 )        dist = ( dist + 16 ) & -64;      else        dist = 64;    }    else    {      dist = ah_snap_width( globals->widths,  globals->num_widths, dist );      if ( hinter->flags & ah_hinter_monochrome )      {        /* monochrome horizontal hinting: snap widths to integer pixels */        /* with a different threshold                                   */        if ( dist < 64 )          dist = 64;        else          dist = ( dist + 32 ) & -64;      }      else      {        /* for horizontal anti-aliased hinting, we adopt a more subtle */        /* approach: we strengthen small stems, round stems whose size */        /* is between 1 and 2 pixels to an integer, otherwise nothing  */        if ( dist < 48 )          dist = ( dist + 64 ) >> 1;        else if ( dist < 128 )          dist = ( dist + 42 ) & -64;      }    }    stem_edge->pos = base_edge->pos + sign * dist;  }  static  void  ah_align_serif_edge( AH_Hinter*  hinter,                             AH_Edge*    base,                             AH_Edge*    serif )  {    FT_Pos  dist;    FT_Pos  sign = 1;    UNUSED( hinter );    dist = serif->opos - base->opos;    if ( dist < 0 )    {      dist = -dist;      sign = -1;    }    /* do not strengthen serifs */    if ( base->flags & ah_edge_done )    {      if ( dist > 64 )        dist = ( dist + 16 ) & -64;      else if ( dist <= 32 )        dist = ( dist + 33 ) >> 1;    }    serif->pos = base->pos + sign * dist;  }  /*************************************************************************/  /*************************************************************************/  /*************************************************************************/  /****                                                                 ****/  /****       E D G E   H I N T I N G                                   ****/  /****                                                                 ****/  /*************************************************************************/  /*************************************************************************/  /*************************************************************************/  /* Another alternative edge hinting algorithm */  static  void  ah_hint_edges_3( AH_Hinter*  hinter )  {    AH_Edge*     edges;    AH_Edge*     edge_limit;    AH_Outline*  outline = hinter->glyph;    FT_Int       dimension;    edges      = outline->horz_edges;    edge_limit = edges + outline->num_hedges;    for ( dimension = 1; dimension >= 0; dimension-- )    {      AH_Edge*  edge;      AH_Edge*  before = 0;      AH_Edge*  after  = 0;      AH_Edge*  anchor = 0;      int       has_serifs = 0;      if ( disable_vert_edges && !dimension )        goto Next_Dimension;      if ( disable_horz_edges && dimension )        goto Next_Dimension;      /* we begin by aligning all stems relative to the blue zone */      /* if needed -- that's only for horizontal edges            */      if ( dimension )      {        for ( edge = edges; edge < edge_limit; edge++ )        {          FT_Pos*  blue;          AH_Edge  *edge1, *edge2;          if ( edge->flags & ah_edge_done )            continue;          blue  = edge->blue_edge;          edge1 = 0;          edge2 = edge->link;          if ( blue )          {            edge1 = edge;          }          else if (edge2 && edge2->blue_edge)          {            blue  = edge2->blue_edge;            edge1 = edge2;            edge2 = edge;          }          if ( !edge1 )            continue;          edge1->pos    = blue[0];          edge1->flags |= ah_edge_done;          if ( edge2 && !edge2->blue_edge )          {            ah_align_linked_edge( hinter, edge1, edge2, dimension );            edge2->flags |= ah_edge_done;          }          if ( !anchor )            anchor = edge;         }       }      /* now, we will align all stem edges, trying to maintain the */      /* relative order of stems in the glyph..                    */      before = 0;      after  = 0;      for ( edge = edges; edge < edge_limit; edge++ )      {        AH_Edge  *edge2;        if ( edge->flags & ah_edge_done )          continue;        /* skip all non-stem edges */        edge2 = edge->link;        if ( !edge2 )        {          has_serifs++;          continue;        }        /* now, align the stem */        /* this should not happen, but it's better to be safe.. */        if ( edge2->blue_edge || edge2 < edge )        {#if 0          printf( "strange blue alignement, edge %d to %d\n",                  edge - edges, edge2 - edges );#endif          ah_align_linked_edge( hinter, edge2, edge, dimension );          edge->flags |= ah_edge_done;          continue;        }        {          FT_Bool  min = 0;          FT_Pos   delta;          if ( !anchor )          {            edge->pos = ( edge->opos + 32 ) & -64;            anchor    = edge;          }          else            edge->pos = anchor->pos +                        ( ( edge->opos - anchor->opos + 32 ) & -64 );          edge->flags |= ah_edge_done;          if ( edge > edges && edge->pos < edge[-1].pos )          {            edge->pos = edge[-1].pos;            min       = 1;          }          ah_align_linked_edge( hinter, edge, edge2, dimension );          delta = 0;          if ( edge2 + 1 < edge_limit        &&               edge2[1].flags & ah_edge_done )            delta = edge2[1].pos - edge2->pos;          if ( delta < 0 )          {            edge2->pos += delta;            if ( !min )              edge->pos += delta;          }          edge2->flags |= ah_edge_done;        }      }      if ( !has_serifs )        goto Next_Dimension;      /* now, hint the remaining edges (serifs and single) in order */      /* to complete our processing                                 */      for ( edge = edges; edge < edge_limit; edge++ )      {        if ( edge->flags & ah_edge_done )          continue;        if ( edge->serif )        {          ah_align_serif_edge( hinter, edge->serif, edge );        }        else if ( !anchor )        {          edge->pos = ( edge->opos + 32 ) & -64;          anchor    = edge;        }        else          edge->pos = anchor->pos +                      ( ( edge->opos-anchor->opos + 32 ) & -64 );        edge->flags |= ah_edge_done;        if ( edge > edges && edge->pos < edge[-1].pos )          edge->pos = edge[-1].pos;        if ( edge + 1 < edge_limit        &&             edge[1].flags & ah_edge_done &&             edge->pos > edge[1].pos      )          edge->pos = edge[1].pos;      }    Next_Dimension:      edges      = outline->vert_edges;      edge_limit = edges + outline->num_vedges;    }  }  FT_LOCAL_DEF  void  ah_hinter_hint_edges( AH_Hinter*  hinter,                              int         no_horz_edges,                              int         no_vert_edges )  {    disable_horz_edges = no_horz_edges;    disable_vert_edges = no_vert_edges;    /* AH_Interpolate_Blue_Edges( hinter ); -- doesn't seem to help      */    /* reduce the problem of the disappearing eye in the `e' of Times... */    /* also, creates some artifacts near the blue zones?                 */    {      ah_hint_edges_3( hinter );#if 0      /* outline optimizer removed temporarily */      if ( hinter->flags & ah_hinter_optimize )      {        AH_Optimizer  opt;        if ( !AH_Optimizer_Init( &opt, hinter->glyph, hinter->memory ) )        {          AH_Optimizer_Compute( &opt );          AH_Optimizer_Done( &opt );        }      }#endif    }  }  /*************************************************************************/  /*************************************************************************/  /*************************************************************************/  /****                                                                 ****/  /****       P O I N T   H I N T I N G                                 ****/  /****                                                                 ****/  /*************************************************************************/  /*************************************************************************/  /*************************************************************************/  static  void  ah_hinter_align_edge_points( AH_Hinter*  hinter )  {    AH_Outline*  outline = hinter->glyph;    AH_Edge*     edges;    AH_Edge*     edge_limit;    FT_Int       dimension;    edges      = outline->horz_edges;    edge_limit = edges + outline->num_hedges;    for ( dimension = 1; dimension >= 0; dimension-- )    {      AH_Edge*   edge;      AH_Edge*   before;      AH_Edge*   after;      before = 0;      after  = 0;      edge = edges;      for ( ; edge < edge_limit; edge++ )      {        /* move the points of each segment     */        /* in each edge to the edge's position */        AH_Segment*  seg = edge->first;        do        {          AH_Point*  point = seg->first;          for (;;)          {            if ( dimension )            {              point->y      = edge->pos;              point->flags |= ah_flah_touch_y;            }            else            {              point->x      = edge->pos;              point->flags |= ah_flah_touch_x;            }

⌨️ 快捷键说明

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