p5.js icon indicating copy to clipboard operation
p5.js copied to clipboard

[p5.js 2.0 Beta Bug Report]: Some google fonts don't load

Open davepagurek opened this issue 11 months ago • 14 comments

Most appropriate sub-area of p5.js?

  • [ ] Accessibility
  • [ ] Color
  • [ ] Core/Environment/Rendering
  • [ ] Data
  • [ ] DOM
  • [ ] Events
  • [ ] Image
  • [ ] IO
  • [ ] Math
  • [x] Typography
  • [ ] Utilities
  • [ ] WebGL
  • [ ] Build process
  • [ ] Unit testing
  • [ ] Internationalization
  • [ ] Friendly errors
  • [ ] Other (specify if possible)

p5.js version

2.0 beta 1

Web browser and version

Firefox

Operating system

MacOS

Steps to reproduce this

I'm not sure what the difference is, but I was playing around with loading google fonts, and I have an example of one that works and one that doesn't:

let font

async function setup() {
  createCanvas(400, 400);
  
  // ok
  // font = await loadFont('https://fonts.googleapis.com/css2?family=Sniglet:wght@400;800&display=swap')
  
  // not ok?
  font = await loadFont('https://fonts.googleapis.com/css2?family=Jersey+10&display=swap')
}

function draw() {
  background(220);
  textFont(font)
  textSize(20)
  text('test', 50, 50)
}

Live: https://editor.p5js.org/davepagurek/sketches/c8__rjh8_

Anyone have any ideas what Jersey 10 does that Sniglet doesn't that would the error Failed to create FontFace for "Jersey 10" to be thrown? Maybe the number in the name?

davepagurek avatar Jan 22 '25 00:01 davepagurek

hey @davepagurek i tried with more fonts but all fonts loading are failing , here is the code when font are loaded in p5js,

p5.prototype.loadFont = function(path, onSuccess, onError) {
  p5._validateParameters('loadFont', arguments);
  const p5Font = new p5.Font(this);

  const self = this;
  opentype.load(path, (err, font) => {
    if (err) {
      p5._friendlyFileLoadError(4, path);
      if (typeof onError !== 'undefined') {
        return onError(err);
      }
      console.error(err, path);
      return;
    }

    p5Font.font = font;

issue is that opentype.js only supports font imported from any file or array buffer and not from direct url, like, opentype.load('fonts/Roboto-Black.ttf', function(err, font) {...

do you planning to support fonts from remote urls in p5js? I am glad to continue as my first issue.

Sahil-Gupta584 avatar Feb 11 '25 16:02 Sahil-Gupta584

Hi @Sahil-Gupta584, I believe the code you're looking at is on the main branch, which is for p5 1.x. We've changed up how font loading works in 2.0, which lives on the dev-2.0 branch. The new implementation of loadFont is here: https://github.com/processing/p5.js/blob/d17c3ee4ddc7353874c3f4120d813df939da634f/src/type/p5.Font.js#L530

We've replaced OpenType with Typr, a smaller dependency, and also don't rely on it at all for drawing in 2D mode, which instead can deal with CSS directly.

davepagurek avatar Feb 11 '25 16:02 davepagurek

@davepagurek I am trying to solve this issue but i am unable to setup dev environment , i switched to dev 2.0 branch ,npm run dev, but i am seeing a simple canvas element on localhost, where to i test my fonts?

Sahil-Gupta584 avatar Feb 12 '25 15:02 Sahil-Gupta584

Hi @davepagurek! maybe the issue isn't strictly related to google fonts.

I encountered a similar issue today trying to load the SFCompact font locally. The error reported was WARN: No glyph data for 'd615b059-33a5-4636-95fd-94d405ecb07b', retrying as FontFace, and since I was trying to use webGL I also get a WEBGL: only Opentype (.otf) and Truetype (.ttf) fonts are supported, despite having loaded a .ttf file. The font loads just fine for both the canvas renderer and webgl in 1.11.3.

Here's my sample sketch https://editor.p5js.org/aferriss/sketches/3CLsXYiXd

It seems like the font does load when not in webgl mode, or at least there's some fallback that allows a font to render (though I'm unsure it was the one I was trying to load).

Happy to open a separate issue if you think it's unrelated.

Image

aferriss avatar Feb 12 '25 17:02 aferriss

The issue here is that we get glyph data for some fonts and not others. Loading them via FontFace is a fallback that allows the font to render in 2D, but without the glyph data such fonts can't be used in webgl or textToX functions... The messaging probably needs to be cleaned up here so that this is more clear. The other question is of course why we're not getting glyph data for a .ttf file. When I test that font file in the typr demo it works correctly, so something else is going on that we'll need to look into...

dhowe avatar Feb 13 '25 14:02 dhowe

@dhowe do you think the original sketch in the issue has the same issue? It's all in the 2D renderer so FontFace should be sufficient. Maybe something again with the face that there's a space and a number in the name?

davepagurek avatar Feb 13 '25 14:02 davepagurek

@dhowe do you think the original sketch in the issue has the same issue? It's all in the 2D renderer so FontFace should be sufficient. Maybe something again with the face that there's a space and a number in the name?

what do you see when you run that sketch? I get:

Image

dhowe avatar Feb 13 '25 15:02 dhowe

Oh interesting, maybe it's a Firefox specific issue? I get this:

Image

davepagurek avatar Feb 13 '25 15:02 davepagurek

Oh interesting, maybe it's a Firefox specific issue? I get this:

confirmed here as well - spaces cause this error in FF, fixed in #7555

dhowe avatar Feb 13 '25 16:02 dhowe

@aferriss this should be fixed in #7555

dhowe avatar Feb 13 '25 16:02 dhowe

Reviving this issue -- while the original issue is fixed, there are still some font files that won't parse.

One example: this google font seems to throw an error in Typr after decompressing the woff2 and having pako: https://editor.p5js.org/davepagurek/sketches/MCLVYBut4 image

One other instance that @ksen0 found: https://editor.p5js.org/davepagurek/sketches/PHwST-bh6

davepagurek avatar Apr 13 '25 17:04 davepagurek

It seems like there are other differences between woff2 and woff other than just Brotli compression, possibly some differences in how the tables are structured? If someone with more domain knowledge knows what would have to be done to support this (either preprocessing the data before it goes to Typr, or via a patch to Typr), feel free to chime in!

davepagurek avatar Apr 13 '25 17:04 davepagurek

So yes, there is more to parsing a woff2 than simply decompressing. I'm also not sure if they need to parsed completely or if they can be converted easily to another format that we already handle (eg woff). Here are a few js examples that do it:

https://github.com/bramstein/opentype https://github.com/foliojs/fontkit WOFF2Font.js https://github.com/fontello/wawoff2

For example (from an opentype issue):

<script src="https://unpkg.com/[email protected]/build/decompress_binding.js"></script>
<form>
    <label>Decompress:
        <input type=file accept=".woff2" onchange="files[0].arrayBuffer().then(buf=>form.size.innerText=Module.decompress(buf).length)">
    </label>
</form>

Ideally we could extract the woff2 bits from one of these and test it (perhaps in @davepagurek's addon), then discuss how much code this adds and whether it is worth including

dhowe avatar Apr 13 '25 17:04 dhowe

The wawoff2 example is more or less what the woff2 addon is currently doing: https://github.com/davepagurek/p5.woff2/blob/634e84e939385657e48e5fa1299e5766ea363d51/src/p5.woff2.js#L14-L15 So Based on the variable names in their decompress script, the decompressed version should be a ttf already? Maybe there's still something weird about the ttf data?

Another option is to try using a different library for the woff2 handling in case there are some edge cases that wawoff2 isn't handling that we're hitting.

davepagurek avatar Apr 13 '25 18:04 davepagurek