fix the issue

This commit is contained in:
saqib mir
2026-07-01 17:28:00 +05:30
parent abcd407c35
commit 72ed04f2ed
+129
View File
@@ -1,5 +1,8 @@
#include <gtest/gtest.h>
#include <pdfengine/display_list.hpp>
#include <pdfengine/path_interpreter.hpp>
#include <pdfengine/content_object.hpp>
#include "../src/parser/content_stream_parser.hpp"
#include <string>
#include <vector>
@@ -20,6 +23,38 @@ public:
void visit(const DrawImageCommand&) override { calls.push_back("DrawImage"); }
};
class PathVerifyVisitor : public CommandVisitor {
public:
struct PathInfo {
std::string type;
size_t segmentCount = 0;
FillRule rule = FillRule::NonZero;
};
std::vector<PathInfo> paths;
std::vector<std::string> calls;
void visit(const SaveStateCommand&) override { calls.push_back("SaveState"); }
void visit(const RestoreStateCommand&) override { calls.push_back("RestoreState"); }
void visit(const SetTransformCommand& cmd) override {
calls.push_back("SetTransform(" + std::to_string(cmd.matrix.a) + "," + std::to_string(cmd.matrix.d) + ")");
}
void visit(const FillRectCommand&) override {}
void visit(const DrawTextCommand&) override {}
void visit(const FillPathCommand& cmd) override {
calls.push_back("FillPath");
paths.push_back({"Fill", cmd.path.segments().size(), cmd.rule});
}
void visit(const StrokePathCommand& cmd) override {
calls.push_back("StrokePath");
paths.push_back({"Stroke", cmd.path.segments().size(), FillRule::NonZero});
}
void visit(const FillStrokePathCommand& cmd) override {
calls.push_back("FillStrokePath");
paths.push_back({"FillStroke", cmd.path.segments().size(), cmd.rule});
}
void visit(const DrawImageCommand&) override {}
};
TEST(DisplayListTest, RecordAndReplay) {
DisplayList list;
@@ -53,3 +88,97 @@ TEST(DisplayListTest, Clear) {
list.clear();
EXPECT_EQ(list.size(), 0);
}
TEST(DisplayListTest, PathObjectInterpreterStroke) {
Path path;
path.moveTo(10.0f, 20.0f);
path.lineTo(30.0f, 40.0f);
PathObject pathObj;
pathObj.path = path;
pathObj.paintOp = PathPaintOp::Stroke;
pathObj.transform = Matrix(1.5f, 0.0f, 0.0f, 1.5f, 5.0f, 5.0f);
DisplayList list;
PathObjectInterpreter::interpret(pathObj, list);
PathVerifyVisitor visitor;
list.replay(visitor);
ASSERT_EQ(visitor.calls.size(), 4);
EXPECT_EQ(visitor.calls[0], "SaveState");
EXPECT_EQ(visitor.calls[1], "SetTransform(1.500000,1.500000)");
EXPECT_EQ(visitor.calls[2], "StrokePath");
EXPECT_EQ(visitor.calls[3], "RestoreState");
ASSERT_EQ(visitor.paths.size(), 1);
EXPECT_EQ(visitor.paths[0].type, "Stroke");
EXPECT_EQ(visitor.paths[0].segmentCount, 2);
}
TEST(DisplayListTest, PathObjectInterpreterFillEvenOdd) {
Path path;
path.addRect(0.0f, 0.0f, 10.0f, 10.0f);
PathObject pathObj;
pathObj.path = path;
pathObj.paintOp = PathPaintOp::Fill;
pathObj.fillRule = FillRule::EvenOdd;
pathObj.transform = Matrix(1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
DisplayList list;
PathObjectInterpreter::interpret(pathObj, list);
PathVerifyVisitor visitor;
list.replay(visitor);
ASSERT_EQ(visitor.calls.size(), 4);
EXPECT_EQ(visitor.calls[2], "FillPath");
ASSERT_EQ(visitor.paths.size(), 1);
EXPECT_EQ(visitor.paths[0].type, "Fill");
EXPECT_EQ(visitor.paths[0].segmentCount, 5); // moveTo + 3 lineTo + close
EXPECT_EQ(visitor.paths[0].rule, FillRule::EvenOdd);
}
TEST(DisplayListTest, ContentStreamParserPaths) {
DisplayList list;
ContentStreamParser parser;
// Parse stroke path (m, l, S)
parser.parse("10 20 m 30 40 l S", list);
// Parse fill path (re, f)
parser.parse("5 6 7 8 re f", list);
// Parse fill and stroke (m, c, B)
parser.parse("1 2 m 3 4 5 6 7 8 c B", list);
PathVerifyVisitor visitor;
list.replay(visitor);
// S -> StrokePath
// f -> FillPath
// B -> FillPath, StrokePath
ASSERT_EQ(visitor.calls.size(), 4);
EXPECT_EQ(visitor.calls[0], "StrokePath");
EXPECT_EQ(visitor.calls[1], "FillPath");
EXPECT_EQ(visitor.calls[2], "FillPath");
EXPECT_EQ(visitor.calls[3], "StrokePath");
ASSERT_EQ(visitor.paths.size(), 4);
// 1st: 10 20 m 30 40 l S -> MoveTo, LineTo
EXPECT_EQ(visitor.paths[0].type, "Stroke");
EXPECT_EQ(visitor.paths[0].segmentCount, 2);
// 2nd: 5 6 7 8 re f -> MoveTo, 3xLineTo, Close
EXPECT_EQ(visitor.paths[1].type, "Fill");
EXPECT_EQ(visitor.paths[1].segmentCount, 5);
// 3rd & 4th: 1 2 m 3 4 5 6 7 8 c B -> MoveTo, CubicBezierTo
EXPECT_EQ(visitor.paths[2].type, "Fill");
EXPECT_EQ(visitor.paths[2].segmentCount, 2);
EXPECT_EQ(visitor.paths[3].type, "Stroke");
EXPECT_EQ(visitor.paths[3].segmentCount, 2);
}