#include #include "XCUIBackend/XCUIStandaloneTextAtlasProvider.h" #include namespace { using XCEngine::Editor::XCUIBackend::IXCUITextAtlasProvider; using XCEngine::Editor::XCUIBackend::XCUIStandaloneTextAtlasProvider; TEST(XCUIStandaloneTextAtlasProviderTest, BuildsDefaultEditorAtlasWithoutImGuiContext) { XCUIStandaloneTextAtlasProvider provider = {}; IXCUITextAtlasProvider::AtlasTextureView atlasView = {}; IXCUITextAtlasProvider::AtlasTextureView alphaView = {}; ASSERT_TRUE(provider.IsReady()); ASSERT_TRUE(provider.GetAtlasTextureView(IXCUITextAtlasProvider::PixelFormat::RGBA32, atlasView)); ASSERT_TRUE(provider.GetAtlasTextureView(IXCUITextAtlasProvider::PixelFormat::Alpha8, alphaView)); EXPECT_TRUE(atlasView.IsValid()); EXPECT_TRUE(alphaView.IsValid()); EXPECT_EQ(atlasView.format, IXCUITextAtlasProvider::PixelFormat::RGBA32); EXPECT_EQ(alphaView.format, IXCUITextAtlasProvider::PixelFormat::Alpha8); EXPECT_GT(provider.GetFontCount(), 0u); } TEST(XCUIStandaloneTextAtlasProviderTest, ExposesDefaultFontMetricsAndGlyphs) { XCUIStandaloneTextAtlasProvider provider = {}; const IXCUITextAtlasProvider::FontHandle defaultFont = provider.GetDefaultFont(); ASSERT_TRUE(defaultFont.IsValid()); IXCUITextAtlasProvider::FontInfo fontInfo = {}; ASSERT_TRUE(provider.GetFontInfo(defaultFont, fontInfo)); EXPECT_GT(fontInfo.nominalSize, 0.0f); IXCUITextAtlasProvider::BakedFontInfo bakedFontInfo = {}; ASSERT_TRUE(provider.GetBakedFontInfo(defaultFont, 0.0f, bakedFontInfo)); EXPECT_GT(bakedFontInfo.lineHeight, 0.0f); EXPECT_GT(bakedFontInfo.rasterizerDensity, 0.0f); IXCUITextAtlasProvider::GlyphInfo glyphInfo = {}; ASSERT_TRUE(provider.FindGlyph(defaultFont, 0.0f, static_cast('A'), glyphInfo)); EXPECT_EQ(glyphInfo.requestedCodepoint, static_cast('A')); EXPECT_GT(glyphInfo.advanceX, 0.0f); EXPECT_GE(glyphInfo.u1, glyphInfo.u0); EXPECT_GE(glyphInfo.v1, glyphInfo.v0); } TEST(XCUIStandaloneTextAtlasProviderTest, RebuildsAfterResetAndRejectsQueriesWhileUnready) { XCUIStandaloneTextAtlasProvider provider = {}; const IXCUITextAtlasProvider::FontHandle defaultFont = provider.GetDefaultFont(); ASSERT_TRUE(defaultFont.IsValid()); provider.Reset(); IXCUITextAtlasProvider::AtlasTextureView atlasView = {}; IXCUITextAtlasProvider::FontInfo fontInfo = {}; IXCUITextAtlasProvider::BakedFontInfo bakedFontInfo = {}; IXCUITextAtlasProvider::GlyphInfo glyphInfo = {}; EXPECT_FALSE(provider.IsReady()); EXPECT_FALSE(provider.GetAtlasTextureView(IXCUITextAtlasProvider::PixelFormat::RGBA32, atlasView)); EXPECT_EQ(provider.GetFontCount(), 0u); EXPECT_FALSE(provider.GetDefaultFont().IsValid()); EXPECT_FALSE(provider.GetFontInfo(defaultFont, fontInfo)); EXPECT_FALSE(provider.GetBakedFontInfo(defaultFont, 18.0f, bakedFontInfo)); EXPECT_FALSE(provider.FindGlyph(defaultFont, 18.0f, static_cast('A'), glyphInfo)); ASSERT_TRUE(provider.RebuildDefaultEditorAtlas()); ASSERT_TRUE(provider.IsReady()); ASSERT_TRUE(provider.GetAtlasTextureView(IXCUITextAtlasProvider::PixelFormat::RGBA32, atlasView)); EXPECT_TRUE(atlasView.IsValid()); } TEST(XCUIStandaloneTextAtlasProviderTest, ResolvesGlyphsForNonNominalRequestedFontSizes) { XCUIStandaloneTextAtlasProvider provider = {}; const IXCUITextAtlasProvider::FontHandle defaultFont = provider.GetDefaultFont(); ASSERT_TRUE(defaultFont.IsValid()); IXCUITextAtlasProvider::BakedFontInfo bakedFontInfo = {}; ASSERT_TRUE(provider.GetBakedFontInfo(defaultFont, 13.0f, bakedFontInfo)); EXPECT_GT(bakedFontInfo.lineHeight, 0.0f); EXPECT_GT(bakedFontInfo.rasterizerDensity, 0.0f); IXCUITextAtlasProvider::GlyphInfo glyphInfo = {}; ASSERT_TRUE(provider.FindGlyph(defaultFont, 13.0f, static_cast('A'), glyphInfo)); EXPECT_EQ(glyphInfo.requestedCodepoint, static_cast('A')); EXPECT_GT(glyphInfo.advanceX, 0.0f); EXPECT_GE(glyphInfo.u1, glyphInfo.u0); EXPECT_GE(glyphInfo.v1, glyphInfo.v0); } TEST(XCUIStandaloneTextAtlasProviderTest, LazilyAddsGlyphsOutsideThePrebakedAsciiRanges) { XCUIStandaloneTextAtlasProvider provider = {}; const IXCUITextAtlasProvider::FontHandle defaultFont = provider.GetDefaultFont(); ASSERT_TRUE(defaultFont.IsValid()); IXCUITextAtlasProvider::AtlasTextureView beforeView = {}; ASSERT_TRUE(provider.GetAtlasTextureView(IXCUITextAtlasProvider::PixelFormat::RGBA32, beforeView)); constexpr std::uint32_t dynamicCodepoint = 0x4E2Du; IXCUITextAtlasProvider::GlyphInfo glyphInfo = {}; ASSERT_TRUE(provider.FindGlyph(defaultFont, 16.0f, dynamicCodepoint, glyphInfo)); IXCUITextAtlasProvider::AtlasTextureView refreshedView = {}; ASSERT_TRUE(provider.GetAtlasTextureView(IXCUITextAtlasProvider::PixelFormat::RGBA32, refreshedView)); EXPECT_EQ(refreshedView.atlasStorageKey, beforeView.atlasStorageKey); EXPECT_EQ(glyphInfo.requestedCodepoint, dynamicCodepoint); if (refreshedView.pixelDataKey != beforeView.pixelDataKey) { EXPECT_EQ(glyphInfo.resolvedCodepoint, dynamicCodepoint); EXPECT_GT(glyphInfo.advanceX, 0.0f); EXPECT_TRUE(glyphInfo.visible); IXCUITextAtlasProvider::GlyphInfo secondLookup = {}; ASSERT_TRUE(provider.FindGlyph(defaultFont, 16.0f, dynamicCodepoint, secondLookup)); EXPECT_EQ(secondLookup.requestedCodepoint, dynamicCodepoint); EXPECT_EQ(secondLookup.resolvedCodepoint, dynamicCodepoint); IXCUITextAtlasProvider::AtlasTextureView secondView = {}; ASSERT_TRUE(provider.GetAtlasTextureView(IXCUITextAtlasProvider::PixelFormat::RGBA32, secondView)); EXPECT_EQ(secondView.pixelDataKey, refreshedView.pixelDataKey); return; } if (glyphInfo.resolvedCodepoint != dynamicCodepoint) { EXPECT_EQ(glyphInfo.resolvedCodepoint, static_cast('?')); EXPECT_GT(glyphInfo.advanceX, 0.0f); EXPECT_TRUE(glyphInfo.visible); return; } if (!glyphInfo.visible) { EXPECT_GE(glyphInfo.advanceX, 0.0f); return; } if (glyphInfo.resolvedCodepoint == dynamicCodepoint) { EXPECT_NE(refreshedView.pixelDataKey, beforeView.pixelDataKey); } EXPECT_GT(glyphInfo.advanceX, 0.0f); EXPECT_TRUE(glyphInfo.visible); } TEST(XCUIStandaloneTextAtlasProviderTest, MissingGlyphFallsBackToQuestionMarkWhenFontCannotRasterizeIt) { XCUIStandaloneTextAtlasProvider provider = {}; const IXCUITextAtlasProvider::FontHandle defaultFont = provider.GetDefaultFont(); ASSERT_TRUE(defaultFont.IsValid()); IXCUITextAtlasProvider::GlyphInfo glyphInfo = {}; ASSERT_TRUE(provider.FindGlyph(defaultFont, 16.0f, 0x10FFFFu, glyphInfo)); EXPECT_EQ(glyphInfo.requestedCodepoint, 0x10FFFFu); EXPECT_EQ(glyphInfo.resolvedCodepoint, static_cast('?')); EXPECT_GT(glyphInfo.advanceX, 0.0f); EXPECT_TRUE(glyphInfo.visible); } } // namespace