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

[p5.js 2.0 Bug Report]: textToPoints/Paths/Contours does not quite align with regular text rendering

Open davepagurek opened this issue 2 weeks ago • 4 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.1.1

Web browser and version

Firefox, Chrome

Operating system

MacOS

Steps to reproduce this

Steps:

  1. Draw a font using textToContours
  2. Draw the same text using text

Ideally these should line up. It's generally a little different. e.g. in this visualization, textToContours is in red, and regular text is in blue:

Image

This varies per font, and also is slightly different on WebGL vs 2D mode. It's OK if it's not perfect, but it can be quite off.

Snippet:

let testWebGL = true
let font;
// let fontSrc = 'https://fonts.gstatic.com/s/inter/v20/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuLyfMZhrib2Bg-4.ttf'
// let fontSrc = 'https://fonts.gstatic.com/s/raleway/v36/1Ptxg8zYS_SKggPN4iEgvnHyvveLxVvaooCPNLA3JC9c.ttf'
// let fontSrc = 'https://fonts.gstatic.com/s/hennypenny/v18/wXKvE3UZookzsxz_kjGSfMQqt3M7tMDT.ttf'
// let fontSrc = 'https://fonts.gstatic.com/s/breeserif/v18/4UaHrEJCrhhnVA3DgluAx63j5pN1MwI.ttf'
// let fontSrc = 'https://fonts.gstatic.com/s/poppins/v24/pxiByp8kv8JHgFVrLCz7V1tvFP-KUEg.ttf'
let fontSrc = 'https://fonts.gstatic.com/s/inknutantiqua/v16/Y4GRYax7VC4ot_qNB4nYpBdaKU2_xbj5bBoIYJNf.ttf';

async function setup() {
  font = await loadFont(fontSrc);
  createCanvas(400, 400, testWebGL ? WEBGL : P2D);
}

function draw() {
  background(255);
  push()
  if (!testWebGL) translate(width/2, height/2)
  textAlign(CENTER, CENTER);
  textSize(80);
  blendMode(MULTIPLY);

  // Get the point array.
  let contours = font.textToContours("p5*js", 0, 0, { sampleFactor: 0.5 });

  noStroke();
  fill("red");

  beginShape();
  for (const pts of contours) {
    beginContour();
    for (const pt of pts) {
      vertex(pt.x, pt.y);
    }
    endContour(CLOSE);
  }
  endShape();

  fill("blue");
  textFont(font);
  text("p5*js", 0, 0);
  pop()
}

Live: https://editor.p5js.org/davepagurek/sketches/lmA-l9GMJ

davepagurek avatar Dec 03 '25 15:12 davepagurek

@davepagurek did you (or could you) include textToPoints() in this comparison?

dhowe avatar Dec 03 '25 15:12 dhowe

Similar issue, since all of the textToPoints/Paths/Contours functions go through the same base alignment code:

Image

https://editor.p5js.org/davepagurek/sketches/cBK1cymYK

davepagurek avatar Dec 03 '25 15:12 davepagurek

so if you move the textFont() call to the top, the alignments match... which suggests to me that somewhere we are using the renderer's font, instead of the font on which these functions are called

Image

perhaps here: https://github.com/processing/p5.js/blob/dev-2.0/src/type/p5.Font.js#L989

though, in webgl mode, alignment is closer but still not quite right

Image

dhowe avatar Dec 03 '25 15:12 dhowe

I think I figured out the webgl shift, needed to account for the alphabeticBaseline. I just put up a PR with that, lmk what you think! live version here: https://editor.p5js.org/davepagurek/sketches/VPrz_2Wff

davepagurek avatar Dec 03 '25 17:12 davepagurek