diff options
-rw-r--r-- | src/compiler.js | 2 | ||||
-rw-r--r-- | src/jsifier.js | 17 | ||||
-rw-r--r-- | src/library_browser.js | 50 | ||||
-rw-r--r-- | src/library_sdl.js | 54 | ||||
-rw-r--r-- | tests/runner.py | 2 |
5 files changed, 96 insertions, 29 deletions
diff --git a/src/compiler.js b/src/compiler.js index fc9ae7fc..699b0393 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -71,7 +71,7 @@ do { var inter = intertyper(lines); // Load library, with preprocessing and macros. Must be done after intertyper, so we know if we have debug info or not -for (suffix in set('', '_sdl', '_gl')) { +for (suffix in set('', '_sdl', '_gl', '_browser')) { eval(processMacros(preprocess(read('library' + suffix + '.js'), CONSTANTS))); } diff --git a/src/jsifier.js b/src/jsifier.js index 7c5c5f4f..0a590163 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -215,14 +215,17 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) { } else if (typeof snippet === 'object') { // JSON.stringify removes functions, so we need to make sure they are added var funcs = []; + var hasNonFunc = false; for (var x in snippet) { if (typeof snippet[x] === 'function') { funcs.push(x + ': ' + snippet[x].toString()); + } else { + hasNonFunc = true; } } snippet = JSON.stringify(snippet); if (funcs.length > 0) { - snippet = snippet.replace(/}$/, ', ' + funcs.join(', ') + ' }'); + snippet = snippet.replace(/}$/, (hasNonFunc ? ', ' : '') + funcs.join(', ') + ' }'); } } else if (typeof snippet === 'function') { snippet = snippet.toString(); @@ -241,11 +244,17 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) { }); } - var deps = Library[ident + '__deps']; + var deps = Library[ident + '__deps'] || []; if (redirectedIdent) { - deps = (deps || []).concat(Library[redirectedIdent + '__deps']); + deps = deps.concat(Library[redirectedIdent + '__deps'] || []); } - return 'var _' + ident + '=' + snippet + (deps ? '\n' + deps.map(addFromLibrary).join('\n') : ''); + // $ident's are special, we do not prefix them with a '_'. + if (ident[0] === '$') { + ident = ident.substr(1); + } else { + ident = '_' + ident; + } + return 'var ' + ident + '=' + snippet + (deps ? '\n' + deps.map(addFromLibrary).join('\n') : ''); } item.JS = addFromLibrary(shortident); } else { diff --git a/src/library_browser.js b/src/library_browser.js new file mode 100644 index 00000000..ccc13698 --- /dev/null +++ b/src/library_browser.js @@ -0,0 +1,50 @@ +// Utilities for browser environments + +mergeInto(Library, { + $Browser: { + syncLoad: function(url) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", url, false); + xhr.send(null); + var buffer = xhr.mozResponseArrayBuffer; + return new Uint8Array(buffer); + }, + + // Given binary data for an image, in a format like PNG or JPG, we convert it + // to flat pixel data. We do so using the browser's native code. + decodeImage: function(pixels, format) { + function encodeBase64(data) { + var BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + var PAD = '='; + var ret = ''; + var leftchar = 0; + var leftbits = 0; + for (var i = 0; i < data.length; i++) { + leftchar = (leftchar << 8) | data[i]; + leftbits += 8; + while (leftbits >= 6) { + var curr = (leftchar >> (leftbits-6)) & 0x3f; + leftbits -= 6; + ret += BASE[curr]; + } + } + if (leftbits == 2) { + ret += BASE[(leftchar&3) << 4]; + ret += PAD + PAD; + } else if (leftbits == 4) { + ret += BASE[(leftchar&0xf) << 2]; + ret += PAD; + } + return ret; + } + var img = new Image(); + var canvas = document.createElement('canvas'); + img.src = 'data:image/' + format + ';base64,' + encodeBase64(pixels); + var ctx = canvas.getContext('2d'); + ctx.drawImage(Module.img, 0, 0); + var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + return imageData; + }, + } +}); + diff --git a/src/library_sdl.js b/src/library_sdl.js index 629df786..0dda52ef 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -2,19 +2,8 @@ // Module.canvas and at least one of Module.context2D, Module.contextGL. mergeInto(Library, { - _SDL: { - // Given binary data for an image, in a format like PNG or JPG, we convert it - // to flat pixel data. - _decodeImage: function(image) { - var img = new Image(); - var canvas = document.createElement('canvas'); - img.src = imageToBase64(image); - var ctx = canvas.getContext('2d'); - ctx.drawImage(Module.img,0,0); - var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); - return imageData; - }, - + $SDL__deps: ['$Browser'], + $SDL: { defaults: { width: 320, height: 240 @@ -22,21 +11,28 @@ mergeInto(Library, { surfaces: {}, - makeSurface: function(width, height, depth, flags) { - var surf = _malloc(14*QUANTUM_SIZE); // SDL_Surface has 14 fields of quantum size - __SDL.surfaces[surf] = { + makeSurface: function(width, height, flags) { + var surf = _malloc(14*QUANTUM_SIZE); // SDL_Surface has 14 fields of quantum size + var buffer = _malloc(width*height*4); + IHEAP[surf+QUANTUM_SIZE*0] = flags; // SDL_Surface.flags + IHEAP[surf+QUANTUM_SIZE*1] = 0; // SDL_Surface.format TODO + IHEAP[surf+QUANTUM_SIZE*2] = width; // SDL_Surface.w + IHEAP[surf+QUANTUM_SIZE*3] = height; // SDL_Surface.h + IHEAP[surf+QUANTUM_SIZE*4] = width*4; // SDL_Surface.pitch, assuming RGBA for now, since that is what ImageData gives us in browsers + IHEAP[surf+QUANTUM_SIZE*5] = buffer; // SDL_Surface.pixels + SDL.surfaces[surf] = { width: width, height: height, canvas: Module.canvas, context: Module.context2D, surf: surf, - buffer: _malloc(width*height*4) + buffer: buffer }; return surf; }, }, - SDL_Init__deps: ['_SDL'], + SDL_Init__deps: ['$SDL'], SDL_Init: function(what) { return 0; // success }, @@ -48,8 +44,8 @@ mergeInto(Library, { IHEAP[ret] = 0; // TODO IHEAP[ret+QUANTUM_SIZE] = 0; // TODO IHEAP[ret+QUANTUM_SIZE*2] = 0; // TODO - IHEAP[ret+QUANTUM_SIZE*3] = __SDL.defaults.width; - IHEAP[ret+QUANTUM_SIZE*4] = __SDL.defaults.height; + IHEAP[ret+QUANTUM_SIZE*3] = SDL.defaults.width; + IHEAP[ret+QUANTUM_SIZE*4] = SDL.defaults.height; return ret; }, @@ -62,7 +58,7 @@ mergeInto(Library, { }, SDL_SetVideoMode: function(width, height, depth, flags) { - return __SDL.makeSurface(width, height, depth, flags); + return SDL.makeSurface(width, height, flags); }, SDL_Quit: function() { @@ -70,7 +66,7 @@ mergeInto(Library, { }, SDL_LockSurface: function(surf) { - var surfData = __SDL.surfaces[surf]; + var surfData = SDL.surfaces[surf]; surfData.image = surfData.context.getImageData(0, 0, surfData.width, surfData.height); // Copy pixel data to somewhere accessible to 'C/C++' var num = surfData.image.data.length; @@ -86,7 +82,7 @@ mergeInto(Library, { }, SDL_UnlockSurface: function(surf) { - var surfData = __SDL.surfaces[surf]; + var surfData = SDL.surfaces[surf]; // Copy pixel data to image var num = surfData.image.data.length; for (var i = 0; i < num; i++) { @@ -125,6 +121,18 @@ mergeInto(Library, { SDL_GetError: function() { return Pointer_make(intArrayFromString("SDL is cool"), null); + }, + + IMG_Load: function(filename) { + var format = filename.split('.').slice(-1)[0]; + var data = Browser.syncLoad(filename); + var raw = Browser.decodeImage(data, format); + var surf = SDL.makeSurface(raw.width, raw.height, 0); + // XXX Extremely inefficient! + for (var i = 0; i < raw.width*raw.height*4; i++) { + IHEAP[SDL.surfaces[surf].buffer+i] = raw.data[i]; + } + return surf; } }); diff --git a/tests/runner.py b/tests/runner.py index ea9b2f94..4ce0746d 100644 --- a/tests/runner.py +++ b/tests/runner.py @@ -1901,7 +1901,7 @@ if 'benchmark' not in sys.argv: src.write( ''' _STDIO.prepare('paper.pdf', eval(read('paper.pdf.js'))); - run(args); + run(); print("Data: " + JSON.stringify(_STDIO.streams[_STDIO.filenames['*s-0*d.']].data)); // work around __formatString__ fail ''' ) |