Skip to content

Commit

Permalink
Handling those HTML tags in the same place: "b", "em", "i", "strong",…
Browse files Browse the repository at this point in the history
… "u"
  • Loading branch information
Lucas-C committed Jul 1, 2024
1 parent eebb8bd commit db9a009
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 42 deletions.
16 changes: 12 additions & 4 deletions fpdf/fpdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,11 +293,13 @@ def __init__(
# Graphics state variables defined as properties by GraphicsStateMixin.
# We set their default values here.
self.font_family = "" # current font family
self.font_style = "" # current font style
self.font_style = (
"" # current font style (BOLD/ITALICS - does not handle UNDERLINE)
)
self.underline = False # underlining flag
self.font_size_pt = 12 # current font size in points
self.font_stretching = 100 # current font stretching
self.char_spacing = 0 # current character spacing
self.underline = False # underlining flag
self.current_font = None # None or an instance of CoreFont or TTFFont
self.draw_color = self.DEFAULT_DRAW_COLOR
self.fill_color = self.DEFAULT_FILL_COLOR
Expand Down Expand Up @@ -410,11 +412,17 @@ def _set_min_pdf_version(self, version):
self.pdf_version = max(self.pdf_version, version)

@property
def is_ttf_font(self):
def emphasis(self) -> TextEmphasis:
return TextEmphasis.coerce(
f"{self.font_style}U" if self.underline else self.font_style
)

@property
def is_ttf_font(self) -> bool:
return self.current_font and self.current_font.type == "TTF"

@property
def page_mode(self):
def page_mode(self) -> PageMode:
return self._page_mode

@page_mode.setter
Expand Down
73 changes: 36 additions & 37 deletions fpdf/html.py
Original file line number Diff line number Diff line change
Expand Up @@ -592,28 +592,19 @@ def _write_data(self, data):
" You can open up an issue on github.com/py-pdf/fpdf2 if this is something you would like to see implemented."
)
self.pdf.start_section(data, self.heading_level - 1, strict=False)
LOGGER.debug(f"write: '%s' h={self.h:.2f}", data)
self._write_paragraph(data)

def handle_starttag(self, tag, attrs):
self._pre_started = False
attrs = dict(attrs)
LOGGER.debug("STARTTAG %s %s", tag, attrs)
css_style = parse_css_style(attrs.get("style", ""))
self._tags_stack.append(tag)
if css_style.get("break-before") == "page":
self._end_paragraph()
# pylint: disable=protected-access
self.pdf._perform_page_break()
if tag == "strong":
tag = "b"
if tag == "em":
tag = "i"
if tag in ("b", "i", "u"):
if self.td_th is not None:
self.td_th[tag] = True
else:
self.set_style(tag, True)
if tag in ("b", "i", "u") and self.td_th is not None:
self.td_th[tag] = True
if tag == "a":
self.href = attrs["href"]
try:
Expand Down Expand Up @@ -702,12 +693,24 @@ def handle_starttag(self, tag, attrs):
if color:
self.set_text_color(*color)
if tag_style.emphasis:
self.emphasis = tag_style.emphasis
self.emphasis |= tag_style.emphasis
self.set_font(
family=tag_style.family or self.font_family,
size=tag_style.size_pt or self.font_size,
)
if tag in ("blockquote", "center", "code", "dd", "dt", "pre"):
if tag in (
"b",
"blockquote",
"center",
"code",
"em",
"i",
"dd",
"dt",
"pre",
"strong",
"u",
):
is_block = tag in ("blockquote", "center", "dd", "dt", "pre")
if is_block:
self._end_paragraph()
Expand All @@ -723,7 +726,7 @@ def handle_starttag(self, tag, attrs):
if tag_style.color:
self.set_text_color(*tag_style.color.colors255)
if tag_style.emphasis:
self.emphasis = tag_style.emphasis
self.emphasis |= tag_style.emphasis
self.set_font(
family=tag_style.family or self.font_family,
size=tag_style.size_pt or self.font_size,
Expand Down Expand Up @@ -933,14 +936,6 @@ def handle_starttag(self, tag, attrs):
x = self.pdf.get_x()
if self.align and self.align[0].upper() == "C":
x = Align.C
LOGGER.debug(
'image "%s" x=%d y=%d width=%d height=%d',
attrs["src"],
x,
self.pdf.get_y(),
width,
height,
)
self.pdf.image(
self.image_map(attrs["src"]), x=x, w=width, h=height, link=self.href
)
Expand All @@ -962,7 +957,6 @@ def handle_starttag(self, tag, attrs):
self._page_break_after_paragraph = True

def handle_endtag(self, tag):
LOGGER.debug("ENDTAG %s", tag)
while (
self._tags_stack
and tag != self._tags_stack[-1]
Expand All @@ -982,13 +976,6 @@ def handle_endtag(self, tag):
tag,
self._tags_stack[-1],
)
if tag in ("strong", "dt"):
tag = "b"
if tag == "em":
tag = "i"
if tag in ("b", "i", "u"):
if not self.td_th is not None:
self.set_style(tag, False)
if tag == "a":
self.href = ""
if tag == "p":
Expand All @@ -1001,7 +988,19 @@ def handle_endtag(self, tag):
self.set_font(font_face.family, font_face.size_pt)
self.set_text_color(*font_face.color.colors255)
self._end_paragraph()
if tag in ("blockquote", "center", "code", "dd", "dt", "pre"):
if tag in (
"b",
"blockquote",
"center",
"code",
"em",
"i",
"dd",
"dt",
"pre",
"strong",
"u",
):
is_block = tag in ("blockquote", "center", "dd", "dt", "pre")
font_face = self.style_stack.pop()
self.emphasis = font_face.emphasis
Expand Down Expand Up @@ -1061,13 +1060,14 @@ def set_font(self, family=None, size=None, set_default=False):
if size:
self.font_size = size
self.h = size / self.pdf.k
style = self.emphasis.style
LOGGER.debug(f"set_font: %s style=%s h={self.h:.2f}", self.font_family, style)
prev_page = self.pdf.page
if not set_default: # make sure there's at least one font defined in the PDF.
self.pdf.page = 0
if (self.font_family, style) != (self.pdf.font_family, self.pdf.font_style):
self.pdf.set_font(self.font_family, style, self.font_size)
if (self.font_family, self.emphasis) != (
self.pdf.font_family,
self.pdf.emphasis,
):
self.pdf.set_font(self.font_family, self.emphasis.style, self.font_size)
if self.font_size != self.pdf.font_size:
self.pdf.set_font_size(self.font_size)
self.pdf.page = prev_page
Expand All @@ -1080,7 +1080,6 @@ def set_style(self, tag, enable):
else:
self.emphasis = self.emphasis.remove(emphasis)
style = self.emphasis.style
LOGGER.debug("SET_FONT_STYLE %s", style)
prev_page = self.pdf.page
self.pdf.page = 0
self.pdf.set_font(style=style)
Expand All @@ -1104,7 +1103,7 @@ def put_link(self, text):
if tag_style.color:
self.set_text_color(*tag_style.color.colors255)
if tag_style.emphasis:
self.emphasis = tag_style.emphasis
self.emphasis |= tag_style.emphasis
self.set_font(
family=tag_style.family or self.font_family,
size=tag_style.size_pt or self.font_size,
Expand Down
Binary file modified test/html/html_description.pdf
Binary file not shown.
Binary file modified test/html/html_measurement_units.pdf
Binary file not shown.
Binary file modified test/html/html_table_with_bgcolor.pdf
Binary file not shown.
2 changes: 1 addition & 1 deletion test/html/test_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ def test_html_bold_italic_underline(tmp_path):
"""<B>bold</B>
<I>italic</I>
<U>underlined</U>
<B><I><U>all at once!</U></I></B>"""
<b><i><u>all at once!</u></i></b>"""
)
assert_pdf_equal(pdf, HERE / "html_bold_italic_underline.pdf", tmp_path)

Expand Down

0 comments on commit db9a009

Please sign in to comment.