From 79925e07d6e57f5c5cbf557fe773fb92b4bb9549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B6=93=E2=82=AC=E7=BB=BE=E8=B7=A8=E4=BC=92=7CDeal?= Date: Tue, 4 Oct 2022 11:08:49 +0800 Subject: [PATCH] Merge: 6cd36ab02e c26ab44880 Merge pull request #801 from theunwisewolf/dev-richtext-scale-support RichElementImage - Add support for scaling --- core/ui/UIRichText.cpp | 91 +++++++++++++++---- core/ui/UIRichText.h | 11 ++- .../UIRichTextTest/UIRichTextTest.cpp | 14 ++- 3 files changed, 96 insertions(+), 20 deletions(-) diff --git a/core/ui/UIRichText.cpp b/core/ui/UIRichText.cpp index 5103a13d75..ff64e61375 100644 --- a/core/ui/UIRichText.cpp +++ b/core/ui/UIRichText.cpp @@ -454,30 +454,73 @@ MyXMLVisitor::MyXMLVisitor(RichText* richText) : _fontElements(20), _richText(ri MyXMLVisitor::setTagDescription("img", false, [](const ValueMap& tagAttrValueMap) { // supported attributes: - // src, height, width + // src, height, width, scaleX, scaleY, scale std::string src; int height = -1; int width = -1; + float scaleX = 1.f; + float scaleY = 1.f; Widget::TextureResType resType = Widget::TextureResType::LOCAL; - if (tagAttrValueMap.find("src") != tagAttrValueMap.end()) + auto it = tagAttrValueMap.find("src"); + if (it != tagAttrValueMap.end()) { - src = tagAttrValueMap.at("src").asString(); + src = it->second.asString(); } - if (tagAttrValueMap.find("height") != tagAttrValueMap.end()) + + it = tagAttrValueMap.find("height"); + if (it != tagAttrValueMap.end()) { - height = tagAttrValueMap.at("height").asInt(); + auto str = it->second.asStringRef(); + if (!str.empty() && str[str.length() - 1] == '%') + { + scaleY = std::atoi(str.data()) / 100.f; + } + else + { + height = it->second.asInt(); + } } - if (tagAttrValueMap.find("width") != tagAttrValueMap.end()) + + it = tagAttrValueMap.find("width"); + if (it != tagAttrValueMap.end()) { - width = tagAttrValueMap.at("width").asInt(); + auto str = it->second.asStringRef(); + if (!str.empty() && str[str.length() - 1] == '%') + { + scaleX = std::atoi(str.data()) / 100.f; + } + else + { + width = it->second.asInt(); + } } - if (tagAttrValueMap.find("type") != tagAttrValueMap.end()) + + it = tagAttrValueMap.find("scaleX"); + if (it != tagAttrValueMap.end()) + { + scaleX = it->second.asFloat(); + } + + it = tagAttrValueMap.find("scaleY"); + if (it != tagAttrValueMap.end()) + { + scaleY = it->second.asFloat(); + } + + it = tagAttrValueMap.find("scale"); + if (it != tagAttrValueMap.end()) + { + scaleX = scaleY = it->second.asFloat(); + } + + it = tagAttrValueMap.find("type"); + if (it != tagAttrValueMap.end()) { // texture type // 0: normal file path // 1: sprite frame name - int type = tagAttrValueMap.at("type").asInt(); + int type = it->second.asInt(); resType = type == 0 ? Widget::TextureResType::LOCAL : Widget::TextureResType::PLIST; } @@ -485,10 +528,13 @@ MyXMLVisitor::MyXMLVisitor(RichText* richText) : _fontElements(20), _richText(ri if (src.length()) { elementImg = RichElementImage::create(0, Color3B::WHITE, 255, src, "", resType); - if (0 <= height) + if (height >= 0) elementImg->setHeight(height); - if (0 <= width) + if (width >= 0) elementImg->setWidth(width); + + elementImg->setScaleX(scaleX); + elementImg->setScaleY(scaleY); } return make_pair(ValueMap(), elementImg); }); @@ -1462,7 +1508,7 @@ void RichText::openUrl(std::string_view url) { _handleOpenUrl(url); } - else + else if (!url.empty()) { Application::getInstance()->openURL(url); } @@ -1542,9 +1588,15 @@ void RichText::formatText(bool force) { auto currentSize = elementRenderer->getContentSize(); if (elmtImage->_width != -1) - elementRenderer->setScaleX(elmtImage->_width / currentSize.width); + elementRenderer->setScaleX((elmtImage->_width / currentSize.width) * elmtImage->_scaleX); + else + elementRenderer->setScaleX(elmtImage->_scaleX); + if (elmtImage->_height != -1) - elementRenderer->setScaleY(elmtImage->_height / currentSize.height); + elementRenderer->setScaleY((elmtImage->_height / currentSize.height) * elmtImage->_scaleY); + else + elementRenderer->setScaleY(elmtImage->_scaleY); + elementRenderer->setContentSize(Vec2(currentSize.width * elementRenderer->getScaleX(), currentSize.height * elementRenderer->getScaleY())); elementRenderer->addComponent( @@ -1598,7 +1650,8 @@ void RichText::formatText(bool force) { RichElementImage* elmtImage = static_cast(element); handleImageRenderer(elmtImage->_filePath, elmtImage->_textureType, elmtImage->_color, - elmtImage->_opacity, elmtImage->_width, elmtImage->_height, elmtImage->_url); + elmtImage->_opacity, elmtImage->_width, elmtImage->_height, elmtImage->_url, + elmtImage->_scaleX, elmtImage->_scaleY); break; } case RichElement::Type::CUSTOM: @@ -1891,7 +1944,9 @@ void RichText::handleImageRenderer(std::string_view filePath, uint8_t /*opacity*/, int width, int height, - std::string_view url) + std::string_view url, + float scaleX, + float scaleY) { Sprite* imageRenderer; if (textureType == Widget::TextureResType::LOCAL) @@ -1906,6 +1961,10 @@ void RichText::handleImageRenderer(std::string_view filePath, imageRenderer->setScaleX(width / currentSize.width); if (height != -1) imageRenderer->setScaleY(height / currentSize.height); + + imageRenderer->setScaleX(imageRenderer->getScaleX() * scaleX); + imageRenderer->setScaleY(imageRenderer->getScaleY() * scaleY); + imageRenderer->setContentSize( Vec2(currentSize.width * imageRenderer->getScaleX(), currentSize.height * imageRenderer->getScaleY())); imageRenderer->setScale(1.f, 1.f); diff --git a/core/ui/UIRichText.h b/core/ui/UIRichText.h index 8cac99f88d..bdc4a2a262 100644 --- a/core/ui/UIRichText.h +++ b/core/ui/UIRichText.h @@ -268,6 +268,9 @@ public: void setWidth(int width); void setHeight(int height); + inline void setScale(float scale) { _scaleX = _scaleY = scale; } + inline void setScaleX(float scaleX) { _scaleX = scaleX; } + inline void setScaleY(float scaleY) { _scaleY = scaleY; } void setUrl(std::string_view url); protected: @@ -277,6 +280,8 @@ protected: friend class RichText; int _width; int _height; + float _scaleX; + float _scaleY; std::string _url; /*!< attributes of anchor tag */ }; @@ -527,7 +532,7 @@ public: std::string getFontFace(); /*!< return the current font face */ void setAnchorFontColor(std::string_view color); /*!< Set the font color of a-tag. @param face the font color. */ std::string getAnchorFontColor(); /*!< return the current font color of a-tag */ - ax::Color3B getAnchorFontColor3B(); /*!< return the current font color of a-tag */ + ax::Color3B getAnchorFontColor3B(); /*!< return the current font color of a-tag */ void setAnchorTextBold(bool enable); /*!< enable bold text of a-tag */ bool isAnchorTextBoldEnabled(); /*!< valid style is bold text of a-tag? */ void setAnchorTextItalic(bool enable); /*!< enable italic text of a-tag */ @@ -613,7 +618,9 @@ protected: uint8_t opacity, int width, int height, - std::string_view url); + std::string_view url, + float scaleX = 1.f, + float scaleY = 1.f); void handleCustomRenderer(Node* renderer); void formatRenderers(); void addNewLine(); diff --git a/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UIRichTextTest/UIRichTextTest.cpp b/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UIRichTextTest/UIRichTextTest.cpp index cf9401dd16..dea8aa9e39 100644 --- a/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UIRichTextTest/UIRichTextTest.cpp +++ b/tests/cpp-tests/Classes/UITest/CocoStudioGUITest/UIRichTextTest/UIRichTextTest.cpp @@ -878,11 +878,21 @@ bool UIRichTextXMLImg::init() // RichText _richText = RichText::createWithXML( - "you should see an image here: and this is text again. and this " - "is the same image, but bigger: and here " + "Image: and this is text again." + "Image with width/height: and " + "Image with scaleX/scaleY: and " + "Image with width%/height%: and " + "Image with empty width/height%: and " + "Image with scale: and " + "Image with w/h/sX/sY: and " "goes text again"); _richText->ignoreContentAdaptWithSize(false); + +#ifdef AX_PLATFORM_PC + _richText->setContentSize(Size(290, 290)); +#else _richText->setContentSize(Size(100, 100)); +#endif _richText->setPosition(Vec2(widgetSize.width / 2, widgetSize.height / 2)); _richText->setLocalZOrder(10);