Skip to content
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ history and [GitHub's 'Contributors' feature](https://github.com/py-pdf/pypdf/gr

* [abyesilyurt](https://github.com/abyesilyurt)
* [ArkieCoder](https://github.com/ArkieCoder)
* [PJ Beers](https://github.com/PJBrs)
* [Clauss, Christian](https://github.com/cclauss)
* [DL6ER](https://github.com/DL6ER)
* [Duy, Phan Thanh](https://github.com/zuypt)
Expand Down
7 changes: 7 additions & 0 deletions docs/user/forms.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ writer.update_page_form_field_values(
writer.pages[0],
{"fieldname": "some filled in text"},
auto_regenerate=False,
flatten=False,
)

with open("filled-out.pdf", "wb") as output_stream:
Expand All @@ -41,6 +42,12 @@ parameter is `True` by default for legacy compatibility, but this flags the PDF
processor to recompute the field's rendering, and may trigger a "save changes"
dialog for users who open the generated PDF.

If you want to flatten your form, that is, keeping all form field contents while
removing the form fields themselves, you can set `flatten=True` to convert form
field contents to regular pdf content, and then use
`writer.remove_annotations(subtypes="/Widget")` to remove all form fields. This
will result in a flattened pdf.

## Some notes about form fields and annotations

PDF forms have a dual-nature approach to the fields:
Expand Down
15 changes: 10 additions & 5 deletions pypdf/_font.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from dataclasses import dataclass, field
from typing import Optional

from pypdf.generic import DictionaryObject

Expand Down Expand Up @@ -29,10 +28,16 @@ class FontDescriptor:
character_widths: dict[str, int] = field(default_factory=dict)

@classmethod
def from_font_resource(cls, pdf_font_dict: DictionaryObject) -> "Optional[FontDescriptor]":
def from_font_resource(cls, pdf_font_dict: DictionaryObject) -> "FontDescriptor":
from pypdf._codecs.core_fontmetrics import CORE_FONT_METRICS # noqa: PLC0415
# Prioritize information from the PDF font dictionary
font_name = pdf_font_dict.get("/BaseFont", "Unknown")
if font_name[1:] in CORE_FONT_METRICS:
return CORE_FONT_METRICS.get(font_name[1:])
font_name = pdf_font_dict.get("/BaseFont", "Unknown").removeprefix("/")
if font_name in CORE_FONT_METRICS:
return CORE_FONT_METRICS[font_name]
return cls(name=font_name)

def text_width(self, text: str) -> float:
"""Sum of character widths specified in PDF font for the supplied text."""
return sum(
[self.character_widths.get(char, self.character_widths.get("default", 0)) for char in text], 0.0
)
Loading
Loading