@grafit/era-dependencies 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/package.json +7 -0
  2. package/vendor/fonts/FontAwesome.otf +0 -0
  3. package/vendor/fonts/fontawesome-webfont.eot +0 -0
  4. package/vendor/fonts/fontawesome-webfont.svg +685 -0
  5. package/vendor/fonts/fontawesome-webfont.ttf +0 -0
  6. package/vendor/fonts/fontawesome-webfont.woff +0 -0
  7. package/vendor/fonts/fontawesome-webfont.woff2 +0 -0
  8. package/vendor/fonts/glyphicons-halflings-regular.eot +0 -0
  9. package/vendor/fonts/glyphicons-halflings-regular.svg +288 -0
  10. package/vendor/fonts/glyphicons-halflings-regular.ttf +0 -0
  11. package/vendor/fonts/glyphicons-halflings-regular.woff +0 -0
  12. package/vendor/fonts/glyphicons-halflings-regular.woff2 +0 -0
  13. package/vendor/scripts/angular/angular-cookies.js +322 -0
  14. package/vendor/scripts/angular/angular-file-upload.js +2087 -0
  15. package/vendor/scripts/angular/angular-filter.js +2287 -0
  16. package/vendor/scripts/angular/angular-locale_ru-ru.js +143 -0
  17. package/vendor/scripts/angular/angular-route.js +1069 -0
  18. package/vendor/scripts/angular/angular-sanitize.js +738 -0
  19. package/vendor/scripts/angular/angular-ui-router-0.2.18.js +4539 -0
  20. package/vendor/scripts/angular/angular.js +31768 -0
  21. package/vendor/scripts/angular/datetimepicker.js +578 -0
  22. package/vendor/scripts/angular/datetimepicker.templates.js +30 -0
  23. package/vendor/scripts/angular/mask.min.js +7 -0
  24. package/vendor/scripts/angular/ng-table.js +1518 -0
  25. package/vendor/scripts/angular/select.js +2356 -0
  26. package/vendor/scripts/angular/ui-bootstrap-tpls-2.1.3.js +7536 -0
  27. package/vendor/scripts/angular/uploader.js +3 -0
  28. package/vendor/scripts/bootbox.js +985 -0
  29. package/vendor/scripts/bootstrap.js +2377 -0
  30. package/vendor/scripts/es6-shim.js +3837 -0
  31. package/vendor/scripts/highchart/highcharts-more.src.js +3165 -0
  32. package/vendor/scripts/highchart/highstock.src.js +32008 -0
  33. package/vendor/scripts/highchart/modules/boost.src.js +2721 -0
  34. package/vendor/scripts/highchart/modules/exporting.src.js +951 -0
  35. package/vendor/scripts/jquery/jquery.js +11008 -0
  36. package/vendor/scripts/jquery.datetimepicker.full.js +2911 -0
  37. package/vendor/scripts/keycloak.js +2382 -0
  38. package/vendor/scripts/lodash.js +16733 -0
  39. package/vendor/scripts/moment-with-locales.js +12251 -0
  40. package/vendor/scripts/moment.js +4234 -0
  41. package/vendor/scripts/old/datepicker-ru.js +38 -0
  42. package/vendor/scripts/old/jquery-ui-1.11.1.js +16375 -0
  43. package/vendor/scripts/old/jquery.form.js +1278 -0
  44. package/vendor/scripts/perfect-scrollbar.js +1549 -0
  45. package/vendor/scripts/pickmeup/pickmeup-locales.js +11 -0
  46. package/vendor/scripts/pickmeup/pickmeup.js +1383 -0
  47. package/vendor/scripts/quill.js +9676 -0
  48. package/vendor/scripts/socket.io.min.js +3 -0
  49. package/vendor/scripts/textAngular/angular-spectrum-colorpicker.min.js +2 -0
  50. package/vendor/scripts/textAngular/spectrum.min.js +1 -0
  51. package/vendor/scripts/textAngular/textAngular-dropdownToggle.js +38 -0
  52. package/vendor/scripts/textAngular/textAngular-rangy.min.js +478 -0
  53. package/vendor/scripts/textAngular/textAngular-sanitize.min.js +322 -0
  54. package/vendor/scripts/textAngular/textAngular.min.js +1481 -0
  55. package/vendor/scripts/textAngular/textAngularSetup.js +1013 -0
  56. package/vendor/styles/bootstrap-theme.css +587 -0
  57. package/vendor/styles/bootstrap-theme.css.map +1 -0
  58. package/vendor/styles/bootstrap-theme.min.css +6 -0
  59. package/vendor/styles/bootstrap-theme.min.css.map +1 -0
  60. package/vendor/styles/bootstrap.css +6757 -0
  61. package/vendor/styles/bootstrap.css.map +1 -0
  62. package/vendor/styles/bootstrap.min.css +6 -0
  63. package/vendor/styles/bootstrap.min.css.map +1 -0
  64. package/vendor/styles/datetimepicker.css +115 -0
  65. package/vendor/styles/font-awesome.css +2199 -0
  66. package/vendor/styles/jquery.datetimepicker.min.css +1 -0
  67. package/vendor/styles/ng-table.css +136 -0
  68. package/vendor/styles/normalize.css +424 -0
  69. package/vendor/styles/perfect-scrollbar.css +165 -0
  70. package/vendor/styles/pickmeup.css +137 -0
  71. package/vendor/styles/spectrum.min.css +1 -0
  72. package/vendor/styles/textAngular.css +193 -0
@@ -0,0 +1,2721 @@
1
+ /**
2
+ * @license Highcharts JS v5.0.12 (2017-05-24)
3
+ * Boost module
4
+ *
5
+ * (c) 2010-2017 Highsoft AS
6
+ * Author: Torstein Honsi
7
+ *
8
+ * License: www.highcharts.com/license
9
+ */
10
+ 'use strict';
11
+ (function(factory) {
12
+ if (typeof module === 'object' && module.exports) {
13
+ module.exports = factory;
14
+ } else {
15
+ factory(Highcharts);
16
+ }
17
+ }(function(Highcharts) {
18
+ (function(H) {
19
+ /**
20
+ * License: www.highcharts.com/license
21
+ * Author: Christer Vasseng, Torstein Honsi
22
+ *
23
+ * This is an experimental Highcharts module that draws long data series on a canvas
24
+ * in order to increase performance of the initial load time and tooltip responsiveness.
25
+ *
26
+ * Compatible with WebGL compatible browsers (not IE < 11).
27
+ *
28
+ * Development plan
29
+ * - Column range.
30
+ * - Check how it works with Highstock and data grouping. Currently it only works when navigator.adaptToUpdatedData
31
+ * is false. It is also recommended to set scrollbar.liveRedraw to false.
32
+ * - Check inverted charts.
33
+ * - Chart callback should be async after last series is drawn. (But not necessarily, we don't do
34
+ that with initial series animation).
35
+ *
36
+ * If this module is taken in as part of the core
37
+ * - All the loading logic should be merged with core. Update styles in the core.
38
+ * - Most of the method wraps should probably be added directly in parent methods.
39
+ *
40
+ * Notes for boost mode
41
+ * - Area lines are not drawn
42
+ * - Lines are not drawn on scatter charts
43
+ * - Zones and negativeColor don't work
44
+ * - Columns are always one pixel wide. Don't set the threshold too low.
45
+ * - Disable animations
46
+ * - Marker shapes are not supported: markers will always be circles
47
+ *
48
+ * Optimizing tips for users
49
+ * - Set extremes (min, max) explicitly on the axes in order for Highcharts to avoid computing extremes.
50
+ * - Set enableMouseTracking to false on the series to improve total rendering time.
51
+ * - The default threshold is set based on one series. If you have multiple, dense series, the combined
52
+ * number of points drawn gets higher, and you may want to set the threshold lower in order to
53
+ * use optimizations.
54
+ * - If drawing large scatter charts, it's beneficial to set the marker radius to a value
55
+ * less than 1. This is to add additional spacing to make the chart more readable.
56
+ * - If the value increments on both the X and Y axis aren't small, consider setting
57
+ * useGPUTranslations to true on the boost settings object. If you do this and
58
+ * the increments are small (e.g. datetime axis with small time increments)
59
+ * it may cause rendering issues due to floating point rounding errors,
60
+ * so your millage may vary.
61
+ *
62
+ * Settings
63
+ * There are two ways of setting the boost threshold:
64
+ * - Per. series: boost based on number of points in individual series
65
+ * - Per. chart: boost based on the number of series
66
+ *
67
+ * To set the series boost threshold, set seriesBoostThreshold on the chart object.
68
+ * To set the series-specific threshold, set boostThreshold on the series object.
69
+ *
70
+ * In addition, the following can be set in the boost object:
71
+ * {
72
+ * //Wether or not to use alpha blending
73
+ * useAlpha: boolean - default: true
74
+ * //Set to true to perform translations on the GPU.
75
+ * //Much faster, but may cause rendering issues
76
+ * //when using values far from 0 due to floating point
77
+ * //rounding issues
78
+ * useGPUTranslations: boolean - default: false
79
+ * //Use pre-allocated buffers, much faster,
80
+ * //but may cause rendering issues with some data sets
81
+ * usePreallocated: boolean - default: false
82
+ * //Output rendering time in console
83
+ * timeRendering: boolean - default: false
84
+ * //Output processing time in console
85
+ * timeSeriesProcessing: boolean - default: false
86
+ * //Output setup time in console
87
+ * timeSetup: boolean - default: false
88
+ * }
89
+ */
90
+
91
+ /**
92
+ * Set the series threshold for when the boost should kick in globally.
93
+ *
94
+ * Setting to e.g. 20 will cause the whole chart to enter boost mode
95
+ * if there are 20 or more series active. When the chart is in boost mode,
96
+ * every series in it will be rendered to a common canvas. This offers
97
+ * a significant speed improvment in charts with a very high
98
+ * amount of series.
99
+ *
100
+ * Note: only available when including the boost module.
101
+ *
102
+ * @default null
103
+ * @apioption boost.seriesThreshold
104
+ */
105
+
106
+ /**
107
+ * Set the point threshold for when a series should enter boost mode.
108
+ *
109
+ * Setting it to e.g. 2000 will cause the series to enter boost mode
110
+ * when there are 2000 or more points in the series.
111
+ *
112
+ * Note: only available when including the boost module.
113
+ *
114
+ * @default 5000
115
+ * @apioption series.boostThreshold
116
+ */
117
+
118
+ /* global Float32Array */
119
+
120
+
121
+ var win = H.win,
122
+ doc = win.document,
123
+ noop = function() {},
124
+ Color = H.Color,
125
+ Series = H.Series,
126
+ seriesTypes = H.seriesTypes,
127
+ each = H.each,
128
+ extend = H.extend,
129
+ addEvent = H.addEvent,
130
+ fireEvent = H.fireEvent,
131
+ grep = H.grep,
132
+ isNumber = H.isNumber,
133
+ merge = H.merge,
134
+ pick = H.pick,
135
+ wrap = H.wrap,
136
+ plotOptions = H.getOptions().plotOptions,
137
+ CHUNK_SIZE = 50000,
138
+ index;
139
+
140
+ // Register color names since GL can't render those directly.
141
+ Color.prototype.names = {
142
+ aliceblue: '#f0f8ff',
143
+ antiquewhite: '#faebd7',
144
+ aqua: '#00ffff',
145
+ aquamarine: '#7fffd4',
146
+ azure: '#f0ffff',
147
+ beige: '#f5f5dc',
148
+ bisque: '#ffe4c4',
149
+ black: '#000000',
150
+ blanchedalmond: '#ffebcd',
151
+ blue: '#0000ff',
152
+ blueviolet: '#8a2be2',
153
+ brown: '#a52a2a',
154
+ burlywood: '#deb887',
155
+ cadetblue: '#5f9ea0',
156
+ chartreuse: '#7fff00',
157
+ chocolate: '#d2691e',
158
+ coral: '#ff7f50',
159
+ cornflowerblue: '#6495ed',
160
+ cornsilk: '#fff8dc',
161
+ crimson: '#dc143c',
162
+ cyan: '#00ffff',
163
+ darkblue: '#00008b',
164
+ darkcyan: '#008b8b',
165
+ darkgoldenrod: '#b8860b',
166
+ darkgray: '#a9a9a9',
167
+ darkgreen: '#006400',
168
+ darkkhaki: '#bdb76b',
169
+ darkmagenta: '#8b008b',
170
+ darkolivegreen: '#556b2f',
171
+ darkorange: '#ff8c00',
172
+ darkorchid: '#9932cc',
173
+ darkred: '#8b0000',
174
+ darksalmon: '#e9967a',
175
+ darkseagreen: '#8fbc8f',
176
+ darkslateblue: '#483d8b',
177
+ darkslategray: '#2f4f4f',
178
+ darkturquoise: '#00ced1',
179
+ darkviolet: '#9400d3',
180
+ deeppink: '#ff1493',
181
+ deepskyblue: '#00bfff',
182
+ dimgray: '#696969',
183
+ dodgerblue: '#1e90ff',
184
+ feldspar: '#d19275',
185
+ firebrick: '#b22222',
186
+ floralwhite: '#fffaf0',
187
+ forestgreen: '#228b22',
188
+ fuchsia: '#ff00ff',
189
+ gainsboro: '#dcdcdc',
190
+ ghostwhite: '#f8f8ff',
191
+ gold: '#ffd700',
192
+ goldenrod: '#daa520',
193
+ gray: '#808080',
194
+ green: '#008000',
195
+ greenyellow: '#adff2f',
196
+ honeydew: '#f0fff0',
197
+ hotpink: '#ff69b4',
198
+ indianred: '#cd5c5c',
199
+ indigo: '#4b0082',
200
+ ivory: '#fffff0',
201
+ khaki: '#f0e68c',
202
+ lavender: '#e6e6fa',
203
+ lavenderblush: '#fff0f5',
204
+ lawngreen: '#7cfc00',
205
+ lemonchiffon: '#fffacd',
206
+ lightblue: '#add8e6',
207
+ lightcoral: '#f08080',
208
+ lightcyan: '#e0ffff',
209
+ lightgoldenrodyellow: '#fafad2',
210
+ lightgrey: '#d3d3d3',
211
+ lightgreen: '#90ee90',
212
+ lightpink: '#ffb6c1',
213
+ lightsalmon: '#ffa07a',
214
+ lightseagreen: '#20b2aa',
215
+ lightskyblue: '#87cefa',
216
+ lightslateblue: '#8470ff',
217
+ lightslategray: '#778899',
218
+ lightsteelblue: '#b0c4de',
219
+ lightyellow: '#ffffe0',
220
+ lime: '#00ff00',
221
+ limegreen: '#32cd32',
222
+ linen: '#faf0e6',
223
+ magenta: '#ff00ff',
224
+ maroon: '#800000',
225
+ mediumaquamarine: '#66cdaa',
226
+ mediumblue: '#0000cd',
227
+ mediumorchid: '#ba55d3',
228
+ mediumpurple: '#9370d8',
229
+ mediumseagreen: '#3cb371',
230
+ mediumslateblue: '#7b68ee',
231
+ mediumspringgreen: '#00fa9a',
232
+ mediumturquoise: '#48d1cc',
233
+ mediumvioletred: '#c71585',
234
+ midnightblue: '#191970',
235
+ mintcream: '#f5fffa',
236
+ mistyrose: '#ffe4e1',
237
+ moccasin: '#ffe4b5',
238
+ navajowhite: '#ffdead',
239
+ navy: '#000080',
240
+ oldlace: '#fdf5e6',
241
+ olive: '#808000',
242
+ olivedrab: '#6b8e23',
243
+ orange: '#ffa500',
244
+ orangered: '#ff4500',
245
+ orchid: '#da70d6',
246
+ palegoldenrod: '#eee8aa',
247
+ palegreen: '#98fb98',
248
+ paleturquoise: '#afeeee',
249
+ palevioletred: '#d87093',
250
+ papayawhip: '#ffefd5',
251
+ peachpuff: '#ffdab9',
252
+ peru: '#cd853f',
253
+ pink: '#ffc0cb',
254
+ plum: '#dda0dd',
255
+ powderblue: '#b0e0e6',
256
+ purple: '#800080',
257
+ red: '#ff0000',
258
+ rosybrown: '#bc8f8f',
259
+ royalblue: '#4169e1',
260
+ saddlebrown: '#8b4513',
261
+ salmon: '#fa8072',
262
+ sandybrown: '#f4a460',
263
+ seagreen: '#2e8b57',
264
+ seashell: '#fff5ee',
265
+ sienna: '#a0522d',
266
+ silver: '#c0c0c0',
267
+ skyblue: '#87ceeb',
268
+ slateblue: '#6a5acd',
269
+ slategray: '#708090',
270
+ snow: '#fffafa',
271
+ springgreen: '#00ff7f',
272
+ steelblue: '#4682b4',
273
+ tan: '#d2b48c',
274
+ teal: '#008080',
275
+ thistle: '#d8bfd8',
276
+ tomato: '#ff6347',
277
+ turquoise: '#40e0d0',
278
+ violet: '#ee82ee',
279
+ violetred: '#d02090',
280
+ wheat: '#f5deb3',
281
+ white: '#ffffff',
282
+ whitesmoke: '#f5f5f5',
283
+ yellow: '#ffff00',
284
+ yellowgreen: '#9acd32'
285
+ };
286
+
287
+ /**
288
+ * Tolerant max() funciton
289
+ * @return {number} max value
290
+ */
291
+ function patientMax() {
292
+ var args = Array.prototype.slice.call(arguments),
293
+ r = -Number.MAX_VALUE;
294
+
295
+ each(args, function(t) {
296
+ if (typeof t !== 'undefined' && typeof t.length !== 'undefined') {
297
+ //r = r < t.length ? t.length : r;
298
+ if (t.length > 0) {
299
+ r = t.length;
300
+ return true;
301
+ }
302
+ }
303
+ });
304
+
305
+ return r;
306
+ }
307
+
308
+ /*
309
+ * Returns true if we should force chart series boosting
310
+ */
311
+ function shouldForceChartSeriesBoosting(chart) {
312
+ // If there are more than five series currently boosting,
313
+ // we should boost the whole chart to avoid running out of webgl contexts.
314
+ var sboostCount = 0,
315
+ series;
316
+
317
+ if (chart.series.length > 1) {
318
+ for (var i = 0; i < chart.series.length; i++) {
319
+ series = chart.series[i];
320
+ if (patientMax(
321
+ series.processedXData,
322
+ series.options.data,
323
+ series.points
324
+ ) >= (series.options.boostThreshold || Number.MAX_VALUE)) {
325
+ sboostCount++;
326
+ }
327
+ }
328
+ }
329
+
330
+ return sboostCount > 5;
331
+ }
332
+
333
+ /*
334
+ * Returns true if the chart is in series boost mode
335
+ * @param chart {Highchart.Chart} - the chart to check
336
+ * @returns {Boolean} - true if the chart is in series boost mode
337
+ */
338
+ function isChartSeriesBoosting(chart) {
339
+ return shouldForceChartSeriesBoosting(chart) || chart.series.length >= pick(
340
+ chart.options.boost && chart.options.boost.seriesThreshold,
341
+ 50
342
+ );
343
+ }
344
+
345
+ /*
346
+ * Returns true if the series is in boost mode
347
+ * @param series {Highchart.Series} - the series to check
348
+ * @returns {boolean} - true if the series is in boost mode
349
+ */
350
+ function isSeriesBoosting(series) {
351
+ return isChartSeriesBoosting(series.chart) ||
352
+ patientMax(
353
+ series.processedXData,
354
+ series.options.data,
355
+ series.points
356
+ ) >= (series.options.boostThreshold || Number.MAX_VALUE);
357
+ }
358
+
359
+ ////////////////////////////////////////////////////////////////////////////////
360
+ // START OF WEBGL ABSTRACTIONS
361
+
362
+ /*
363
+ * A static shader mimicing axis translation functions found in parts/Axis
364
+ * @param gl {WebGLContext} - the context in which the shader is active
365
+ */
366
+ function GLShader(gl) {
367
+ var vertShade = [
368
+ /* eslint-disable */
369
+ '#version 100',
370
+ 'precision highp float;',
371
+
372
+ 'attribute vec4 aVertexPosition;',
373
+ 'attribute vec4 aColor;',
374
+
375
+ 'varying highp vec2 position;',
376
+ 'varying highp vec4 vColor;',
377
+
378
+ 'uniform mat4 uPMatrix;',
379
+ 'uniform float pSize;',
380
+
381
+ 'uniform float translatedThreshold;',
382
+ 'uniform bool hasThreshold;',
383
+
384
+ 'uniform bool skipTranslation;',
385
+
386
+ 'uniform float xAxisTrans;',
387
+ 'uniform float xAxisMin;',
388
+ 'uniform float xAxisMinPad;',
389
+ 'uniform float xAxisPointRange;',
390
+ 'uniform float xAxisLen;',
391
+ 'uniform bool xAxisPostTranslate;',
392
+ 'uniform float xAxisOrdinalSlope;',
393
+ 'uniform float xAxisOrdinalOffset;',
394
+ 'uniform float xAxisPos;',
395
+ 'uniform bool xAxisCVSCoord;',
396
+
397
+ 'uniform float yAxisTrans;',
398
+ 'uniform float yAxisMin;',
399
+ 'uniform float yAxisMinPad;',
400
+ 'uniform float yAxisPointRange;',
401
+ 'uniform float yAxisLen;',
402
+ 'uniform bool yAxisPostTranslate;',
403
+ 'uniform float yAxisOrdinalSlope;',
404
+ 'uniform float yAxisOrdinalOffset;',
405
+ 'uniform float yAxisPos;',
406
+ 'uniform bool yAxisCVSCoord;',
407
+
408
+ 'uniform bool isBubble;',
409
+ 'uniform bool bubbleSizeByArea;',
410
+ 'uniform float bubbleZMin;',
411
+ 'uniform float bubbleZMax;',
412
+ 'uniform float bubbleZThreshold;',
413
+ 'uniform float bubbleMinSize;',
414
+ 'uniform float bubbleMaxSize;',
415
+ 'uniform bool bubbleSizeAbs;',
416
+ 'uniform bool isInverted;',
417
+
418
+ 'float bubbleRadius(){',
419
+ 'float value = aVertexPosition.w;',
420
+ 'float zMax = bubbleZMax;',
421
+ 'float zMin = bubbleZMin;',
422
+ 'float radius = 0.0;',
423
+ 'float pos = 0.0;',
424
+ 'float zRange = zMax - zMin;',
425
+
426
+ 'if (bubbleSizeAbs){',
427
+ 'value = value - bubbleZThreshold;',
428
+ 'zMax = max(zMax - bubbleZThreshold, zMin - bubbleZThreshold);',
429
+ 'zMin = 0.0;',
430
+ '}',
431
+
432
+ 'if (value < zMin){',
433
+ 'radius = bubbleZMin / 2.0 - 1.0;',
434
+ '} else {',
435
+ 'pos = zRange > 0.0 ? (value - zMin) / zRange : 0.5;',
436
+ 'if (bubbleSizeByArea && pos > 0.0){',
437
+ 'pos = sqrt(pos);',
438
+ '}',
439
+ 'radius = ceil(bubbleMinSize + pos * (bubbleMaxSize - bubbleMinSize)) / 2.0;',
440
+ '}',
441
+
442
+ 'return radius * 2.0;',
443
+ '}',
444
+
445
+ 'float translate(float val,',
446
+ 'float pointPlacement,',
447
+ 'float localA,',
448
+ 'float localMin,',
449
+ 'float minPixelPadding,',
450
+ 'float pointRange,',
451
+ 'float len,',
452
+ 'bool cvsCoord',
453
+ '){',
454
+
455
+ 'float sign = 1.0;',
456
+ 'float cvsOffset = 0.0;',
457
+
458
+ 'if (cvsCoord) {',
459
+ 'sign *= -1.0;',
460
+ 'cvsOffset = len;',
461
+ '}',
462
+
463
+ 'return sign * (val - localMin) * localA + cvsOffset + ',
464
+ '(sign * minPixelPadding);', //' + localA * pointPlacement * pointRange;',
465
+ '}',
466
+
467
+ 'float xToPixels(float value){',
468
+ 'if (skipTranslation){',
469
+ 'return value;// + xAxisPos;',
470
+ '}',
471
+
472
+ 'return translate(value, 0.0, xAxisTrans, xAxisMin, xAxisMinPad, xAxisPointRange, xAxisLen, xAxisCVSCoord);// + xAxisPos;',
473
+ '}',
474
+
475
+ 'float yToPixels(float value, float checkTreshold){',
476
+ 'float v;',
477
+ 'if (skipTranslation){',
478
+ 'v = value;// + yAxisPos;',
479
+ '} else {',
480
+ 'v = translate(value, 0.0, yAxisTrans, yAxisMin, yAxisMinPad, yAxisPointRange, yAxisLen, yAxisCVSCoord);// + yAxisPos;',
481
+ '}',
482
+ 'if (checkTreshold > 0.0 && hasThreshold) {',
483
+ 'v = min(v, translatedThreshold);',
484
+ '}',
485
+ 'return v;',
486
+ '}',
487
+
488
+ 'void main(void) {',
489
+ 'if (isBubble){',
490
+ 'gl_PointSize = bubbleRadius();',
491
+ '} else {',
492
+ 'gl_PointSize = pSize;',
493
+ '}',
494
+ //'gl_PointSize = 10.0;',
495
+ 'vColor = aColor;',
496
+
497
+ 'if (isInverted) {',
498
+ 'gl_Position = uPMatrix * vec4(xToPixels(aVertexPosition.y) + yAxisPos, yToPixels(aVertexPosition.x, aVertexPosition.z) + xAxisPos, 0.0, 1.0);',
499
+ '} else {',
500
+ 'gl_Position = uPMatrix * vec4(xToPixels(aVertexPosition.x) + xAxisPos, yToPixels(aVertexPosition.y, aVertexPosition.z) + yAxisPos, 0.0, 1.0);',
501
+ '}',
502
+ //'gl_Position = uPMatrix * vec4(aVertexPosition.x, aVertexPosition.y, 0.0, 1.0);',
503
+ '}'
504
+ /* eslint-enable */
505
+ ].join('\n'),
506
+ //Fragment shader source
507
+ fragShade = [
508
+ /* eslint-disable */
509
+ 'precision highp float;',
510
+ 'uniform vec4 fillColor;',
511
+ 'varying highp vec2 position;',
512
+ 'varying highp vec4 vColor;',
513
+ 'uniform sampler2D uSampler;',
514
+ 'uniform bool isCircle;',
515
+ 'uniform bool hasColor;',
516
+
517
+ // 'vec4 toColor(float value, vec2 point) {',
518
+ // 'return vec4(0.0, 0.0, 0.0, 0.0);',
519
+ // '}',
520
+
521
+ 'void main(void) {',
522
+ 'vec4 col = fillColor;',
523
+
524
+ 'if (hasColor) {',
525
+ 'col = vColor;',
526
+ '}',
527
+
528
+ 'if (isCircle) {',
529
+ 'gl_FragColor = col * texture2D(uSampler, gl_PointCoord.st);',
530
+ '} else {',
531
+ 'gl_FragColor = col;',
532
+ '}',
533
+ '}'
534
+ /* eslint-enable */
535
+ ].join('\n'),
536
+ uLocations = {},
537
+ //The shader program
538
+ shaderProgram,
539
+ //Uniform handle to the perspective matrix
540
+ pUniform,
541
+ //Uniform for point size
542
+ psUniform,
543
+ //Uniform for fill color
544
+ fillColorUniform,
545
+ //Uniform for isBubble
546
+ isBubbleUniform,
547
+ //Uniform for bubble abs sizing
548
+ bubbleSizeAbsUniform,
549
+ bubbleSizeAreaUniform,
550
+ //Skip translation uniform
551
+ skipTranslationUniform,
552
+ //Set to 1 if circle
553
+ isCircleUniform,
554
+ //Uniform for invertion
555
+ isInverted,
556
+ //Texture uniform
557
+ uSamplerUniform;
558
+
559
+ /* String to shader program
560
+ * @param {string} str - the program source
561
+ * @param {string} type - the program type: either `vertex` or `fragment`
562
+ * @returns {bool|shader}
563
+ */
564
+ function stringToProgram(str, type) {
565
+ var t = type === 'vertex' ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER,
566
+ shader = gl.createShader(t);
567
+
568
+ gl.shaderSource(shader, str);
569
+ gl.compileShader(shader);
570
+
571
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
572
+ //console.error('shader error:', gl.getShaderInfoLog(shader));
573
+ return false;
574
+ }
575
+ return shader;
576
+ }
577
+
578
+ /*
579
+ * Create the shader.
580
+ * Loads the shader program statically defined above
581
+ */
582
+ function createShader() {
583
+ var v = stringToProgram(vertShade, 'vertex'),
584
+ f = stringToProgram(fragShade, 'fragment');
585
+
586
+ if (!v || !f) {
587
+ shaderProgram = false;
588
+ //console.error('error creating shader program');
589
+ return false;
590
+ }
591
+
592
+ function uloc(n) {
593
+ return gl.getUniformLocation(shaderProgram, n);
594
+ }
595
+
596
+ shaderProgram = gl.createProgram();
597
+
598
+ gl.attachShader(shaderProgram, v);
599
+ gl.attachShader(shaderProgram, f);
600
+ gl.linkProgram(shaderProgram);
601
+
602
+ gl.useProgram(shaderProgram);
603
+
604
+ gl.bindAttribLocation(shaderProgram, 0, 'aVertexPosition');
605
+
606
+ pUniform = uloc('uPMatrix');
607
+ psUniform = uloc('pSize');
608
+ fillColorUniform = uloc('fillColor');
609
+ isBubbleUniform = uloc('isBubble');
610
+ bubbleSizeAbsUniform = uloc('bubbleSizeAbs');
611
+ bubbleSizeAreaUniform = uloc('bubbleSizeByArea');
612
+ uSamplerUniform = uloc('uSampler');
613
+ skipTranslationUniform = uloc('skipTranslation');
614
+ isCircleUniform = uloc('isCircle');
615
+ isInverted = uloc('isInverted');
616
+
617
+ return true;
618
+ }
619
+
620
+ /*
621
+ * Destroy the shader
622
+ */
623
+ function destroy() {
624
+ if (gl && shaderProgram) {
625
+ gl.deleteProgram(shaderProgram);
626
+ }
627
+ }
628
+
629
+ /*
630
+ * Bind the shader.
631
+ * This makes the shader the active one until another one is bound,
632
+ * or until 0 is bound.
633
+ */
634
+ function bind() {
635
+ gl.useProgram(shaderProgram);
636
+ }
637
+
638
+ /*
639
+ * Set a uniform value.
640
+ * This uses a hash map to cache uniform locations.
641
+ * @param name {string} - the name of the uniform to set
642
+ * @param val {float} - the value to set
643
+ */
644
+ function setUniform(name, val) {
645
+ var u = uLocations[name] = uLocations[name] ||
646
+ gl.getUniformLocation(shaderProgram, name);
647
+ gl.uniform1f(u, val);
648
+ }
649
+
650
+ /*
651
+ * Set the active texture
652
+ * @param texture - the texture
653
+ */
654
+ function setTexture() {
655
+ gl.uniform1i(uSamplerUniform, 0);
656
+ }
657
+
658
+ /*
659
+ * Set if inversion state
660
+ * @flag is the state
661
+ */
662
+ function setInverted(flag) {
663
+ gl.uniform1i(isInverted, flag);
664
+ }
665
+
666
+ ////////////////////////////////////////////////////////////////////////////
667
+
668
+ /*
669
+ * Enable/disable circle drawing
670
+ */
671
+ function setDrawAsCircle(flag) {
672
+ gl.uniform1i(isCircleUniform, flag ? 1 : 0);
673
+ }
674
+
675
+ /*
676
+ * Flush
677
+ */
678
+ function reset() {
679
+ gl.uniform1i(isBubbleUniform, 0);
680
+ gl.uniform1i(isCircleUniform, 0);
681
+ }
682
+
683
+ /*
684
+ * Set bubble uniforms
685
+ * @param series {Highcharts.Series} - the series to use
686
+ */
687
+ function setBubbleUniforms(series, zCalcMin, zCalcMax) {
688
+ var seriesOptions = series.options,
689
+ zMin = Number.MAX_VALUE,
690
+ zMax = -Number.MAX_VALUE;
691
+
692
+ if (series.type === 'bubble') {
693
+ zMin = pick(seriesOptions.zMin, Math.min(
694
+ zMin,
695
+ Math.max(
696
+ zCalcMin,
697
+ seriesOptions.displayNegative === false ?
698
+ seriesOptions.zThreshold : -Number.MAX_VALUE
699
+ )
700
+ ));
701
+
702
+ zMax = pick(seriesOptions.zMax, Math.max(zMax, zCalcMax));
703
+
704
+ gl.uniform1i(isBubbleUniform, 1);
705
+ gl.uniform1i(isCircleUniform, 1);
706
+ gl.uniform1i(bubbleSizeAreaUniform, series.options.sizeBy !== 'width');
707
+ gl.uniform1i(bubbleSizeAbsUniform, series.options.sizeByAbsoluteValue);
708
+
709
+ setUniform('bubbleZMin', zMin);
710
+ setUniform('bubbleZMax', zMax);
711
+ setUniform('bubbleZThreshold', series.options.zThreshold);
712
+ setUniform('bubbleMinSize', series.minPxSize);
713
+ setUniform('bubbleMaxSize', series.maxPxSize);
714
+ }
715
+ }
716
+
717
+ /*
718
+ * Set the Color uniform.
719
+ * @param color {Array<float>} - an array with RGBA values
720
+ */
721
+ function setColor(color) {
722
+ gl.uniform4f(
723
+ fillColorUniform,
724
+ color[0] / 255.0,
725
+ color[1] / 255.0,
726
+ color[2] / 255.0,
727
+ color[3]
728
+ );
729
+ }
730
+
731
+ /*
732
+ * Set skip translation
733
+ */
734
+ function setSkipTranslation(flag) {
735
+ gl.uniform1i(skipTranslationUniform, flag === true ? 1 : 0);
736
+ }
737
+
738
+ /*
739
+ * Set the perspective matrix
740
+ * @param m {Matrix4x4} - the matrix
741
+ */
742
+ function setPMatrix(m) {
743
+ gl.uniformMatrix4fv(pUniform, false, m);
744
+ }
745
+
746
+ /*
747
+ * Set the point size.
748
+ * @param p {float} - point size
749
+ */
750
+ function setPointSize(p) {
751
+ gl.uniform1f(psUniform, p);
752
+ }
753
+
754
+ /*
755
+ * Get the shader program handle
756
+ * @returns {GLInt} - the handle for the program
757
+ */
758
+ function getProgram() {
759
+ return shaderProgram;
760
+ }
761
+
762
+ if (gl) {
763
+ createShader();
764
+ }
765
+
766
+ return {
767
+ psUniform: function() {
768
+ return psUniform;
769
+ },
770
+ pUniform: function() {
771
+ return pUniform;
772
+ },
773
+ fillColorUniform: function() {
774
+ return fillColorUniform;
775
+ },
776
+ setBubbleUniforms: setBubbleUniforms,
777
+ bind: bind,
778
+ program: getProgram,
779
+ create: createShader,
780
+ setUniform: setUniform,
781
+ setPMatrix: setPMatrix,
782
+ setColor: setColor,
783
+ setPointSize: setPointSize,
784
+ setSkipTranslation: setSkipTranslation,
785
+ setTexture: setTexture,
786
+ setDrawAsCircle: setDrawAsCircle,
787
+ reset: reset,
788
+ setInverted: setInverted,
789
+ destroy: destroy
790
+ };
791
+ }
792
+
793
+ /*
794
+ * Vertex Buffer abstraction
795
+ * A vertex buffer is a set of vertices which are passed to the GPU
796
+ * in a single call.
797
+ * @param gl {WebGLContext} - the context in which to create the buffer
798
+ * @param shader {GLShader} - the shader to use
799
+ */
800
+ function GLVertexBuffer(gl, shader, dataComponents /*, type */ ) {
801
+ var buffer = false,
802
+ vertAttribute = false,
803
+ components = dataComponents || 2,
804
+ preAllocated = false,
805
+ iterator = 0,
806
+ data;
807
+
808
+ // type = type || 'float';
809
+
810
+ function destroy() {
811
+ if (buffer) {
812
+ gl.deleteBuffer(buffer);
813
+ }
814
+ }
815
+
816
+ /*
817
+ * Build the buffer
818
+ * @param dataIn {Array<float>} - a 0 padded array of indices
819
+ * @param attrib {String} - the name of the Attribute to bind the buffer to
820
+ * @param dataComponents {Integer} - the number of components per. indice
821
+ */
822
+ function build(dataIn, attrib, dataComponents) {
823
+
824
+ data = dataIn || [];
825
+
826
+ if ((!data || data.length === 0) && !preAllocated) {
827
+ //console.error('trying to render empty vbuffer');
828
+ buffer = false;
829
+ return false;
830
+ }
831
+
832
+ components = dataComponents || components;
833
+
834
+ if (buffer) {
835
+ gl.deleteBuffer(buffer);
836
+ }
837
+
838
+ buffer = gl.createBuffer();
839
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
840
+ gl.bufferData(
841
+ gl.ARRAY_BUFFER,
842
+ preAllocated || new Float32Array(data),
843
+ gl.STATIC_DRAW
844
+ );
845
+
846
+ // gl.bindAttribLocation(shader.program(), 0, 'aVertexPosition');
847
+ vertAttribute = gl.getAttribLocation(shader.program(), attrib);
848
+ gl.enableVertexAttribArray(vertAttribute);
849
+
850
+ return true;
851
+ }
852
+
853
+ /*
854
+ * Bind the buffer
855
+ */
856
+ function bind() {
857
+ if (!buffer) {
858
+ return false;
859
+ }
860
+
861
+ // gl.bindAttribLocation(shader.program(), 0, 'aVertexPosition');
862
+ //gl.enableVertexAttribArray(vertAttribute);
863
+ //gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
864
+ gl.vertexAttribPointer(vertAttribute, components, gl.FLOAT, false, 0, 0);
865
+ //gl.enableVertexAttribArray(vertAttribute);
866
+ }
867
+
868
+ /*
869
+ * Render the buffer
870
+ * @param from {Integer} - the start indice
871
+ * @param to {Integer} - the end indice
872
+ * @param drawMode {String} - the draw mode
873
+ */
874
+ function render(from, to, drawMode) {
875
+ var length = preAllocated ? preAllocated.length : data.length;
876
+
877
+ if (!buffer) {
878
+ return false;
879
+ }
880
+
881
+ if (!length) {
882
+ return false;
883
+ }
884
+
885
+ if (!from || from > length || from < 0) {
886
+ from = 0;
887
+ }
888
+
889
+ if (!to || to > length) {
890
+ to = length;
891
+ }
892
+
893
+ drawMode = drawMode || 'points';
894
+
895
+ gl.drawArrays(
896
+ gl[drawMode.toUpperCase()],
897
+ from / components,
898
+ (to - from) / components
899
+ );
900
+
901
+ return true;
902
+ }
903
+
904
+ function push(x, y, a, b) {
905
+ if (preAllocated) { // && iterator <= preAllocated.length - 4) {
906
+ preAllocated[++iterator] = x;
907
+ preAllocated[++iterator] = y;
908
+ preAllocated[++iterator] = a;
909
+ preAllocated[++iterator] = b;
910
+ }
911
+ }
912
+
913
+ /*
914
+ * Note about pre-allocated buffers:
915
+ * - This is slower for charts with many series
916
+ */
917
+ function allocate(size) {
918
+ size *= 4;
919
+ iterator = -1;
920
+
921
+ //if (!preAllocated || (preAllocated && preAllocated.length !== size)) {
922
+ preAllocated = new Float32Array(size);
923
+ //}
924
+ }
925
+
926
+ ////////////////////////////////////////////////////////////////////////////
927
+ return {
928
+ destroy: destroy,
929
+ bind: bind,
930
+ data: data,
931
+ build: build,
932
+ render: render,
933
+ allocate: allocate,
934
+ push: push
935
+ };
936
+ }
937
+
938
+ /* Main renderer. Used to render series.
939
+ * Notes to self:
940
+ * - May be able to build a point map by rendering to a separate canvas
941
+ * and encoding values in the color data.
942
+ * - Need to figure out a way to transform the data quicker
943
+ */
944
+ function GLRenderer(postRenderCallback) {
945
+ var // Shader
946
+ shader = false,
947
+ // Vertex buffers - keyed on shader attribute name
948
+ vbuffer = false,
949
+ // Opengl context
950
+ gl = false,
951
+ // Width of our viewport in pixels
952
+ width = 0,
953
+ // Height of our viewport in pixels
954
+ height = 0,
955
+ // The data to render - array of coordinates
956
+ data = false,
957
+ // The marker data
958
+ markerData = false,
959
+ // Is the texture ready?
960
+ textureIsReady = false,
961
+ // Exports
962
+ exports = {},
963
+ // Is it inited?
964
+ isInited = false,
965
+ // The series stack
966
+ series = [],
967
+ // Texture for circles
968
+ circleTexture = doc.createElement('canvas'),
969
+ // Context for circle texture
970
+ circleCtx = circleTexture.getContext('2d'),
971
+ // Handle for the circle texture
972
+ circleTextureHandle,
973
+ // Things to draw as "rectangles" (i.e lines)
974
+ asBar = {
975
+ 'column': true,
976
+ 'area': true
977
+ },
978
+ asCircle = {
979
+ 'scatter': true,
980
+ 'bubble': true
981
+ },
982
+ //Render settings
983
+ settings = {
984
+ pointSize: 1,
985
+ lineWidth: 3,
986
+ fillColor: '#AA00AA',
987
+ useAlpha: true,
988
+ usePreallocated: false,
989
+ useGPUTranslations: false,
990
+ timeRendering: false,
991
+ timeSeriesProcessing: false,
992
+ timeSetup: false
993
+ };
994
+
995
+ ////////////////////////////////////////////////////////////////////////////
996
+
997
+ function setOptions(options) {
998
+ merge(true, settings, options);
999
+ }
1000
+
1001
+ function seriesPointCount(series) {
1002
+ var isStacked,
1003
+ xData,
1004
+ s;
1005
+
1006
+ if (isSeriesBoosting(series)) {
1007
+ isStacked = !!series.options.stacking;
1008
+ xData = series.xData || series.options.xData || series.processedXData;
1009
+ s = (isStacked ? series.data : (xData || series.options.data)).length;
1010
+
1011
+ if (series.type === 'treemap') {
1012
+ s *= 12;
1013
+ } else if (series.type === 'heatmap') {
1014
+ s *= 6;
1015
+ } else if (asBar[series.type]) {
1016
+ s *= 2;
1017
+ }
1018
+
1019
+ return s;
1020
+ }
1021
+
1022
+ return 0;
1023
+ }
1024
+
1025
+ /* Allocate a float buffer to fit all series */
1026
+ function allocateBuffer(chart) {
1027
+ var s = 0;
1028
+
1029
+ if (!settings.usePreallocated) {
1030
+ return;
1031
+ }
1032
+
1033
+ each(chart.series, function(series) {
1034
+ if (isSeriesBoosting(series)) {
1035
+ s += seriesPointCount(series);
1036
+ }
1037
+ });
1038
+
1039
+ vbuffer.allocate(s);
1040
+ }
1041
+
1042
+ function allocateBufferForSingleSeries(series) {
1043
+ var s = 0;
1044
+
1045
+ if (!settings.usePreallocated) {
1046
+ return;
1047
+ }
1048
+
1049
+ if (isSeriesBoosting(series)) {
1050
+ s = seriesPointCount(series);
1051
+ }
1052
+
1053
+ vbuffer.allocate(s);
1054
+ }
1055
+
1056
+ /*
1057
+ * Returns an orthographic perspective matrix
1058
+ * @param {number} width - the width of the viewport in pixels
1059
+ * @param {number} height - the height of the viewport in pixels
1060
+ */
1061
+ function orthoMatrix(width, height) {
1062
+ var near = 0,
1063
+ far = 1;
1064
+
1065
+ return [
1066
+ 2 / width, 0, 0, 0,
1067
+ 0, -(2 / height), 0, 0,
1068
+ 0, 0, -2 / (far - near), 0, -1, 1, -(far + near) / (far - near), 1
1069
+ ];
1070
+ }
1071
+
1072
+ /*
1073
+ * Clear the depth and color buffer
1074
+ */
1075
+ function clear() {
1076
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
1077
+ }
1078
+
1079
+ /*
1080
+ * Get the WebGL context
1081
+ * @returns {WebGLContext} - the context
1082
+ */
1083
+ function getGL() {
1084
+ return gl;
1085
+ }
1086
+
1087
+ /*
1088
+ * Push data for a single series
1089
+ * This calculates additional vertices and transforms the data to be
1090
+ * aligned correctly in memory
1091
+ */
1092
+ function pushSeriesData(series, inst) {
1093
+ var isRange = series.pointArrayMap &&
1094
+ series.pointArrayMap.join(',') === 'low,high',
1095
+ chart = series.chart,
1096
+ options = series.options,
1097
+ isStacked = !!options.stacking,
1098
+ rawData = options.data,
1099
+ xExtremes = series.xAxis.getExtremes(),
1100
+ xMin = xExtremes.min,
1101
+ xMax = xExtremes.max,
1102
+ yExtremes = series.yAxis.getExtremes(),
1103
+ yMin = yExtremes.min,
1104
+ yMax = yExtremes.max,
1105
+ xData = series.xData || options.xData || series.processedXData,
1106
+ yData = series.yData || options.yData || series.processedYData,
1107
+ zData = series.zData || options.zData || series.processedZData,
1108
+ yAxis = series.yAxis,
1109
+ xAxis = series.xAxis,
1110
+ useRaw = !xData || xData.length === 0,
1111
+ // threshold = options.threshold,
1112
+ // yBottom = chart.yAxis[0].getThreshold(threshold),
1113
+ // hasThreshold = isNumber(threshold),
1114
+ // colorByPoint = series.options.colorByPoint,
1115
+ // This is required for color by point, so make sure this is
1116
+ // uncommented if enabling that
1117
+ // colorIndex = 0,
1118
+ // Required for color axis support
1119
+ // caxis,
1120
+ // connectNulls = options.connectNulls,
1121
+ // For some reason eslint doesn't pick up that this is actually used
1122
+ maxVal, //eslint-disable-line no-unused-vars
1123
+ points = series.points || false,
1124
+ lastX = false,
1125
+ minVal,
1126
+ color,
1127
+ scolor,
1128
+ sdata = isStacked ? series.data : (xData || rawData),
1129
+ closestLeft = {
1130
+ x: Number.MIN_VALUE,
1131
+ y: 0
1132
+ },
1133
+ closestRight = {
1134
+ x: Number.MIN_VALUE,
1135
+ y: 0
1136
+ };
1137
+
1138
+ if (options.boostData && options.boostData.length > 0) {
1139
+ return;
1140
+ }
1141
+
1142
+ series.closestPointRangePx = Number.MAX_VALUE;
1143
+
1144
+ // Push color to color buffer - need to do this per. vertex
1145
+ function pushColor(color) {
1146
+ if (color) {
1147
+ inst.colorData.push(color[0]);
1148
+ inst.colorData.push(color[1]);
1149
+ inst.colorData.push(color[2]);
1150
+ inst.colorData.push(color[3]);
1151
+ }
1152
+ }
1153
+
1154
+ //Push a vertice to the data buffer
1155
+ function vertice(x, y, checkTreshold, pointSize, color) {
1156
+ pushColor(color);
1157
+ if (settings.usePreallocated) {
1158
+ vbuffer.push(x, y, checkTreshold ? 1 : 0, pointSize || 1);
1159
+ } else {
1160
+ data.push(x);
1161
+ data.push(y);
1162
+ data.push(checkTreshold ? 1 : 0);
1163
+ data.push(pointSize || 1);
1164
+ }
1165
+ }
1166
+
1167
+ // Push a rectangle to the data buffer
1168
+ function pushRect(x, y, w, h, color) {
1169
+ pushColor(color);
1170
+ vertice(x + w, y);
1171
+ pushColor(color);
1172
+ vertice(x, y);
1173
+ pushColor(color);
1174
+ vertice(x, y + h);
1175
+
1176
+ pushColor(color);
1177
+ vertice(x, y + h);
1178
+ pushColor(color);
1179
+ vertice(x + w, y + h);
1180
+ pushColor(color);
1181
+ vertice(x + w, y);
1182
+ }
1183
+
1184
+ // Special case for point shapes
1185
+ if (points && points.length > 0) {
1186
+
1187
+ // If we're doing points, we assume that the points are already
1188
+ // translated, so we skip the shader translation.
1189
+ inst.skipTranslation = true;
1190
+ // Force triangle draw mode
1191
+ inst.drawMode = 'triangles';
1192
+
1193
+ // We don't have a z component in the shader, so we need to sort.
1194
+ if (points[0].node && points[0].node.levelDynamic) {
1195
+ points.sort(function(a, b) {
1196
+ if (a.node) {
1197
+ if (a.node.levelDynamic > b.node.levelDynamic) {
1198
+ return 1;
1199
+ } else if (a.node.levelDynamic < b.node.levelDynamic) {
1200
+ return -1;
1201
+ }
1202
+ }
1203
+ return 0;
1204
+ });
1205
+ }
1206
+
1207
+ each(points, function(point) {
1208
+ var plotY = point.plotY,
1209
+ shapeArgs,
1210
+ swidth,
1211
+ pointAttr;
1212
+
1213
+ if (plotY !== undefined && !isNaN(plotY) && point.y !== null) {
1214
+ shapeArgs = point.shapeArgs;
1215
+
1216
+
1217
+ pointAttr = point.series.pointAttribs(point);
1218
+
1219
+ swidth = pointAttr['stroke-width'] || 0;
1220
+
1221
+ // Handle point colors
1222
+ color = H.color(pointAttr.fill).rgba;
1223
+ color[0] /= 255.0;
1224
+ color[1] /= 255.0;
1225
+ color[2] /= 255.0;
1226
+
1227
+ // So there are two ways of doing this. Either we can
1228
+ // create a rectangle of two triangles, or we can do a
1229
+ // point and use point size. Latter is faster, but
1230
+ // only supports squares. So we're doing triangles.
1231
+ // We could also use one color per. vertice to get
1232
+ // better color interpolation.
1233
+
1234
+ // If there's stroking, we do an additional rect
1235
+ //if (pointAttr.stroke !== 'none' && swidth && swidth > 0) {
1236
+ if (series.type === 'treemap') {
1237
+ swidth = swidth || 1;
1238
+ scolor = H.color(pointAttr.stroke).rgba;
1239
+
1240
+ scolor[0] /= 255.0;
1241
+ scolor[1] /= 255.0;
1242
+ scolor[2] /= 255.0;
1243
+
1244
+ pushRect(
1245
+ shapeArgs.x,
1246
+ shapeArgs.y,
1247
+ shapeArgs.width,
1248
+ shapeArgs.height,
1249
+ scolor
1250
+ );
1251
+
1252
+ swidth /= 2;
1253
+ }
1254
+ // } else {
1255
+ // swidth = 0;
1256
+ // }
1257
+
1258
+ pushRect(
1259
+ shapeArgs.x + swidth,
1260
+ shapeArgs.y + swidth,
1261
+ shapeArgs.width - (swidth * 2),
1262
+ shapeArgs.height - (swidth * 2),
1263
+ color
1264
+ );
1265
+ }
1266
+ });
1267
+
1268
+ return;
1269
+ }
1270
+
1271
+ // Extract color axis
1272
+ // each(chart.axes || [], function (a) {
1273
+ // if (H.ColorAxis && a instanceof H.ColorAxis) {
1274
+ // caxis = a;
1275
+ // }
1276
+ // });
1277
+
1278
+ each(sdata, function(d, i) {
1279
+ var x,
1280
+ y,
1281
+ z,
1282
+ px = false,
1283
+ nx = false,
1284
+ // This is in fact used.
1285
+ low, //eslint-disable-line no-unused-vars
1286
+ chartDestroyed = typeof chart.index === 'undefined',
1287
+ nextInside = false,
1288
+ prevInside = false,
1289
+ pcolor = false,
1290
+ drawAsBar = asBar[series.type],
1291
+ isXInside = false,
1292
+ isYInside = true;
1293
+
1294
+ if (chartDestroyed) {
1295
+ return false;
1296
+ }
1297
+
1298
+ // Uncomment this to enable color by point.
1299
+ // This currently left disabled as the charts look really ugly
1300
+ // when enabled and there's a lot of points.
1301
+ // Leaving in for the future (tm).
1302
+ // if (colorByPoint) {
1303
+ // colorIndex = ++colorIndex % series.chart.options.colors.length;
1304
+ // pcolor = toRGBAFast(series.chart.options.colors[colorIndex]);
1305
+ // pcolor[0] /= 255.0;
1306
+ // pcolor[1] /= 255.0;
1307
+ // pcolor[2] /= 255.0;
1308
+ // }
1309
+
1310
+ if (useRaw) {
1311
+ x = d[0];
1312
+ y = d[1];
1313
+
1314
+ if (sdata[i + 1]) {
1315
+ nx = sdata[i + 1][0];
1316
+ }
1317
+
1318
+ if (sdata[i - 1]) {
1319
+ px = sdata[i - 1][0];
1320
+ }
1321
+
1322
+ if (d.length >= 3) {
1323
+ z = d[2];
1324
+
1325
+ if (d[2] > inst.zMax) {
1326
+ inst.zMax = d[2];
1327
+ }
1328
+
1329
+ if (d[2] < inst.zMin) {
1330
+ inst.zMin = d[2];
1331
+ }
1332
+ }
1333
+
1334
+ } else {
1335
+ x = d;
1336
+ y = yData[i];
1337
+
1338
+ if (sdata[i + 1]) {
1339
+ nx = sdata[i + 1];
1340
+ }
1341
+
1342
+ if (sdata[i - 1]) {
1343
+ px = sdata[i - 1];
1344
+ }
1345
+
1346
+ if (zData && zData.length) {
1347
+ z = zData[i];
1348
+
1349
+ if (zData[i] > inst.zMax) {
1350
+ inst.zMax = zData[i];
1351
+ }
1352
+
1353
+ if (zData[i] < inst.zMin) {
1354
+ inst.zMin = zData[i];
1355
+ }
1356
+ }
1357
+ }
1358
+
1359
+ if (nx && nx >= xMin && nx <= xMax) {
1360
+ nextInside = true;
1361
+ }
1362
+
1363
+ if (px && px >= xMin && px <= xMax) {
1364
+ prevInside = true;
1365
+ }
1366
+
1367
+ if (isRange) {
1368
+ if (useRaw) {
1369
+ y = d.slice(1, 3);
1370
+ }
1371
+
1372
+ low = y[0];
1373
+ y = y[1];
1374
+
1375
+ } else if (isStacked) {
1376
+ x = d.x;
1377
+ y = d.stackY;
1378
+ low = y - d.y;
1379
+ }
1380
+
1381
+ if (!series.requireSorting) {
1382
+ isYInside = y >= yMin && y <= yMax;
1383
+ }
1384
+
1385
+ if (x > xMax && closestRight.x < xMax) {
1386
+ closestRight.x = x;
1387
+ closestRight.y = y;
1388
+ }
1389
+
1390
+ if (x < xMin && closestLeft.x < xMin) {
1391
+ closestLeft.x = x;
1392
+ closestLeft.y = y;
1393
+ }
1394
+
1395
+ if (y !== 0 && (!y || !isYInside)) {
1396
+ return;
1397
+ }
1398
+
1399
+ if (x >= xMin && x <= xMax) {
1400
+ isXInside = true;
1401
+ }
1402
+
1403
+ if (!isXInside && !nextInside && !prevInside) {
1404
+ return;
1405
+ }
1406
+
1407
+ // Skip translations - temporary floating point fix
1408
+ if (!settings.useGPUTranslations) {
1409
+ inst.skipTranslation = true;
1410
+ x = xAxis.toPixels(x, true);
1411
+ y = yAxis.toPixels(y, true);
1412
+ }
1413
+
1414
+ if (drawAsBar) {
1415
+
1416
+ maxVal = y;
1417
+ minVal = 0;
1418
+
1419
+ if (y < 0) {
1420
+ minVal = y;
1421
+ y = 0;
1422
+ }
1423
+
1424
+ if (!settings.useGPUTranslations) {
1425
+ minVal = yAxis.toPixels(minVal, true);
1426
+ }
1427
+
1428
+ // Need to add an extra point here
1429
+ vertice(x, minVal, 0, 0, pcolor);
1430
+ }
1431
+
1432
+ // No markers on out of bounds things.
1433
+ // Out of bound things are shown if and only if the next
1434
+ // or previous point is inside the rect.
1435
+ if (inst.hasMarkers) { // && isXInside) {
1436
+ // x = H.correctFloat(
1437
+ // Math.min(Math.max(-1e5, xAxis.translate(
1438
+ // x,
1439
+ // 0,
1440
+ // 0,
1441
+ // 0,
1442
+ // 1,
1443
+ // 0.5,
1444
+ // false
1445
+ // )), 1e5)
1446
+ // );
1447
+
1448
+ if (lastX !== false) {
1449
+ series.closestPointRangePx = Math.min(
1450
+ series.closestPointRangePx,
1451
+ Math.abs(x - lastX)
1452
+ );
1453
+ }
1454
+ }
1455
+
1456
+ vertice(
1457
+ x,
1458
+ y,
1459
+ 0,
1460
+ series.type === 'bubble' ? (z || 1) : 2,
1461
+ pcolor
1462
+ );
1463
+
1464
+ // Uncomment this to support color axis.
1465
+ // if (caxis) {
1466
+ // color = H.color(caxis.toColor(y)).rgba;
1467
+
1468
+ // inst.colorData.push(color[0] / 255.0);
1469
+ // inst.colorData.push(color[1] / 255.0);
1470
+ // inst.colorData.push(color[2] / 255.0);
1471
+ // inst.colorData.push(color[3]);
1472
+ // }
1473
+
1474
+ lastX = x;
1475
+
1476
+ //return true;
1477
+ });
1478
+
1479
+ function pushSupplementPoint(point) {
1480
+ if (!settings.useGPUTranslations) {
1481
+ inst.skipTranslation = true;
1482
+ point.x = xAxis.toPixels(point.x, true);
1483
+ point.y = yAxis.toPixels(point.y, true);
1484
+ }
1485
+
1486
+ // We should only do this for lines, and we should ignore markers
1487
+ // since there's no point here that would have a marker.
1488
+
1489
+ vertice(
1490
+ point.x,
1491
+ point.y,
1492
+ 0,
1493
+ 2
1494
+ );
1495
+ }
1496
+
1497
+ if (!lastX) {
1498
+ // There are no points within the selected range
1499
+ pushSupplementPoint(closestLeft);
1500
+ pushSupplementPoint(closestRight);
1501
+ }
1502
+ }
1503
+
1504
+ /*
1505
+ * Push a series to the renderer
1506
+ * If we render the series immediatly, we don't have to loop later
1507
+ * @param s {Highchart.Series} - the series to push
1508
+ */
1509
+ function pushSeries(s) {
1510
+ if (series.length > 0) {
1511
+ series[series.length - 1].to = data.length;
1512
+ if (series[series.length - 1].hasMarkers) {
1513
+ series[series.length - 1].markerTo = markerData.length;
1514
+ }
1515
+ }
1516
+
1517
+ if (settings.timeSeriesProcessing) {
1518
+ console.time('building ' + s.type + ' series'); //eslint-disable-line no-console
1519
+ }
1520
+
1521
+ series.push({
1522
+ from: data.length,
1523
+ markerFrom: markerData.length,
1524
+ // Push RGBA values to this array to use per. point coloring.
1525
+ // It should be 0-padded, so each component should be pushed in
1526
+ // succession.
1527
+ colorData: [],
1528
+ series: s,
1529
+ zMin: Number.MAX_VALUE,
1530
+ zMax: -Number.MAX_VALUE,
1531
+ hasMarkers: s.options.marker ? s.options.marker.enabled !== false : false,
1532
+ showMarksers: true,
1533
+ drawMode: ({
1534
+ 'area': 'lines',
1535
+ 'arearange': 'lines',
1536
+ 'areaspline': 'line_strip',
1537
+ 'column': 'lines',
1538
+ 'line': 'line_strip',
1539
+ 'scatter': 'points',
1540
+ 'heatmap': 'triangles',
1541
+ 'treemap': 'triangles',
1542
+ 'bubble': 'points'
1543
+ })[s.type] || 'line_strip'
1544
+ });
1545
+
1546
+ // Add the series data to our buffer(s)
1547
+ pushSeriesData(s, series[series.length - 1]);
1548
+
1549
+ if (settings.timeSeriesProcessing) {
1550
+ console.timeEnd('building ' + s.type + ' series'); //eslint-disable-line no-console
1551
+ }
1552
+ }
1553
+
1554
+ /*
1555
+ * Flush the renderer.
1556
+ * This removes pushed series and vertices.
1557
+ * Should be called after clearing and before rendering
1558
+ */
1559
+ function flush() {
1560
+ series = [];
1561
+ exports.data = data = [];
1562
+ markerData = [];
1563
+ }
1564
+
1565
+ /*
1566
+ * Pass x-axis to shader
1567
+ * @param axis {Highcharts.Axis} - the x-axis
1568
+ */
1569
+ function setXAxis(axis) {
1570
+ if (!shader) {
1571
+ return;
1572
+ }
1573
+
1574
+ shader.setUniform('xAxisTrans', axis.transA);
1575
+ shader.setUniform('xAxisMin', axis.min);
1576
+ shader.setUniform('xAxisMinPad', axis.minPixelPadding);
1577
+ shader.setUniform('xAxisPointRange', axis.pointRange);
1578
+ shader.setUniform('xAxisLen', axis.len);
1579
+ shader.setUniform('xAxisPos', axis.pos);
1580
+ shader.setUniform('xAxisCVSCoord', !axis.horiz);
1581
+ }
1582
+
1583
+ /*
1584
+ * Pass y-axis to shader
1585
+ * @param axis {Highcharts.Axis} - the y-axis
1586
+ */
1587
+ function setYAxis(axis) {
1588
+ if (!shader) {
1589
+ return;
1590
+ }
1591
+
1592
+ shader.setUniform('yAxisTrans', axis.transA);
1593
+ shader.setUniform('yAxisMin', axis.min);
1594
+ shader.setUniform('yAxisMinPad', axis.minPixelPadding);
1595
+ shader.setUniform('yAxisPointRange', axis.pointRange);
1596
+ shader.setUniform('yAxisLen', axis.len);
1597
+ shader.setUniform('yAxisPos', axis.pos);
1598
+ shader.setUniform('yAxisCVSCoord', !axis.horiz);
1599
+ }
1600
+
1601
+ /*
1602
+ * Set the translation threshold
1603
+ * @param has {boolean} - has threshold flag
1604
+ * @param translation {Float} - the threshold
1605
+ */
1606
+ function setThreshold(has, translation) {
1607
+ shader.setUniform('hasThreshold', has);
1608
+ shader.setUniform('translatedThreshold', translation);
1609
+ }
1610
+
1611
+ /*
1612
+ * Render the data
1613
+ * This renders all pushed series.
1614
+ */
1615
+ function render(chart) {
1616
+
1617
+ if (chart) {
1618
+ if (!chart.chartHeight || !chart.chartWidth) {
1619
+ //chart.setChartSize();
1620
+ }
1621
+
1622
+ width = chart.chartWidth || 800;
1623
+ height = chart.chartHeight || 400;
1624
+ } else {
1625
+ return false;
1626
+ }
1627
+
1628
+ if (!gl || !width || !height) {
1629
+ return false;
1630
+ }
1631
+
1632
+ if (settings.timeRendering) {
1633
+ console.time('gl rendering'); //eslint-disable-line no-console
1634
+ }
1635
+
1636
+ shader.bind();
1637
+
1638
+ gl.viewport(0, 0, width, height);
1639
+ shader.setPMatrix(orthoMatrix(width, height));
1640
+
1641
+ if (settings.lineWidth > 1 && !H.isMS) {
1642
+ gl.lineWidth(settings.lineWidth);
1643
+ }
1644
+
1645
+ vbuffer.build(exports.data, 'aVertexPosition', 4);
1646
+ vbuffer.bind();
1647
+
1648
+ if (textureIsReady) {
1649
+ gl.bindTexture(gl.TEXTURE_2D, circleTextureHandle);
1650
+ shader.setTexture(circleTextureHandle);
1651
+ }
1652
+
1653
+ shader.setInverted(chart.options.chart ? chart.options.chart.inverted : false);
1654
+
1655
+ // Render the series
1656
+ each(series, function(s, si) {
1657
+ var options = s.series.options,
1658
+ threshold = options.threshold,
1659
+ hasThreshold = isNumber(threshold),
1660
+ yBottom = s.series.yAxis.getThreshold(threshold),
1661
+ translatedThreshold = yBottom,
1662
+ cbuffer,
1663
+ showMarkers = pick(
1664
+ options.marker ? options.marker.enabled : null,
1665
+ s.series.xAxis.isRadial ? true : null,
1666
+ s.series.closestPointRangePx >
1667
+ 2 * ((
1668
+ options.marker ?
1669
+ options.marker.radius :
1670
+ 10
1671
+ ) || 10)
1672
+ ),
1673
+ fillColor = s.series.fillOpacity ?
1674
+ new Color(s.series.color).setOpacity(
1675
+ pick(options.fillOpacity, 0.85)
1676
+ ).get() :
1677
+ s.series.color,
1678
+ color;
1679
+
1680
+ vbuffer.bind();
1681
+
1682
+ if (options.colorByPoint) {
1683
+ fillColor = s.series.chart.options.colors[si];
1684
+ }
1685
+
1686
+ color = H.color(fillColor).rgba;
1687
+
1688
+ if (!settings.useAlpha) {
1689
+ color[3] = 1.0;
1690
+ }
1691
+
1692
+ //Blending
1693
+ if (options.boostBlending === 'add') {
1694
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
1695
+ gl.blendEquation(gl.FUNC_ADD);
1696
+
1697
+ } else if (options.boostBlending === 'mult') {
1698
+ gl.blendFunc(gl.DST_COLOR, gl.ZERO);
1699
+
1700
+ } else if (options.boostBlending === 'darken') {
1701
+ gl.blendFunc(gl.ONE, gl.ONE);
1702
+ gl.blendEquation(gl.FUNC_MIN);
1703
+
1704
+ } else {
1705
+ //gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);//, gl.ONE, gl.ZERO);
1706
+ //gl.blendEquation(gl.FUNC_ADD);
1707
+ gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
1708
+ }
1709
+
1710
+ shader.reset();
1711
+
1712
+ // If there are entries in the colorData buffer, build and bind it.
1713
+ if (s.colorData.length > 0) {
1714
+ shader.setUniform('hasColor', 1.0);
1715
+ cbuffer = GLVertexBuffer(gl, shader); //eslint-disable-line new-cap
1716
+ cbuffer.build(s.colorData, 'aColor', 4);
1717
+ cbuffer.bind();
1718
+ }
1719
+
1720
+ // Set series specific uniforms
1721
+ shader.setColor(color);
1722
+ setXAxis(s.series.xAxis);
1723
+ setYAxis(s.series.yAxis);
1724
+ setThreshold(hasThreshold, translatedThreshold);
1725
+
1726
+ if (s.drawMode === 'points') {
1727
+ if (options.marker && options.marker.radius) {
1728
+ shader.setPointSize(options.marker.radius * 2.0);
1729
+ } else {
1730
+ shader.setPointSize(1);
1731
+ }
1732
+ }
1733
+
1734
+ // If set to true, the toPixels translations in the shader
1735
+ // is skipped, i.e it's assumed that the value is a pixel coord.
1736
+ shader.setSkipTranslation(s.skipTranslation);
1737
+
1738
+ if (s.series.type === 'bubble') {
1739
+ shader.setBubbleUniforms(s.series, s.zMin, s.zMax);
1740
+ }
1741
+
1742
+ shader.setDrawAsCircle((asCircle[s.series.type] && textureIsReady) || false);
1743
+
1744
+ // Do the actual rendering
1745
+ vbuffer.render(s.from, s.to, s.drawMode);
1746
+
1747
+ if (s.hasMarkers && showMarkers) {
1748
+ if (options.marker && options.marker.radius) {
1749
+ shader.setPointSize(options.marker.radius * 2.0);
1750
+ } else {
1751
+ shader.setPointSize(10);
1752
+ }
1753
+ shader.setDrawAsCircle(true);
1754
+ vbuffer.render(s.from, s.to, 'POINTS');
1755
+ }
1756
+ });
1757
+
1758
+ vbuffer.destroy();
1759
+
1760
+ if (settings.timeRendering) {
1761
+ console.timeEnd('gl rendering'); //eslint-disable-line no-console
1762
+ }
1763
+
1764
+ flush();
1765
+
1766
+ if (postRenderCallback) {
1767
+ postRenderCallback();
1768
+ }
1769
+ }
1770
+
1771
+ /*
1772
+ * Render the data when ready
1773
+ */
1774
+ function renderWhenReady(chart) {
1775
+ clear();
1776
+
1777
+ if (chart.renderer.forExport) {
1778
+ return render(chart);
1779
+ }
1780
+
1781
+ if (isInited) {
1782
+ render(chart);
1783
+ } else {
1784
+ setTimeout(function() {
1785
+ renderWhenReady(chart);
1786
+ }, 1);
1787
+ }
1788
+ }
1789
+
1790
+ /*
1791
+ * Set the viewport size in pixels
1792
+ * Creates an orthographic perspective matrix and applies it.
1793
+ * @param w {Integer} - the width of the viewport
1794
+ * @param h {Integer} - the height of the viewport
1795
+ */
1796
+ function setSize(w, h) {
1797
+ // Skip if there's no change
1798
+ if (width === w && h === h) {
1799
+ return;
1800
+ }
1801
+
1802
+ width = w;
1803
+ height = h;
1804
+
1805
+ shader.bind();
1806
+ shader.setPMatrix(orthoMatrix(width, height));
1807
+ }
1808
+
1809
+ /*
1810
+ * Init OpenGL
1811
+ * @param canvas {HTMLCanvas} - the canvas to render to
1812
+ */
1813
+ function init(canvas, noFlush) {
1814
+ var i = 0,
1815
+ contexts = [
1816
+ 'webgl',
1817
+ 'experimental-webgl',
1818
+ 'moz-webgl',
1819
+ 'webkit-3d'
1820
+ ];
1821
+
1822
+ isInited = false;
1823
+
1824
+ if (!canvas) {
1825
+ return false;
1826
+ }
1827
+
1828
+ if (settings.timeSetup) {
1829
+ console.time('gl setup'); //eslint-disable-line no-console
1830
+ }
1831
+
1832
+ for (; i < contexts.length; i++) {
1833
+ gl = canvas.getContext(contexts[i]);
1834
+ if (gl) {
1835
+ break;
1836
+ }
1837
+ }
1838
+
1839
+ if (gl) {
1840
+ if (!noFlush) {
1841
+ flush();
1842
+ }
1843
+ } else {
1844
+ return false;
1845
+ }
1846
+
1847
+ gl.enable(gl.BLEND);
1848
+ // gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
1849
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
1850
+ gl.disable(gl.DEPTH_TEST);
1851
+ gl.depthMask(gl.FALSE);
1852
+
1853
+ shader = GLShader(gl); //eslint-disable-line new-cap
1854
+ vbuffer = GLVertexBuffer(gl, shader); //eslint-disable-line new-cap
1855
+
1856
+ textureIsReady = false;
1857
+
1858
+ // Set up the circle texture used for bubbles
1859
+ circleTextureHandle = gl.createTexture();
1860
+
1861
+ // Draw the circle
1862
+ circleTexture.width = 512;
1863
+ circleTexture.height = 512;
1864
+
1865
+ circleCtx.fillStyle = '#FFF';
1866
+ circleCtx.beginPath();
1867
+ circleCtx.arc(256, 256, 256, 0, 2 * Math.PI);
1868
+ circleCtx.fill();
1869
+
1870
+ try {
1871
+
1872
+ gl.bindTexture(gl.TEXTURE_2D, circleTextureHandle);
1873
+
1874
+ gl.texImage2D(
1875
+ gl.TEXTURE_2D,
1876
+ 0,
1877
+ gl.RGBA,
1878
+ gl.RGBA,
1879
+ gl.UNSIGNED_BYTE,
1880
+ circleTexture
1881
+ );
1882
+
1883
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
1884
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
1885
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
1886
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
1887
+
1888
+ gl.generateMipmap(gl.TEXTURE_2D);
1889
+
1890
+ gl.bindTexture(gl.TEXTURE_2D, null);
1891
+
1892
+ textureIsReady = true;
1893
+ } catch (e) {}
1894
+
1895
+ isInited = true;
1896
+
1897
+ if (settings.timeSetup) {
1898
+ console.timeEnd('gl setup'); //eslint-disable-line no-console
1899
+ }
1900
+
1901
+ return true;
1902
+ }
1903
+
1904
+ /*
1905
+ * Check if we have a valid OGL context
1906
+ * @returns {Boolean} - true if the context is valid
1907
+ */
1908
+ function valid() {
1909
+ return gl !== false;
1910
+ }
1911
+
1912
+ /*
1913
+ * Check if the renderer has been initialized
1914
+ * @returns {Boolean} - true if it has, false if not
1915
+ */
1916
+ function inited() {
1917
+ return isInited;
1918
+ }
1919
+
1920
+ function destroy() {
1921
+ vbuffer.destroy();
1922
+ shader.destroy();
1923
+ if (gl) {
1924
+ //gl.deleteTexture(circleTextureHandle);
1925
+ }
1926
+ }
1927
+
1928
+ ////////////////////////////////////////////////////////////////////////////
1929
+ exports = {
1930
+ allocateBufferForSingleSeries: allocateBufferForSingleSeries,
1931
+ pushSeries: pushSeries,
1932
+ setSize: setSize,
1933
+ inited: inited,
1934
+ setThreshold: setThreshold,
1935
+ init: init,
1936
+ render: renderWhenReady,
1937
+ settings: settings,
1938
+ valid: valid,
1939
+ clear: clear,
1940
+ flush: flush,
1941
+ setXAxis: setXAxis,
1942
+ setYAxis: setYAxis,
1943
+ data: data,
1944
+ gl: getGL,
1945
+ allocateBuffer: allocateBuffer,
1946
+ destroy: destroy,
1947
+ setOptions: setOptions
1948
+ };
1949
+
1950
+ return exports;
1951
+ }
1952
+
1953
+ // END OF WEBGL ABSTRACTIONS
1954
+ ////////////////////////////////////////////////////////////////////////////////
1955
+
1956
+ /*
1957
+ * Create a canvas + context and attach it to the target
1958
+ * @param target {Highcharts.Chart|Highcharts.Series} - the canvas target
1959
+ * @param chart {Highcharts.Chart} - the chart
1960
+ */
1961
+ function createAndAttachRenderer(chart, series) {
1962
+ var width = chart.chartWidth,
1963
+ height = chart.chartHeight,
1964
+ target = chart,
1965
+ targetGroup = chart.seriesGroup || series.group,
1966
+ swapXY = function(proceed, x, y, a, b, c, d) {
1967
+ proceed.call(series, y, x, a, b, c, d);
1968
+ };
1969
+
1970
+ if (isChartSeriesBoosting(chart)) {
1971
+ target = chart;
1972
+ } else {
1973
+ target = series;
1974
+ }
1975
+
1976
+ if (target.ogl) {
1977
+ //target.ogl.destroy();
1978
+ }
1979
+
1980
+ if (!target.image) {
1981
+ target.canvas = doc.createElement('canvas');
1982
+
1983
+ target.image = chart.renderer.image(
1984
+ '',
1985
+ 0,
1986
+ 0,
1987
+ width,
1988
+ height
1989
+ ).add(targetGroup);
1990
+
1991
+ target.boostClipRect = chart.renderer.clipRect(
1992
+ chart.plotLeft,
1993
+ chart.plotTop,
1994
+ chart.plotWidth,
1995
+ chart.chartHeight
1996
+ );
1997
+
1998
+ target.image.clip(target.boostClipRect);
1999
+
2000
+ if (target.inverted) {
2001
+ each(['moveTo', 'lineTo', 'rect', 'arc'], function(fn) {
2002
+ wrap(false, fn, swapXY);
2003
+ });
2004
+ }
2005
+
2006
+ if (target instanceof H.Chart) {
2007
+ target.markerGroup = target.renderer.g().add(targetGroup);
2008
+
2009
+ target.markerGroup.translate(series.xAxis.pos, series.yAxis.pos);
2010
+ }
2011
+ }
2012
+
2013
+ target.canvas.width = width;
2014
+ target.canvas.height = height;
2015
+
2016
+ target.image.attr({
2017
+ x: 0,
2018
+ y: 0,
2019
+ width: width,
2020
+ height: height,
2021
+ style: 'pointer-events: none'
2022
+ });
2023
+
2024
+ target.boostClipRect.attr({
2025
+ x: chart.plotLeft,
2026
+ y: chart.plotTop,
2027
+ width: chart.plotWidth,
2028
+ height: chart.chartHeight
2029
+ });
2030
+
2031
+ if (!target.ogl) {
2032
+
2033
+
2034
+ target.ogl = GLRenderer(function() { // eslint-disable-line new-cap
2035
+ target.image.attr({
2036
+ href: target.canvas.toDataURL('image/png')
2037
+ });
2038
+ }); //eslint-disable-line new-cap
2039
+
2040
+ target.ogl.init(target.canvas);
2041
+ // target.ogl.clear();
2042
+ target.ogl.setOptions(chart.options.boost || {});
2043
+
2044
+ if (target instanceof H.Chart) {
2045
+ target.ogl.allocateBuffer(chart);
2046
+ }
2047
+ }
2048
+
2049
+ target.ogl.setSize(width, height);
2050
+
2051
+ return target.ogl;
2052
+ }
2053
+
2054
+ /*
2055
+ * Performs the actual render if the renderer is
2056
+ * attached to the series.
2057
+ * @param renderer {OGLRenderer} - the renderer
2058
+ * @param series {Highcharts.Series} - the series
2059
+ */
2060
+ function renderIfNotSeriesBoosting(renderer, series, chart) {
2061
+ if (renderer &&
2062
+ series.image &&
2063
+ series.canvas &&
2064
+ !isChartSeriesBoosting(chart || series.chart)
2065
+ ) {
2066
+ renderer.render(chart || series.chart);
2067
+ }
2068
+ }
2069
+
2070
+ function allocateIfNotSeriesBoosting(renderer, series) {
2071
+ if (renderer &&
2072
+ series.image &&
2073
+ series.canvas &&
2074
+ !isChartSeriesBoosting(series.chart)
2075
+ ) {
2076
+ renderer.allocateBufferForSingleSeries(series);
2077
+ }
2078
+ }
2079
+
2080
+ /*
2081
+ * An "async" foreach loop.
2082
+ * Uses a setTimeout to keep the loop from blocking the UI thread
2083
+ * @param arr {Array} - the array to loop through
2084
+ * @param fn {Function} - the callback to call for each item
2085
+ * @param finalFunc {Function} - the callback to call when done
2086
+ * @param chunkSize {Number} - the number of iterations per. timeout
2087
+ * @param i {Number} - the current index
2088
+ * @param noTimeout {Boolean} - set to true to skip timeouts
2089
+ */
2090
+ function eachAsync(arr, fn, finalFunc, chunkSize, i, noTimeout) {
2091
+ i = i || 0;
2092
+ chunkSize = chunkSize || CHUNK_SIZE;
2093
+
2094
+ var threshold = i + chunkSize,
2095
+ proceed = true;
2096
+
2097
+ while (proceed && i < threshold && i < arr.length) {
2098
+ proceed = fn(arr[i], i);
2099
+ ++i;
2100
+ }
2101
+ if (proceed) {
2102
+ if (i < arr.length) {
2103
+
2104
+ if (noTimeout) {
2105
+ eachAsync(arr, fn, finalFunc, chunkSize, i, noTimeout);
2106
+ } else if (win.requestAnimationFrame) {
2107
+ //If available, do requestAnimationFrame - shaves off a few ms
2108
+ win.requestAnimationFrame(function() {
2109
+ eachAsync(arr, fn, finalFunc, chunkSize, i);
2110
+ });
2111
+ } else {
2112
+ setTimeout(function() {
2113
+ eachAsync(arr, fn, finalFunc, chunkSize, i);
2114
+ });
2115
+ }
2116
+
2117
+ } else if (finalFunc) {
2118
+ finalFunc();
2119
+ }
2120
+ }
2121
+ }
2122
+
2123
+ ////////////////////////////////////////////////////////////////////////////////
2124
+ // Following is the parts of the boost that's common between OGL/Legacy
2125
+
2126
+ /**
2127
+ * Return a full Point object based on the index.
2128
+ * The boost module uses stripped point objects for performance reasons.
2129
+ * @param {Number} boostPoint A stripped-down point object
2130
+ * @returns {Object} A Point object as per http://api.highcharts.com/highcharts#Point
2131
+ */
2132
+ Series.prototype.getPoint = function(boostPoint) {
2133
+ var point = boostPoint,
2134
+ xData = this.xData || this.options.xData || this.processedXData || false;
2135
+
2136
+ if (boostPoint && !(boostPoint instanceof this.pointClass)) {
2137
+ point = (new this.pointClass()).init( // eslint-disable-line new-cap
2138
+ this,
2139
+ this.options.data[boostPoint.i],
2140
+ xData ? xData[boostPoint.i] : undefined
2141
+ );
2142
+
2143
+ point.category = point.x;
2144
+
2145
+ point.dist = boostPoint.dist;
2146
+ point.distX = boostPoint.distX;
2147
+ point.plotX = boostPoint.plotX;
2148
+ point.plotY = boostPoint.plotY;
2149
+ point.index = boostPoint.i;
2150
+ }
2151
+
2152
+ return point;
2153
+ };
2154
+
2155
+ /**
2156
+ * Return a point instance from the k-d-tree
2157
+ */
2158
+ wrap(Series.prototype, 'searchPoint', function(proceed) {
2159
+ return this.getPoint(
2160
+ proceed.apply(this, [].slice.call(arguments, 1))
2161
+ );
2162
+ });
2163
+
2164
+ /**
2165
+ * Extend series.destroy to also remove the fake k-d-tree points (#5137).
2166
+ * Normally this is handled by Series.destroy that calls Point.destroy,
2167
+ * but the fake search points are not registered like that.
2168
+ */
2169
+ wrap(Series.prototype, 'destroy', function(proceed) {
2170
+ var series = this,
2171
+ chart = series.chart;
2172
+
2173
+ if (chart.markerGroup === series.markerGroup) {
2174
+ series.markerGroup = null;
2175
+ }
2176
+
2177
+ if (chart.hoverPoints) {
2178
+ chart.hoverPoints = grep(chart.hoverPoints, function(point) {
2179
+ return point.series === series;
2180
+ });
2181
+ }
2182
+
2183
+ if (chart.hoverPoint && chart.hoverPoint.series === series) {
2184
+ chart.hoverPoint = null;
2185
+ }
2186
+
2187
+ proceed.call(this);
2188
+ });
2189
+
2190
+ /**
2191
+ * Do not compute extremes when min and max are set.
2192
+ * If we use this in the core, we can add the hook
2193
+ * to hasExtremes to the methods directly.
2194
+ */
2195
+ wrap(Series.prototype, 'getExtremes', function(proceed) {
2196
+ if (!isSeriesBoosting(this) || (!this.hasExtremes || !this.hasExtremes())) {
2197
+ return proceed.apply(this, Array.prototype.slice.call(arguments, 1));
2198
+ }
2199
+ });
2200
+
2201
+ // Set default options
2202
+ each([
2203
+ 'area',
2204
+ 'arearange',
2205
+ 'column',
2206
+ 'line',
2207
+ 'scatter',
2208
+ 'heatmap',
2209
+ 'bubble',
2210
+ 'treemap',
2211
+ 'heatmap'
2212
+ ],
2213
+ function(type) {
2214
+ if (plotOptions[type]) {
2215
+ plotOptions[type].boostThreshold = 5000;
2216
+ plotOptions[type].boostData = [];
2217
+ }
2218
+ }
2219
+ );
2220
+
2221
+ /**
2222
+ * Override a bunch of methods the same way. If the number of points is
2223
+ * below the threshold, run the original method. If not, check for a
2224
+ * canvas version or do nothing.
2225
+ *
2226
+ * Note that we're not overriding any of these for heatmaps.
2227
+ */
2228
+ each([
2229
+ 'translate',
2230
+ 'generatePoints',
2231
+ 'drawTracker',
2232
+ 'drawPoints',
2233
+ 'render'
2234
+ ], function(method) {
2235
+ function branch(proceed) {
2236
+ var letItPass = this.options.stacking &&
2237
+ (method === 'translate' || method === 'generatePoints');
2238
+
2239
+ if (!isSeriesBoosting(this) ||
2240
+ letItPass ||
2241
+ this.type === 'heatmap' ||
2242
+ this.type === 'treemap'
2243
+ ) {
2244
+
2245
+ // Clear image
2246
+ if (method === 'render' && this.image && !isChartSeriesBoosting(this.chart)) {
2247
+ this.image.attr({
2248
+ href: ''
2249
+ });
2250
+ this.animate = null; // We're zooming in, don't run animation
2251
+ }
2252
+
2253
+ proceed.call(this);
2254
+
2255
+ // If a canvas version of the method exists, like renderCanvas(), run
2256
+ } else if (this[method + 'Canvas']) {
2257
+ this[method + 'Canvas']();
2258
+ }
2259
+ }
2260
+
2261
+ wrap(Series.prototype, method, branch);
2262
+
2263
+ // A special case for some types - their translate method is already wrapped
2264
+ if (method === 'translate') {
2265
+ if (seriesTypes.column) {
2266
+ wrap(seriesTypes.column.prototype, method, branch);
2267
+ }
2268
+
2269
+ if (seriesTypes.arearange) {
2270
+ wrap(seriesTypes.arearange.prototype, method, branch);
2271
+ }
2272
+
2273
+ if (seriesTypes.treemap) {
2274
+ wrap(seriesTypes.treemap.prototype, method, branch);
2275
+ }
2276
+ }
2277
+ });
2278
+
2279
+ /*
2280
+ * Returns true if the current browser supports webgl
2281
+ */
2282
+ function hasWebGLSupport() {
2283
+ var i = 0,
2284
+ canvas,
2285
+ contexts = ['webgl', 'experimental-webgl', 'moz-webgl', 'webkit-3d'],
2286
+ context = false;
2287
+
2288
+ if (typeof win.WebGLRenderingContext !== 'undefined') {
2289
+ canvas = doc.createElement('canvas');
2290
+
2291
+ for (; i < contexts.length; i++) {
2292
+ try {
2293
+ context = canvas.getContext(contexts[i]);
2294
+ if (typeof context !== 'undefined' && context !== null) {
2295
+ return true;
2296
+ }
2297
+ } catch (e) {
2298
+
2299
+ }
2300
+ }
2301
+ }
2302
+
2303
+ return false;
2304
+ }
2305
+
2306
+ /* Used for treemap|heatmap.drawPoints */
2307
+ function pointDrawHandler(proceed) {
2308
+ if (!isSeriesBoosting(this)) {
2309
+ return proceed.call(this);
2310
+ }
2311
+
2312
+ //Make sure we have a valid OGL context
2313
+ var renderer = createAndAttachRenderer(this.chart, this);
2314
+
2315
+ if (renderer) {
2316
+ allocateIfNotSeriesBoosting(renderer, this);
2317
+ renderer.pushSeries(this);
2318
+ }
2319
+
2320
+ renderIfNotSeriesBoosting(renderer, this);
2321
+ }
2322
+
2323
+
2324
+
2325
+ ////////////////////////////////////////////////////////////////////////////////
2326
+ // We're wrapped in a closure, so just return if there's no webgl support
2327
+
2328
+ if (!hasWebGLSupport()) {
2329
+ if (typeof H.initCanvasBoost !== 'undefined') {
2330
+ // Fallback to canvas boost
2331
+ H.initCanvasBoost();
2332
+ } else {
2333
+ H.error(26);
2334
+ }
2335
+ } else {
2336
+
2337
+ ////////////////////////////////////////////////////////////////////////////
2338
+ // GL-SPECIFIC WRAPPINGS FOLLOWS
2339
+
2340
+ /** If the series is a heatmap or treemap, or if the series is not boosting
2341
+ * do the default behaviour. Otherwise, process if the series has no
2342
+ * extremes.
2343
+ */
2344
+ wrap(Series.prototype, 'processData', function(proceed) {
2345
+ // If this is a heatmap, do default behaviour
2346
+ if (!isSeriesBoosting(this) ||
2347
+ this.type === 'heatmap' ||
2348
+ this.type === 'treemap') {
2349
+ proceed.apply(this, Array.prototype.slice.call(arguments, 1));
2350
+ }
2351
+
2352
+ if (!this.hasExtremes || !this.hasExtremes(true)) {
2353
+ proceed.apply(this, Array.prototype.slice.call(arguments, 1));
2354
+ }
2355
+ });
2356
+
2357
+ H.extend(Series.prototype, {
2358
+ pointRange: 0,
2359
+ directTouch: false,
2360
+ allowDG: false, // No data grouping, let boost handle large data
2361
+ hasExtremes: function(checkX) {
2362
+ var options = this.options,
2363
+ data = options.data,
2364
+ xAxis = this.xAxis && this.xAxis.options,
2365
+ yAxis = this.yAxis && this.yAxis.options;
2366
+
2367
+ return data.length > (options.boostThreshold || Number.MAX_VALUE) &&
2368
+ isNumber(yAxis.min) && isNumber(yAxis.max) &&
2369
+ (!checkX || (isNumber(xAxis.min) && isNumber(xAxis.max)));
2370
+ },
2371
+
2372
+ /**
2373
+ * If implemented in the core, parts of this can probably be
2374
+ * shared with other similar methods in Highcharts.
2375
+ */
2376
+ destroyGraphics: function() {
2377
+ var series = this,
2378
+ points = this.points,
2379
+ point,
2380
+ i;
2381
+
2382
+ if (points) {
2383
+ for (i = 0; i < points.length; i = i + 1) {
2384
+ point = points[i];
2385
+ if (point && point.graphic) {
2386
+ point.graphic = point.graphic.destroy();
2387
+ }
2388
+ }
2389
+ }
2390
+
2391
+ each(['graph', 'area', 'tracker'], function(prop) {
2392
+ if (series[prop]) {
2393
+ series[prop] = series[prop].destroy();
2394
+ }
2395
+ });
2396
+ },
2397
+
2398
+ renderCanvas: function() {
2399
+ var series = this,
2400
+ options = series.options || {},
2401
+ renderer = false,
2402
+ chart = series.chart,
2403
+ xAxis = this.xAxis,
2404
+ yAxis = this.yAxis,
2405
+ //ctx,
2406
+ //c = 0,
2407
+ xData = options.xData || series.processedXData,
2408
+ yData = options.yData || series.processedYData,
2409
+
2410
+ rawData = options.data,
2411
+ xExtremes = xAxis.getExtremes(),
2412
+ xMin = xExtremes.min,
2413
+ xMax = xExtremes.max,
2414
+ yExtremes = yAxis.getExtremes(),
2415
+ yMin = yExtremes.min,
2416
+ yMax = yExtremes.max,
2417
+ pointTaken = {},
2418
+ lastClientX,
2419
+ sampling = !!series.sampling,
2420
+ points,
2421
+ enableMouseTracking = options.enableMouseTracking !== false,
2422
+ threshold = options.threshold,
2423
+ yBottom = yAxis.getThreshold(threshold),
2424
+ isRange = series.pointArrayMap &&
2425
+ series.pointArrayMap.join(',') === 'low,high',
2426
+ isStacked = !!options.stacking,
2427
+ cropStart = series.cropStart || 0,
2428
+ requireSorting = series.requireSorting,
2429
+ useRaw = !xData,
2430
+ minVal,
2431
+ maxVal,
2432
+ minI,
2433
+ maxI,
2434
+
2435
+ addKDPoint = function(clientX, plotY, i) {
2436
+ //Shaves off about 60ms compared to repeated concatination
2437
+ index = clientX + ',' + plotY;
2438
+
2439
+ // The k-d tree requires series points.
2440
+ // Reduce the amount of points, since the time to build the
2441
+ // tree increases exponentially.
2442
+ if (enableMouseTracking && !pointTaken[index]) {
2443
+ pointTaken[index] = true;
2444
+
2445
+ if (chart.inverted) {
2446
+ clientX = xAxis.len - clientX;
2447
+ plotY = yAxis.len - plotY;
2448
+ }
2449
+
2450
+ points.push({
2451
+ clientX: clientX,
2452
+ plotX: clientX,
2453
+ plotY: plotY,
2454
+ i: cropStart + i
2455
+ });
2456
+ }
2457
+ };
2458
+
2459
+ // Get or create the renderer
2460
+ renderer = createAndAttachRenderer(chart, series);
2461
+
2462
+ if (!this.visible) {
2463
+ if (!isChartSeriesBoosting(chart) && renderer) {
2464
+ renderer.clear();
2465
+ this.image.attr({
2466
+ href: ''
2467
+ });
2468
+ }
2469
+ return;
2470
+ }
2471
+
2472
+ // If we are zooming out from SVG mode, destroy the graphics
2473
+ if (this.points || this.graph) {
2474
+ this.destroyGraphics();
2475
+ }
2476
+
2477
+ // If we're rendering per. series we should create the marker groups
2478
+ // as usual.
2479
+ if (!isChartSeriesBoosting(chart)) {
2480
+ this.markerGroup = series.plotGroup(
2481
+ 'markerGroup',
2482
+ 'markers',
2483
+ true,
2484
+ 1,
2485
+ chart.seriesGroup
2486
+ );
2487
+ } else {
2488
+ //Use a single group for the markers
2489
+ this.markerGroup = chart.markerGroup;
2490
+ }
2491
+
2492
+ points = this.points = [];
2493
+
2494
+ // Do not start building while drawing
2495
+ series.buildKDTree = noop;
2496
+
2497
+ if (renderer) {
2498
+ allocateIfNotSeriesBoosting(renderer, this);
2499
+ renderer.pushSeries(series);
2500
+ // Perform the actual renderer if we're on series level
2501
+ renderIfNotSeriesBoosting(renderer, this, chart);
2502
+ //console.log(series, chart);
2503
+ }
2504
+
2505
+ /* This builds the KD-tree */
2506
+ function processPoint(d, i) {
2507
+ var x,
2508
+ y,
2509
+ clientX,
2510
+ plotY,
2511
+ isNull,
2512
+ low,
2513
+ chartDestroyed = typeof chart.index === 'undefined',
2514
+ isYInside = true;
2515
+
2516
+ if (!chartDestroyed) {
2517
+ if (useRaw) {
2518
+ x = d[0];
2519
+ y = d[1];
2520
+ } else {
2521
+ x = d;
2522
+ y = yData[i];
2523
+ }
2524
+
2525
+ // Resolve low and high for range series
2526
+ if (isRange) {
2527
+ if (useRaw) {
2528
+ y = d.slice(1, 3);
2529
+ }
2530
+ low = y[0];
2531
+ y = y[1];
2532
+ } else if (isStacked) {
2533
+ x = d.x;
2534
+ y = d.stackY;
2535
+ low = y - d.y;
2536
+ }
2537
+
2538
+ isNull = y === null;
2539
+
2540
+ // Optimize for scatter zooming
2541
+ if (!requireSorting) {
2542
+ isYInside = y >= yMin && y <= yMax;
2543
+ }
2544
+
2545
+ if (!isNull && x >= xMin && x <= xMax && isYInside) {
2546
+
2547
+ // We use ceil to allow the KD tree to work with sub
2548
+ // pixels, which can be used in boost to space pixels
2549
+ clientX = Math.ceil(xAxis.toPixels(x, true));
2550
+
2551
+ if (sampling) {
2552
+ if (minI === undefined || clientX === lastClientX) {
2553
+ if (!isRange) {
2554
+ low = y;
2555
+ }
2556
+ if (maxI === undefined || y > maxVal) {
2557
+ maxVal = y;
2558
+ maxI = i;
2559
+ }
2560
+ if (minI === undefined || low < minVal) {
2561
+ minVal = low;
2562
+ minI = i;
2563
+ }
2564
+
2565
+ }
2566
+ if (clientX !== lastClientX) { // Add points and reset
2567
+ if (minI !== undefined) { // then maxI is also a number
2568
+ plotY = yAxis.toPixels(maxVal, true);
2569
+ yBottom = yAxis.toPixels(minVal, true);
2570
+
2571
+ addKDPoint(clientX, plotY, maxI);
2572
+ if (yBottom !== plotY) {
2573
+ addKDPoint(clientX, yBottom, minI);
2574
+ }
2575
+ }
2576
+
2577
+ minI = maxI = undefined;
2578
+ lastClientX = clientX;
2579
+ }
2580
+ } else {
2581
+ plotY = Math.ceil(yAxis.toPixels(y, true));
2582
+ addKDPoint(clientX, plotY, i);
2583
+ }
2584
+ }
2585
+ }
2586
+
2587
+ return !chartDestroyed;
2588
+ }
2589
+
2590
+ function doneProcessing() {
2591
+ fireEvent(series, 'renderedCanvas');
2592
+ // Pass tests in Pointer.
2593
+ // Replace this with a single property, and replace when zooming
2594
+ // in below boostThreshold.
2595
+ series.directTouch = false;
2596
+ series.options.stickyTracking = true;
2597
+
2598
+ // Go back to prototype, ready to build
2599
+ delete series.buildKDTree;
2600
+ series.buildKDTree();
2601
+ }
2602
+
2603
+ // Loop over the points to build the k-d tree
2604
+ eachAsync(
2605
+ isStacked ? series.data : (xData || rawData),
2606
+ processPoint,
2607
+ doneProcessing,
2608
+ chart.renderer.forExport ? Number.MAX_VALUE : undefined
2609
+ );
2610
+ }
2611
+ });
2612
+
2613
+ /*
2614
+ * We need to handle heatmaps separatly, since we can't perform the
2615
+ * size/color calculations in the shader easily.
2616
+ *
2617
+ * This likely needs future optimization.
2618
+ *
2619
+ */
2620
+ each(['heatmap', 'treemap'],
2621
+ function(t) {
2622
+ if (seriesTypes[t]) {
2623
+ wrap(seriesTypes[t].prototype, 'drawPoints', pointDrawHandler);
2624
+ seriesTypes[t].prototype.directTouch = false; // Use k-d-tree
2625
+ }
2626
+ }
2627
+ );
2628
+
2629
+ if (seriesTypes.bubble) {
2630
+ // By default, the bubble series does not use the KD-tree, so force it
2631
+ // to.
2632
+ delete seriesTypes.bubble.prototype.buildKDTree;
2633
+ seriesTypes.bubble.prototype.directTouch = false;
2634
+
2635
+ // Needed for markers to work correctly
2636
+ wrap(
2637
+ seriesTypes.bubble.prototype,
2638
+ 'markerAttribs',
2639
+ function(proceed) {
2640
+ if (isSeriesBoosting(this)) {
2641
+ return false;
2642
+ }
2643
+ return proceed.apply(this, [].slice.call(arguments, 1));
2644
+ }
2645
+ );
2646
+ }
2647
+
2648
+ seriesTypes.scatter.prototype.fill = true;
2649
+
2650
+ extend(seriesTypes.area.prototype, {
2651
+ fill: true,
2652
+ fillOpacity: true,
2653
+ sampling: true
2654
+ });
2655
+
2656
+ extend(seriesTypes.column.prototype, {
2657
+ fill: true,
2658
+ sampling: true
2659
+ });
2660
+
2661
+ wrap(Series.prototype, 'setVisible', function(proceed, vis) {
2662
+ proceed.call(this, vis, false);
2663
+ if (this.visible === false && this.ogl && this.canvas && this.image) {
2664
+ this.ogl.clear();
2665
+ this.image.attr({
2666
+ href: ''
2667
+ });
2668
+ } else {
2669
+ this.chart.redraw();
2670
+ }
2671
+ });
2672
+
2673
+ /**
2674
+ * Take care of the canvas blitting
2675
+ */
2676
+ H.Chart.prototype.callbacks.push(function(chart) {
2677
+
2678
+ /* Convert chart-level canvas to image */
2679
+ function canvasToSVG() {
2680
+ if (chart.ogl && isChartSeriesBoosting(chart)) {
2681
+ chart.ogl.render(chart);
2682
+ }
2683
+ }
2684
+
2685
+ /* Clear chart-level canvas */
2686
+ function preRender() {
2687
+
2688
+ if (!isChartSeriesBoosting(chart) && chart.didBoost) {
2689
+ chart.didBoost = false;
2690
+ // Clear the canvas
2691
+ if (chart.image) {
2692
+ chart.image.attr({
2693
+ href: ''
2694
+ });
2695
+ }
2696
+ }
2697
+
2698
+ if (chart.canvas && chart.ogl && isChartSeriesBoosting(chart)) {
2699
+ chart.didBoost = true;
2700
+
2701
+ // Allocate
2702
+ chart.ogl.allocateBuffer(chart);
2703
+ }
2704
+
2705
+ //see #6518 + #6739
2706
+ if (chart.markerGroup && chart.xAxis && chart.xAxis.length > 0 && chart.yAxis && chart.yAxis.length > 0) {
2707
+ chart.markerGroup.translate(
2708
+ chart.xAxis[0].pos,
2709
+ chart.yAxis[0].pos
2710
+ );
2711
+ }
2712
+
2713
+ }
2714
+
2715
+ addEvent(chart, 'predraw', preRender);
2716
+ addEvent(chart, 'render', canvasToSVG);
2717
+ });
2718
+ } // if hasCanvasSupport
2719
+
2720
+ }(Highcharts));
2721
+ }));