Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ This can also be enabled programmatically with `warnings.simplefilter('default',
### Fixed
* SVG: `currentColor` and `inherit` are now read regardless of case, like the color keywords, so `fill="currentcolor"`, as in the Font Awesome icons of many web pages, no longer fails with `ValueError: unsupported color specification currentcolor` - thanks to @RavSinghChandan
* SVG: black or gray text no longer fails with an `AssertionError` when it is in a `<tspan>` that has its own style, as in every text written by Inkscape: the check on the text color left out `DeviceGray`, the color fpdf2 uses for black and gray - thanks to @RavSinghChandan
* `SVGObject.from_file()` reads a file in the encoding it declares, such as `<?xml version="1.0" encoding="iso-8859-1"?>`, like `FPDF.image()` does, instead of always decoding it as UTF-8, which failed with a `UnicodeDecodeError`; an `encoding` given explicitly is still used - thanks to @RavSinghChandan
* SVG: an image without an `xmlns` declaration no longer fails with `ValueError: substring not found` when it contains a tag that is not supported, such as `<title>` or `<script>`; the tag is skipped with a warning, as in an image that declares the namespace - thanks to @RavSinghChandan
* `FPDF.text()` raises a clear `ValueError` for a NaN or infinite `x` or `y`, like `FPDF.set_xy()`, instead of writing `nan` or `inf` into the page, which is not a valid PDF number - thanks to @RavSinghChandan
* SVG: `clip-path="none"`, as written by Inkscape, no longer fails with an `AssertionError`, and a `url(#id)` reference to a clip path whose id contains a `-` or a `.`, or that is quoted, now finds that clip path, instead of failing with a `KeyError` or clipping with another one whose id is the part before the `-` or `.` - thanks to @RavSinghChandan
Expand Down
8 changes: 7 additions & 1 deletion fpdf/svg.py
Original file line number Diff line number Diff line change
Expand Up @@ -1113,7 +1113,7 @@ def from_file(
cls,
filename: str | PathLike[str],
*args: Any,
encoding: str = "utf-8",
encoding: Optional[str] = None,
**kwargs: Any,
) -> "SVGObject":
"""
Expand All @@ -1123,11 +1123,17 @@ def from_file(
filename (path-like): the path to a file containing SVG data.
*args: forwarded directly to the SVGObject initializer. For subclass use.
encoding (str): optional charset encoding to use when reading the file.
By default, the encoding declared by the file is used, as in
`FPDF.image()`, and UTF-8 if it declares none.
**kwargs: forwarded directly to the SVGObject initializer. For subclass use.

Returns:
A converted `SVGObject`.
"""
if encoding is None:
# The XML parser reads the encoding declaration of the file
with open(filename, "rb") as svgfile:
return cls(svgfile.read(), *args, **kwargs)
with open(filename, "r", encoding=encoding) as svgfile:
return cls(svgfile.read(), *args, **kwargs)

Expand Down
26 changes: 26 additions & 0 deletions test/svg/test_svg.py
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,32 @@ def test_svg_text_gray_color_in_styled_tspan(
svg.draw_to_page(pdf)
assert f"{color_operators} [] 0 d BT" in bytes(pdf.output()).decode("latin-1")

@pytest.mark.parametrize(
"declaration, file_encoding, from_file_kwargs",
[
('<?xml version="1.0" encoding="iso-8859-1"?>', "latin-1", {}),
("", "utf-8", {}),
("", "latin-1", {"encoding": "latin-1"}),
],
)
def test_svg_from_file_encoding(
self, tmp_path, declaration, file_encoding, from_file_kwargs
):
svg_path = tmp_path / "text.svg"
svg_path.write_bytes(
(
f'{declaration}<svg xmlns="http://www.w3.org/2000/svg" width="50" '
'height="20"><text x="1" y="10" font-family="helvetica">Z\u00fcrich'
"</text></svg>"
).encode(file_encoding)
)
svg = fpdf.svg.SVGObject.from_file(svg_path, **from_file_kwargs)
pdf = fpdf.FPDF()
pdf.compress = False
pdf.add_page()
svg.draw_to_page(pdf)
assert "(Z\u00fcrich) Tj" in bytes(pdf.output()).decode("latin-1")

def test_svg_symbol(self):
svg_data = (
'<svg xmlns="http://www.w3.org/2000/svg" '
Expand Down
Loading