Skip to content
Open
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
1 change: 1 addition & 0 deletions src/parse/pdf_resources/page_font.h
Original file line number Diff line number Diff line change
Expand Up @@ -2566,6 +2566,7 @@ namespace pdflib
return cmap_initialized
and cmap_numb_to_char.count(numb)==1
and cmap_numb_to_char.at(numb).size()>0
and cmap_numb_to_char.at(numb)!=std::string(1, '\0')
and cmap_numb_to_char.at(numb)!=replacement_char;
};

Expand Down
53 changes: 53 additions & 0 deletions tests/test_unit_nul_mapping.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from io import BytesIO

import pytest

from docling_parse.pdf_parser import DecodeConfig, DoclingPdfParser
from tests.pdf_builder import content_stream, simple_page_pdf


def _extract_character(mapping: str, glyph_name: str) -> str:
cmap = (
"/CIDInit /ProcSet findresource begin\n"
"12 dict begin\nbegincmap\n"
"/CIDSystemInfo << /Registry (Adobe) /Ordering (UCS) /Supplement 0 >> def\n"
"/CMapName /Test-UCS def\n/CMapType 2 def\n"
"1 begincodespacerange\n<00> <FF>\nendcodespacerange\n"
f"1 beginbfrange\n<41> <41> <{mapping}>\nendbfrange\n"
"endcmap\nCMapName currentdict /CMap defineresource pop\nend\nend"
)
pdf = simple_page_pdf(
"BT /F1 24 Tf 20 100 Td (A) Tj ET",
resources="/Font << /F1 5 0 R >>",
extra_objects=[
"<< /Type /Font /Subtype /Type1 /BaseFont /XXXXXX+FakeSubset "
"/FirstChar 65 /LastChar 65 /Widths [600] "
f"/Encoding << /Differences [65 /{glyph_name}] >> "
"/ToUnicode 6 0 R >>",
content_stream(cmap),
],
)
parser = DoclingPdfParser(loglevel="fatal")
doc = parser.load(
BytesIO(pdf),
decode_config=DecodeConfig(keep_glyphs=True),
)
page = doc.get_page(1)
assert len(page.char_cells) == 1
return page.char_cells[0].text


def test_authoritative_minus_overrides_conflicting_identity_before_normalization():
assert _extract_character(mapping="2212", glyph_name="plus") == "-"


@pytest.mark.parametrize(("glyph_name", "expected"), [("minus", "-"), ("plus", "+")])
def test_nul_mapping_recovers_from_known_glyph_identity(glyph_name: str, expected: str):
assert _extract_character(mapping="0000", glyph_name=glyph_name) == expected


def test_nul_mapping_with_unknown_identity_remains_unresolved():
assert (
_extract_character(mapping="0000", glyph_name="gid00043")
== "GLYPH<name:gid00043>"
)
Loading