Skip to content

Commit

Permalink
Merge pull request #385 from chinapandaman/PPF-384
Browse files Browse the repository at this point in the history
PPF-384: support auto detect font color
  • Loading branch information
chinapandaman authored Oct 17, 2023
2 parents befc6e6 + 06493f9 commit a953bca
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 9 deletions.
2 changes: 1 addition & 1 deletion PyPDFForm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@

PyPDFForm = Wrapper

__version__ = "1.3.1"
__version__ = "1.3.2"
3 changes: 3 additions & 0 deletions PyPDFForm/core/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@
CHOICE_FIELD_IDENTIFIER = "/Ch"
CHOICES_IDENTIFIER = "/Opt"

FONT_SIZE_IDENTIFIER = "Tf"
FONT_COLOR_IDENTIFIER = " rg"

CHECKBOX_TO_DRAW = "\u2713"
RADIO_TO_DRAW = "\u25CF"
29 changes: 24 additions & 5 deletions PyPDFForm/core/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,32 @@ def get_text_field_font_size(element: pdfrw.PdfDict) -> Union[float, int]:
for pattern in TEXT_FIELD_APPEARANCE_PATTERNS:
text_appearance = traverse_pattern(pattern, element)
if text_appearance:
text_appearance = text_appearance.replace("(", "").replace(")", "")
properties = text_appearance.split(" ")
if len(properties) > 1:
try:
result = float(properties[1])
for i, val in enumerate(properties):
if val == constants.FONT_SIZE_IDENTIFIER:
return float(properties[i - 1])

return result


def get_text_field_font_color(element: pdfrw.PdfDict) -> Union[Tuple[float, float, float], None]:
"""Returns the font color tuple of the text field if presented or black."""

result = (0, 0, 0)
for pattern in TEXT_FIELD_APPEARANCE_PATTERNS:
text_appearance = traverse_pattern(pattern, element)
if text_appearance:
if constants.FONT_COLOR_IDENTIFIER not in text_appearance:
return result

text_appearance = text_appearance.replace("(", "").replace(")", "").split(" ")
for i, val in enumerate(text_appearance):
if val == constants.FONT_COLOR_IDENTIFIER.replace(" ", ""):
result = (float(text_appearance[i - 3]),
float(text_appearance[i - 2]),
float(text_appearance[i - 1]))
break
except ValueError:
pass

return result

Expand Down
2 changes: 2 additions & 0 deletions PyPDFForm/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ def update_text_field_attributes(
elements[key].font_size = template.get_text_field_font_size(
_element
) or font_size_core.text_field_font_size(_element)
if elements[key].font_color is None:
elements[key].font_color = template.get_text_field_font_color(_element)
if (
template.is_text_multiline(_element)
and elements[key].text_wrap_length is None
Expand Down
1 change: 0 additions & 1 deletion PyPDFForm/middleware/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ def dropdown_to_text(dropdown: Dropdown) -> Text:
result = Text(dropdown.name)

result.font = constants.GLOBAL_FONT
result.font_color = constants.GLOBAL_FONT_COLOR

if dropdown.value is not None:
result.value = (
Expand Down
4 changes: 2 additions & 2 deletions PyPDFForm/wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def __init__(
each.font = kwargs.get("global_font", constants.GLOBAL_FONT)
each.font_size = kwargs.get("global_font_size")
each.font_color = kwargs.get(
"global_font_color", constants.GLOBAL_FONT_COLOR
"global_font_color"
)

def read(self) -> bytes:
Expand Down Expand Up @@ -82,7 +82,7 @@ def fill(
self,
data: Dict[str, Union[str, bool, int]],
) -> Wrapper:
"""Fill a PDF form."""
"""Fills a PDF form."""

for key, value in data.items():
if key in self.elements:
Expand Down
Binary file added pdf_samples/sample_template_with_font_colors.pdf
Binary file not shown.
Binary file added pdf_samples/test_fill_font_color.pdf
Binary file not shown.
6 changes: 6 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ def sejda_template_complex(pdf_samples):
return f.read()


@pytest.fixture
def sample_template_with_font_colors(pdf_samples):
with open(os.path.join(pdf_samples, "sample_template_with_font_colors.pdf"), "rb+") as f:
return f.read()


@pytest.fixture
def sample_template_paragraph_complex(pdf_samples):
with open(
Expand Down
25 changes: 25 additions & 0 deletions tests/test_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,3 +388,28 @@ def test_version(pdf_samples):

obj = PyPDFForm(os.path.join(pdf_samples, "versions", "unknown.pdf"))
assert obj.version is None


def test_fill_font_color(
sample_template_with_font_colors, pdf_samples, request
):
expected_path = os.path.join(pdf_samples, "test_fill_font_color.pdf")
with open(expected_path, "rb+") as f:
obj = PyPDFForm(sample_template_with_font_colors).fill(
{
"red_12": "red",
"green_14": "green",
"blue_16": "blue",
"mixed_auto": "mixed"
},
)

request.config.results["expected_path"] = expected_path
request.config.results["stream"] = obj.read()
assert len(obj.read()) == len(obj.stream)
assert obj.read() == obj.stream

expected = f.read()

assert len(obj.stream) == len(expected)
assert obj.stream == expected

0 comments on commit a953bca

Please sign in to comment.