ft2_font.cpp
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:8k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * ft2_font.cpp
  3.  *****************************************************************************
  4.  * Copyright (C) 2003 VideoLAN
  5.  * $Id: ft2_font.cpp 7327 2004-04-12 14:25:15Z asmax $
  6.  *
  7.  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
  8.  *          Olivier Teuli鑢e <ipkiss@via.ecp.fr>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24. #include "ft2_font.hpp"
  25. #include "ft2_bitmap.hpp"
  26. #include "../utils/ustring.hpp"
  27. FT2Font::FT2Font( intf_thread_t *pIntf, const string &rName, int size ):
  28.     GenericFont( pIntf ), m_name( rName ), m_buffer( NULL ), m_size( size ),
  29.     m_lib( NULL ), m_face( NULL ), m_dotGlyph( NULL )
  30. {
  31. }
  32. FT2Font::~FT2Font()
  33. {
  34.     if( m_dotGlyph )
  35.     {
  36.         FT_Done_Glyph( m_dotGlyph );
  37.     }
  38.     if( m_face )
  39.     {
  40.         FT_Done_Face( m_face );
  41.     }
  42.     if( m_lib )
  43.     {
  44.         FT_Done_FreeType( m_lib );
  45.     }
  46.     if( m_buffer )
  47.     {
  48.         free( m_buffer );
  49.     }
  50. }
  51. bool FT2Font::init()
  52. {
  53.     int err;
  54.     // Initalise libfreetype
  55.     if( FT_Init_FreeType( &m_lib ) )
  56.     {
  57.         msg_Err( getIntf(), "Failed to initalize libfreetype" );
  58.         return false;
  59.     }
  60.     // Open the font
  61.     FILE *file = fopen( m_name.c_str(), "rb" );
  62.     if( file )
  63.     {
  64.         msg_Dbg( getIntf(), "Loading font %s", m_name.c_str() );
  65.     }
  66.     else
  67.     {
  68.         msg_Dbg( getIntf(), "Unable to open the font %s", m_name.c_str() );
  69.         return false;
  70.     }
  71.     // Get the file size
  72.     fseek( file, 0, SEEK_END );
  73.     int size = ftell( file );
  74.     rewind( file );
  75.     // Allocate the buffer
  76.     m_buffer = malloc( size );
  77.     if( !m_buffer )
  78.     {
  79.         msg_Err( getIntf(), "Not enough memory for the font %s",
  80.                  m_name.c_str() );
  81.         return false;
  82.     }
  83.     // Read the font data
  84.     fread( m_buffer, size, 1, file );
  85.     fclose( file );
  86.     // Load the font from the buffer
  87.     err = FT_New_Memory_Face( m_lib, (const FT_Byte*)m_buffer, size, 0,
  88.                               &m_face );
  89.     if ( err == FT_Err_Unknown_File_Format )
  90.     {
  91.         msg_Err( getIntf(), "Unsupported font format (%s)", m_name.c_str() );
  92.         return false;
  93.     }
  94.     else if ( err )
  95.     {
  96.         msg_Err( getIntf(), "Error opening font (%s)", m_name.c_str() );
  97.         return false;
  98.     }
  99.     // Select the charset
  100.     if( FT_Select_Charmap( m_face, ft_encoding_unicode ) )
  101.     {
  102.         msg_Err( getIntf(), "Font has no UNICODE table (%s)", m_name.c_str() );
  103.         return false;
  104.     }
  105.     // Set the pixel size
  106.     if( FT_Set_Pixel_Sizes( m_face, 0, m_size ) )
  107.     {
  108.         msg_Warn( getIntf(), "Cannot set a pixel size of %d (%s)", m_size,
  109.                   m_name.c_str() );
  110.     }
  111.     // Get the font metrucs
  112.     m_height = m_face->size->metrics.height >> 6;
  113.     m_ascender = m_face->size->metrics.ascender >> 6;
  114.     m_descender = m_face->size->metrics.descender >> 6;
  115.     // Render the '.' symbol and compute its size
  116.     m_dotIndex = FT_Get_Char_Index( m_face, '.' );
  117.     FT_Load_Glyph( m_face, m_dotIndex, FT_LOAD_DEFAULT );
  118.     FT_Get_Glyph( m_face->glyph, &m_dotGlyph );
  119.     FT_BBox dotSize;
  120.     FT_Glyph_Get_CBox( m_dotGlyph, ft_glyph_bbox_pixels, &dotSize );
  121.     m_dotWidth = dotSize.xMax - dotSize.xMin;
  122.     m_dotAdvance = m_face->glyph->advance.x >> 6;
  123.     FT_Glyph_To_Bitmap( &m_dotGlyph, ft_render_mode_normal, NULL, 1 );
  124.     return true;
  125. }
  126. GenericBitmap *FT2Font::drawString( const UString &rString, uint32_t color,
  127.                                     int maxWidth ) const
  128. {
  129.     int err;
  130.     uint32_t code;
  131.     int n;
  132.     int penX = 0;
  133.     int width1 = 0, width2 = 0;
  134.     int yMin = 0, yMax = 0;
  135.     uint32_t *pString = (uint32_t*)rString.u_str();
  136.     // Check if freetype has been initialized
  137.     if( !m_face )
  138.     {
  139.         return NULL;
  140.     }
  141.     // Get the length of the string
  142.     int len = rString.length();
  143.     // Array of glyph bitmaps and position
  144.     FT_Glyph *glyphs = new FT_Glyph[len];
  145.     int *pos = new int[len];
  146.     // Does the font support kerning ?
  147.     FT_Bool useKerning = FT_HAS_KERNING( m_face );
  148.     int previous = 0;
  149.     // Index of the last glyph when the text is truncated with trailing ...
  150.     int maxIndex = 0;
  151.     // Position of the first trailing dot
  152.     int firstDotX = 0;
  153.     // First, render all the glyphs
  154.     for( n = 0; n < len; n++ )
  155.     {
  156.         code = *(pString++);
  157.         // Load the glyph
  158.         int glyphIndex = FT_Get_Char_Index( m_face, code );
  159.         err = FT_Load_Glyph( m_face, glyphIndex, FT_LOAD_DEFAULT );
  160.         err = FT_Get_Glyph( m_face->glyph, &glyphs[n] );
  161.         // Retrieve kerning distance and move pen position
  162.         if( useKerning && previous && glyphIndex )
  163.         {
  164.             FT_Vector delta;
  165.             FT_Get_Kerning( m_face, previous, glyphIndex,
  166.                             ft_kerning_default, &delta );
  167.             penX += delta.x >> 6;
  168.         }
  169.         // Get the glyph size
  170.         FT_BBox glyphSize;
  171.         FT_Glyph_Get_CBox( glyphs[n], ft_glyph_bbox_pixels, &glyphSize );
  172.         // Render the glyph
  173.         err = FT_Glyph_To_Bitmap( &glyphs[n], ft_render_mode_normal, NULL, 1 );
  174.         pos[n] = penX;
  175.         width1 = penX + glyphSize.xMax - glyphSize.xMin;
  176.         yMin = __MIN( yMin, glyphSize.yMin );
  177.         yMax = __MAX( yMax, glyphSize.yMax );
  178.         // Next position
  179.         penX += m_face->glyph->advance.x >> 6;
  180.         // Save glyph index
  181.         previous = glyphIndex;
  182.         if( maxWidth != -1 )
  183.         {
  184.             // Check if the truncated text with the '...' fit in the maxWidth
  185.             int curX = penX;
  186.             if( useKerning )
  187.             {
  188.                 FT_Vector delta;
  189.                 FT_Get_Kerning( m_face, glyphIndex, m_dotIndex,
  190.                                 ft_kerning_default, &delta );
  191.                 curX += delta.x >> 6;
  192.             }
  193.             if( curX + 2 * m_dotAdvance + m_dotWidth < maxWidth )
  194.             {
  195.                 width2 = curX + 2 * m_dotAdvance + m_dotWidth;
  196.                 maxIndex++;
  197.                 firstDotX = curX;
  198.             }
  199.         }
  200.         else
  201.         {
  202.             // No check
  203.             width2 = width1;
  204.             maxIndex++;
  205.         }
  206.         // Stop here if the text is too large
  207.         if( maxWidth != -1 && width1 > maxWidth )
  208.         {
  209.             break;
  210.         }
  211.     }
  212.     // Adjust the size for vertical padding
  213.     yMax = __MAX( yMax, m_ascender );
  214.     yMin = __MIN( yMin, m_descender );
  215.     // Create the bitmap
  216.     FT2Bitmap *pBmp = new FT2Bitmap( getIntf(), __MIN( width1, width2 ),
  217.                                      yMax - yMin );
  218.     // Draw the glyphs on the bitmap
  219.     for( n = 0; n < maxIndex; n++ )
  220.     {
  221.         FT_BitmapGlyphRec *pBmpGlyph = (FT_BitmapGlyphRec*)glyphs[n];
  222.         // Draw the glyph on the bitmap
  223.         pBmp->draw( pBmpGlyph->bitmap, pos[n], yMax - pBmpGlyph->top, color );
  224.         // Free the glyph
  225.         FT_Done_Glyph( glyphs[n] );
  226.     }
  227.     // Draw the trailing dots if the text is truncated
  228.     if( maxIndex < len )
  229.     {
  230.         int penX = firstDotX;
  231.         FT_BitmapGlyphRec *pBmpGlyph = (FT_BitmapGlyphRec*)m_dotGlyph;
  232.         for( n = 0; n < 3; n++ )
  233.         {
  234.             // Draw the glyph on the bitmap
  235.             pBmp->draw( pBmpGlyph->bitmap, penX, yMax - pBmpGlyph->top,
  236.                         color );
  237.             penX += m_dotAdvance;
  238.         }
  239.     }
  240.     delete [] glyphs;
  241.     delete [] pos;
  242.     return pBmp;
  243. }