svgdotjs / svgdom

Straightforward DOM implementation to make SVG.js run headless on Node.js
MIT License
269 stars 53 forks source link

Rotating a curve gives unexpected bounding rect #80

Closed Tschrock closed 2 years ago

Tschrock commented 3 years ago

Given a curved path with a rotation applied

<path d="M 100,100 c 100,-100 300,100 200,200 z" transform="rotate(45)"></path>

Preview ![test-bug2](https://user-images.githubusercontent.com/2406499/127681346-82a0804c-e093-4543-9f11-b983971ec0a6.png)

I expect the bounding rectangle returned by element.getBoundingClientRect() to give me the outer bounds of the shape (or at the very least fully contain the shape). Currently, svgdom cuts off part of the curve.

Expected

test-bug2

Actual

test-bug2

Test code ```js const { createSVGWindow } = require('svgdom') const document = createSVGWindow().document; const root = document.documentElement; root.setAttribute("xmlns", "http://www.w3.org/2000/svg"); root.setAttribute("viewBox", "0 0 500 500"); root.setAttribute("width", "500"); root.setAttribute("height", "500"); root.setAttribute("stroke-width", "5"); // Add a curved shape const shape = document.createElementNS("http://www.w3.org/2000/svg", 'path'); shape.setAttribute("fill", "none"); shape.setAttribute("stroke", "blue"); shape.setAttribute("d", "M 100,100 c 100,-100 300,100 200,200 z"); shape.setAttribute("transform", "translate(200) rotate(45)"); root.appendChild(shape); // Get the shape bounds const bounds = shape.getBoundingClientRect(); // Add the bounding box const shapeBox = document.createElementNS("http://www.w3.org/2000/svg", 'rect'); shapeBox.setAttribute("x", bounds.x); shapeBox.setAttribute("y", bounds.y); shapeBox.setAttribute("width", bounds.width); shapeBox.setAttribute("height", bounds.height); shapeBox.setAttribute("fill", "none"); shapeBox.setAttribute("stroke", "green"); root.appendChild(shapeBox); console.log(root.outerHTML); ```
SVG result ```svg ```

Extra note

It looks like Chrome and Firefox don't agree on what the bounding box should be either, but both of them fully contain the shape. I'm not sure what the specs say about this situation.

Chrome ![ss1627660402-ae29](https://user-images.githubusercontent.com/2406499/127679254-3f1843e3-9004-4776-ac98-42c14038bcc2.png)
Firefox ![ss1627660439-ec7c](https://user-images.githubusercontent.com/2406499/127679316-abdbd874-7385-4fda-bd72-bd035e0dbc41.png)
Fuzzyma commented 2 years ago

haha, FF and Chrome are wildly different :D. The situation is actually quite clear. Transformation does not matter for bounding box calculation. Therefore the bounding box should be the one of the unrotated arc.

Will investigate whats going wrong with our implementation

Fuzzyma commented 2 years ago

Scratch that. You used getBoundingClientRect. In that case transform matters.

Fuzzyma commented 2 years ago

Release as 0.1.10. Good catch. I needed to change a key concept of how boxes are calculated