alafr / SVG-to-PDFKit

Insert SVG into a PDF document created with PDFKit
MIT License
397 stars 111 forks source link

Performance issue with SVGtoPDF while exporting large svg with clippath and transform #141

Open netrpe opened 3 years ago

netrpe commented 3 years ago

We want to achieve a kind of multipaging. For this we generate a large svg (for example 6000*6000px). We create a pdf document and add pages to it with doc.addPage. We define a page size (for example A4) and transform the large svg to show the appropriate part on the page. Elements outside of the page range are clipped with a clippath.

Doing this we get a performance issue in the following function:

  this.transform = function(m) {
    this.pathSegments = [];
    this.startPoint = null;
    this.endPoint = null;
    this.totalLength = 0;
    for (let i = 0; i < this.pathCommands.length; i++) {        //250000
      let data = this.pathCommands.shift();
      for (let j = 3; j < data.length; j+=2) {
        let p = transformPoint([data[j], data[j + 1]], m)
        data[j] = p[0];
        data[j + 1] = p[1];
      }
      this.addCommand(data);
    }
    return this;        
  };

Here the loop is going around for approximately 250000 times. Breaking the Chrome debugger within the SVGtoPDF call at any time it shows this location. The transform function is called from

var SvgElemHasChildren = function(obj, inherits) {
  SvgElemStylable.call(this, obj, inherits);
  this.allowedChildren = ['use', 'g', 'a', 'svg', 'image', 'rect', 'circle', 'ellipse', 'line', 'polyline', 'polygon', 'path', 'text'];
  this.getBoundingShape = function() {
    let shape = new SvgShape(),
        children = this.getChildren();
    for (let i = 0; i < children.length; i++) {
      if (children[i].get('display') !== 'none') {
        if (typeof children[i].getBoundingShape === 'function') {
          let childShape = children[i].getBoundingShape().clone();
          if (typeof children[i].getTransformation === 'function') {
            childShape.transform(children[i].getTransformation());          //CALLED FROM HERE
          }
          shape.mergeShape(childShape);
        }
      }
    }
    return shape;
  };

Without clippath it take a second per page; with clippath it takes several minutes !!!

Do you have any suggestions to increase performance or is it a bug which needs to be fixed ?

Maybe this is related to #120?

Thanks in advance, netrpe