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

📄 aflatin.c

📁 奇趣公司比较新的qt/emd版本
💻 C
📖 第 1 页 / 共 5 页
字号:
/***************************************************************************//*                                                                         *//*  aflatin.c                                                              *//*                                                                         *//*    Auto-fitter hinting routines for latin script (body).                *//*                                                                         *//*  Copyright 2003, 2004, 2005, 2006, 2007 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 "aflatin.h"#include "aferrors.h"#ifdef AF_USE_WARPER#include "afwarp.h"#endif  /*************************************************************************/  /*************************************************************************/  /*****                                                               *****/  /*****            L A T I N   G L O B A L   M E T R I C S            *****/  /*****                                                               *****/  /*************************************************************************/  /*************************************************************************/  FT_LOCAL_DEF( void )  af_latin_metrics_init_widths( AF_LatinMetrics  metrics,                                FT_Face          face,                                FT_ULong         charcode )  {    /* scan the array of segments in each direction */    AF_GlyphHintsRec  hints[1];    af_glyph_hints_init( hints, face->memory );    metrics->axis[AF_DIMENSION_HORZ].width_count = 0;    metrics->axis[AF_DIMENSION_VERT].width_count = 0;    {      FT_Error             error;      FT_UInt              glyph_index;      int                  dim;      AF_LatinMetricsRec   dummy[1];      AF_Scaler            scaler = &dummy->root.scaler;      glyph_index = FT_Get_Char_Index( face, charcode );      if ( glyph_index == 0 )        goto Exit;      error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );      if ( error || face->glyph->outline.n_points <= 0 )        goto Exit;      FT_ZERO( dummy );      dummy->units_per_em = metrics->units_per_em;      scaler->x_scale     = scaler->y_scale = 0x10000L;      scaler->x_delta     = scaler->y_delta = 0;      scaler->face        = face;      scaler->render_mode = FT_RENDER_MODE_NORMAL;      scaler->flags       = 0;      af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy );      error = af_glyph_hints_reload( hints, &face->glyph->outline );      if ( error )        goto Exit;      for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )      {        AF_LatinAxis  axis    = &metrics->axis[dim];        AF_AxisHints  axhints = &hints->axis[dim];        AF_Segment    seg, limit, link;        FT_UInt       num_widths = 0;        error = af_latin_hints_compute_segments( hints,                                                 (AF_Dimension)dim );        if ( error )          goto Exit;        af_latin_hints_link_segments( hints,                                      (AF_Dimension)dim );        seg   = axhints->segments;        limit = seg + axhints->num_segments;        for ( ; seg < limit; seg++ )        {          link = seg->link;          /* we only consider stem segments there! */          if ( link && link->link == seg && link > seg )          {            FT_Pos  dist;            dist = seg->pos - link->pos;            if ( dist < 0 )              dist = -dist;            if ( num_widths < AF_LATIN_MAX_WIDTHS )              axis->widths[ num_widths++ ].org = dist;          }        }        af_sort_widths( num_widths, axis->widths );        axis->width_count = num_widths;      }  Exit:      for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )      {        AF_LatinAxis  axis = &metrics->axis[dim];        FT_Pos        stdw;        stdw = ( axis->width_count > 0 )                 ? axis->widths[0].org                 : AF_LATIN_CONSTANT( metrics, 50 );        /* let's try 20% of the smallest width */        axis->edge_distance_threshold = stdw / 5;        axis->standard_width          = stdw;        axis->extra_light             = 0;      }    }    af_glyph_hints_done( hints );  }#define AF_LATIN_MAX_TEST_CHARACTERS  12  static const char* const  af_latin_blue_chars[AF_LATIN_MAX_BLUES] =  {    "THEZOCQS",    "HEZLOCUS",    "fijkdbh",    "xzroesc",    "xzroesc",    "pqgjy"  };  static void  af_latin_metrics_init_blues( AF_LatinMetrics  metrics,                               FT_Face          face )  {    FT_Pos        flats [AF_LATIN_MAX_TEST_CHARACTERS];    FT_Pos        rounds[AF_LATIN_MAX_TEST_CHARACTERS];    FT_Int        num_flats;    FT_Int        num_rounds;    FT_Int        bb;    AF_LatinBlue  blue;    FT_Error      error;    AF_LatinAxis  axis  = &metrics->axis[AF_DIMENSION_VERT];    FT_GlyphSlot  glyph = face->glyph;    /* we compute the blues simply by loading each character from the    */    /* 'af_latin_blue_chars[blues]' string, then compute its top-most or */    /* bottom-most points (depending on `AF_IS_TOP_BLUE')                */    AF_LOG(( "blue zones computation\n" ));    AF_LOG(( "------------------------------------------------\n" ));    for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )    {      const char*  p     = af_latin_blue_chars[bb];      const char*  limit = p + AF_LATIN_MAX_TEST_CHARACTERS;      FT_Pos*      blue_ref;      FT_Pos*      blue_shoot;      AF_LOG(( "blue %3d: ", bb ));      num_flats  = 0;      num_rounds = 0;      for ( ; p < limit && *p; p++ )      {        FT_UInt     glyph_index;        FT_Int      best_point, best_y, best_first, best_last;        FT_Vector*  points;        FT_Bool     round;        AF_LOG(( "'%c'", *p ));        /* load the character in the face -- skip unknown or empty ones */        glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );        if ( glyph_index == 0 )          continue;        error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );        if ( error || glyph->outline.n_points <= 0 )          continue;        /* now compute min or max point indices and coordinates */        points      = glyph->outline.points;        best_point  = -1;        best_y      = 0;  /* make compiler happy */        best_first  = 0;  /* ditto */        best_last   = 0;  /* ditto */        {          FT_Int  nn;          FT_Int  first = 0;          FT_Int  last  = -1;          for ( nn = 0; nn < glyph->outline.n_contours; first = last+1, nn++ )          {            FT_Int  old_best_point = best_point;            FT_Int  pp;            last = glyph->outline.contours[nn];            /* Avoid single-point contours since they are never rasterized. */            /* In some fonts, they correspond to mark attachment points     */            /* which are way outside of the glyph's real outline.           */            if ( last <= first )                continue;            if ( AF_LATIN_IS_TOP_BLUE( bb ) )            {              for ( pp = first; pp <= last; pp++ )                if ( best_point < 0 || points[pp].y > best_y )                {                  best_point = pp;                  best_y     = points[pp].y;                }            }            else            {              for ( pp = first; pp <= last; pp++ )                if ( best_point < 0 || points[pp].y < best_y )                {                  best_point = pp;                  best_y     = points[pp].y;                }            }            if ( best_point != old_best_point )            {              best_first = first;              best_last  = last;            }          }          AF_LOG(( "%5d", best_y ));        }        /* now check whether the point belongs to a straight or round   */        /* segment; we first need to find in which contour the extremum */        /* lies, then inspect its previous and next points              */        {          FT_Int  prev, next;          FT_Pos  dist;          /* now look for the previous and next points that are not on the */          /* same Y coordinate.  Threshold the `closeness'...              */          prev = best_point;          next = prev;          do          {            if ( prev > best_first )              prev--;            else              prev = best_last;            dist = points[prev].y - best_y;            if ( dist < -5 || dist > 5 )              break;          } while ( prev != best_point );          do          {            if ( next < best_last )              next++;            else              next = best_first;            dist = points[next].y - best_y;            if ( dist < -5 || dist > 5 )              break;          } while ( next != best_point );          /* now, set the `round' flag depending on the segment's kind */          round = FT_BOOL(            FT_CURVE_TAG( glyph->outline.tags[prev] ) != FT_CURVE_TAG_ON ||            FT_CURVE_TAG( glyph->outline.tags[next] ) != FT_CURVE_TAG_ON );          AF_LOG(( "%c ", round ? 'r' : 'f' ));        }        if ( round )          rounds[num_rounds++] = best_y;        else          flats[num_flats++]   = best_y;      }      AF_LOG(( "\n" ));      if ( num_flats == 0 && num_rounds == 0 )      {        /*         *  we couldn't find a single glyph to compute this blue zone,         *  we will simply ignore it then         */        AF_LOG(( "empty!\n" ));        continue;      }      /* we have computed the contents of the `rounds' and `flats' tables, */      /* now determine the reference and overshoot position of the blue -- */      /* we simply take the median value after a simple sort               */      af_sort_pos( num_rounds, rounds );      af_sort_pos( num_flats,  flats );      blue       = & axis->blues[axis->blue_count];      blue_ref   = & blue->ref.org;      blue_shoot = & blue->shoot.org;      axis->blue_count++;      if ( num_flats == 0 )      {        *blue_ref   =        *blue_shoot = rounds[num_rounds / 2];      }      else if ( num_rounds == 0 )      {        *blue_ref   =        *blue_shoot = flats[num_flats / 2];      }      else      {        *blue_ref   = flats[num_flats / 2];        *blue_shoot = rounds[num_rounds / 2];      }      /* there are sometimes problems: if the overshoot position of top     */      /* zones is under its reference position, or the opposite for bottom  */      /* zones.  We must thus check everything there and correct the errors */      if ( *blue_shoot != *blue_ref )      {        FT_Pos   ref      = *blue_ref;        FT_Pos   shoot    = *blue_shoot;        FT_Bool  over_ref = FT_BOOL( shoot > ref );        if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref )          *blue_shoot = *blue_ref = ( shoot + ref ) / 2;      }      blue->flags = 0;      if ( AF_LATIN_IS_TOP_BLUE( bb ) )        blue->flags |= AF_LATIN_BLUE_TOP;      /*       * The following flags is used later to adjust the y and x scales       * in order to optimize the pixel grid alignment of the top of small       * letters.       */      if ( bb == AF_LATIN_BLUE_SMALL_TOP )        blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;      AF_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));    }    return;  }  FT_LOCAL_DEF( FT_Error )  af_latin_metrics_init( AF_LatinMetrics  metrics,                         FT_Face          face )  {    FT_Error    error = AF_Err_Ok;    FT_CharMap  oldmap = face->charmap;    FT_UInt     ee;    static const FT_Encoding  latin_encodings[] =    {      FT_ENCODING_UNICODE,      FT_ENCODING_APPLE_ROMAN,      FT_ENCODING_ADOBE_STANDARD,      FT_ENCODING_ADOBE_LATIN_1,      FT_ENCODING_NONE  /* end of list */    };    metrics->units_per_em = face->units_per_EM;    /* do we have a latin charmap in there? */    for ( ee = 0; latin_encodings[ee] != FT_ENCODING_NONE; ee++ )    {      error = FT_Select_Charmap( face, latin_encodings[ee] );      if ( !error )        break;    }    if ( !error )    {      /* For now, compute the standard width and height from the `o'. */      af_latin_metrics_init_widths( metrics, face, 'o' );      af_latin_metrics_init_blues( metrics, face );    }    FT_Set_Charmap( face, oldmap );    return AF_Err_Ok;  }  static void  af_latin_metrics_scale_dim( AF_LatinMetrics  metrics,                              AF_Scaler        scaler,                              AF_Dimension     dim )  {    FT_Fixed      scale;    FT_Pos        delta;    AF_LatinAxis  axis;    FT_UInt       nn;    if ( dim == AF_DIMENSION_HORZ )

⌨️ 快捷键说明

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