Ejemplo n.º 1
0
const FontFace* Font::GetFaceTTF(int pointSize)
{
    // Create & initialize FreeType library if it does not exist yet
    FreeTypeLibrary* freeType = GetSubsystem<FreeTypeLibrary>();
    if (!freeType)
        context_->RegisterSubsystem(freeType = new FreeTypeLibrary(context_));

    FT_Face face;
    FT_Error error;
    FT_Library library = freeType->GetLibrary();

    if (pointSize <= 0)
    {
        LOGERROR("Zero or negative point size");
        return 0;
    }

    if (!fontDataSize_)
    {
        LOGERROR("Font not loaded");
        return 0;
    }

    error = FT_New_Memory_Face(library, &fontData_[0], fontDataSize_, 0, &face);
    if (error)
    {
        LOGERROR("Could not create font face");
        return 0;
    }
    error = FT_Set_Char_Size(face, 0, pointSize * 64, FONT_DPI, FONT_DPI);
    if (error)
    {
        FT_Done_Face(face);
        LOGERROR("Could not set font point size " + String(pointSize));
        return 0;
    }

    SharedPtr<FontFace> newFace(new FontFace());

    FT_GlyphSlot slot = face->glyph;
    unsigned numGlyphs = 0;

    // Build glyph mapping
    FT_UInt glyphIndex;
    FT_ULong charCode = FT_Get_First_Char(face, &glyphIndex);
    while (glyphIndex != 0)
    {
        numGlyphs = Max((int)glyphIndex + 1, (int)numGlyphs);
        newFace->glyphMapping_[charCode] = glyphIndex;
        charCode = FT_Get_Next_Char(face, charCode, &glyphIndex);
    }

    LOGDEBUG("Font face has " + String(numGlyphs) + " glyphs");

    // Load each of the glyphs to see the sizes & store other information
    int maxHeight = 0;
    FT_Pos ascender = face->size->metrics.ascender;

    newFace->glyphs_.Reserve(numGlyphs);

    for (unsigned i = 0; i < numGlyphs; ++i)
    {
        FontGlyph newGlyph;

        error = FT_Load_Glyph(face, i, FT_LOAD_DEFAULT);
        if (!error)
        {
            // Note: position within texture will be filled later
            newGlyph.width_ = (short)((slot->metrics.width) >> 6);
            newGlyph.height_ = (short)((slot->metrics.height) >> 6);
            newGlyph.offsetX_ = (short)((slot->metrics.horiBearingX) >> 6);
            newGlyph.offsetY_ = (short)((ascender - slot->metrics.horiBearingY) >> 6);
            newGlyph.advanceX_ = (short)((slot->metrics.horiAdvance) >> 6);

            maxHeight = Max(maxHeight, newGlyph.height_);
        }
        else
        {
Ejemplo n.º 2
0
// ------------------------------------------------------------------- init ---
void init( void )
{
    size_t i, j;
    int ptSize = 50*64;
    int device_hdpi = 72;
    int device_vdpi = 72;

    texture_atlas_t * atlas = texture_atlas_new( 512, 512, 3 );

    /* Init freetype */
    FT_Library ft_library;
    assert(!FT_Init_FreeType(&ft_library));

    /* Load our fonts */
    FT_Face ft_face[NUM_EXAMPLES];
    assert(!FT_New_Face( ft_library, fonts[ENGLISH], 0, &ft_face[ENGLISH]) );
    assert(!FT_Set_Char_Size( ft_face[ENGLISH], 0, ptSize, device_hdpi, device_vdpi ) );
    // ftfdump( ft_face[ENGLISH] );            // wonderful world of encodings ...
    force_ucs2_charmap( ft_face[ENGLISH] ); // which we ignore.

    assert( !FT_New_Face(ft_library, fonts[ARABIC], 0, &ft_face[ARABIC]) );
    assert( !FT_Set_Char_Size(ft_face[ARABIC], 0, ptSize, device_hdpi, device_vdpi ) );
    // ftfdump( ft_face[ARABIC] );
    force_ucs2_charmap( ft_face[ARABIC] );

    assert(!FT_New_Face( ft_library, fonts[CHINESE], 0, &ft_face[CHINESE]) );
    assert(!FT_Set_Char_Size( ft_face[CHINESE], 0, ptSize, device_hdpi, device_vdpi ) );
    // ftfdump( ft_face[CHINESE] );
    force_ucs2_charmap( ft_face[CHINESE] );

    /* Get our harfbuzz font structs */
    hb_font_t *hb_ft_font[NUM_EXAMPLES];
    hb_ft_font[ENGLISH] = hb_ft_font_create( ft_face[ENGLISH], NULL );
    hb_ft_font[ARABIC]  = hb_ft_font_create( ft_face[ARABIC] , NULL );
    hb_ft_font[CHINESE] = hb_ft_font_create( ft_face[CHINESE], NULL );

    /* Create a buffer for harfbuzz to use */
    hb_buffer_t *buf = hb_buffer_create();

    for (i=0; i < NUM_EXAMPLES; ++i)
    {
        hb_buffer_set_direction( buf, text_directions[i] ); /* or LTR */
        hb_buffer_set_script( buf, scripts[i] ); /* see hb-unicode.h */
        hb_buffer_set_language( buf,
                                hb_language_from_string(languages[i], strlen(languages[i])) );

        /* Layout the text */
        hb_buffer_add_utf8( buf, texts[i], strlen(texts[i]), 0, strlen(texts[i]) );
        hb_shape( hb_ft_font[i], buf, NULL, 0 );

        unsigned int         glyph_count;
        hb_glyph_info_t     *glyph_info   = hb_buffer_get_glyph_infos(buf, &glyph_count);
        hb_glyph_position_t *glyph_pos    = hb_buffer_get_glyph_positions(buf, &glyph_count);


        FT_GlyphSlot slot;
        FT_Bitmap ft_bitmap;
        float size = 24;
        size_t hres = 64;
        FT_Error error;
        FT_Int32 flags = 0;
        flags |= FT_LOAD_RENDER;
        flags |= FT_LOAD_TARGET_LCD;
        FT_Library_SetLcdFilter( ft_library, FT_LCD_FILTER_LIGHT );
        FT_Matrix matrix = { (int)((1.0/hres) * 0x10000L),
                             (int)((0.0)      * 0x10000L),
                             (int)((0.0)      * 0x10000L),
                             (int)((1.0)      * 0x10000L)
                           };
        /* Set char size */
        error = FT_Set_Char_Size( ft_face[i], (int)(ptSize), 0, 72*hres, 72 );
        if( error )
        {
            //fprintf( stderr, "FT_Error (line %d, code 0x%02x) : %s\n",
            //         __LINE__, FT_Errors[error].code, FT_Errors[error].message );
            FT_Done_Face( ft_face[i] );
            break;
        }

        /* Set transform matrix */
        FT_Set_Transform( ft_face[i], &matrix, NULL );

        for (j = 0; j < glyph_count; ++j)
        {
            /* Load glyph */
            error = FT_Load_Glyph( ft_face[i], glyph_info[j].codepoint, flags );
            if( error )
            {
                //fprintf( stderr, "FT_Error (line %d, code 0x%02x) : %s\n",
                //         __LINE__, FT_Errors[error].code, FT_Errors[error].message );
                FT_Done_Face( ft_face[i] );
                break;
            }

            slot = ft_face[i]->glyph;
            ft_bitmap = slot->bitmap;
            int ft_bitmap_width = slot->bitmap.width;
            int ft_bitmap_rows  = slot->bitmap.rows;
            int ft_bitmap_pitch = slot->bitmap.pitch;
            int ft_glyph_top    = slot->bitmap_top;
            int ft_glyph_left   = slot->bitmap_left;

            int w = ft_bitmap_width/3; // 3 because of LCD/RGB encoding
            int h = ft_bitmap_rows;

            ivec4 region = texture_atlas_get_region( atlas, w+1, h+1 );
            if ( region.x < 0 )
            {
                fprintf( stderr, "Texture atlas is full (line %d)\n",  __LINE__ );
                continue;
            }
            int x = region.x, y = region.y;
            texture_atlas_set_region( atlas, region.x, region.y,
                                      w, h, ft_bitmap.buffer, ft_bitmap.pitch );
            printf("%d: %dx%d %f %f\n",
                   glyph_info[j].codepoint,
                   ft_bitmap_width,
                   ft_bitmap_rows,
                   glyph_pos[j].x_advance/64.,
                   glyph_pos[j].y_advance/64.);
        }

        /* clean up the buffer, but don't kill it just yet */
        hb_buffer_reset(buf);
    }


    /* Cleanup */
    hb_buffer_destroy( buf );
    for( i=0; i < NUM_EXAMPLES; ++i )
        hb_font_destroy( hb_ft_font[i] );
    FT_Done_FreeType( ft_library );

    glClearColor(1,1,1,1);
    glEnable( GL_BLEND );
    glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
    glEnable( GL_TEXTURE_2D );
    glBindTexture( GL_TEXTURE_2D, atlas->id );
    texture_atlas_upload( atlas );

    typedef struct {
        float x,y,z, u,v, r,g,b,a, shift, gamma;
    } vertex_t;
    vertex_t vertices[4] =  {
        {  0,  0,0, 0,1, 0,0,0,1, 0, 1},
        {  0,512,0, 0,0, 0,0,0,1, 0, 1},
        {512,512,0, 1,0, 0,0,0,1, 0, 1},
        {512,  0,0, 1,1, 0,0,0,1, 0, 1}
    };
    GLuint indices[6] = { 0, 1, 2, 0,2,3 };
    buffer = vertex_buffer_new( "vertex:3f,"
                                "tex_coord:2f,"
                                "color:4f,"
                                "ashift:1f,"
                                "agamma:1f" );
    vertex_buffer_push_back( buffer, vertices, 4, indices, 6 );

    shader = shader_load("shaders/text.vert",
                         "shaders/text.frag");
    mat4_set_identity( &projection );
    mat4_set_identity( &model );
    mat4_set_identity( &view );
}