1
0
Fork 0
forked from fte/fteqw

Try to update our javascript.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6071 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2021-10-05 05:05:50 +00:00
parent 8267939edb
commit 0218f2dcf2
4 changed files with 62 additions and 55 deletions

View file

@ -2258,6 +2258,9 @@ nacl-dbg:
################################################# #################################################
#webgl helpers #webgl helpers
ifeq ($(FTE_TARGET),web)
$(OUT_DIR)/$(EXE_NAME): ftejslib.js
endif
ifneq ($(shell which emcc 2> /dev/null),) ifneq ($(shell which emcc 2> /dev/null),)
EMCC?=emcc EMCC?=emcc
else else

View file

@ -1083,7 +1083,7 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, chanupdat
palSourcePlay(src); palSourcePlay(src);
} }
PrintALError(sfx&&sfx->name?sfx->name:"post start sound"); PrintALError(sfx?sfx->name:"post start sound");
} }
/* /*

View file

@ -2298,7 +2298,7 @@ vfsfile_t *QDECL FS_OpenVFS(const char *filename, const char *mode, enum fs_rela
{ {
if (gameonly_homedir) if (gameonly_homedir)
{ {
if ((*mode == 'w') if ((*mode == 'w' && gameonly_gamedir->handle->CreateFile)
? gameonly_homedir->handle->CreateFile(gameonly_homedir->handle, &loc, filename) ? gameonly_homedir->handle->CreateFile(gameonly_homedir->handle, &loc, filename)
: gameonly_homedir->handle->FindFile (gameonly_homedir->handle, &loc, filename, NULL)) : gameonly_homedir->handle->FindFile (gameonly_homedir->handle, &loc, filename, NULL))
vfs = gameonly_homedir->handle->OpenVFS (gameonly_homedir->handle, &loc, mode); vfs = gameonly_homedir->handle->OpenVFS (gameonly_homedir->handle, &loc, mode);
@ -2318,7 +2318,7 @@ vfsfile_t *QDECL FS_OpenVFS(const char *filename, const char *mode, enum fs_rela
{ {
if (gameonly_gamedir) if (gameonly_gamedir)
{ {
if ((*mode == 'w') if ((*mode == 'w' && gameonly_gamedir->handle->CreateFile)
? gameonly_gamedir->handle->CreateFile(gameonly_gamedir->handle, &loc, filename) ? gameonly_gamedir->handle->CreateFile(gameonly_gamedir->handle, &loc, filename)
: gameonly_gamedir->handle->FindFile (gameonly_gamedir->handle, &loc, filename, NULL)) : gameonly_gamedir->handle->FindFile (gameonly_gamedir->handle, &loc, filename, NULL))
vfs = gameonly_gamedir->handle->OpenVFS (gameonly_gamedir->handle, &loc, mode); vfs = gameonly_gamedir->handle->OpenVFS (gameonly_gamedir->handle, &loc, mode);

View file

@ -12,7 +12,7 @@ mergeInto(LibraryManager.library,
//FIXME: split+merge by \n //FIXME: split+merge by \n
emscriptenfte_print : function(msg) emscriptenfte_print : function(msg)
{ {
FTEC.linebuffer += Pointer_stringify(msg); FTEC.linebuffer += UTF8ToString(msg);
for(;;) for(;;)
{ {
nl = FTEC.linebuffer.indexOf("\n"); nl = FTEC.linebuffer.indexOf("\n");
@ -24,14 +24,14 @@ mergeInto(LibraryManager.library,
}, },
emscriptenfte_alert : function(msg) emscriptenfte_alert : function(msg)
{ {
msg = Pointer_stringify(msg); msg = UTF8ToString(msg);
console.log(msg); console.log(msg);
alert(msg); alert(msg);
}, },
emscriptenfte_window_location : function(msg) emscriptenfte_window_location : function(msg)
{ {
msg = Pointer_stringify(msg); msg = UTF8ToString(msg);
console.log("Redirecting page to " + msg); console.log("Redirecting page to " + msg);
window.location = msg; window.location = msg;
}, },
@ -96,7 +96,7 @@ mergeInto(LibraryManager.library,
writeStringToMemory(url, urlptr); writeStringToMemory(url, urlptr);
var mimeptr = _malloc(mime.length+1); var mimeptr = _malloc(mime.length+1);
writeStringToMemory(mime, mimeptr); writeStringToMemory(mime, mimeptr);
Runtime.dynCall('viii', FTEC.evcb.loadfile, [urlptr, mimeptr, handle]); {{{makeDynCall('viii')}}}(FTEC.evcb.loadfile, urlptr, mimeptr, handle);
_free(mimeptr); _free(mimeptr);
_free(urlptr); _free(urlptr);
window.focus(); window.focus();
@ -115,7 +115,7 @@ mergeInto(LibraryManager.library,
case 'resize': case 'resize':
if (FTEC.evcb.resize != 0) if (FTEC.evcb.resize != 0)
{ {
Runtime.dynCall('vii', FTEC.evcb.resize, [Module['canvas'].width, Module['canvas'].height]); {{{makeDynCall('vii')}}}(FTEC.evcb.resize, Module['canvas'].width, Module['canvas'].height);
} }
break; break;
case 'mousemove': case 'mousemove':
@ -133,12 +133,12 @@ mergeInto(LibraryManager.library,
event.movementX = event.webkitMovementX; event.movementX = event.webkitMovementX;
event.movementY = event.webkitMovementY; event.movementY = event.webkitMovementY;
} }
Runtime.dynCall('viiffff', FTEC.evcb.mouse, [0, false, event.movementX, event.movementY, 0, 0]); {{{makeDynCall('viiffff')}}}(FTEC.evcb.mouse, 0, false, event.movementX, event.movementY, 0, 0);
} }
else else
{ {
var rect = Module['canvas'].getBoundingClientRect(); var rect = Module['canvas'].getBoundingClientRect();
Runtime.dynCall('viiffff', FTEC.evcb.mouse, [0, true, (event.clientX - rect.left)*(Module['canvas'].width/rect.width), (event.clientY - rect.top)*(Module['canvas'].height/rect.height), 0, 0]); {{{makeDynCall('viiffff')}}}(FTEC.evcb.mouse, 0, true, (event.clientX - rect.left)*(Module['canvas'].width/rect.width), (event.clientY - rect.top)*(Module['canvas'].height/rect.height), 0, 0);
} }
} }
break; break;
@ -149,7 +149,7 @@ mergeInto(LibraryManager.library,
//so lets spam requests for it //so lets spam requests for it
if (Browser.isFullScreen == 0) if (Browser.isFullScreen == 0)
if (FTEC.evcb.wantfullscreen != 0) if (FTEC.evcb.wantfullscreen != 0)
if (Runtime.dynCall('i', FTEC.evcb.wantfullscreen, [])) if ({{{makeDynCall('i')}}}(FTEC.evcb.wantfullscreen))
{ {
Browser.requestFullScreen(true, true); Browser.requestFullScreen(true, true);
} }
@ -168,7 +168,7 @@ mergeInto(LibraryManager.library,
case 'mouseup': case 'mouseup':
if (FTEC.evcb.button != 0) if (FTEC.evcb.button != 0)
{ {
Runtime.dynCall('viii', FTEC.evcb.button, [0, event.type=='mousedown', event.button]); {{{makeDynCall('viii')}}}(FTEC.evcb.button, 0, event.type=='mousedown', event.button);
event.preventDefault(); event.preventDefault();
} }
break; break;
@ -176,7 +176,7 @@ mergeInto(LibraryManager.library,
case 'wheel': case 'wheel':
if (FTEC.evcb.button != 0) if (FTEC.evcb.button != 0)
{ {
Runtime.dynCall('viii', FTEC.evcb.button, [0, 2, event.deltaY]); {{{makeDynCall('viii')}}}(FTEC.evcb.button, 0, 2, event.deltaY);
event.preventDefault(); event.preventDefault();
} }
break; break;
@ -184,16 +184,16 @@ mergeInto(LibraryManager.library,
if (FTEC.evcb.button != 0) if (FTEC.evcb.button != 0)
{ {
for (var i = 0; i < 8; i++) for (var i = 0; i < 8; i++)
Runtime.dynCall('viii', FTEC.evcb.button, [0, false, i]); {{{makeDynCall('viii')}}}(FTEC.evcb.button, 0, false, i);
} }
if (FTEC.pointerislocked == -1) if (FTEC.pointerislocked == -1)
FTEC.pointerislocked = 0; FTEC.pointerislocked = 0;
break; break;
case 'focus': case 'focus':
case 'blur': case 'blur':
Runtime.dynCall('iiiii', FTEC.evcb.key, [0, false, 16, 0]); //shift {{{makeDynCall('iiiii')}}}(FTEC.evcb.key, 0, false, 16, 0); //shift
Runtime.dynCall('iiiii', FTEC.evcb.key, [0, false, 17, 0]); //alt {{{makeDynCall('iiiii')}}}(FTEC.evcb.key, 0, false, 17, 0); //alt
Runtime.dynCall('iiiii', FTEC.evcb.key, [0, false, 18, 0]); //ctrl {{{makeDynCall('iiiii')}}}(FTEC.evcb.key, 0, false, 18, 0); //ctrl
if (FTEC.pointerislocked == -1) if (FTEC.pointerislocked == -1)
FTEC.pointerislocked = 0; FTEC.pointerislocked = 0;
break; break;
@ -202,8 +202,8 @@ mergeInto(LibraryManager.library,
{ {
if (event.charCode >= 122 && event.charCode <= 123) //no f11/f12 if (event.charCode >= 122 && event.charCode <= 123) //no f11/f12
break; break;
Runtime.dynCall('iiiii', FTEC.evcb.key, [0, 1, 0, event.charCode]); {{{makeDynCall('iiiii')}}}(FTEC.evcb.key, 0, 1, 0, event.charCode);
Runtime.dynCall('iiiii', FTEC.evcb.key, [0, 0, 0, event.charCode]); {{{makeDynCall('iiiii')}}}(FTEC.evcb.key, 0, 0, 0, event.charCode);
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
} }
@ -214,7 +214,7 @@ mergeInto(LibraryManager.library,
//we don't steal that because its impossible to leave it again once used. //we don't steal that because its impossible to leave it again once used.
if (FTEC.evcb.key != 0 && event.keyCode != 122) if (FTEC.evcb.key != 0 && event.keyCode != 122)
{ {
if (Runtime.dynCall('iiiii', FTEC.evcb.key, [0, event.type=='keydown', event.keyCode, 0])) if ({{{makeDynCall('iiiii')}}}(FTEC.evcb.key, 0, event.type=='keydown', event.keyCode, 0))
event.preventDefault(); event.preventDefault();
} }
break; break;
@ -228,13 +228,13 @@ mergeInto(LibraryManager.library,
{ {
var t = touches[i]; var t = touches[i];
if (FTEC.evcb.mouse) if (FTEC.evcb.mouse)
Runtime.dynCall('viiffff', FTEC.evcb.mouse, [t.identifier+1, true, t.pageX, t.pageY, 0, Math.sqrt(t.radiusX*t.radiusX+t.radiusY*t.radiusY)]); {{{makeDynCall('viiffff')}}}(FTEC.evcb.mouse, t.identifier+1, true, t.pageX, t.pageY, 0, Math.sqrt(t.radiusX*t.radiusX+t.radiusY*t.radiusY));
if (FTEC.evcb.button) if (FTEC.evcb.button)
{ {
if (event.type == 'touchstart') if (event.type == 'touchstart')
Runtime.dynCall('viii', FTEC.evcb.button, [t.identifier+1, 1, 0]); {{{makeDynCall('viii')}}}(FTEC.evcb.button, t.identifier+1, 1, 0);
else if (event.type != 'touchmove') else if (event.type != 'touchmove')
Runtime.dynCall('viii', FTEC.evcb.button, [t.identifier+1, 0, 0]); {{{makeDynCall('viii')}}}(FTEC.evcb.button, t.identifier+1, 0, 0);
} }
} }
event.preventDefault(); event.preventDefault();
@ -271,10 +271,10 @@ mergeInto(LibraryManager.library,
delete FTEH.gamepads[gp.index]; delete FTEH.gamepads[gp.index];
if (FTEC.evcb.jaxis) //try and clear out the axis when released. if (FTEC.evcb.jaxis) //try and clear out the axis when released.
for (var j = 0; j < 6; j+=1) for (var j = 0; j < 6; j+=1)
Runtime.dynCall('viifi', FTEC.evcb.jaxis, [gp.index, j, 0, true]); {{{makeDynCall('viifi')}}}(FTEC.evcb.jaxis, gp.index, j, 0, true);
if (FTEC.evcb.jbutton) //try and clear out the axis when released. if (FTEC.evcb.jbutton) //try and clear out the axis when released.
for (var j = 0; j < 32+4; j+=1) for (var j = 0; j < 32+4; j+=1)
Runtime.dynCall('viiii', FTEC.evcb.jbutton, [gp.index, j, 0, true]); {{{makeDynCall('viiii')}}}(FTEC.evcb.jbutton, gp.index, j, 0, true);
console.log("Gamepad disconnected from index %d: %s", gp.index, gp.id); console.log("Gamepad disconnected from index %d: %s", gp.index, gp.id);
break; break;
case 'pointerlockchange': case 'pointerlockchange':
@ -307,6 +307,9 @@ mergeInto(LibraryManager.library,
FTEC.usevr = false; FTEC.usevr = false;
} }
break; break;
case 'beforeunload':
event.preventDefault();
return 'quit this game like everything else?';
default: default:
console.log(event); console.log(event);
break; break;
@ -392,11 +395,11 @@ mergeInto(LibraryManager.library,
if (b.lastframe != p) if (b.lastframe != p)
{ //cache it to avoid spam { //cache it to avoid spam
b.lastframe = p; b.lastframe = p;
Runtime.dynCall('viiii', FTEC.evcb.jbutton, [gp.index, j, p, gp.mapping=="standard"]); {{{makeDynCall('viiii')}}}(FTEC.evcb.jbutton, gp.index, j, p, gp.mapping=="standard");
} }
} }
for (var j = 0; j < gp.axes.length; j+=1) for (var j = 0; j < gp.axes.length; j+=1)
Runtime.dynCall('viifi', FTEC.evcb.jaxis, [gp.index, j, gp.axes[j], gp.mapping=="standard"]); {{{makeDynCall('viifi')}}}(FTEC.evcb.jaxis, gp.index, j, gp.axes[j], gp.mapping=="standard");
} }
}, },
emscriptenfte_setupcanvas__deps: ['$FTEC', '$Browser', 'emscriptenfte_buf_createfromarraybuf'], emscriptenfte_setupcanvas__deps: ['$FTEC', '$Browser', 'emscriptenfte_buf_createfromarraybuf'],
@ -452,7 +455,7 @@ mergeInto(LibraryManager.library,
document.addEventListener(event, FTEC.handleevent, true); document.addEventListener(event, FTEC.handleevent, true);
}); });
var windowevents = ['message','vrdisplaypresentchange','vrdisplayactivate','vrdisplaydeactivate','gamepadconnected', 'gamepaddisconnected']; var windowevents = ['message','vrdisplaypresentchange','vrdisplayactivate','vrdisplaydeactivate','gamepadconnected', 'gamepaddisconnected', 'beforeunload'];
windowevents.forEach(function(event) windowevents.forEach(function(event)
{ {
window.addEventListener(event, FTEC.handleevent, true); window.addEventListener(event, FTEC.handleevent, true);
@ -492,7 +495,7 @@ mergeInto(LibraryManager.library,
Browser.setCanvasSize(rect.width, rect.height, false); Browser.setCanvasSize(rect.width, rect.height, false);
} }
if (FTEC.evcb.resize != 0) if (FTEC.evcb.resize != 0)
Runtime.dynCall('vii', FTEC.evcb.resize, [Module['canvas'].width, Module['canvas'].height]); {{{makeDynCall('vii')}}}(FTEC.evcb.resize, Module['canvas'].width, Module['canvas'].height);
}; };
window.onresize(); window.onresize();
@ -514,26 +517,26 @@ mergeInto(LibraryManager.library,
}, },
emscriptenfte_settitle : function(txt) emscriptenfte_settitle : function(txt)
{ {
document.title = Pointer_stringify(txt); document.title = UTF8ToString(txt);
}, },
emscriptenfte_abortmainloop : function(fname) emscriptenfte_abortmainloop : function(fname)
{ {
fname = Pointer_stringify(fname); fname = UTF8ToString(fname);
FTEC.aborted = true; FTEC.aborted = true;
throw 'oh noes! something bad happened in ' + fname + '!\n' + Module['stackTrace'](); throw 'oh noes! something bad happened in ' + fname + '!\n' + Module['stackTrace']();
}, },
emscriptenfte_setupmainloop__deps: ['$FTEC'],
emscriptenfte_setupmainloop : function(fnc) emscriptenfte_setupmainloop : function(fnc)
{ {
Module['noExitRuntime'] = true; Module['noExitRuntime'] = true;
FTEC.aborted = false; FTEC.aborted = false;
//Module.abort = abort = function(msg) {};
function step(timestamp) function step(timestamp)
{ {
var dovsync = false; var dovsync = false;
var vr = false; var vr = false;
if (FTE.aborted) if (FTEC.aborted)
return; return;
if (FTEC.vrDisplay) if (FTEC.vrDisplay)
@ -544,7 +547,7 @@ mergeInto(LibraryManager.library,
try //this try is needed to handle Host_EndGame properly. try //this try is needed to handle Host_EndGame properly.
{ {
dovsync = Runtime.dynCall('i', fnc, []); dovsync = {{{makeDynCall('i')}}}(fnc);
} }
catch(err) catch(err)
{ {
@ -555,13 +558,14 @@ mergeInto(LibraryManager.library,
if (dovsync) if (dovsync)
{ {
if (FTEC.vrDisplay) if (FTEC.vrDisplay)
FTEC.vrDisplay.requestAnimationFrame(step); FTEC.vrDisplay.requestAnimationFrame(Module["sched"]);
else else
Browser.requestAnimationFrame(step); Browser.requestAnimationFrame(Module["sched"]);
} }
else else
setTimeout(step, 0); setTimeout(Module["sched"], 0);
}; };
Module["sched"] = step;
//don't start it instantly, so we can distinguish between types of errors (emscripten sucks!). //don't start it instantly, so we can distinguish between types of errors (emscripten sucks!).
setTimeout(step, 1); setTimeout(step, 1);
}, },
@ -582,7 +586,7 @@ mergeInto(LibraryManager.library,
emscriptenfte_buf_open__deps : ['emscriptenfte_buf_create'], emscriptenfte_buf_open__deps : ['emscriptenfte_buf_create'],
emscriptenfte_buf_open : function(name, createifneeded) emscriptenfte_buf_open : function(name, createifneeded)
{ {
name = Pointer_stringify(name); name = UTF8ToString(name);
var f = FTEH.f[name]; var f = FTEH.f[name];
var r = -1; var r = -1;
if (f == null) if (f == null)
@ -642,8 +646,8 @@ mergeInto(LibraryManager.library,
}, },
emscriptenfte_buf_rename : function(oldname, newname) emscriptenfte_buf_rename : function(oldname, newname)
{ {
oldname = Pointer_stringify(oldname); oldname = UTF8ToString(oldname);
newname = Pointer_stringify(newname); newname = UTF8ToString(newname);
var f = FTEH.f[oldname]; var f = FTEH.f[oldname];
if (f == null) if (f == null)
return 0; return 0;
@ -656,7 +660,7 @@ mergeInto(LibraryManager.library,
}, },
emscriptenfte_buf_delete : function(name) emscriptenfte_buf_delete : function(name)
{ {
name = Pointer_stringify(name); name = UTF8ToString(name);
var f = FTEH.f[name]; var f = FTEH.f[name];
if (f) if (f)
{ {
@ -756,8 +760,8 @@ mergeInto(LibraryManager.library,
emscriptenfte_ws_connect__deps: ['emscriptenfte_handle_alloc'], emscriptenfte_ws_connect__deps: ['emscriptenfte_handle_alloc'],
emscriptenfte_ws_connect : function(brokerurl, protocolname) emscriptenfte_ws_connect : function(brokerurl, protocolname)
{ {
var _url = Pointer_stringify(brokerurl); var _url = UTF8ToString(brokerurl);
var _protocol = Pointer_stringify(protocolname); var _protocol = UTF8ToString(protocolname);
var s = {ws:null, inq:[], err:0, con:0}; var s = {ws:null, inq:[], err:0, con:0};
try { try {
s.ws = new WebSocket(_url, _protocol); s.ws = new WebSocket(_url, _protocol);
@ -864,7 +868,7 @@ console.log("emscriptenfte_rtc_create callback: " + evtype);
var stringlen = (stringdata.length*3)+1; var stringlen = (stringdata.length*3)+1;
var dataptr = _malloc(stringlen); var dataptr = _malloc(stringlen);
stringToUTF8(stringdata, dataptr, stringlen); stringToUTF8(stringdata, dataptr, stringlen);
Runtime.dynCall('viiii', callback, [ctxp,ctxi,evtype,dataptr]); {{{makeDynCall('viiii')}}}(callback, ctxp,ctxi,evtype,dataptr);
_free(dataptr); _free(dataptr);
} }
}; };
@ -973,8 +977,8 @@ console.log(e);
emscriptenfte_rtc_offer : function(sockid, offer, offertype) emscriptenfte_rtc_offer : function(sockid, offer, offertype)
{ {
var s = FTEH.h[sockid]; var s = FTEH.h[sockid];
offer = Pointer_stringify(offer); offer = UTF8ToString(offer);
offertype = Pointer_stringify(offertype); offertype = UTF8ToString(offertype);
if (s === undefined) if (s === undefined)
return -1; return -1;
@ -1012,7 +1016,7 @@ console.log(e);
emscriptenfte_rtc_candidate : function(sockid, offer) emscriptenfte_rtc_candidate : function(sockid, offer)
{ {
var s = FTEH.h[sockid]; var s = FTEH.h[sockid];
offer = Pointer_stringify(offer); offer = UTF8ToString(offer);
if (s === undefined) if (s === undefined)
return -1; return -1;
@ -1028,7 +1032,7 @@ console.log(desc);
emscriptenfte_async_wget_data2 : function(url, ctx, onload, onerror, onprogress) emscriptenfte_async_wget_data2 : function(url, ctx, onload, onerror, onprogress)
{ {
var _url = Pointer_stringify(url); var _url = UTF8ToString(url);
console.log("Attempting download of " + _url); console.log("Attempting download of " + _url);
var http = new XMLHttpRequest(); var http = new XMLHttpRequest();
try try
@ -1038,7 +1042,7 @@ console.log(desc);
catch(e) catch(e)
{ {
if (onerror) if (onerror)
Runtime.dynCall('vii', onerror, [ctx, 404]); {{{makeDynCall('vii')}}}(onerror, ctx, 404);
return; return;
} }
http.responseType = 'arraybuffer'; http.responseType = 'arraybuffer';
@ -1049,12 +1053,12 @@ console.log("onload: " + _url + " status " + http.status);
if (http.status == 200) if (http.status == 200)
{ {
if (onload) if (onload)
Runtime.dynCall('vii', onload, [ctx, _emscriptenfte_buf_createfromarraybuf(http.response)]); {{{makeDynCall('vii')}}}(onload, ctx, _emscriptenfte_buf_createfromarraybuf(http.response));
} }
else else
{ {
if (onerror) if (onerror)
Runtime.dynCall('vii', onerror, [ctx, http.status]); {{{makeDynCall('vii')}}}(onerror, ctx, http.status);
} }
}; };
@ -1062,13 +1066,13 @@ console.log("onload: " + _url + " status " + http.status);
{ {
console.log("onerror: " + _url); console.log("onerror: " + _url);
if (onerror) if (onerror)
Runtime.dynCall('vii', onerror, [ctx, 0]); {{{makeDynCall('vii')}}}(onerror, ctx, 0);
}; };
http.onprogress = function(e) http.onprogress = function(e)
{ {
if (onprogress) if (onprogress)
Runtime.dynCall('viii', onprogress, [ctx, e.loaded, e.total]); {{{makeDynCall('viii')}}}(onprogress, ctx, e.loaded, e.total);
}; };
try //ffs try //ffs
@ -1157,7 +1161,7 @@ console.log("onerror: " + _url);
var img = new Image(); var img = new Image();
var gltex = GL.textures[texid]; var gltex = GL.textures[texid];
img.name = Pointer_stringify(fname); img.name = UTF8ToString(fname);
img.onload = function() img.onload = function()
{ {
if (img.width < 1 || img.height < 1) if (img.width < 1 || img.height < 1)