Skip to content

Commit

Permalink
Fix insert_toc_placeholder() not properly setting the page orientatio…
Browse files Browse the repository at this point in the history
…n - close #1312 (#1315)
  • Loading branch information
Lucas-C authored Dec 3, 2024
1 parent fabd0ce commit 1f2b9e4
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 67 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ This can also be enabled programmatically with `warnings.simplefilter('default',

## [2.8.2] - Not released yet
### Added
* new optional parameter `border` for table cells [issue #1192](https://github.com/py-pdf/fpdf2/issues/1192) users can define specific borders (left, right, top, bottom) for individual cells
* new optional parameter `border` for table cells: users can define specific borders (left, right, top, bottom) for individual cells - [issue #1192](https://github.com/py-pdf/fpdf2/issues/1192)
* [`FPDF.write_html()`](https://py-pdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.write_html): now parses `<title>` tags to set the [document title](https://py-pdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_title). By default, it is added as PDF metadata, but not rendered in the document body. However, this can be enabled by passing `render_title_tag=True` to `FPDF.write_html()`.
* support for LZWDecode compression [issue #1271](https://github.com/py-pdf/fpdf2/issues/1271)
* support for [page labels](https://py-pdf.github.io/fpdf2/PageLabels.html) and created a [reference table of contents](https://py-pdf.github.io/fpdf2/DocumentOutlineAndTableOfContents.html) implementation
Expand All @@ -27,6 +27,7 @@ This can also be enabled programmatically with `warnings.simplefilter('default',
* `FPDF.set_text_shaping(False)` was broken since version 2.7.8 and is now working properly - [issue #1287](https://github.com/py-pdf/fpdf2/issues/1287)
* fixed bug where cells with `rowspan`, `colspan` > 1 and null text were not displayed properly - [issue #1293](https://github.com/py-pdf/fpdf2/issues/1293)
* `CreationDate` metadata used a wrong timezone offset for UTC - [issue #1261](https://github.com/py-pdf/fpdf2/issues/1261)
* [`insert_toc_placeholder()`](https://py-pdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.insert_toc_placeholder) did not properly the page orientation, which caused a bug when the last page of the document was in a different orientation - [issue #1213](https://github.com/py-pdf/fpdf2/issues/1213)
### Changed
* improved logic for handling text substitution of the total number of pages, ensuring compatibility with text shaping - [issue #1090](https://github.com/py-pdf/fpdf2/issues/1090)
* all [`AnnotationDict`](https://py-pdf.github.io/fpdf2/fpdf/annotations.html) properties can now be passed to `FPDF.text_annotation()`, `FPDF.free_text_annotation()`, `FPDF.add_action()`, `FPDF.add_text_markup_annotation()` & `FPDF.ink_annotation()`. This includes `title`, `color`, `border_width`...
Expand Down
12 changes: 12 additions & 0 deletions fpdf/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -1050,3 +1050,15 @@ class PageBoundaries(CoerciveEnum):
CROP_BOX = Name("CropBox")
MEDIA_BOX = Name("MediaBox")
TRIM_BOX = Name("TrimBox")


class PageOrientation(CoerciveEnum):
PORTRAIT = intern("P")
LANDSCAPE = intern("L")

# pylint: disable=arguments-differ
@classmethod
def coerce(cls, value):
if isinstance(value, str):
value = value.upper()
return super(cls, cls).coerce(value)
21 changes: 11 additions & 10 deletions fpdf/fpdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class Image:
PageLabelStyle,
PageLayout,
PageMode,
PageOrientation,
PathPaintRule,
RenderStyle,
TextDirection,
Expand Down Expand Up @@ -162,6 +163,7 @@ class ToCPlaceholder(NamedTuple):
render_function: Callable
start_page: int
y: int
page_orientation: str
pages: int = 1


Expand Down Expand Up @@ -556,24 +558,23 @@ def default_page_dimensions(self):
"Return a pair (width, height) in the unit specified to FPDF constructor"
return (
(self.dw_pt, self.dh_pt)
if self.def_orientation == "P"
if self.def_orientation == PageOrientation.PORTRAIT
else (self.dh_pt, self.dw_pt)
)

def _set_orientation(self, orientation, page_width_pt, page_height_pt):
orientation = orientation.lower()
if orientation in ("p", "portrait"):
self.cur_orientation = "P"
self.cur_orientation = PageOrientation.coerce(orientation)
if self.cur_orientation is PageOrientation.PORTRAIT:
self.w_pt = page_width_pt
self.h_pt = page_height_pt
elif orientation in ("l", "landscape"):
self.cur_orientation = "L"
else:
self.w_pt = page_height_pt
self.h_pt = page_width_pt
else:
raise FPDFException(f"Incorrect orientation: {orientation}")
self.w = self.w_pt / self.k
self.h = self.h_pt / self.k
if hasattr(self, "auto_page_break"): # not set when called from constructor
# When self.h is modified, the .page_break_trigger must be re-computed:
self.set_auto_page_break(self.auto_page_break, self.b_margin)

def set_display_mode(self, zoom, layout="continuous"):
"""
Expand Down Expand Up @@ -1064,7 +1065,6 @@ def _beginpage(
self._set_orientation(
orientation or self.def_orientation, page_width_pt, page_height_pt
)
self.page_break_trigger = self.h - self.b_margin
page.set_dimensions(self.w_pt, self.h_pt)

def header(self):
Expand Down Expand Up @@ -4810,6 +4810,7 @@ def _insert_table_of_contents(self):
self.page, self.y = tocp.start_page, tocp.y
# flag rendering ToC for page breaking function
self.in_toc_rendering = True
self._set_orientation(tocp.page_orientation, self.dw_pt, self.dh_pt)
tocp.render_function(self, self._outline)
self.in_toc_rendering = False # set ToC rendering flag off
expected_final_page = tocp.start_page + tocp.pages - 1
Expand Down Expand Up @@ -5137,7 +5138,7 @@ def insert_toc_placeholder(
f" on page {self.toc_placeholder.start_page}"
)
self.toc_placeholder = ToCPlaceholder(
render_toc_function, self.page, self.y, pages
render_toc_function, self.page, self.y, self.cur_orientation, pages
)
self._toc_allow_page_insertion = allow_extra_pages
for _ in range(pages):
Expand Down
5 changes: 2 additions & 3 deletions test/errors/test_FPDF_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,10 @@ def test_orientation_portrait_landscape():


def test_incorrect_orientation():
with pytest.raises(FPDFException) as e:
with pytest.raises(ValueError) as error:
fpdf.FPDF(orientation="hello")

msg = "Incorrect orientation: hello"
assert str(e.value) == msg
assert str(error.value) == "HELLO is not a valid PageOrientation"


def test_units():
Expand Down
Binary file not shown.
67 changes: 14 additions & 53 deletions test/outline/test_outline.py
Original file line number Diff line number Diff line change
Expand Up @@ -367,60 +367,21 @@ def insert_test_content(pdf):
)


def insert_test_content_with_deprecated_TitleStyle(pdf):
with pytest.warns(DeprecationWarning):
pdf.set_section_title_styles(
# Level 0 titles:
TitleStyle(
font_family="Times",
font_style="B",
font_size_pt=24,
color=128,
underline=True,
t_margin=10,
l_margin=10,
b_margin=0,
),
# Level 1 subtitles:
TitleStyle(
font_family="Times",
font_style="B",
font_size_pt=20,
color=128,
underline=True,
t_margin=10,
l_margin=20,
b_margin=5,
),
)

pdf.start_section("Title 1")
pdf.start_section("Subtitle 1.1", level=1)
p(
pdf,
(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit,"
" sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
),
)
pdf.add_page()
pdf.start_section("Subtitle 1.2", level=1)
p(
pdf,
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
)
pdf.add_page()
pdf.start_section("Title 2")
pdf.start_section("Subtitle 2.1", level=1)
p(
pdf,
"Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.",
)
def test_insert_toc_placeholder_with_last_page_in_landscape(tmp_path):
pdf = FPDF()
pdf.set_font("Helvetica")
pdf.add_page()
pdf.start_section("Subtitle 2.2", level=1)
p(
pdf,
"Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
pdf.set_y(50)
pdf.set_font(size=40)
p(pdf, "Doc Title", align="C")
pdf.set_font(size=12)
pdf.insert_toc_placeholder(render_toc)
insert_test_content(pdf)
pdf.add_page(orientation="L")
pdf.start_section("Title 3")
p(pdf, text="Nullam tempus magna quam, ac dictum neque blandit quis.")
assert_pdf_equal(
pdf, HERE / "insert_toc_placeholder_with_last_page_in_landscape.pdf", tmp_path
)


Expand Down

0 comments on commit 1f2b9e4

Please sign in to comment.