You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

137 lines
5.3 KiB

#include <gtest/gtest.h>
#include <cstddef>
#include <cstdint>
#include <SDL.h>
#include <expected.hpp>
#include <function_ref.hpp>
#include "engine/load_file.hpp"
#include "engine/palette.h"
#include "engine/point.hpp"
#include "engine/rectangle.hpp"
#include "engine/render/primitive_render.hpp"
#include "engine/render/text_render.hpp"
#include "engine/size.hpp"
#include "engine/surface.hpp"
#include "utils/paths.h"
#include "utils/sdl_wrap.h"
#include "utils/surface_to_png.hpp"
namespace devilution {
namespace {
constexpr char FixturesPath[] = "../test/fixtures/text_render_integration_test/";
SDLPaletteUniquePtr LoadPalette()
{
struct Color {
uint8_t r, g, b;
};
std::array<Color, 256> palData;
LoadFileInMem("ui_art\\diablo.pal", palData);
SDLPaletteUniquePtr palette = SDLWrap::AllocPalette(256);
for (unsigned i = 0; i < palData.size(); i++) {
palette->colors[i] = SDL_Color {
palData[i].r, palData[i].g, palData[i].b, SDL_ALPHA_OPAQUE
};
}
return palette;
}
std::vector<std::byte> ReadFile(const std::string &path)
{
SDL_RWops *rwops = SDL_RWFromFile(path.c_str(), "rb");
std::vector<std::byte> result;
if (rwops == nullptr) return result;
const size_t size = SDL_RWsize(rwops);
result.resize(size);
SDL_RWread(rwops, result.data(), size, 1);
SDL_RWclose(rwops);
return result;
}
void DrawWithBorder(const Surface &out, const Rectangle &area, tl::function_ref<void(const Rectangle &)> fn)
{
const uint8_t debugColor = PAL8_RED;
DrawHorizontalLine(out, area.position, area.size.width, debugColor);
DrawHorizontalLine(out, area.position + Displacement { 0, area.size.height - 1 }, area.size.width, debugColor);
DrawVerticalLine(out, area.position, area.size.height, debugColor);
DrawVerticalLine(out, area.position + Displacement { area.size.width - 1, 0 }, area.size.height, debugColor);
fn(Rectangle {
Point { area.position.x + 1, area.position.y + 1 },
Size { area.size.width - 2, area.size.height - 2 } });
}
TEST(TextRenderIntegrationTest, GoldenTest)
{
SDLPaletteUniquePtr palette = LoadPalette();
OwnedSurface out { Size { 200, 140 } };
SDL_SetSurfacePalette(out.surface, palette.get());
ASSERT_NE(out.surface, nullptr);
int y = -15;
DrawWithBorder(out, Rectangle { Point { 0, y += 15 }, Size { 96, 15 } }, [&](const Rectangle &rect) {
DrawString(out, "DrawString", rect,
TextRenderOptions { .flags = UiFlags::ColorUiGold });
});
DrawWithBorder(out, Rectangle { Point { 0, y += 15 }, Size { 120, 15 } }, [&](const Rectangle &rect) {
DrawString(out, "KerningFitSpacing", rect,
TextRenderOptions { .flags = UiFlags::KerningFitSpacing | UiFlags::ColorUiSilver });
});
DrawWithBorder(out, Rectangle { Point { 0, y += 15 }, Size { 170, 15 } }, [&](const Rectangle &rect) {
DrawString(out, "KerningFitSpacing | AlignCenter", rect,
TextRenderOptions { .flags = UiFlags::KerningFitSpacing | UiFlags::AlignCenter | UiFlags::ColorUiSilver });
});
DrawWithBorder(out, Rectangle { Point { 0, y += 15 }, Size { 170, 15 } }, [&](const Rectangle &rect) {
DrawString(out, "KerningFitSpacing | AlignRight", rect,
TextRenderOptions { .flags = UiFlags::KerningFitSpacing | UiFlags::AlignRight | UiFlags::ColorUiSilver });
});
y += 4;
DrawWithBorder(out, Rectangle { Point { 0, y += 15 }, Size { 186, 15 } }, [&](const Rectangle &rect) {
DrawStringWithColors(out, "{}{}{}{}",
{ { "Draw", UiFlags::ColorUiSilver },
{ "String", UiFlags::ColorUiGold },
{ "With", UiFlags::ColorUiSilverDark },
{ "Colors", UiFlags::ColorUiGoldDark } },
rect);
});
DrawWithBorder(out, Rectangle { Point { 0, y += 15 }, Size { 120, 15 } }, [&](const Rectangle &rect) {
DrawStringWithColors(out, "{}{}{}",
{ { "Kerning", UiFlags::ColorUiSilver },
{ "Fit", UiFlags::ColorUiGold },
{ "Spacing", UiFlags::ColorUiSilverDark } },
rect,
TextRenderOptions { .flags = UiFlags::KerningFitSpacing });
});
DrawWithBorder(out, Rectangle { Point { 0, y += 15 }, Size { 170, 15 } }, [&](const Rectangle &rect) {
DrawStringWithColors(out, "{}{}{}",
{ { "KerningFitSpacing", UiFlags::ColorUiSilver },
{ " | ", UiFlags::ColorUiGold },
{ "AlignCenter", UiFlags::ColorUiSilverDark } },
rect,
TextRenderOptions { .flags = UiFlags::KerningFitSpacing | UiFlags::AlignCenter | UiFlags::ColorUiSilver });
});
DrawWithBorder(out, Rectangle { Point { 0, y += 15 }, Size { 170, 15 } }, [&](const Rectangle &rect) {
DrawStringWithColors(out, "{}{}{}",
{ { "KerningFitSpacing", UiFlags::ColorUiSilver },
{ " | ", UiFlags::ColorUiGold },
{ "AlignRight", UiFlags::ColorUiSilverDark } },
rect,
TextRenderOptions { .flags = UiFlags::KerningFitSpacing | UiFlags::AlignRight | UiFlags::ColorUiSilver });
});
const std::string actualPath = paths::BasePath() + FixturesPath + "actual.png";
const std::string expectedPath = paths::BasePath() + FixturesPath + "expected.png";
SDL_RWops *actual = SDL_RWFromFile(actualPath.c_str(), "wb");
ASSERT_NE(actual, nullptr) << SDL_GetError();
ASSERT_TRUE(WriteSurfaceToFilePng(out, actual).has_value());
EXPECT_EQ(ReadFile(actualPath), ReadFile(expectedPath)) << "\n"
<< expectedPath << "\n"
<< actualPath;
}
} // namespace
} // namespace devilution