From b2f6a0235c5de32a3fcd359e28f4d1e3bd6950df Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 4 May 2018 23:12:54 +0200 Subject: Add web page preview (image or html content), not finished --- src/Text.cpp | 129 ++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 106 insertions(+), 23 deletions(-) (limited to 'src/Text.cpp') diff --git a/src/Text.cpp b/src/Text.cpp index c433ddc..bc23235 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -1,6 +1,7 @@ #include "../include/Text.hpp" #include "../include/Cache.hpp" #include "../include/Gif.hpp" +#include "../include/WebPagePreview.hpp" #include #include @@ -10,6 +11,7 @@ namespace dchat const float EMOJI_PADDING = 5.0f; const float EMOJI_SCALE_WITH_TEXT = 1.7f; const float EMOJI_SCALE_STANDALONE = 5.0f; + const float IMAGE_HEIGHT_SCALE = 15.0f; const sf::Color URL_COLOR(15, 192, 252); @@ -40,7 +42,6 @@ namespace dchat { setString(_str); } - void Text::setString(const sf::String &str) { if(str != this->str) @@ -101,7 +102,7 @@ namespace dchat void Text::setLineSpacing(float lineSpacing) { - if(lineSpacing != this->lineSpacing) + if(fabs(lineSpacing - this->lineSpacing) > 0.001f) { this->lineSpacing = lineSpacing; dirty = true; @@ -414,8 +415,22 @@ namespace dchat glyphPos.x += glyph.advance; } + + if(textElement.type != TextElement::Type::TEXT) + { + prevCodePoint = 0; + } + + if(textElement.type == TextElement::Type::URL) + { + glyphPos.y += vspace + lineSpacing; + textElement.position.y = glyphPos.y; + + glyphPos.x = 0.0f; + glyphPos.y += floor(vspace * IMAGE_HEIGHT_SCALE) + lineSpacing; + } } - totalHeight = glyphPos.y + lineSpacing + vspace; + totalHeight = glyphPos.y + vspace + lineSpacing; } void Text::draw(sf::RenderTarget &target, Cache &cache) @@ -447,43 +462,111 @@ namespace dchat { if(textElement.type == TextElement::Type::EMOJI) { + float emojiSize = vspace * (textElement.ownLine ? EMOJI_SCALE_STANDALONE : EMOJI_SCALE_WITH_TEXT); + sf::Vector2f pos = position; pos += textElement.position; pos.x = floor(pos.x); pos.y = floor(pos.y); - float emojiSize = vspace * (textElement.ownLine ? EMOJI_SCALE_STANDALONE : EMOJI_SCALE_WITH_TEXT); sf::Vector2f size(emojiSize, emojiSize); // TODO: Optimize this (add unordered_map that takes StringViewUtf32 as key) auto u8Str = sf::String::fromUtf32(textElement.text.data, textElement.text.data + textElement.text.size).toUtf8(); const std::string &utf8Str = *(std::basic_string*)&u8Str; - const ImageByUrlResult imageByUrlResult = cache.getImageByUrl(utf8Str); - if(imageByUrlResult.type == ImageByUrlResult::Type::CACHED) + const ContentByUrlResult contentByUrlResult = cache.getContentByUrl(utf8Str); + if(contentByUrlResult.type == ContentByUrlResult::Type::CACHED) { - if(imageByUrlResult.isGif) + switch(contentByUrlResult.cachedType) { - auto gifSize = imageByUrlResult.gif->getSize(); - float widthToHeightRatio = (float)gifSize.x / (float)gifSize.y; - - imageByUrlResult.gif->setPosition(pos); - imageByUrlResult.gif->setScale(sf::Vector2f(size.x / (float)gifSize.x * widthToHeightRatio, size.y / (float)gifSize.y)); - imageByUrlResult.gif->draw(target); + case ContentByUrlResult::CachedType::GIF: + { + auto gifSize = contentByUrlResult.gif->getSize(); + float widthToHeightRatio = (float)gifSize.x / (float)gifSize.y; + + contentByUrlResult.gif->setPosition(pos); + contentByUrlResult.gif->setScale(sf::Vector2f(size.x / (float)gifSize.x * widthToHeightRatio, size.y / (float)gifSize.y)); + contentByUrlResult.gif->draw(target); + break; + } + case ContentByUrlResult::CachedType::TEXTURE: + { + auto textureSize = contentByUrlResult.texture->getSize(); + float widthToHeightRatio = (float)textureSize.x / (float)textureSize.y; + + // TODO: Store this sprite somewhere, might not be efficient to create a new sprite object every frame + sf::Sprite sprite(*contentByUrlResult.texture); + sprite.setPosition(pos); + sprite.setScale(size.x / (float)textureSize.x * widthToHeightRatio, size.y / (float)textureSize.y); + target.draw(sprite); + break; + } + default: + // Ignore html in emoji.... + break; } - else + } + else + { + sf::RectangleShape rect(size); + rect.setFillColor(sf::Color::White); + rect.setPosition(pos); + target.draw(rect); + } + } + else if(textElement.type == TextElement::Type::URL) + { + sf::Vector2f pos = position; + pos.y += floor(textElement.position.y); + float imageHeight = floor(vspace * IMAGE_HEIGHT_SCALE); + + // TODO: Optimize this (add unordered_map that takes StringViewUtf32 as key) + auto u8Str = sf::String::fromUtf32(textElement.text.data, textElement.text.data + textElement.text.size).toUtf8(); + const std::string &utf8Str = *(std::basic_string*)&u8Str; + const ContentByUrlResult contentByUrlResult = cache.getContentByUrl(utf8Str); + if(contentByUrlResult.type == ContentByUrlResult::Type::CACHED) + { + switch(contentByUrlResult.cachedType) { - auto textureSize = imageByUrlResult.texture->getSize(); - float widthToHeightRatio = (float)textureSize.x / (float)textureSize.y; - - // TODO: Store this sprite somewhere, might not be efficient to create a new sprite object every frame - sf::Sprite sprite(*imageByUrlResult.texture); - sprite.setPosition(pos); - sprite.setScale(size.x / (float)textureSize.x * widthToHeightRatio, size.y / (float)textureSize.y); - target.draw(sprite); + case ContentByUrlResult::CachedType::GIF: + { + auto gifSize = contentByUrlResult.gif->getSize(); + float widthToHeightRatio = (float)gifSize.x / (float)gifSize.y; + + contentByUrlResult.gif->setPosition(pos); + contentByUrlResult.gif->setScale(sf::Vector2f(imageHeight / (float)gifSize.x * widthToHeightRatio, imageHeight / (float)gifSize.y)); + contentByUrlResult.gif->draw(target); + break; + } + case ContentByUrlResult::CachedType::TEXTURE: + { + auto textureSize = contentByUrlResult.texture->getSize(); + float widthToHeightRatio = (float)textureSize.x / (float)textureSize.y; + + // TODO: Store this sprite somewhere, might not be efficient to create a new sprite object every frame + sf::Sprite sprite(*contentByUrlResult.texture); + sprite.setPosition(pos); + sprite.setScale(imageHeight / (float)textureSize.x * widthToHeightRatio, imageHeight / (float)textureSize.y); + target.draw(sprite); + break; + } + case ContentByUrlResult::CachedType::WEB_PAGE_PREVIEW: + { + const float previewWidth = floor(imageHeight * 1.77f); + + // No need to perform culling here, that is done in @Text draw function + contentByUrlResult.webPagePreview->title.setCharacterSize(characterSize); + contentByUrlResult.webPagePreview->title.setMaxWidth(previewWidth); + contentByUrlResult.webPagePreview->title.setPosition(pos); + contentByUrlResult.webPagePreview->title.setLineSpacing(0.0f); + contentByUrlResult.webPagePreview->title.setFillColor(URL_COLOR); + contentByUrlResult.webPagePreview->title.draw(target, cache); + break; + } } } else { - sf::RectangleShape rect(size); + sf::RectangleShape rect(sf::Vector2f(imageHeight, imageHeight)); rect.setFillColor(sf::Color::White); rect.setPosition(pos); target.draw(rect); -- cgit v1.2.3