Skip to content

Commit cfdcea1

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 016310b commit cfdcea1

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;
@@ -312,18 +300,6 @@ Image::loadFromBuffer(uint8_t *buf, unsigned len) {
312300
#endif
313301
}
314302

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

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

@@ -461,31 +421,8 @@ Image::loadSurface() {
461421
#endif
462422
}
463423

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

491428
this->errorInfo.set("Unsupported image type");
@@ -1459,115 +1396,6 @@ Image::rotatePixels(uint8_t* pixels, int width, int height, int channels,
14591396

14601397
#endif /* HAVE_JPEG */
14611398

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

16421470
/*
1643-
* Return UNKNOWN, SVG, GIF, JPEG, or PNG based on the filename.
1471+
* Return UNKNOWN, GIF, JPEG, or PNG based on the filename.
16441472
*/
16451473

16461474
Image::type
@@ -1651,7 +1479,6 @@ Image::extension(const char *filename) {
16511479
if (len >= 4 && 0 == strcmp(".gif", filename - 4)) return Image::GIF;
16521480
if (len >= 4 && 0 == strcmp(".jpg", filename - 4)) return Image::JPEG;
16531481
if (len >= 4 && 0 == strcmp(".png", filename - 4)) return Image::PNG;
1654-
if (len >= 4 && 0 == strcmp(".svg", filename - 4)) return Image::SVG;
16551482
return Image::UNKNOWN;
16561483
}
16571484

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

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

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
@@ -97,10 +97,6 @@ Napi::Object init(Napi::Env env, Napi::Object exports) {
9797
#endif
9898
#endif
9999

100-
#ifdef HAVE_RSVG
101-
exports.Set("rsvgVersion", Napi::String::New(env, LIBRSVG_VERSION));
102-
#endif
103-
104100
char freetype_version[10];
105101
snprintf(freetype_version, 10, "%d.%d.%d", FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH);
106102
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
@@ -2513,20 +2513,4 @@ describe('Canvas', function () {
25132513
assert.throws(() => { ctx.beginTag('Link', {}) })
25142514
})
25152515
})
2516-
2517-
describe('loadImage', function () {
2518-
it('doesn\'t crash when you don\'t specify width and height', async function () {
2519-
const err = {name: "Error"};
2520-
2521-
// TODO: remove this when we have a static build or something
2522-
if (os.platform() !== 'win32') {
2523-
err.message = "Width and height must be set on the svg element";
2524-
}
2525-
2526-
await assert.rejects(async () => {
2527-
const svg = `<svg xmlns="http://www.w3.org/2000/svg"><path d="M1,1"/></svg>`;
2528-
await loadImage(Buffer.from(svg));
2529-
}, err);
2530-
});
2531-
});
25322516
})

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)