From 64d84829b3038b6acf0142128f32f7d2bf23a46d Mon Sep 17 00:00:00 2001
From: CpDong <93034081+Bubbu0129@users.noreply.github.com>
Date: Tue, 27 Dec 2022 09:02:43 +0800
Subject: [PATCH] Fix #632:
without "height" attribute fails to leave
enough blank space for itself (#634)
Fixes https://github.com/PyFPDF/fpdf2/issues/632
---
CHANGELOG.md | 2 ++
fpdf/fpdf.py | 4 +++-
fpdf/html.py | 4 +++-
test/html/test_html.py | 15 +++++++++++++++
...html_table_without_explicit_dimensions.pdf | Bin 14780 -> 14788 bytes
test/html/test_img_not_overlapping.pdf | Bin 0 -> 11198 bytes
test/image/test_load_image.py | 2 +-
test/test_perfs.py | 2 +-
8 files changed, 25 insertions(+), 4 deletions(-)
create mode 100644 test/html/test_img_not_overlapping.pdf
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 004ab4140..b2beddee2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,7 @@ This can also be enabled programmatically with `warnings.simplefilter('default',
## [2.6.1] - not released yet
### Added
+* ensured support for Python 3.11
* the `x` parameter of [`FPDF.image()`](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.image) now accepts a value of `"C"` / `Align.C` / `"R"` / `Align.R` to horizontally position the image centered or aligned right
* support for `[]()` links when `markdown=True`
* support for `line-height` attribute of paragraph (`
`) in `write_html()` - thanks to @Bubbu0129
@@ -28,6 +29,7 @@ This can also be enabled programmatically with `warnings.simplefilter('default',
### Fixed
* a `ValueError: Incoherent hierarchy` could be raised when using `write_html()` with some headings hierarchy
* performance issue with adding large images with `FlateDecode` image filter
+* image (`
`) without `height` attribute overlaps with the following content [#632](https://github.com/PyFPDF/fpdf2/issues/632)
## [2.6.0] - 2022-11-20
### Added
diff --git a/fpdf/fpdf.py b/fpdf/fpdf.py
index b120d139f..4b6b5e769 100644
--- a/fpdf/fpdf.py
+++ b/fpdf/fpdf.py
@@ -3585,7 +3585,7 @@ def image(
if link:
self.link(x, y, w, h, link)
- return info
+ return {**info, "rendered_width": w, "rendered_height": h}
def _vector_image(
self,
@@ -3647,6 +3647,8 @@ def _vector_image(
if link:
self.link(x, y, w, h, link)
+ return {"rendered_width": w, "rendered_height": h}
+
def _downscale_image(self, name, img, info, w, h):
width_in_pt, height_in_pt = w * self.k, h * self.k
lowres_name = f"lowres-{name}"
diff --git a/fpdf/html.py b/fpdf/html.py
index 740362bad..acb774217 100644
--- a/fpdf/html.py
+++ b/fpdf/html.py
@@ -636,9 +636,11 @@ def handle_starttag(self, tag, attrs):
width,
height,
)
- self.pdf.image(
+ image_info = self.pdf.image(
self.image_map(attrs["src"]), x, y, width, height, link=self.href
)
+ width = image_info["rendered_width"]
+ height = image_info["rendered_height"]
self.pdf.set_x(x + width)
if self.table_col_index is not None:
#
in a
: we grow the cell height according to the image height:
diff --git a/test/html/test_html.py b/test/html/test_html.py
index 878ca0902..a6e43a6b7 100644
--- a/test/html/test_html.py
+++ b/test/html/test_html.py
@@ -621,6 +621,21 @@ def test_html_custom_line_height(tmp_path):
assert_pdf_equal(pdf, HERE / "html_custom_line_height.pdf", tmp_path)
+def test_img_not_overlapping(tmp_path):
+ pdf = FPDF()
+ pdf.add_page()
+ pdf.write_html(
+ """
+text
+"""
+ )
+ assert_pdf_equal(
+ pdf,
+ HERE / "test_img_not_overlapping.pdf",
+ tmp_path,
+ )
+
+
def test_warn_on_tags_not_matching(caplog):
pdf = FPDF()
pdf.add_page()
diff --git a/test/html/test_img_inside_html_table_without_explicit_dimensions.pdf b/test/html/test_img_inside_html_table_without_explicit_dimensions.pdf
index 0500abe3537b2f38358894f4cf2cf2d2176d87b4..78983577fac863fc2217f3c63477ea3827f9a727 100644
GIT binary patch
delta 397
zcmdl}e580oC1bsbF_)bkS8+*EYGN)|#hltcYc3{70oKo!N4ZTaZ{Pjw@5*|%WoKiO
zLWe|UZFxXsz_q%_V3E`t)`@2-c7z_@5V|6e3>wvCIx0*02}KL0VH<9*Z9K+qmzc!OYF)O@5lzuaOl=Jh55!NlvqH24}G0VfApCFeZI@wwGjG!jRTh+w;
z&i8L-{$}YYHUF|%lxdb(y@|1c0SGAMDR6-q1_ov(M(ARe<_0EcVul8$1{N4%W)|k?
zVkSlg=;j%k7#l(CovdeR5$EV=?&R!jX=vbLU}0uyVr=YWVrF1$X6S5bW@2DuW@=|c
dP(>^xfD?;KDvDCmxPTT|m~yGAy863u0RWC5csl?9
diff --git a/test/html/test_img_not_overlapping.pdf b/test/html/test_img_not_overlapping.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..d65c643d9e21644832a8079afd6a4b5da22e000e
GIT binary patch
literal 11198
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 |