vscode-drawio
                                
                                 vscode-drawio copied to clipboard
                                
                                    vscode-drawio copied to clipboard
                            
                            
                            
                        Bundled offline version gets custom fonts wrong in bundled png image format, when rendering the png
Using: Updated extension (1.6.2), vs code, windows 10.
Issue: ("custom") Fonts are not used, and text is rendered incorrectly when saving diagram as bundled file (e g .drawio.png).
Repro:
- Create diagram using plugin. Save to device. Add shape (rectangle) with some text.
- Set font of shape to use e g "Roboto" (open font by Google, see https://fonts.google.com/specimen/Roboto)
- Save diagram.
Expected result:
(a) Roboto is used in shape in editor (after step 2) and (b) rendered png bitmap is created using the Roboto font.
Actual result:
(a) Roboto is indeed correctly used in the editor (after step 2)

but
(b) the png image is not correctly rendered with the font, but instead seems to default to a serif (times new roman...?) font instead:

Analysis
This works using the online drawio version (v.14.9.9): If I open the test diagram in diagrams.net and save it, I get the expected result (b): The rendered png image is created correctly using the Roboto font.
So, this extension bundles an older drawio version for its offline use. That may explain the issue?

The following script
import os
import xml.etree.ElementTree as ET
import re
import requests
import base64
ET.register_namespace('', "http://www.w3.org/2000/svg")
ET.register_namespace('xlink', "http://www.w3.org/1999/xlink")
currentDir = os.path.dirname(__file__)
def get_fonts_css(fontURL, embed=True):
    headers = {
        "User-Agent":
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 " +
        "(KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36"
    }
    r = requests.get(fontURL, headers=headers)
    if r.status_code != 200:
        raise RuntimeError(f"Failed to get fonts css: '{fontURL}', '{r}'")
    if ".woff" not in r.text:
        raise RuntimeError("Failed to get woff fonts.")
    # Embed all fonts
    prefix = "data:font/{0};charset=utf-8;base64,"
    res = r.text
    if embed:
        def repl(match):
            url = match.group(1)
            print(f"Embedding '{url}' ...")
            ext = os.path.splitext(url)[1].strip(".")
            r = requests.get(url, headers=headers)
            if r.status_code != 200:
                raise RuntimeError(f"Failed to get fonts: '{url}', '{r}'")
            return "url({0})".format(
                prefix.format(ext) +
                base64.b64encode(r.content).decode(encoding="utf-8"))
        res, _ = re.subn(r"url\((.*?)\)", repl, res)
    return res
def replace_fonts(f, fontsCSS):
    print(f"Replace fonts in {f}")
    xml = ET.parse(f)
    root = xml.getroot()
    s = root.findall(".//{*}style")
    s[0].text = fontsCSS
    xml.write(f, encoding="utf-8")
fontURL = "https://fonts.googleapis.com/css?family=Fira+Code:i,b,r|Fira+Sans:i,b,r"  # noqa: E501
fontsCSS = get_fonts_css(fontURL)
f = os.path.join(currentDir, "Workflow.svg")
replace_fonts(f, fontsCSS)
Replaces fonts in the svg, for a working workaround.
Replaces fonts in the svg, for a working workaround.
Thanks! That is interesting and related - but this issue is about png, not svg.
AFAIK drawio cannot successfully bundle fonts in svg, at all. I am pretty sure there is an issue for this in the drawio project here on github.
However, drawio does handle fonts successfully for png, so there is something off about this vs code plugin not getting the same result. Which is what this issue is about. :-)