Added
- Declared support for Python 3.14 (added the classifier and CI matrix
entry across Ubuntu, macOS, and Windows, alongside the existing 3.9–3.13). - Clipping paths now support
<circle>,<ellipse>, and<polygon>clip
shapes, in addition to paths and rectangles, and clipping masks referenced
from within a<use>element. - Transforms are now applied to clipping-path shapes, fixing clip paths that
relied on previously unsupported transforms (issue #366). - The gradient shape classes now implement
getBounds(), so drawings that
contain gradient fills can be measured — for example when used as a flowable
by rst2pdf (issue #466).
Changed
- Renamed the gradient shape classes
_LinearGradientShapeand
_RadialGradientShapetoLinearGradientShapeandRadialGradientShape.
They appear in the renderedDrawingtree and were never meant to be
private, so the leading underscore was misleading.
Removed
- Removed the deprecated
_LinearGradientShapeand_RadialGradientShape
aliases. UseLinearGradientShapeandRadialGradientShapeinstead.
Fixed
-
The
visibilityproperty is now respected on shapes. Elements with
visibility="hidden"(orcollapse), set directly or inherited from an
ancestor, were still rendered (issue #359). -
display: noneset through astyleattribute is now respected. Only the
displaypresentation attribute was read, so<g style="display:none">and
<rect style="display:none"/>were still rendered (issue #401). -
Embedded
<image>geometry is no longer truncated to whole points. The
x,y,width, andheightof an SVG<image>were each passed through
int(), so a raster placed at fractional coordinates landed up to ~1pt away
from a vector element with identical coordinates. Because width/height were
truncated too, the error grew across the image rather than being a constant
shift (issue #490). -
font-familyvalues are now split per CSS instead of on whitespace. An
unquoted multi-word name such asfont-family: Cascadia Codewas split into
CascadiaandCode, so a font registered under its full name was never
found (issue #374). Commas inside a quoted name (font-family: "Foo, Bar", Arial) no longer split the list either; that previously handedshlexan
unbalanced quote and raisedValueError: No closing quotation, aborting the
conversion of a valid value. -
Replaced
locale.getdefaultlocale()(used for<switch>systemLanguage
matching) with a small environment-variable lookup.getdefaultlocale()is
deprecated and is removed in Python 3.15; the replacement keeps the same
behaviour, emits no deprecation warning on 3.12–3.14, and adds unit tests for
the language-matching path. -
Clipping paths now support the
clip-ruleattribute instead of incorrectly
usingfill-rule(issue #485). -
fill="url(...)"and gradientxlink:hrefvalues are now matched correctly
when the referenced id is quoted (url('#name'),url("#name")) or
contains a right parenthesis; the previous regex rejected or truncated
these forms. -
Rendering to
reportlab.graphics.renderSVG.SVGCanvas(as used by
easy-thumbnails[svg]) no longer raises
AttributeError: 'SVGCanvas' object has no attribute 'beginPath'when
drawing a clipped gradient; that canvas doesn't implementbeginPath(),
so the gradient's clip path is now skipped on it instead of erroring.
Type safety and internal quality (no behavior change)
- Completed static type annotations for
svglib.py; the package now passes
mypy --stricton its own source, with a single documented per-module
override for the untyped reportlab/cssselect2 base classes it subclasses. - Pinned a
[tool.mypy]configuration inpyproject.tomland now enforce mypy
in CI (newtype-check.ymlworkflow) and via a local pre-commit hook, so type
regressions fail before merge. - Tightened internal gradient handling types: parsed gradient definitions now
use aTypedDictinstead of an opaqueDict[str, Any], and the internal
group/parent parameters are typed asOptional[Group]. - Added docstrings to the remaining undocumented functions in
svglib.py,
bringing documentation coverage to 100%.
Tooling and housekeeping
- Removed the DeepSource configuration. Its checks were redundant with ruff,
mypy --strict, CodeQL, and the pytest matrix, and only produced recurring
noise on pull requests. - Removed the long-defunct
uniconvsample tests. They contained no assertions
and shelled out to UniConvertor, an abandoned Python 2 tool, so they had been
permanently skipped. - Fixed and revived the Windows CI workflow. It was a disabled placeholder that
compiled GTK/Cairo from source (a ~20–40 minute step); it now runs a real
CPython 3.9/3.13 matrix in well under a minute by dropping the source build
and skipping the network-heavy sample tests on Windows (they already run on
Ubuntu and macOS). The redundant manual Windows workflow was removed.