Skip to content

Commit

Permalink
add toc extra pages test
Browse files Browse the repository at this point in the history
  • Loading branch information
andersonhc committed Nov 7, 2024
1 parent 89b754a commit 4a00a89
Show file tree
Hide file tree
Showing 6 changed files with 316 additions and 61 deletions.
23 changes: 21 additions & 2 deletions fpdf/fpdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,25 @@ def alias_nb_pages(self, alias="{nb}"):
"""
self.str_alias_nb_pages = alias

def set_page_label(
self,
label_style: Union[str, PageLabelStyle] = None,
label_prefix: str = None,
label_start: int = None,
):
current_page_label = (
None if self.page == 1 else self.pages[self.page - 1].get_page_label()
)
new_page_label = None
if label_style or label_prefix or label_start:
label_style = (
PageLabelStyle.coerce(label_style, case_sensitive=True)
if label_style
else None
)
new_page_label = PDFPageLabel(label_style, label_prefix, label_start)
self.pages[self.page].set_page_label(current_page_label, new_page_label)

def add_page(
self,
orientation: str = "",
Expand Down Expand Up @@ -5199,7 +5218,7 @@ def start_section(self, name, level=0, strict=True):
self.add_page()
with self._marked_sequence(title=name) as struct_elem:
outline_struct_elem = struct_elem
with self._use_title_style(title_style):
with self.use_title_style(title_style):
self.multi_cell(
w=self.epw,
h=self.font_size,
Expand All @@ -5212,7 +5231,7 @@ def start_section(self, name, level=0, strict=True):
)

@contextmanager
def _use_title_style(self, title_style: TextStyle):
def use_title_style(self, title_style: TextStyle):
if title_style:
if title_style.t_margin:
self.ln(title_style.t_margin)
Expand Down
113 changes: 55 additions & 58 deletions fpdf/outline.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from typing import List, NamedTuple, Optional, TYPE_CHECKING

from .enums import Align, XPos, YPos
from .fonts import FontFace
from .fonts import TextStyle
from .syntax import Destination, PDFObject, PDFString
from .structure_tree import StructElem

Expand Down Expand Up @@ -112,77 +112,74 @@ def build_outline_objs(sections):
class TableOfContents:

def __init__(self):
self.title = "Table of Contents"
self.title_style = FontFace(emphasis="B", size_pt=16)
self.text_style = TextStyle()
self.use_section_title_styles = False
self.level_indent = 7.5
self.line_spacing = 1.5
self.ignore_pages_before_toc = True

def render_toc_title(self, pdf: "FPDF"):
with pdf.use_font_face(self.title_style):
pdf.set_x(pdf.l_margin)
pdf.multi_cell(
w=pdf.epw,
text=self.title,
new_x=XPos.LMARGIN,
new_y=YPos.NEXT,
h=pdf.font_size * self.line_spacing,
)
pdf.ln()
def get_text_style(self, pdf: "FPDF", item: OutlineSection):
if self.use_section_title_styles and pdf.section_title_styles[item.level]:
return pdf.section_title_styles[item.level]
return self.text_style

def render_toc_item(self, pdf: "FPDF", item: OutlineSection):
link = pdf.add_link(page=item.page_number)
page_label = pdf.pages[item.page_number].get_label()

# render the text on the left
indent = (item.level * self.level_indent) + pdf.l_margin
pdf.set_x(indent)
pdf.multi_cell(
w=pdf.w - indent - pdf.r_margin,
text=item.name,
new_x=XPos.END,
new_y=YPos.LAST,
link=link,
align=Align.J,
h=pdf.font_size * self.line_spacing,
)
with pdf.use_title_style(self.get_text_style(pdf, item)):
indent = (item.level * self.level_indent) + pdf.l_margin
pdf.set_x(indent)
pdf.multi_cell(
w=pdf.w - indent - pdf.r_margin,
text=item.name,
new_x=XPos.END,
new_y=YPos.LAST,
link=link,
align=Align.J,
h=pdf.font_size * self.line_spacing,
)

# fill in-between with dots
current_x = pdf.get_x()
page_label_length = pdf.get_string_width(page_label)
in_between_space = pdf.w - current_x - page_label_length - pdf.r_margin
in_between = ""
if in_between_space > 0:
while pdf.get_string_width(in_between + " ") < in_between_space:
in_between += "."

if len(in_between) > 1:
pdf.multi_cell(
w=pdf.w - current_x - pdf.r_margin,
text=in_between[:-1],
new_x=XPos.END,
new_y=YPos.LAST,
link=link,
align=Align.L,
h=pdf.font_size * self.line_spacing,
)

# render the page number on the right
pdf.set_x(current_x)
pdf.multi_cell(
w=pdf.w - current_x - pdf.r_margin,
text=page_label,
new_x=XPos.END,
new_y=YPos.LAST,
link=link,
align=Align.R,
h=pdf.font_size * self.line_spacing,
)
pdf.ln()
# fill in-between with dots
current_x = pdf.get_x()
page_label_length = pdf.get_string_width(page_label)
in_between_space = pdf.w - current_x - page_label_length - pdf.r_margin
if in_between_space < 0:
# no space to render the page number - go to next line
pdf.ln()
current_x = pdf.get_x()
in_between_space = pdf.w - current_x - page_label_length - pdf.r_margin
in_between = ""
if in_between_space > 0:
while pdf.get_string_width(in_between + " ") < in_between_space:
in_between += "."

if len(in_between) > 1:
pdf.multi_cell(
w=pdf.w - current_x - pdf.r_margin,
text=in_between[:-1],
new_x=XPos.END,
new_y=YPos.LAST,
link=link,
align=Align.L,
h=pdf.font_size * self.line_spacing,
)

# render the page number on the right
pdf.set_x(current_x)
pdf.multi_cell(
w=pdf.w - current_x - pdf.r_margin,
text=page_label,
new_x=XPos.LMARGIN,
new_y=YPos.NEXT,
link=link,
align=Align.R,
h=pdf.font_size * self.line_spacing,
)

def render_toc(self, pdf: "FPDF", outline: List[OutlineSection]):
"This method can be overriden by subclasses to customize the Table of Contents style."
self.render_toc_title(pdf)
for section in outline:
if (
self.ignore_pages_before_toc
Expand Down
Loading

0 comments on commit 4a00a89

Please sign in to comment.