在 SVG 元素的 ForeignObject HTML 中呈现自定义外部字体时遇到问题

Having trouble rendering a custom external font within a ForeignObject's HTML of an SVG element

这是一个复杂的问题。我创建了一个 Chrome 扩展,它将通过 WebSocket 从客户端接收 JSON-RPC 请求,使用 HTML 修饰呈现文本,并使用 PNG 图像响应客户端。我正在使用一个 Canvas 和一个 SVG 元素来使用包含我正在呈现的 HTML 的 foreignObject 标记来呈现文本。除了当我需要使用外部字体时,这一切都很棒。这里发生了三个间接级别,所以也许我对浏览器的要求太多了;但我希望不会。

您可能认为直接将文本呈现为 SVG 是一种选择,但这意味着我将失去 HTML 提供的一些丰富功能,例如自动换行。有一些 SVG 自动换行的技巧,但我不想走那条路。这可能只是我遇到的许多问题中的第一个。

我需要的是让 SVG 标签内的 HTML 识别我希望它使用的外部字体。这只需要在 Chromium 中工作,所以针对 Chromium 的解决方案对我来说是一个可行的选择。

<link rel='preload' href='https://fonts.gstatic.com/s/roboto/v27/KFOkCnqEu92Fr1MmgVxIIzI.woff2' as='font' crossorigin='anonymous' />
<style>@font-face { font-family: Roboto; src: url('https://fonts.gstatic.com/s/roboto/v27/KFOkCnqEu92Fr1MmgVxIIzI.woff2'); } body { font-family: Roboto; font-size: 28px; }</style>
<canvas style='position:absolute; top:90px; left:394px;' id='canvas'></canvas>
<div><span style="font-family:courier; font-size:20px">External straight-HTML (works): </span>Hello World!</div><br/>
<span style='font-family:courier; font-size:20px'>HTML within SVG (doesn't work): </span><br/><br/>
<span style='font-family:courier; font-size:20px'>&nbsp;&nbsp;Text directly to SVG (works): </span><br/><br/>

<script>

   // Get the canvas element from the above HTML and an associated context.
    var canvas = document.querySelector('#canvas');
    var ctx = canvas.getContext('2d');

    // Create an empty SVG image.
    var svg = new Image();

    // Before we set the svg.src value, we need to define what to do 
    // immediately after the svg element has completed loading.
    svg.onload = function() {

        // DOES NOT RENDER USING CORRECT FONT HERE.
        // Draw the image into the canvas context.  This is the HTML
        // source containing the foreign object that I wish to render
        // using the external font.
        ctx.drawImage(svg, 0, 0);
    
        // Prove that the SVG element itself can use the external font.
        // THIS WORKS, but is not what I want.
        ctx.font = "28px Roboto";
        ctx.fillText("Hello World!", 0, 80);
   }

    // Build HTML to create a SVG image generated from HTML.
    var source = "<svg xmlns='http://www.w3.org/2000/svg'>"
               + "<foreignObject width='2000' height='800' overflow='visible'>"
               + "<div xmlns='http://www.w3.org/1999/xhtml'>" 
               + "<link rel='preload' href='https://fonts.gstatic.com/s/roboto/v27/KFOkCnqEu92Fr1MmgVxIIzI.woff2' as='font' type='font/woff2' crossorigin='anonymous' />"
               + "<style>@font-face { font-family: Roboto; src: url('https://fonts.gstatic.com/s/roboto/v27/KFOkCnqEu92Fr1MmgVxIIzI.woff2); } body { font-family: Roboto; font-size: 28px; }</style>"
               + "<div>Hello World!</div>"
               + "</div>"
               + "</foreignObject>"
               + "</svg>";

    // This doesn't always work because sometimes the font isn't yet available even though we've theoretically preloaded the font.
    svg.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(source);

</script>

特别感谢 Robert Longson 让我走上了正确的道路。主要问题是当您设置 SVG 的 src 数据值时,您的 SVG 数据必须包含在该源数据中绘制图像所需的一切。使用异物时也是如此。这与在 HTML canvas 上绘制 SVG 图像非常不同。因此(连同其他一些小的更改)外部字体本身必须是该 src 数据的一部分,因此您必须提供包含该字体数据的数据 URL。我必须做的另一件事是在 div 的样式中明确指定要使用的字体。

<style id="myStyle">@font-face { font-family: Roboto; src: url('data:application/octet-stream;base64,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'); } body { font-family: Roboto; font-size: 28px; }</style>
<canvas style='position:absolute; top:75px; left:394px;' id='canvas'></canvas>
<div><span style="font-family:courier; font-size:20px">External straight-HTML (works): </span>Hello World!</div><br/>
<span style='font-family:courier; font-size:20px'>&nbsp;&nbsp;&nbsp;HTML within SVG (now works): </span><br/><br/>
<span style='font-family:courier; font-size:20px'>&nbsp;&nbsp;Text directly to SVG (works): </span><br/><br/>

<script>

    // Get the canvas element from the above HTML and an associated context.
    var canvas = document.querySelector('#canvas');
    var ctx = canvas.getContext('2d');

    // Create an empty SVG image.
    var svg = new Image();

    // Before we set the svg.src value, we need to define what to do 
    // immediately after the svg element has completed loading.
    svg.onload = function() {

        // Draw the image into the canvas context.  This is the HTML
        // source containing the foreign object that I wish to render
        // using the external font.  THIS NOW WORKS.
        ctx.drawImage(svg, 0, 0);
    
        // Prove that the SVG element itself can use the external font.
        // THIS WORKS, but is not what I want.
        ctx.font = "28px Roboto";
        ctx.fillText("Hello World!", 0, 95);
    }

    // Hacky way of getting the data URI from the above HTML.
    // I would have just duplicated the data URI below, but Stack 
    // Overflow limits the size of this source, and that would make
    // it too big, so I have to programmatically extract it.
    var dataUri = document.getElementById("myStyle").innerText.split("url('")[1].split("');")[0];
    
    // Build HTML to create a SVG image generated from HTML.
    var source = "<svg xmlns='http://www.w3.org/2000/svg'>"
    
               // Beginning of foreign object.
               + "<foreignObject width='2000' height='800' overflow='visible'><div xmlns='http://www.w3.org/1999/xhtml'>" 

               // This NOW WORKS inside of the foreign object.
               + "<style>@font-face { font-family: Roboto; src: url('" + dataUri + "'); }</style>"
               + "<div style='font-family:Roboto; font-size:28px'>Hello World!</div>"

               // End of foreign object.
               + "</div></foreignObject>"
               + "</svg>";

    // Set the SVG source data now.
    svg.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(source);

</script>