From f20c411f076d8ee8f60508826ba6e3539911f118 Mon Sep 17 00:00:00 2001 From: Lucas Cimon <925560+Lucas-C@users.noreply.github.com> Date: Mon, 20 Nov 2023 11:52:21 +0100 Subject: [PATCH] Supporting tags from SVG files --- fpdf/svg.py | 41 ++++++++++++++++++ test/svg/generated_pdf/text-samples.pdf | Bin 0 -> 1241 bytes test/svg/parameters.py | 1 + .../svg_sources/embedded-raster-images.svg | 2 +- test/svg/svg_sources/text-samples.svg | 13 ++++++ 5 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 test/svg/generated_pdf/text-samples.pdf create mode 100644 test/svg/svg_sources/text-samples.svg diff --git a/fpdf/svg.py b/fpdf/svg.py index fc9d0f7da..f4c1e3818 100644 --- a/fpdf/svg.py +++ b/fpdf/svg.py @@ -852,6 +852,8 @@ def handle_defs(self, defs): self.build_path(child) elif child.tag in xmlns_lookup("svg", "image"): self.build_image(child) + elif child.tag in xmlns_lookup("svg", "text"): + self.build_text(child) elif child.tag in shape_tags: self.build_shape(child) elif child.tag in xmlns_lookup("svg", "clipPath"): @@ -926,6 +928,8 @@ def build_group(self, group, pdf_group=None): pdf_group.add_item(self.build_xref(child), False) elif child.tag in xmlns_lookup("svg", "image"): pdf_group.add_item(self.build_image(child), False) + elif child.tag in xmlns_lookup("svg", "text"): + pdf_group.add_item(self.build_text(child), False) else: LOGGER.warning( "Ignoring unsupported SVG tag: <%s> (contributions are welcome to add support for it)", @@ -984,6 +988,43 @@ def apply_clipping_path(self, stylable, svg_element): clipping_path_id = re.search(r"url\((\#\w+)\)", clipping_path) stylable.clipping_path = self.cross_references[clipping_path_id[1]] + @force_nodocument + def build_text(self, text): + if "dx" in text.attrib or "dy" in text.attrib: + raise NotImplementedError( + '"dx" / "dy" defined on is currently not supported (but contributions are welcome!)' + ) + if "lengthAdjust" in text.attrib: + raise NotImplementedError( + '"lengthAdjust" defined on is currently not supported (but contributions are welcome!)' + ) + if "rotate" in text.attrib: + raise NotImplementedError( + '"rotate" defined on is currently not supported (but contributions are welcome!)' + ) + if "style" in text.attrib: + raise NotImplementedError( + '"style" defined on is currently not supported (but contributions are welcome!)' + ) + if "textLength" in text.attrib: + raise NotImplementedError( + '"textLength" defined on is currently not supported (but contributions are welcome!)' + ) + if "transform" in text.attrib: + raise NotImplementedError( + '"transform" defined on is currently not supported (but contributions are welcome!)' + ) + font_family = text.attrib.get("font-family") + font_size = text.attrib.get("font-size") + # TODO: reuse code from line_break & text_region modules. + # We could either: + # 1. handle text regions in this module (svg), with a dedicated SVGText class. + # 2. handle text regions in the drawing module, maybe by defining a PaintedPath.text() method. + # This may be the best approach, as we would benefit from the global transformation performed in SVGObject.transform_to_rect_viewport() + svg_text = None + self.update_xref(text.attrib.get("id"), svg_text) + return svg_text + @force_nodocument def build_image(self, image): href = None diff --git a/test/svg/generated_pdf/text-samples.pdf b/test/svg/generated_pdf/text-samples.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8124b0b1f2689e7e649bae89e632024875c74d59 GIT binary patch literal 1241 zcmah}O=uHA6b7jx+k-`_! z1wmT$AmY`7e`pUDi{i!7n+HXOS`?+AAUzaOP{f0H(Kq>NmK5wOSlkqCp$EKTQgrA-vE8O@NqW!7>cR?U-sWR?sA641~=ebOos#3oEETSlp1 zR?QBg@RIc+vQBiv8h4eU5F6-Cf=%Kee>Emw&){Ud4;lbGZ~`<`vm~)&mFx_5P{<91f_CAcCF?lUyg{%HJsLW}3eH$r%&>#l z94Ds`FLE@>AvV?vO!-Foa|J+|bw*LS>>v`}q`FUlvY~NN}+lRikUHzdwVztEb z_1!zC!@aA+`(7^3f86S2jP6~nxo0b5T4w01r+xm6G57w($SAqD*0mJszg=Mrv@cO2ndnQJt}%QM7K$W&`?NXyxv$sW&Qy~w_}a~ literal 0 HcmV?d00001 diff --git a/test/svg/parameters.py b/test/svg/parameters.py index 22a744fb2..e4f5533b9 100644 --- a/test/svg/parameters.py +++ b/test/svg/parameters.py @@ -783,6 +783,7 @@ def Gs(**kwargs): svgfile("path_clippingpath.svg"), id=" containing a used in a group with color - issue #1147", ), + pytest.param(svgfile("text-samples.svg"), id=" tests"), ) svg_path_edge_cases = ( diff --git a/test/svg/svg_sources/embedded-raster-images.svg b/test/svg/svg_sources/embedded-raster-images.svg index ffef5b6ed..ddb936169 100644 --- a/test/svg/svg_sources/embedded-raster-images.svg +++ b/test/svg/svg_sources/embedded-raster-images.svg @@ -1,7 +1,7 @@ - Example image.svg - embedding raster images + Example embedded-raster-images.svg diff --git a/test/svg/svg_sources/text-samples.svg b/test/svg/svg_sources/text-samples.svg new file mode 100644 index 000000000..281f15112 --- /dev/null +++ b/test/svg/svg_sources/text-samples.svg @@ -0,0 +1,13 @@ + + + Example text-samples.svg + + + + My + cat + is + Grumpy! + +