Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

actualBoundingBox failing when facing some non-default characters, though when .fillText() - they're rendered completely okay #831

Open
polnikale opened this issue May 16, 2024 · 0 comments

Comments

@polnikale
Copy link

For most of the symbols and languages .actualBoundingBoxLeft/Right works 100% correctly and shows super accurate data, thanks for that

Unfortunately, for some languages(and also with emojis) it fails

Looks at the code:

const initGlobalCanvas = () => {
  GlobalFonts.registerFromPath(
    path.resolve(__dirname, "..", "AppleColorEmoji.ttf"),
    "Apple Color Emoji"
  );
  GlobalFonts.registerFromPath(
    path.resolve(__dirname, "..", "NotoSansArabic-Regular.ttf"),
    "Noto Sans Arabic Regular"
  );
  // ....
};

const testIssue = () => {
  initGlobalCanvas();
  const width = 1000;
  const height = 1500;
  console.log("ORDER - initing canvas");
  const canvas = createCanvas(width, height);
  const ctx = canvas.getContext("2d");

const testIssue = async () => {
  initGlobalCanvas();
  const width = 1000;
  const height = 1500;
  console.log("ORDER - initing canvas");
  const canvas = createCanvas(width, height);
  const ctx = canvas.getContext("2d");

  ctx.font = "50px Arial, Apple Color Emoji, Noto Sans Arabic Regular";

  const runTest = () => {
    const firstOk = ctx.measureText("Default text");
    const secondUkrNotOk = ctx.measureText("Defaulї text");
    const thirdEmojiNotOk = ctx.measureText("Defaul😊 text");
    const fourthNotOk = ctx.measureText("Defaulلم text");
    const fifthOk = ctx.measureText("Defaulű text");

    console.log(
      "firstOk",
      firstOk.actualBoundingBoxLeft,
      firstOk.actualBoundingBoxRight,
      firstOk.width
    );
    console.log(
      "secondUkrNotOk",
      secondUkrNotOk.actualBoundingBoxLeft,
      secondUkrNotOk.actualBoundingBoxRight,
      secondUkrNotOk.width
    );
    console.log(
      "thirdEmojiNotOk",
      thirdEmojiNotOk.actualBoundingBoxLeft,
      thirdEmojiNotOk.actualBoundingBoxRight,
      thirdEmojiNotOk.width
    );
    console.log(
      "fourthNotOk",
      fourthNotOk.actualBoundingBoxLeft,
      fourthNotOk.actualBoundingBoxRight,
      fourthNotOk.width
    );
    console.log(
      "fifthOk",
      fifthOk.actualBoundingBoxLeft,
      fifthOk.actualBoundingBoxRight,
      fifthOk.width
    );

    ctx.fillText("Default text", 500, 500);
    ctx.fillText("Defaulї text", 500, 600);
    ctx.fillText("Defaul😊 text", 500, 700);
    ctx.fillText("Defaulلم text", 500, 800);
    ctx.fillText("Defaulű text", 500, 900);
  };

  console.log("left");
  runTest();

  ctx.textAlign = "center";

  ctx.clearRect(0, 0, width, height);

  ctx.fillStyle = "white";
  ctx.fillRect(0, 0, width, height);
  ctx.fillStyle = "black";

  console.log("center");
  runTest();

  const buffer = canvas.toBuffer("image/png");

  const folderPath = path.join(__dirname, "images");
  const filePath = path.join(folderPath, `test.png`);

  await writeFile(filePath, buffer);
};

When I run testIssue - that's what result I see

left
firstOk 0 50.802734375 50.58000183105469
secondUkrNotOk 0 28.6845703125 50.58000183105469
thirdEmojiNotOk 0 28.6845703125 55.29999923706055
fourthNotOk 0 28.6845703125 53.25
fifthOk 0 53.5859375 53.36000061035156
center
firstOk 25.290000915527344 25.512733459472656 50.58000183105469
secondUkrNotOk 25.290000915527344 3.3945693969726562 50.58000183105469
thirdEmojiNotOk 27.649999618530273 1.0345706939697266 55.29999923706055
fourthNotOk 26.625 2.0595703125 53.25
fifthOk 26.68000030517578 26.90593719482422 53.36000061035156

It seems like that actualBoundingBoxRight stop at the moment it sees the non-expected symbol. You can see that all of them have pretty much same right. In every example I replaced "t" with a different symbol

But for some cases, for a lot of languages - it works correctly. I'm not sure why. I have all the fonts for all the languages installed. It works correctly for japanese and korean, but seems to be failing for some arabic, ukrainian, and emojis

As you can see on the image provided, all the fonts are rendered correctly. It's just measurement which is wrong

test

Would be great if you could take a look

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant