Turn audio into a shareable video. forked from nypublicradio/audiogram

context2d.js 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. 'use strict';
  2. /*!
  3. * Canvas - Context2d
  4. * Copyright (c) 2010 LearnBoost <tj@learnboost.com>
  5. * MIT Licensed
  6. */
  7. /**
  8. * Module dependencies.
  9. */
  10. var canvas = require('./bindings')
  11. , Context2d = canvas.CanvasRenderingContext2d
  12. , CanvasGradient = canvas.CanvasGradient
  13. , CanvasPattern = canvas.CanvasPattern
  14. , ImageData = canvas.ImageData;
  15. /**
  16. * Export `Context2d` as the module.
  17. */
  18. var Context2d = exports = module.exports = Context2d;
  19. /**
  20. * Cache color string RGBA values.
  21. */
  22. var cache = {};
  23. /**
  24. * Text baselines.
  25. */
  26. var baselines = ['alphabetic', 'top', 'bottom', 'middle', 'ideographic', 'hanging'];
  27. /**
  28. * Font RegExp helpers.
  29. */
  30. var weights = 'normal|bold|bolder|lighter|[1-9]00'
  31. , styles = 'normal|italic|oblique'
  32. , units = 'px|pt|pc|in|cm|mm|%'
  33. , string = '\'([^\']+)\'|"([^"]+)"|[\\w-]+';
  34. /**
  35. * Font parser RegExp;
  36. */
  37. var fontre = new RegExp('^ *'
  38. + '(?:(' + weights + ') *)?'
  39. + '(?:(' + styles + ') *)?'
  40. + '([\\d\\.]+)(' + units + ') *'
  41. + '((?:' + string + ')( *, *(?:' + string + '))*)'
  42. );
  43. /**
  44. * Parse font `str`.
  45. *
  46. * @param {String} str
  47. * @return {Object}
  48. * @api private
  49. */
  50. var parseFont = exports.parseFont = function(str){
  51. var font = {}
  52. , captures = fontre.exec(str);
  53. // Invalid
  54. if (!captures) return;
  55. // Cached
  56. if (cache[str]) return cache[str];
  57. // Populate font object
  58. font.weight = captures[1] || 'normal';
  59. font.style = captures[2] || 'normal';
  60. font.size = parseFloat(captures[3]);
  61. font.unit = captures[4];
  62. font.family = captures[5].replace(/["']/g, '').split(',')[0].trim();
  63. // TODO: dpi
  64. // TODO: remaining unit conversion
  65. switch (font.unit) {
  66. case 'pt':
  67. font.size /= .75;
  68. break;
  69. case 'in':
  70. font.size *= 96;
  71. break;
  72. case 'mm':
  73. font.size *= 96.0 / 25.4;
  74. break;
  75. case 'cm':
  76. font.size *= 96.0 / 2.54;
  77. break;
  78. }
  79. return cache[str] = font;
  80. };
  81. /**
  82. * Enable or disable image smoothing.
  83. *
  84. * @api public
  85. */
  86. Context2d.prototype.__defineSetter__('imageSmoothingEnabled', function(val){
  87. this._imageSmoothing = !! val;
  88. this.patternQuality = val ? 'best' : 'fast';
  89. });
  90. /**
  91. * Get image smoothing value.
  92. *
  93. * @api public
  94. */
  95. Context2d.prototype.__defineGetter__('imageSmoothingEnabled', function(val){
  96. return !! this._imageSmoothing;
  97. });
  98. /**
  99. * Create a pattern from `Image` or `Canvas`.
  100. *
  101. * @param {Image|Canvas} image
  102. * @param {String} repetition
  103. * @return {CanvasPattern}
  104. * @api public
  105. */
  106. Context2d.prototype.createPattern = function(image, repetition){
  107. // TODO Use repetition (currently always 'repeat')
  108. return new CanvasPattern(image);
  109. };
  110. /**
  111. * Create a linear gradient at the given point `(x0, y0)` and `(x1, y1)`.
  112. *
  113. * @param {Number} x0
  114. * @param {Number} y0
  115. * @param {Number} x1
  116. * @param {Number} y1
  117. * @return {CanvasGradient}
  118. * @api public
  119. */
  120. Context2d.prototype.createLinearGradient = function(x0, y0, x1, y1){
  121. return new CanvasGradient(x0, y0, x1, y1);
  122. };
  123. /**
  124. * Create a radial gradient at the given point `(x0, y0)` and `(x1, y1)`
  125. * and radius `r0` and `r1`.
  126. *
  127. * @param {Number} x0
  128. * @param {Number} y0
  129. * @param {Number} r0
  130. * @param {Number} x1
  131. * @param {Number} y1
  132. * @param {Number} r1
  133. * @return {CanvasGradient}
  134. * @api public
  135. */
  136. Context2d.prototype.createRadialGradient = function(x0, y0, r0, x1, y1, r1){
  137. return new CanvasGradient(x0, y0, r0, x1, y1, r1);
  138. };
  139. /**
  140. * Reset transform matrix to identity, then apply the given args.
  141. *
  142. * @param {...}
  143. * @api public
  144. */
  145. Context2d.prototype.setTransform = function(){
  146. this.resetTransform();
  147. this.transform.apply(this, arguments);
  148. };
  149. /**
  150. * Set the fill style with the given css color string.
  151. *
  152. * @api public
  153. */
  154. Context2d.prototype.__defineSetter__('fillStyle', function(val){
  155. if (!val) return;
  156. if ('CanvasGradient' == val.constructor.name
  157. || 'CanvasPattern' == val.constructor.name) {
  158. this.lastFillStyle = val;
  159. this._setFillPattern(val);
  160. } else if ('string' == typeof val) {
  161. this._setFillColor(val);
  162. }
  163. });
  164. /**
  165. * Get previous fill style.
  166. *
  167. * @return {CanvasGradient|String}
  168. * @api public
  169. */
  170. Context2d.prototype.__defineGetter__('fillStyle', function(){
  171. return this.lastFillStyle || this.fillColor;
  172. });
  173. /**
  174. * Set the stroke style with the given css color string.
  175. *
  176. * @api public
  177. */
  178. Context2d.prototype.__defineSetter__('strokeStyle', function(val){
  179. if (!val) return;
  180. if ('CanvasGradient' == val.constructor.name
  181. || 'CanvasPattern' == val.constructor.name) {
  182. this.lastStrokeStyle = val;
  183. this._setStrokePattern(val);
  184. } else if ('string' == typeof val) {
  185. this._setStrokeColor(val);
  186. }
  187. });
  188. /**
  189. * Get previous stroke style.
  190. *
  191. * @return {CanvasGradient|String}
  192. * @api public
  193. */
  194. Context2d.prototype.__defineGetter__('strokeStyle', function(){
  195. return this.lastStrokeStyle || this.strokeColor;
  196. });
  197. /**
  198. * Set font.
  199. *
  200. * @see exports.parseFont()
  201. * @api public
  202. */
  203. Context2d.prototype.__defineSetter__('font', function(val){
  204. if (!val) return;
  205. if ('string' == typeof val) {
  206. var font;
  207. if (font = parseFont(val)) {
  208. this.lastFontString = val;
  209. this._setFont(
  210. font.weight
  211. , font.style
  212. , font.size
  213. , font.unit
  214. , font.family);
  215. }
  216. }
  217. });
  218. /**
  219. * Get the current font.
  220. *
  221. * @api public
  222. */
  223. Context2d.prototype.__defineGetter__('font', function(){
  224. return this.lastFontString || '10px sans-serif';
  225. });
  226. /**
  227. * Set text baseline.
  228. *
  229. * @api public
  230. */
  231. Context2d.prototype.__defineSetter__('textBaseline', function(val){
  232. if (!val) return;
  233. var n = baselines.indexOf(val);
  234. if (~n) {
  235. this.lastBaseline = val;
  236. this._setTextBaseline(n);
  237. }
  238. });
  239. /**
  240. * Get the current baseline setting.
  241. *
  242. * @api public
  243. */
  244. Context2d.prototype.__defineGetter__('textBaseline', function(){
  245. return this.lastBaseline || 'alphabetic';
  246. });
  247. /**
  248. * Set text alignment.
  249. *
  250. * @api public
  251. */
  252. Context2d.prototype.__defineSetter__('textAlign', function(val){
  253. switch (val) {
  254. case 'center':
  255. this._setTextAlignment(0);
  256. this.lastTextAlignment = val;
  257. break;
  258. case 'left':
  259. case 'start':
  260. this._setTextAlignment(-1);
  261. this.lastTextAlignment = val;
  262. break;
  263. case 'right':
  264. case 'end':
  265. this._setTextAlignment(1);
  266. this.lastTextAlignment = val;
  267. break;
  268. }
  269. });
  270. /**
  271. * Get the current font.
  272. *
  273. * @see exports.parseFont()
  274. * @api public
  275. */
  276. Context2d.prototype.__defineGetter__('textAlign', function(){
  277. return this.lastTextAlignment || 'start';
  278. });
  279. /**
  280. * Create `ImageData` with the given dimensions or
  281. * `ImageData` instance for dimensions.
  282. *
  283. * @param {Number|ImageData} width
  284. * @param {Number} height
  285. * @return {ImageData}
  286. * @api public
  287. */
  288. Context2d.prototype.createImageData = function(width, height){
  289. if ('ImageData' == width.constructor.name) {
  290. height = width.height;
  291. width = width.width;
  292. }
  293. return new ImageData(new Uint8ClampedArray(width * height * 4), width, height);
  294. };