From 8fcc4b0dd8289f69fed7b99f0d2108914b59c98c Mon Sep 17 00:00:00 2001
From: Christoph Reiter <reiter.christoph@gmail.com>
Date: Thu, 22 Oct 2020 13:02:44 +0200
Subject: [PATCH] Draw into a temporary canvas first and then copy it to the
 DOM one

This allows the detection to be async and pasue execution between capturing
the image, analyzing it and then finally drawing it.
---
 packages/qr-code-scanner/src/qr-code-scanner.js | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/packages/qr-code-scanner/src/qr-code-scanner.js b/packages/qr-code-scanner/src/qr-code-scanner.js
index bfb785d2..f8504b21 100644
--- a/packages/qr-code-scanner/src/qr-code-scanner.js
+++ b/packages/qr-code-scanner/src/qr-code-scanner.js
@@ -201,7 +201,8 @@ export class QrCodeScanner extends ScopedElementsMixin(DBPLitElement) {
         console.assert(this._lock.isLocked());
         await this.updateComplete;
 
-        let canvasElement = this._("#canvas");
+        let targetCanvas = this._("#canvas");
+        let canvasElement = document.createElement("canvas");
         let firstDrawDone = false;
 
         this._askPermission = true;
@@ -218,14 +219,11 @@ export class QrCodeScanner extends ScopedElementsMixin(DBPLitElement) {
             if (video.readyState === video.HAVE_ENOUGH_DATA) {
                 this._loading = false;
 
+                // draw into a temporary canvas first
                 canvasElement.height = video.videoHeight;
                 canvasElement.width = video.videoWidth;
                 let canvas = canvasElement.getContext("2d");
                 canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);
-                if (!firstDrawDone) {
-                    this.dispatchEvent(new CustomEvent("scan-started", {bubbles: true, composed: true}));
-                    firstDrawDone = true;
-                }
 
                 let maskWidth = canvasElement.width;
                 let maskHeight = canvasElement.height;
@@ -286,6 +284,15 @@ export class QrCodeScanner extends ScopedElementsMixin(DBPLitElement) {
                 canvas.rect(maskStartX + maskWidth - borderWidth, maskStartY + maskHeight/3*2, borderWidth, maskHeight/3);
                 canvas.fill();
 
+                targetCanvas.height = canvasElement.height;
+                targetCanvas.width = canvasElement.width;
+                targetCanvas.getContext("2d").drawImage(canvasElement, 0, 0);
+
+                if (!firstDrawDone) {
+                    this.dispatchEvent(new CustomEvent("scan-started", {bubbles: true, composed: true}));
+                    firstDrawDone = true;
+                }
+
                 if (code) {
                     if (lastSentData !== code.data) {
                         this._outputData = code.data;
-- 
GitLab