#include "EngineFrame/Component/Text.h" #include "Text.h" #include "EngineCore/Game.h" Text::Text() { } Text::Text(std::string Str, TTF_Font *font, SDL_Color color) { m_text = Str; m_font = font; m_text_color = color; Init(Str, font, color); } Text::Text(std::string Str, TTF_Font *font, SDL_Color textColor, SDL_Color strokeColor, int strokeSize) { m_text = Str; m_font = font; m_text_color = textColor; m_stroke_color = strokeColor; m_stroke_size = strokeSize; Init(Str, font, textColor, strokeColor, strokeSize); } Text::~Text() { } void Text::Init(std::string Str, TTF_Font *font, SDL_Color color) { // TTF_SetFontOutline(font, 1); // 先渲染为表面 SDL_Surface *textSurface = TTF_RenderUTF8_Blended(font, Str.c_str(), color); if (!textSurface) { SDL_LogError(0, "文字渲染为表面失败!TTF_Error:%s", TTF_GetError()); } // 再将表面转换为纹理 SDL_Renderer *renderer = Game::GetInstance().GetRenderer(); m_texture = SDL_CreateTextureFromSurface(renderer, textSurface); if (!m_texture) { SDL_LogError(0, "表面转换为纹理失败!SDL_Error:%s", SDL_GetError()); } // 设置纹理过滤模式为最近邻,避免缩放模糊 SDL_SetTextureScaleMode(m_texture, SDL_ScaleModeNearest); Size.x = textSurface->w; Size.y = textSurface->h; TextureSize.x = textSurface->w; TextureSize.y = textSurface->h; // 释放表面 SDL_FreeSurface(textSurface); } void Text::Init(std::string Str, TTF_Font *font, SDL_Color textColor, SDL_Color strokeColor, int strokeSize) { // 先保存原始字体的轮廓设置 int originalOutline = TTF_GetFontOutline(font); // 设置字体轮廓大小(描边宽度) TTF_SetFontOutline(font, strokeSize); // 渲染描边(使用描边颜色) SDL_Surface *strokeSurface = TTF_RenderUTF8_Blended(font, Str.c_str(), strokeColor); if (!strokeSurface) { SDL_LogError(0, "描边渲染为表面失败!TTF_Error:%s", TTF_GetError()); TTF_SetFontOutline(font, originalOutline); // 恢复原始设置 return; } // 恢复字体轮廓设置,用于渲染文字本身 TTF_SetFontOutline(font, 0); // 渲染文字本身(使用文字颜色) SDL_Surface *textSurface = TTF_RenderUTF8_Blended(font, Str.c_str(), textColor); if (!textSurface) { SDL_LogError(0, "文字渲染为表面失败!TTF_Error:%s", TTF_GetError()); SDL_FreeSurface(strokeSurface); TTF_SetFontOutline(font, originalOutline); // 恢复原始设置 return; } // 创建一个合并描边和文字的表面 SDL_Renderer *renderer = Game::GetInstance().GetRenderer(); // 计算最终纹理大小(描边会增加额外尺寸) int finalWidth = strokeSurface->w; int finalHeight = strokeSurface->h; // 创建一个临时表面用于合并描边和文字 SDL_Surface *finalSurface = SDL_CreateRGBSurfaceWithFormat( 0, finalWidth, finalHeight, 32, SDL_PIXELFORMAT_RGBA32); if (!finalSurface) { SDL_LogError(0, "创建最终表面失败!SDL_Error:%s", SDL_GetError()); SDL_FreeSurface(textSurface); SDL_FreeSurface(strokeSurface); TTF_SetFontOutline(font, originalOutline); return; } // 将描边绘制到最终表面 SDL_Rect strokeRect = {0, 0, strokeSurface->w, strokeSurface->h}; SDL_BlitSurface(strokeSurface, nullptr, finalSurface, &strokeRect); // 计算文字在描边中间的位置 SDL_Rect textRect = { strokeSize, // X偏移(描边宽度) strokeSize, // Y偏移(描边宽度) textSurface->w, textSurface->h}; SDL_BlitSurface(textSurface, nullptr, finalSurface, &textRect); // 将合并后的表面转换为纹理 m_texture = SDL_CreateTextureFromSurface(renderer, finalSurface); if (!m_texture) { SDL_LogError(0, "表面转换为纹理失败!SDL_Error:%s", SDL_GetError()); } // 设置尺寸信息 Size.x = finalSurface->w; Size.y = finalSurface->h; TextureSize.x = finalSurface->w; TextureSize.y = finalSurface->h; // 释放所有临时表面 SDL_FreeSurface(textSurface); SDL_FreeSurface(strokeSurface); SDL_FreeSurface(finalSurface); // 恢复字体原始轮廓设置 TTF_SetFontOutline(font, originalOutline); } void Text::HandleEvents(SDL_Event *e) { } void Text::Update(float deltaTime) { } void Text::Render(float deltaTime) { SDL_Renderer *renderer = Game::GetInstance().GetRenderer(); if (!renderer || !m_texture) return; SDL_Rect dstrect = {Pos.x, Pos.y, Size.x, Size.y}; SDL_RenderCopy(renderer, m_texture, NULL, &dstrect); } void Text::Clear() { } void Text::SetPos(SDL_Point pos) { Pos = pos; } SDL_Point Text::GetPos() { return Pos; } void Text::SetText(std::string Str) { if (Str == m_text) return; if (!m_font) { SDL_LogError(0, "SetText失败:字体指针为空!"); return; } // 如果有原纹理先删除原纹理 if (m_texture) { SDL_DestroyTexture(m_texture); m_texture = nullptr; // 置空指针 } m_text = Str; // 根据是否有描边选择对应的Init方法 if (m_stroke_size > 0) { Init(Str, m_font, m_text_color, m_stroke_color, m_stroke_size); } else { Init(Str, m_font, m_text_color); } } std::string Text::GetText() { return m_text; }