summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--browser/src/layer/tile/CanvasSectionContainer.ts16
-rw-r--r--browser/src/layer/tile/CanvasTileLayer.js53
2 files changed, 55 insertions, 14 deletions
diff --git a/browser/src/layer/tile/CanvasSectionContainer.ts b/browser/src/layer/tile/CanvasSectionContainer.ts
index 61c78f7de4..396d48fc0a 100644
--- a/browser/src/layer/tile/CanvasSectionContainer.ts
+++ b/browser/src/layer/tile/CanvasSectionContainer.ts
@@ -1510,6 +1510,22 @@ class CanvasSectionContainer {
this.canvas.width = newWidth;
this.canvas.height = newHeight;
+ // Partial fix for #5876 reduce size if canvas context is null
+ // WKWebView has a hard limit on the number of bytes of canvas
+ // context memory that can be allocated. Canvas with sizes that
+ // are too large will return a null context so reduce the size
+ // of the canvas until a non-null context is obtained.
+ if ((window as any).ThisIsTheiOSApp) {
+ this.context = this.canvas.getContext('2d', { alpha: false });
+ while (!this.context && this.canvas.width >= 2 && this.canvas.height >= 2) {
+ this.canvas.width /= 2;
+ this.canvas.height /= 2;
+ this.context = this.canvas.getContext('2d', { alpha: false });
+ }
+ for (var i: number = 0; i < this.sections.length; i++)
+ this.sections[i].context = this.context;
+ }
+
// CSS pixels can be fractional, but need to round to the same real pixels
var cssWidth: number = newWidth / app.dpiScale; // NB. beware
var cssHeight: number = newHeight / app.dpiScale;
diff --git a/browser/src/layer/tile/CanvasTileLayer.js b/browser/src/layer/tile/CanvasTileLayer.js
index a6b4c209f4..498df2a33b 100644
--- a/browser/src/layer/tile/CanvasTileLayer.js
+++ b/browser/src/layer/tile/CanvasTileLayer.js
@@ -6619,6 +6619,19 @@ L.CanvasTileLayer = L.Layer.extend({
return new L.LatLngBounds(nw, se);
},
+ _reclaimTileCanvasMemory: function (tile) {
+ // Partial fix for #5876 allow immediate reuse of canvas context memory
+ // WKWebView has a hard limit on the number of bytes of canvas
+ // context memory that can be allocated. Reducing the canvas
+ // size to zero is a way to reduce the number of bytes counted
+ // against this limit.
+ if (window.ThisIsTheiOSApp && tile && tile.el && tile.el instanceof HTMLCanvasElement) {
+ tile.el.width = 0;
+ tile.el.height = 0;
+ delete tile.el;
+ }
+ },
+
_removeTile: function (key) {
var tile = this._tiles[key];
if (!tile) { return; }
@@ -6712,6 +6725,32 @@ L.CanvasTileLayer = L.Layer.extend({
var imgData;
var ctx = canvas.getContext('2d');
+ // Partial fix for issue #5876 discard excess canvas contexts
+ // WKWebView has a hardcoded memory limit for all canvas contexts
+ // so if canvas.getContext('2d') returns null, convert the canvas
+ // of other tiles to an image until canvas.getContext('2d') succeeds.
+ if (!ctx && window.ThisIsTheiOSApp) {
+ for (var key in this._tiles) {
+ var value = this._tiles[key];
+ if (value && value !== tile && value.el && value.el instanceof HTMLCanvasElement) {
+ var imageSrc = value.el.toDataURL();
+ this._reclaimTileCanvasMemory(value);
+ value.el = document.createElement('img');
+ value.el.src = imageSrc;
+ if (!(value._invalidCount > 0) && this._tileCache[key])
+ this._tileCache[key] = value.el;
+ ctx = canvas.getContext('2d');
+ if (ctx)
+ break;
+ }
+ }
+
+ // If we can't free up enough canvas context, there is nothing
+ // more we can do. Is there a better way to handle this?
+ if (!ctx)
+ return;
+ }
+
while (offset < allDeltas.length)
{
if (this._debugDeltas)
@@ -6768,20 +6807,6 @@ L.CanvasTileLayer = L.Layer.extend({
if (imgData)
ctx.putImageData(imgData, 0, 0);
- // Partial fix for issue #5876 discard canvas contexts immediately
- // WKWebView has a hardcoded memory limit for all canvas contexts
- // so immediately convert the canvas to an image and release the
- // canvas context's backing store.
- // This bug only appears in the iOS app because most .png tiles are
- // passed as raw data, not as "data:" strings, in the iOS app.
- if (window.ThisIsTheiOSApp) {
- tile.el = document.createElement('img');
- tile.el.src = canvas.toDataURL();
- canvas.width = 0;
- canvas.height = 0;
- canvas = null;
- }
-
if (traceEvent)
traceEvent.finish();
},