Skip to content

Commit d25967d

Browse files
authored
Merge pull request #946 from adroitwhiz/fix-0x0
Fix SVG costume dimensions appearing as 0x0 in GUI
2 parents 4afa7f5 + cacb115 commit d25967d

File tree

2 files changed

+70
-4
lines changed

2 files changed

+70
-4
lines changed

src/SVGSkin.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,12 +196,17 @@ class SVGSkin extends Skin {
196196
const svgText = serializeSvgToString(svgTag, true /* shouldInjectFonts */);
197197
this._svgImageLoaded = false;
198198

199+
const {x, y, width, height} = svgTag.viewBox.baseVal;
200+
// While we're setting the size before the image is loaded, this doesn't cause the skin to appear with the wrong
201+
// size for a few frames while the new image is loading, because we don't emit the `WasAltered` event, telling
202+
// drawables using this skin to update, until the image is loaded.
203+
// We need to do this because the VM reads the skin's `size` directly after calling `setSVG`.
204+
// TODO: return a Promise so that the VM can read the skin's `size` after the image is loaded.
205+
this._size[0] = width;
206+
this._size[1] = height;
207+
199208
// If there is another load already in progress, replace the old onload to effectively cancel the old load
200209
this._svgImage.onload = () => {
201-
const {x, y, width, height} = svgTag.viewBox.baseVal;
202-
this._size[0] = width;
203-
this._size[1] = height;
204-
205210
if (width === 0 || height === 0) {
206211
super.setEmptyImageData();
207212
return;

test/integration/skin-size-tests.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/* global render, ImageData */
2+
const {chromium} = require('playwright-chromium');
3+
const test = require('tap').test;
4+
const path = require('path');
5+
6+
const indexHTML = path.resolve(__dirname, 'index.html');
7+
8+
// immediately invoked async function to let us wait for each test to finish before starting the next.
9+
(async () => {
10+
const browser = await chromium.launch();
11+
const page = await browser.newPage();
12+
13+
await page.goto(`file://${indexHTML}`);
14+
15+
await test('SVG skin size set properly', async t => {
16+
t.plan(1);
17+
const skinSize = await page.evaluate(() => {
18+
const skinID = render.createSVGSkin(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 100"></svg>`);
19+
return render.getSkinSize(skinID);
20+
});
21+
t.same(skinSize, [50, 100]);
22+
});
23+
24+
await test('Bitmap skin size set correctly', async t => {
25+
t.plan(1);
26+
const skinSize = await page.evaluate(() => {
27+
// Bitmap costumes are double resolution, so double the ImageData size
28+
const skinID = render.createBitmapSkin(new ImageData(100, 200), 2);
29+
return render.getSkinSize(skinID);
30+
});
31+
t.same(skinSize, [50, 100]);
32+
});
33+
34+
await test('Pen skin size set correctly', async t => {
35+
t.plan(1);
36+
const skinSize = await page.evaluate(() => {
37+
const skinID = render.createPenSkin();
38+
return render.getSkinSize(skinID);
39+
});
40+
const nativeSize = await page.evaluate(() => render.getNativeSize());
41+
t.same(skinSize, nativeSize);
42+
});
43+
44+
await test('Text bubble skin size set correctly', async t => {
45+
t.plan(1);
46+
const skinSize = await page.evaluate(() => {
47+
const skinID = render.createTextSkin('say', 'Hello', false);
48+
return render.getSkinSize(skinID);
49+
});
50+
// The subtleties in font rendering may cause the size of the text bubble to vary, so just make sure it's not 0
51+
t.notSame(skinSize, [0, 0]);
52+
});
53+
54+
// close the browser window we used
55+
await browser.close();
56+
})().catch(err => {
57+
// Handle promise rejections by exiting with a nonzero code to ensure that tests don't erroneously pass
58+
// eslint-disable-next-line no-console
59+
console.error(err.message);
60+
process.exit(1);
61+
});

0 commit comments

Comments
 (0)