Search code examples
pythonpdfsvgopacityreportlab

Opacity issue when saving a SVG in a PDF with Reportlab


I have this SVG file:

<svg version="1.1" viewBox="0 0 390 390" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <line class="arrow" opacity="0.5" stroke="#15781B" stroke-linecap="butt" stroke-width="9.0" x1="307.5" x2="279.60592002787337" y1="352.5" y2="296.7118400557468" />
    <polygon class="arrow" fill="#15781B" opacity="0.5019607843137255" points="264.51246117974983,266.5249223594996 264.5124611797498,304.25856947980856 294.69937887599696,289.165110631685" />
    <text fill="white" font-size="11" font-weight="bold" opacity="0.5" x="264.0" y="291.0">DEF</text>
    <line class="arrow" opacity="0.5019607843137255" stroke="#15781B" stroke-linecap="butt" stroke-width="9.0" x1="262.5" x2="262.5" y1="307.5" y2="255.75" />
    <polygon class="arrow" fill="#15781B" opacity="0.5" points="262.5,222.0 245.625,255.75 279.375,255.75" />
    <text fill="white"  font-size="11" font-weight="bold" opacity="0.5" x="252.0" y="249.0">ABC</text>
</svg>

If you save it as a b.svg file, and open it, you will see that there is some overlapping with opacity : the text ABC and DEF is readable.

Now when I render it in a PDF file with the well-known method from Generating PDFs from SVG input :

from svglib.svglib import svg2rlg
from reportlab.graphics import renderPDF
drawing = svg2rlg("b.svg")
renderPDF.drawToFile(drawing, "b.pdf")

then the opacity is lost in the PDF file, and the left part of the D letter of "DEF" is unreadable:

enter image description here

Question: How to include a SVG into a PDF and keep the opacity?


Solution

  • A quick look at the svglib code shows that svglib does not parse the "opacity" attribute, but it does parse the "fill-opacity" and "stroke-opacity" attributes. So changing your svg to

    <svg version="1.1" viewBox="0 0 390 390" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
        <line class="arrow" fill-opacity="0.5" stroke-opacity="0.5" stroke="#15781B" stroke-linecap="butt" stroke-width="9.0" x1="307.5" x2="279.60592002787337" y1="352.5" y2="296.7118400557468" />
        <polygon class="arrow" fill="#15781B" fill-opacity="0.5019607843137255" stroke-opacity="0.5019607843137255" points="264.51246117974983,266.5249223594996 264.5124611797498,304.25856947980856 294.69937887599696,289.165110631685" />
        <text fill="white" font-size="11" font-weight="bold" fill-opacity="0.5" stroke-opacity="0.5" x="264.0" y="291.0">DEF</text>
        <line class="arrow" fill-opacity="0.5019607843137255" stroke-opacity="0.5019607843137255" stroke="#15781B" stroke-linecap="butt" stroke-width="9.0" x1="262.5" x2="262.5" y1="307.5" y2="255.75" />
        <polygon class="arrow" fill="#15781B" fill-opacity="0.5" stroke-opacity="0.5" points="262.5,222.0 245.625,255.75 279.375,255.75" />
        <text fill="white"  font-size="11" font-weight="bold" fill-opacity="0.5" stroke-opacity="0.5" x="252.0" y="249.0">ABC</text>
    </svg>
    

    should do the trick. enter image description here

    UPDATE

    This seems to be an open issue since 2018