SVG images are now supported in HTML (via `<object> and <embed>` tags).

This commit is contained in:
Georg Brandl 2009-02-18 00:52:12 +01:00
parent 487fdb2b96
commit 298ea6ea5b
7 changed files with 195 additions and 9 deletions

View File

@ -61,6 +61,9 @@ New features added
- Scaled images now get a link to the unscaled version. - Scaled images now get a link to the unscaled version.
- SVG images are now supported in HTML (via ``<object>`` and
``<embed>`` tags).
- Added a ``toctree`` callable to the templates, and the ability - Added a ``toctree`` callable to the templates, and the ability
to include external links in toctrees. The 'collapse' keyword to include external links in toctrees. The 'collapse' keyword
argument indicates whether or not to only display subitems of argument indicates whether or not to only display subitems of

View File

@ -283,6 +283,26 @@ class HTMLTranslator(BaseTranslator):
node['uri'] = posixpath.join(self.builder.imgpath, node['uri'] = posixpath.join(self.builder.imgpath,
self.builder.images[olduri]) self.builder.images[olduri])
if node['uri'].lower().endswith('svg') or \
node['uri'].lower().endswith('svgz'):
atts = {'data': node['uri'], 'type': 'image/svg+xml'}
if 'width' in node:
atts['width'] = node['width']
if 'height' in node:
atts['height'] = node['height']
if 'align' in node:
self.body.append('<div align="%s" class="align-%s">' %
(node['align'], node['align']))
self.context.append('</div>\n')
else:
self.context.append('')
embatts = atts.copy()
embatts['src'] = embatts.pop('data')
self.body.append(self.starttag(node, 'object', '', **atts))
self.body.append(self.emptytag(node, 'embed', '', **embatts))
self.body.append('</object>\n')
return
if node.has_key('scale'): if node.has_key('scale'):
if Image and not (node.has_key('width') if Image and not (node.has_key('width')
and node.has_key('height')): and node.has_key('height')):

View File

@ -23,3 +23,6 @@ Sphinx image handling
.. an image with subdir and unspecified extension .. an image with subdir and unspecified extension
.. image:: subdir/simg.* .. image:: subdir/simg.*
.. an SVG image (for HTML at least)
.. image:: svgimg.*

BIN
tests/root/svgimg.pdf Normal file

Binary file not shown.

158
tests/root/svgimg.svg Normal file
View File

@ -0,0 +1,158 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://web.resource.org/cc/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="60"
width="60"
_SVGFile__filename="oldscale/apps/warning.svg"
version="1.0"
y="0"
x="0"
id="svg1"
sodipodi:version="0.32"
inkscape:version="0.41"
sodipodi:docname="exclamation.svg"
sodipodi:docbase="/home/danny/work/icons/primary/scalable/actions">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0000000"
inkscape:pageshadow="2"
inkscape:zoom="7.5136000"
inkscape:cx="42.825186"
inkscape:cy="24.316071"
inkscape:window-width="1020"
inkscape:window-height="691"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:current-layer="svg1" />
<defs
id="defs3">
<linearGradient
id="linearGradient1160">
<stop
style="stop-color: #000000;stop-opacity: 1.0;"
id="stop1161"
offset="0" />
<stop
style="stop-color:#ffffff;stop-opacity:1;"
id="stop1162"
offset="1" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient1160"
id="linearGradient1163" />
</defs>
<metadata
id="metadata12">
<RDF
id="RDF13">
<Work
about=""
id="Work14">
<title
id="title15">Part of the Flat Icon Collection (Thu Aug 26 14:31:40 2004)</title>
<description
id="description17" />
<subject
id="subject18">
<Bag
id="Bag19">
<li
id="li20" />
</Bag>
</subject>
<publisher
id="publisher21">
<Agent
about=""
id="Agent22">
<title
id="title23" />
</Agent>
</publisher>
<creator
id="creator24">
<Agent
about=""
id="Agent25">
<title
id="title26">Danny Allen</title>
</Agent>
</creator>
<rights
id="rights28">
<Agent
about=""
id="Agent29">
<title
id="title30">Danny Allen</title>
</Agent>
</rights>
<date
id="date32" />
<format
id="format33">image/svg+xml</format>
<type
id="type35"
resource="http://purl.org/dc/dcmitype/StillImage" />
<license
id="license36"
resource="http://creativecommons.org/licenses/LGPL/2.1/">
<date
id="date37" />
</license>
<language
id="language38">en</language>
</Work>
</RDF>
<rdf:RDF
id="RDF40">
<cc:Work
rdf:about=""
id="Work41">
<dc:format
id="format42">image/svg+xml</dc:format>
<dc:type
id="type44"
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="g2099">
<path
style="color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:8.1250000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none"
d="M 55.311891,51.920745 L 4.6880989,51.920744 L 29.999995,8.0792542 L 55.311891,51.920745 z "
id="path1724" />
<path
style="color:#000000;fill:#ffe940;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.1250010;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none"
d="M 55.311891,51.920745 L 4.6880989,51.920744 L 29.999995,8.0792542 L 55.311891,51.920745 z "
id="path1722" />
<path
style="font-size:12.000000;font-weight:900;fill:none;fill-opacity:1.0000000;stroke:#ffffff;stroke-width:8.1250000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
d="M 34.944960,10.779626 L 34.944960,33.186510 C 34.944960,34.752415 34.501979,36.081368 33.616007,37.173380 C 32.750636,38.265402 31.545298,38.811408 29.999995,38.811408 C 28.475302,38.811408 27.269965,38.265402 26.383993,37.173380 C 25.498020,36.060767 25.055030,34.731804 25.055030,33.186510 L 25.055030,10.779626 C 25.055030,9.1931155 25.498020,7.8641562 26.383993,6.7927462 C 27.269965,5.7007332 28.475302,5.1547262 29.999995,5.1547262 C 31.009593,5.1547262 31.885265,5.4019740 32.627010,5.8964706 C 33.389356,6.3909681 33.966274,7.0709005 34.357752,7.9362696 C 34.749221,8.7810349 34.944960,9.7288200 34.944960,10.779626 z "
id="path1099" />
<path
style="font-size:12.000000;font-weight:900;fill:#e71c02;fill-opacity:1.0000000;stroke:none;stroke-width:3.1249981;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1.0000000"
d="M 29.999995,3.5986440 C 28.102272,3.5986440 26.318514,4.3848272 25.156245,5.8173940 C 24.028906,7.1806889 23.499995,8.9087770 23.499995,10.786144 L 23.499995,33.192394 C 23.499995,35.036302 24.050685,36.772771 25.156245,38.161144 C 26.318514,39.593721 28.102273,40.379893 29.999995,40.379894 C 31.913354,40.379894 33.697195,39.576736 34.843745,38.129894 C 35.959941,36.754118 36.499995,35.052976 36.499995,33.192394 L 36.499995,10.786144 C 36.499995,9.5413010 36.276626,8.3551469 35.781245,7.2861440 C 35.278844,6.1755772 34.477762,5.2531440 33.468745,4.5986440 C 32.454761,3.9226545 31.264694,3.5986439 29.999995,3.5986440 z "
id="path835"
sodipodi:nodetypes="cccccccccccc" />
<path
style="color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:5.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none"
d="M 36.506243,49.901522 C 36.506243,53.492972 33.591442,56.407773 29.999991,56.407773 C 26.408541,56.407773 23.493739,53.492972 23.493739,49.901522 C 23.493739,46.310071 26.408541,43.395270 29.999991,43.395270 C 33.591442,43.395270 36.506243,46.310071 36.506243,49.901522 z "
id="path1727" />
<path
style="color:#000000;fill:#e71c02;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:3.1250000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none"
d="M 36.506243,49.901522 C 36.506243,53.492972 33.591442,56.407773 29.999991,56.407773 C 26.408541,56.407773 23.493739,53.492972 23.493739,49.901522 C 23.493739,46.310071 26.408541,43.395270 29.999991,43.395270 C 33.591442,43.395270 36.506243,46.310071 36.506243,49.901522 z "
id="path1725" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@ -59,6 +59,8 @@ HTML_XPATH = {
".//img[@src='_images/img.png']": '', ".//img[@src='_images/img.png']": '',
".//img[@src='_images/img1.png']": '', ".//img[@src='_images/img1.png']": '',
".//img[@src='_images/simg.png']": '', ".//img[@src='_images/simg.png']": '',
".//object[@data='_images/svgimg.svg']": '',
".//embed[@src='_images/svgimg.svg']": '',
}, },
'subdir/images.html': { 'subdir/images.html': {
".//img[@src='../_images/img1.png']": '', ".//img[@src='../_images/img1.png']": '',

View File

@ -56,21 +56,21 @@ def test_images():
htmlbuilder.post_process_images(tree) htmlbuilder.post_process_images(tree)
assert "no matching candidate for image URI u'foo.*'" in \ assert "no matching candidate for image URI u'foo.*'" in \
app._warning.content[-1] app._warning.content[-1]
assert set(htmlbuilder.images.keys()) == set(['subdir/img.png', 'img.png', assert set(htmlbuilder.images.keys()) == \
'subdir/simg.png']) set(['subdir/img.png', 'img.png', 'subdir/simg.png', 'svgimg.svg'])
assert set(htmlbuilder.images.values()) == set(['img.png', 'img1.png', assert set(htmlbuilder.images.values()) == \
'simg.png']) set(['img.png', 'img1.png', 'simg.png', 'svgimg.svg'])
app._warning.reset() app._warning.reset()
latexbuilder = LaTeXBuilder(app, env) latexbuilder = LaTeXBuilder(app, env)
latexbuilder.post_process_images(tree) latexbuilder.post_process_images(tree)
assert "no matching candidate for image URI u'foo.*'" in \ assert "no matching candidate for image URI u'foo.*'" in \
app._warning.content[-1] app._warning.content[-1]
assert set(latexbuilder.images.keys()) == set(['subdir/img.png', assert set(latexbuilder.images.keys()) == \
'subdir/simg.png', set(['subdir/img.png', 'subdir/simg.png', 'img.png', 'img.pdf',
'img.png', 'img.pdf']) 'svgimg.pdf'])
assert set(latexbuilder.images.values()) == set(['img.pdf', 'img.png', assert set(latexbuilder.images.values()) == \
'img1.png', 'simg.png']) set(['img.pdf', 'img.png', 'img1.png', 'simg.png', 'svgimg.pdf'])
def test_second_update(): def test_second_update():
# delete, add and "edit" (change saved mtime) some files and update again # delete, add and "edit" (change saved mtime) some files and update again