// Copyright (c) 2023 Dominic Masters // // This software is released under the MIT License. // https://opensource.org/licenses/MIT #include "UILabel.hpp" using namespace Dawn; void UILabel::getSelfQuads(UICanvas &ctx) { std::vector quads; if(this->texture == nullptr || this->text.empty()) return; glm::vec4 quad; glm::vec2 pos = glm::vec2(0, this->texture->fontSize); bool_t lastCharWasSpace = false; for(size_t i = 0; i < text.size(); i++) { wchar_t c = text[i]; auto info = texture->getCharacterData(c); // Newline(s) if(c == L'\n') { pos.x = 0; pos.y += this->texture->fontSize; continue; } // Spaces if(c == L' ') { pos.x += info.advance.x; lastCharWasSpace = true; continue; } // Word Wrap if(wordWrap) { if(lastCharWasSpace) { // Scan ahead to next space float_t wordWidth = pos.x;// Start at current position and scan ahead. for(size_t j = i; j < text.size(); j++) { wchar_t c2 = text[j]; if(c2 == L' ' || c2 == L'\n') { break;// If we hit another space, we are OK. } // Will this character fit on the row? If not the whole word will wrap. auto info2 = texture->getCharacterData(c); wordWidth += info.advance.x; if(wordWidth > size.x) { pos.x = 0; pos.y += this->texture->fontSize; break; } } lastCharWasSpace = false; } // } else if(pos.x + info.size.x > subAlignedPosition.x + size.x) { // // Not word wrap, but instead just overflow characters. // pos.x = 0; // pos.y += this->texture->fontSize; } ctx.addQuad( { subAlignedPosition.x + pos.x + info.offset.x, subAlignedPosition.y + pos.y + info.offset.y, subAlignedPosition.x + pos.x + info.size.x + info.offset.x, subAlignedPosition.y + pos.y + info.size.y + info.offset.y }, { info.quad.x, info.quad.y, info.quad.z, info.quad.w }, this->color, UIShaderQuadStyle::FONT, texture->texture ); pos += info.advance; } } float_t UILabel::getContentWidth() { if(this->texture == nullptr || this->text.empty()) return 0.0f; float_t lineWidth = 0.0f; float_t width = 0.0f; for(wchar_t c : text) { if(c == L'\n') { width = Math::max(width, lineWidth); lineWidth = 0.0f; continue; } auto info = texture->getCharacterData(c); lineWidth += info.advance.x; if( this->hasExplicitWidth() && lineWidth >= size.x ) return size.x; } width = Math::max(width, lineWidth); return width; } float_t UILabel::getContentHeight() { if(this->texture == nullptr || this->text.empty()) return 0.0f; float_t height = this->texture->fontSize; float_t lineWidth = 0.0f; bool_t lastCharWasSpace = false; for(wchar_t c : text) { if(c == L'\n') { height += this->texture->fontSize; continue; } auto info = texture->getCharacterData(c); if(c == L' ') { lineWidth += info.advance.x; lastCharWasSpace = true; continue; } if(wordWrap) { if(lastCharWasSpace) { // Scan ahead to next space float_t wordWidth = lineWidth;// Start at current position and scan ahead. for(size_t j = 0; j < text.size(); j++) { wchar_t c2 = text[j]; if(c2 == L' ' || c2 == L'\n') { break;// If we hit another space, we are OK. } // Will this character fit on the row? If not the whole word will wrap. auto info2 = texture->getCharacterData(c); wordWidth += info.advance.x; if(wordWidth > size.x) { height += this->texture->fontSize; lineWidth = 0.0f; break; } } lastCharWasSpace = false; } // } else if(lineWidth + info.size.x > size.x) { // height += this->texture->fontSize; // lineWidth = 0.0f; } } return height; } std::shared_ptr UILabel::getFont() { return this->texture; } std::wstring UILabel::getText() { return this->text; } void UILabel::setFont(std::shared_ptr texture) { this->texture = texture; } void UILabel::setText(const std::wstring &text) { this->text = text; }