deeplook / svglib

Read SVG files and convert them to other formats.
GNU Lesser General Public License v3.0
325 stars 79 forks source link

Embedding SVG fonts in PDF/rlg #388

Open rocketinventor opened 1 year ago

rocketinventor commented 1 year ago

Hi, I am using svglib in order to embed a PDF (using rebortlab).

The code looks like this:

from svglib.svglib import svg2rlg
from reportlab.pdfgen import canvas

...

    c = canvas.Canvas(output_pdf, pagesize=letter)

...

            # convert SVG to a ReportLab drawing object
            drawing = svg2rlg(img_file)
            # set the canvas size to match the drawing size
            c.setPageSize((drawing.width, drawing.height))
            # render the drawing on the PDF canvas
            renderPDF.draw(drawing, c, 0, 0)

I have a svg with an embedded font:

<?xml version='1.0' encoding='UTF-8'?>
  <svg id="qoppa_document" width="595pt" height="842pt" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><!-- jPDFWeb v2023R1.00, Build #19 -->
    <style>title p { display: block; }</style>
    <style type="text/css">
        @font-face {font-family:f0-0;src:url("data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAARUAAoAAAAABSQAAQABAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAAA9AAAADYAAABWW/VcTmNtYXAAAAEsAAAAOAAAAEQAmwCcZ2x5ZgAAAWQAAAHDAAAB5M+9k4doZWFkAAADKAAAADAAAAA2JlqhUmhoZWEAAANYAAAAIAAAACQK+gI4aG10eAAAA3gAAAAbAAAAHA
...

When it converts to a drawing object, I get messages like so:

Unable to find a suitable font for 'font-family:f0-0', weight:normal, style:normal

(as described in #284)

I know that it is possible to suppress these warnings, but that is not so helpful since the resulting PDF does not look right at all. In this case, a specialized font is needed, and it does not work otherwise.

Ill-rendered PDF

This is what it is supposed to look like: Correctly rendered One font is used for the title, and a different, specialized font is used for "engraving" the notation.

Is there any way to embed the font data into the rlg object/PDF? If there is a way to render the text to a path, that would also be helpful as an alternative route to explore.

Please advise,

Thanks!

github-actions[bot] commented 1 year ago

Thank you for raising your first issue! Your help to improve svglib is much appreciated!

rocketinventor commented 1 year ago

Also, if this is a limitation with svglib, what type of work would be needed in order to make it work (ie. properly parse and embed the font-face) into the rlg?

deeplook commented 1 year ago

I'm not sure fonts embedded in CSS are really supported in svglib. The README says: "CSS is supported, but the range of supported attributes is still limited." @claudep is the expert here.

Typically you need to register fonts with reportlab, if you want to use them, see their docs and/or the test suite.

claudep commented 1 year ago

I can confirm that embedded font definitions is not supported by svglib.

svglib is extracting the font family names in svg files, then try to register them with Reportlab (some of that code is in https://github.com/deeplook/svglib/blob/master/svglib/fonts.py). So the path to the font file should be available on the current system. I don't see a ~simple way to workaround this for embedded fonts.

deeplook commented 1 year ago

One font is used for the title, and a different, specialized font is used for "engraving" the notation.

If lilypond is an option for you, you can generate SVG output for it and throw it at svglib. It works with some minor glitch that could be worked around or fixed. I've even worked on it, but it will take me some while to find it again. Here is a (boring) example SVG and snapshot of the PDF:

tmpfmll596q-1