From ce57bac447cbe7cf9e264d8aaa3608a5e61c24be Mon Sep 17 00:00:00 2001 From: Adil Allawi Date: Wed, 14 Dec 2011 22:28:34 +0000 Subject: [PATCH 1/5] Build Text Layer one div at a a time as an Interval instead of a all in a TimeOut to keep the browser responsive --- src/canvas.js | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/canvas.js b/src/canvas.js index 4aaf75508..1efddbefa 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -259,7 +259,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { this.textLayerQueue = []; // Prevent textLayerQueue from being rendered while rendering a new page if (this.textLayerTimer) - clearTimeout(this.textLayerTimer); + clearInterval(this.textLayerTimer); }, executeIRQueue: function canvasGraphicsExecuteIRQueue(codeIR, @@ -329,17 +329,21 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { var self = this; var renderTextLayer = function canvasRenderTextLayer() { + var finished = true; var textDivs = self.textDivs; - for (var i = 0, length = textDivs.length; i < length; ++i) { - if (textDivs[i].dataset.textLength > 1) { // avoid div by zero - textLayer.appendChild(textDivs[i]); + if (textDivs.length > 0) { + var textDiv = textDivs.shift(); + if (textDiv.dataset.textLength > 1) { // avoid div by zero + textLayer.appendChild(textDiv); // Adjust div width (via letterSpacing) to match canvas text // Due to the .offsetWidth calls, this is slow - textDivs[i].style.letterSpacing = - ((textDivs[i].dataset.canvasWidth - textDivs[i].offsetWidth) / - (textDivs[i].dataset.textLength - 1)) + 'px'; + textDiv.style.letterSpacing = + ((textDiv.dataset.canvasWidth - textDiv.offsetWidth) / + (textDiv.dataset.textLength - 1)) + 'px'; } + finished = false; } + return finished; } var textLayerQueue = this.textLayerQueue; textLayerQueue.push(renderTextLayer); @@ -347,12 +351,16 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { // Lazy textLayer rendering (to prevent UI hangs) // Only render queue if activity has stopped, where "no activity" == // "no beginDrawing() calls in the last N ms" - this.textLayerTimer = setTimeout(function renderTextLayerQueue() { + this.textLayerTimer = setInterval(function renderTextLayerQueue() { // Render most recent (==most relevant) layers first for (var i = textLayerQueue.length - 1; i >= 0; i--) { - textLayerQueue.pop().call(); + var finished = textLayerQueue[i].call(); + if (finished) + textLayerQueue.splice(i,1); } - }, 500); + if (textLayerQueue.length == 0) + clearInterval(this.textLayerTimer); + }, 1); }, // Graphics state From cc007b539a73d0d96d7d34d48851a4aad7f95f75 Mon Sep 17 00:00:00 2001 From: Adil Allawi Date: Thu, 15 Dec 2011 09:20:55 +0000 Subject: [PATCH 2/5] fix lint nitpick --- src/canvas.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/canvas.js b/src/canvas.js index 1efddbefa..fbebc0aa2 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -356,7 +356,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { for (var i = textLayerQueue.length - 1; i >= 0; i--) { var finished = textLayerQueue[i].call(); if (finished) - textLayerQueue.splice(i,1); + textLayerQueue.splice(i, 1); } if (textLayerQueue.length == 0) clearInterval(this.textLayerTimer); From 4a14a798845e42e946f41da89a4bdc6ceab4a08d Mon Sep 17 00:00:00 2001 From: Adil Allawi Date: Thu, 15 Dec 2011 10:08:50 +0000 Subject: [PATCH 3/5] use array index instead of array.shift() --- src/canvas.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/canvas.js b/src/canvas.js index fbebc0aa2..38b33d19d 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -328,11 +328,12 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { return; var self = this; + var textDivIndex = 0; var renderTextLayer = function canvasRenderTextLayer() { - var finished = true; + var finished = false; var textDivs = self.textDivs; - if (textDivs.length > 0) { - var textDiv = textDivs.shift(); + if (textDivIndex < textDivs.length) { + var textDiv = textDivs[textDivIndex++]; if (textDiv.dataset.textLength > 1) { // avoid div by zero textLayer.appendChild(textDiv); // Adjust div width (via letterSpacing) to match canvas text @@ -341,8 +342,9 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { ((textDiv.dataset.canvasWidth - textDiv.offsetWidth) / (textDiv.dataset.textLength - 1)) + 'px'; } - finished = false; } + else + finished = true; return finished; } var textLayerQueue = this.textLayerQueue; From 5bd080fd0508197e34e03e2d73447b7cfe9a3c26 Mon Sep 17 00:00:00 2001 From: Adil Allawi Date: Thu, 15 Dec 2011 11:32:58 +0000 Subject: [PATCH 4/5] oops, interval was not clearing because 'this' is not the same 'this' inside an interval. Should use local variable 'self' instead. Reviewers you should have spotted this! :) --- src/canvas.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/canvas.js b/src/canvas.js index 2d1130b4f..50c762bca 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -361,7 +361,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { textLayerQueue.splice(i, 1); } if (textLayerQueue.length == 0) - clearInterval(this.textLayerTimer); + clearInterval(self.textLayerTimer); }, 1); }, From b921486bce08ef6cc2683989848b44f28861e2f4 Mon Sep 17 00:00:00 2001 From: Adil Allawi Date: Fri, 16 Dec 2011 10:38:30 +0000 Subject: [PATCH 5/5] simplify adding of textdivs to DOM as queue is no longer needed --- src/canvas.js | 52 +++++++++++++++------------------------------------ 1 file changed, 15 insertions(+), 37 deletions(-) diff --git a/src/canvas.js b/src/canvas.js index 50c762bca..0e351c1b8 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -257,9 +257,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { this.ctx.scale(cw / mediaBox.width, ch / mediaBox.height); this.textDivs = []; this.textLayerQueue = []; - // Prevent textLayerQueue from being rendered while rendering a new page - if (this.textLayerTimer) - clearInterval(this.textLayerTimer); }, executeIRQueue: function canvasGraphicsExecuteIRQueue(codeIR, @@ -328,41 +325,22 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { return; var self = this; - var textDivIndex = 0; - var renderTextLayer = function canvasRenderTextLayer() { - var finished = false; - var textDivs = self.textDivs; - if (textDivIndex < textDivs.length) { - var textDiv = textDivs[textDivIndex++]; - if (textDiv.dataset.textLength > 1) { // avoid div by zero - textLayer.appendChild(textDiv); - // Adjust div width (via letterSpacing) to match canvas text - // Due to the .offsetWidth calls, this is slow - textDiv.style.letterSpacing = - ((textDiv.dataset.canvasWidth - textDiv.offsetWidth) / - (textDiv.dataset.textLength - 1)) + 'px'; - } - } - else - finished = true; - return finished; - } - var textLayerQueue = this.textLayerQueue; - textLayerQueue.push(renderTextLayer); - - // Lazy textLayer rendering (to prevent UI hangs) - // Only render queue if activity has stopped, where "no activity" == - // "no beginDrawing() calls in the last N ms" - this.textLayerTimer = setInterval(function renderTextLayerQueue() { - // Render most recent (==most relevant) layers first - for (var i = textLayerQueue.length - 1; i >= 0; i--) { - var finished = textLayerQueue[i].call(); - if (finished) - textLayerQueue.splice(i, 1); - } - if (textLayerQueue.length == 0) + var textDivs = this.textDivs; + this.textLayerTimer = setInterval(function renderTextLayer() { + if (textDivs.length === 0) { clearInterval(self.textLayerTimer); - }, 1); + return; + } + var textDiv = textDivs.shift(); + if (textDiv.dataset.textLength > 1) { // avoid div by zero + textLayer.appendChild(textDiv); + // Adjust div width (via letterSpacing) to match canvas text + // Due to the .offsetWidth calls, this is slow + textDiv.style.letterSpacing = + ((textDiv.dataset.canvasWidth - textDiv.offsetWidth) / + (textDiv.dataset.textLength - 1)) + 'px'; + } + }, 0); }, // Graphics state