mxAsyncCanvas.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /**
  2. * mxAsyncCanvas
  3. */
  4. /**
  5. * Extends mxAbstractCanvas2D
  6. */
  7. function mxAsyncCanvas(htmlCanvas)
  8. {
  9. mxAbstractCanvas2D.call(this);
  10. this.htmlCanvas = htmlCanvas;
  11. htmlCanvas.images = htmlCanvas.images || [];
  12. htmlCanvas.subCanvas = htmlCanvas.subCanvas || [];
  13. };
  14. /**
  15. * Extends mxAbstractCanvas2D
  16. */
  17. mxUtils.extend(mxAsyncCanvas, mxAbstractCanvas2D);
  18. /**
  19. * Variable: htmlCanvas
  20. *
  21. * The canvas instance this object is obtaining async resources for
  22. */
  23. mxAsyncCanvas.prototype.htmlCanvas = null;
  24. /**
  25. * Variable: canvasIndex
  26. *
  27. * The current index into the canvas sub-canvas array being processed
  28. */
  29. mxAsyncCanvas.prototype.canvasIndex = 0;
  30. /**
  31. * Variable: ctx
  32. *
  33. * Holds the current canvas context
  34. */
  35. mxAsyncCanvas.prototype.waitCounter = 0;
  36. /**
  37. * Variable: ctx
  38. *
  39. * Holds the current canvas context
  40. */
  41. mxAsyncCanvas.prototype.onComplete = null;
  42. mxAsyncCanvas.prototype.incWaitCounter = function()
  43. {
  44. this.waitCounter++;
  45. };
  46. mxAsyncCanvas.prototype.decWaitCounter = function()
  47. {
  48. this.waitCounter--;
  49. if (this.waitCounter == 0 && this.onComplete != null)
  50. {
  51. this.onComplete();
  52. this.onComplete = null;
  53. }
  54. };
  55. mxAsyncCanvas.prototype.updateFont = function()
  56. {
  57. var style = '';
  58. if ((this.state.fontStyle & mxConstants.FONT_BOLD) == mxConstants.FONT_BOLD)
  59. {
  60. style += 'bold ';
  61. }
  62. if ((this.state.fontStyle & mxConstants.FONT_ITALIC) == mxConstants.FONT_ITALIC)
  63. {
  64. style += 'italic ';
  65. }
  66. this.ctx.font = style + this.state.fontSize + 'px ' + this.state.fontFamily;
  67. };
  68. mxAsyncCanvas.prototype.rotate = function(theta, flipH, flipV, cx, cy)
  69. {
  70. };
  71. mxAsyncCanvas.prototype.setAlpha = function(alpha)
  72. {
  73. this.state.alpha = alpha;
  74. };
  75. mxAsyncCanvas.prototype.setFontColor = function(value)
  76. {
  77. this.state.fontColor = value;
  78. };
  79. mxAsyncCanvas.prototype.setFontBackgroundColor = function(value)
  80. {
  81. if (value == mxConstants.NONE)
  82. {
  83. value = null;
  84. }
  85. this.state.fontBackgroundColor = value;
  86. };
  87. mxAsyncCanvas.prototype.setFontBorderColor = function(value)
  88. {
  89. if (value == mxConstants.NONE)
  90. {
  91. value = null;
  92. }
  93. this.state.fontBorderColor = value;
  94. };
  95. mxAsyncCanvas.prototype.setFontSize = function(value)
  96. {
  97. this.state.fontSize = value;
  98. };
  99. mxAsyncCanvas.prototype.setFontFamily = function(value)
  100. {
  101. this.state.fontFamily = value;
  102. };
  103. mxAsyncCanvas.prototype.setFontStyle = function(value)
  104. {
  105. this.state.fontStyle = value;
  106. };
  107. mxAsyncCanvas.prototype.rect = function(x, y, w, h) {};
  108. mxAsyncCanvas.prototype.roundrect = function(x, y, w, h, dx, dy) {};
  109. mxAsyncCanvas.prototype.ellipse = function(x, y, w, h) {};
  110. //Redirect can be implemented via a hook
  111. mxAsyncCanvas.prototype.rewriteImageSource = function(src)
  112. {
  113. if (src.substring(0, 7) == 'http://' || src.substring(0, 8) == 'https://')
  114. {
  115. src = '/proxy?url=' + encodeURIComponent(src);
  116. }
  117. return src;
  118. };
  119. mxAsyncCanvas.prototype.image = function(x, y, w, h, src, aspect, flipH, flipV)
  120. {
  121. src = this.rewriteImageSource(src);
  122. var image = this.htmlCanvas.images[src];
  123. if (image == null)
  124. {
  125. var image = new Image();
  126. image.onload = mxUtils.bind(this, function()
  127. {
  128. this.decWaitCounter();
  129. });
  130. image.onerror = mxUtils.bind(this, function()
  131. {
  132. this.decWaitCounter();
  133. // TODO null the image out? this.htmlCanvas.images[src] = null;
  134. });
  135. this.incWaitCounter();
  136. this.htmlCanvas.images[src] = image;
  137. image.src = src;
  138. }
  139. };
  140. mxAsyncCanvas.prototype.fill = function() {};
  141. mxAsyncCanvas.prototype.stroke = function() {};
  142. mxAsyncCanvas.prototype.fillAndStroke = function() {};
  143. mxAsyncCanvas.prototype.text = function(x, y, w, h, str, align, valign, wrap, format, overflow, clip, rotation)
  144. {
  145. if (str == null || str.length == 0)
  146. {
  147. return;
  148. }
  149. var sc = this.state.scale;
  150. if (format == 'html' && typeof html2canvas === 'function')
  151. {
  152. this.incWaitCounter();
  153. var canvasIndex = this.canvasIndex++;
  154. html2canvas(str,
  155. {
  156. onrendered: mxUtils.bind(this, function(canvas)
  157. {
  158. this.htmlCanvas.subCanvas[canvasIndex] = canvas;
  159. this.decWaitCounter();
  160. }),
  161. scale: sc,
  162. logging: true
  163. });
  164. }
  165. };
  166. mxAsyncCanvas.prototype.finish = function(handler)
  167. {
  168. // TODO: Check if waitCounter updates need a monitor. Question is
  169. // if image load-handler can be executed in parallel leading to
  170. // race conditions when updating the "shared" waitCounter.
  171. if (this.waitCounter == 0)
  172. {
  173. handler();
  174. }
  175. else
  176. {
  177. this.onComplete = handler;
  178. }
  179. };