/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ //////////////////////////////////////////////////////////////////////////////////////////////////// #if defined(LYSHINE_INTERNAL_UNIT_TEST) #include #include namespace { bool IsClose(float value1, float value2, float epsilon = 0.0001f) { return fabsf(value1 - value2) < epsilon; } using FontList = AZStd::list < IFFont * >; void AssertTextNotEmpty(const AZStd::list& drawBatches) { for (const UiTextComponent::DrawBatch& drawBatch : drawBatches) { AZ_Assert(!drawBatch.text.empty(), "Test failed"); } } void AssertDrawBatchFontOrder( const AZStd::list& drawBatches, const FontList& fontList) { AZ_Assert(drawBatches.size() == fontList.size(), "Test failed"); auto drawBatchIt = drawBatches.begin(); auto fontsIt = fontList.begin(); for (; drawBatchIt != drawBatches.end(); ++drawBatchIt, ++fontsIt) { const UiTextComponent::DrawBatch& drawBatch = *drawBatchIt; const IFFont* font = *fontsIt; AZ_Assert(drawBatch.font == font, "Test failed"); } } void AssertDrawBatchSingleColor( const AZStd::list& drawBatches, const AZ::Vector3& color) { auto drawBatchIt = drawBatches.begin(); for (; drawBatchIt != drawBatches.end(); ++drawBatchIt) { const UiTextComponent::DrawBatch& drawBatch = *drawBatchIt; AZ_Assert(drawBatch.color == color, "Test failed"); } } using ColorList = AZStd::list < AZ::Vector3 >; void AssertDrawBatchMultiColor( const AZStd::list& drawBatches, const ColorList& colorList) { auto drawBatchIt = drawBatches.begin(); auto colorIt = colorList.begin(); for (; drawBatchIt != drawBatches.end(); ++drawBatchIt, ++colorIt) { const UiTextComponent::DrawBatch& drawBatch = *drawBatchIt; const AZ::Vector3& color(*colorIt); AZ_Assert(drawBatch.color == color, "Test failed"); } } using StringList = AZStd::list < LyShine::StringType >; void AssertDrawBatchTextContent( const AZStd::list& drawBatches, const StringList& stringList) { AZ_Assert(drawBatches.size() == stringList.size(), "Test failed"); auto drawBatchIt = drawBatches.begin(); auto stringIt = stringList.begin(); for (; drawBatchIt != drawBatches.end(); ++drawBatchIt, ++stringIt) { const UiTextComponent::DrawBatch& drawBatch = *drawBatchIt; const LyShine::StringType& text = *stringIt; AZ_Assert(drawBatch.text == text, "Test failed"); } } void AssertDrawBatchTextNumNewlines( const AZStd::list& drawBatches, const int numNewlines) { int numNewlinesFound = 0; auto drawBatchIt = drawBatches.begin(); for (; drawBatchIt != drawBatches.end(); ++drawBatchIt) { const UiTextComponent::DrawBatch& drawBatch = *drawBatchIt; numNewlinesFound += static_cast(AZStd::count_if(drawBatch.text.begin(), drawBatch.text.end(), [](char c) -> bool { return c == '\n'; })); } AZ_Assert(numNewlines == numNewlinesFound, "Test failed"); } FontFamilyPtr FontFamilyLoad(const char* fontFamilyFilename) { FontFamilyPtr fontFamily = gEnv->pCryFont->GetFontFamily(fontFamilyFilename); if (!fontFamily) { fontFamily = gEnv->pCryFont->LoadFontFamily(fontFamilyFilename); AZ_Assert(gEnv->pCryFont->GetFontFamily(fontFamilyFilename).get(), "Test failed"); } // We need the font family to load correctly in order to test properly AZ_Assert(fontFamily.get(), "Test failed"); return fontFamily; } //! \brief Verify fonts that ship with Lumberyard load correctly. //! //! This test depends on the LyShineExamples and UiBasics gems being //! included in the project. //! //! There are other fonts that ship in other projects (SamplesProject, //! FeatureTests), but that would call for project-specific unit-tests //! which don't belong here. void VerifyShippingFonts() { FontFamilyLoad("ui/fonts/lyshineexamples/notosans/notosans.fontfamily"); FontFamilyLoad("ui/fonts/lyshineexamples/notoserif/notoserif.fontfamily"); FontFamilyLoad("fonts/vera.fontfamily"); } void NewlineSanitizeTests() { { AZStd::string inputString("Test\\nHi"); SanitizeUserEnteredNewlineChar(inputString); const AZStd::string expectedOutput("Test\nHi"); AZ_Assert(expectedOutput == inputString, "Test failed"); // Sanity check that AZStd::regex and std::regex are functionally equivalent. { const std::string NewlineDelimiter("\n"); const std::regex UserInputNewlineDelimiter("\\\\n"); std::string inputStringCopy("Test\\nHi"); inputStringCopy = std::regex_replace(inputStringCopy, UserInputNewlineDelimiter, NewlineDelimiter); AZ_Assert(inputStringCopy == std::string(inputString.c_str()), "Test failed"); AZ_Assert(AZStd::string(inputStringCopy.c_str()) == inputString, "Test failed"); } } } void BuildDrawBatchesTests(FontFamily* fontFamily) { UiTextComponent::InlineImageContainer inlineImages; const float defaultImageHeight = 32.0f; STextDrawContext fontContext; fontContext.SetEffect(0); fontContext.SetSizeIn800x600(false); fontContext.SetSize(vector2f(32.0f, 32.0f)); const float defaultAscent = fontFamily->normal->GetAscender(fontContext); // Plain string { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(1 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); FontList fontList; fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); AssertDrawBatchSingleColor(drawBatches, TextMarkup::ColorInvalid); } } // Plain string: newline { const LyShine::StringType markupTestString("Regular Bold Italic\n"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(1 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); FontList fontList; fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); AssertDrawBatchSingleColor(drawBatches, TextMarkup::ColorInvalid); } } // Single bold { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); FontList fontList; fontList.push_back(fontFamily->bold); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); AssertDrawBatchSingleColor(drawBatches, TextMarkup::ColorInvalid); } } // Single italic { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); FontList fontList; fontList.push_back(fontFamily->italic); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); AssertDrawBatchSingleColor(drawBatches, TextMarkup::ColorInvalid); } } // Bold-italic { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); FontList fontList; fontList.push_back(fontFamily->boldItalic); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); AssertDrawBatchSingleColor(drawBatches, TextMarkup::ColorInvalid); } } // Anchor tag { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); auto drawBatchIter = drawBatches.begin(); const auto& drawBatch = *drawBatchIter; AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action", "Test failed"); AZ_Assert(drawBatch.data == "data", "Test failed"); AZ_Assert(drawBatch.clickableId == 0, "Test failed"); ++drawBatchIter; const auto& nextDrawBatch = *drawBatchIter; AZ_Assert(!nextDrawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(nextDrawBatch.action.empty(), "Test failed"); AZ_Assert(nextDrawBatch.data.empty(), "Test failed"); AZ_Assert(nextDrawBatch.clickableId == -1, "Test failed"); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Anchor tag: multiple anchor tags { const LyShine::StringType markupTestString( "this" " is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(4 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); auto batchIter = drawBatches.begin(); { const auto& drawBatch = *(batchIter++); AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action1", "Test failed"); AZ_Assert(drawBatch.data == "data1", "Test failed"); AZ_Assert(drawBatch.clickableId == 0, "Test failed"); } { const auto& drawBatch = *(batchIter++); AZ_Assert(!drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action.empty(), "Test failed"); AZ_Assert(drawBatch.data.empty(), "Test failed"); AZ_Assert(drawBatch.clickableId == -1, "Test failed"); } { const auto& drawBatch = *(batchIter++); AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action2", "Test failed"); AZ_Assert(drawBatch.data == "data2", "Test failed"); AZ_Assert(drawBatch.clickableId == 1, "Test failed"); } { const auto& drawBatch = *(batchIter++); AZ_Assert(!drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action.empty(), "Test failed"); AZ_Assert(drawBatch.data.empty(), "Test failed"); AZ_Assert(drawBatch.clickableId == -1, "Test failed"); } StringList stringList; stringList.push_back("this"); stringList.push_back(" is a "); stringList.push_back("test"); stringList.push_back("!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } { const LyShine::StringType markupTestString( "this" " is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); auto batchIter = drawBatches.begin(); { const auto& drawBatch = *(batchIter++); AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action1", "Test failed"); AZ_Assert(drawBatch.data == "data1", "Test failed"); AZ_Assert(drawBatch.clickableId == 0, "Test failed"); } { const auto& drawBatch = *(batchIter++); AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action2", "Test failed"); AZ_Assert(drawBatch.data == "data2", "Test failed"); AZ_Assert(drawBatch.clickableId == 1, "Test failed"); } StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } { const LyShine::StringType markupTestString( "this is " "a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(3 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); auto batchIter = drawBatches.begin(); { const auto& drawBatch = *(batchIter++); AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action1", "Test failed"); AZ_Assert(drawBatch.data == "data1", "Test failed"); AZ_Assert(drawBatch.clickableId == 0, "Test failed"); } { const auto& drawBatch = *(batchIter++); AZ_Assert(!drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action.empty(), "Test failed"); AZ_Assert(drawBatch.data.empty(), "Test failed"); AZ_Assert(drawBatch.clickableId == -1, "Test failed"); } { const auto& drawBatch = *(batchIter++); AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action2", "Test failed"); AZ_Assert(drawBatch.data == "data2", "Test failed"); AZ_Assert(drawBatch.clickableId == 1, "Test failed"); } StringList stringList; stringList.push_back("this"); stringList.push_back(" is "); stringList.push_back("a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->bold); fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Anchor tag with link color applied via markup { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); auto batchIter = drawBatches.begin(); { const auto& drawBatch = *(batchIter++); AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action", "Test failed"); AZ_Assert(drawBatch.data == "data", "Test failed"); AZ_Assert(drawBatch.clickableId == 0, "Test failed"); } { const auto& drawBatch = *(batchIter++); AZ_Assert(!drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action.empty(), "Test failed"); AZ_Assert(drawBatch.data.empty(), "Test failed"); AZ_Assert(drawBatch.clickableId == -1, "Test failed"); } StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(AZ::Vector3(1.0f, 0.0f, 0.0f)); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Anchor tag with multiple colors within link { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(3 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); // All drawbatches should have the same clickable ID since there's only one link that // encompasses all of the text. for (auto& drawBatch : drawBatches) { AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action", "Test failed"); AZ_Assert(drawBatch.data == "data", "Test failed"); AZ_Assert(drawBatch.clickableId == 0, "Test failed"); } StringList stringList; stringList.push_back("this "); stringList.push_back("is"); stringList.push_back(" a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(AZ::Vector3(1.0f, 0.0f, 0.0f)); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Multiple anchor tags with link colors applied within markup { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(5 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); auto batchIter = drawBatches.begin(); { const auto& drawBatch = *(batchIter++); AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action1", "Test failed"); AZ_Assert(drawBatch.data == "data1", "Test failed"); AZ_Assert(drawBatch.clickableId == 0, "Test failed"); } { const auto& drawBatch = *(batchIter++); AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action1", "Test failed"); AZ_Assert(drawBatch.data == "data1", "Test failed"); AZ_Assert(drawBatch.clickableId == 0, "Test failed"); } { const auto& drawBatch = *(batchIter++); AZ_Assert(!drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action.empty(), "Test failed"); AZ_Assert(drawBatch.data.empty(), "Test failed"); AZ_Assert(drawBatch.clickableId == -1, "Test failed"); } { const auto& drawBatch = *(batchIter++); AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action2", "Test failed"); AZ_Assert(drawBatch.data == "data2", "Test failed"); AZ_Assert(drawBatch.clickableId == 1, "Test failed"); } { const auto& drawBatch = *(batchIter++); AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action2", "Test failed"); AZ_Assert(drawBatch.data == "data2", "Test failed"); AZ_Assert(drawBatch.clickableId == 1, "Test failed"); } StringList stringList; stringList.push_back("this "); stringList.push_back("is"); stringList.push_back(" a "); stringList.push_back("te"); stringList.push_back("st!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(AZ::Vector3(1.0f, 0.0f, 0.0f)); colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(AZ::Vector3(1.0f, 0.0f, 0.0f)); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font face { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(1 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontFamilyPtr notoSerifFamily = gEnv->pCryFont->GetFontFamily("notoserif"); AZ_Assert(notoSerifFamily, "Test failed"); FontList fontList; fontList.push_back(notoSerifFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font face (different font) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(1 == fontFamilyRefs.size(), "Test failed", "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed", "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontFamilyPtr notoSansFamily = gEnv->pCryFont->GetFontFamily("notosans"); AZ_Assert(notoSansFamily, "Test failed"); FontList fontList; fontList.push_back(notoSansFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font face (leading space) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(1 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontFamilyPtr notoSansFamily = gEnv->pCryFont->GetFontFamily("notosans"); AZ_Assert(notoSansFamily, "Test failed"); FontList fontList; fontList.push_back(notoSansFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font face (trailing space) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(1 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontFamilyPtr notoSansFamily = gEnv->pCryFont->GetFontFamily("notosans"); AZ_Assert(notoSansFamily, "Test failed"); FontList fontList; fontList.push_back(notoSansFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font face (leading and trailing space) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(1 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontFamilyPtr notoSansFamily = gEnv->pCryFont->GetFontFamily("notosans"); AZ_Assert(notoSansFamily, "Test failed"); FontList fontList; fontList.push_back(notoSansFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font face ("pass-through" font) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(1 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontFamilyPtr defaultUiFamily = gEnv->pCryFont->GetFontFamily("default-ui"); AZ_Assert(defaultUiFamily, "Test failed"); FontList fontList; fontList.push_back(defaultUiFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font face (invalid font) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font face (invalid empty string) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font color (red, lower case) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(AZ::Vector3(1.0f, 0.0f, 0.0f)); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font color (red, upper case) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(AZ::Vector3(1.0f, 0.0f, 0.0f)); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font color (red, mixed case) 1 { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(AZ::Vector3(1.0f, 0.0f, 0.0f)); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font color (red, mixed case) 2 { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(AZ::Vector3(1.0f, 0.0f, 0.0f)); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font color (red, upper case, leading space) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(AZ::Vector3(1.0f, 0.0f, 0.0f)); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font color (red, upper case, trailing space) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(AZ::Vector3(1.0f, 0.0f, 0.0f)); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font color (red, upper case, leading and trailing space) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(AZ::Vector3(1.0f, 0.0f, 0.0f)); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font color (green, upper case) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(AZ::Vector3(0.0f, 1.0f, 0.0f)); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font color (blue, upper case) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(AZ::Vector3(0.0f, 0.0f, 1.0f)); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font color (invalid hex value) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(AZ::Vector3(0.0f, 0.0f, 0.0f)); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font color (invalid hex value) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font color (invalid formatting) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font color (invalid formatting) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font color (invalid value, empty string) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font color (invalid value, empty string, spaces) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font color (invalid value, leading hash, empty following) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font color (invalid value, leading spaces with hash) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font color (invalid value, trailing spaces with hash) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font color (invalid value, leading and trailing spaces with hash) { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font face and color { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(1 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontFamilyPtr notoSerifFamily = gEnv->pCryFont->GetFontFamily("notoserif"); AZ_Assert(notoSerifFamily, "Test failed"); FontList fontList; fontList.push_back(notoSerifFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(AZ::Vector3(1.0f, 0.0f, 0.0f)); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: font color and face { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(1 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); AssertDrawBatchTextContent(drawBatches, stringList); FontFamilyPtr notoSerifFamily = gEnv->pCryFont->GetFontFamily("notoserif"); AZ_Assert(notoSerifFamily, "Test failed"); FontList fontList; fontList.push_back(notoSerifFamily->normal); fontList.push_back(fontFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(AZ::Vector3(1.0f, 0.0f, 0.0f)); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Font tag: invalid attribute { const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(false == TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); } } // Mixed test: Bold, italic, bold-italic { const LyShine::StringType markupTestString("Regular Bold Italic\nBold-Italic"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(5 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("Regular "); stringList.push_back("Bold"); stringList.push_back(" "); stringList.push_back("Italic\n"); stringList.push_back("Bold-Italic"); AssertDrawBatchTextContent(drawBatches, stringList); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->bold); fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->italic); fontList.push_back(fontFamily->boldItalic); AssertDrawBatchFontOrder(drawBatches, fontList); AssertDrawBatchSingleColor(drawBatches, TextMarkup::ColorInvalid); } } // Mixed test: Font color, font face, bold { const LyShine::StringType markupTestString("Regular Bold"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(1 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("Regular "); stringList.push_back("Bold"); AssertDrawBatchTextContent(drawBatches, stringList); FontFamilyPtr notoSerifFamily = gEnv->pCryFont->GetFontFamily("notoserif"); AZ_Assert(notoSerifFamily, "Test failed"); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(notoSerifFamily->bold); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(AZ::Vector3(0.0f, 1.0f, 0.0f)); colorList.push_back(AZ::Vector3(0.0f, 1.0f, 0.0f)); AssertDrawBatchMultiColor(drawBatches, colorList); } } // Mixed test: Multiple font faces, color, bold { const LyShine::StringType markupTestString("Regular Bold Italic Bold-Italic\nHere is default-ui"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(2 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(7 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("Regular "); stringList.push_back("Bold"); stringList.push_back(" "); stringList.push_back("Italic"); stringList.push_back(" Bold-Italic"); stringList.push_back("\nHere is "); stringList.push_back("default-ui"); AssertDrawBatchTextContent(drawBatches, stringList); FontFamilyPtr notoSerifFamily = gEnv->pCryFont->GetFontFamily("notoserif"); AZ_Assert(notoSerifFamily, "Test failed"); FontFamilyPtr defaultUiFamily = gEnv->pCryFont->GetFontFamily("default-ui"); AZ_Assert(notoSerifFamily, "Test failed"); FontList fontList; fontList.push_back(fontFamily->normal); fontList.push_back(notoSerifFamily->bold); fontList.push_back(fontFamily->normal); fontList.push_back(fontFamily->italic); fontList.push_back(fontFamily->boldItalic); fontList.push_back(fontFamily->normal); fontList.push_back(defaultUiFamily->normal); AssertDrawBatchFontOrder(drawBatches, fontList); ColorList colorList; colorList.push_back(AZ::Vector3(0.0f, 1.0f, 0.0f)); colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); colorList.push_back(TextMarkup::ColorInvalid); AssertDrawBatchMultiColor(drawBatches, colorList); } } } using SizeList = AZStd::list < size_t >; void AssertBatchLineSizes( const UiTextComponent::DrawBatchLines& batchLines, const SizeList& batchSizes) { AZ_Assert(batchLines.batchLines.size() == batchSizes.size(), "Test failed"); auto linesIt = batchLines.batchLines.begin(); auto sizesIt = batchSizes.begin(); for (; linesIt != batchLines.batchLines.end(); ++linesIt, ++sizesIt) { const UiTextComponent::DrawBatchContainer& batchLine = (*linesIt).drawBatchList; const size_t batchSize = *sizesIt; AZ_Assert(batchLine.size() == batchSize, "Test failed"); } } using DrawBatchLines = UiTextComponent::DrawBatchLines; using DrawBatchContainer = UiTextComponent::DrawBatchContainer; using DrawBatch = UiTextComponent::DrawBatch; void WrapTextTests(FontFamily* fontFamily) { UiTextComponent::InlineImageContainer inlineImages; const float defaultImageHeight = 32.0f; STextDrawContext fontContext; fontContext.SetEffect(0); fontContext.SetSizeIn800x600(false); fontContext.SetSize(vector2f(32.0f, 32.0f)); const float defaultAscent = fontFamily->normal->GetAscender(fontContext); { const LyShine::StringType testMarkup("Regular Bold Italic\n"); DrawBatchContainer drawBatches; DrawBatch b1; b1.font = fontFamily->normal; b1.text = testMarkup; drawBatches.push_back(b1); InsertNewlinesToWrapText(drawBatches, fontContext, 1000.0f); AZ_Assert(drawBatches.front().text == testMarkup, "Test failed"); } { // "Regular Bold v .Italic\nBold-Italic" StringList stringList; stringList.push_back("Regular Bold v ."); stringList.push_back("Italic\n"); stringList.push_back("Bold-Italic"); StringList::const_iterator citer = stringList.begin(); DrawBatchContainer drawBatches; DrawBatch b1; b1.font = fontFamily->normal; b1.text = *citer; ++citer; drawBatches.push_back(b1); DrawBatch b2; b2.font = fontFamily->italic; b2.text = *citer; ++citer; drawBatches.push_back(b2); DrawBatch b3; b3.font = fontFamily->normal; b3.text = *citer; ++citer; drawBatches.push_back(b3); InsertNewlinesToWrapText(drawBatches, fontContext, 1000.0f); AssertDrawBatchTextContent(drawBatches, stringList); } // Anchor tag: single line, no wrapping { const LyShine::StringType textNoMarkup("this is a test!"); const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); StringList stringList; stringList.push_back("this"); stringList.push_back(" is a test!"); // 1000.0f should be too big to cause any newlines to be inserted const float wrapWidth = 1000.0f; InsertNewlinesToWrapText(drawBatches, fontContext, wrapWidth); AssertDrawBatchTextContent(drawBatches, stringList); } // Anchor tag: word-wrap cases { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); // Element size 75% of text length should insert one newline const float textWidth = fontFamily->normal->GetTextSize(textNoMarkup.c_str(), true, fontContext).x; const float wrapWidth = textWidth * 0.75f; InsertNewlinesToWrapText(drawBatches, fontContext, wrapWidth); const int numNewlines = 1; AssertDrawBatchTextNumNewlines(drawBatches, numNewlines); } { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); AZ_Assert(0 == fontFamilyRefs.size(), "Test failed"); AZ_Assert(2 == drawBatches.size(), "Test failed"); AssertTextNotEmpty(drawBatches); // Element size 45% of text length should insert two newlines const float textWidth = fontFamily->normal->GetTextSize(textNoMarkup.c_str(), true, fontContext).x; const float wrapWidth = textWidth * 0.45f; InsertNewlinesToWrapText(drawBatches, fontContext, wrapWidth); const int numNewlines = 2; AssertDrawBatchTextNumNewlines(drawBatches, numNewlines); } } } void BatchLinesTests(FontFamily* fontFamily) { STextDrawContext fontContext; fontContext.SetEffect(0); fontContext.SetSizeIn800x600(false); fontContext.SetSize(vector2f(32.0f, 32.0f)); UiTextComponent::InlineImageContainer inlineImages; float defaultImageHeight = 32.0f; const float defaultAscent = fontFamily->normal->GetAscender(fontContext); UiTextInterface::DisplayedTextFunction displayedTextFunction(DefaultDisplayedTextFunction); { DrawBatchLines batchLines; DrawBatchContainer drawBatches; DrawBatch b1; b1.font = fontFamily->normal; b1.text = "a"; drawBatches.push_back(b1); CreateBatchLines(batchLines, drawBatches, fontFamily); AZ_Assert(1 == batchLines.batchLines.size(), "Test failed"); SizeList sizeList; sizeList.push_back(1); AssertBatchLineSizes(batchLines, sizeList); } { DrawBatchLines batchLines; DrawBatchContainer drawBatches; DrawBatch b1; b1.font = fontFamily->normal; b1.text = "a\n"; drawBatches.push_back(b1); CreateBatchLines(batchLines, drawBatches, fontFamily); AZ_Assert(2 == batchLines.batchLines.size(), "Test failed"); SizeList sizeList; sizeList.push_back(1); sizeList.push_back(1); AssertBatchLineSizes(batchLines, sizeList); } { DrawBatchLines batchLines; DrawBatchContainer drawBatches; DrawBatch b1; b1.font = fontFamily->normal; b1.text = "a\nb"; drawBatches.push_back(b1); CreateBatchLines(batchLines, drawBatches, fontFamily); AZ_Assert(2 == batchLines.batchLines.size(), "Test failed"); SizeList sizeList; sizeList.push_back(1); sizeList.push_back(1); AssertBatchLineSizes(batchLines, sizeList); } { DrawBatchLines batchLines; DrawBatchContainer drawBatches; DrawBatch b1; b1.font = fontFamily->normal; b1.text = "a\n\nb"; drawBatches.push_back(b1); CreateBatchLines(batchLines, drawBatches, fontFamily); AZ_Assert(3 == batchLines.batchLines.size(), "Test failed"); SizeList sizeList; sizeList.push_back(1); sizeList.push_back(1); sizeList.push_back(1); AssertBatchLineSizes(batchLines, sizeList); } { DrawBatchLines batchLines; DrawBatchContainer drawBatches; DrawBatch b1; b1.font = fontFamily->normal; b1.text = "a\n\n\nb"; drawBatches.push_back(b1); CreateBatchLines(batchLines, drawBatches, fontFamily); AZ_Assert(4 == batchLines.batchLines.size(), "Test failed"); SizeList sizeList; sizeList.push_back(1); sizeList.push_back(1); sizeList.push_back(1); sizeList.push_back(1); AssertBatchLineSizes(batchLines, sizeList); } { DrawBatchLines batchLines; DrawBatchContainer drawBatches; DrawBatch b1; b1.font = fontFamily->normal; b1.text = "Regular Bold Italic\n"; drawBatches.push_back(b1); CreateBatchLines(batchLines, drawBatches, fontFamily); AZ_Assert(2 == batchLines.batchLines.size(), "Test failed"); SizeList sizeList; sizeList.push_back(1); sizeList.push_back(1); AssertBatchLineSizes(batchLines, sizeList); } { const LyShine::StringType markupTestString("Regular Bold ItalicBold-Italic"); TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); DrawBatchLines batchLines; BatchAwareWrapText(batchLines, drawBatches, fontFamily, fontContext, 290.0f); AZ_Assert(2 == batchLines.batchLines.size(), "Test failed"); SizeList sizeList; sizeList.push_back(1); sizeList.push_back(2); AssertBatchLineSizes(batchLines, sizeList); } { const LyShine::StringType markupTestString("Regular Bold Italic\nBold-Italic"); TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); DrawBatchLines batchLines; CreateBatchLines(batchLines, drawBatches, fontFamily); AZ_Assert(2 == batchLines.batchLines.size(), "Test failed"); SizeList sizeList; sizeList.push_back(4); sizeList.push_back(1); AssertBatchLineSizes(batchLines, sizeList); } // Anchor tag: word-wrap, anchor doesn't span multiple lines { const LyShine::StringType textNoMarkup("this is a test!"); const LyShine::StringType markupTestString("this is a test!"); { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); // 1000.0f should be too big to cause any newlines to be inserted const float wrapWidth = 1000.0f; InsertNewlinesToWrapText(drawBatches, fontContext, wrapWidth); DrawBatchLines batchLines; CreateBatchLines(batchLines, drawBatches, fontFamily); AZ_Assert(1 == batchLines.batchLines.size(), "Test failed"); SizeList sizeList; sizeList.push_back(2); AssertBatchLineSizes(batchLines, sizeList); } { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); // Element size 75% of text length should insert one newline const float textWidth = fontFamily->normal->GetTextSize(textNoMarkup.c_str(), true, fontContext).x; const float wrapWidth = textWidth * 0.75f; InsertNewlinesToWrapText(drawBatches, fontContext, wrapWidth); DrawBatchLines batchLines; CreateBatchLines(batchLines, drawBatches, fontFamily); AZ_Assert(2 == batchLines.batchLines.size(), "Test failed"); SizeList sizeList; sizeList.push_back(2); sizeList.push_back(1); AssertBatchLineSizes(batchLines, sizeList); } { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); // Element size 45% of text length should insert two newlines const float textWidth = fontFamily->normal->GetTextSize(textNoMarkup.c_str(), true, fontContext).x; const float wrapWidth = textWidth * 0.45f; InsertNewlinesToWrapText(drawBatches, fontContext, wrapWidth); DrawBatchLines batchLines; CreateBatchLines(batchLines, drawBatches, fontFamily); AZ_Assert(3 == batchLines.batchLines.size(), "Test failed"); SizeList sizeList; sizeList.push_back(2); sizeList.push_back(1); sizeList.push_back(1); AssertBatchLineSizes(batchLines, sizeList); } } // Anchor tag: word-wrap, single anchor spans multiple lines { const LyShine::StringType textNoMarkup("this is a test!"); const LyShine::StringType markupTestString("this is a test!"); // Sanity check: single-line case { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); // 1000.0f should be too big to cause any newlines to be inserted const float wrapWidth = 1000.0f; InsertNewlinesToWrapText(drawBatches, fontContext, wrapWidth); DrawBatchLines batchLines; CreateBatchLines(batchLines, drawBatches, fontFamily); AZ_Assert(1 == batchLines.batchLines.size(), "Test failed"); SizeList sizeList; sizeList.push_back(1); AssertBatchLineSizes(batchLines, sizeList); // Since a single anchor tag spans the entirety of the text, // we can just iterate over all drawbatches for all lines // and verify that the anchor tag information exists across // all drawbatch lines. for (auto& batchLine : batchLines.batchLines) { for (auto& drawBatch : batchLine.drawBatchList) { AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action", "Test failed"); AZ_Assert(drawBatch.data == "data", "Test failed"); AZ_Assert(drawBatch.clickableId == 0, "Test failed"); } } } // Verify that anchor tag on word-wrapped text expands to both lines { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); // Element size 75% of text length should insert one newline const float textWidth = fontFamily->normal->GetTextSize(textNoMarkup.c_str(), true, fontContext).x; const float wrapWidth = textWidth * 0.75f; InsertNewlinesToWrapText(drawBatches, fontContext, wrapWidth); DrawBatchLines batchLines; CreateBatchLines(batchLines, drawBatches, fontFamily); AZ_Assert(2 == batchLines.batchLines.size(), "Test failed"); SizeList sizeList; sizeList.push_back(1); sizeList.push_back(1); AssertBatchLineSizes(batchLines, sizeList); // Since a single anchor tag spans the entirety of the text, // we can just iterate over all drawbatches for all lines // and verify that the anchor tag information exists across // all drawbatch lines. for (auto& batchLine : batchLines.batchLines) { for (auto& drawBatch : batchLine.drawBatchList) { AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action", "Test failed"); AZ_Assert(drawBatch.data == "data", "Test failed"); AZ_Assert(drawBatch.clickableId == 0, "Test failed"); } } } { TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); // Element size 45% of text length should insert two newlines const float textWidth = fontFamily->normal->GetTextSize(textNoMarkup.c_str(), true, fontContext).x; const float wrapWidth = textWidth * 0.45f; InsertNewlinesToWrapText(drawBatches, fontContext, wrapWidth); DrawBatchLines batchLines; CreateBatchLines(batchLines, drawBatches, fontFamily); AZ_Assert(3 == batchLines.batchLines.size(), "Test failed"); SizeList sizeList; sizeList.push_back(1); sizeList.push_back(1); sizeList.push_back(1); AssertBatchLineSizes(batchLines, sizeList); // Since a single anchor tag spans the entirety of the text, // we can just iterate over all drawbatches for all lines // and verify that the anchor tag information exists across // all drawbatch lines. for (auto& batchLine : batchLines.batchLines) { for (auto& drawBatch : batchLine.drawBatchList) { AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action", "Test failed"); AZ_Assert(drawBatch.data == "data", "Test failed"); AZ_Assert(drawBatch.clickableId == 0, "Test failed"); } } } } ///////////////////////////////////////////////////////////// // Anchor tag: word-wrap, multiple anchor spans multiple lines { { const LyShine::StringType textNoMarkup("this is a test!"); const LyShine::StringType markupTestString( "this is a test" "!" ); TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); // Element size 75% of text length should insert one newline const float textWidth = fontFamily->normal->GetTextSize(textNoMarkup.c_str(), true, fontContext).x; const float wrapWidth = textWidth * 0.75f; InsertNewlinesToWrapText(drawBatches, fontContext, wrapWidth); DrawBatchLines batchLines; CreateBatchLines(batchLines, drawBatches, fontFamily); AZ_Assert(2 == batchLines.batchLines.size(), "Test failed"); SizeList sizeList; sizeList.push_back(1); sizeList.push_back(2); AssertBatchLineSizes(batchLines, sizeList); auto batchLineIter = batchLines.batchLines.begin(); { const auto& batchLine = *batchLineIter; auto drawBatchIter = batchLine.drawBatchList.begin(); { const DrawBatch& drawBatch = *drawBatchIter; AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action1", "Test failed"); AZ_Assert(drawBatch.data == "data1", "Test failed"); AZ_Assert(drawBatch.clickableId == 0, "Test failed"); } } // Next line ++batchLineIter; { const auto& batchLine = *batchLineIter; auto drawBatchIter = batchLine.drawBatchList.begin(); { const DrawBatch& drawBatch = *drawBatchIter; AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action1", "Test failed"); AZ_Assert(drawBatch.data == "data1", "Test failed"); AZ_Assert(drawBatch.clickableId == 0, "Test failed"); } // Next batch ++drawBatchIter; { const DrawBatch& drawBatch = *drawBatchIter; AZ_Assert(drawBatch.text == "!", "Test failed"); AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action2", "Test failed"); AZ_Assert(drawBatch.data == "data2", "Test failed"); AZ_Assert(drawBatch.clickableId == 1, "Test failed"); } } } { const LyShine::StringType textNoMarkup("this is a test!"); const LyShine::StringType markupTestString( "t" "his is a test!" ); TextMarkup::Tag markupRoot; AZ_Assert(TextMarkup::ParseMarkupBuffer(markupTestString, markupRoot), "Test failed"); AZStd::list drawBatches; AZStd::stack batchStack; AZStd::stack fontFamilyStack; fontFamilyStack.push(fontFamily); UiTextComponent::FontFamilyRefSet fontFamilyRefs; BuildDrawBatchesAndAssignClickableIds(drawBatches, fontFamilyRefs, inlineImages, defaultImageHeight, defaultAscent, batchStack, fontFamilyStack, &markupRoot); // Element size 75% of text length should insert one newline const float textWidth = fontFamily->normal->GetTextSize(textNoMarkup.c_str(), true, fontContext).x; const float wrapWidth = textWidth * 0.75f; InsertNewlinesToWrapText(drawBatches, fontContext, wrapWidth); DrawBatchLines batchLines; CreateBatchLines(batchLines, drawBatches, fontFamily); AZ_Assert(2 == batchLines.batchLines.size(), "Test failed"); SizeList sizeList; sizeList.push_back(2); sizeList.push_back(1); AssertBatchLineSizes(batchLines, sizeList); auto batchLineIter = batchLines.batchLines.begin(); { const auto& batchLine = *batchLineIter; auto drawBatchIter = batchLine.drawBatchList.begin(); { const DrawBatch& drawBatch = *drawBatchIter; AZ_Assert(drawBatch.text == "t", "Test failed"); AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action1", "Test failed"); AZ_Assert(drawBatch.data == "data1", "Test failed"); AZ_Assert(drawBatch.clickableId == 0, "Test failed"); } // Next batch ++drawBatchIter; { const DrawBatch& drawBatch = *drawBatchIter; AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action2", "Test failed"); AZ_Assert(drawBatch.data == "data2", "Test failed"); AZ_Assert(drawBatch.clickableId == 1, "Test failed"); } } // Next line ++batchLineIter; { const auto& batchLine = *batchLineIter; auto drawBatchIter = batchLine.drawBatchList.begin(); { const DrawBatch& drawBatch = *drawBatchIter; AZ_Assert(drawBatch.IsClickable(), "Test failed"); AZ_Assert(UiTextComponent::DrawBatch::Type::Text == drawBatch.GetType(), "Test failed"); AZ_Assert(drawBatch.action == "action2", "Test failed"); AZ_Assert(drawBatch.data == "data2", "Test failed"); AZ_Assert(drawBatch.clickableId == 1, "Test failed"); } } } } } void CreateComponent(AZ::Entity* entity, const AZ::Uuid& componentTypeId) { entity->Deactivate(); entity->CreateComponent(componentTypeId); entity->Activate(); } void TestCharacterSpacing(CLyShine* lyshine, const AZStd::string& fontPath, float fontSize, const AZStd::string& testString, float characterSpacing, const char* testName) { AZ::EntityId canvasEntityId = lyshine->CreateCanvas(); UiCanvasInterface* canvas = UiCanvasBus::FindFirstHandler(canvasEntityId); AZ_Assert(canvas, "Test failed"); AZ::Entity* testElem = canvas->CreateChildElement("TrackingTestElement"); AZ_Assert(testElem, "Test failed"); CreateComponent(testElem, LyShine::UiTransform2dComponentUuid); CreateComponent(testElem, LyShine::UiTextComponentUuid); AZ::EntityId testElemId = testElem->GetId(); EBUS_EVENT_ID(testElemId, UiTextBus, SetText, testString); EBUS_EVENT_ID(testElemId, UiTextBus, SetFont, fontPath); EBUS_EVENT_ID(testElemId, UiTextBus, SetFontSize, fontSize); float baseWidth; EBUS_EVENT_ID_RESULT(baseWidth, testElemId, UiLayoutCellDefaultBus, GetTargetWidth, LyShine::UiLayoutCellUnspecifiedSize); EBUS_EVENT_ID(testElemId, UiTextBus, SetCharacterSpacing, characterSpacing); float newWidth; EBUS_EVENT_ID_RESULT(newWidth, testElemId, UiLayoutCellDefaultBus, GetTargetWidth, LyShine::UiLayoutCellUnspecifiedSize); const int testStringLength = testString.length(); const int numGapsBetweenCharacters = testStringLength >= 1 ? testStringLength - 1 : 0; const float ems = characterSpacing * 0.001f; float expectedWidth = baseWidth + numGapsBetweenCharacters * ems * fontSize; if (expectedWidth < 0.0f) { expectedWidth = 0.0f; } AZ_Assert(IsClose(newWidth, expectedWidth), "Test failed: Character Spacing, %s. Expected: %f, actual: %f", testName, expectedWidth, newWidth); lyshine->ReleaseCanvas(canvasEntityId, false); } void TestLineSpacing(CLyShine* lyshine, const AZStd::string& fontPath, float fontSize, const AZStd::string& testString, int numNewlines, float lineSpacing, const char* testName) { AZ::EntityId canvasEntityId = lyshine->CreateCanvas(); UiCanvasInterface* canvas = UiCanvasBus::FindFirstHandler(canvasEntityId); AZ_Assert(canvas, "Test failed"); AZ::Entity* testElem = canvas->CreateChildElement("LeadingTestElement"); AZ_Assert(testElem, "Test failed"); CreateComponent(testElem, LyShine::UiTransform2dComponentUuid); CreateComponent(testElem, LyShine::UiTextComponentUuid); AZ::EntityId testElemId = testElem->GetId(); EBUS_EVENT_ID(testElemId, UiTextBus, SetText, testString); EBUS_EVENT_ID(testElemId, UiTextBus, SetFont, fontPath); EBUS_EVENT_ID(testElemId, UiTextBus, SetFontSize, fontSize); float baseHeight; EBUS_EVENT_ID_RESULT(baseHeight, testElemId, UiLayoutCellDefaultBus, GetTargetHeight, LyShine::UiLayoutCellUnspecifiedSize); EBUS_EVENT_ID(testElemId, UiTextBus, SetLineSpacing, lineSpacing); float newHeight; EBUS_EVENT_ID_RESULT(newHeight, testElemId, UiLayoutCellDefaultBus, GetTargetHeight, LyShine::UiLayoutCellUnspecifiedSize); float expectedHeight = baseHeight + numNewlines * lineSpacing; if (expectedHeight < 0.0f) { expectedHeight = 0.0f; } AZ_Assert(IsClose(newHeight, expectedHeight), "Test failed: Line Spacing, %s. Expected: %f, actual: %f", testName, expectedHeight, newHeight); lyshine->ReleaseCanvas(canvasEntityId, false); } void TrackingLeadingTests(CLyShine* lyshine) { // Character Spacing TestCharacterSpacing(lyshine, "default-ui", 32.0f, "Hi", 1000.0f, "one space"); TestCharacterSpacing(lyshine, "default-ui", 32.0f, "W", 1000.0f, "no spaces"); TestCharacterSpacing(lyshine, "default-ui", 32.0f, "", 1000.0f, "empty string"); TestCharacterSpacing(lyshine, "default-ui", 32.0f, "Hi", 4500.0f, "bigger spacing"); TestCharacterSpacing(lyshine, "default-ui", 32.0f, "abcde", 1000.0f, "four spaces"); TestCharacterSpacing(lyshine, "default-ui", 32.0f, "abcde", 3500.0f, "four spaces, larger spacing"); TestCharacterSpacing(lyshine, "default-ui", 32.0f, "12345678", 5432.1f, "seven spaces, non-round spacing"); TestCharacterSpacing(lyshine, "default-ui", 32.0f, "12345678", 5432.1f, "seven spaces, non-round spacing, lots of kerning"); TestCharacterSpacing(lyshine, "default-ui", 32.0f, "Hi", -1000.0f, "negative spacing"); TestCharacterSpacing(lyshine, "default-ui", 32.0f, "abcde", -1000.0f, "negative spacing, 4 spaces"); TestCharacterSpacing(lyshine, "default-ui", 16.0f, "Hi", 1000.0f, "smaller font size, one space"); TestCharacterSpacing(lyshine, "default-ui", 16.0f, "abcdefghijk", 1000.0f, "smaller font size, ten spaces"); TestCharacterSpacing(lyshine, "default-ui", 16.0f, "abcdefghijk", 3500.0f, "smaller font size, ten spaces, larger spacing"); TestCharacterSpacing(lyshine, "default-ui", 64.0f, "Hi", 1000.0f, "larger font size, one space"); TestCharacterSpacing(lyshine, "default-ui", 64.0f, "abcdefgh", 1000.0f, "larger font size, seven spaces"); TestCharacterSpacing(lyshine, "default-ui", 64.0f, "abcdefgh", 5200.0f, "larger font size, seven spaces, larger spacing"); TestCharacterSpacing(lyshine, "default", 32.0f, "abcdefgh", 1000.0f, "default (monospace) font, seven spaces"); TestCharacterSpacing(lyshine, "notosans-regular", 32.0f, "WAW.AWA|WAW", 2500.0f, "noto sans font, 10 spaces, larger spacing"); TestCharacterSpacing(lyshine, "notosans-regular", 32.0f, "WAW.AWA|WAW", 25.0f, "noto sans font, 10 spaces, smaller spacing"); TestCharacterSpacing(lyshine, "notosans-regular", 32.0f, "WAW.AWA|WAW", -25.0f, "noto sans font, 10 spaces, smaller negative spacing"); // Line Spacing TestLineSpacing(lyshine, "default-ui", 32.0f, "Hi\nHello", 1, 5.0f, "one newline"); TestLineSpacing(lyshine, "default-ui", 32.0f, "1\n2\n3\n4\n5", 4, 5.0f, "four newlines"); TestLineSpacing(lyshine, "default-ui", 32.0f, "1\n2\n3\n4\n5\n6\n7\n8", 7, 8.3f, "seven newlines, larger spacing"); TestLineSpacing(lyshine, "default-ui", 32.0f, "1\n2", 1, -1.0f, "one newline, negative spacing"); TestLineSpacing(lyshine, "default-ui", 32.0f, "1\n2\n3\n4", 3, -2.2f, "three newlines, negative spacing, larger spacing"); TestLineSpacing(lyshine, "default-ui", 18.0f, "1\n2", 1, 1.0f, "one newlines, smaller font"); TestLineSpacing(lyshine, "default-ui", 18.0f, "1\n2\n3\n4\n5", 4, 1.0f, "four newlines, smaller font"); TestLineSpacing(lyshine, "default-ui", 64.0f, "1\n2", 1, 1.0f, "one newlines, larger font"); TestLineSpacing(lyshine, "default-ui", 64.0f, "1\n2\n3\n4\n5", 4, 1.0f, "four newlines, larger font"); TestLineSpacing(lyshine, "default", 16.0f, "1\n2\n3\n4\n5", 4, 1.0f, "four newlines, default (mono) font"); TestLineSpacing(lyshine, "notosans-regular", 20.0f, "1\n2\n3\n4\n5", 4, 1.0f, "four newlines, notosans font"); } void ComponentGetSetTextTests(CLyShine* lyshine) { { AZ::EntityId canvasEntityId = lyshine->CreateCanvas(); UiCanvasInterface* canvas = UiCanvasBus::FindFirstHandler(canvasEntityId); AZ_Assert(canvas, "Test failed"); AZ::Entity* testElem = canvas->CreateChildElement("Test1"); AZ_Assert(testElem, "Test failed"); CreateComponent(testElem, LyShine::UiTransform2dComponentUuid); CreateComponent(testElem, LyShine::UiTextComponentUuid); AZ::EntityId testElemId = testElem->GetId(); const AZStd::string testString("Hi"); EBUS_EVENT_ID(testElemId, UiTextBus, SetText, testString); AZStd::string resultString; EBUS_EVENT_ID_RESULT(resultString, testElemId, UiTextBus, GetText); AZ_Assert(testString == resultString, "Test failed"); resultString.clear(); EBUS_EVENT_ID_RESULT(resultString, testElemId, UiTextBus, GetTextWithFlags, UiTextInterface::GetTextFlags::GetAsIs); AZ_Assert(testString == resultString, "Test failed"); lyshine->ReleaseCanvas(canvasEntityId, false); } { AZ::EntityId canvasEntityId = lyshine->CreateCanvas(); UiCanvasInterface* canvas = UiCanvasBus::FindFirstHandler(canvasEntityId); AZ_Assert(canvas, "Test failed"); AZ::Entity* testElem = canvas->CreateChildElement("Test1"); AZ_Assert(testElem, "Test failed"); CreateComponent(testElem, LyShine::UiTransform2dComponentUuid); CreateComponent(testElem, LyShine::UiTextComponentUuid); AZ::EntityId testElemId = testElem->GetId(); const AZStd::string testString("Hi"); EBUS_EVENT_ID(testElemId, UiTextBus, SetTextWithFlags, testString, UiTextInterface::SetAsIs); AZStd::string resultString; EBUS_EVENT_ID_RESULT(resultString, testElemId, UiTextBus, GetText); AZ_Assert(testString == resultString, "Test failed"); resultString.clear(); EBUS_EVENT_ID_RESULT(resultString, testElemId, UiTextBus, GetTextWithFlags, UiTextInterface::GetTextFlags::GetAsIs); AZ_Assert(testString == resultString, "Test failed"); lyshine->ReleaseCanvas(canvasEntityId, false); } { AZ::EntityId canvasEntityId = lyshine->CreateCanvas(); UiCanvasInterface* canvas = UiCanvasBus::FindFirstHandler(canvasEntityId); AZ_Assert(canvas, "Test failed"); AZ::Entity* testElem = canvas->CreateChildElement("Test1"); AZ_Assert(testElem, "Test failed"); CreateComponent(testElem, LyShine::UiTransform2dComponentUuid); CreateComponent(testElem, LyShine::UiTextComponentUuid); AZ::EntityId testElemId = testElem->GetId(); const AZStd::string testString("&<>%"); EBUS_EVENT_ID(testElemId, UiTextBus, SetTextWithFlags, testString, UiTextInterface::SetAsIs); AZStd::string resultString; EBUS_EVENT_ID_RESULT(resultString, testElemId, UiTextBus, GetText); AZ_Assert(testString == resultString, "Test failed"); resultString.clear(); EBUS_EVENT_ID_RESULT(resultString, testElemId, UiTextBus, GetTextWithFlags, UiTextInterface::GetTextFlags::GetAsIs); AZ_Assert(testString == resultString, "Test failed"); lyshine->ReleaseCanvas(canvasEntityId, false); } { AZ::EntityId canvasEntityId = lyshine->CreateCanvas(); UiCanvasInterface* canvas = UiCanvasBus::FindFirstHandler(canvasEntityId); AZ_Assert(canvas, "Test failed"); AZ::Entity* testElem = canvas->CreateChildElement("Test1"); AZ_Assert(testElem, "Test failed"); CreateComponent(testElem, LyShine::UiTransform2dComponentUuid); CreateComponent(testElem, LyShine::UiTextComponentUuid); AZ::EntityId testElemId = testElem->GetId(); const AZStd::string testString("&<>%"); EBUS_EVENT_ID(testElemId, UiTextBus, SetTextWithFlags, testString, UiTextInterface::SetAsIs); AZStd::string resultString; EBUS_EVENT_ID_RESULT(resultString, testElemId, UiTextBus, GetText); AZ_Assert(testString == resultString, "Test failed"); resultString.clear(); EBUS_EVENT_ID_RESULT(resultString, testElemId, UiTextBus, GetTextWithFlags, UiTextInterface::GetTextFlags::GetAsIs); AZ_Assert(testString == resultString, "Test failed"); lyshine->ReleaseCanvas(canvasEntityId, false); } { AZ::EntityId canvasEntityId = lyshine->CreateCanvas(); UiCanvasInterface* canvas = UiCanvasBus::FindFirstHandler(canvasEntityId); AZ_Assert(canvas, "Test failed"); AZ::Entity* testElem = canvas->CreateChildElement("Test1"); AZ_Assert(testElem, "Test failed"); CreateComponent(testElem, LyShine::UiTransform2dComponentUuid); CreateComponent(testElem, LyShine::UiTextComponentUuid); AZ::EntityId testElemId = testElem->GetId(); const AZStd::string testString("&<>%"); EBUS_EVENT_ID(testElemId, UiTextBus, SetTextWithFlags, testString, UiTextInterface::SetEscapeMarkup); AZStd::string resultString; EBUS_EVENT_ID_RESULT(resultString, testElemId, UiTextBus, GetText); AZ_Assert(testString == resultString, "Test failed"); resultString.clear(); EBUS_EVENT_ID_RESULT(resultString, testElemId, UiTextBus, GetTextWithFlags, UiTextInterface::GetTextFlags::GetAsIs); AZ_Assert(testString == resultString, "Test failed"); lyshine->ReleaseCanvas(canvasEntityId, false); } } void ComponentGetSetTextTestsLoc(CLyShine* lyshine) { if (AZStd::string("korean") == GetISystem()->GetLocalizationManager()->GetLanguage()) { static const LyShine::StringType koreanHello("\xEC\x95\x88\xEB\x85\x95\xED\x95\x98\xEC\x84\xB8\xEC\x9A\x94"); // Tests: Get/SetText with localization { AZ::EntityId canvasEntityId = lyshine->CreateCanvas(); UiCanvasInterface* canvas = UiCanvasBus::FindFirstHandler(canvasEntityId); AZ_Assert(canvas, "Test failed"); AZ::Entity* testElem = canvas->CreateChildElement("Test1"); AZ_Assert(testElem, "Test failed"); CreateComponent(testElem, LyShine::UiTransform2dComponentUuid); CreateComponent(testElem, LyShine::UiTextComponentUuid); AZ::EntityId testElemId = testElem->GetId(); // Verify that GetText and GetAsIs returns the unlocalized key "@ui_Hello" { AZStd::string testString("@ui_Hello"); EBUS_EVENT_ID(testElemId, UiTextBus, SetTextWithFlags, testString, UiTextInterface::SetLocalized); AZStd::string resultString; EBUS_EVENT_ID_RESULT(resultString, testElemId, UiTextBus, GetText); AZ_Assert(testString == resultString, "Test failed"); resultString.clear(); EBUS_EVENT_ID_RESULT(resultString, testElemId, UiTextBus, GetTextWithFlags, UiTextInterface::GetTextFlags::GetAsIs); AZ_Assert(testString == resultString, "Test failed"); resultString.clear(); } // Verify that passing GetLocalized to GetTextWithFlags returns the localized content of "@ui_Hello" { AZStd::string testString = koreanHello; AZStd::string resultString; EBUS_EVENT_ID_RESULT(resultString, testElemId, UiTextBus, GetTextWithFlags, UiTextInterface::GetLocalized); AZ_Assert(testString == resultString, "Test failed"); resultString.clear(); } lyshine->ReleaseCanvas(canvasEntityId, false); } // Tests: Get/SetText with localization and escaping markup { AZ::EntityId canvasEntityId = lyshine->CreateCanvas(); UiCanvasInterface* canvas = UiCanvasBus::FindFirstHandler(canvasEntityId); AZ_Assert(canvas, "Test failed"); AZ::Entity* testElem = canvas->CreateChildElement("Test1"); AZ_Assert(testElem, "Test failed"); CreateComponent(testElem, LyShine::UiTransform2dComponentUuid); CreateComponent(testElem, LyShine::UiTextComponentUuid); AZ::EntityId testElemId = testElem->GetId(); // Verify that GetText and GetAsIs returns the unlocalized key "@ui_Hello" along // with the original (escaped) markup characters { AZStd::string testString("&<>% @ui_Hello"); UiTextInterface::SetTextFlags setTextFlags = static_cast(UiTextInterface::SetEscapeMarkup | UiTextInterface::SetLocalized); EBUS_EVENT_ID(testElemId, UiTextBus, SetTextWithFlags, testString, setTextFlags); AZStd::string resultString; EBUS_EVENT_ID_RESULT(resultString, testElemId, UiTextBus, GetText); AZ_Assert(testString == resultString, "Test failed"); resultString.clear(); EBUS_EVENT_ID_RESULT(resultString, testElemId, UiTextBus, GetTextWithFlags, UiTextInterface::GetTextFlags::GetAsIs); AZ_Assert(testString == resultString, "Test failed"); resultString.clear(); } // Verify that passing GetLocalized to GetTextWithFlags returns the localized content of "@ui_Hello" // along with the original (escaped) markup characters in the string { AZStd::string testString = LyShine::StringType("&<>% ") + koreanHello; AZStd::string resultString; EBUS_EVENT_ID_RESULT(resultString, testElemId, UiTextBus, GetTextWithFlags, UiTextInterface::GetLocalized); AZ_Assert(testString == resultString, "Test failed"); resultString.clear(); } lyshine->ReleaseCanvas(canvasEntityId, false); } // Tests: Setting localized text with abutting invalid localization key chars // // Purpose: localization tokens appear in strings surrounded by characters that // shouldn't be part of the localization key. // // For example: // "@ui_Hello, @ui_Welcome!" // // This should only consider "@ui_Hello" and "@ui_Hello" for localization. The // abutting punctuation characters - comma, exclamation point - should not be // considered as part of the localization key. // // Markup example: // "@ui_DeathStatus" // // The end font-tag text ("") following the loc key "@ui_DeathStatus" should // not be considered for localization. // // Abutting loc keys example: // "@ui_item1@ui_item2" // // There are two loc keys in the above example and should be localized independently // of each other.. { AZ::EntityId canvasEntityId = lyshine->CreateCanvas(); UiCanvasInterface* canvas = UiCanvasBus::FindFirstHandler(canvasEntityId); AZ_Assert(canvas, "Test failed"); AZ::Entity* testElem = canvas->CreateChildElement("Test1"); AZ_Assert(testElem, "Test failed"); CreateComponent(testElem, LyShine::UiTransform2dComponentUuid); CreateComponent(testElem, LyShine::UiTextComponentUuid); AZ::EntityId testElemId = testElem->GetId(); // Verify that localizing keys won't consider punctuation as part // of the localization key. { AZStd::string testString("@ui_Hello, @ui_Hello!"); UiTextInterface::SetTextFlags setTextFlags = static_cast(UiTextInterface::SetLocalized); EBUS_EVENT_ID(testElemId, UiTextBus, SetTextWithFlags, testString, setTextFlags); testString = koreanHello + ", " + koreanHello + "!"; AZStd::string resultString; EBUS_EVENT_ID_RESULT(resultString, testElemId, UiTextBus, GetTextWithFlags, UiTextInterface::GetLocalized); AZ_Assert(testString == resultString, "Test failed"); } // Verify that localizing keys won't consider markup as part // of the localization key. { AZStd::string testString("@ui_Hello"); UiTextInterface::SetTextFlags setTextFlags = static_cast(UiTextInterface::SetLocalized); EBUS_EVENT_ID(testElemId, UiTextBus, SetTextWithFlags, testString, setTextFlags); testString = LyShine::StringType("") + koreanHello + ""; AZStd::string resultString; EBUS_EVENT_ID_RESULT(resultString, testElemId, UiTextBus, GetTextWithFlags, UiTextInterface::GetLocalized); AZ_Assert(testString == resultString, "Test failed"); } // Verify that localizing adjacent keys will localize the keys separately // and not consider them to be one single key { AZStd::string testString("@ui_Hello@ui_Hello"); UiTextInterface::SetTextFlags setTextFlags = static_cast(UiTextInterface::SetLocalized); EBUS_EVENT_ID(testElemId, UiTextBus, SetTextWithFlags, testString, setTextFlags); testString = koreanHello + koreanHello; AZStd::string resultString; EBUS_EVENT_ID_RESULT(resultString, testElemId, UiTextBus, GetTextWithFlags, UiTextInterface::GetLocalized); AZ_Assert(testString == resultString, "Test failed"); } lyshine->ReleaseCanvas(canvasEntityId, false); } } } // This tests for whether or not the MarkupFlag is functioning properly void MarkupFlagTest(CLyShine* lyshine) { AZ::EntityId canvasEntityId = lyshine->CreateCanvas(); UiCanvasInterface* canvas = UiCanvasBus::FindFirstHandler(canvasEntityId); AZ_Assert(canvas, "Test failed"); AZ::Entity* testElem = canvas->CreateChildElement("Test1"); AZ_Assert(testElem, "Test failed"); CreateComponent(testElem, LyShine::UiTransform2dComponentUuid); CreateComponent(testElem, LyShine::UiTextComponentUuid); AZ::EntityId testElemId = testElem->GetId(); EBUS_EVENT_ID(testElemId, UiTextBus, SetText, " "); bool enabled(true); AZ::Vector2 NewSize(0, 0); // Sizes expected based on the default font AZ::Vector2 MarkUpEnabledSize(8, 32); AZ::Vector2 MarkUpDisabledSize(354, 32); // Test that markup is disabled by default. EBUS_EVENT_ID_RESULT(enabled, testElemId, UiTextBus, GetIsMarkupEnabled); AZ_Assert(!enabled, "Test failed"); // Test that setting it to false when it is already false, does not set it to true. EBUS_EVENT_ID(testElemId, UiTextBus, SetIsMarkupEnabled, false); EBUS_EVENT_ID_RESULT(enabled, testElemId, UiTextBus, GetIsMarkupEnabled); AZ_Assert(!enabled, "Test failed"); // Check that the flag is actually disabled by checking the size of the textbox EBUS_EVENT_ID_RESULT(NewSize, testElemId, UiTextBus, GetTextSize); AZ_Assert(NewSize == MarkUpDisabledSize, "Test failed"); // Test that setting it to true when it is false, sets it to true EBUS_EVENT_ID(testElemId, UiTextBus, SetIsMarkupEnabled, true); EBUS_EVENT_ID_RESULT(enabled, testElemId, UiTextBus, GetIsMarkupEnabled); AZ_Assert(enabled, "Test failed"); // Check that the flag is actually enabled by checking the size of the textbox EBUS_EVENT_ID_RESULT(NewSize, testElemId, UiTextBus, GetTextSize); AZ_Assert(NewSize == MarkUpEnabledSize, "Test failed"); // Test that setting it to true when it is true, does not set it to false EBUS_EVENT_ID(testElemId, UiTextBus, SetIsMarkupEnabled, true); EBUS_EVENT_ID_RESULT(enabled, testElemId, UiTextBus, GetIsMarkupEnabled); AZ_Assert(enabled, "Test failed"); // Check that the flag is actually enabled by checking the size of the textbox EBUS_EVENT_ID_RESULT(NewSize, testElemId, UiTextBus, GetTextSize); AZ_Assert(NewSize == MarkUpEnabledSize, "Test failed"); // Test that setting it to false when it is true, properly sets it to false. EBUS_EVENT_ID(testElemId, UiTextBus, SetIsMarkupEnabled, false); EBUS_EVENT_ID_RESULT(enabled, testElemId, UiTextBus, GetIsMarkupEnabled); AZ_Assert(!enabled, "Test failed"); // Check that the flag is actually disabled by checking the size of the textbox EBUS_EVENT_ID_RESULT(NewSize, testElemId, UiTextBus, GetTextSize); AZ_Assert(NewSize == MarkUpDisabledSize, "Test failed"); lyshine->ReleaseCanvas(canvasEntityId, false); } } void FontSharedPtrTests() { // Verify test font isn't loaded { const char* fontName = "notosans-regular"; AZ_Assert(nullptr == GetISystem()->GetICryFont()->GetFont(fontName), "Test failed"); } // Basic font load and unload { const char* fontName = "notosans-regular"; IFFont* font = GetISystem()->GetICryFont()->NewFont(fontName); AZ_Assert(font, "Test failed"); AZ_Assert(font == GetISystem()->GetICryFont()->GetFont(fontName), "Test failed"); const bool loadSuccess = font->Load("ui/fonts/lyshineexamples/notosans/notosans-regular.font"); AZ_Assert(loadSuccess, "Test failed"); font->AddRef(); AZ_Assert(1 == font->Release(), "Test failed"); AZ_Assert(0 == font->Release(), "Test failed"); AZ_Assert(nullptr == GetISystem()->GetICryFont()->GetFont(fontName), "Test failed"); } // Font and font family case sensitivity checks { // IFFont case sensitivity checks { const char* fontName = "notosans-regular"; const char* fontNameUpper = "NOTOSANS-REGULAR"; const char* fontNameMixed1 = "Notosans-regular"; const char* fontNameMixed2 = "Notosans-Regular"; const char* fontNameMixed3 = "NoToSaNs-ReGuLaR"; IFFont* const font = GetISystem()->GetICryFont()->NewFont(fontName); AZ_Assert(font, "Test failed"); AZ_Assert(2 == font->AddRef(), "Test failed"); AZ_Assert(1 == font->Release(), "Test failed"); // Verify that creating a new font for a font that's already created returns // that same font AZ_Assert(font == GetISystem()->GetICryFont()->NewFont(fontName), "Test failed"); AZ_Assert(font == GetISystem()->GetICryFont()->NewFont(fontNameUpper), "Test failed"); AZ_Assert(font == GetISystem()->GetICryFont()->NewFont(fontNameMixed1), "Test failed"); AZ_Assert(font == GetISystem()->GetICryFont()->NewFont(fontNameMixed2), "Test failed"); AZ_Assert(font == GetISystem()->GetICryFont()->NewFont(fontNameMixed3), "Test failed"); // Getting the font with the expected name returns the same font AZ_Assert(font == GetISystem()->GetICryFont()->GetFont(fontName), "Test failed"); AZ_Assert(font == GetISystem()->GetICryFont()->GetFont(fontNameUpper), "Test failed"); AZ_Assert(font == GetISystem()->GetICryFont()->GetFont(fontNameMixed1), "Test failed"); AZ_Assert(font == GetISystem()->GetICryFont()->GetFont(fontNameMixed2), "Test failed"); AZ_Assert(font == GetISystem()->GetICryFont()->GetFont(fontNameMixed3), "Test failed"); // Release the font AZ_Assert(0 == font->Release(), "Test failed"); } // FontFamily case sensitivity checks { const char* notoSansFontFamily = "ui/fonts/lyshineexamples/notosans/notosans.fontfamily"; const char* notoSansName = "notosans"; // Shouldn't be loaded yet FontFamilyPtr fontFamily = gEnv->pCryFont->GetFontFamily(notoSansFontFamily); AZ_Assert(!fontFamily.get(), "Test failed"); fontFamily = gEnv->pCryFont->GetFontFamily(notoSansName); AZ_Assert(!fontFamily.get(), "Test failed"); // Should load successfully fontFamily = gEnv->pCryFont->LoadFontFamily(notoSansFontFamily); AZ_Assert(fontFamily.get(), "Test failed"); // GetFontFamily case-sensitivity tests by filepath { AZ_Assert(fontFamily == gEnv->pCryFont->GetFontFamily(notoSansFontFamily), "Test failed"); const char* notoSansFontFamilyUpper = "UI/FONTS/LYSHINEEXAMPLES/NOTOSANS/NOTOSANS.FONTFAMILY"; const char* notoSansFontFamilyMixed1 = "ui/fonts/lyshineexamples/notosans/Notosans.fontfamily"; const char* notoSansFontFamilyMixed2 = "ui/fonts/lyshineexamples/notosans/Notosans.Fontfamily"; const char* notoSansFontFamilyMixed3 = "ui/fonts/lyshineexamples/notosans/NotoSans.Fontfamily"; const char* notoSansFontFamilyMixed4 = "ui/fonts/lyshineexamples/notosans/notosans.FONTFAMILY"; const char* notoSansFontFamilyMixed5 = "ui/fonts/lyshineexamples/notosans/NOTOSANS.fontfamily"; const char* notoSansFontFamilyMixed6 = "Ui/fonts/lyshineexamples/notosans/notosans.fontfamily"; const char* notoSansFontFamilyMixed7 = "ui/fonts/lyshineexamples/Notosans/notosans.fontfamily"; AZ_Assert(fontFamily == gEnv->pCryFont->GetFontFamily(notoSansFontFamilyUpper), "Test failed"); AZ_Assert(fontFamily == gEnv->pCryFont->GetFontFamily(notoSansFontFamilyMixed1), "Test failed"); AZ_Assert(fontFamily == gEnv->pCryFont->GetFontFamily(notoSansFontFamilyMixed2), "Test failed"); AZ_Assert(fontFamily == gEnv->pCryFont->GetFontFamily(notoSansFontFamilyMixed3), "Test failed"); AZ_Assert(fontFamily == gEnv->pCryFont->GetFontFamily(notoSansFontFamilyMixed4), "Test failed"); AZ_Assert(fontFamily == gEnv->pCryFont->GetFontFamily(notoSansFontFamilyMixed5), "Test failed"); AZ_Assert(fontFamily == gEnv->pCryFont->GetFontFamily(notoSansFontFamilyMixed6), "Test failed"); AZ_Assert(fontFamily == gEnv->pCryFont->GetFontFamily(notoSansFontFamilyMixed7), "Test failed"); } // GetFontFamily case-sensitivity tests by font name { AZ_Assert(fontFamily == gEnv->pCryFont->GetFontFamily(notoSansName), "Test failed"); const char* notoSansNameUpper = "NOTOSANS"; const char* notoSansNameMixed1 = "Notosans"; const char* notoSansNameMixed2 = "NotoSans"; AZ_Assert(fontFamily == gEnv->pCryFont->GetFontFamily(notoSansNameUpper), "Test failed"); AZ_Assert(fontFamily == gEnv->pCryFont->GetFontFamily(notoSansNameMixed1), "Test failed"); AZ_Assert(fontFamily == gEnv->pCryFont->GetFontFamily(notoSansNameMixed2), "Test failed"); } } } // Font family ref count test { const char* notoSansFontFamily = "ui/fonts/lyshineexamples/notosans/notosans.fontfamily"; const char* notoSansRegularPath = "ui/fonts/lyshineexamples/notosans/notosans-regular.font"; const char* notoSansItalicPath = "ui/fonts/lyshineexamples/notosans/notosans-italic.font"; const char* notoSansBoldPath = "ui/fonts/lyshineexamples/notosans/notosans-bold.font"; const char* notoSansBoldItalicPath = "ui/fonts/lyshineexamples/notosans/notosans-bolditalic.font"; const char* notoSansRegular = "notosans-regular"; const char* notoSansBold = "notosans-bold"; const char* notoSansItalic = "notosans-italic"; const char* notoSansBoldItalic = "notosans-boldItalic"; { FontFamilyPtr notoSans = FontFamilyLoad(notoSansFontFamily); AZ_Assert(2 == notoSans->normal->AddRef(), "Test failed"); AZ_Assert(1 == notoSans->normal->Release(), "Test failed"); AZ_Assert(2 == notoSans->bold->AddRef(), "Test failed"); AZ_Assert(1 == notoSans->bold->Release(), "Test failed"); AZ_Assert(2 == notoSans->italic->AddRef(), "Test failed"); AZ_Assert(1 == notoSans->italic->Release(), "Test failed"); AZ_Assert(2 == notoSans->boldItalic->AddRef(), "Test failed"); AZ_Assert(1 == notoSans->boldItalic->Release(), "Test failed"); // This is a negative test which is difficult to support currently. // Uncommenting this line should trigger an assert in CryFont because // the font was de-allocated while still being referenced by a // FontFamily //notoSans->normal->Release(); // Attempt to load FontFamily already loaded { FontFamilyPtr dupeFamily = GetISystem()->GetICryFont()->LoadFontFamily(notoSansFontFamily); AZ_Assert(nullptr == dupeFamily, "Test failed"); //Ref counts should remain the same AZ_Assert(2 == notoSans->normal->AddRef(), "Test failed"); AZ_Assert(1 == notoSans->normal->Release(), "Test failed"); AZ_Assert(2 == notoSans->bold->AddRef(), "Test failed"); AZ_Assert(1 == notoSans->bold->Release(), "Test failed"); AZ_Assert(2 == notoSans->italic->AddRef(), "Test failed"); AZ_Assert(1 == notoSans->italic->Release(), "Test failed"); AZ_Assert(2 == notoSans->boldItalic->AddRef(), "Test failed"); AZ_Assert(1 == notoSans->boldItalic->Release(), "Test failed"); } IFFont* fontRegular = GetISystem()->GetICryFont()->GetFont(notoSansRegularPath); AZ_Assert(fontRegular, "Test failed"); AZ_Assert(fontRegular == notoSans->normal, "Test failed"); // Verify that ref counts are handled properly when font family // fonts are referenced outside of the font family. { // NewFont shouldn't increment ref count IFFont* checkFont = GetISystem()->GetICryFont()->NewFont(notoSansRegularPath); AZ_Assert(fontRegular == checkFont, "Test failed"); AZ_Assert(2 == checkFont->AddRef(), "Test failed"); AZ_Assert(1 == checkFont->Release(), "Test failed"); // Load also doesn't increment ref count AZ_Assert(checkFont->Load(notoSansRegularPath), "Test failed"); AZ_Assert(2 == checkFont->AddRef(), "Test failed"); AZ_Assert(1 == checkFont->Release(), "Test failed"); // If font is loaded as a Font Family, then ref counts will increment FontFamilyPtr notoSansRegularFamily = FontFamilyLoad(notoSansRegularPath); // Verify that every font of the single-font font family are the same AZ_Assert(notoSansRegularFamily->normal == notoSansRegularFamily->bold, "Test failed"); AZ_Assert(notoSansRegularFamily->bold == notoSansRegularFamily->italic, "Test failed"); AZ_Assert(notoSansRegularFamily->italic == notoSansRegularFamily->boldItalic, "Test failed"); // Verify that the single-font is the same font in the original font family AZ_Assert(notoSansRegularFamily->normal == notoSans->normal, "Test failed"); // Check "single font as a font family" ref counts AZ_Assert(6 == notoSansRegularFamily->normal->AddRef(), "Test failed"); AZ_Assert(5 == notoSansRegularFamily->normal->Release(), "Test failed"); AZ_Assert(6 == notoSansRegularFamily->bold->AddRef(), "Test failed"); AZ_Assert(5 == notoSansRegularFamily->bold->Release(), "Test failed"); AZ_Assert(6 == notoSansRegularFamily->italic->AddRef(), "Test failed"); AZ_Assert(5 == notoSansRegularFamily->italic->Release(), "Test failed"); AZ_Assert(6 == notoSansRegularFamily->boldItalic->AddRef(), "Test failed"); AZ_Assert(5 == notoSansRegularFamily->boldItalic->Release(), "Test failed"); // Check ref counts of the original font family AZ_Assert(6 == notoSans->normal->AddRef(), "Test failed"); AZ_Assert(5 == notoSans->normal->Release(), "Test failed"); AZ_Assert(2 == notoSans->bold->AddRef(), "Test failed"); AZ_Assert(1 == notoSans->bold->Release(), "Test failed"); AZ_Assert(2 == notoSans->italic->AddRef(), "Test failed"); AZ_Assert(1 == notoSans->italic->Release(), "Test failed"); AZ_Assert(2 == notoSans->boldItalic->AddRef(), "Test failed"); AZ_Assert(1 == notoSans->boldItalic->Release(), "Test failed"); // Attempt to load single-font font-family again { FontFamilyPtr dupeFamily = GetISystem()->GetICryFont()->LoadFontFamily(notoSansRegularPath); AZ_Assert(nullptr == dupeFamily, "Test failed"); //Ref counts should remain the same AZ_Assert(6 == notoSansRegularFamily->normal->AddRef(), "Test failed"); AZ_Assert(5 == notoSansRegularFamily->normal->Release(), "Test failed"); AZ_Assert(6 == notoSansRegularFamily->bold->AddRef(), "Test failed"); AZ_Assert(5 == notoSansRegularFamily->bold->Release(), "Test failed"); AZ_Assert(6 == notoSansRegularFamily->italic->AddRef(), "Test failed"); AZ_Assert(5 == notoSansRegularFamily->italic->Release(), "Test failed"); AZ_Assert(6 == notoSansRegularFamily->boldItalic->AddRef(), "Test failed"); AZ_Assert(5 == notoSansRegularFamily->boldItalic->Release(), "Test failed"); } } // BEGIN JAV_LY_FORK: r_persistFontFamilies keeps font families loaded for lifetime of application. // In this case, the normal/regular font has already been loaded as a "pass through" font family, // so it has been persisted in memory. Even though the FontFamilyPtr used has gone out of scope. // notoSansRegularFamily should now be out of scope, so the original font family's // ref counts should return to their original values { AZ_Assert(6 == notoSans->normal->AddRef(), "Test failed"); AZ_Assert(5 == notoSans->normal->Release(), "Test failed"); AZ_Assert(2 == notoSans->bold->AddRef(), "Test failed"); AZ_Assert(1 == notoSans->bold->Release(), "Test failed"); AZ_Assert(2 == notoSans->italic->AddRef(), "Test failed"); AZ_Assert(1 == notoSans->italic->Release(), "Test failed"); AZ_Assert(2 == notoSans->boldItalic->AddRef(), "Test failed"); AZ_Assert(1 == notoSans->boldItalic->Release(), "Test failed"); } // Reference a FontFamily already loaded { FontFamilyPtr dupeFamily = GetISystem()->GetICryFont()->GetFontFamily("notosans"); // Ref couts for underlying fonts should stay the same AZ_Assert(6 == notoSans->normal->AddRef(), "Test failed"); AZ_Assert(5 == notoSans->normal->Release(), "Test failed"); AZ_Assert(2 == notoSans->bold->AddRef(), "Test failed"); AZ_Assert(1 == notoSans->bold->Release(), "Test failed"); AZ_Assert(2 == notoSans->italic->AddRef(), "Test failed"); AZ_Assert(1 == notoSans->italic->Release(), "Test failed"); AZ_Assert(2 == notoSans->boldItalic->AddRef(), "Test failed"); AZ_Assert(1 == notoSans->boldItalic->Release(), "Test failed"); } // END JAV_LY_FORK IFFont* fontBold = GetISystem()->GetICryFont()->GetFont(notoSansBoldPath); AZ_Assert(fontBold, "Test failed"); AZ_Assert(fontBold == notoSans->bold, "Test failed"); IFFont* fontItalic = GetISystem()->GetICryFont()->GetFont(notoSansItalicPath); AZ_Assert(fontItalic, "Test failed"); AZ_Assert(fontItalic == notoSans->italic, "Test failed"); IFFont* fontBoldItalic = GetISystem()->GetICryFont()->GetFont(notoSansBoldItalicPath); AZ_Assert(fontBoldItalic, "Test failed"); AZ_Assert(fontBoldItalic == notoSans->boldItalic, "Test failed"); } // Once FontFamilyPtr goes out of scope, all associated font family // fonts should get unloaded too. IFFont* fontRegular = GetISystem()->GetICryFont()->GetFont(notoSansRegular); AZ_Assert(!fontRegular, "Test failed"); IFFont* fontBold = GetISystem()->GetICryFont()->GetFont(notoSansBold); AZ_Assert(!fontBold, "Test failed"); IFFont* fontItalic = GetISystem()->GetICryFont()->GetFont(notoSansItalic); AZ_Assert(!fontItalic, "Test failed"); IFFont* fontBoldItalic = GetISystem()->GetICryFont()->GetFont(notoSansBoldItalic); AZ_Assert(!fontBoldItalic, "Test failed"); } // Load Vera.font as a font family, then load Vera.fontfamily that also // uses Vera.font as a font { const char* veraFontFile = "fonts/vera.font"; FontFamilyPtr veraFont = gEnv->pCryFont->LoadFontFamily(veraFontFile); AZ_Assert(veraFont.get(), "Test failed"); // Verify that vera.font has been referenced 4 times for all four // font styles in the font family markup (single fonts loaded as // font families get re-used for each of the font styles) AZ_Assert(5 == veraFont->normal->AddRef(), "Test failed"); AZ_Assert(4 == veraFont->normal->Release(), "Test failed"); AZ_Assert(5 == veraFont->bold->AddRef(), "Test failed"); AZ_Assert(4 == veraFont->bold->Release(), "Test failed"); AZ_Assert(5 == veraFont->italic->AddRef(), "Test failed"); AZ_Assert(4 == veraFont->italic->Release(), "Test failed"); AZ_Assert(5 == veraFont->boldItalic->AddRef(), "Test failed"); AZ_Assert(4 == veraFont->boldItalic->Release(), "Test failed"); const char* veraFontFamilyFile = "fonts/vera.fontfamily"; FontFamilyPtr veraFontFamily = gEnv->pCryFont->LoadFontFamily(veraFontFamilyFile); // BEGIN JAV_LY_FORK: The above "vera.font" is a pass-through font (not a font family) // and is now mapped by by its full filepath rather than just the filename. AZ_Assert(veraFontFamily.get(), "Test failed"); // The vera font family uses vera.font for its regular-weighted font, // so the ref count for vera.font increases by one, from 4 to 5. AZ_Assert(6 == veraFont->normal->AddRef(), "Test failed"); AZ_Assert(5 == veraFont->normal->Release(), "Test failed"); AZ_Assert(6 == veraFont->bold->AddRef(), "Test failed"); AZ_Assert(5 == veraFont->bold->Release(), "Test failed"); AZ_Assert(6 == veraFont->italic->AddRef(), "Test failed"); AZ_Assert(5 == veraFont->italic->Release(), "Test failed"); AZ_Assert(6 == veraFont->boldItalic->AddRef(), "Test failed"); AZ_Assert(5 == veraFont->boldItalic->Release(), "Test failed"); // END JAV_LY_FORK } } void UiTextComponent::UnitTest(CLyShine* lyshine, IConsoleCmdArgs* cmdArgs) { const bool testsRunningAtStartup = cmdArgs == nullptr; if (testsRunningAtStartup) { FontSharedPtrTests(); } else { // These tests assume the unit-tests run at startup in order for ref count // values to make sense. AZ_Warning("LyShine", false, "Unit-tests: skipping FontSharedPtrTests due to tests running " "ad-hoc. Run unit tests at startup for full coverage. See ui_RunUnitTestsOnStartup."); } VerifyShippingFonts(); // These fonts are required for subsequent unit-tests to work. FontFamilyPtr notoSans = FontFamilyLoad("ui/fonts/lyshineexamples/notosans/notosans.fontfamily"); FontFamilyPtr notoSerif = FontFamilyLoad("ui/fonts/lyshineexamples/notoserif/notoserif.fontfamily"); NewlineSanitizeTests(); BuildDrawBatchesTests(notoSans.get()); WrapTextTests(notoSans.get()); BatchLinesTests(notoSans.get()); TrackingLeadingTests(lyshine); ComponentGetSetTextTests(lyshine); MarkupFlagTest(lyshine); } void UiTextComponent::UnitTestLocalization(CLyShine* lyshine, IConsoleCmdArgs* /* cmdArgs */) { ILocalizationManager* pLocMan = GetISystem()->GetLocalizationManager(); string localizationXml("libs/localization/localization.xml"); bool initLocSuccess = false; if (pLocMan) { if (pLocMan->InitLocalizationData(localizationXml.c_str())) { if (pLocMan->LoadLocalizationDataByTag("init")) { initLocSuccess = true; } } } ComponentGetSetTextTestsLoc(lyshine); } #endif