changeset 3955:7df9ef183985

pdftool: improve scalability
author Thomas Junk <thomas.junk@intevation.de>
date Tue, 16 Jul 2019 11:37:47 +0200
parents cb4fda122321
children 9a155ab8cc21 66a421f3e3a6
files client/src/components/Pdftool.vue
diffstat 1 files changed, 179 insertions(+), 132 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/components/Pdftool.vue	Mon Jul 15 17:54:12 2019 +0200
+++ b/client/src/components/Pdftool.vue	Tue Jul 16 11:37:47 2019 +0200
@@ -209,6 +209,12 @@
     close() {
       this.$store.commit("application/showPdfTool", false);
     },
+    millimeter2pixels(length, dpi) {
+      return (dpi * length) / 25.4;
+    },
+    pixel2millimeter(pixels, dpi) {
+      return (pixels * 25.4) / dpi;
+    },
     // When a template is chosen from the dropdown, its propoerties are
     // applied to the rest of the form.
     applyTemplateToForm() {
@@ -309,144 +315,185 @@
           1000 * pixelsPerMapMillimeter * metersPerPixel
         );
         console.log("scaleDenominator = ", scaleDenominator);
-
-        var data = canvas.toDataURL("image/jpeg");
-        this.pdf.doc.addImage(
-          data,
-          "JPEG",
-          0,
-          0,
+        const width80DPI = this.millimeter2pixels(this.pdf.width, 80);
+        const height80DPI = this.millimeter2pixels(this.pdf.height, 80);
+        const currentHeight = this.millimeter2pixels(
+          this.pdf.height,
+          this.form.resolution
+        );
+        const currentWidth = this.millimeter2pixels(
           this.pdf.width,
-          this.pdf.height
+          this.form.resolution
         );
+        //const scaleFactor = this.form.resolution / 80;
+        var snapshot = canvas.toDataURL("image/jpeg");
+        const offscreen = document.createElement("canvas");
+        offscreen.width = currentWidth;
+        offscreen.height = currentHeight;
+        const image = new Image();
+        image.src = snapshot;
+        image.onload = () => {
+          offscreen
+            .getContext("2d")
+            .drawImage(
+              image,
+              (currentWidth - width80DPI) / 2,
+              (currentHeight - height80DPI) / 2,
+              width80DPI,
+              height80DPI,
+              0,
+              0,
+              currentWidth,
+              currentHeight
+            );
+          const data = offscreen.toDataURL("image/jpeg");
+          this.pdf.doc.addImage(
+            data,
+            "JPEG",
+            0,
+            0,
+            this.pdf.width,
+            this.pdf.height
+          );
 
-        if (this.templateData) {
-          this.pdf.doc.setFont("linbiolinum", "normal");
-          let defaultFontSize = 11,
-            defaultRounding = 2,
-            defaultTextColor = "black",
-            defaultBgColor = "white",
-            defaultPadding = 3,
-            defaultOffset = { x: 0, y: 0 },
-            defaultBorderColor = "white";
-          this.templateData.elements.forEach(e => {
-            switch (e.type) {
-              case "text": {
-                this.addText(
-                  e.position,
-                  e.offset || defaultOffset,
-                  e.width,
-                  e.fontSize || defaultFontSize,
-                  e.color || defaultTextColor,
-                  e.text
-                );
-                break;
-              }
-              case "box": {
-                this.addBox(
-                  e.position,
-                  e.offset || defaultOffset,
-                  e.width,
-                  e.height,
-                  // handling the case when the rectangle  not rounded (rounding = 0)
-                  e.rounding === 0 || e.rounding ? e.rounding : defaultRounding,
-                  e.color || defaultBgColor,
-                  e.brcolor || defaultBorderColor
-                );
-                break;
+          if (this.templateData) {
+            this.pdf.doc.setFont("linbiolinum", "normal");
+            let defaultFontSize = 11,
+              defaultRounding = 2,
+              defaultTextColor = "black",
+              defaultBgColor = "white",
+              defaultPadding = 3,
+              defaultOffset = { x: 0, y: 0 },
+              defaultBorderColor = "white";
+            this.templateData.elements.forEach(e => {
+              switch (e.type) {
+                case "text": {
+                  this.addText(
+                    e.position,
+                    e.offset || defaultOffset,
+                    e.width,
+                    e.fontSize || defaultFontSize,
+                    e.color || defaultTextColor,
+                    e.text
+                  );
+                  break;
+                }
+                case "box": {
+                  this.addBox(
+                    e.position,
+                    e.offset || defaultOffset,
+                    e.width,
+                    e.height,
+                    // handling the case when the rectangle  not rounded (rounding = 0)
+                    e.rounding === 0 || e.rounding
+                      ? e.rounding
+                      : defaultRounding,
+                    e.color || defaultBgColor,
+                    e.brcolor || defaultBorderColor
+                  );
+                  break;
+                }
+                case "textbox": {
+                  this.addTextBox(
+                    e.position,
+                    e.offset || defaultOffset,
+                    e.width,
+                    e.height,
+                    e.rounding === 0 || e.rounding
+                      ? e.rounding
+                      : defaultRounding,
+                    e.padding || defaultPadding,
+                    e.fontSize || defaultFontSize,
+                    e.color || defaultTextColor,
+                    e.background || defaultBgColor,
+                    e.text,
+                    e.brcolor || defaultBorderColor
+                  );
+                  break;
+                }
+                case "image": {
+                  this.addImage(
+                    e.url,
+                    e.format,
+                    e.position,
+                    e.offset || defaultOffset,
+                    e.width,
+                    e.height
+                  );
+                  break;
+                }
+                case "bottleneck": {
+                  this.addBottleneckInfo(
+                    e.position,
+                    e.offset || defaultOffset,
+                    e.rounding === 0 || e.rounding
+                      ? e.rounding
+                      : defaultRounding,
+                    e.color || defaultTextColor,
+                    e.brcolor || defaultBorderColor
+                  );
+                  break;
+                }
+                case "legend": {
+                  this.addLegend(
+                    e.position,
+                    e.offset || defaultOffset,
+                    e.rounding === 0 || e.rounding
+                      ? e.rounding
+                      : defaultRounding,
+                    e.brcolor || defaultBorderColor
+                  );
+                  break;
+                }
+                case "scalebar": {
+                  this.addScaleBar(
+                    scaleDenominator,
+                    e.position,
+                    e.offset || defaultOffset,
+                    e.rounding === 0 || e.rounding
+                      ? e.rounding
+                      : defaultRounding,
+                    e.brcolor || defaultBorderColor
+                  );
+                  break;
+                }
+                case "scale": {
+                  this.addScale(
+                    scaleDenominator,
+                    e.position,
+                    e.width,
+                    e.offset || defaultOffset,
+                    e.fontSize || defaultFontSize,
+                    e.color || defaultTextColor
+                  );
+                  break;
+                }
+                case "northarrow": {
+                  this.addNorthArrow(
+                    e.position,
+                    e.offset || defaultOffset,
+                    e.size
+                  );
+                  break;
+                }
               }
-              case "textbox": {
-                this.addTextBox(
-                  e.position,
-                  e.offset || defaultOffset,
-                  e.width,
-                  e.height,
-                  e.rounding === 0 || e.rounding ? e.rounding : defaultRounding,
-                  e.padding || defaultPadding,
-                  e.fontSize || defaultFontSize,
-                  e.color || defaultTextColor,
-                  e.background || defaultBgColor,
-                  e.text,
-                  e.brcolor || defaultBorderColor
-                );
-                break;
-              }
-              case "image": {
-                this.addImage(
-                  e.url,
-                  e.format,
-                  e.position,
-                  e.offset || defaultOffset,
-                  e.width,
-                  e.height
-                );
-                break;
-              }
-              case "bottleneck": {
-                this.addBottleneckInfo(
-                  e.position,
-                  e.offset || defaultOffset,
-                  e.rounding === 0 || e.rounding ? e.rounding : defaultRounding,
-                  e.color || defaultTextColor,
-                  e.brcolor || defaultBorderColor
-                );
-                break;
-              }
-              case "legend": {
-                this.addLegend(
-                  e.position,
-                  e.offset || defaultOffset,
-                  e.rounding === 0 || e.rounding ? e.rounding : defaultRounding,
-                  e.brcolor || defaultBorderColor
-                );
-                break;
-              }
-              case "scalebar": {
-                this.addScaleBar(
-                  scaleDenominator,
-                  e.position,
-                  e.offset || defaultOffset,
-                  e.rounding === 0 || e.rounding ? e.rounding : defaultRounding,
-                  e.brcolor || defaultBorderColor
-                );
-                break;
-              }
-              case "scale": {
-                this.addScale(
-                  scaleDenominator,
-                  e.position,
-                  e.width,
-                  e.offset || defaultOffset,
-                  e.fontSize || defaultFontSize,
-                  e.color || defaultTextColor
-                );
-                break;
-              }
-              case "northarrow": {
-                this.addNorthArrow(
-                  e.position,
-                  e.offset || defaultOffset,
-                  e.size
-                );
-                break;
-              }
-            }
+            });
+
+            this.pdf.doc.save(this.filename);
+          }
+
+          // reset to original size
+          map.setSize(this.mapSize);
+          map.getView().fit(this.mapExtent, {
+            size: this.mapSize,
+            // necessary to get to the previous zoom level in all cases
+            // details see https://github.com/openlayers/openlayers/issues/9235
+            constrainResolution: false
           });
 
-          this.pdf.doc.save(this.filename);
-        }
-
-        // reset to original size
-        map.setSize(this.mapSize);
-        map.getView().fit(this.mapExtent, {
-          size: this.mapSize,
-          // necessary to get to the previous zoom level in all cases
-          // details see https://github.com/openlayers/openlayers/issues/9235
-          constrainResolution: false
-        });
-
-        // as we are done: re-enable button
-        this.readyToGenerate = true;
+          // as we are done: re-enable button
+          this.readyToGenerate = true;
+        };
       });
 
       // trigger rendering