Exemple #1
0
// Get the kerning between two characters
float Font::GetKerning( char first, char second, unsigned int size )
{
    // If anything is invalid, there's no kerning
    if ( first == 0 || second == 0 || size == 0 || !_fontFace )
    {
        return 0.0f;
    }

    if ( FT_HAS_KERNING( _myFontFace ) && SetCurrentSize( size ) )
    {
        // Get the characters as indices
        FT_UInt firstIndex = FT_Get_Char_Index( _myFontFace, first );
        FT_UInt secondIndex = FT_Get_Char_Index( _myFontFace, second );

        // Get the kerning vector
        FT_Vector kerning;
        FT_Get_Kerning( _myFontFace, firstIndex, secondIndex, FT_KERNING_DEFAULT, &kerning );

        // We don't need to apply the kerning scale to bitmap fonts
        float scale = ( FT_IS_SCALABLE( _myFontFace ) ? KerningScale : 1.0f );
        return kerning.x * scale;
    }

    return 0.0f;
}
Exemple #2
0
// Get the spacing between two lines
float Font::GetLineSpacing( unsigned int size )
{
    if ( _fontFace && SetCurrentSize( size ) )
    {
        return _myFontFace->size->metrics.height * KerningScale;
    }

    return 0.0f;
}
Exemple #3
0
// Attempts to load font information from a file
bool Font::LoadFromFile( const std::string& fname )
{
    // Remove any loaded information
    Dispose();

    // Attempt to create our FreeType library
    FT_Library library;
    if ( 0 != FT_Init_FreeType( &library ) )
    {
#if defined( _DEBUG ) || defined( DEBUG )
        std::cout << "Failed to initialize FreeType for '" << fname << "'." << std::endl;
#endif
        return false;
    }
    _library = library;

    // Attempt to load the font face
    FT_Face fontFace;
    if ( 0 != FT_New_Face( library, fname.c_str(), 0, &fontFace ) )
    {
#if defined( _DEBUG ) || defined( DEBUG )
        std::cout << "Failed to create font face for '" << fname << "'." << std::endl;
#endif
        return false;
    }
    _fontFace = fontFace;

    // Get the font name
    _fontName = fontFace->family_name ? fontFace->family_name : "N/A";

    // Attempt to select the Unicode character map
    if ( 0 != FT_Select_Charmap( fontFace, FT_ENCODING_UNICODE ) )
    {
#if defined( _DEBUG ) || defined( DEBUG )
        std::cout << "Failed to select unicode font for '" << fname << "'." << std::endl;
#endif
        Dispose();
        return false;
    }

    // Set our default font size to be 12
    SetCurrentSize( 12U );

    return true;
}
Exemple #4
0
int Font::GetKerning(Uint32 first, Uint32 second, unsigned int characterSize) const
{
    // Special case where first or second is 0 (null character)
    if (first == 0 || second == 0)
        return 0;

    FT_Face face = static_cast<FT_Face>(myFace);

    if (face && FT_HAS_KERNING(face) && SetCurrentSize(characterSize))
    {
        // Convert the characters to indices
        FT_UInt index1 = FT_Get_Char_Index(face, first);
        FT_UInt index2 = FT_Get_Char_Index(face, second);

        // Get the kerning vector
        FT_Vector kerning;
        FT_Get_Kerning(face, index1, index2, FT_KERNING_DEFAULT, &kerning);

        // Return the X advance
        return kerning.x >> 6;
    }
Exemple #5
0
// Load a character glyph
Font::Glyph Font::LoadGlyph( char ch, unsigned int size )
{
    Glyph glyph;

    // Ensure we can even retrieve the glyph
    if ( !_fontFace || !SetCurrentSize( size ) )
    {
        return glyph;
    }

    // Attempt to load the font's glyph for the given character
    if ( 0 != FT_Load_Char( _myFontFace, ch, FT_LOAD_TARGET_NORMAL | FT_LOAD_FORCE_AUTOHINT ) )
    {
        return glyph;
    }

    // Get the glyph's description
    FT_Glyph ftGlyph;
    if ( 0 != FT_Get_Glyph( _myFontFace->glyph, &ftGlyph ) )
    {
        return glyph;
    }

    // Rasterize the glyph
    FT_Glyph_To_Bitmap( &ftGlyph, FT_RENDER_MODE_NORMAL, 0, 1 );
    FT_Bitmap& bitmap = reinterpret_cast<FT_BitmapGlyph>( ftGlyph )->bitmap;

    // Get the glyph's advance
    glyph.Advance = static_cast<float>( _myFontFace->glyph->metrics.horiAdvance ) * KerningScale;

    int width = bitmap.width;
    int height = bitmap.rows;

    if ( ( width > 0 ) && ( height > 0 ) )
    {
        // Get the glyph's page
        GlyphPage& page = _pages[ size ];

        // Leave a small padding around characters, so that filtering doesn't
        // pollute them with pixels from neighbors
        const unsigned int padding = 1;
        
        // Find a good position for the new glyph into the texture
        UintRect emptyArea = FindGlyphRect( page, width + 2 * padding, height + 2 * padding );;

        // Ensure the texture data is in the center of the texture rectangle
        emptyArea.X += padding;
        emptyArea.Y += padding;
        emptyArea.Width -= 2 * padding;
        emptyArea.Height -= 2 * padding;
        glyph.TextureBounds = emptyArea;

        // Set the glyph's bounding box
        glyph.Bounds.X      =  ( _myFontFace->glyph->metrics.horiBearingX ) * KerningScale;
        glyph.Bounds.Y      = -( _myFontFace->glyph->metrics.horiBearingY ) * KerningScale;
        glyph.Bounds.Width  =  ( _myFontFace->glyph->metrics.width        ) * KerningScale;
        glyph.Bounds.Height =  ( _myFontFace->glyph->metrics.height       ) * KerningScale;


        // Extract the glyph's pixels from the bitmap
        _pixelBuffer.resize( width * height * 4, 255 );
        const unsigned char* pixels = bitmap.buffer;
        if ( bitmap.pixel_mode == FT_PIXEL_MODE_MONO )
        {
            // Pixels are 1 bit monochrome values
            for ( int y = 0; y < height; ++y )
            {
                for ( int x = 0; x < width; ++x )
                {
                    // The color channels remain white, just fill the alpha channel
                    std::size_t index = ( x + y * width ) * 4 + 3;
                    _pixelBuffer[ index ] = ( ( pixels[ x / 8 ] ) & ( 1 << ( 7 - ( x % 8 ) ) ) ) ? 255 : 0;
                }
                pixels += bitmap.pitch;
            }
        }
        else
        {
            // Pixels are 8 bits gray levels
            for ( int y = 0; y < height; ++y )
            {
                for ( int x = 0; x < width; ++x )
                {
                    // The color channels remain white, just fill the alpha channel
                    std::size_t index = ( x + y * width ) * 4 + 3;
                    _pixelBuffer[ index ] = pixels[ x ];
                }
                pixels += bitmap.pitch;
            }
        }

        // Write the pixels to the texture
        page.Texture->UpdateArea( emptyArea.X, emptyArea.Y, emptyArea.Width, emptyArea.Height, &_pixelBuffer[ 0 ] );
    }

    // Cleanup
    FT_Done_Glyph( ftGlyph );

    return glyph;
}