freetype中FT_Set_Transform()和FT_Load_Char()分析(待续)

来源:互联网 发布:设计本软件下载 编辑:程序博客网 时间:2024/06/06 22:55

在程序中:  

………………

pen.x = 0 * 64;  

   pen.y = ( target_height - 70 ) * 64; 

 FT_Set_Transform( face, 0, &pen );  

error = FT_Load_Char( face, text[n], FT_LOAD_RENDER );  (渲染的位图会根据pen,设置好face->glyph->bitmap_left和tbitmap_top)

………………

先设置了pen的x和y值,然后执行FT_Set_Transform()。我们进入FT_Set_Transform()分析。

1( void )2  FT_Set_Transform( FT_Face     face,3                    FT_Matrix*  matrix,4                    FT_Vector*  delta )5  {6    FT_Face_Internal  internal;789    if ( !face )10      return;1112    internal = face->internal;1314    internal->transform_flags = 0;1516    if ( !matrix )17    {18      internal->transform_matrix.xx = 0x10000L;19      internal->transform_matrix.xy = 0;20      internal->transform_matrix.yx = 0;21      internal->transform_matrix.yy = 0x10000L;22      matrix = &internal->transform_matrix;23    }24    else25      internal->transform_matrix = *matrix;2627    /* set transform_flags bit flag 0 if `matrix' isn't the identity */28    if ( ( matrix->xy | matrix->yx ) ||29         matrix->xx != 0x10000L      ||30         matrix->yy != 0x10000L      )31      internal->transform_flags |= 1;3233    if ( !delta )34    {35      internal->transform_delta.x = 0;36      internal->transform_delta.y = 0;37      delta = &internal->transform_delta;38    }39    else40      internal->transform_delta = *delta;4142    /* set transform_flags bit flag 1 if `delta' isn't the null vector */43    if ( delta->x | delta->y )44      internal->transform_flags |= 2;45  }
第9行判断是否有face,如果不存在则出错。
第16行判断是否有matrix(矩阵变换),不存在时按默认设置。

第33行当传入delta时按照它设置face->internal->transform_delta。

继续分析程序中的FT_Load_Char:

1( FT_Error )2  FT_Load_Char( FT_Face   face,3                FT_ULong  char_code,4                FT_Int32  load_flags )5  {6    FT_UInt  glyph_index;789    if ( !face )10      return FT_Err_Invalid_Face_Handle;1112    glyph_index = (FT_UInt)char_code;13    if ( face->charmap )14      glyph_index = FT_Get_Char_Index( face, char_code );1516    return FT_Load_Glyph( face, glyph_index, load_flags );17  }

当存在face时,调用了FT_Load_Glyph来加载位图。我们进入FT_Load_Glyph中:

1  FT_EXPORT_DEF( FT_Error )2  FT_Load_Glyph( FT_Face   face,3                 FT_UInt   glyph_index,4                 FT_Int32  load_flags )5  {6    FT_Error      error;7    FT_Driver     driver;8    FT_GlyphSlot  slot;9    FT_Library    library;10    FT_Bool       autohint = FALSE;11    FT_Module     hinter;12    TT_Face       ttface = (TT_Face)face;131415    if ( !face || !face->size || !face->glyph )16      return FT_Err_Invalid_Face_Handle;1718    /* The validity test for `glyph_index' is performed by the */19    /* font drivers.                                           */2021    slot = face->glyph;22    ft_glyphslot_clear( slot );2324    driver  = face->driver;25    library = driver->root.library;26    hinter  = library->auto_hinter;2728    /* resolve load flags dependencies */2930    if ( load_flags & FT_LOAD_NO_RECURSE )31      load_flags |= FT_LOAD_NO_SCALE         |32                    FT_LOAD_IGNORE_TRANSFORM;3334    if ( load_flags & FT_LOAD_NO_SCALE )35    {36      load_flags |= FT_LOAD_NO_HINTING |37                    FT_LOAD_NO_BITMAP;3839      load_flags &= ~FT_LOAD_RENDER;40    }4142    /*43     * Determine whether we need to auto-hint or not.44     * The general rules are:45     *46     * - Do only auto-hinting if we have a hinter module, a scalable font47     *   format dealing with outlines, and no transforms except simple48     *   slants and/or rotations by integer multiples of 90 degrees.49     *50     * - Then, auto-hint if FT_LOAD_FORCE_AUTOHINT is set or if we don't51     *   have a native font hinter.52     *53     * - Otherwise, auto-hint for LIGHT hinting mode or if there isn't54     *   any hinting bytecode in the TrueType/OpenType font.55     *56     * - Exception: The font is `tricky' and requires the native hinter to57     *   load properly.58     */5960    if ( hinter                                           &&61         !( load_flags & FT_LOAD_NO_HINTING )             &&62         !( load_flags & FT_LOAD_NO_AUTOHINT )            &&63         FT_DRIVER_IS_SCALABLE( driver )                  &&64         FT_DRIVER_USES_OUTLINES( driver )                &&65         !FT_IS_TRICKY( face )                            &&66         ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM )    ||           ( face->internal->transform_matrix.yx == 0 &&             face->internal->transform_matrix.xx != 0 ) ||           ( face->internal->transform_matrix.xx == 0 &&             face->internal->transform_matrix.yx != 0 ) ) )    {      if ( ( load_flags & FT_LOAD_FORCE_AUTOHINT ) ||           !FT_DRIVER_HAS_HINTER( driver )         )        autohint = TRUE;      else      {        FT_Render_Mode  mode = FT_LOAD_TARGET_MODE( load_flags );        /* the check for `num_locations' assures that we actually    */        /* test for instructions in a TTF and not in a CFF-based OTF */        if ( mode == FT_RENDER_MODE_LIGHT                       ||             face->internal->ignore_unpatented_hinter           ||             ( FT_IS_SFNT( face )                             &&               ttface->num_locations                          &&               ttface->max_profile.maxSizeOfInstructions == 0 ) )          autohint = TRUE;      }    }    if ( autohint )    {      FT_AutoHinter_Service  hinting;      /* try to load embedded bitmaps first if available            */      /*                                                            */      /* XXX: This is really a temporary hack that should disappear */      /*      promptly with FreeType 2.1!                           */      /*                                                            */      if ( FT_HAS_FIXED_SIZES( face )             &&          ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )      {        error = driver->clazz->load_glyph( slot, face->size,                                           glyph_index,                                           load_flags | FT_LOAD_SBITS_ONLY );        if ( !error && slot->format == FT_GLYPH_FORMAT_BITMAP )          goto Load_Ok;      }      {        FT_Face_Internal  internal        = face->internal;        FT_Int            transform_flags = internal->transform_flags;        /* since the auto-hinter calls FT_Load_Glyph by itself, */        /* make sure that glyphs aren't transformed             */        internal->transform_flags = 0;        /* load auto-hinted outline */        hinting = (FT_AutoHinter_Service)hinter->clazz->module_interface;        error   = hinting->load_glyph( (FT_AutoHinter)hinter,                                       slot, face->size,                                       glyph_index, load_flags );        internal->transform_flags = transform_flags;      }    }    else    {      error = driver->clazz->load_glyph( slot,                                         face->size,                                         glyph_index,                                         load_flags );      if ( error )        goto Exit;      if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )      {        /* check that the loaded outline is correct */        error = FT_Outline_Check( &slot->outline );        if ( error )          goto Exit;#ifdef GRID_FIT_METRICS        if ( !( load_flags & FT_LOAD_NO_HINTING ) )          ft_glyphslot_grid_fit_metrics( slot,              FT_BOOL( load_flags & FT_LOAD_VERTICAL_LAYOUT ) );#endif      }    }  Load_Ok:    /* compute the advance */    if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )    {      slot->advance.x = 0;      slot->advance.y = slot->metrics.vertAdvance;    }    else    {      slot->advance.x = slot->metrics.horiAdvance;      slot->advance.y = 0;    }    /* compute the linear advance in 16.16 pixels */    if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 &&         ( FT_IS_SCALABLE( face ) )                  )    {      FT_Size_Metrics*  metrics = &face->size->metrics;      /* it's tricky! */      slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance,                                           metrics->x_scale, 64 );      slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance,                                           metrics->y_scale, 64 );    }    if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 )    {      FT_Face_Internal  internal = face->internal;      /* now, transform the glyph image if needed */      if ( internal->transform_flags )      {        /* get renderer */        FT_Renderer  renderer = ft_lookup_glyph_renderer( slot );        if ( renderer )          error = renderer->clazz->transform_glyph(                                     renderer, slot,                                     &internal->transform_matrix,                                     &internal->transform_delta );        else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )        {          /* apply `standard' transformation if no renderer is available */          if ( internal->transform_flags & 1 )            FT_Outline_Transform( &slot->outline,                                  &internal->transform_matrix );          if ( internal->transform_flags & 2 )            FT_Outline_Translate( &slot->outline,                                  internal->transform_delta.x,                                  internal->transform_delta.y );        }        /* transform advance */        FT_Vector_Transform( &slot->advance, &internal->transform_matrix );      }    }    FT_TRACE5(( "  x advance: %d\n" , slot->advance.x ));    FT_TRACE5(( "  y advance: %d\n" , slot->advance.y ));    FT_TRACE5(( "  linear x advance: %d\n" , slot->linearHoriAdvance ));    FT_TRACE5(( "  linear y advance: %d\n" , slot->linearVertAdvance ));    /* do we need to render the image now? */    if ( !error                                    &&         slot->format != FT_GLYPH_FORMAT_BITMAP    &&         slot->format != FT_GLYPH_FORMAT_COMPOSITE &&         load_flags & FT_LOAD_RENDER )    {      FT_Render_Mode  mode = FT_LOAD_TARGET_MODE( load_flags );      if ( mode == FT_RENDER_MODE_NORMAL      &&           (load_flags & FT_LOAD_MONOCHROME ) )        mode = FT_RENDER_MODE_MONO;      error = FT_Render_Glyph( slot, mode );    }  Exit:    return error;  }




0 0