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

getBbox is incorrect in node.js #1267

Open
testerez opened this issue Mar 31, 2022 · 9 comments
Open

getBbox is incorrect in node.js #1267

testerez opened this issue Mar 31, 2022 · 9 comments

Comments

@testerez
Copy link

testerez commented Mar 31, 2022

I'm trying to calculate the size of an SVG in node but I'm getting incorrect results.

Here is the SVG:

<svg>
    <path d="M126.32 126.32C155.22 97.43 155.22 50.57 126.32 21.67C97.42 -7.22 50.57 -7.22 21.67 21.67C-7.22 50.57 -7.22 97.43 21.67 126.32C50.57 155.22 97.42 155.22 126.32 126.32Z " fill="black"></path>
</svg>

And the node.js code:

import { registerWindow, SVG } from '@svgdotjs/svg.js';
import { createSVGWindow } from 'svgdom';
import { svgString } from '../../svgString';

const window = createSVGWindow();
const { document } = window;
registerWindow(window, document);

const rootSvg = SVG(svgString);
console.log(rootSvg.bbox());

Result:

{
    "x": 21.67,
    "y": 21.67,
    "w": 126.32499999999997,
    "width": 126.32499999999997,
    "h": 126.32499999999997,
    "height": 126.32499999999997,
    "x2": 147.99499999999998,
    "y2": 147.99499999999998,
    "cx": 84.83249999999998,
    "cy": 84.83249999999998
  }

When calculating the bbox the same way in the browser, I'm getting the expected result:

{
    "x": 0.0025005340576171875,
    "y": 0.0025005340576171875,
    "w": 147.99249267578125,
    "width": 147.99249267578125,
    "h": 147.99249267578125,
    "height": 147.99249267578125,
    "x2": 147.99499320983887,
    "y2": 147.99499320983887,
    "cx": 73.99874687194824,
    "cy": 73.99874687194824
  }

(width and height are correct here)

I've put together an example to compare node and browser results here: https://stackblitz.com/edit/nextjs-ct2xan?file=svgString.js

@jameshowe
Copy link

Similar problem, mines related to measuring text elements, the widths seem to be short:

Screenshot 2022-07-23 at 21 02 03

The red rectangle is using the coordinates I get back from getBBox() / getClientBoundingBox(). The width gets shorter the longer the text gets e.g.

Screenshot 2022-07-23 at 21 05 04

@twilson90
Copy link

Similar problem, mines related to measuring text elements, the widths seem to be short:

Screenshot 2022-07-23 at 21 02 03

The red rectangle is using the coordinates I get back from getBBox() / getClientBoundingBox(). The width gets shorter the longer the text gets e.g.

Screenshot 2022-07-23 at 21 05 04

I'm also having the same issue with measuring text elements. My guess is it's using dimensions from another font, default serif maybe.
Any solution?

@Fuzzyma
Copy link
Member

Fuzzyma commented May 4, 2024

Usually if you register your own font properly it should use that one to measure the dimensions. I would need the font file to test that issue

@Fuzzyma
Copy link
Member

Fuzzyma commented Jun 18, 2024

@testerez @jameshowe @twilson90 In order to investigate this I need the font files.

@jameshowe
Copy link

@Fuzzyma the custom font in the example is https://fonts.google.com/specimen/Mansalva (regular), but you can see it happens even with Arial fonts too.

@Fuzzyma
Copy link
Member

Fuzzyma commented Jun 18, 2024

@jameshowe do you have an example for me with Arial? I guess thats easiest to replicate

@jameshowe
Copy link

This was a while ago, I'm not sure I have the code anymore (presume that's what you are after). I'll have a look around.

@jameshowe
Copy link

Ok so thankfully manage to find it, I've tried to strip it back to the smallest possible demonstrable PoC - I am able to replicate the same issue using Arial font with the following code:

import { createSVGWindow } from 'svgdom';
import { SVG, registerWindow } from '@svgdotjs/svg.js';
import { writeFileSync } from 'fs';

const window = createSVGWindow();
const doc = window.document;
registerWindow(window, doc);
// create svg.js instance
const canvas = SVG(doc.documentElement).size(530, 670);
let curOffset = 30
for (let i = 12; i < 30; i++) {
  // render text
  const position = canvas.text(`ARIAL FONT @ ${i}px`);
  position
    .font({
      fill: 'black',
      family: 'Arial',
      size: i
    })
    .move(30, curOffset)
  // render bounding box
  const bounds = position.node.getBoundingClientRect()
  canvas
    .rect(bounds.width, bounds.height)
    .move(bounds.x, bounds.y)
    .fill('#00000000')
    .stroke('red');
  // add some padding between each render
  curOffset += bounds.height + 5
}

await writeFileSync('output.svg', canvas.svg());

For the packages:

@Fuzzyma
Copy link
Member

Fuzzyma commented Aug 29, 2024

Thanks will look into it once I find some time

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

4 participants