New Upstream Release - python-svglib
Ready changes
Summary
Merged new upstream version: 1.5.1+dfsg (was: 1.4.1+dfsg).
Resulting package
Built on 2023-02-08T02:15 (took 3m7s)
The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:
apt install -t fresh-releases python3-svglib
Lintian Result
Diff
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000..1dcb0ac
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,13 @@
+If you want to start a discussion rather then open an issue, please use the
+now enabled GitHub [discussions feature for this project](https://github.com/deeplook/svglib/discussions)!
+
+When submitting a new issue please try to be as concise and precise as possible.
+This means to show only minimal SVG or PDF files that show something unexpected.
+
+In times of widely available files infected with malicious code on the net it
+is also appreciated to include bitmap snapshots of your PDFs inside an issue
+description or SVG code on a separate, linked GitHub gist.
+
+Otherwise please provide information where relevant like specific versions of
+components in your setup, e.g. OS, Python, reportlab, svglib, type of install
+or anything else.
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..6164747
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,44 @@
+name: CI
+on: [push, pull_request, workflow_dispatch]
+jobs:
+ tests:
+ name: "Python ${{ matrix.python-version }} on ${{ matrix.os }}"
+ runs-on: "${{ matrix.os }}"
+ strategy:
+ matrix:
+ python-version: ["3.7", "3.8", "3.9", "3.10", "pypy-3.7"]
+ os: ["ubuntu-latest", "macos-latest", "windows-latest"]
+ steps:
+ - uses: "actions/checkout@v3"
+ - name: "Cache for wikipedia flags"
+ uses: actions/cache@v3
+ env:
+ cache-name: "cache-wikipedia-flags"
+ with:
+ path: "tests/samples/wikipedia/flags"
+ key: "wikipedia-flags-${{ matrix.python-version }}-${{ matrix.os }}"
+ - name: "Cache for wikipedia symbols"
+ uses: actions/cache@v3
+ env:
+ cache-name: "cache-wikipedia-symbols"
+ with:
+ path: "tests/samples/wikipedia/symbols"
+ key: "wikipedia-symbols-${{ matrix.python-version }}-${{ matrix.os }}"
+ - name: "Cache for w3c svg12 tinytestsuite"
+ uses: actions/cache@v3
+ env:
+ cache-name: "cache-w3c-svg12-tinytestsuite"
+ with:
+ path: "tests/samples/W3C_SVG_12_TinyTestSuite"
+ key: "w3c-svg12-tinytestsuite-${{ matrix.python-version }}-${{ matrix.os }}"
+ - uses: "actions/setup-python@v4"
+ with:
+ python-version: "${{ matrix.python-version }}"
+ - name: "Install dependencies"
+ run: |
+ python -VV
+ python -m site
+ python -m pip install --upgrade pip setuptools wheel
+ python -m pip install --upgrade virtualenv tox tox-gh-actions
+ - name: "Run tox targets for ${{ matrix.python-version }}"
+ run: "python -m tox"
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 0000000..4085a60
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,50 @@
+name: "CodeQL"
+
+on:
+ push:
+ branches: [ "master" ]
+ pull_request:
+ branches: [ "master" ]
+ schedule:
+ - cron: "40 23 * * 4"
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [ python ]
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: After Prepare
+ run: python3 -m pip install --upgrade --user flake8
+
+ - name: Before Index
+ run: |
+ python3 -m flake8 --version
+ python3 -m flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics
+ python3 -m flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v2
+ with:
+ languages: ${{ matrix.language }}
+ queries: +security-and-quality
+
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@v2
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v2
+ with:
+ category: "/language:${{ matrix.language }}"
diff --git a/.github/workflows/greetings.yml b/.github/workflows/greetings.yml
new file mode 100644
index 0000000..b171c8b
--- /dev/null
+++ b/.github/workflows/greetings.yml
@@ -0,0 +1,16 @@
+name: Greetings
+
+on: [pull_request, issues]
+
+jobs:
+ greeting:
+ runs-on: ubuntu-latest
+ permissions:
+ issues: write
+ pull-requests: write
+ steps:
+ - uses: actions/first-interaction@v1
+ with:
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+ issue-message: 'Thank you for raising your first issue! Your help to improve svglib is much appreciated!'
+ pr-message: 'Thank you for making your first pull request! Your contribution to svglib is highly appreciated!'
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..bf2b547
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,24 @@
+.cache
+.coverage
+MANIFEST
+coverage.xml
+nosetests.xml
+junit-report.xml
+pylint.txt
+toy.py
+violations.pyflakes.txt
+cover/
+build/
+docs/_build
+*.egg-info/
+*.pyc
+*.swp
+*.egg
+env/
+.workon
+dist/
+tests/samples/misc/*-svglib.pdf
+tests/samples/wikipedia/flags
+tests/samples/wikipedia/symbols
+tests/samples/W3C_SVG_12_TinyTestSuite.tar.gz
+tests/samples/W3C_SVG_12_TinyTestSuite/
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 3ef70a1..5f4b9f1 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -3,6 +3,18 @@
ChangeLog
=========
+1.5.1 (2023-01-07)
+------------------
+- Final fix to conversion from shorthand quadratic to cubic bézier (#372).
+
+1.5.0 (2023-01-05)
+------------------
+- Add support for ``ex`` units (assuming for em/2).
+- Add support for ``image/jpg`` embedded images (in addition to ``image/jpeg``).
+- Avoid crash on ``@import`` rules in stylesheets. The rules are simply ignored
+ (#285).
+- Fix conversion from shorthand quadratic to cubic bézier (#364).
+
1.4.1 (2022-08-05)
------------------
- No source code changes, only fixed a leftover set_trace() in the released code
diff --git a/README.rst b/README.rst
index 6b29304..86cbaf3 100644
--- a/README.rst
+++ b/README.rst
@@ -83,8 +83,8 @@ Features
Known limitations
-----------------
-- support for stylesheets is still experimental. Please report any
- bug or shortcoming on the `svglib issue tracker`_.
+- @import rules in stylesheets are ignored. CSS is supported, but the range
+ of supported attributes is still limited
- clipping is limited to single paths, no mask support
- color gradients are not supported (limitation of reportlab)
- SVG ``ForeignObject`` elements are not supported.
diff --git a/debian/changelog b/debian/changelog
index 3f61a3e..d3d9254 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+python-svglib (1.5.1+dfsg-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk> Wed, 08 Feb 2023 02:12:35 -0000
+
python-svglib (1.4.1+dfsg-1) unstable; urgency=medium
* New upstream version 1.4.1+dfsg
diff --git a/setup.cfg b/setup.cfg
index 96689e6..1b44118 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,6 +1,6 @@
[metadata]
name = svglib
-version = 1.4.1
+version = 1.5.1
description = A pure-Python library for reading and converting SVG
long_description = file: README.rst
keywords =
diff --git a/svglib/svglib.py b/svglib/svglib.py
index 026e7d5..727b669 100755
--- a/svglib/svglib.py
+++ b/svglib/svglib.py
@@ -71,10 +71,10 @@ def find_font(font_name, weight='normal', style='normal'):
return _fonts_find_font(font_name, weight, style)
-__version__ = '1.4.1'
+__version__ = '1.5.1'
__license__ = 'LGPL 3'
__author__ = 'Dinu Gherman'
-__date__ = '2022-08-05'
+__date__ = '2023-01-07'
XML_NS = 'http://www.w3.org/XML/1998/namespace'
@@ -133,7 +133,7 @@ class CSSMatcher(cssselect2.Matcher):
)
for rule in rules:
- if not rule.prelude:
+ if not rule.prelude or rule.type == 'at-rule':
continue
selectors = cssselect2.compile_selector_list(rule.prelude)
selector_string = tinycss2.serialize(rule.prelude)
@@ -325,10 +325,14 @@ class Svg2RlgAttributeConverter(AttributeConverter):
return float(text[:-2]) * em_base
elif text.endswith("px"):
return float(text[:-2])
-
- if "ex" in text:
- logger.warning("Ignoring unit ex")
- text = text.replace("ex", '')
+ elif text.endswith("ex"):
+ # The x-height of the text must be assumed to be 0.5em tall when the
+ # text cannot be measured.
+ return float(text[:-2]) * em_base / 2
+ elif text.endswith("ch"):
+ # The advance measure of the "0" glyph must be assumed to be 0.5em
+ # wide when the text cannot be measured.
+ return float(text[:-2]) * em_base / 2
text = text.strip()
length = toLength(text) # this does the default measurements such as mm and cm
@@ -681,7 +685,7 @@ class SvgRenderer:
return None
# First handle any raster embedded image data
- match = re.match(r"^data:image/(jpeg|png);base64", xlink_href)
+ match = re.match(r"^data:image/(jpe?g|png);base64", xlink_href)
if match:
img_format = match.groups()[0]
image_data = base64.decodebytes(xlink_href[(match.span(0)[1] + 1):].encode('ascii'))
@@ -1090,6 +1094,7 @@ class Svg2RlgShapeConverter(SvgShapeConverter):
unclosed_subpath_pointers = []
subpath_start = []
lastop = ''
+ last_quadratic_cp = None
for i in range(0, len(normPath), 2):
op, nums = normPath[i:i+2]
@@ -1164,15 +1169,18 @@ class Svg2RlgShapeConverter(SvgShapeConverter):
elif op == 'Q':
x0, y0 = points[-2:]
x1, y1, xn, yn = nums
+ last_quadratic_cp = (x1, y1)
(x0, y0), (x1, y1), (x2, y2), (xn, yn) = \
convert_quadratic_to_cubic_path((x0, y0), (x1, y1), (xn, yn))
path.curveTo(x1, y1, x2, y2, xn, yn)
elif op == 'T':
- if len(points) < 4:
- xp, yp, x0, y0 = points[-2:] * 2
+ if last_quadratic_cp is not None:
+ xp, yp = last_quadratic_cp
else:
- xp, yp, x0, y0 = points[-4:]
+ xp, yp = points[-2:]
+ x0, y0 = points[-2:]
xi, yi = x0 + (x0 - xp), y0 + (y0 - yp)
+ last_quadratic_cp = (xi, yi)
xn, yn = nums
(x0, y0), (x1, y1), (x2, y2), (xn, yn) = \
convert_quadratic_to_cubic_path((x0, y0), (xi, yi), (xn, yn))
@@ -1183,18 +1191,20 @@ class Svg2RlgShapeConverter(SvgShapeConverter):
x0, y0 = points[-2:]
x1, y1, xn, yn = nums
x1, y1, xn, yn = x0 + x1, y0 + y1, x0 + xn, y0 + yn
+ last_quadratic_cp = (x1, y1)
(x0, y0), (x1, y1), (x2, y2), (xn, yn) = \
convert_quadratic_to_cubic_path((x0, y0), (x1, y1), (xn, yn))
path.curveTo(x1, y1, x2, y2, xn, yn)
elif op == 't':
- if len(points) < 4:
- xp, yp, x0, y0 = points[-2:] * 2
+ if last_quadratic_cp is not None:
+ xp, yp = last_quadratic_cp
else:
- xp, yp, x0, y0 = points[-4:]
+ xp, yp = points[-2:]
x0, y0 = points[-2:]
xn, yn = nums
xn, yn = x0 + xn, y0 + yn
xi, yi = x0 + (x0 - xp), y0 + (y0 - yp)
+ last_quadratic_cp = (xi, yi)
(x0, y0), (x1, y1), (x2, y2), (xn, yn) = \
convert_quadratic_to_cubic_path((x0, y0), (xi, yi), (xn, yn))
path.curveTo(x1, y1, x2, y2, xn, yn)
@@ -1219,6 +1229,9 @@ class Svg2RlgShapeConverter(SvgShapeConverter):
else:
logger.debug("Suspicious path operator: %s", op)
+
+ if op not in ('Q', 'q', 'T', 't'):
+ last_quadratic_cp = None
lastop = op
gr = Group()
diff --git a/tests/test_basic.py b/tests/test_basic.py
index 429f754..bc3d319 100755
--- a/tests/test_basic.py
+++ b/tests/test_basic.py
@@ -566,6 +566,18 @@ class TestStyleSheets:
assert main_group.contents[0].contents[1].contents[0].fontName == 'Helvetica-Bold'
assert main_group.contents[0].contents[2].contents[0].fontName == 'Helvetica'
+ def test_import_rule_no_crash(self):
+ # Just test that svglib does not crash. Import rules are currently ignored.
+ drawing = drawing_from_svg('''
+ <svg>
+ <defs>
+ <style type="text/css">
+ @import url('https://fonts.example.org/css2?family=Ubuntu+Condensed');
+ </style>
+ </defs>
+ </svg>
+ ''')
+
class TestGroupNode:
def test_svg_groups_have_svgid(self):
Debdiff
[The following lists of changes regard files as different if they have different names, permissions or owners.]
Files in second set of .debs but not in first
-rw-r--r-- root/root /usr/lib/python3/dist-packages/svglib-1.5.1.egg-info/PKG-INFO -rw-r--r-- root/root /usr/lib/python3/dist-packages/svglib-1.5.1.egg-info/dependency_links.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/svglib-1.5.1.egg-info/requires.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/svglib-1.5.1.egg-info/top_level.txt
Files in first set of .debs but not in second
-rw-r--r-- root/root /usr/lib/python3/dist-packages/svglib-1.4.1.egg-info/PKG-INFO -rw-r--r-- root/root /usr/lib/python3/dist-packages/svglib-1.4.1.egg-info/dependency_links.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/svglib-1.4.1.egg-info/requires.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/svglib-1.4.1.egg-info/top_level.txt
No differences were encountered in the control files