Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions rust/docvortex-pdfium/src/path_evidence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,14 +333,17 @@ fn open_thin_rectangle(subpath: &PreparedSubpath, x0: f64, x1: f64, y0: f64, y1:
.into_iter()
.map(|(x, y)| ((x * 1000.0).round() / 1000.0, (y * 1000.0).round() / 1000.0))
.collect::<Vec<_>>();
if rounded.iter().any(|point| !expected.contains(point)) {
// 与参考实现的集合相等语义保持一致:四个角点必须全部出现,缺失角点的退化开放路径不能折叠。
if expected.iter().any(|point| !rounded.contains(point))
|| rounded.iter().any(|point| !expected.contains(point))
{
return false;
}
subpath.raw.lines.iter().all(|&(first, last)| {
let a = subpath.raw.points[first];
let b = subpath.raw.points[last];
!((a.0 - b.0).abs() > 0.001 && (a.1 - b.1).abs() > 0.001)
})
// 轴对齐判断必须发生在对象/Form 矩阵与页面坐标转换之后,与 Python 参考实现一致。
subpath
.lines
.iter()
.all(|&(a, b)| !((a.0 - b.0).abs() > 0.001 && (a.1 - b.1).abs() > 0.001))
}

/// 生成单个 Path 的绘图线候选,不应用对象裁剪。
Expand Down
45 changes: 45 additions & 0 deletions tests/test_pdf_drawing_lines_extraction.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,51 @@ def test_native_path_evidence_matches_python_reference(monkeypatch) -> None:
assert backend_info()["pdfium_path_evidence_bridge_calls"] >= 1


def _open_filled_path_pdf(path_commands: bytes) -> bytes:
"""构造仅包含一个开放填充 Path 的最小 PDF,用于原生/参考差分。"""
content = b"0 0 0 rg\n" + path_commands
return _pdf(
[
b"<< /Type /Catalog /Pages 2 0 R >>",
b"<< /Type /Pages /Kids [3 0 R] /Count 1 >>",
b"<< /Type /Page /Parent 2 0 R /MediaBox [0 0 100 50] /Resources << >> /Contents 4 0 R >>",
b"<< /Length %d >>\nstream\n%s\nendstream" % (len(content), content),
]
)


@pytest.mark.parametrize(
("path_commands", "expected_line_count"),
[
# 缺失左上角且重复右下角时,参考实现不接受该开放路径为细矩形。
(b"20 20 m 30 20 l 30 21 l 30 20 l f", 0),
# 对象矩阵会把两条局部斜边转换为轴对齐边,应按转换后的线段判定。
(b"q 1 0 -2 1 40 0 cm 20 20 m 30 20 l 32 21 l 22 21 l f Q", 1),
],
)
def test_native_open_filled_path_edges_match_reference(monkeypatch, path_commands, expected_line_count) -> None:
"""覆盖开放细矩形的角点完整性与矩阵后轴对齐两个后端分歧行为。"""
from docvortex.document.pdf import _object_bridge
from docvortex._compute_backend import backend_info, get_native
from docvortex.document.pdf.native_coordinates import _normalize_pdf_page_bbox

original_reader = _object_bridge.read_path_evidence
calls_before = backend_info()["pdfium_path_evidence_bridge_calls"]
with PDFDocument(_open_filled_path_pdf(path_commands)) as document:
with document._open_page(0) as page:
bbox = _normalize_pdf_page_bbox(page.get_bbox())
native_lines, native_infos = native_objects._extract_page_paths_and_lines(page, bbox, 0)
monkeypatch.setattr(_object_bridge, "read_path_evidence", lambda *args, **kwargs: None)
reference_lines, reference_infos = native_objects._extract_page_paths_and_lines(page, bbox, 0)

monkeypatch.setattr(_object_bridge, "read_path_evidence", original_reader)
assert native_lines == reference_lines
assert native_infos == reference_infos
assert len(native_lines) == expected_line_count
if get_native() is not None and hasattr(get_native(), "read_pdfium_path_evidence"):
assert backend_info()["pdfium_path_evidence_bridge_calls"] > calls_before


def test_drawing_lines_match_vector_and_snapshot_entries() -> None:
"""独立线接口、矢量几何和页面快照的绘图线逐字段且按顺序一致。"""
data = _vector_page_pdf(600)
Expand Down
Loading