diff options
-rw-r--r-- | src/library.js | 4 | ||||
-rw-r--r-- | src/library_browser.js | 6 | ||||
-rw-r--r-- | src/library_gl.js | 70 | ||||
-rw-r--r-- | src/library_sdl.js | 196 | ||||
-rw-r--r-- | system/include/SDL/SDL_keycode.h | 3 | ||||
-rwxr-xr-x | tests/runner.py | 52 | ||||
-rw-r--r-- | tests/sdl_gfx_primitives.c | 46 | ||||
-rw-r--r-- | tests/sdl_gfx_primitives.png | bin | 0 -> 2357 bytes | |||
-rw-r--r-- | tests/sdl_rotozoom.c | 20 | ||||
-rw-r--r-- | tests/sdl_rotozoom.png | bin | 360054 -> 437956 bytes | |||
-rw-r--r-- | tests/utime/test_utime.c | 53 |
11 files changed, 325 insertions, 125 deletions
diff --git a/src/library.js b/src/library.js index b7973d98..3597891e 100644 --- a/src/library.js +++ b/src/library.js @@ -867,10 +867,6 @@ LibraryManager.library = { } var file = FS.findObject(Pointer_stringify(path)); if (file === null) return -1; - if (!file.write) { - ___setErrNo(ERRNO_CODES.EPERM); - return -1; - } file.timestamp = time; return 0; }, diff --git a/src/library_browser.js b/src/library_browser.js index d9fd3ee5..7f79b2bd 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -84,13 +84,17 @@ mergeInto(LibraryManager.library, { var imagePlugin = {}; imagePlugin['canHandle'] = function(name) { - return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/.exec(name); + return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/i.test(name); }; imagePlugin['handle'] = function(byteArray, name, onload, onerror) { var b = null; if (Browser.hasBlobConstructor) { try { b = new Blob([byteArray], { type: getMimetype(name) }); + if (b.size !== byteArray.length) { // Safari bug #118630 + // Safari's Blob can only take an ArrayBuffer + b = new Blob([(new Uint8Array(byteArray)).buffer], { type: getMimetype(name) }); + } } catch(e) { Runtime.warnOnce('Blob constructor present but fails: ' + e + '; falling back to blob builder'); } diff --git a/src/library_gl.js b/src/library_gl.js index e59492cf..959773bc 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -122,14 +122,6 @@ var LibraryGL = { } }, - // Linear lookup in one of the tables (buffers, programs, etc.). TODO: consider using a weakmap to make this faster, if it matters - scan: function(table, object) { - for (var item in table) { - if (table[item] == object) return item; - } - return 0; - }, - // Find a token in a shader source string findToken: function(source, token) { function isIdentChar(ch) { @@ -402,15 +394,15 @@ var LibraryGL = { {{{ makeSetValue('p', 'i*4', 'result[i]', 'i32') }}}; } } else if (result instanceof WebGLBuffer) { - {{{ makeSetValue('p', '0', 'GL.scan(GL.buffers, result)', 'i32') }}}; + {{{ makeSetValue('p', '0', 'result.name | 0', 'i32') }}}; } else if (result instanceof WebGLProgram) { - {{{ makeSetValue('p', '0', 'GL.scan(GL.programs, result)', 'i32') }}}; + {{{ makeSetValue('p', '0', 'result.name | 0', 'i32') }}}; } else if (result instanceof WebGLFramebuffer) { - {{{ makeSetValue('p', '0', 'GL.scan(GL.framebuffers, result)', 'i32') }}}; + {{{ makeSetValue('p', '0', 'result.name | 0', 'i32') }}}; } else if (result instanceof WebGLRenderbuffer) { - {{{ makeSetValue('p', '0', 'GL.scan(GL.renderbuffers, result)', 'i32') }}}; + {{{ makeSetValue('p', '0', 'result.name | 0', 'i32') }}}; } else if (result instanceof WebGLTexture) { - {{{ makeSetValue('p', '0', 'GL.scan(GL.textures, result)', 'i32') }}}; + {{{ makeSetValue('p', '0', 'result.name | 0', 'i32') }}}; } else { throw 'Unknown object returned from WebGL getParameter'; } @@ -445,15 +437,15 @@ var LibraryGL = { {{{ makeSetValue('p', 'i*4', 'result[i]', 'float') }}}; } } else if (result instanceof WebGLBuffer) { - {{{ makeSetValue('p', '0', 'GL.scan(GL.buffers, result)', 'float') }}}; + {{{ makeSetValue('p', '0', 'result.name | 0', 'float') }}}; } else if (result instanceof WebGLProgram) { - {{{ makeSetValue('p', '0', 'GL.scan(GL.programs, result)', 'float') }}}; + {{{ makeSetValue('p', '0', 'result.name | 0', 'float') }}}; } else if (result instanceof WebGLFramebuffer) { - {{{ makeSetValue('p', '0', 'GL.scan(GL.framebuffers, result)', 'float') }}}; + {{{ makeSetValue('p', '0', 'result.name | 0', 'float') }}}; } else if (result instanceof WebGLRenderbuffer) { - {{{ makeSetValue('p', '0', 'GL.scan(GL.renderbuffers, result)', 'float') }}}; + {{{ makeSetValue('p', '0', 'result.name | 0', 'float') }}}; } else if (result instanceof WebGLTexture) { - {{{ makeSetValue('p', '0', 'GL.scan(GL.textures, result)', 'float') }}}; + {{{ makeSetValue('p', '0', 'result.name | 0', 'float') }}}; } else { throw 'Unknown object returned from WebGL getParameter'; } @@ -508,7 +500,9 @@ var LibraryGL = { glGenTextures: function(n, textures) { for (var i = 0; i < n; i++) { var id = GL.getNewId(GL.textures); - GL.textures[id] = Module.ctx.createTexture(); + var texture = Module.ctx.createTexture(); + texture.name = id; + GL.textures[id] = texture; {{{ makeSetValue('textures', 'i*4', 'id', 'i32') }}}; } }, @@ -517,7 +511,9 @@ var LibraryGL = { glDeleteTextures: function(n, textures) { for (var i = 0; i < n; i++) { var id = {{{ makeGetValue('textures', 'i*4', 'i32') }}}; - Module.ctx.deleteTexture(GL.textures[id]); + var texture = GL.textures[id]; + Module.ctx.deleteTexture(texture); + texture.name = 0; GL.textures[id] = null; } }, @@ -622,7 +618,9 @@ var LibraryGL = { glGenBuffers: function(n, buffers) { for (var i = 0; i < n; i++) { var id = GL.getNewId(GL.buffers); - GL.buffers[id] = Module.ctx.createBuffer(); + var buffer = Module.ctx.createBuffer(); + buffer.name = id; + GL.buffers[id] = buffer; {{{ makeSetValue('buffers', 'i*4', 'id', 'i32') }}}; } }, @@ -631,7 +629,9 @@ var LibraryGL = { glDeleteBuffers: function(n, buffers) { for (var i = 0; i < n; i++) { var id = {{{ makeGetValue('buffers', 'i*4', 'i32') }}}; - Module.ctx.deleteBuffer(GL.buffers[id]); + var buffer = GL.buffers[id]; + Module.ctx.deleteBuffer(buffer); + buffer.name = 0; GL.buffers[id] = null; if (id == GL.currArrayBuffer) GL.currArrayBuffer = 0; @@ -665,7 +665,9 @@ var LibraryGL = { glGenRenderbuffers: function(n, renderbuffers) { for (var i = 0; i < n; i++) { var id = GL.getNewId(GL.renderbuffers); - GL.renderbuffers[id] = Module.ctx.createRenderbuffer(); + var renderbuffer = Module.ctx.createRenderbuffer(); + renderbuffer.name = id; + GL.renderbuffers[id] = renderbuffer; {{{ makeSetValue('renderbuffers', 'i*4', 'id', 'i32') }}}; } }, @@ -674,8 +676,10 @@ var LibraryGL = { glDeleteRenderbuffers: function(n, renderbuffers) { for (var i = 0; i < n; i++) { var id = {{{ makeGetValue('renderbuffers', 'i*4', 'i32') }}}; - Module.ctx.deleteRenderbuffer(GL.renderbuffers[id]); - GL.renderbuffers[id]; + var renderbuffer = GL.renderbuffers[id]; + Module.ctx.deleteRenderbuffer(renderbuffer); + renderbuffer.name = 0; + GL.renderbuffers[id] = null; } }, @@ -1139,13 +1143,17 @@ var LibraryGL = { glCreateProgram__sig: 'i', glCreateProgram: function() { var id = GL.getNewId(GL.programs); - GL.programs[id] = Module.ctx.createProgram(); + var program = Module.ctx.createProgram(); + program.name = id; + GL.programs[id] = program; return id; }, glDeleteProgram__sig: 'vi', glDeleteProgram: function(program) { - Module.ctx.deleteProgram(GL.programs[program]); + var program = GL.programs[program]; + Module.ctx.deleteProgram(program); + program.name = 0; GL.programs[program] = null; GL.uniformTable[program] = null; }, @@ -1221,7 +1229,9 @@ var LibraryGL = { glGenFramebuffers: function(n, ids) { for (var i = 0; i < n; ++i) { var id = GL.getNewId(GL.framebuffers); - GL.framebuffers[id] = Module.ctx.createFramebuffer(); + var framebuffer = Module.ctx.createFramebuffer(); + framebuffer.name = id; + GL.framebuffers[id] = framebuffer; {{{ makeSetValue('ids', 'i*4', 'id', 'i32') }}}; } }, @@ -1230,7 +1240,9 @@ var LibraryGL = { glDeleteFramebuffers: function(n, framebuffers) { for (var i = 0; i < n; ++i) { var id = {{{ makeGetValue('framebuffers', 'i*4', 'i32') }}}; - Module.ctx.deleteFramebuffer(GL.framebuffers[id]); + var framebuffer = GL.framebuffers[id]; + Module.ctx.deleteFramebuffer(framebuffer); + framebuffer.name = 0; GL.framebuffers[id] = null; } }, diff --git a/src/library_sdl.js b/src/library_sdl.js index af71da26..b7d73862 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -21,6 +21,8 @@ var LibrarySDL = { version: null, surfaces: {}, + // A pool of freed canvas elements. Reusing them avoids GC pauses. + canvasPool: [], events: [], fonts: [null], @@ -246,7 +248,7 @@ var LibrarySDL = { }, translateRGBAToCSSRGBA: function(r, g, b, a) { - return 'rgba(' + r + ',' + g + ',' + b + ',' + (a/255) + ')'; + return 'rgba(' + (r&0xff) + ',' + (g&0xff) + ',' + (b&0xff) + ',' + (a&0xff)/255 + ')'; }, translateRGBAToColor: function(r, g, b, a) { @@ -288,7 +290,11 @@ var LibrarySDL = { SDL.GL = SDL.GL || useWebGL; var canvas; if (!usePageCanvas) { - canvas = document.createElement('canvas'); + if (SDL.canvasPool.length > 0) { + canvas = SDL.canvasPool.pop(); + } else { + canvas = document.createElement('canvas'); + } canvas.width = width; canvas.height = height; } else { @@ -355,8 +361,10 @@ var LibrarySDL = { }, freeSurface: function(surf) { - _free(SDL.surfaces[surf].buffer); - _free(SDL.surfaces[surf].pixelFormat); + var info = SDL.surfaces[surf]; + if (!info.usePageCanvas && info.canvas) SDL.canvasPool.push(info.canvas); + _free(info.buffer); + _free(info.pixelFormat); _free(surf); SDL.surfaces[surf] = null; }, @@ -1062,6 +1070,7 @@ var LibrarySDL = { surfData.ctx.fillStyle = SDL.translateColorToCSSRGBA(color); surfData.ctx.fillRect(r.x, r.y, r.w, r.h); surfData.ctx.restore(); + return 0; }, SDL_BlitSurface__deps: ['SDL_UpperBlit'], @@ -1071,11 +1080,19 @@ var LibrarySDL = { zoomSurface: function(src, x, y, smooth) { var srcData = SDL.surfaces[src]; - var w = srcData.width*x; - var h = srcData.height*y; - var ret = SDL.makeSurface(w, h, srcData.flags, false, 'zoomSurface'); + var w = srcData.width * x; + var h = srcData.height * y; + var ret = SDL.makeSurface(Math.abs(w), Math.abs(h), srcData.flags, false, 'zoomSurface'); var dstData = SDL.surfaces[ret]; - dstData.ctx.drawImage(srcData.canvas, 0, 0, w, h); + if (x >= 0 && y >= 0) dstData.ctx.drawImage(srcData.canvas, 0, 0, w, h); + else { + dstData.ctx.save(); + dstData.ctx.scale(x < 0 ? -1 : 1, y < 0 ? -1 : 1); + dstData.ctx.drawImage(srcData.canvas, w < 0 ? w : 0, h < 0 ? h : 0, Math.abs(w), Math.abs(h)); + // XXX I think this should work according to the spec, but currently + // fails on FF: dstData.ctx.drawImage(srcData.canvas, 0, 0, w, h); + dstData.ctx.restore(); + } return ret; }, @@ -1096,6 +1113,14 @@ var LibrarySDL = { SDL.surfaces[surf].alpha = alpha; }, + SDL_SetColorKey: function(surf, flag, key) { + // SetColorKey assigns one color to be rendered as transparent. I don't + // think the canvas API allows for anything like this, and iterating through + // each pixel to replace that color seems prohibitively expensive. + Runtime.warnOnce('SDL_SetColorKey is a no-op for performance reasons'); + return 0; + }, + SDL_GetTicks: function() { return Math.floor(Date.now() - SDL.startTime); }, @@ -1512,15 +1537,20 @@ var LibrarySDL = { }, Mix_HaltChannel: function(channel) { - var info = SDL.channels[channel]; - if (info.audio) { - info.audio.pause(); - info.audio = null; - } else { - Module.printErr('No Audio for channel: ' + channel); + function halt(channel) { + var info = SDL.channels[channel]; + if (info.audio) { + info.audio.pause(); + info.audio = null; + } + if (SDL.channelFinished) { + Runtime.getFuncWrapper(SDL.channelFinished, 'vi')(channel); + } } - if (SDL.channelFinished) { - Runtime.getFuncWrapper(SDL.channelFinished, 'vi')(channel); + if (channel != -1) { + halt(channel); + } else { + for (var i = 0; i < SDL.channels.length; ++i) halt(i); } return 0; }, @@ -1707,6 +1737,7 @@ var LibrarySDL = { }, TTF_RenderText_Blended: 'TTF_RenderText_Solid', // XXX ignore blending vs. solid TTF_RenderText_Shaded: 'TTF_RenderText_Solid', // XXX ignore blending vs. solid + TTF_RenderUTF8_Solid: 'TTF_RenderText_Solid', TTF_SizeText: function(font, text, w, h) { var fontData = SDL.fonts[font]; @@ -1731,35 +1762,114 @@ var LibrarySDL = { // SDL gfx + $SDL_gfx: { + drawRectangle: function(surf, x1, y1, x2, y2, action, cssColor) { + x1 = x1 << 16 >> 16; + y1 = y1 << 16 >> 16; + x2 = x2 << 16 >> 16; + y2 = y2 << 16 >> 16; + var surfData = SDL.surfaces[surf]; + assert(!surfData.locked); // but we could unlock and re-lock if we must.. + // TODO: if ctx does not change, leave as is, and also do not re-set xStyle etc. + var x = x1 < x2 ? x1 : x2; + var y = y1 < y2 ? y1 : y2; + var w = Math.abs(x2 - x1); + var h = Math.abs(y2 - y1); + surfData.ctx.save(); + surfData.ctx[action + 'Style'] = cssColor; + surfData.ctx[action + 'Rect'](x, y, w, h); + surfData.ctx.restore(); + }, + drawLine: function(surf, x1, y1, x2, y2, cssColor) { + x1 = x1 << 16 >> 16; + y1 = y1 << 16 >> 16; + x2 = x2 << 16 >> 16; + y2 = y2 << 16 >> 16; + var surfData = SDL.surfaces[surf]; + assert(!surfData.locked); // but we could unlock and re-lock if we must.. + surfData.ctx.save(); + surfData.ctx.strokeStyle = cssColor; + surfData.ctx.beginPath(); + surfData.ctx.moveTo(x1, y1); + surfData.ctx.lineTo(x2, y2); + surfData.ctx.stroke(); + surfData.ctx.restore(); + }, + // See http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas + drawEllipse: function(surf, x, y, rx, ry, action, cssColor) { + x = x << 16 >> 16; + y = y << 16 >> 16; + rx = rx << 16 >> 16; + ry = ry << 16 >> 16; + var surfData = SDL.surfaces[surf]; + assert(!surfData.locked); // but we could unlock and re-lock if we must.. + + surfData.ctx.save(); + surfData.ctx.beginPath(); + surfData.ctx.translate(x, y); + surfData.ctx.scale(rx, ry); + surfData.ctx.arc(0, 0, 1, 0, 2 * Math.PI); + surfData.ctx.restore(); + + surfData.ctx.save(); + surfData.ctx[action + 'Style'] = cssColor; + surfData.ctx[action](); + surfData.ctx.restore(); + }, + // the gfx library uses something different from the rest of SDL... + translateColorToCSSRGBA: function(rgba) { + return 'rgba(' + (rgba>>>24) + ',' + (rgba>>16 & 0xff) + ',' + (rgba>>8 & 0xff) + ',' + (rgba&0xff) + ')'; + } + }, + + boxColor__deps: ['$SDL_gfx'], + boxColor: function(surf, x1, y1, x2, y2, color) { + return SDL_gfx.drawRectangle(surf, x1, y1, x2, y2, 'fill', SDL_gfx.translateColorToCSSRGBA(color)); + }, + + boxRGBA__deps: ['$SDL_gfx'], boxRGBA: function(surf, x1, y1, x2, y2, r, g, b, a) { - var surfData = SDL.surfaces[surf]; - assert(!surfData.locked); // but we could unlock and re-lock if we must.. - // TODO: if ctx does not change, leave as is, and also do not re-set xStyle etc. - surfData.ctx.save(); - surfData.ctx.fillStyle = SDL.translateRGBAToCSSRGBA(r, g, b, a); - surfData.ctx.fillRect(x1, y1, x2-x1, y2-y1); - surfData.ctx.restore(); + return SDL_gfx.drawRectangle(surf, x1, y1, x2, y2, 'fill', SDL.translateRGBAToCSSRGBA(r, g, b, a)); }, + rectangleColor__deps: ['$SDL_gfx'], + rectangleColor: function(surf, x1, y1, x2, y2, color) { + return SDL_gfx.drawRectangle(surf, x1, y1, x2, y2, 'stroke', SDL_gfx.translateColorToCSSRGBA(color)); + }, + + rectangleRGBA__deps: ['$SDL_gfx'], rectangleRGBA: function(surf, x1, y1, x2, y2, r, g, b, a) { - var surfData = SDL.surfaces[surf]; - assert(!surfData.locked); // but we could unlock and re-lock if we must.. - surfData.ctx.save(); - surfData.ctx.strokeStyle = SDL.translateRGBAToCSSRGBA(r, g, b, a); - surfData.ctx.strokeRect(x1, y1, x2-x1, y2-y1); - surfData.ctx.restore(); + return SDL_gfx.drawRectangle(surf, x1, y1, x2, y2, 'stroke', SDL.translateRGBAToCSSRGBA(r, g, b, a)); + }, + + ellipseColor__deps: ['$SDL_gfx'], + ellipseColor: function(surf, x, y, rx, ry, color) { + return SDL_gfx.drawEllipse(surf, x, y, rx, ry, 'stroke', SDL_gfx.translateColorToCSSRGBA(color)); + }, + + ellipseRGBA__deps: ['$SDL_gfx'], + ellipseRGBA: function(surf, x, y, rx, ry, r, g, b, a) { + return SDL_gfx.drawEllipse(surf, x, y, rx, ry, 'stroke', SDL.translateRGBAToCSSRGBA(r, g, b, a)); + }, + + filledEllipseColor__deps: ['$SDL_gfx'], + filledEllipseColor: function(surf, x, y, rx, ry, color) { + return SDL_gfx.drawEllipse(surf, x, y, rx, ry, 'fill', SDL_gfx.translateColorToCSSRGBA(color)); + }, + + filledEllipseRGBA__deps: ['$SDL_gfx'], + filledEllipseRGBA: function(surf, x, y, rx, ry, r, g, b, a) { + return SDL_gfx.drawEllipse(surf, x, y, rx, ry, 'fill', SDL.translateRGBAToCSSRGBA(r, g, b, a)); }, + lineColor__deps: ['$SDL_gfx'], + lineColor: function(surf, x1, y1, x2, y2, color) { + return SDL_gfx.drawLine(surf, x1, y1, x2, y2, SDL_gfx.translateColorToCSSRGBA(color)); + }, + + lineRGBA__deps: ['$SDL_gfx'], lineRGBA: function(surf, x1, y1, x2, y2, r, g, b, a) { - var surfData = SDL.surfaces[surf]; - assert(!surfData.locked); // but we could unlock and re-lock if we must.. - surfData.ctx.save(); - surfData.ctx.strokeStyle = SDL.translateRGBAToCSSRGBA(r, g, b, a); - surfData.ctx.beginPath(); - surfData.ctx.moveTo(x1, y1); - surfData.ctx.lineTo(x2, y2); - surfData.ctx.stroke(); - surfData.ctx.restore(); + return SDL_gfx.drawLine(surf, x1, y1, x2, y2, SDL.translateRGBAToCSSRGBA(r, g, b, a)); }, pixelRGBA__deps: ['boxRGBA'], @@ -1845,12 +1955,18 @@ var LibrarySDL = { return -1; }, + // Joysticks + + SDL_NumJoysticks: function() { return 0 }, + + SDL_JoystickOpen: function(deviceIndex) { return 0 }, + + SDL_JoystickGetButton: function(joystick, button) { return 0 }, + // Misc SDL_InitSubSystem: function(flags) { return 0 }, - SDL_NumJoysticks: function() { return 0 }, - SDL_RWFromFile: function(filename, mode) { return filename; // XXX We just forward the filename }, diff --git a/system/include/SDL/SDL_keycode.h b/system/include/SDL/SDL_keycode.h index 472ca28e..84063b8b 100644 --- a/system/include/SDL/SDL_keycode.h +++ b/system/include/SDL/SDL_keycode.h @@ -310,7 +310,8 @@ enum SDLK_KBDILLUMDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMDOWN), SDLK_KBDILLUMUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMUP), SDLK_EJECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EJECT), - SDLK_SLEEP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SLEEP) + SDLK_SLEEP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SLEEP), + SDLK_LAST = SDL_SCANCODE_TO_KEYCODE(SDL_NUM_SCANCODES) }; /** diff --git a/tests/runner.py b/tests/runner.py index 2cda8d8f..96b00c50 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -7012,49 +7012,8 @@ def process(filename): self.do_run(src, re.sub('(^|\n)\s+', '\\1', expected)) def test_utime(self): - add_pre_run_and_checks = ''' -def process(filename): - src = open(filename, 'r').read().replace( - '// {{PRE_RUN_ADDITIONS}}', - \'\'\' - var TEST_F1 = FS.createFolder('/', 'writeable', true, true); - var TEST_F2 = FS.createFolder('/', 'unwriteable', true, false); - \'\'\' - ).replace( - '// {{POST_RUN_ADDITIONS}}', - \'\'\' - Module.print('first changed: ' + (TEST_F1.timestamp == 1200000000000)); - Module.print('second changed: ' + (TEST_F2.timestamp == 1200000000000)); - \'\'\' - ) - open(filename, 'w').write(src) -''' - src = r''' - #include <stdio.h> - #include <errno.h> - #include <utime.h> - - int main() { - struct utimbuf t = {1000000000, 1200000000}; - char* writeable = "/writeable"; - char* unwriteable = "/unwriteable"; - - utime(writeable, &t); - printf("writeable errno: %d\n", errno); - - utime(unwriteable, &t); - printf("unwriteable errno: %d\n", errno); - - return 0; - } - ''' - expected = ''' - writeable errno: 0 - unwriteable errno: 1 - first changed: true - second changed: false - ''' - self.do_run(src, re.sub('(^|\n)\s+', '\\1', expected), post_build=add_pre_run_and_checks) + src = open(path_from_root('tests', 'utime', 'test_utime.c'), 'r').read() + self.do_run(src, 'success', force_c=True) def test_utf(self): self.banned_js_engines = [SPIDERMONKEY_ENGINE] # only node handles utf well @@ -13076,8 +13035,11 @@ Press any key to continue.''' self.btest('sdl_maprgba.c', reference='sdl_maprgba.png', reference_slack=3) def test_sdl_rotozoom(self): - shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'example.png')) - self.btest('sdl_rotozoom.c', reference='sdl_rotozoom.png', args=['--preload-file', 'example.png']) + shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) + self.btest('sdl_rotozoom.c', reference='sdl_rotozoom.png', args=['--preload-file', 'screenshot.png'], reference_slack=3) + + def test_sdl_gfx_primitives(self): + self.btest('sdl_gfx_primitives.c', reference='sdl_gfx_primitives.png', reference_slack=1) def test_sdl_canvas_palette_2(self): open(os.path.join(self.get_dir(), 'pre.js'), 'w').write(''' diff --git a/tests/sdl_gfx_primitives.c b/tests/sdl_gfx_primitives.c new file mode 100644 index 00000000..db0c6181 --- /dev/null +++ b/tests/sdl_gfx_primitives.c @@ -0,0 +1,46 @@ +#include "SDL/SDL.h" +#include "SDL/SDL_gfxPrimitives.h" + +#ifdef EMSCRIPTEN +#include "emscripten.h" +#endif + +int main(int argc, char **argv) { + SDL_Init(SDL_INIT_VIDEO); + + const int width = 400; + const int height = 400; + SDL_Surface *screen = SDL_SetVideoMode(width, height, 32, SDL_SWSURFACE); + boxColor(screen, 0, 0, width, height, 0xff); + + boxColor(screen, 0, 0, 98, 98, 0xff0000ff); + boxRGBA(screen, 100, 0, 198, 98, 0, 0, 0xff, 0xff); + // check that the x2 > x1 case is handled correctly + boxColor(screen, 298, 98, 200, 0, 0x00ff00ff); + boxColor(screen, 398, 98, 300, 0, 0xff0000ff); + + rectangleColor(screen, 0, 100, 98, 198, 0x000ffff); + rectangleRGBA(screen, 100, 100, 198, 198, 0xff, 0, 0, 0xff); + + ellipseColor(screen, 300, 150, 99, 49, 0x00ff00ff); + filledEllipseColor(screen, 100, 250, 99, 49, 0x00ff00ff); + filledEllipseRGBA(screen, 250, 300, 49, 99, 0, 0, 0xff, 0xff); + + lineColor(screen, 300, 200, 400, 300, 0x00ff00ff); + lineRGBA(screen, 300, 300, 400, 400, 0, 0xff, 0, 0xff); + + SDL_UpdateRect(screen, 0, 0, 0, 0); + +#ifndef EMSCRIPTEN + SDL_Event evt; + SDL_SaveBMP(screen, "native_output.bmp"); + while (1) { + if (SDL_PollEvent(&evt) != 0 && evt.type == SDL_QUIT) break; + SDL_Delay(33); + } +#endif + + SDL_Quit(); + + return 1; +} diff --git a/tests/sdl_gfx_primitives.png b/tests/sdl_gfx_primitives.png Binary files differnew file mode 100644 index 00000000..525b4f8f --- /dev/null +++ b/tests/sdl_gfx_primitives.png diff --git a/tests/sdl_rotozoom.c b/tests/sdl_rotozoom.c index b3970f6c..e81258d9 100644 --- a/tests/sdl_rotozoom.c +++ b/tests/sdl_rotozoom.c @@ -6,15 +6,18 @@ #include "emscripten.h" #endif +const int numSprites = 8; SDL_Surface *screen; -SDL_Surface *sprite[6]; +SDL_Surface *sprite[numSprites]; void mainloop() { int i; + int row = 0; SDL_Rect rect = { 0, 0, 100, 100 }; - for (i = 0; i < 6; i++) { + for (i = 0; i < numSprites; i++) { rect.x = i & 1 ? 200 : 0; - rect.y = i & 2 ? 200 : 0; + rect.y = row * 200; + row += i & 1; SDL_BlitSurface(sprite[i], 0, screen, &rect); SDL_UpdateRect(screen, 0, 0, 0, 0); } @@ -23,20 +26,27 @@ void mainloop() { int main(int argc, char **argv) { SDL_Init(SDL_INIT_VIDEO); - screen = SDL_SetVideoMode(400, 400, 32, SDL_SWSURFACE); + const int width = 400; + const int height = 200 * (numSprites + 1) / 2; + screen = SDL_SetVideoMode(width, height, 32, SDL_SWSURFACE); + SDL_Rect rect = { 0, 0, width, height }; + SDL_FillRect(screen, &rect, SDL_MapRGBA(screen->format, 0, 0, 0, 0xff)); - sprite[0] = IMG_Load("example.png"); + sprite[0] = IMG_Load("screenshot.png"); sprite[1] = SDL_CreateRGBSurface(SDL_SWSURFACE, 100, 100, 32, 0xFF000000, 0xFF0000, 0xFF00, 0xFF); SDL_FillRect(sprite[1], 0, 0xA0A0A0A0); sprite[2] = zoomSurface(sprite[0], 0.5, 0.5, SMOOTHING_ON); sprite[3] = zoomSurface(sprite[1], 0.5, 0.5, SMOOTHING_ON); sprite[4] = rotozoomSurface(sprite[0], -20, 0.3, SMOOTHING_ON); sprite[5] = rotozoomSurface(sprite[1], 45, 0.5, SMOOTHING_ON); + sprite[6] = zoomSurface(sprite[0], -0.5, 0.5, SMOOTHING_ON); + sprite[7] = zoomSurface(sprite[0], -0.5, -0.5, SMOOTHING_ON); mainloop(); #ifndef EMSCRIPTEN SDL_Event evt; + SDL_SaveBMP(screen, "native_output.bmp"); while (1) { if (SDL_PollEvent(&evt) != 0 && evt.type == SDL_QUIT) break; //mainloop(); diff --git a/tests/sdl_rotozoom.png b/tests/sdl_rotozoom.png Binary files differindex 3ca8da70..5c5dec2f 100644 --- a/tests/sdl_rotozoom.png +++ b/tests/sdl_rotozoom.png diff --git a/tests/utime/test_utime.c b/tests/utime/test_utime.c new file mode 100644 index 00000000..1793f4a5 --- /dev/null +++ b/tests/utime/test_utime.c @@ -0,0 +1,53 @@ +#include <assert.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <utime.h> +#include <sys/stat.h> + +void setup() { + mkdir("writeable", 0777); + mkdir("unwriteable", 0111); +} + +void cleanup() { + rmdir("writeable"); + rmdir("unwriteable"); +} + +void test() { + struct stat s; + // currently, the most recent timestamp is shared for atime, + // ctime and mtime. using unique values for each in the test + // will fail + struct utimbuf t = {1000000000, 1000000000}; + + utime("writeable", &t); + assert(!errno); + memset(&s, 0, sizeof s); + stat("writeable", &s); + assert(s.st_atime == t.actime); + assert(s.st_mtime == t.modtime); + + // write permissions aren't checked when setting node + // attributes unless the user uid isn't the owner (so + // therefor, this should work fine) + utime("unwriteable", &t); + assert(!errno); + memset(&s, 0, sizeof s); + stat("unwriteable", &s); + assert(s.st_atime == t.actime); + assert(s.st_mtime == t.modtime); + + puts("success"); +} + +int main() { + atexit(cleanup); + signal(SIGABRT, cleanup); + setup(); + test(); + return EXIT_SUCCESS; +}
\ No newline at end of file |