#include #include "font.hh" #include "TextWidget.hh" TextWidget::TextWidget(TTF_Font *font, std::string text, int width, int height, std::string name) : Widget(width, height, std::move(name)), text_(std::move(text)), font_(font), textSurf_(nullptr) { layout(); } TextWidget::~TextWidget() { } void TextWidget::setText(std::string text) { if (text != text_) { text_ = std::move(text); invalidateGL(); textSurf_.release(); layout(); } } void TextWidget::setForegroundColor(SDL_Color fg) { Widget::setForegroundColor(fg); // Trigger text rerender textSurf_.release(); layout(); } void TextWidget::layout(Widget *caller) { int width, height; std::tie(width, height) = Widget::baseLayout(caller); // Determine text size int textWidth, textHeight; if ((height == 0) || (width == 0)) { if(TTF_SizeUTF8(font_, text_.c_str(), &textWidth, &textHeight) != 0) throw TTFException{}; } bool multiline = false; if (height == 0) { if (width != 0) { textSurf_.reset(TTF_RenderUTF8_Blended_Wrapped(font_, text_.c_str(), fg_, width - padLeft_ - padRight_)); if (!textSurf_) throw TTFException{}; multiline = true; // TODO: Get proper tight bounding box for multiline text height = textSurf_->h - // TTF_FontLineSkip(font_.getFont()) + padTop_ + padBottom_; } else { width = textWidth + padLeft_ + padRight_; height = textHeight + padTop_ + padBottom_; } } if (width == 0) { width = textWidth + padLeft_ + padRight_; } if ((width != realWidth_) || (height != realHeight_) || !textSurf_) { if (!multiline) { textSurf_.reset(TTF_RenderUTF8_Blended(font_, text_.c_str(), fg_)); if (!textSurf_) throw TTFException{}; } if ((width != realWidth_) || (height != realHeight_)) { bool parentLayout = false; if (parent_ && (caller != parent_) && (((width != realWidth_) && ((parent_->getWidth() == WRAP_CONTENT) || (parent_->getWidth() == WRAP_CONTENT_FILL))) || ((height != realHeight_) && ((parent_->getHeight() == WRAP_CONTENT) || (parent_->getHeight() == WRAP_CONTENT_FILL))))) parentLayout = true; realWidth_ = width; realHeight_ = height; if (parentLayout) _layout(*parent_); printf("TextWidget %s now %d, %d\n", name_.c_str(), realWidth_, realHeight_); } invalidateGL(); } } void TextWidget::render(SDL_Surface *dst, SDL_Rect *dstRect) const { Widget::render(dst, dstRect); SDL_Rect rect = calcContentRect(dst, dstRect, textSurf_->clip_rect); if (SDL_BlitSurface(textSurf_.get(), nullptr, dst, &rect) != 0) throw SDLException{}; }