Index: bower_components/gif.js/src/gif.coffee |
diff --git a/bower_components/gif.js/src/gif.coffee b/bower_components/gif.js/src/gif.coffee |
deleted file mode 100644 |
index e87524d1f0e8d909f271e55a3b25f4c7bc437cad..0000000000000000000000000000000000000000 |
--- a/bower_components/gif.js/src/gif.coffee |
+++ /dev/null |
@@ -1,191 +0,0 @@ |
-{EventEmitter} = require 'events' |
-browser = require './browser.coffee' |
- |
-class GIF extends EventEmitter |
- |
- defaults = |
- workerScript: 'gif.worker.js' |
- workers: 2 |
- repeat: 0 # repeat forever, -1 = repeat once |
- background: '#fff' |
- quality: 10 # pixel sample interval, lower is better |
- width: null # size derermined from first frame if possible |
- height: null |
- transparent: null |
- |
- frameDefaults = |
- delay: 500 # ms |
- copy: false |
- |
- constructor: (options) -> |
- @running = false |
- |
- @options = {} |
- @frames = [] |
- |
- @freeWorkers = [] |
- @activeWorkers = [] |
- |
- @setOptions options |
- for key, value of defaults |
- @options[key] ?= value |
- |
- setOption: (key, value) -> |
- @options[key] = value |
- if @_canvas? and key in ['width', 'height'] |
- @_canvas[key] = value |
- |
- setOptions: (options) -> |
- @setOption key, value for own key, value of options |
- |
- addFrame: (image, options={}) -> |
- frame = {} |
- frame.transparent = @options.transparent |
- for key of frameDefaults |
- frame[key] = options[key] or frameDefaults[key] |
- |
- # use the images width and height for options unless already set |
- @setOption 'width', image.width unless @options.width? |
- @setOption 'height', image.height unless @options.height? |
- |
- if ImageData? and image instanceof ImageData |
- frame.data = image.data |
- else if (CanvasRenderingContext2D? and image instanceof CanvasRenderingContext2D) or (WebGLRenderingContext? and image instanceof WebGLRenderingContext) |
- if options.copy |
- frame.data = @getContextData image |
- else |
- frame.context = image |
- else if image.childNodes? |
- if options.copy |
- frame.data = @getImageData image |
- else |
- frame.image = image |
- else |
- throw new Error 'Invalid image' |
- |
- @frames.push frame |
- |
- render: -> |
- throw new Error 'Already running' if @running |
- |
- if not @options.width? or not @options.height? |
- throw new Error 'Width and height must be set prior to rendering' |
- |
- @running = true |
- @nextFrame = 0 |
- @finishedFrames = 0 |
- |
- @imageParts = (null for i in [0...@frames.length]) |
- numWorkers = @spawnWorkers() |
- @renderNextFrame() for i in [0...numWorkers] |
- |
- @emit 'start' |
- @emit 'progress', 0 |
- |
- abort: -> |
- loop |
- worker = @activeWorkers.shift() |
- break unless worker? |
- console.log "killing active worker" |
- worker.terminate() |
- @running = false |
- @emit 'abort' |
- |
- # private |
- |
- spawnWorkers: -> |
- numWorkers = Math.min(@options.workers, @frames.length) |
- [@freeWorkers.length...numWorkers].forEach (i) => |
- console.log "spawning worker #{ i }" |
- worker = new Worker @options.workerScript |
- worker.onmessage = (event) => |
- @activeWorkers.splice @activeWorkers.indexOf(worker), 1 |
- @freeWorkers.push worker |
- @frameFinished event.data |
- @freeWorkers.push worker |
- return numWorkers |
- |
- frameFinished: (frame) -> |
- console.log "frame #{ frame.index } finished - #{ @activeWorkers.length } active" |
- @finishedFrames++ |
- @emit 'progress', @finishedFrames / @frames.length |
- @imageParts[frame.index] = frame |
- if null in @imageParts |
- @renderNextFrame() |
- else |
- @finishRendering() |
- |
- finishRendering: -> |
- len = 0 |
- for frame in @imageParts |
- len += (frame.data.length - 1) * frame.pageSize + frame.cursor |
- len += frame.pageSize - frame.cursor |
- console.log "rendering finished - filesize #{ Math.round(len / 1000) }kb" |
- data = new Uint8Array len |
- offset = 0 |
- for frame in @imageParts |
- for page, i in frame.data |
- data.set page, offset |
- if i is frame.data.length - 1 |
- offset += frame.cursor |
- else |
- offset += frame.pageSize |
- |
- image = new Blob [data], |
- type: 'image/gif' |
- |
- @emit 'finished', image, data |
- |
- renderNextFrame: -> |
- throw new Error 'No free workers' if @freeWorkers.length is 0 |
- return if @nextFrame >= @frames.length # no new frame to render |
- |
- frame = @frames[@nextFrame++] |
- worker = @freeWorkers.shift() |
- task = @getTask frame |
- |
- console.log "starting frame #{ task.index + 1 } of #{ @frames.length }" |
- @activeWorkers.push worker |
- worker.postMessage task#, [task.data.buffer] |
- |
- getContextData: (ctx) -> |
- return ctx.getImageData(0, 0, @options.width, @options.height).data |
- |
- getImageData: (image) -> |
- if not @_canvas? |
- @_canvas = document.createElement 'canvas' |
- @_canvas.width = @options.width |
- @_canvas.height = @options.height |
- |
- ctx = @_canvas.getContext '2d' |
- ctx.setFill = @options.background |
- ctx.fillRect 0, 0, @options.width, @options.height |
- ctx.drawImage image, 0, 0 |
- |
- return @getContextData ctx |
- |
- getTask: (frame) -> |
- index = @frames.indexOf frame |
- task = |
- index: index |
- last: index is (@frames.length - 1) |
- delay: frame.delay |
- transparent: frame.transparent |
- width: @options.width |
- height: @options.height |
- quality: @options.quality |
- repeat: @options.repeat |
- canTransfer: (browser.name is 'chrome') |
- |
- if frame.data? |
- task.data = frame.data |
- else if frame.context? |
- task.data = @getContextData frame.context |
- else if frame.image? |
- task.data = @getImageData frame.image |
- else |
- throw new Error 'Invalid frame' |
- |
- return task |
- |
-module.exports = GIF |