初版网页

This commit is contained in:
2026-08-10 21:05:36 +08:00
parent cfc0849081
commit f50e9f7c1e
19 changed files with 1697 additions and 16 deletions
+70
View File
@@ -0,0 +1,70 @@
#include "web_server/Pixel_Frame.h"
#include "web_server/Web_Event_Adapter.h"
#include "web_server/Web_Plot_Session.h"
#include <gtest/gtest.h>
#include <cstring>
#include <variant>
namespace renderive::web {
namespace {
std::uint32_t read_u32_le(const std::string& value, std::size_t offset) {
return static_cast<std::uint8_t>(value[offset]) |
(static_cast<std::uint32_t>(static_cast<std::uint8_t>(value[offset + 1])) << 8U) |
(static_cast<std::uint32_t>(static_cast<std::uint8_t>(value[offset + 2])) << 16U) |
(static_cast<std::uint32_t>(static_cast<std::uint8_t>(value[offset + 3])) << 24U);
}
TEST(RenderiveWebBridge, DecodesOnlyEventMessages) {
const auto resize = Web_Event_Adapter::decode(
R"({"category":"event","type":"resize","width":800,"height":450})");
ASSERT_TRUE(resize.has_value());
ASSERT_TRUE(std::holds_alternative<Viewport_Resize>(*resize));
EXPECT_EQ(std::get<Viewport_Resize>(*resize).size, (Size{800, 450}));
const auto pointer = Web_Event_Adapter::decode(
R"({"category":"event","type":"pointer_press","x":22.5,"y":18,"button":"left","buttons":1,"modifiers":3})");
ASSERT_TRUE(pointer.has_value());
ASSERT_TRUE(std::holds_alternative<Pointer_Event>(*pointer));
EXPECT_EQ(std::get<Pointer_Event>(*pointer).button, Mouse_Button::Left);
EXPECT_DOUBLE_EQ(std::get<Pointer_Event>(*pointer).position.x, 22.5);
EXPECT_FALSE(Web_Event_Adapter::decode(R"({"category":"command","type":"frame"})"));
EXPECT_FALSE(Web_Event_Adapter::decode("not-json"));
}
TEST(RenderiveWebBridge, EncodesRgbaPixelFrame) {
const Pixel pixels[] = {pack_rgba(255, 0, 0), pack_rgba(0, 255, 0)};
const Image_View image{reinterpret_cast<const std::byte*>(pixels), 2, 1,
static_cast<int>(sizeof(pixels)), Pixel_Format::Premultiplied_32};
const std::string frame = encode_pixel_frame(image);
ASSERT_EQ(frame.size(), pixel_frame_header_size + 8);
EXPECT_EQ(frame.substr(0, 4), "RVP1");
EXPECT_EQ(read_u32_le(frame, 4), 2U);
EXPECT_EQ(read_u32_le(frame, 8), 1U);
EXPECT_EQ(read_u32_le(frame, 12), 8U);
const auto* rgba = reinterpret_cast<const std::uint8_t*>(frame.data() + pixel_frame_header_size);
EXPECT_EQ(rgba[0], 255);
EXPECT_EQ(rgba[1], 0);
EXPECT_EQ(rgba[2], 0);
EXPECT_EQ(rgba[3], 255);
EXPECT_EQ(rgba[4], 0);
EXPECT_EQ(rgba[5], 255);
}
TEST(RenderiveWebBridge, RendersPixelsOnlyForFrameEvent) {
Web_Plot_Session session;
EXPECT_FALSE(session.handle(Viewport_Resize{{640, 360}}).has_value());
EXPECT_FALSE(session.handle(Set_Demo_Mode{Demo_Mode::Usb}).has_value());
const auto frame = session.handle(Frame_Request{});
ASSERT_TRUE(frame.has_value());
ASSERT_GE(frame->size(), pixel_frame_header_size);
EXPECT_EQ(frame->substr(0, 4), "RVP1");
EXPECT_EQ(read_u32_le(*frame, 4), 640U);
EXPECT_EQ(read_u32_le(*frame, 8), 360U);
}
} // namespace
} // namespace renderive::web