Skip to content

Commit 0b3e7c3

Browse files
authored
Merge pull request #179 from paulkaplan/fix-bbox-strokes
Enlarge bounding box by the largest stroke width.
2 parents 77c163e + ab4046b commit 0b3e7c3

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

src/svg-quirks-mode/svg-renderer.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,34 @@ class SvgRenderer {
162162
this._svgTag.insertBefore(newDefs, this._svgTag.childNodes[0]);
163163
}
164164

165+
/**
166+
* Find the largest stroke width in the svg. If a shape has no
167+
* `stroke` property, it has a stroke-width of 0. If it has a `stroke`,
168+
* it is by default a stroke-width of 1.
169+
* This is used to enlarge the computed bounding box, which doesn't take
170+
* stroke width into account.
171+
* @param {SVGSVGElement} rootNode The root SVG node to traverse.
172+
* @return {number} The largest stroke width in the SVG.
173+
*/
174+
_findLargestStrokeWidth (rootNode) {
175+
let largestStrokeWidth = 0;
176+
const collectStrokeWidths = domElement => {
177+
if (domElement.getAttribute) {
178+
if (domElement.getAttribute('stroke')) {
179+
largestStrokeWidth = Math.max(largestStrokeWidth, 1);
180+
}
181+
if (domElement.getAttribute('stroke-width')) {
182+
largestStrokeWidth = Math.max(largestStrokeWidth, Number(domElement.getAttribute('stroke-width')));
183+
}
184+
}
185+
for (let i = 0; i < domElement.childNodes.length; i++) {
186+
collectStrokeWidths(domElement.childNodes[i]);
187+
}
188+
};
189+
collectStrokeWidths(rootNode);
190+
return largestStrokeWidth;
191+
}
192+
165193
/**
166194
* Transform the measurements of the SVG.
167195
* In Scratch 2.0, SVGs are drawn without respect to the width,
@@ -203,6 +231,15 @@ class SvgRenderer {
203231
this._svgDom = parser.parseFromString(svgText, 'text/xml');
204232
this._svgTag = this._svgDom.documentElement;
205233

234+
// Enlarge the bbox from the largest found stroke width
235+
// This may have false-positives, but at least the bbox will always
236+
// contain the full graphic including strokes.
237+
const halfStrokeWidth = this._findLargestStrokeWidth(this._svgTag) / 2;
238+
bbox.width += halfStrokeWidth * 2;
239+
bbox.height += halfStrokeWidth * 2;
240+
bbox.x -= halfStrokeWidth;
241+
bbox.y -= halfStrokeWidth;
242+
206243
// Set the correct measurements on the SVG tag, and save them.
207244
this._svgTag.setAttribute('width', bbox.width);
208245
this._svgTag.setAttribute('height', bbox.height);

0 commit comments

Comments
 (0)