Remove support for non-HTML5 browsers.
Display API change: - getTile -> startTile (no longer returns a tile) - setSubTile -> subTile (drop img/tile first parameter) - putTile -> finishTile (no longer takes img/tile paramter) The Display tile logic uses canvas image data directly and caches/reuses a 16x16 imageData tile (for other sizes, the tile is create for each call). This gives a 30% speedup on Chrome 13 (and no significant change for Firefox 3.6/4.0). Other: - Remove rgbxImageFill and cmapImageFill routines. - Simplify constructor tests and just error if createImageData is not supported by canvas instead of . - Remove webkit canvas bug workaround that effects Chrome 7. Chrome 7 usage share is now less than 0.5 percent and the workaround is ugly. Drop the function wrapping in the constructor and the canvas flush() routine. - Remove support for getImageData (Opera 11+ now required) Update browser support list: - Chrome 8+ (really any except 7) - Firefox 3.6+ - Safari 4+ - Opera 11+ - IE9+ - iOS 4.2+
This commit is contained in:
parent
859fc7f18f
commit
490d471c53
|
@ -19,11 +19,9 @@ var that = {}, // Public API methods
|
||||||
c_ctx = null,
|
c_ctx = null,
|
||||||
c_forceCanvas = false,
|
c_forceCanvas = false,
|
||||||
|
|
||||||
c_imageData, c_rgbxImage, c_cmapImage,
|
|
||||||
|
|
||||||
// Predefine function variables (jslint)
|
// Predefine function variables (jslint)
|
||||||
imageDataCreate, imageDataGet, rgbxImageData, cmapImageData,
|
imageDataGet, rgbxImageData, cmapImageData,
|
||||||
rgbxImageFill, cmapImageFill, setFillColor, rescale, flush,
|
setFillColor, rescale,
|
||||||
|
|
||||||
// The full frame buffer (logical canvas) size
|
// The full frame buffer (logical canvas) size
|
||||||
fb_width = 0,
|
fb_width = 0,
|
||||||
|
@ -33,9 +31,11 @@ var that = {}, // Public API methods
|
||||||
cleanRect = {'x1': 0, 'y1': 0, 'x2': -1, 'y2': -1},
|
cleanRect = {'x1': 0, 'y1': 0, 'x2': -1, 'y2': -1},
|
||||||
|
|
||||||
c_prevStyle = "",
|
c_prevStyle = "",
|
||||||
|
tile = null,
|
||||||
|
tile16x16 = null,
|
||||||
|
tile_x = 0,
|
||||||
|
tile_y = 0;
|
||||||
|
|
||||||
c_webkit_bug = false,
|
|
||||||
c_flush_timer = null;
|
|
||||||
|
|
||||||
// Configuration attributes
|
// Configuration attributes
|
||||||
Util.conf_defaults(conf, that, defaults, [
|
Util.conf_defaults(conf, that, defaults, [
|
||||||
|
@ -66,15 +66,6 @@ that.get_width = function() { return fb_width; };
|
||||||
that.set_height = function (val) { that.resize(fb_width, val); };
|
that.set_height = function (val) { that.resize(fb_width, val); };
|
||||||
that.get_height = function() { return fb_height; };
|
that.get_height = function() { return fb_height; };
|
||||||
|
|
||||||
that.set_prefer_js = function(val) {
|
|
||||||
if (val && c_forceCanvas) {
|
|
||||||
Util.Warn("Preferring Javascript to Canvas ops is not supported");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
conf.prefer_js = val;
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -85,7 +76,7 @@ that.set_prefer_js = function(val) {
|
||||||
function constructor() {
|
function constructor() {
|
||||||
Util.Debug(">> Display.constructor");
|
Util.Debug(">> Display.constructor");
|
||||||
|
|
||||||
var c, func, imgTest, tval, i, curDat, curSave,
|
var c, func, i, curDat, curSave,
|
||||||
has_imageData = false, UE = Util.Engine;
|
has_imageData = false, UE = Util.Engine;
|
||||||
|
|
||||||
if (! conf.target) { throw("target must be set"); }
|
if (! conf.target) { throw("target must be set"); }
|
||||||
|
@ -108,70 +99,19 @@ function constructor() {
|
||||||
|
|
||||||
that.clear();
|
that.clear();
|
||||||
|
|
||||||
/*
|
// Check canvas features
|
||||||
* Determine browser Canvas feature support
|
if ('createImageData' in c_ctx) {
|
||||||
* and select fastest rendering methods
|
conf.render_mode = "canvas rendering";
|
||||||
*/
|
|
||||||
tval = 0;
|
|
||||||
try {
|
|
||||||
imgTest = c_ctx.getImageData(0, 0, 1,1);
|
|
||||||
imgTest.data[0] = 123;
|
|
||||||
imgTest.data[3] = 255;
|
|
||||||
c_ctx.putImageData(imgTest, 0, 0);
|
|
||||||
tval = c_ctx.getImageData(0, 0, 1, 1).data[0];
|
|
||||||
if (tval === 123) {
|
|
||||||
has_imageData = true;
|
|
||||||
}
|
|
||||||
} catch (exc1) {}
|
|
||||||
|
|
||||||
if (has_imageData) {
|
|
||||||
Util.Info("Canvas supports imageData");
|
|
||||||
c_forceCanvas = false;
|
|
||||||
if (c_ctx.createImageData) {
|
|
||||||
// If it's there, it's faster
|
|
||||||
Util.Info("Using Canvas createImageData");
|
|
||||||
conf.render_mode = "createImageData rendering";
|
|
||||||
c_imageData = imageDataCreate;
|
|
||||||
} else if (c_ctx.getImageData) {
|
|
||||||
// I think this is mostly just Opera
|
|
||||||
Util.Info("Using Canvas getImageData");
|
|
||||||
conf.render_mode = "getImageData rendering";
|
|
||||||
c_imageData = imageDataGet;
|
|
||||||
}
|
|
||||||
Util.Info("Prefering javascript operations");
|
|
||||||
if (conf.prefer_js === null) {
|
|
||||||
conf.prefer_js = true;
|
|
||||||
}
|
|
||||||
c_rgbxImage = rgbxImageData;
|
|
||||||
c_cmapImage = cmapImageData;
|
|
||||||
} else {
|
} else {
|
||||||
Util.Warn("Canvas lacks imageData, using fillRect (slow)");
|
throw("Canvas does not support createImageData");
|
||||||
conf.render_mode = "fillRect rendering (slow)";
|
}
|
||||||
c_forceCanvas = true;
|
if (conf.prefer_js === null) {
|
||||||
conf.prefer_js = false;
|
Util.Info("Prefering javascript operations");
|
||||||
c_rgbxImage = rgbxImageFill;
|
conf.prefer_js = true;
|
||||||
c_cmapImage = cmapImageFill;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UE.webkit && UE.webkit >= 534.7 && UE.webkit <= 534.9) {
|
// Initialize cached tile imageData
|
||||||
// Workaround WebKit canvas rendering bug #46319
|
tile16x16 = c_ctx.createImageData(16, 16);
|
||||||
conf.render_mode += ", webkit bug workaround";
|
|
||||||
Util.Debug("Working around WebKit bug #46319");
|
|
||||||
c_webkit_bug = true;
|
|
||||||
for (func in {"fillRect":1, "copyImage":1, "rgbxImage":1,
|
|
||||||
"cmapImage":1, "blitStringImage":1}) {
|
|
||||||
that[func] = (function() {
|
|
||||||
var myfunc = that[func]; // Save original function
|
|
||||||
//Util.Debug("Wrapping " + func);
|
|
||||||
return function() {
|
|
||||||
myfunc.apply(this, arguments);
|
|
||||||
if (!c_flush_timer) {
|
|
||||||
c_flush_timer = setTimeout(flush, 100);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine browser support for setting the cursor via data URI
|
* Determine browser support for setting the cursor via data URI
|
||||||
|
@ -425,18 +365,6 @@ that.absY = function(y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Force canvas redraw (for webkit bug #46319 workaround)
|
|
||||||
flush = function() {
|
|
||||||
var old_val;
|
|
||||||
//Util.Debug(">> flush");
|
|
||||||
old_val = conf.target.style.marginRight;
|
|
||||||
conf.target.style.marginRight = "1px";
|
|
||||||
c_flush_timer = null;
|
|
||||||
setTimeout(function () {
|
|
||||||
conf.target.style.marginRight = old_val;
|
|
||||||
}, 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
setFillColor = function(color) {
|
setFillColor = function(color) {
|
||||||
var rgb, newStyle;
|
var rgb, newStyle;
|
||||||
if (conf.true_color) {
|
if (conf.true_color) {
|
||||||
|
@ -498,10 +426,16 @@ that.copyImage = function(old_x, old_y, new_x, new_y, w, h) {
|
||||||
* faster than direct Canvas fillStyle, fillRect rendering. In
|
* faster than direct Canvas fillStyle, fillRect rendering. In
|
||||||
* gecko, Javascript array handling is much slower.
|
* gecko, Javascript array handling is much slower.
|
||||||
*/
|
*/
|
||||||
that.getTile = function(x, y, width, height, color) {
|
that.startTile = function(x, y, width, height, color) {
|
||||||
var img, data = [], rgb, red, green, blue, i;
|
var data, rgb, red, green, blue, i;
|
||||||
img = {'x': x, 'y': y, 'width': width, 'height': height,
|
tile_x = x;
|
||||||
'data': data};
|
tile_y = y;
|
||||||
|
if ((width === 16) && (height === 16)) {
|
||||||
|
tile = tile16x16;
|
||||||
|
} else {
|
||||||
|
tile = c_ctx.createImageData(width, height);
|
||||||
|
}
|
||||||
|
data = tile.data;
|
||||||
if (conf.prefer_js) {
|
if (conf.prefer_js) {
|
||||||
if (conf.true_color) {
|
if (conf.true_color) {
|
||||||
rgb = color;
|
rgb = color;
|
||||||
|
@ -515,18 +449,18 @@ that.getTile = function(x, y, width, height, color) {
|
||||||
data[i ] = red;
|
data[i ] = red;
|
||||||
data[i + 1] = green;
|
data[i + 1] = green;
|
||||||
data[i + 2] = blue;
|
data[i + 2] = blue;
|
||||||
|
data[i + 3] = 255;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
that.fillRect(x, y, width, height, color);
|
that.fillRect(x, y, width, height, color);
|
||||||
}
|
}
|
||||||
return img;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
that.setSubTile = function(img, x, y, w, h, color) {
|
that.subTile = function(x, y, w, h, color) {
|
||||||
var data, p, rgb, red, green, blue, width, j, i, xend, yend;
|
var data, p, rgb, red, green, blue, width, j, i, xend, yend;
|
||||||
if (conf.prefer_js) {
|
if (conf.prefer_js) {
|
||||||
data = img.data;
|
data = tile.data;
|
||||||
width = img.width;
|
width = tile.width;
|
||||||
if (conf.true_color) {
|
if (conf.true_color) {
|
||||||
rgb = color;
|
rgb = color;
|
||||||
} else {
|
} else {
|
||||||
|
@ -543,25 +477,19 @@ that.setSubTile = function(img, x, y, w, h, color) {
|
||||||
data[p ] = red;
|
data[p ] = red;
|
||||||
data[p + 1] = green;
|
data[p + 1] = green;
|
||||||
data[p + 2] = blue;
|
data[p + 2] = blue;
|
||||||
|
data[p + 3] = 255;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
that.fillRect(img.x + x, img.y + y, w, h, color);
|
that.fillRect(tile_x + x, tile_y + y, w, h, color);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
that.putTile = function(img) {
|
that.finishTile = function() {
|
||||||
if (conf.prefer_js) {
|
if (conf.prefer_js) {
|
||||||
c_rgbxImage(img.x, img.y, img.width, img.height, img.data, 0);
|
c_ctx.putImageData(tile, tile_x - viewport.x, tile_y - viewport.y)
|
||||||
}
|
}
|
||||||
// else: No-op, under gecko already done by setSubTile
|
// else: No-op, if not prefer_js then already done by setSubTile
|
||||||
};
|
|
||||||
|
|
||||||
imageDataGet = function(width, height) {
|
|
||||||
return c_ctx.getImageData(0, 0, width, height);
|
|
||||||
};
|
|
||||||
imageDataCreate = function(width, height) {
|
|
||||||
return c_ctx.createImageData(width, height);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
rgbxImageData = function(x, y, width, height, arr, offset) {
|
rgbxImageData = function(x, y, width, height, arr, offset) {
|
||||||
|
@ -569,12 +497,11 @@ rgbxImageData = function(x, y, width, height, arr, offset) {
|
||||||
/*
|
/*
|
||||||
if ((x - v.x >= v.w) || (y - v.y >= v.h) ||
|
if ((x - v.x >= v.w) || (y - v.y >= v.h) ||
|
||||||
(x - v.x + width < 0) || (y - v.y + height < 0)) {
|
(x - v.x + width < 0) || (y - v.y + height < 0)) {
|
||||||
//console.log("skipping, out of bounds: ", x, y);
|
|
||||||
// Skipping because outside of viewport
|
// Skipping because outside of viewport
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
img = c_imageData(width, height);
|
img = c_ctx.createImageData(width, height);
|
||||||
data = img.data;
|
data = img.data;
|
||||||
for (i=0, j=offset; i < (width * height * 4); i=i+4, j=j+4) {
|
for (i=0, j=offset; i < (width * height * 4); i=i+4, j=j+4) {
|
||||||
data[i ] = arr[j ];
|
data[i ] = arr[j ];
|
||||||
|
@ -585,22 +512,9 @@ rgbxImageData = function(x, y, width, height, arr, offset) {
|
||||||
c_ctx.putImageData(img, x - v.x, y - v.y);
|
c_ctx.putImageData(img, x - v.x, y - v.y);
|
||||||
};
|
};
|
||||||
|
|
||||||
// really slow fallback if we don't have imageData
|
|
||||||
rgbxImageFill = function(x, y, width, height, arr, offset) {
|
|
||||||
var i, j, sx = 0, sy = 0;
|
|
||||||
for (i=0, j=offset; i < (width * height); i+=1, j+=4) {
|
|
||||||
that.fillRect(x+sx, y+sy, 1, 1, [arr[j], arr[j+1], arr[j+2]]);
|
|
||||||
sx += 1;
|
|
||||||
if ((sx % width) === 0) {
|
|
||||||
sx = 0;
|
|
||||||
sy += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
cmapImageData = function(x, y, width, height, arr, offset) {
|
cmapImageData = function(x, y, width, height, arr, offset) {
|
||||||
var img, i, j, data, rgb, cmap;
|
var img, i, j, data, rgb, cmap;
|
||||||
img = c_imageData(width, height);
|
img = c_ctx.createImageData(width, height);
|
||||||
data = img.data;
|
data = img.data;
|
||||||
cmap = conf.colourMap;
|
cmap = conf.colourMap;
|
||||||
for (i=0, j=offset; i < (width * height * 4); i+=4, j+=1) {
|
for (i=0, j=offset; i < (width * height * 4); i+=4, j+=1) {
|
||||||
|
@ -613,25 +527,11 @@ cmapImageData = function(x, y, width, height, arr, offset) {
|
||||||
c_ctx.putImageData(img, x - viewport.x, y - viewport.y);
|
c_ctx.putImageData(img, x - viewport.x, y - viewport.y);
|
||||||
};
|
};
|
||||||
|
|
||||||
cmapImageFill = function(x, y, width, height, arr, offset) {
|
|
||||||
var i, j, sx = 0, sy = 0, cmap;
|
|
||||||
cmap = conf.colourMap;
|
|
||||||
for (i=0, j=offset; i < (width * height); i+=1, j+=1) {
|
|
||||||
that.fillRect(x+sx, y+sy, 1, 1, [arr[j]]);
|
|
||||||
sx += 1;
|
|
||||||
if ((sx % width) === 0) {
|
|
||||||
sx = 0;
|
|
||||||
sy += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
that.blitImage = function(x, y, width, height, arr, offset) {
|
that.blitImage = function(x, y, width, height, arr, offset) {
|
||||||
if (conf.true_color) {
|
if (conf.true_color) {
|
||||||
c_rgbxImage(x, y, width, height, arr, offset);
|
rgbxImageData(x, y, width, height, arr, offset);
|
||||||
} else {
|
} else {
|
||||||
c_cmapImage(x, y, width, height, arr, offset);
|
cmapImageData(x, y, width, height, arr, offset);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1096,7 +1096,7 @@ encHandlers.RRE = function display_rre() {
|
||||||
|
|
||||||
encHandlers.HEXTILE = function display_hextile() {
|
encHandlers.HEXTILE = function display_hextile() {
|
||||||
//Util.Debug(">> display_hextile");
|
//Util.Debug(">> display_hextile");
|
||||||
var subencoding, subrects, tile, color, cur_tile,
|
var subencoding, subrects, color, cur_tile,
|
||||||
tile_x, x, w, tile_y, y, h, xy, s, sx, sy, wh, sw, sh,
|
tile_x, x, w, tile_y, y, h, xy, s, sx, sy, wh, sw, sh,
|
||||||
rQ = ws.get_rQ(), rQi = ws.get_rQi();
|
rQ = ws.get_rQ(), rQi = ws.get_rQi();
|
||||||
|
|
||||||
|
@ -1185,7 +1185,7 @@ encHandlers.HEXTILE = function display_hextile() {
|
||||||
rQi += fb_Bpp;
|
rQi += fb_Bpp;
|
||||||
}
|
}
|
||||||
|
|
||||||
tile = display.getTile(x, y, w, h, FBU.background);
|
display.startTile(x, y, w, h, FBU.background);
|
||||||
if (FBU.subencoding & 0x08) { // AnySubrects
|
if (FBU.subencoding & 0x08) { // AnySubrects
|
||||||
subrects = rQ[rQi];
|
subrects = rQ[rQi];
|
||||||
rQi += 1;
|
rQi += 1;
|
||||||
|
@ -1206,10 +1206,10 @@ encHandlers.HEXTILE = function display_hextile() {
|
||||||
sw = (wh >> 4) + 1;
|
sw = (wh >> 4) + 1;
|
||||||
sh = (wh & 0x0f) + 1;
|
sh = (wh & 0x0f) + 1;
|
||||||
|
|
||||||
display.setSubTile(tile, sx, sy, sw, sh, color);
|
display.subTile(sx, sy, sw, sh, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
display.putTile(tile);
|
display.finishTile();
|
||||||
}
|
}
|
||||||
ws.set_rQi(rQi);
|
ws.set_rQi(rQi);
|
||||||
FBU.lastsubencoding = FBU.subencoding;
|
FBU.lastsubencoding = FBU.subencoding;
|
||||||
|
|
Loading…
Reference in New Issue