Skip to content

Commit

Permalink
Fixing a bug with string width calculation when Markdown is enabled - c…
Browse files Browse the repository at this point in the history
…lose #351
  • Loading branch information
Lucas-C committed Mar 7, 2022
1 parent fb1ea17 commit 525dbc5
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 24 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/),
and [PEP 440](https://www.python.org/dev/peps/pep-0440/).

## [2.5.2] - not released yet
### Fixed
- a bug with string width calculation when Markdown is enabled - _cf._ [#351](https://github.com/PyFPDF/fpdf2/issues/351)

## [2.5.1] - 2022-03-07
### Added
Expand Down
47 changes: 23 additions & 24 deletions fpdf/fpdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -2124,7 +2124,12 @@ def _render_styled_cell_text(
styled_txt_width = text_line.text_width / 1000 * self.font_size
if not styled_txt_width:
for styled_txt_frag in text_line.fragments:
styled_txt_width += self.get_string_width(styled_txt_frag.string)
unscaled_width = self.get_normalized_string_width_with_style(
styled_txt_frag.string, styled_txt_frag.style
)
if self.font_stretching != 100:
unscaled_width *= self.font_stretching / 100
styled_txt_width += unscaled_width * self.font_size / 1000
if w == 0:
w = self.w - self.r_margin - self.x
elif w is None:
Expand Down Expand Up @@ -2212,18 +2217,15 @@ def _render_styled_cell_text(
s += " 0 Tw"
self.ws = 0
for frag in text_line.fragments:
txt_frag = frag.string
style = frag.style
underline = frag.underline
if self.font_style != style:
self.font_style = style
if self.font_style != frag.style:
self.font_style = frag.style
self.current_font = self.fonts[
self.font_family + self.font_style
]
s += f" /F{self.current_font['i']} {self.font_size_pt:.2f} Tf"
style_changed = True
txt_frag_mapped = ""
for char in txt_frag:
for char in frag.string:
uni = ord(char)
txt_frag_mapped += chr(self.current_font["subset"].pick(uni))

Expand All @@ -2241,12 +2243,12 @@ def _render_styled_cell_text(
if not is_last_word:
adj = -(word_spacing * self.k) * 1000 / self.font_size_pt
s += f"{adj:.3f}({space}) "
if underline:
underlines.append((self.x + dx + s_width, txt_frag))
self.underline = underline
if frag.underline:
underlines.append((self.x + dx + s_width, frag.string))
self.underline = frag.underline
s_width += self.get_string_width(
txt_frag, True
) + word_spacing * txt_frag.count(" ")
frag.string, True
) + word_spacing * frag.string.count(" ")
s += "] TJ"
else:
if word_spacing and word_spacing != self.ws:
Expand All @@ -2256,19 +2258,16 @@ def _render_styled_cell_text(
self.ws = word_spacing

for frag in text_line.fragments:
txt_frag = frag.string
style = frag.style
underline = frag.underline
if self.font_style != style:
self.font_style = style
if self.font_style != frag.style:
self.font_style = frag.style
self.current_font = self.fonts[
self.font_family + self.font_style
]
s += f" /F{self.current_font['i']} {self.font_size_pt:.2f} Tf"
style_changed = True
if self.unifontsubset:
txt_frag_mapped = ""
for char in txt_frag:
for char in frag.string:
uni = ord(char)
txt_frag_mapped += chr(
self.current_font["subset"].pick(uni)
Expand All @@ -2278,14 +2277,14 @@ def _render_styled_cell_text(
txt_frag_mapped.encode("utf-16-be").decode("latin-1")
)
else:
txt_frag_escaped = escape_parens(txt_frag)
txt_frag_escaped = escape_parens(frag.string)
s += f" ({txt_frag_escaped}) Tj"
if underline:
underlines.append((self.x + dx + s_width, txt_frag))
self.underline = underline
if frag.underline:
underlines.append((self.x + dx + s_width, frag.string))
self.underline = frag.underline
s_width += self.get_string_width(
txt_frag, True
) + self.ws * txt_frag.count(" ")
frag.string, True
) + self.ws * frag.string.count(" ")
s += " ET"
# Restoring font style & underline mode after handling changes
# by Markdown annotations:
Expand Down
Binary file added test/html/html_table_with_empty_cell_contents.pdf
Binary file not shown.
27 changes: 27 additions & 0 deletions test/html/test_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,33 @@ def test_img_inside_html_table_centered_with_caption(tmp_path):
)


def test_html_table_with_empty_cell_contents(tmp_path): # issue 349
pdf = MyFPDF()
pdf.set_font_size(30)
pdf.add_page()
# Reference table cells positions:
pdf.write_html(
"""<table><thead><tr>
<th width="25%">left</th><th width="50%">center</th><th width="25%">right</th>
</tr></thead><tbody><tr>
<td>1</td><td>2</td><td>3</td>
</tr><tr>
<td>4</td><td>5</td><td>6</td>
</tr></tbody></table>"""
)
# Table with empty cells:
pdf.write_html(
"""<table><thead><tr>
<th width="25%">left</th><th width="50%">center</th><th width="25%">right</th>
</tr></thead><tbody><tr>
<td>1</td><td></td><td>3</td>
</tr><tr>
<td></td><td>5</td><td></td>
</tr></tbody></table>"""
)
assert_pdf_equal(pdf, HERE / "html_table_with_empty_cell_contents.pdf", tmp_path)


def test_html_justify_paragraph(tmp_path):
pdf = MyFPDF()
pdf.add_page()
Expand Down
Binary file modified test/text/cell_markdown_right_aligned.pdf
Binary file not shown.

0 comments on commit 525dbc5

Please sign in to comment.