Skip to content

Commit 00c91f9

Browse files
committed
remove all SVG image related functionality
I think this is going to have to come back in JS via canvg or something. librsvg is too much of a pain (tons of dependencies) and doesn't integrate with our fonts anyways.
1 parent b701a5e commit 00c91f9

5 files changed

Lines changed: 1 addition & 263 deletions

File tree

src/Image.cc

Lines changed: 1 addition & 195 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,6 @@ Image::Image(const Napi::CallbackInfo& info) : ObjectWrap<Image>(info), env(info
8686
width = height = 0;
8787
naturalWidth = naturalHeight = 0;
8888
state = DEFAULT;
89-
#ifdef HAVE_RSVG
90-
_rsvg = NULL;
91-
_is_svg = false;
92-
_svg_last_width = _svg_last_height = 0;
93-
#endif
9489
}
9590

9691
/*
@@ -210,13 +205,6 @@ Image::clearData() {
210205
free(filename);
211206
filename = NULL;
212207

213-
#ifdef HAVE_RSVG
214-
if (_rsvg != NULL) {
215-
g_object_unref(_rsvg);
216-
_rsvg = NULL;
217-
}
218-
#endif
219-
220208
width = height = 0;
221209
naturalWidth = naturalHeight = 0;
222210
state = DEFAULT;
@@ -310,18 +298,6 @@ Image::loadFromBuffer(uint8_t *buf, unsigned len) {
310298
#endif
311299
}
312300

313-
// confirm svg using first 1000 chars
314-
// if a very long comment precedes the root <svg> tag, isSVG returns false
315-
unsigned head_len = (len < 1000 ? len : 1000);
316-
if (isSVG(buf, head_len)) {
317-
#ifdef HAVE_RSVG
318-
return loadSVGFromBuffer(buf, len);
319-
#else
320-
this->errorInfo.set("node-canvas was built without SVG support");
321-
return CAIRO_STATUS_READ_ERROR;
322-
#endif
323-
}
324-
325301
if (isBMP(buf, len))
326302
return loadBMPFromBuffer(buf, len);
327303

@@ -397,22 +373,6 @@ Image::loaded() {
397373
* Returns this image's surface.
398374
*/
399375
cairo_surface_t *Image::surface() {
400-
#ifdef HAVE_RSVG
401-
if (_is_svg && (_svg_last_width != width || _svg_last_height != height)) {
402-
if (_surface != NULL) {
403-
cairo_surface_destroy(_surface);
404-
_surface = NULL;
405-
}
406-
407-
cairo_status_t status = renderSVGToSurface();
408-
if (status != CAIRO_STATUS_SUCCESS) {
409-
g_object_unref(_rsvg);
410-
Napi::Error::New(env, cairo_status_to_string(status)).ThrowAsJavaScriptException();
411-
412-
return NULL;
413-
}
414-
}
415-
#endif
416376
return _surface;
417377
}
418378

@@ -462,31 +422,8 @@ Image::loadSurface() {
462422
#endif
463423
}
464424

465-
// confirm svg using first 1000 chars
466-
// if a very long comment precedes the root <svg> tag, isSVG returns false
467-
uint8_t head[1000] = {0};
468-
fseek(stream, 0 , SEEK_END);
469-
long len = ftell(stream);
470-
unsigned head_len = (len < 1000 ? len : 1000);
471-
unsigned head_size = head_len * sizeof(uint8_t);
472-
rewind(stream);
473-
if (head_size != fread(&head, 1, head_size, stream)) {
474-
fclose(stream);
475-
return CAIRO_STATUS_READ_ERROR;
476-
}
477-
rewind(stream);
478-
if (isSVG(head, head_len)) {
479-
#ifdef HAVE_RSVG
480-
return loadSVG(stream);
481-
#else
482-
this->errorInfo.set("node-canvas was built without SVG support");
483-
return CAIRO_STATUS_READ_ERROR;
484-
#endif
485-
}
486-
487425
if (isBMP(buf, 2))
488426
return loadBMP(stream);
489-
490427
fclose(stream);
491428

492429
this->errorInfo.set("Unsupported image type");
@@ -1460,115 +1397,6 @@ Image::rotatePixels(uint8_t* pixels, int width, int height, int channels,
14601397

14611398
#endif /* HAVE_JPEG */
14621399

1463-
#ifdef HAVE_RSVG
1464-
1465-
/*
1466-
* Load SVG from buffer
1467-
*/
1468-
1469-
cairo_status_t
1470-
Image::loadSVGFromBuffer(uint8_t *buf, unsigned len) {
1471-
_is_svg = true;
1472-
1473-
if (NULL == (_rsvg = rsvg_handle_new_from_data(buf, len, nullptr))) {
1474-
return CAIRO_STATUS_READ_ERROR;
1475-
}
1476-
1477-
double d_width;
1478-
double d_height;
1479-
1480-
rsvg_handle_get_intrinsic_size_in_pixels(_rsvg, &d_width, &d_height);
1481-
1482-
width = naturalWidth = d_width;
1483-
height = naturalHeight = d_height;
1484-
1485-
if (width <= 0 || height <= 0) {
1486-
this->errorInfo.set("Width and height must be set on the svg element");
1487-
return CAIRO_STATUS_READ_ERROR;
1488-
}
1489-
1490-
return renderSVGToSurface();
1491-
}
1492-
1493-
/*
1494-
* Renders the Rsvg handle to this image's surface
1495-
*/
1496-
cairo_status_t
1497-
Image::renderSVGToSurface() {
1498-
cairo_status_t status;
1499-
1500-
_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
1501-
1502-
status = cairo_surface_status(_surface);
1503-
if (status != CAIRO_STATUS_SUCCESS) {
1504-
g_object_unref(_rsvg);
1505-
return status;
1506-
}
1507-
1508-
cairo_t *cr = cairo_create(_surface);
1509-
status = cairo_status(cr);
1510-
if (status != CAIRO_STATUS_SUCCESS) {
1511-
g_object_unref(_rsvg);
1512-
return status;
1513-
}
1514-
1515-
RsvgRectangle viewport = {
1516-
0, // x
1517-
0, // y
1518-
static_cast<double>(width),
1519-
static_cast<double>(height)
1520-
};
1521-
gboolean render_ok = rsvg_handle_render_document(_rsvg, cr, &viewport, nullptr);
1522-
if (!render_ok) {
1523-
g_object_unref(_rsvg);
1524-
cairo_destroy(cr);
1525-
return CAIRO_STATUS_READ_ERROR; // or WRITE?
1526-
}
1527-
1528-
cairo_destroy(cr);
1529-
1530-
_svg_last_width = width;
1531-
_svg_last_height = height;
1532-
1533-
return status;
1534-
}
1535-
1536-
/*
1537-
* Load SVG
1538-
*/
1539-
1540-
cairo_status_t
1541-
Image::loadSVG(FILE *stream) {
1542-
_is_svg = true;
1543-
1544-
struct stat s;
1545-
int fd = fileno(stream);
1546-
1547-
// stat
1548-
if (fstat(fd, &s) < 0) {
1549-
fclose(stream);
1550-
return CAIRO_STATUS_READ_ERROR;
1551-
}
1552-
1553-
uint8_t *buf = (uint8_t *) malloc(s.st_size);
1554-
1555-
if (!buf) {
1556-
fclose(stream);
1557-
return CAIRO_STATUS_NO_MEMORY;
1558-
}
1559-
1560-
size_t read = fread(buf, s.st_size, 1, stream);
1561-
fclose(stream);
1562-
1563-
cairo_status_t result = CAIRO_STATUS_READ_ERROR;
1564-
if (1 == read) result = loadSVGFromBuffer(buf, s.st_size);
1565-
free(buf);
1566-
1567-
return result;
1568-
}
1569-
1570-
#endif /* HAVE_RSVG */
1571-
15721400
/*
15731401
* Load BMP from buffer.
15741402
*/
@@ -1641,7 +1469,7 @@ cairo_status_t Image::loadBMP(FILE *stream){
16411469
}
16421470

16431471
/*
1644-
* Return UNKNOWN, SVG, GIF, JPEG, or PNG based on the filename.
1472+
* Return UNKNOWN, GIF, JPEG, or PNG based on the filename.
16451473
*/
16461474

16471475
Image::type
@@ -1652,7 +1480,6 @@ Image::extension(const char *filename) {
16521480
if (len >= 4 && 0 == strcmp(".gif", filename - 4)) return Image::GIF;
16531481
if (len >= 4 && 0 == strcmp(".jpg", filename - 4)) return Image::JPEG;
16541482
if (len >= 4 && 0 == strcmp(".png", filename - 4)) return Image::PNG;
1655-
if (len >= 4 && 0 == strcmp(".svg", filename - 4)) return Image::SVG;
16561483
return Image::UNKNOWN;
16571484
}
16581485

@@ -1683,27 +1510,6 @@ Image::isPNG(uint8_t *data) {
16831510
return 'P' == data[1] && 'N' == data[2] && 'G' == data[3];
16841511
}
16851512

1686-
/*
1687-
* Skip "<?" and "<!" tags to test if root tag starts "<svg"
1688-
*/
1689-
int
1690-
Image::isSVG(uint8_t *data, unsigned len) {
1691-
for (unsigned i = 3; i < len; i++) {
1692-
if ('<' == data[i-3]) {
1693-
switch (data[i-2]) {
1694-
case '?':
1695-
case '!':
1696-
break;
1697-
case 's':
1698-
return ('v' == data[i-1] && 'g' == data[i]);
1699-
default:
1700-
return false;
1701-
}
1702-
}
1703-
}
1704-
return false;
1705-
}
1706-
17071513
/*
17081514
* Check for valid BMP signatures
17091515
*/

src/Image.h

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,6 @@
2323
#endif
2424
#endif
2525

26-
#ifdef HAVE_RSVG
27-
#include <librsvg/rsvg.h>
28-
// librsvg <= 2.36.1, identified by undefined macro, needs an extra include
29-
#ifndef LIBRSVG_CHECK_VERSION
30-
#include <librsvg/rsvg-cairo.h>
31-
#endif
32-
#endif
33-
3426
using JPEGDecodeL = std::function<uint32_t (uint8_t* const src)>;
3527

3628
class Image : public Napi::ObjectWrap<Image> {
@@ -58,7 +50,6 @@ class Image : public Napi::ObjectWrap<Image> {
5850
static int isPNG(uint8_t *data);
5951
static int isJPEG(uint8_t *data);
6052
static int isGIF(uint8_t *data);
61-
static int isSVG(uint8_t *data, unsigned len);
6253
static int isBMP(uint8_t *data, unsigned len);
6354
static cairo_status_t readPNG(void *closure, unsigned char *data, unsigned len);
6455
inline int isComplete(){ return COMPLETE == state; }
@@ -68,11 +59,6 @@ class Image : public Napi::ObjectWrap<Image> {
6859
cairo_status_t loadPNGFromBuffer(uint8_t *buf);
6960
cairo_status_t loadPNG();
7061
void clearData();
71-
#ifdef HAVE_RSVG
72-
cairo_status_t loadSVGFromBuffer(uint8_t *buf, unsigned len);
73-
cairo_status_t loadSVG(FILE *stream);
74-
cairo_status_t renderSVGToSurface();
75-
#endif
7662
#ifdef HAVE_GIF
7763
cairo_status_t loadGIFFromBuffer(uint8_t *buf, unsigned len);
7864
cairo_status_t loadGIF(FILE *stream);
@@ -128,7 +114,6 @@ class Image : public Napi::ObjectWrap<Image> {
128114
, GIF
129115
, JPEG
130116
, PNG
131-
, SVG
132117
} type;
133118

134119
static type extension(const char *filename);
@@ -137,10 +122,4 @@ class Image : public Napi::ObjectWrap<Image> {
137122
cairo_surface_t *_surface;
138123
uint8_t *_data = nullptr;
139124
int _data_len;
140-
#ifdef HAVE_RSVG
141-
RsvgHandle *_rsvg;
142-
bool _is_svg;
143-
int _svg_last_width;
144-
int _svg_last_height;
145-
#endif
146125
};

src/init.cc

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,6 @@ Napi::Object init(Napi::Env env, Napi::Object exports) {
9999
#endif
100100
#endif
101101

102-
#ifdef HAVE_RSVG
103-
exports.Set("rsvgVersion", Napi::String::New(env, LIBRSVG_VERSION));
104-
#endif
105-
106102
char freetype_version[10];
107103
snprintf(freetype_version, 10, "%d.%d.%d", FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH);
108104
exports.Set("freetypeVersion", Napi::String::New(env, freetype_version));

test/canvas.test.js

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2387,20 +2387,4 @@ describe('Canvas', function () {
23872387
assert.throws(() => { ctx.beginTag('Link', {}) })
23882388
})
23892389
})
2390-
2391-
describe('loadImage', function () {
2392-
it('doesn\'t crash when you don\'t specify width and height', async function () {
2393-
const err = {name: "Error"};
2394-
2395-
// TODO: remove this when we have a static build or something
2396-
if (os.platform() !== 'win32') {
2397-
err.message = "Width and height must be set on the svg element";
2398-
}
2399-
2400-
await assert.rejects(async () => {
2401-
const svg = `<svg xmlns="http://www.w3.org/2000/svg"><path d="M1,1"/></svg>`;
2402-
await loadImage(Buffer.from(svg));
2403-
}, err);
2404-
});
2405-
});
24062390
})

test/image.test.js

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ const fs = require('fs')
1111
const path = require('path')
1212

1313
const { createCanvas, loadImage, rsvgVersion, Image } = require('../')
14-
const HAVE_SVG = rsvgVersion !== undefined
1514

1615

1716
const pngCheckers = path.join(__dirname, '/fixtures/checkers.png')
@@ -121,32 +120,6 @@ describe('Image', function () {
121120
}, MyError)
122121
})
123122

124-
it('loads SVG data URL base64', function () {
125-
if (!HAVE_SVG) this.skip()
126-
const base64Enc = fs.readFileSync(svgTree, 'base64')
127-
const dataURL = `data:image/svg+xml;base64,${base64Enc}`
128-
return loadImage(dataURL).then((img) => {
129-
assert.strictEqual(img.onerror, null)
130-
assert.strictEqual(img.onload, null)
131-
assert.strictEqual(img.width, 200)
132-
assert.strictEqual(img.height, 200)
133-
assert.strictEqual(img.complete, true)
134-
})
135-
})
136-
137-
it('loads SVG data URL utf8', function () {
138-
if (!HAVE_SVG) this.skip()
139-
const utf8Encoded = fs.readFileSync(svgTree, 'utf8')
140-
const dataURL = `data:image/svg+xml;utf8,${utf8Encoded}`
141-
return loadImage(dataURL).then((img) => {
142-
assert.strictEqual(img.onerror, null)
143-
assert.strictEqual(img.onload, null)
144-
assert.strictEqual(img.width, 200)
145-
assert.strictEqual(img.height, 200)
146-
assert.strictEqual(img.complete, true)
147-
})
148-
})
149-
150123
it('calls Image#onload multiple times', function () {
151124
return loadImage(pngClock).then((img) => {
152125
let onloadCalled = 0

0 commit comments

Comments
 (0)