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

📄 aflatin.c

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/***************************************************************************//*                                                                         *//*  aflatin.c                                                              *//*                                                                         *//*    Auto-fitter hinting routines for latin script (body).                *//*                                                                         *//*  Copyright 2003, 2004, 2005 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"  /*************************************************************************/  /*************************************************************************/  /*****                                                               *****/  /*****            L A T I N   G L O B A L   M E T R I C S            *****/  /*****                                                               *****/  /*************************************************************************/  /*************************************************************************/  static void  af_latin_metrics_init_widths( AF_LatinMetrics  metrics,                                FT_Face          face )  {    /* 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;    /* For now, compute the standard width and height from the `o'. */    {      FT_Error             error;      FT_UInt              glyph_index;      int                  dim;      AF_ScriptMetricsRec  dummy[1];      AF_Scaler            scaler = &dummy->scaler;      glyph_index = FT_Get_Char_Index( face, 'o' );      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 );      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, 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;        FT_Pos        edge_distance_threshold = 32000;        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;        /* we will now try to find the smallest width */        if ( num_widths > 0 && axis->widths[0].org < edge_distance_threshold )          edge_distance_threshold = axis->widths[0].org;        /* Now, compute the edge distance threshold as a fraction of the */        /* smallest width in the font.  Set it in `hinter->glyph' too!   */        if ( edge_distance_threshold == 32000 )          edge_distance_threshold = 50;        /* let's try 20% */        axis->edge_distance_threshold = edge_distance_threshold / 5;      }    }  Exit:    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_Vector*  extremum;        FT_Vector*  points;        FT_Vector*  point_limit;        FT_Vector*  point;        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;        point_limit = points + glyph->outline.n_points;        point       = points;        extremum    = point;        point++;        if ( AF_LATIN_IS_TOP_BLUE( bb ) )        {          for ( ; point < point_limit; point++ )            if ( point->y > extremum->y )              extremum = point;        }        else        {          for ( ; point < point_limit; point++ )            if ( point->y < extremum->y )              extremum = point;        }        AF_LOG(( "%5d", (int)extremum->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 see its previous and next points                  */        {          FT_Int  idx = (FT_Int)( extremum - points );          FT_Int  n;          FT_Int  first, last, prev, next, end;          FT_Pos  dist;          last  = -1;          first = 0;          for ( n = 0; n < glyph->outline.n_contours; n++ )          {            end = glyph->outline.contours[n];            if ( end >= idx )            {              last = end;              break;            }            first = end + 1;          }          /* XXX: should never happen! */          if ( last < 0 )            continue;          /* now look for the previous and next points that are not on the */          /* same Y coordinate.  Threshold the `closeness'...              */          prev = idx;          next = prev;          do          {            if ( prev > first )              prev--;            else              prev = last;            dist = points[prev].y - extremum->y;            if ( dist < -5 || dist > 5 )              break;          } while ( prev != idx );          do          {            if ( next < last )              next++;            else              next = first;            dist = points[next].y - extremum->y;            if ( dist < -5 || dist > 5 )              break;          } while ( next != idx );          /* 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++] = extremum->y;        else          flats[num_flats++] = extremum->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 )    {      af_latin_metrics_init_widths( metrics, face );      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 )    {      scale = scaler->x_scale;      delta = scaler->x_delta;    }    else    {      scale = scaler->y_scale;      delta = scaler->y_delta;    }    axis = &metrics->axis[dim];    if ( axis->org_scale == scale && axis->org_delta == delta )      return;    axis->org_scale = scale;    axis->org_delta = delta;    /*     * correct X and Y scale to optimize the alignment of the top of small     * letters to the pixel grid     */    {      AF_LatinAxis  Axis = &metrics->axis[AF_DIMENSION_VERT];      AF_LatinBlue  blue = NULL;      for ( nn = 0; nn < Axis->blue_count; nn++ )      {        if ( Axis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT )        {          blue = &Axis->blues[nn];          break;        }      }      if ( blue )      {        FT_Pos  scaled = FT_MulFix( blue->shoot.org, scaler->y_scale );        FT_Pos  fitted = FT_PIX_ROUND( scaled );        if ( scaled != fitted )        {          if ( dim == AF_DIMENSION_HORZ )          {            if ( fitted < scaled )              scale -= scale/50;  /* x_scale = x_scale*0.98 */          }          else          {            scale = FT_MulDiv( scale, fitted, scaled );          }        }      }    }    axis->scale = scale;    axis->delta = delta;    if ( dim == AF_DIMENSION_HORZ )    {      metrics->root.scaler.x_scale = scale;      metrics->root.scaler.x_delta = delta;    }    else    {      metrics->root.scaler.y_scale = scale;

⌨️ 快捷键说明

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