Created
October 27, 2011 16:29
-
-
Save unxed/1320056 to your computer and use it in GitHub Desktop.
FileSystem API-based cache for Kothic-JS - v.0.04
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; | |
BlobBuilder = window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder; | |
Object.size = function(obj) { | |
var size = 0, key; | |
for (key in obj) { | |
if (obj.hasOwnProperty(key)) size++; | |
} | |
return size; | |
}; | |
function base64pngToBin(str) | |
{ | |
return new Uint8Array( base64toIntArray(str.substr(22)) ).buffer; | |
} | |
function base64toIntArray(str) { | |
var b64decoded = []; | |
var chr1, chr2, chr3; | |
var enc, tmp, lim; | |
for (var i=0; i<str.length; ) { | |
enc = []; | |
lim = 4; | |
for (var j=0; j<lim; j++) { | |
if ((i+j) < str.length) | |
{ | |
tmp = str.charCodeAt(i+j); | |
if ((tmp >= 65) && (tmp <= 90)) { enc.push(tmp - 65); } | |
else if ((tmp >= 97) && (tmp <= 122)) { enc.push(tmp - 71); } | |
else if ((tmp >= 48) && (tmp <= 57)) { enc.push(tmp + 4); } | |
else if (tmp == 43) { enc.push(62); } | |
else if (tmp == 47) { enc.push(63); } | |
else if (tmp == 61) { enc.push(64); } | |
else { | |
if ((i+j+1) < str.length) { lim++; } | |
} | |
} | |
else { while (j<lim) { enc.push(64); j++; } } | |
} | |
i+=j; | |
chr1 = (enc[0] << 2) | (enc[1] >> 4); | |
chr2 = ((enc[1] & 15) << 4) | (enc[2] >> 2); | |
chr3 = ((enc[2] & 3) << 6) | enc[3]; | |
b64decoded.push(chr1); | |
if (enc[2] < 64) { | |
b64decoded.push(chr2); | |
} | |
if (enc[3] < 64) { | |
b64decoded.push(chr3); | |
} | |
} | |
return b64decoded; | |
} | |
if (typeof(window.requestFileSystem) != 'undefined') | |
{ | |
window.requestFileSystem(TEMPORARY, 1024 * 1024 * 128, onInitFs, errorHandler); | |
} | |
function onInitFs(fs_) { | |
window.fs = fs_; | |
} | |
function errorHandler(e) { | |
var msg = ''; | |
switch (e.code) { | |
case FileError.QUOTA_EXCEEDED_ERR: | |
msg = 'QUOTA_EXCEEDED_ERR'; | |
break; | |
case FileError.NOT_FOUND_ERR: | |
msg = 'NOT_FOUND_ERR'; | |
break; | |
case FileError.SECURITY_ERR: | |
msg = 'SECURITY_ERR'; | |
break; | |
case FileError.INVALID_MODIFICATION_ERR: | |
msg = 'INVALID_MODIFICATION_ERR'; | |
break; | |
case FileError.INVALID_STATE_ERR: | |
msg = 'INVALID_STATE_ERR'; | |
break; | |
default: | |
msg = 'Unknown Error'; | |
break; | |
}; | |
console.log('Error: ' + msg); | |
} | |
L.TileLayer.Kothic = L.TileLayer.Canvas.extend({ | |
options: { | |
tileSize: 256 * 4, | |
zoomOffset: 2, | |
minZoom: 2, | |
maxZoom: 22, | |
updateWhenIdle: true, | |
unloadInvisibleTiles: true, | |
attribution: 'Map data © 2011 OpenStreetMap contributors, Rendering by <a href="http://github.com/kothic/kothic-js">Kothic JS</a>', | |
async: true, | |
buffered: true | |
}, | |
initialize: function(options) { | |
L.Util.setOptions(this, options); | |
this._canvases = {}; | |
this._debugMessages = []; | |
var layer = this; | |
window.onKothicDataResponse = L.Util.bind(this._onKothicDataResponse, this); | |
}, | |
saveToCache: function(canvas, zoom, x, y) | |
{ | |
if ((typeof(fs) != 'undefined') && (typeof(window.requestFileSystem) != 'undefined')) | |
{ | |
// we now have correct filesystem object to use for cache | |
fs.root.getFile(x + '_' + y + '_' + zoom + '.png', {create: true}, function(fileEntry) { | |
console.log('saving to cache: '+fileEntry.fullPath); | |
// Create a FileWriter object for our FileEntry. | |
fileEntry.createWriter(function(fileWriter) { | |
fileWriter.seek(0); // Start write position at 0. | |
var bb = new BlobBuilder(); | |
bb.append(base64pngToBin(canvas.toDataURL("image/png"))); | |
fileWriter.write(bb.getBlob('image/png')); | |
bb = null; | |
console.log('saved to cache: '+fileEntry.fullPath); | |
}, errorHandler); | |
}, errorHandler); | |
} | |
}, | |
_onKothicDataResponse: function(data, zoom, x, y) { | |
var key = [zoom, x, y].join('/'), | |
canvas = this._canvases[key], | |
buffered = this.options.buffered, | |
zoomOffset = this.options.zoomOffset, | |
layer = this; | |
function onRenderComplete(debugInfo) { | |
layer.tileDrawn(canvas); | |
layer.saveToCache(canvas, zoom, x, y); | |
// TODO move this logic outside | |
// var debugStr = layer.getDebugStr(debugInfo, x, y, zoom); | |
// layer._debugMessages.push(debugStr); | |
// temporary disable debug messages | |
} | |
Kothic.render(canvas, data, zoom + zoomOffset, layer._additionalStyle, onRenderComplete, buffered); | |
delete this._canvases[key]; | |
}, | |
getDebugStr: function(debugInfo, x, y, zoom) { | |
return '<b>tile ' + x + ':' + y + ':' + zoom + '</b><br />' + | |
'<table><tr><td>' + debugInfo.layersStyled + ' ms</td><td>layers styled</td></tr>' + | |
'<tr><td>' + debugInfo.mapRendered + ' ms</td><td>map rendered</td></tr>' + | |
'<tr><td>' + debugInfo.iconsAndTextRendered + ' ms</td><td>icons/text rendered</td></tr>' + | |
'<tr><td>' + debugInfo.total + ' ms</td><td>total</td></tr></table>'; | |
}, | |
getDebugMessages: function() { | |
return this._debugMessages; | |
}, | |
drawTile: function(canvas, tilePoint, zoom) { | |
console.log('debug: _canvases size: '+Object.size(this._canvases)); | |
var zoomOffset = this.options.zoomOffset, | |
key = [(zoom - zoomOffset), tilePoint.x, tilePoint.y].join('/'), | |
path = '/' + [tilePoint.x, tilePoint.y, (zoom - zoomOffset)].join('_') + '.png'; | |
console.log('seeking cache for: '+path); | |
var url = 'http://2g0.ru/map/kothic/tileprxy.php?z=' + (zoom - zoomOffset) + '&x=' + tilePoint.x + '&y=' + tilePoint.y; | |
var layer = this; | |
if ((typeof(fs) != 'undefined') && (typeof(window.requestFileSystem) != 'undefined')) | |
{ | |
fs.root.getFile(path, {}, function(fileEntry) { | |
// if tile is cached, no need to draw it on a canvas layer - it has already been drawn on PNG layer | |
layer.tileDrawn(canvas); | |
/* | |
var cached_img = new Image(); | |
cached_img.src = fileEntry.toURL(); | |
cached_img.onload = function () { | |
canvas.getContext('2d').drawImage(cached_img, 0, 0); | |
layer.tileDrawn(canvas); | |
console.log('shown from cache: '+path); | |
} | |
*/ | |
}, function(e) { | |
layer._canvases[key] = canvas; | |
layer._loadScript(url); | |
errorHandler(e); | |
console.log('requesting from server: '+path); | |
} ); | |
} else { | |
layer._canvases[key] = canvas; | |
layer._loadScript(url); | |
} | |
}, | |
setAdditionalStyle: function(fn) { | |
this._additionalStyle = fn; | |
// TODO implement layer.redraw() in Leaflet | |
if (this._map && this._map._container) { | |
this._reset(); | |
this._update(); | |
} | |
}, | |
_loadScript: function(url) { | |
var script = document.createElement('script'); | |
script.src = url; | |
script.charset = 'utf-8'; | |
document.getElementsByTagName('head')[0].appendChild(script); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment