(root)/
freetype-2.13.2/
src/
base/
ftadvanc.c
       1  /****************************************************************************
       2   *
       3   * ftadvanc.c
       4   *
       5   *   Quick computation of advance widths (body).
       6   *
       7   * Copyright (C) 2008-2023 by
       8   * David Turner, Robert Wilhelm, and Werner Lemberg.
       9   *
      10   * This file is part of the FreeType project, and may only be used,
      11   * modified, and distributed under the terms of the FreeType project
      12   * license, LICENSE.TXT.  By continuing to use, modify, or distribute
      13   * this file you indicate that you have read the license and
      14   * understand and accept it fully.
      15   *
      16   */
      17  
      18  
      19  #include <freetype/internal/ftdebug.h>
      20  
      21  #include <freetype/ftadvanc.h>
      22  #include <freetype/internal/ftobjs.h>
      23  
      24  
      25    static FT_Error
      26    ft_face_scale_advances_( FT_Face    face,
      27                             FT_Fixed*  advances,
      28                             FT_UInt    count,
      29                             FT_Int32   flags )
      30    {
      31      FT_Fixed  scale;
      32      FT_UInt   nn;
      33  
      34  
      35      if ( flags & FT_LOAD_NO_SCALE )
      36        return FT_Err_Ok;
      37  
      38      if ( !face->size )
      39        return FT_THROW( Invalid_Size_Handle );
      40  
      41      if ( flags & FT_LOAD_VERTICAL_LAYOUT )
      42        scale = face->size->metrics.y_scale;
      43      else
      44        scale = face->size->metrics.x_scale;
      45  
      46      /* this must be the same scaling as to get linear{Hori,Vert}Advance */
      47      /* (see `FT_Load_Glyph' implementation in src/base/ftobjs.c)        */
      48  
      49      for ( nn = 0; nn < count; nn++ )
      50        advances[nn] = FT_MulDiv( advances[nn], scale, 64 );
      51  
      52      return FT_Err_Ok;
      53    }
      54  
      55  
      56     /* at the moment, we can perform fast advance retrieval only in */
      57     /* the following cases:                                         */
      58     /*                                                              */
      59     /*  - unscaled load                                             */
      60     /*  - unhinted load                                             */
      61     /*  - light-hinted load                                         */
      62     /*  - if a variations font, it must have an `HVAR' or `VVAR'    */
      63     /*    table (thus the old MM or GX fonts don't qualify; this    */
      64     /*    gets checked by the driver-specific functions)            */
      65  
      66  #define LOAD_ADVANCE_FAST_CHECK( face, flags )                      \
      67            ( flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING )    || \
      68              FT_LOAD_TARGET_MODE( flags ) == FT_RENDER_MODE_LIGHT )
      69  
      70  
      71    /* documentation is in ftadvanc.h */
      72  
      73    FT_EXPORT_DEF( FT_Error )
      74    FT_Get_Advance( FT_Face    face,
      75                    FT_UInt    gindex,
      76                    FT_Int32   flags,
      77                    FT_Fixed  *padvance )
      78    {
      79      FT_Face_GetAdvancesFunc  func;
      80  
      81  
      82      if ( !face )
      83        return FT_THROW( Invalid_Face_Handle );
      84  
      85      if ( !padvance )
      86        return FT_THROW( Invalid_Argument );
      87  
      88      if ( gindex >= (FT_UInt)face->num_glyphs )
      89        return FT_THROW( Invalid_Glyph_Index );
      90  
      91      func = face->driver->clazz->get_advances;
      92      if ( func && LOAD_ADVANCE_FAST_CHECK( face, flags ) )
      93      {
      94        FT_Error  error;
      95  
      96  
      97        error = func( face, gindex, 1, flags, padvance );
      98        if ( !error )
      99          return ft_face_scale_advances_( face, padvance, 1, flags );
     100  
     101        if ( FT_ERR_NEQ( error, Unimplemented_Feature ) )
     102          return error;
     103      }
     104  
     105      return FT_Get_Advances( face, gindex, 1, flags, padvance );
     106    }
     107  
     108  
     109    /* documentation is in ftadvanc.h */
     110  
     111    FT_EXPORT_DEF( FT_Error )
     112    FT_Get_Advances( FT_Face    face,
     113                     FT_UInt    start,
     114                     FT_UInt    count,
     115                     FT_Int32   flags,
     116                     FT_Fixed  *padvances )
     117    {
     118      FT_Error  error = FT_Err_Ok;
     119  
     120      FT_Face_GetAdvancesFunc  func;
     121  
     122      FT_UInt  num, end, nn;
     123      FT_Int   factor;
     124  
     125  
     126      if ( !face )
     127        return FT_THROW( Invalid_Face_Handle );
     128  
     129      if ( !padvances )
     130        return FT_THROW( Invalid_Argument );
     131  
     132      num = (FT_UInt)face->num_glyphs;
     133      end = start + count;
     134      if ( start >= num || end < start || end > num )
     135        return FT_THROW( Invalid_Glyph_Index );
     136  
     137      if ( count == 0 )
     138        return FT_Err_Ok;
     139  
     140      func = face->driver->clazz->get_advances;
     141      if ( func && LOAD_ADVANCE_FAST_CHECK( face, flags ) )
     142      {
     143        error = func( face, start, count, flags, padvances );
     144        if ( !error )
     145          return ft_face_scale_advances_( face, padvances, count, flags );
     146  
     147        if ( FT_ERR_NEQ( error, Unimplemented_Feature ) )
     148          return error;
     149      }
     150  
     151      error = FT_Err_Ok;
     152  
     153      if ( flags & FT_ADVANCE_FLAG_FAST_ONLY )
     154        return FT_THROW( Unimplemented_Feature );
     155  
     156      flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
     157      factor = ( flags & FT_LOAD_NO_SCALE ) ? 1 : 1024;
     158      for ( nn = 0; nn < count; nn++ )
     159      {
     160        error = FT_Load_Glyph( face, start + nn, flags );
     161        if ( error )
     162          break;
     163  
     164        /* scale from 26.6 to 16.16, unless NO_SCALE was requested */
     165        padvances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
     166                        ? face->glyph->advance.y * factor
     167                        : face->glyph->advance.x * factor;
     168      }
     169  
     170      return error;
     171    }
     172  
     173  
     174  /* END */