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

Different baseline rendering positions are different to node-canvas #209

Open
loveloki opened this issue Dec 18, 2024 · 0 comments
Open

Comments

@loveloki
Copy link

When set different baseline, the rendering positions are different to node-canvas.

Code

Click to show the code
import { createCanvas } from "canvas";
import fs from "node:fs";
import { Canvas } from "skia-canvas";

// skia-canvas
let skiaCanvas = new Canvas(1000, 1000);

testDrawText(skiaCanvas, "skia-canvas");

await skiaCanvas.saveAs("skia-canvas.pdf");

// node-canvas
let nodeCanvas = new createCanvas(1000, 1000, "pdf");
nodeCanvas.getContext("2d").textDrawingMode = "glyph";

testDrawText(nodeCanvas, "node-canvas");

fs.writeFileSync("node-canvas.pdf", nodeCanvas.toBuffer());

function testDrawText(canvas, tip) {
  const crossLineHalfWidth = 25;
  const step = 60;
  const x = 50;
  let y = 60;
  let fontFamily = "zcool-gdh";
  let text = "The quick brown fox jumps over the lazy dog";

  let ctx = canvas.getContext("2d");

  ctx.strokeStyle = "purple";
  ctx.fillStyle = "black";
  ctx.lineWidth = 1;
  ctx.font = `normal 20pt '${fontFamily}'`;

  const baselines = ["top", "hanging", "middle", "alphabetic", "ideographic", "bottom"];

  drawTextWithTip(tip);

  baselines.forEach((baseline, index) => drawTextWithCrossLine(text, x, y + step * (index + 1), baseline));

  y = 600;
  fontFamily = "Times new Roman";
  ctx.font = `normal 12pt '${fontFamily}'`;
  text = "Abcdefg";

  drawTextWithLine(text, x + 100, y);

  function drawTextWithCrossLine(text, x, y, baseline) {
    ctx.textBaseline = baseline;

    ctx.fillText(`${text}(${baseline})`, x, y);

    ctx.moveTo(x - crossLineHalfWidth, y);
    ctx.lineTo(x + crossLineHalfWidth, y);
    ctx.stroke();

    ctx.moveTo(x, y - crossLineHalfWidth);
    ctx.lineTo(x, y + crossLineHalfWidth);
    ctx.stroke();
  }

  function drawTextWithLine(text, x, y) {
    ctx.moveTo(0, y);
    ctx.lineTo(x + 1000, y);
    ctx.stroke();

    baselines.forEach((baseline, index) => {
      const newX = x + step * 2 * index;

      ctx.textBaseline = "alphabetic";
      ctx.fillText(baseline, newX, y - step);

      ctx.textBaseline = baseline;
      ctx.fillText(text, newX, y);
    });
  }

  function drawTextWithTip(text) {
    ctx.textBaseline = "alphabetic";
    ctx.fillText(text, x, y);
  }
}

result

image
image

file

This is is the result PDF and font file: all-file.zip

Question

  1. Position is different to node-cnavas, maybe this is a issue like as TextMetrics & rendered text changed from v1.0.2 to v^2.0.0 #208
  2. Font metrics height very different, I use measureText api, the result is this:
skia-canvas metrics is:  TextMetrics {
  width: 26.670000076293945,
  actualBoundingBoxLeft: 0,
  actualBoundingBoxRight: 26.670000076293945,
  actualBoundingBoxAscent: 26.073354721069336,
  actualBoundingBoxDescent: 5.926646709442139,
  fontBoundingBoxAscent: 26.073354721069336,
  fontBoundingBoxDescent: 5.926646709442139,
  emHeightAscent: 26.073354721069336,
  emHeightDescent: 5.926646709442139,
  hangingBaseline: 16.53333282470703,
  alphabeticBaseline: 0,
  ideographicBaseline: -5.926646709442139,
  lines: [
    {
      x: 0,
      y: -26.073354721069336,
      width: 26.670000076293945,
      height: 32,
      baseline: 0,
      startIndex: 0,
      endIndex: 6
    }
  ]
}
node-canvas metrics is:  {
  width: 26.666015625,
  actualBoundingBoxLeft: 1.83984375,
  actualBoundingBoxRight: 24.826171875,
  actualBoundingBoxAscent: 17.759765625,
  actualBoundingBoxDescent: -1.4404296875,
  emHeightAscent: 22.90625,
  emHeightDescent: 3.759765625,
  alphabeticBaseline: -0.0263671875
}

And In chrome, metrics is:

web-canvas metrics is:  {
  actualBoundingBoxAscent: 17.75555992126465,
  actualBoundingBoxDescent: -1.4396400451660156,
  actualBoundingBoxLeft: -1.839539885520935,
  actualBoundingBoxRight: 24.820459365844727,
  alphabeticBaseline: -0,
  fontBoundingBoxAscent: 23,
  fontBoundingBoxDescent: 4,
  hangingBaseline: 18.399999618530273,
  ideographicBaseline: -4,
  width: 26.659988403320312,
}

See the result, the width is basically the same, but the height is very different(skia-canvas is 32 and node-cnavas is 26.67, web-canvas is 27). Is this caused by different calculation algorithms for font metrics? The difference in metrics between node-canvas and web-canvas is even smaller.

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