Exemple #1
0
    // ---------------------------------------------------- texture_font_delete ---
    void
    texture_font_delete( texture_font_t *self )
    {
        size_t i;
        texture_glyph_t *glyph;

        assert( self );

        if(self->location == TEXTURE_FONT_FILE && self->filename)
            free( self->filename );

        for( i=0; i<vector_size( self->glyphs ); ++i)
        {
            glyph = *(texture_glyph_t **) vector_get( self->glyphs, i );
            texture_glyph_delete( glyph);
        }

        vector_delete( self->glyphs );
        free( self );
    }
Exemple #2
0
// ---------------------------------------------------- texture_font_delete ---
void
texture_font_delete( texture_font_t *self )
{
    assert( self );

    if( self->filename )
    {
        free( self->filename );
    }

    size_t i;
    texture_glyph_t *glyph;
    for( i=0; i<vector_size( self->glyphs ); ++i)
    {
        glyph = *(texture_glyph_t **) vector_get( self->glyphs, i );
        texture_glyph_delete( glyph);
    }

    vector_delete( self->glyphs );
    free( self );
}
/* ------------------------------------------------------------------------- */
size_t
texture_font_cache_glyphs( TextureFont *self,
                           wchar_t * charcodes )
{
    size_t i, x, y, width, height, depth, w, h;
    FT_Library    library;
    FT_Error      error;
    FT_Face       face;
    FT_GlyphSlot  slot;
    FT_UInt       glyph_index;
    TextureGlyph *glyph;
    Region        region;
    unsigned char c;
    size_t        missed = 0;
    width  = self->atlas->width;
    height = self->atlas->height;
    depth  = self->atlas->depth;

    if( !texture_font_load_face( &library, self->filename, self->size, &face ) )
    {
        return wcslen(charcodes);
    }

    /* Load each glyph */
    for( i=0; i<wcslen(charcodes); ++i )
    {
        glyph_index = FT_Get_Char_Index( face, charcodes[i] );

        // WARNING: We use texture-atlas depth to guess if user wants
        //          LCD subpixel rendering
        FT_Int32 flags = FT_LOAD_RENDER;

        if( !self->hinting )
        {
            flags |= FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT;
        }
        else
        {
            flags |= FT_LOAD_FORCE_AUTOHINT;
        }

        if( depth == 3 )
        {
            FT_Library_SetLcdFilter( library, FT_LCD_FILTER_LIGHT );
            flags |= FT_LOAD_TARGET_LCD;
            if( self->lcd_filter )
            {
                FT_Library_SetLcdFilterWeights( library, self->lcd_weights );
            }
        }
        error = FT_Load_Glyph( face, glyph_index, 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_FreeType( library );
            return wcslen(charcodes)-i;
        }
        slot = face->glyph;

        /* Gamma correction (sort of) */
        for( x=0; x<slot->bitmap.width; ++x )
        {
            for( y=0; y<slot->bitmap.rows; ++y )
            {
                c = *(unsigned char *)(slot->bitmap.buffer
                                       + y*slot->bitmap.pitch + x );
                c = (unsigned char) ( pow(c/255.0, self->gamma) * 255);
                *(unsigned char *)(slot->bitmap.buffer
                                   + y*slot->bitmap.pitch + x ) = c;
            }
        }

        // We want each glyph to be separated by at least one black pixel
        // (for example for shader used in demo-subpixel.c)
        w = slot->bitmap.width/depth + 1;
        h = slot->bitmap.rows + 1;
        region = texture_atlas_get_region( self->atlas, w, h );
        if ( region.x < 0 )
        {
            missed++;
            continue;
        }
        w = w - 1;
        h = h - 1;
        x = region.x;
        y = region.y;
        texture_atlas_set_region( self->atlas, x, y, w, h,
                                  slot->bitmap.buffer, slot->bitmap.pitch );

        glyph = texture_glyph_new( );
        glyph->font = self;
        glyph->charcode = charcodes[i];
        glyph->kerning  = 0;
        glyph->width    = w;
        glyph->height   = h;
        glyph->offset_x = slot->bitmap_left;
        glyph->offset_y = slot->bitmap_top;
        glyph->u0       = x/(float)width;
        glyph->v0       = y/(float)height;
        glyph->u1       = (x + glyph->width)/(float)width;
        glyph->v1       = (y + glyph->height)/(float)height;

        /* Discard hinting to get advance */
        FT_Load_Glyph( face, glyph_index, FT_LOAD_RENDER | FT_LOAD_NO_HINTING);
        slot = face->glyph;
        glyph->advance_x    = slot->advance.x/64.0;
        glyph->advance_y    = slot->advance.y/64.0;

        vector_push_back( self->glyphs, glyph );
        texture_glyph_delete( glyph );
    }
    FT_Done_Face( face );
    FT_Done_FreeType( library );
    texture_atlas_upload( self->atlas );
    texture_font_generate_kerning( self );
    return missed;
}
Exemple #4
0
// ------------------------------------------------- texture_font_get_glyph ---
texture_glyph_t *
texture_font_get_glyph( texture_font_t * self,
                        wchar_t charcode )
{
    assert( self );

    size_t i;
    wchar_t buffer[2] = {0,0};
    texture_glyph_t *glyph;

    assert( self );
    assert( self->filename );
    assert( self->atlas );

    /* Check if charcode has been already loaded */
    for( i=0; i<self->glyphs->size; ++i )
    {
        glyph = *(texture_glyph_t **) vector_get( self->glyphs, i );
        // If charcode is -1, we don't care about outline type or thickness
        if( (glyph->charcode == charcode) &&
            ((charcode == (wchar_t)(-1) ) || 
             ((glyph->outline_type == self->outline_type) &&
              (glyph->outline_thickness == self->outline_thickness)) ))
        {
            return glyph;
        }
    }

    /* charcode -1 is special : it is used for line drawing (overline,
     * underline, strikethrough) and background.
     */
    if( charcode == (wchar_t)(-1) )
    {
        size_t width  = self->atlas->width;
        size_t height = self->atlas->height;
        ivec4 region = texture_atlas_get_region( self->atlas, 5, 5 );
        texture_glyph_t * glyph = texture_glyph_new( );
        static unsigned char data[4*4*3] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
                                            -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
                                            -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
                                            -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
        if ( region.x < 0 )
        {
            fprintf( stderr, "Texture atlas is full (line %d)\n",  __LINE__ );
            texture_glyph_delete(glyph);
            return NULL;
        }
        texture_atlas_set_region( self->atlas, region.x, region.y, 4, 4, data, 0 );
        glyph->charcode = (wchar_t)(-1);
        glyph->s0 = (region.x+2)/(float)width;
        glyph->t0 = (region.y+2)/(float)height;
        glyph->s1 = (region.x+3)/(float)width;
        glyph->t1 = (region.y+3)/(float)height;
        vector_push_back( self->glyphs, &glyph );
        return glyph; //*(texture_glyph_t **) vector_back( self->glyphs );
    }

    /* Glyph has not been already loaded */
    buffer[0] = charcode;
    if( texture_font_load_glyphs( self, buffer ) == 0 )
    {
        return *(texture_glyph_t **) vector_back( self->glyphs );
    }
    return NULL;
}