我正在尝试使用SDL1.2 + SDL_TTF创建文本包装器函数。我知道SDL2.0已经有一个随时可用的文本换行功能(TTF_RenderText_Blended_Wrapped),但我使用的是SDL1.2,因此我试图手动创建包装函数。
基本上我有两个表面,一个是包装表面,另一个是包含渲染字符串的临时表面。渲染的字符串是从要包装的整个字符串中取出的两个空格之间的字符串。每个临时曲面(字符串部分)都会渲染并blit到包装器表面上,并在超出包装器宽度时自动跳转到下一行。
字符串最终被正确包裹,但问题在于包装表面。最初我使用SDL_CreateRGBSurface()创建了一个彩色表面,因为根据我的理解,我不能将字符串部分blit到空表面上。包装完成后,我想删除包装表面上未使用的空间,使表面除文本外是透明的。
为此,我使用了颜色键,但注意到这是一个糟糕的解决方案,因为它也删除了一些文本颜色。我的另一个尝试是在两个表面上使用alpha值,但使用SDL_SetAlpha(),但这在某种程度上导致相同的结果,文本颜色都是错误的。
以下是我编写的代码示例,我非常感谢其他一些想法或解决方案。
TTF_Font* textFont = nullptr;
SDL_Color textColor = {0, 0, 0};
std::string wrapperText = "This text is to be wrapped with transparency";
SDL_Surface* wrapperSurface = nullptr;
SDL_Rect wrapperRect = {0, 0, 160, 50};
std::string tempString = "";
SDL_Surface* tempSurface = nullptr;
SDL_Rect tempRect = {0, 0, 0, 0};
int lineWidthPx = 0;
int lineHeightPx = 0;
int textWidthPx = 0;
int textHeightPx = 0;
std::size_t textBegin = 0;
std::size_t textEnd = 0;
textFont = TTF_OpenFont("res/fonts/Nunito-Black.ttf", 14);
wrapperSurface = SDL_CreateRGBSurface(SDL_HWSURFACE, wrapperRect.w, wrapperRect.h, 32, 255, 255, 255, 255);
SDL_SetAlpha(wrapperSurface, SDL_SRCALPHA | SDL_RLEACCEL, SDL_ALPHA_TRANSPARENT);
while (textEnd < wrapperText.size())
{
textBegin = textEnd + 1;
textEnd = wrapperText.find(" ", textBegin);
if (textEnd == std::string::npos)
textEnd = wrapperText.size(); // Reached end of text
tempString = wrapperText.substr(textBegin - 1, textEnd - textBegin + 1);
TTF_SizeText(textFont, tempString.c_str(), &textWidthPx, &textHeightPx);
lineWidthPx += textWidthPx;
if (lineWidthPx > wrapperRect.w)
{
tempString = wrapperText.substr(textBegin, textEnd - textBegin);
lineWidthPx = 0 + textWidthPx;
lineHeightPx += textHeightPx; // Next line
if (lineHeightPx > wrapperRect.h)
break; // Text is too large for wrapper
}
tempSurface = TTF_RenderUTF8_Solid(textFont, tempString.c_str(), textColor);
SDL_SetAlpha(tempSurface, SDL_SRCALPHA | SDL_RLEACCEL, SDL_ALPHA_OPAQUE);
tempRect = { static_cast<Sint16>(lineWidthPx-textWidthPx), static_cast<Sint16>(lineHeightPx), static_cast<Uint16>(textWidthPx), static_cast<Uint16>(textHeightPx) };
SDL_BlitSurface(tempSurface, NULL, wrapperSurface, &tempRect);
}
TTF_CloseFont(textFont);
textFont = nullptr;
// Remove temporary surface
SDL_FreeSurface(tempSurface);
tempSurface = nullptr;