Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++. FreeType2] Polskie znaki

Ostatnio zmodyfikowano 2011-07-30 14:12
Autor Wiadomość
qba10
Temat założony przez niniejszego użytkownika
[C++. FreeType2] Polskie znaki
» 2011-07-30 00:01:36
Korzystam kodu z lekcji nehe (bodajże lekcja 43) o wykorzystaniu freetype do wyświetlania tekstu w programie z opengl'em
Jednak mam problem z wyświetlaniem polskich liter i generalnie z korzystaniem z unicode
W internecie znalazłem taki link:
http://forum.warsztat.gd/index.php?topic=12446.0

Jednak nie za bardzo kumam jak wykorzystać te informacje.

Poniżej daję  dwie funkcję które służą do generowania tablicy znaków z danej czionki;
C/C++
void make_dlist( FT_Face face, char ch, GLuint list_base, GLuint * tex_base ) {
   
    //The first thing we do is get FreeType to render our character
    //into a bitmap.  This actually requires a couple of FreeType commands:
   
    //Load the Glyph for our character.
    if( FT_Load_Glyph( face, FT_Get_Char_Index( face, ch ), FT_LOAD_DEFAULT ) )
         throw std::runtime_error( "FT_Load_Glyph failed" );
   
    //Move the face's glyph into a Glyph object.
    FT_Glyph glyph;
    if( FT_Get_Glyph( face->glyph, & glyph ) )
         throw std::runtime_error( "FT_Get_Glyph failed" );
   
    //Convert the glyph to a bitmap.
    FT_Glyph_To_Bitmap( & glyph, ft_render_mode_normal, 0, 1 );
    FT_BitmapGlyph bitmap_glyph =( FT_BitmapGlyph ) glyph;
   
    //This reference will make accessing the bitmap easier
    FT_Bitmap & bitmap = bitmap_glyph->bitmap;
   
    //Use our helper function to get the widths of
    //the bitmap data that we will need in order to create
    //our texture.
    int width = next_p2( bitmap.width );
    int height = next_p2( bitmap.rows );
   
    //Allocate memory for the texture data.
    GLubyte * expanded_data = new GLubyte[ 2 * width * height ];
   
    //Here we fill in the data for the expanded bitmap.
    //Notice that we are using two channel bitmap (one for
    //luminocity and one for alpha), but we assign
    //both luminocity and alpha to the value that we
    //find in the FreeType bitmap.
    //We use the ?: operator so that value which we use
    //will be 0 if we are in the padding zone, and whatever
    //is the the Freetype bitmap otherwise.
    for( int j = 0; j < height; j++ ) {
        for( int i = 0; i < width; i++ ) {
            expanded_data[ 2 *( i + j * width ) ] = expanded_data[ 2 *( i + j
            * width ) + 1 ] =( i >= bitmap.width || j >= bitmap.rows ) ? 0
                : bitmap.buffer[ i + bitmap.width * j ];
        }
    }
   
    //Now we just setup some texture paramaters.
    glBindTexture( GL_TEXTURE_2D, tex_base[ ch ] );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
   
    //Here we actually create the texture itself, notice
    //that we are using GL_LUMINANCE_ALPHA to indicate that
    //we are using 2 channel data.
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
    GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data );
   
    //With the texture created, we don't need to expanded data anymore
    delete[] expanded_data;
   
    //So now we can create the display list
    glNewList( list_base + ch, GL_COMPILE );
   
    glBindTexture( GL_TEXTURE_2D, tex_base[ ch ] );
   
    //first we need to move over a little so that
    //the character has the right amount of space
    //between it and the one before it.
    glTranslatef( bitmap_glyph->left, 0, 0 );
   
    //Now we move down a little in the case that the
    //bitmap extends past the bottom of the line
    //(this is only true for characters like 'g' or 'y'.
    glPushMatrix();
    glTranslatef( 0, bitmap_glyph->top - bitmap.rows, 0 );
   
    //Now we need to account for the fact that many of
    //our textures are filled with empty padding space.
    //We figure what portion of the texture is used by
    //the actual character and store that information in
    //the x and y variables, then when we draw the
    //quad, we will only reference the parts of the texture
    //that we contain the character itself.
    float x =( float ) bitmap.width /( float ) width, y =( float ) bitmap.rows
    /( float ) height;
   
    //Here we draw the texturemaped quads.
    //The bitmap that we got from FreeType was not
    //oriented quite like we would like it to be,
    //so we need to link the texture to the quad
    //so that the result will be properly aligned.
    glBegin( GL_QUADS );
    glTexCoord2d( 0, 0 );
    glVertex2f( 0, bitmap.rows );
    glTexCoord2d( 0, y );
    glVertex2f( 0, 0 );
    glTexCoord2d( x, y );
    glVertex2f( bitmap.width, 0 );
    glTexCoord2d( x, 0 );
    glVertex2f( bitmap.width, bitmap.rows );
    glEnd();
    glPopMatrix();
    glTranslatef( face->glyph->advance.x >> 6, 0, 0 );
   
    //increment the raster position as if we were a bitmap font.
    //(only needed if you want to calculate text length)
    //glBitmap(0,0,0,0,face->glyph->advance.x >> 6,0,NULL);
   
    //Finnish the display list
    glEndList();
}

void font_data::init( const char * fname, unsigned int h ) {
    //Allocate some memory to store the texture ids.
    textures = new GLuint[ 128 ];
   
    this->h = h;
   
    //Create and initilize a freetype font library.
    FT_Library library;
    if( FT_Init_FreeType( & library ) )
         throw std::runtime_error( "FT_Init_FreeType failed" );
   
    //The object in which Freetype holds information on a given
    //font is called a "face".
    FT_Face face;
   
    //This is where we load in the font information from the file.
    //Of all the places where the code might die, this is the most likely,
    //as FT_New_Face will die if the font file does not exist or is somehow broken.
    if( FT_New_Face( library, fname, 0, & face ) )
    throw std::runtime_error(
         "FT_New_Face failed (there is probably a problem with your font file)" );
   
    //For some twisted reason, Freetype measures font size
    //in terms of 1/64ths of pixels.  Thus, to make a font
    //h pixels high, we need to request a size of h*64.
    //(h << 6 is just a prettier way of writting h*64)
    FT_Set_Char_Size( face, h << 6, h << 6, 96, 96 );
   
    //Here we ask opengl to allocate resources for
    //all the textures and displays lists which we
    //are about to create.
    list_base = glGenLists( 128 );
    glGenTextures( 128, textures );
   
    //This is where we actually create each of the fonts display lists.
    for( unsigned char i = 0; i < 128; i++ )
         make_dlist( face, i, list_base, textures );
   
    //We don't need the face information now that the display
    //lists have been created, so we free the assosiated resources.
    FT_Done_Face( face );
   
    //Ditto for the library.
    FT_Done_FreeType( library );
}

kombinowałem  cos takiego:

C/C++
list_base = glGenLists( 256 );
glGenTextures( 256, textures );
wchar_t * str = L"!\"#$%&'()*+,-./0123456789:;=>?@ABCDEFGHIJKLMNO\
 PQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~•€£°¡¿ÅÀÂÁ\
 ¡ÄåàâáąäÆæßÇćÈçćèÏïÉÈÊËęÌéèêëęìÎÏÍîïíŁłÑńÒñńòØÖÔÓøöôóÛÙÜÚÙ\
 ûùüúùØøŚ©ś¹«»ŸÝÿýŹŻ®ź¾żАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯаб\
 вгдеёжзийклмнопрстуфхцчшщъыьэюяΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγ\
 δεζηθικλμνξοπρστυφχψω";
//This is where we actually create each of the fonts display lists.
for( unsigned short i = 0; i < 256; i++ )
     make_dlist( face, str[ i ], list_base, textures );

Ale zamiast polskich liter wyświetlały mi się któreś z tych liter:
ÅÀÂÁ¡Äå

P-37593
DejaVu
» 2011-07-30 14:12:23
Sprawdź sobie w źródłach biblioteki SFML :) Ona pracuje na OpenGLu i można w niej określić pulę znaków, które mają być załadowane. http://cpp0x.pl/kursy/Kurs-SFML-C++/Wyswietlanie-tekstu/341

C/C++
bool Font::LoadFromFile( const std::string & Filename, unsigned int CharSize, const Unicode::Text & Charset )
{
    // Clear the previous character map
    myGlyphs.clear();
   
    // Always add these special characters
    Unicode::UTF32String UTFCharset = Charset;
    if( UTFCharset.find( L' ' ) != Unicode::UTF32String::npos ) UTFCharset += L' ';
   
    if( UTFCharset.find( L'\n' ) != Unicode::UTF32String::npos ) UTFCharset += L'\n';
   
    if( UTFCharset.find( L'\v' ) != Unicode::UTF32String::npos ) UTFCharset += L'\v';
   
    if( UTFCharset.find( L'\t' ) != Unicode::UTF32String::npos ) UTFCharset += L'\t';
   
    return priv::FontLoader::GetInstance().LoadFontFromFile( Filename, CharSize, UTFCharset, * this );
}

bool FontLoader::LoadFontFromFile( const std::string & Filename, unsigned int CharSize, const Unicode::UTF32String & Charset, Font & LoadedFont )
{
    // Check if Freetype is correctly initialized
    if( !myLibrary )
    {
        std::cerr << "Failed to load font \"" << Filename << "\", FreeType has not been initialized" << std::endl;
        return false;
    }
   
    // Create a new font face from the specified file
    FT_Face FontFace;
    FT_Error Error = FT_New_Face( myLibrary, Filename.c_str(), 0, & FontFace );
    if( Error )
    {
        std::cerr << "Failed to load font \"" << Filename << "\" (" << GetErrorDesc( Error ) << ")" << std::endl;
        return false;
    }
   
    // Create the bitmap font
    Error = CreateBitmapFont( FontFace, CharSize, Charset, LoadedFont );
    if( Error )
         std::cerr << "Failed to load font \"" << Filename << "\" (" << GetErrorDesc( Error ) << ")" << std::endl;
   
    // Delete the font
    FT_Done_Face( FontFace );
   
    return Error == 0;
}

FT_Error FontLoader::CreateBitmapFont( FT_Face FontFace, unsigned int CharSize, const Unicode::UTF32String & Charset, Font & LoadedFont )
{
    // Make sure we have a valid context
    priv::GraphicsContext Ctx;
   
    // Let's find how many characters to put in each row to make them fit into a squared texture
    GLint MaxSize;
    GLCheck( glGetIntegerv( GL_MAX_TEXTURE_SIZE, & MaxSize ) );
    int NbChars = static_cast < int >( sqrt( static_cast < double >( Charset.length() ) ) * 0.75 );
   
    // Clamp the character size to make sure we won't create a texture too big
    if( NbChars * CharSize >= static_cast < unsigned int >( MaxSize ) )
         CharSize = MaxSize / NbChars;
   
    // Initialize the dimensions
    unsigned int Left = 0;
    unsigned int Top = 0;
    unsigned int TexWidth = Image::GetValidTextureSize( CharSize * NbChars );
    unsigned int TexHeight = CharSize * NbChars;
    std::vector < unsigned int > Tops( TexWidth, 0 );
   
    // Create a pixel buffer for rendering every glyph
    std::vector < Uint8 > GlyphsBuffer( TexWidth * TexHeight * 4 );
   
    // Setup the font size
    FT_Error Error = FT_Set_Pixel_Sizes( FontFace, CharSize, CharSize );
    if( Error )
         return Error;
   
    // Select the unicode character map
    Error = FT_Select_Charmap( FontFace, FT_ENCODING_UNICODE );
    if( Error )
         return Error;
   
    // Render all glyphs and sort them by size to optimize texture space
    typedef std::multimap < FT_BitmapGlyph, Uint32, SizeCompare > GlyphTable;
    GlyphTable Glyphs;
    for( std::size_t i = 0; i < Charset.length(); ++i )
    {
        // Load the glyph corresponding to the current character
        Error = FT_Load_Char( FontFace, Charset[ i ], FT_LOAD_TARGET_NORMAL );
        if( Error )
             return Error;
       
        // Convert the glyph to a bitmap (ie. rasterize it)
        FT_Glyph Glyph;
        Error = FT_Get_Glyph( FontFace->glyph, & Glyph );
        if( Error )
             return Error;
       
        FT_Glyph_To_Bitmap( & Glyph, FT_RENDER_MODE_NORMAL, 0, 1 );
        FT_BitmapGlyph BitmapGlyph =( FT_BitmapGlyph ) Glyph;
       
        // Add it to the sorted table of glyphs
        Glyphs.insert( std::make_pair( BitmapGlyph, Charset[ i ] ) );
    }
   
    // Copy the rendered glyphs into the texture
    unsigned int MaxHeight = 0;
    std::map < Uint32, IntRect > Coords;
    for( GlyphTable::const_iterator i = Glyphs.begin(); i != Glyphs.end(); ++i )
    {
        // Get the bitmap of the current glyph
        Glyph & CurGlyph = LoadedFont.myGlyphs[ i->second ];
        FT_BitmapGlyph BitmapGlyph = i->first;
        FT_Bitmap & Bitmap = BitmapGlyph->bitmap;
       
        // Make sure we don't go over the texture width
        if( Left + Bitmap.width + 1 >= TexWidth )
             Left = 0;
       
        // Compute the top coordinate
        Top = Tops[ Left ];
        for( int x = 0; x < Bitmap.width + 1; ++x )
             Top = std::max( Top, Tops[ Left + x ] );
       
        Top++;
       
        // Make sure we don't go over the texture height -- resize it if we need more space
        if( Top + Bitmap.rows + 1 >= TexHeight )
        {
            TexHeight *= 2;
            GlyphsBuffer.resize( TexWidth * TexHeight * 4 );
        }
       
        // Store the character's position and size
        CurGlyph.Rectangle.Left = BitmapGlyph->left;
        CurGlyph.Rectangle.Top = - BitmapGlyph->top;
        CurGlyph.Rectangle.Right = CurGlyph.Rectangle.Left + Bitmap.width;
        CurGlyph.Rectangle.Bottom = Bitmap.rows - BitmapGlyph->top;
        CurGlyph.Advance = BitmapGlyph->root.advance.x >> 16;
       
        // Texture size may change, so let the texture coordinates be calculated later
        Coords[ i->second ] = IntRect( Left + 1, Top + 1, Left + Bitmap.width + 1, Top + Bitmap.rows + 1 );
       
        // Draw the glyph into our bitmap font
        const Uint8 * Pixels = Bitmap.buffer;
        for( int y = 0; y < Bitmap.rows; ++y )
        {
            for( int x = 0; x < Bitmap.width; ++x )
            {
                std::size_t Index = x + Left + 1 +( y + Top + 1 ) * TexWidth;
                GlyphsBuffer[ Index * 4 + 0 ] = 255;
                GlyphsBuffer[ Index * 4 + 1 ] = 255;
                GlyphsBuffer[ Index * 4 + 2 ] = 255;
                GlyphsBuffer[ Index * 4 + 3 ] = Pixels[ x ];
            }
            Pixels += Bitmap.pitch;
        }
       
        // Update the rendering coordinates
        for( int x = 0; x < Bitmap.width + 1; ++x )
             Tops[ Left + x ] = Top + Bitmap.rows;
       
        Left += Bitmap.width + 1;
        if( Top + Bitmap.rows > MaxHeight )
             MaxHeight = Top + Bitmap.rows;
       
        // Delete the glyph
        FT_Done_Glyph(( FT_Glyph ) BitmapGlyph );
    }
   
    // Create the font's texture
    TexHeight = MaxHeight + 1;
    GlyphsBuffer.resize( TexWidth * TexHeight * 4 );
    LoadedFont.myTexture.LoadFromPixels( TexWidth, TexHeight, & GlyphsBuffer[ 0 ] );
   
    // Now that the texture is created, we can precompute texture coordinates
    for( std::size_t i = 0; i < Charset.size(); ++i )
    {
        Uint32 CurChar = Charset[ i ];
        LoadedFont.myGlyphs[ CurChar ].TexCoords = LoadedFont.myTexture.GetTexCoords( Coords[ CurChar ] );
    }
   
    // Update the character size (it may have been changed by the function)
    LoadedFont.myCharSize = CharSize;
   
    return 0;
}
P-37614
« 1 »
  Strona 1 z 1