Sign in to follow this  
madmaurice

SDL_ttf: Newline?

Recommended Posts

Quote:
Original post by madmaurice
i wondered if you could write a newline with sdl_ttf.
i tried this with \x0D\x0A but i got nothing than 2 squares.

any suggestions?

edit: \n also didn't work
I've never used SDL_ttf, but I don't believe it handles newlines, line wrapping, or anything of that sort (at least based on what I've read on these forums).

I'll leave it to someone else to confirm this, but I think if you want these features you'll have to implement yourself (or use a library that does support them).

Share this post


Link to post
Share on other sites
You can work around it. The following code was tested only in the slightest (as in I tested it with one font, on one test string).

If it were me, I would probably just use the std::vector of surfaces directly rather than perform the additional step of creating a new surface to blit all the others to.

If you want to use this method I highly advise that you cache the result instead of calling this function every frame, it looks expensive.


#include <string>
#include <iostream>
#include <algorithm>

// thanks to Oluseyi from gamedev.net
std::vector<std::string> tokenise(const std::string & str, const std::string & delim)
{
using namespace std;
vector<string> tokens;

size_t p0 = 0, p1 = string::npos;
while(p0 != string::npos)
{
p1 = str.find_first_of(delim, p0);
if(p1 != p0)
{
string token = str.substr(p0, p1 - p0);
tokens.push_back(token);
}
p0 = str.find_first_not_of(delim, p1);
}

return tokens;
}

struct TextGenerator : public std::binary_function<TTF_Font *,std::string,SDL_Surface *>
{
SDL_Surface *operator()( TTF_Font *font, std::string line ) const
{
const SDL_Color white = {0xff,0xff,0xff};
// TODO: handle TTF returning NULL.
return TTF_RenderText_Blended(font,line.c_str(),white);
}
};

SDL_Surface *drawText( TTF_Font *font, const std::string &text )
{

std::vector<std::string> lines = tokenise(text,"\n");

if( lines.empty() )
{
// TODO: handle error
return 0;
}

std::vector<SDL_Surface *> surfaces(lines.size());
std::transform(lines.begin(),lines.end(),surfaces.begin(),std::bind1st(TextGenerator(),font));

// as mentioned above, I would probably just return surfaces here
// with error checking of course.

int w = 0;
int h = 0;
for( int i = 0 ; i < surfaces.size() ; ++i )
{
if(!surfaces[i])
{
std::cout << TTF_GetError() << std::endl;
std::for_each(surfaces.begin(),surfaces.end(),&SDL_FreeSurface);
return 0;
}
h += surfaces[i]->h;
w = std::max(w,surfaces[i]->w);
}

SDL_PixelFormat *format = surfaces.front()->format;

SDL_Surface *result = SDL_CreateRGBSurface(0,w,h,32,format->Rmask,format->Gmask,format->Bmask,format->Gmask);
SDL_Rect offset = {};
for( int i = 0 ; i < surfaces.size() ; ++i )
{
SDL_BlitSurface(surfaces[i],0,result,&offset);
offset.y += surfaces[i]->h;
}

std::for_each(surfaces.begin(),surfaces.end(),&SDL_FreeSurface);
return result;

}



Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this