[Service] Integrate DeviceHome and SignalingServer
[platform/framework/web/wrtjs.git] / device_home / node_modules / pngjs / lib / parser-async.js
1 'use strict';
2
3 var util = require('util');
4 var zlib = require('zlib');
5 var ChunkStream = require('./chunkstream');
6 var FilterAsync = require('./filter-parse-async');
7 var Parser = require('./parser');
8 var bitmapper = require('./bitmapper');
9 var formatNormaliser = require('./format-normaliser');
10
11 var ParserAsync = module.exports = function(options) {
12   ChunkStream.call(this);
13
14   this._parser = new Parser(options, {
15     read: this.read.bind(this),
16     error: this._handleError.bind(this),
17     metadata: this._handleMetaData.bind(this),
18     gamma: this.emit.bind(this, 'gamma'),
19     palette: this._handlePalette.bind(this),
20     transColor: this._handleTransColor.bind(this),
21     finished: this._finished.bind(this),
22     inflateData: this._inflateData.bind(this),
23     simpleTransparency: this._simpleTransparency.bind(this),
24     headersFinished: this._headersFinished.bind(this)
25   });
26   this._options = options;
27   this.writable = true;
28
29   this._parser.start();
30 };
31 util.inherits(ParserAsync, ChunkStream);
32
33
34 ParserAsync.prototype._handleError = function(err) {
35
36   this.emit('error', err);
37
38   this.writable = false;
39
40   this.destroy();
41
42   if (this._inflate && this._inflate.destroy) {
43     this._inflate.destroy();
44   }
45
46   if (this._filter) {
47     this._filter.destroy();
48     // For backward compatibility with Node 7 and below.
49     // Suppress errors due to _inflate calling write() even after
50     // it's destroy()'ed.
51     this._filter.on('error', function() {});
52   }
53
54   this.errord = true;
55 };
56
57 ParserAsync.prototype._inflateData = function(data) {
58   if (!this._inflate) {
59     if (this._bitmapInfo.interlace) {
60       this._inflate = zlib.createInflate();
61
62       this._inflate.on('error', this.emit.bind(this, 'error'));
63       this._filter.on('complete', this._complete.bind(this));
64
65       this._inflate.pipe(this._filter);
66     }
67     else {
68       var rowSize = ((this._bitmapInfo.width * this._bitmapInfo.bpp * this._bitmapInfo.depth + 7) >> 3) + 1;
69       var imageSize = rowSize * this._bitmapInfo.height;
70       var chunkSize = Math.max(imageSize, zlib.Z_MIN_CHUNK);
71
72       this._inflate = zlib.createInflate({ chunkSize: chunkSize });
73       var leftToInflate = imageSize;
74
75       var emitError = this.emit.bind(this, 'error');
76       this._inflate.on('error', function(err) {
77         if (!leftToInflate) {
78           return;
79         }
80
81         emitError(err);
82       });
83       this._filter.on('complete', this._complete.bind(this));
84
85       var filterWrite = this._filter.write.bind(this._filter);
86       this._inflate.on('data', function(chunk) {
87         if (!leftToInflate) {
88           return;
89         }
90
91         if (chunk.length > leftToInflate) {
92           chunk = chunk.slice(0, leftToInflate);
93         }
94
95         leftToInflate -= chunk.length;
96
97         filterWrite(chunk);
98       });
99
100       this._inflate.on('end', this._filter.end.bind(this._filter));
101     }
102   }
103   this._inflate.write(data);
104 };
105
106 ParserAsync.prototype._handleMetaData = function(metaData) {
107   this._metaData = metaData;
108   this._bitmapInfo = Object.create(metaData);
109
110   this._filter = new FilterAsync(this._bitmapInfo);
111 };
112
113 ParserAsync.prototype._handleTransColor = function(transColor) {
114   this._bitmapInfo.transColor = transColor;
115 };
116
117 ParserAsync.prototype._handlePalette = function(palette) {
118   this._bitmapInfo.palette = palette;
119 };
120
121 ParserAsync.prototype._simpleTransparency = function() {
122   this._metaData.alpha = true;
123 };
124
125 ParserAsync.prototype._headersFinished = function() {
126   // Up until this point, we don't know if we have a tRNS chunk (alpha)
127   // so we can't emit metadata any earlier
128   this.emit('metadata', this._metaData);
129 };
130
131 ParserAsync.prototype._finished = function() {
132   if (this.errord) {
133     return;
134   }
135
136   if (!this._inflate) {
137     this.emit('error', 'No Inflate block');
138   }
139   else {
140     // no more data to inflate
141     this._inflate.end();
142   }
143   this.destroySoon();
144 };
145
146 ParserAsync.prototype._complete = function(filteredData) {
147
148   if (this.errord) {
149     return;
150   }
151
152   try {
153     var bitmapData = bitmapper.dataToBitMap(filteredData, this._bitmapInfo);
154
155     var normalisedBitmapData = formatNormaliser(bitmapData, this._bitmapInfo);
156     bitmapData = null;
157   }
158   catch (ex) {
159     this._handleError(ex);
160     return;
161   }
162
163   this.emit('parsed', normalisedBitmapData);
164 };