ft2_font.cpp
资源名称:vlc-1.0.5.zip [点击查看]
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:9k
源码类别:
midi
开发平台:
Unix_Linux
- /*****************************************************************************
- * ft2_font.cpp
- *****************************************************************************
- * Copyright (C) 2003 the VideoLAN team
- * $Id: b0ade15924f41011cb5a209446a36374cb722e5e $
- *
- * Authors: Cyril Deguet <asmax@via.ecp.fr>
- * Olivier Teulière <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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
- #include "ft2_font.hpp"
- #include "ft2_bitmap.hpp"
- #include "../utils/ustring.hpp"
- #ifdef HAVE_FRIBIDI
- #include <fribidi/fribidi.h>
- #endif
- FT2Font::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 );
- }
- free( m_buffer );
- }
- bool FT2Font::init()
- {
- int err;
- // Initialize libfreetype
- if( FT_Init_FreeType( &m_lib ) )
- {
- msg_Err( getIntf(), "failed to initialize freetype" );
- 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 )
- 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;
- }
- }