source: trunk/src/gl/texture_font.cc @ 25

Last change on this file since 25 was 25, checked in by melon, 12 years ago

Modified thrown error messages to provide more details

File size: 4.6 KB
RevLine 
[21]1// Copyright (C) 2012-2013 ChaosForge / Kornel Kisielewicz
2// http://chaosforge.org/
3//
4// This file is part of NV Libraries.
5// For conditions of distribution and use, see copyright notice in nv.hh
[25]6#include <sstream>
[23]7#include <stdexcept>
8
[21]9#include "nv/gl/texture_font.hh"
10#include "nv/lib/freetype2.hh"
11
12using namespace nv;
13
[24]14texture_glyph::texture_glyph()
[21]15        : charcode(0), size(0,0), offset(0,0), advance(0.f,0.f), tl(0.f,0.f), br(0.f,0.f)
16{
17}
18
[24]19float texture_glyph::get_kerning( const uint16 charcode )
[21]20{
21        auto i = kerning.find( charcode );
22        return i != kerning.end() ? i->second : 0.0f;
23}
24
25texture_font::texture_font( texture_atlas* atlas, const char * filename, float size )
26        : m_atlas( atlas ), m_filename(filename), m_size( size ),
27        m_height(0), m_linegap(0), m_ascender(0), m_descender(0),
28        m_rlibrary( nullptr ), m_rface( nullptr ), m_hinting( true ), m_filtering( true )
29{
30        size_t hres = 64;
31        FT_Error error;
32        FT_Matrix matrix = {
33                (int)((1.0/hres) * 0x10000L),
34                (int)((0.0)      * 0x10000L),
35                (int)((0.0)      * 0x10000L),
36                (int)((1.0)      * 0x10000L)
37        };
38
39        m_lcd_weights[0] = 0x10;
40        m_lcd_weights[1] = 0x40;
41        m_lcd_weights[2] = 0x70;
42        m_lcd_weights[3] = 0x40;
43        m_lcd_weights[4] = 0x10;
44         
45        error = FT_Init_FreeType( (FT_Library*)(&m_rlibrary) );
46        if ( error ) throw std::runtime_error( "FT_Error" );
47
48        error = FT_New_Face( (FT_Library)(m_rlibrary), filename, 0, (FT_Face*)(&m_rface) );
49        if ( error ) throw std::runtime_error( "FT_Error" );
50
51        error = FT_Set_Char_Size( (FT_Face)(m_rface), (int)(size*64), 0, 72*64, 72 );
52        if ( error ) throw std::runtime_error( "FT_Error" );
53
54    FT_Set_Transform( (FT_Face)(m_rface), &matrix, NULL );
55
56    FT_Size_Metrics metrics = ((FT_Face)(m_rface))->size->metrics;
57    m_ascender = (metrics.ascender >> 6) / 100.0;
58    m_descender = (metrics.descender >> 6) / 100.0;
59    m_height = (metrics.height >> 6) / 100.0;
60    m_linegap = m_height - m_ascender + m_descender;
61}
62
[24]63const texture_glyph* texture_font::get_glyph( uint16 charcode ) const
[21]64{
[24]65        auto i = m_glyphs.find( charcode );
66        if ( i == m_glyphs.end() )
[21]67        {
68                return nullptr;
69        }
70        return &(i->second);
71}
72
73bool texture_font::load_glyphs( const std::string& codes )
74{
75        FT_Face face     = (FT_Face)(m_rface);
76        size_t depth     = m_atlas->get_depth();
77        glm::ivec2 asize = m_atlas->get_size();
78        FT_Int32 flags = 0;
79        flags |= FT_LOAD_RENDER;
80        if( !m_hinting )
81        {
82                flags |= FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT;
83        }
84        else
85        {
86                flags |= FT_LOAD_FORCE_AUTOHINT;
87        }
88
89        if( m_atlas->get_depth() == 3 )
90        {
91                FT_Library_SetLcdFilter( (FT_Library)(m_rlibrary), FT_LCD_FILTER_LIGHT );
92                flags |= FT_LOAD_TARGET_LCD;
93                if ( m_filtering )
94                {
95                        FT_Library_SetLcdFilterWeights( (FT_Library)(m_rlibrary), m_lcd_weights );
96                }
97        }
98
99        for ( char c : codes )
100        {
101                FT_UInt glyph_index = FT_Get_Char_Index( face, c );
102                FT_Error error = FT_Load_Glyph( face, glyph_index, flags );
[25]103                if ( error )
104                {
105                        std::stringstream error_msg;
106                        error_msg << "FT_Error while loading glyphs, error: "
107                                << error << " code: " << c;
108                        throw std::runtime_error( error_msg.str().c_str() );
109                }
[21]110
111                FT_GlyphSlot slot   = face->glyph;
112                FT_Bitmap ft_bitmap = slot->bitmap;
113                int ft_bitmap_width = slot->bitmap.width;
114                int ft_bitmap_rows  = slot->bitmap.rows;
115                int ft_glyph_top    = slot->bitmap_top;
116                int ft_glyph_left   = slot->bitmap_left;
117
118                glm::ivec2 gsize( ft_bitmap_width/depth + 1, ft_bitmap_rows + 1 );
119                region r = m_atlas->get_region( gsize );
120                if ( r.pos.x < 0 )
121                {
[25]122                        std::stringstream error_msg;
123                        error_msg << "Atlas full while loading glyphs, "
124                                << "r.pos.x: " << r.pos.x << " code: "
125                                << c;
126                        throw std::runtime_error( error_msg.str().c_str() );
[21]127                }
128                r.size.x -= 1;
129                r.size.y -= 1;
130                m_atlas->set_region( r, ft_bitmap.buffer, ft_bitmap.pitch );
131
[24]132                m_glyphs[ c ] = texture_glyph();
133                texture_glyph* g = &(m_glyphs.find( c )->second);
[21]134
135                g->charcode = c;
136                g->size     = gsize;
137                g->offset   = glm::ivec2( ft_glyph_left, ft_glyph_top );
138                g->tl       = glm::vec2( r.pos.x/(float)asize.x, r.pos.y/(float)asize.y );
139                g->br       = glm::vec2( ( r.pos.x + gsize.x )/(float)asize.x, (r.pos.y + gsize.y )/(float)asize.y );
140
141                // Discard hinting to get advance
142                FT_Load_Glyph( face, glyph_index, FT_LOAD_RENDER | FT_LOAD_NO_HINTING);
143                slot = face->glyph;
144                g->advance = glm::ivec2( slot->advance.x/64.0, slot->advance.y/64.0 );
145        }
146        generate_kerning();
147        return true;
148}
149
150texture_font::~texture_font()
151{
152        if ( m_rface )    FT_Done_Face( (FT_Face)(m_rface) );
153        if ( m_rlibrary ) FT_Done_FreeType( (FT_Library)(m_rlibrary) );
154}
155
156void texture_font::generate_kerning()
157{
158
159}
160
Note: See TracBrowser for help on using the repository browser.