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

📄 ft2_font.cpp

📁 video linux conference
💻 CPP
字号:
/***************************************************************************** * ft2_font.cpp ***************************************************************************** * Copyright (C) 2003 VideoLAN * $Id: ft2_font.cpp 10873 2005-05-02 09:01:55Z rocky $ * * Authors: Cyril Deguet     <asmax@via.ecp.fr> *          Olivier Teuli鑢e <ipkiss@via.ecp.fr> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. *****************************************************************************/#include "ft2_font.hpp"#include "ft2_bitmap.hpp"#include "../utils/ustring.hpp"#ifdef HAVE_FRIBIDI#include <fribidi/fribidi.h>#endifFT2Font::FT2Font( intf_thread_t *pIntf, const string &rName, int size ):    GenericFont( pIntf ), m_name( rName ), m_buffer( NULL ), m_size( size ),    m_lib( NULL ), m_face( NULL ){}FT2Font::~FT2Font(){    // Clear the glyph cache    GlyphMap_t::iterator iter;    for( iter = m_glyphCache.begin(); iter != m_glyphCache.end(); ++iter )    {        FT_Done_Glyph( (*iter).second.m_glyph );    }    if( m_face )    {        FT_Done_Face( m_face );    }    if( m_lib )    {        FT_Done_FreeType( m_lib );    }    if( m_buffer )    {        free( m_buffer );    }}bool FT2Font::init(){    int err;    // Initalise libfreetype    if( FT_Init_FreeType( &m_lib ) )    {        msg_Err( getIntf(), "Failed to initalize libfreetype" );        return false;    }    // Open the font    FILE *file = fopen( m_name.c_str(), "rb" );    if( file )    {        msg_Dbg( getIntf(), "Loading font %s", m_name.c_str() );    }    else    {        msg_Dbg( getIntf(), "Unable to open the font %s", m_name.c_str() );        return false;    }    // Get the file size    fseek( file, 0, SEEK_END );    int size = ftell( file );    rewind( file );    // Allocate the buffer    m_buffer = malloc( size );    if( !m_buffer )    {        msg_Err( getIntf(), "Not enough memory for the font %s",                 m_name.c_str() );        return false;    }    // Read the font data    fread( m_buffer, size, 1, file );    fclose( file );    // Load the font from the buffer    err = FT_New_Memory_Face( m_lib, (const FT_Byte*)m_buffer, size, 0,                              &m_face );    if ( err == FT_Err_Unknown_File_Format )    {        msg_Err( getIntf(), "Unsupported font format (%s)", m_name.c_str() );        return false;    }    else if ( err )    {        msg_Err( getIntf(), "Error opening font (%s)", m_name.c_str() );        return false;    }    // Select the charset    if( FT_Select_Charmap( m_face, ft_encoding_unicode ) )    {        msg_Err( getIntf(), "Font has no UNICODE table (%s)", m_name.c_str() );        return false;    }    // Set the pixel size    if( FT_Set_Pixel_Sizes( m_face, 0, m_size ) )    {        msg_Warn( getIntf(), "Cannot set a pixel size of %d (%s)", m_size,                  m_name.c_str() );    }    // Get the font metrucs    m_height = m_face->size->metrics.height >> 6;    m_ascender = m_face->size->metrics.ascender >> 6;    m_descender = m_face->size->metrics.descender >> 6;    return true;}GenericBitmap *FT2Font::drawString( const UString &rString, uint32_t color,                                    int maxWidth ) const{    uint32_t code;    int n;    int penX = 0;    int width1 = 0, width2 = 0;    int yMin = 0, yMax = 0;    uint32_t *pString = (uint32_t*)rString.u_str();    // Check if freetype has been initialized    if( !m_face )    {        return NULL;    }    // Get the length of the string    int len = rString.length();    // Use fribidi if available#ifdef HAVE_FRIBIDI    uint32_t *pFribidiString = NULL;    if( len > 0 )    {        pFribidiString = new uint32_t[len+1];        FriBidiCharType baseDir = FRIBIDI_TYPE_ON;        fribidi_log2vis( (FriBidiChar*)pString, len, &baseDir,                         (FriBidiChar*)pFribidiString, 0, 0, 0 );        pString = pFribidiString;    }#endif    // Array of glyph bitmaps and position    FT_BitmapGlyphRec **glyphs = new FT_BitmapGlyphRec*[len];    int *pos = new int[len];    // Does the font support kerning ?    FT_Bool useKerning = FT_HAS_KERNING( m_face );    int previous = 0;    // Index of the last glyph when the text is truncated with trailing ...    int maxIndex = 0;    // Position of the first trailing dot    int firstDotX = 0;    /// Get the dot glyph    Glyph_t &dotGlyph = getGlyph( '.' );    // First, render all the glyphs    for( n = 0; n < len; n++ )    {        code = *(pString++);        // Get the glyph for this character        Glyph_t &glyph = getGlyph( code );        glyphs[n] = (FT_BitmapGlyphRec*)(glyph.m_glyph);        // Retrieve kerning distance and move pen position        if( useKerning && previous && glyph.m_index )        {            FT_Vector delta;            FT_Get_Kerning( m_face, previous, glyph.m_index,                            ft_kerning_default, &delta );            penX += delta.x >> 6;        }        pos[n] = penX;        width1 = penX + glyph.m_size.xMax - glyph.m_size.xMin;        yMin = __MIN( yMin, glyph.m_size.yMin );        yMax = __MAX( yMax, glyph.m_size.yMax );        // Next position        penX += glyph.m_advance;        // Save glyph index        previous = glyph.m_index;        if( maxWidth != -1 )        {            // Check if the truncated text with the '...' fit in the maxWidth            int curX = penX;            if( useKerning )            {                FT_Vector delta;                FT_Get_Kerning( m_face, glyph.m_index, dotGlyph.m_index,                                ft_kerning_default, &delta );                curX += delta.x >> 6;            }            int dotWidth = 2 * dotGlyph.m_advance +                dotGlyph.m_size.xMax - dotGlyph.m_size.xMin;            if( curX + dotWidth < maxWidth )            {                width2 = curX + dotWidth;                maxIndex++;                firstDotX = curX;            }        }        else        {            // No check            width2 = width1;            maxIndex++;        }        // Stop here if the text is too large        if( maxWidth != -1 && width1 > maxWidth )        {            break;        }    }#ifdef HAVE_FRIBIDI    if( len > 0 )    {        delete[] pFribidiString;    }#endif    // Adjust the size for vertical padding    yMax = __MAX( yMax, m_ascender );    yMin = __MIN( yMin, m_descender );    // Create the bitmap    FT2Bitmap *pBmp = new FT2Bitmap( getIntf(), __MIN( width1, width2 ),                                     yMax - yMin );    // Draw the glyphs on the bitmap    for( n = 0; n < maxIndex; n++ )    {        FT_BitmapGlyphRec *pBmpGlyph = (FT_BitmapGlyphRec*)glyphs[n];        // Draw the glyph on the bitmap        pBmp->draw( pBmpGlyph->bitmap, pos[n], yMax - pBmpGlyph->top, color );    }    // Draw the trailing dots if the text is truncated    if( maxIndex < len )    {        int penX = firstDotX;        FT_BitmapGlyphRec *pBmpGlyph = (FT_BitmapGlyphRec*)dotGlyph.m_glyph;        for( n = 0; n < 3; n++ )        {            // Draw the glyph on the bitmap            pBmp->draw( pBmpGlyph->bitmap, penX, yMax - pBmpGlyph->top,                        color );            penX += dotGlyph.m_advance;        }    }    delete [] glyphs;    delete [] pos;    return pBmp;}FT2Font::Glyph_t &FT2Font::getGlyph( uint32_t code ) const{    // Try to find the glyph in the cache    GlyphMap_t::iterator iter = m_glyphCache.find( code );    if( iter != m_glyphCache.end() )    {        return (*iter).second;    }    else    {        // Add a new glyph in the cache        Glyph_t &glyph = m_glyphCache[code];        // Load and render the glyph        glyph.m_index = FT_Get_Char_Index( m_face, code );        FT_Load_Glyph( m_face, glyph.m_index, FT_LOAD_DEFAULT );        FT_Get_Glyph( m_face->glyph, &glyph.m_glyph );        FT_Glyph_Get_CBox( glyph.m_glyph, ft_glyph_bbox_pixels,                           &glyph.m_size );        glyph.m_advance = m_face->glyph->advance.x >> 6;        FT_Glyph_To_Bitmap( &glyph.m_glyph, ft_render_mode_normal, NULL, 1 );        return glyph;    }}

⌨️ 快捷键说明

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