Jump to content
  • Advertisement
Sign in to follow this  
Decrius

[SDL] Blitting to another surface but 'screen'?

This topic is 3970 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, As SDL_ttf takes ALOOOT of ram, increases 200/500 kB per second (I redraw the fonts everytime), I decided to put the surfaces I create when drawing fonts (each line has a new surface) into one surface that only will be created when a new line is added. However, I cant get SDL_BlitSurface to work.
void write_history(string history, SDL_Surface *screen, TTF_Font *font, SDL_Color color_font, SDL_Rect rect)
{
    rect.y = 0;

    string tmp;

    size_t found;
    found = history.find_first_of('\n');
    while (found != string::npos)
    {
        tmp = history.substr(0, found);
        SDL_BlitSurface(TTF_RenderText_Blended(font, tmp.c_str(), color_font), NULL, screen, &rect);

        history = history.substr(found + 1);

        rect.y += 14;
        found = history.find_first_of('\n', found);
    }
}

int main(/* arguments */)
{
    // init here

    SDL_Surface *screen = SDL_SetVideoMode(640, 320, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);

    TTF_Init();
    atexit(TTF_Quit);

    SDL_Surface *text;
    TTF_Font *font = TTF_OpenFont("vera.ttf", 11);

    SDL_Rect rect;
    rect.x = 0;
    rect.y = 0;
    SDL_Color color_font = SDL_newColor(192, 192, 192);

    while (1) // loop to display frames
    {
        if (new_line_is_added == true)
        {
            write_history(history, text, font, color_font, rect);
        }

        SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 0, 0, 0));

        SDL_BlitSurface(text, NULL, screen, NULL);

        SDL_Delay(10);
        SDL_Flip(screen);
    }

    TTF_CloseFont(font);
    SDL_FreeSurface(text);
    SDL_FreeSurface(screen);

    // sdl quit code
}
This is just a quick example. What am I doing wrong? It displays nothing but black... Or does anyone know why its taking so much ram? And is increasing every second? Thank you, Decrius [Edited by - Decrius on February 3, 2008 9:22:08 AM]

Share this post


Link to post
Share on other sites
Advertisement
You are fixing the wrong problem. TTF_RenderText_*() returns a new surface. This takes up RAM. To free the RAM you must call SDL_FreeSurface() on that. If you fix that, your RAM use should stay fairly constant (if you remember to manage the memory of other surfaces too).

However, generating and discarding surfaces every frame is expensive too. A better way would be to keep the surface around and only free it when you need to change the text.

class Text
{
public:
Text( const std::string &initialText, TTF_Font *font, const SDL_Color colour )
:
font(font),
colour(colour)
{
assert(font);
surface = TTF_RenderText_Blended(font, initialText.c_str(), colour);
if( !surface )
{
throw std::runtime_error(TTF_GetError());
}
}

void blit( SDL_Surface *destination, int x, int y )
{
SDL_Rect rect = {x,y};
SDL_BlitSurface(surface,0,destination,&dest);
}

void updateText( const std::string &text )
{
SDL_Surface *temp = TTF_RenderText_Blended(font, text.c_str(), colour);
if( !temp)
{
throw std::runtime_error(TTF_GetError());
}
SDL_FreeSurface(surface);
surface = temp;
}

private:
SDL_Surface *surface;
TTF_Font *font;
SDL_Color colour;
};



That is an example of how you might write a class to manage this for you.

Share this post


Link to post
Share on other sites
Ah, thanks for the reply. That method indeed doesn't consume more and more ram. I already thought it had something to do with freeing resources, however, the method I did didn't work :/

Got only one problem...

At the moment I basically just fill 'surface' with 'temp', this will replace anything that was in 'surface'. Can I somehow add 'temp' to the bottom of 'surface'? So it will not replace the text that is already in there?

Thanks anyways

Share this post


Link to post
Share on other sites
You mean you want to add a line to the text?

Its a little bit more complicated, but not too much.

class Text
{
public:
Text( const std::string &initialText, TTF_Font *font, const SDL_Color colour )
:
font(font),
colour(colour)
{
assert(font);
surface = TTF_RenderText_Blended(font, initialText.c_str(), colour);
if( !surface )
{
throw std::runtime_error(TTF_GetError());
}
}

void blit( SDL_Surface *destination, int x, int y )
{
SDL_Rect rect = {x,y};
SDL_BlitSurface(surface,0,destination,&dest);
}

// you may not need this
void updateText( const std::string &text )
{
SDL_Surface *temp = TTF_RenderText_Blended(font, text.c_str(), colour);
if( !temp)
{
throw std::runtime_error(TTF_GetError());
}
SDL_FreeSurface(surface);
surface = temp;
}

void appendLine( const std::string &line )
{
SDL_Surface *temp = TTF_RenderText_Blended(font, line.c_str(), colour);
if( !temp)
{
throw std::runtime_error(TTF_GetError());
}

const SDL_Format *format = surface->format;
int width = std::max(temp->w,surface->w);
int height = temp->h + surface->h;
SDL_Surface *final = SDL_CreateRGBSurface(SDL_SWSURFACE,width,height,format->BitsPerPixel,
format->Rmask, format->Bmask, format->Gmask, format->Amask);

if( !final)
{
SDL_FreeSurface(temp);
throw std::runtime_error(SDL_GetError());
}

SDL_BlitSurface(surface,0,final,0);
SDL_Rect dest = {0,surface->h};
SDL_BlitSurface(temp,0,final,&dest);
SDL_FreeSurface(temp);
SDL_FreeSurface(surface);
surface = final;
}

private:
SDL_Surface *surface;
TTF_Font *font;
SDL_Color colour;
};



Disclaimer: code not compiled or tested.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!