744 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			744 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
|  **      ==============================
 | |
|  **       O           O      O   OOOO
 | |
|  **       O           O     O O  O   O
 | |
|  **       O           O     O O  O   O
 | |
|  **       OOOO   OOOO O     OOO  OOOO
 | |
|  **       O   O       O    O   O O   O
 | |
|  **       O   O       O    O   O O   O
 | |
|  **       OOOO        OOOO O   O OOOO
 | |
|  **      ==============================
 | |
|  **      Dr. Stefan Bosse http://www.bsslab.de
 | |
|  **
 | |
|  **      COPYRIGHT: THIS SOFTWARE, EXECUTABLE AND SOURCE CODE IS OWNED
 | |
|  **                 BY THE AUTHOR(S).
 | |
|  **                 THIS SOURCE CODE MAY NOT BE COPIED, EXTRACTED,
 | |
|  **                 MODIFIED, OR OTHERWISE USED IN A CONTEXT
 | |
|  **                 OUTSIDE OF THE SOFTWARE SYSTEM.
 | |
|  **
 | |
|  **    $AUTHORS:     Christopher Jeffrey and contributors, Stefan Bosse
 | |
|  **    $INITIAL:     (C) 2013-2015, Christopher Jeffrey and contributors
 | |
|  **    $MODIFIED:    sbosse (2017).
 | |
|  **    $VERSION:     1.2.2
 | |
|  **
 | |
|  **    $INFO:
 | |
|  *
 | |
|  * overlayimage.js - w3m image element for blessed
 | |
|  *
 | |
|  **    $ENDOFINFO
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * Modules
 | |
|  */
 | |
| var Comp = Require('com/compat');
 | |
| 
 | |
| var fs = Require('fs')
 | |
|   , cp = Require('child_process');
 | |
| 
 | |
| var helpers = Require('term/helpers');
 | |
| 
 | |
| var Node = Require('term/widgets/node');
 | |
| var Box = Require('term/widgets/box');
 | |
| 
 | |
| /**
 | |
|  * OverlayImage
 | |
|  * Good example of w3mimgdisplay commands:
 | |
|  * https://github.com/hut/ranger/blob/master/ranger/ext/img_display.py
 | |
|  */
 | |
| 
 | |
| function OverlayImage(options) {
 | |
|   var self = this;
 | |
| 
 | |
|   if (!instanceOf(this,Node)) {
 | |
|     return new OverlayImage(options);
 | |
|   }
 | |
| 
 | |
|   options = options || {};
 | |
| 
 | |
|   Box.call(this, options);
 | |
| 
 | |
|   if (options.w3m) {
 | |
|     OverlayImage.w3mdisplay = options.w3m;
 | |
|   }
 | |
| 
 | |
|   if (OverlayImage.hasW3MDisplay == null) {
 | |
|     if (fs.existsSync(OverlayImage.w3mdisplay)) {
 | |
|       OverlayImage.hasW3MDisplay = true;
 | |
|     } else if (options.search !== false) {
 | |
|       var file = helpers.findFile('/usr', 'w3mimgdisplay')
 | |
|               || helpers.findFile('/lib', 'w3mimgdisplay')
 | |
|               || helpers.findFile('/bin', 'w3mimgdisplay');
 | |
|       if (file) {
 | |
|         OverlayImage.hasW3MDisplay = true;
 | |
|         OverlayImage.w3mdisplay = file;
 | |
|       } else {
 | |
|         OverlayImage.hasW3MDisplay = false;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   this.on('hide', function() {
 | |
|     self._lastFile = self.file;
 | |
|     self.clearImage();
 | |
|   });
 | |
| 
 | |
|   this.on('show', function() {
 | |
|     if (!self._lastFile) return;
 | |
|     self.setImage(self._lastFile);
 | |
|   });
 | |
| 
 | |
|   this.on('detach', function() {
 | |
|     self._lastFile = self.file;
 | |
|     self.clearImage();
 | |
|   });
 | |
| 
 | |
|   this.on('attach', function() {
 | |
|     if (!self._lastFile) return;
 | |
|     self.setImage(self._lastFile);
 | |
|   });
 | |
| 
 | |
|   this.onScreenEvent('resize', function() {
 | |
|     self._needsRatio = true;
 | |
|   });
 | |
| 
 | |
|   // Get images to overlap properly. Maybe not worth it:
 | |
|   // this.onScreenEvent('render', function() {
 | |
|   //   self.screen.program.flush();
 | |
|   //   if (!self._noImage) return;
 | |
|   //   function display(el, next) {
 | |
|   //     if (el.type === 'w3mimage' && el.file) {
 | |
|   //       el.setImage(el.file, next);
 | |
|   //     } else {
 | |
|   //       next();
 | |
|   //     }
 | |
|   //   }
 | |
|   //   function done(el) {
 | |
|   //     el.children.forEach(recurse);
 | |
|   //   }
 | |
|   //   function recurse(el) {
 | |
|   //     display(el, function() {
 | |
|   //       var pending = el.children.length;
 | |
|   //       el.children.forEach(function(el) {
 | |
|   //         display(el, function() {
 | |
|   //           if (!--pending) done(el);
 | |
|   //         });
 | |
|   //       });
 | |
|   //     });
 | |
|   //   }
 | |
|   //   recurse(self.screen);
 | |
|   // });
 | |
| 
 | |
|   this.onScreenEvent('render', function() {
 | |
|     self.screen.program.flush();
 | |
|     if (!self._noImage) {
 | |
|       self.setImage(self.file);
 | |
|     }
 | |
|   });
 | |
| 
 | |
|   if (this.options.file || this.options.img) {
 | |
|     this.setImage(this.options.file || this.options.img);
 | |
|   }
 | |
| }
 | |
| 
 | |
| //OverlayImage.prototype.__proto__ = Box.prototype;
 | |
| inheritPrototype(OverlayImage,Box);
 | |
| 
 | |
| OverlayImage.prototype.type = 'overlayimage';
 | |
| 
 | |
| OverlayImage.w3mdisplay = '/usr/lib/w3m/w3mimgdisplay';
 | |
| 
 | |
| OverlayImage.prototype.spawn = function(file, args, opt, callback) {
 | |
|   var spawn = require('child_process').spawn
 | |
|     , ps;
 | |
| 
 | |
|   opt = opt || {};
 | |
|   ps = spawn(file, args, opt);
 | |
| 
 | |
|   ps.on('error', function(err) {
 | |
|     if (!callback) return;
 | |
|     return callback(err);
 | |
|   });
 | |
| 
 | |
|   ps.on('exit', function(code) {
 | |
|     if (!callback) return;
 | |
|     if (code !== 0) return callback(new Error('Exit Code: ' + code));
 | |
|     return callback(null, code === 0);
 | |
|   });
 | |
| 
 | |
|   return ps;
 | |
| };
 | |
| 
 | |
| OverlayImage.prototype.setImage = function(img, callback) {
 | |
|   var self = this;
 | |
| 
 | |
|   if (this._settingImage) {
 | |
|     this._queue = this._queue || [];
 | |
|     this._queue.push([img, callback]);
 | |
|     return;
 | |
|   }
 | |
|   this._settingImage = true;
 | |
| 
 | |
|   var reset = function() {
 | |
|     self._settingImage = false;
 | |
|     self._queue = self._queue || [];
 | |
|     var item = self._queue.shift();
 | |
|     if (item) {
 | |
|       self.setImage(item[0], item[1]);
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   if (OverlayImage.hasW3MDisplay === false) {
 | |
|     reset();
 | |
|     if (!callback) return;
 | |
|     return callback(new Error('W3M Image Display not available.'));
 | |
|   }
 | |
| 
 | |
|   if (!img) {
 | |
|     reset();
 | |
|     if (!callback) return;
 | |
|     return callback(new Error('No image.'));
 | |
|   }
 | |
| 
 | |
|   this.file = img;
 | |
| 
 | |
|   return this.getPixelRatio(function(err, ratio) {
 | |
|     if (err) {
 | |
|       reset();
 | |
|       if (!callback) return;
 | |
|       return callback(err);
 | |
|     }
 | |
| 
 | |
|     return self.renderImage(img, ratio, function(err, success) {
 | |
|       if (err) {
 | |
|         reset();
 | |
|         if (!callback) return;
 | |
|         return callback(err);
 | |
|       }
 | |
| 
 | |
|       if (self.shrink || self.options.autofit) {
 | |
|         delete self.shrink;
 | |
|         delete self.options.shrink;
 | |
|         self.options.autofit = true;
 | |
|         return self.imageSize(function(err, size) {
 | |
|           if (err) {
 | |
|             reset();
 | |
|             if (!callback) return;
 | |
|             return callback(err);
 | |
|           }
 | |
| 
 | |
|           if (self._lastSize
 | |
|               && ratio.tw === self._lastSize.tw
 | |
|               && ratio.th === self._lastSize.th
 | |
|               && size.width === self._lastSize.width
 | |
|               && size.height === self._lastSize.height
 | |
|               && self.aleft === self._lastSize.aleft
 | |
|               && self.atop === self._lastSize.atop) {
 | |
|             reset();
 | |
|             if (!callback) return;
 | |
|             return callback(null, success);
 | |
|           }
 | |
| 
 | |
|           self._lastSize = {
 | |
|             tw: ratio.tw,
 | |
|             th: ratio.th,
 | |
|             width: size.width,
 | |
|             height: size.height,
 | |
|             aleft: self.aleft,
 | |
|             atop: self.atop
 | |
|           };
 | |
| 
 | |
|           self.position.width = size.width / ratio.tw | 0;
 | |
|           self.position.height = size.height / ratio.th | 0;
 | |
| 
 | |
|           self._noImage = true;
 | |
|           self.screen.render();
 | |
|           self._noImage = false;
 | |
| 
 | |
|           reset();
 | |
|           return self.renderImage(img, ratio, callback);
 | |
|         });
 | |
|       }
 | |
| 
 | |
|       reset();
 | |
|       if (!callback) return;
 | |
|       return callback(null, success);
 | |
|     });
 | |
|   });
 | |
| };
 | |
| 
 | |
| OverlayImage.prototype.renderImage = function(img, ratio, callback) {
 | |
|   var self = this;
 | |
| 
 | |
|   if (cp.execSync) {
 | |
|     callback = callback || function(err, result) { return result; };
 | |
|     try {
 | |
|       return callback(null, this.renderImageSync(img, ratio));
 | |
|     } catch (e) {
 | |
|       return callback(e);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (OverlayImage.hasW3MDisplay === false) {
 | |
|     if (!callback) return;
 | |
|     return callback(new Error('W3M Image Display not available.'));
 | |
|   }
 | |
| 
 | |
|   if (!ratio) {
 | |
|     if (!callback) return;
 | |
|     return callback(new Error('No ratio.'));
 | |
|   }
 | |
| 
 | |
|   // clearImage unsets these:
 | |
|   var _file = self.file;
 | |
|   var _lastSize = self._lastSize;
 | |
|   return self.clearImage(function(err) {
 | |
|     if (err) return callback(err);
 | |
| 
 | |
|     self.file = _file;
 | |
|     self._lastSize = _lastSize;
 | |
| 
 | |
|     var opt = {
 | |
|       stdio: 'pipe',
 | |
|       env: process.env,
 | |
|       cwd: process.env.HOME
 | |
|     };
 | |
| 
 | |
|     var ps = self.spawn(OverlayImage.w3mdisplay, [], opt, function(err, success) {
 | |
|       if (!callback) return;
 | |
|       return err
 | |
|         ? callback(err)
 | |
|         : callback(null, success);
 | |
|     });
 | |
| 
 | |
|     var width = self.width * ratio.tw | 0
 | |
|       , height = self.height * ratio.th | 0
 | |
|       , aleft = self.aleft * ratio.tw | 0
 | |
|       , atop = self.atop * ratio.th | 0;
 | |
| 
 | |
|     var input = '0;1;'
 | |
|       + aleft + ';'
 | |
|       + atop + ';'
 | |
|       + width + ';'
 | |
|       + height + ';;;;;'
 | |
|       + img
 | |
|       + '\n4;\n3;\n';
 | |
| 
 | |
|     self._props = {
 | |
|       aleft: aleft,
 | |
|       atop: atop,
 | |
|       width: width,
 | |
|       height: height
 | |
|     };
 | |
| 
 | |
|     ps.stdin.write(input);
 | |
|     ps.stdin.end();
 | |
|   });
 | |
| };
 | |
| 
 | |
| OverlayImage.prototype.clearImage = function(callback) {
 | |
|   if (cp.execSync) {
 | |
|     callback = callback || function(err, result) { return result; };
 | |
|     try {
 | |
|       return callback(null, this.clearImageSync());
 | |
|     } catch (e) {
 | |
|       return callback(e);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (OverlayImage.hasW3MDisplay === false) {
 | |
|     if (!callback) return;
 | |
|     return callback(new Error('W3M Image Display not available.'));
 | |
|   }
 | |
| 
 | |
|   if (!this._props) {
 | |
|     if (!callback) return;
 | |
|     return callback(null);
 | |
|   }
 | |
| 
 | |
|   var opt = {
 | |
|     stdio: 'pipe',
 | |
|     env: process.env,
 | |
|     cwd: process.env.HOME
 | |
|   };
 | |
| 
 | |
|   var ps = this.spawn(OverlayImage.w3mdisplay, [], opt, function(err, success) {
 | |
|     if (!callback) return;
 | |
|     return err
 | |
|       ? callback(err)
 | |
|       : callback(null, success);
 | |
|   });
 | |
| 
 | |
|   var width = this._props.width + 2
 | |
|     , height = this._props.height + 2
 | |
|     , aleft = this._props.aleft
 | |
|     , atop = this._props.atop;
 | |
| 
 | |
|   if (this._drag) {
 | |
|     aleft -= 10;
 | |
|     atop -= 10;
 | |
|     width += 10;
 | |
|     height += 10;
 | |
|   }
 | |
| 
 | |
|   var input = '6;'
 | |
|    + aleft + ';'
 | |
|    + atop + ';'
 | |
|    + width + ';'
 | |
|    + height
 | |
|    + '\n4;\n3;\n';
 | |
| 
 | |
|   delete this.file;
 | |
|   delete this._props;
 | |
|   delete this._lastSize;
 | |
| 
 | |
|   ps.stdin.write(input);
 | |
|   ps.stdin.end();
 | |
| };
 | |
| 
 | |
| OverlayImage.prototype.imageSize = function(callback) {
 | |
|   var img = this.file;
 | |
| 
 | |
|   if (cp.execSync) {
 | |
|     callback = callback || function(err, result) { return result; };
 | |
|     try {
 | |
|       return callback(null, this.imageSizeSync());
 | |
|     } catch (e) {
 | |
|       return callback(e);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (OverlayImage.hasW3MDisplay === false) {
 | |
|     if (!callback) return;
 | |
|     return callback(new Error('W3M Image Display not available.'));
 | |
|   }
 | |
| 
 | |
|   if (!img) {
 | |
|     if (!callback) return;
 | |
|     return callback(new Error('No image.'));
 | |
|   }
 | |
| 
 | |
|   var opt = {
 | |
|     stdio: 'pipe',
 | |
|     env: process.env,
 | |
|     cwd: process.env.HOME
 | |
|   };
 | |
| 
 | |
|   var ps = this.spawn(OverlayImage.w3mdisplay, [], opt);
 | |
| 
 | |
|   var buf = '';
 | |
| 
 | |
|   ps.stdout.setEncoding('utf8');
 | |
| 
 | |
|   ps.stdout.on('data', function(data) {
 | |
|     buf += data;
 | |
|   });
 | |
| 
 | |
|   ps.on('error', function(err) {
 | |
|     if (!callback) return;
 | |
|     return callback(err);
 | |
|   });
 | |
| 
 | |
|   ps.on('exit', function() {
 | |
|     if (!callback) return;
 | |
|     var size = buf.trim().split(/\s+/);
 | |
|     return callback(null, {
 | |
|       raw: buf.trim(),
 | |
|       width: +size[0],
 | |
|       height: +size[1]
 | |
|     });
 | |
|   });
 | |
| 
 | |
|   var input = '5;' + img + '\n';
 | |
| 
 | |
|   ps.stdin.write(input);
 | |
|   ps.stdin.end();
 | |
| };
 | |
| 
 | |
| OverlayImage.prototype.termSize = function(callback) {
 | |
|   var self = this;
 | |
| 
 | |
|   if (cp.execSync) {
 | |
|     callback = callback || function(err, result) { return result; };
 | |
|     try {
 | |
|       return callback(null, this.termSizeSync());
 | |
|     } catch (e) {
 | |
|       return callback(e);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (OverlayImage.hasW3MDisplay === false) {
 | |
|     if (!callback) return;
 | |
|     return callback(new Error('W3M Image Display not available.'));
 | |
|   }
 | |
| 
 | |
|   var opt = {
 | |
|     stdio: 'pipe',
 | |
|     env: process.env,
 | |
|     cwd: process.env.HOME
 | |
|   };
 | |
| 
 | |
|   var ps = this.spawn(OverlayImage.w3mdisplay, ['-test'], opt);
 | |
| 
 | |
|   var buf = '';
 | |
| 
 | |
|   ps.stdout.setEncoding('utf8');
 | |
| 
 | |
|   ps.stdout.on('data', function(data) {
 | |
|     buf += data;
 | |
|   });
 | |
| 
 | |
|   ps.on('error', function(err) {
 | |
|     if (!callback) return;
 | |
|     return callback(err);
 | |
|   });
 | |
| 
 | |
|   ps.on('exit', function() {
 | |
|     if (!callback) return;
 | |
| 
 | |
|     if (!buf.trim()) {
 | |
|       // Bug: w3mimgdisplay will sometimes
 | |
|       // output nothing. Try again:
 | |
|       return self.termSize(callback);
 | |
|     }
 | |
| 
 | |
|     var size = buf.trim().split(/\s+/);
 | |
| 
 | |
|     return callback(null, {
 | |
|       raw: buf.trim(),
 | |
|       width: +size[0],
 | |
|       height: +size[1]
 | |
|     });
 | |
|   });
 | |
| 
 | |
|   ps.stdin.end();
 | |
| };
 | |
| 
 | |
| OverlayImage.prototype.getPixelRatio = function(callback) {
 | |
|   var self = this;
 | |
| 
 | |
|   if (cp.execSync) {
 | |
|     callback = callback || function(err, result) { return result; };
 | |
|     try {
 | |
|       return callback(null, this.getPixelRatioSync());
 | |
|     } catch (e) {
 | |
|       return callback(e);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // XXX We could cache this, but sometimes it's better
 | |
|   // to recalculate to be pixel perfect.
 | |
|   if (this._ratio && !this._needsRatio) {
 | |
|     return callback(null, this._ratio);
 | |
|   }
 | |
| 
 | |
|   return this.termSize(function(err, dimensions) {
 | |
|     if (err) return callback(err);
 | |
| 
 | |
|     self._ratio = {
 | |
|       tw: dimensions.width / self.screen.width,
 | |
|       th: dimensions.height / self.screen.height
 | |
|     };
 | |
| 
 | |
|     self._needsRatio = false;
 | |
| 
 | |
|     return callback(null, self._ratio);
 | |
|   });
 | |
| };
 | |
| 
 | |
| OverlayImage.prototype.renderImageSync = function(img, ratio) {
 | |
|   if (OverlayImage.hasW3MDisplay === false) {
 | |
|     throw new Error('W3M Image Display not available.');
 | |
|   }
 | |
| 
 | |
|   if (!ratio) {
 | |
|     throw new Error('No ratio.');
 | |
|   }
 | |
| 
 | |
|   // clearImage unsets these:
 | |
|   var _file = this.file;
 | |
|   var _lastSize = this._lastSize;
 | |
| 
 | |
|   this.clearImageSync();
 | |
| 
 | |
|   this.file = _file;
 | |
|   this._lastSize = _lastSize;
 | |
| 
 | |
|   var width = this.width * ratio.tw | 0
 | |
|     , height = this.height * ratio.th | 0
 | |
|     , aleft = this.aleft * ratio.tw | 0
 | |
|     , atop = this.atop * ratio.th | 0;
 | |
| 
 | |
|   var input = '0;1;'
 | |
|     + aleft + ';'
 | |
|     + atop + ';'
 | |
|     + width + ';'
 | |
|     + height + ';;;;;'
 | |
|     + img
 | |
|     + '\n4;\n3;\n';
 | |
| 
 | |
|   this._props = {
 | |
|     aleft: aleft,
 | |
|     atop: atop,
 | |
|     width: width,
 | |
|     height: height
 | |
|   };
 | |
| 
 | |
|   try {
 | |
|     cp.execFileSync(OverlayImage.w3mdisplay, [], {
 | |
|       env: process.env,
 | |
|       encoding: 'utf8',
 | |
|       input: input,
 | |
|       timeout: 1000
 | |
|     });
 | |
|   } catch (e) {
 | |
|     ;
 | |
|   }
 | |
| 
 | |
|   return true;
 | |
| };
 | |
| 
 | |
| OverlayImage.prototype.clearImageSync = function() {
 | |
|   if (OverlayImage.hasW3MDisplay === false) {
 | |
|     throw new Error('W3M Image Display not available.');
 | |
|   }
 | |
| 
 | |
|   if (!this._props) {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   var width = this._props.width + 2
 | |
|     , height = this._props.height + 2
 | |
|     , aleft = this._props.aleft
 | |
|     , atop = this._props.atop;
 | |
| 
 | |
|   if (this._drag) {
 | |
|     aleft -= 10;
 | |
|     atop -= 10;
 | |
|     width += 10;
 | |
|     height += 10;
 | |
|   }
 | |
| 
 | |
|   var input = '6;'
 | |
|    + aleft + ';'
 | |
|    + atop + ';'
 | |
|    + width + ';'
 | |
|    + height
 | |
|    + '\n4;\n3;\n';
 | |
| 
 | |
|   delete this.file;
 | |
|   delete this._props;
 | |
|   delete this._lastSize;
 | |
| 
 | |
|   try {
 | |
|     cp.execFileSync(OverlayImage.w3mdisplay, [], {
 | |
|       env: process.env,
 | |
|       encoding: 'utf8',
 | |
|       input: input,
 | |
|       timeout: 1000
 | |
|     });
 | |
|   } catch (e) {
 | |
|     ;
 | |
|   }
 | |
| 
 | |
|   return true;
 | |
| };
 | |
| 
 | |
| OverlayImage.prototype.imageSizeSync = function() {
 | |
|   var img = this.file;
 | |
| 
 | |
|   if (OverlayImage.hasW3MDisplay === false) {
 | |
|     throw new Error('W3M Image Display not available.');
 | |
|   }
 | |
| 
 | |
|   if (!img) {
 | |
|     throw new Error('No image.');
 | |
|   }
 | |
| 
 | |
|   var buf = '';
 | |
|   var input = '5;' + img + '\n';
 | |
| 
 | |
|   try {
 | |
|     buf = cp.execFileSync(OverlayImage.w3mdisplay, [], {
 | |
|       env: process.env,
 | |
|       encoding: 'utf8',
 | |
|       input: input,
 | |
|       timeout: 1000
 | |
|     });
 | |
|   } catch (e) {
 | |
|     ;
 | |
|   }
 | |
| 
 | |
|   var size = buf.trim().split(/\s+/);
 | |
| 
 | |
|   return {
 | |
|     raw: buf.trim(),
 | |
|     width: +size[0],
 | |
|     height: +size[1]
 | |
|   };
 | |
| };
 | |
| 
 | |
| OverlayImage.prototype.termSizeSync = function(_, recurse) {
 | |
|   if (OverlayImage.hasW3MDisplay === false) {
 | |
|     throw new Error('W3M Image Display not available.');
 | |
|   }
 | |
| 
 | |
|   var buf = '';
 | |
| 
 | |
|   try {
 | |
|     buf = cp.execFileSync(OverlayImage.w3mdisplay, ['-test'], {
 | |
|       env: process.env,
 | |
|       encoding: 'utf8',
 | |
|       timeout: 1000
 | |
|     });
 | |
|   } catch (e) {
 | |
|     ;
 | |
|   }
 | |
| 
 | |
|   if (!buf.trim()) {
 | |
|     // Bug: w3mimgdisplay will sometimes
 | |
|     // output nothing. Try again:
 | |
|     recurse = recurse || 0;
 | |
|     if (++recurse === 5) {
 | |
|       throw new Error('Term size not determined.');
 | |
|     }
 | |
|     return this.termSizeSync(_, recurse);
 | |
|   }
 | |
| 
 | |
|   var size = buf.trim().split(/\s+/);
 | |
| 
 | |
|   return {
 | |
|     raw: buf.trim(),
 | |
|     width: +size[0],
 | |
|     height: +size[1]
 | |
|   };
 | |
| };
 | |
| 
 | |
| OverlayImage.prototype.getPixelRatioSync = function() {
 | |
|   // XXX We could cache this, but sometimes it's better
 | |
|   // to recalculate to be pixel perfect.
 | |
|   if (this._ratio && !this._needsRatio) {
 | |
|     return this._ratio;
 | |
|   }
 | |
|   this._needsRatio = false;
 | |
| 
 | |
|   var dimensions = this.termSizeSync();
 | |
| 
 | |
|   this._ratio = {
 | |
|     tw: dimensions.width / this.screen.width,
 | |
|     th: dimensions.height / this.screen.height
 | |
|   };
 | |
| 
 | |
|   return this._ratio;
 | |
| };
 | |
| 
 | |
| OverlayImage.prototype.displayImage = function(callback) {
 | |
|   return this.screen.displayImage(this.file, callback);
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Expose
 | |
|  */
 | |
| 
 | |
| module.exports = OverlayImage;
 |