/* Highcharts JS v8.1.0 (2020-05-05) Boost module (c) 2010-2019 Highsoft AS Author: Torstein Honsi License: www.highcharts.com/license This is a Highcharts module that draws long data series on a canvas in order to increase performance of the initial load time and tooltip responsiveness. Compatible with WebGL compatible browsers (not IE < 11). If this module is taken in as part of the core - All the loading logic should be merged with core. Update styles in the core. - Most of the method wraps should probably be added directly in parent methods. Notes for boost mode - Area lines are not drawn - Lines are not drawn on scatter charts - Zones and negativeColor don't work - Dash styles are not rendered on lines. - Columns are always one pixel wide. Don't set the threshold too low. - Disable animations - Marker shapes are not supported: markers will always be circles, except heatmap series, where markers are always rectangles. Optimizing tips for users - Set extremes (min, max) explicitly on the axes in order for Highcharts to avoid computing extremes. - Set enableMouseTracking to false on the series to improve total rendering time. - The default threshold is set based on one series. If you have multiple, dense series, the combined number of points drawn gets higher, and you may want to set the threshold lower in order to use optimizations. - If drawing large scatter charts, it's beneficial to set the marker radius to a value less than 1. This is to add additional spacing to make the chart more readable. - If the value increments on both the X and Y axis aren't small, consider setting useGPUTranslations to true on the boost settings object. If you do this and the increments are small (e.g. datetime axis with small time increments) it may cause rendering issues due to floating point rounding errors, so your millage may vary. Settings There are two ways of setting the boost threshold: - Per series: boost based on number of points in individual series - Per chart: boost based on the number of series To set the series boost threshold, set seriesBoostThreshold on the chart object. To set the series-specific threshold, set boostThreshold on the series object. In addition, the following can be set in the boost object: { //Wether or not to use alpha blending useAlpha: boolean - default: true //Set to true to perform translations on the GPU. //Much faster, but may cause rendering issues //when using values far from 0 due to floating point //rounding issues useGPUTranslations: boolean - default: false //Use pre-allocated buffers, much faster, //but may cause rendering issues with some data sets usePreallocated: boolean - default: false } */ (function(c){"object"===typeof module&&module.exports?(c["default"]=c,module.exports=c):"function"===typeof define&&define.amd?define("highcharts/modules/boost",["highcharts"],function(m){c(m);c.Highcharts=m;return c}):c("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(c){function m(c,E,f,C){c.hasOwnProperty(E)||(c[E]=C.apply(null,f))}c=c?c._modules:{};m(c,"modules/boost/boostables.js",[],function(){return"area arearange column columnrange bar line scatter heatmap bubble treemap".split(" ")}); m(c,"modules/boost/boostable-map.js",[c["modules/boost/boostables.js"]],function(c){var k={};c.forEach(function(c){k[c]=1});return k});m(c,"modules/boost/wgl-shader.js",[c["parts/Utilities.js"]],function(c){var k=c.clamp,f=c.error,C=c.pick;return function(d){function c(){v.length&&f("[highcharts boost] shader error - "+v.join("\n"))}function w(b,a){var g=d.createShader("vertex"===a?d.VERTEX_SHADER:d.FRAGMENT_SHADER);d.shaderSource(g,b);d.compileShader(g);return d.getShaderParameter(g,d.COMPILE_STATUS)? g:(v.push("when compiling "+a+" shader:\n"+d.getShaderInfoLog(g)),!1)}function r(){function g(a){return d.getUniformLocation(b,a)}var k=w("#version 100\n#define LN10 2.302585092994046\nprecision highp float;\nattribute vec4 aVertexPosition;\nattribute vec4 aColor;\nvarying highp vec2 position;\nvarying highp vec4 vColor;\nuniform mat4 uPMatrix;\nuniform float pSize;\nuniform float translatedThreshold;\nuniform bool hasThreshold;\nuniform bool skipTranslation;\nuniform float xAxisTrans;\nuniform float xAxisMin;\nuniform float xAxisMinPad;\nuniform float xAxisPointRange;\nuniform float xAxisLen;\nuniform bool xAxisPostTranslate;\nuniform float xAxisOrdinalSlope;\nuniform float xAxisOrdinalOffset;\nuniform float xAxisPos;\nuniform bool xAxisCVSCoord;\nuniform bool xAxisIsLog;\nuniform bool xAxisReversed;\nuniform float yAxisTrans;\nuniform float yAxisMin;\nuniform float yAxisMinPad;\nuniform float yAxisPointRange;\nuniform float yAxisLen;\nuniform bool yAxisPostTranslate;\nuniform float yAxisOrdinalSlope;\nuniform float yAxisOrdinalOffset;\nuniform float yAxisPos;\nuniform bool yAxisCVSCoord;\nuniform bool yAxisIsLog;\nuniform bool yAxisReversed;\nuniform bool isBubble;\nuniform bool bubbleSizeByArea;\nuniform float bubbleZMin;\nuniform float bubbleZMax;\nuniform float bubbleZThreshold;\nuniform float bubbleMinSize;\nuniform float bubbleMaxSize;\nuniform bool bubbleSizeAbs;\nuniform bool isInverted;\nfloat bubbleRadius(){\nfloat value = aVertexPosition.w;\nfloat zMax = bubbleZMax;\nfloat zMin = bubbleZMin;\nfloat radius = 0.0;\nfloat pos = 0.0;\nfloat zRange = zMax - zMin;\nif (bubbleSizeAbs){\nvalue = value - bubbleZThreshold;\nzMax = max(zMax - bubbleZThreshold, zMin - bubbleZThreshold);\nzMin = 0.0;\n}\nif (value < zMin){\nradius = bubbleZMin / 2.0 - 1.0;\n} else {\npos = zRange > 0.0 ? (value - zMin) / zRange : 0.5;\nif (bubbleSizeByArea && pos > 0.0){\npos = sqrt(pos);\n}\nradius = ceil(bubbleMinSize + pos * (bubbleMaxSize - bubbleMinSize)) / 2.0;\n}\nreturn radius * 2.0;\n}\nfloat translate(float val,\nfloat pointPlacement,\nfloat localA,\nfloat localMin,\nfloat minPixelPadding,\nfloat pointRange,\nfloat len,\nbool cvsCoord,\nbool isLog,\nbool reversed\n){\nfloat sign = 1.0;\nfloat cvsOffset = 0.0;\nif (cvsCoord) {\nsign *= -1.0;\ncvsOffset = len;\n}\nif (isLog) {\nval = log(val) / LN10;\n}\nif (reversed) {\nsign *= -1.0;\ncvsOffset -= sign * len;\n}\nreturn sign * (val - localMin) * localA + cvsOffset + \n(sign * minPixelPadding);\n}\nfloat xToPixels(float value) {\nif (skipTranslation){\nreturn value;// + xAxisPos;\n}\nreturn translate(value, 0.0, xAxisTrans, xAxisMin, xAxisMinPad, xAxisPointRange, xAxisLen, xAxisCVSCoord, xAxisIsLog, xAxisReversed);// + xAxisPos;\n}\nfloat yToPixels(float value, float checkTreshold) {\nfloat v;\nif (skipTranslation){\nv = value;// + yAxisPos;\n} else {\nv = translate(value, 0.0, yAxisTrans, yAxisMin, yAxisMinPad, yAxisPointRange, yAxisLen, yAxisCVSCoord, yAxisIsLog, yAxisReversed);// + yAxisPos;\nif (v > yAxisLen) {\nv = yAxisLen;\n}\n}\nif (checkTreshold > 0.0 && hasThreshold) {\nv = min(v, translatedThreshold);\n}\nreturn v;\n}\nvoid main(void) {\nif (isBubble){\ngl_PointSize = bubbleRadius();\n} else {\ngl_PointSize = pSize;\n}\nvColor = aColor;\nif (skipTranslation && isInverted) {\ngl_Position = uPMatrix * vec4(aVertexPosition.y + yAxisPos, aVertexPosition.x + xAxisPos, 0.0, 1.0);\n} else if (isInverted) {\ngl_Position = uPMatrix * vec4(yToPixels(aVertexPosition.y, aVertexPosition.z) + yAxisPos, xToPixels(aVertexPosition.x) + xAxisPos, 0.0, 1.0);\n} else {\ngl_Position = uPMatrix * vec4(xToPixels(aVertexPosition.x) + xAxisPos, yToPixels(aVertexPosition.y, aVertexPosition.z) + yAxisPos, 0.0, 1.0);\n}\n}", "vertex"),e=w("precision highp float;\nuniform vec4 fillColor;\nvarying highp vec2 position;\nvarying highp vec4 vColor;\nuniform sampler2D uSampler;\nuniform bool isCircle;\nuniform bool hasColor;\nvoid main(void) {\nvec4 col = fillColor;\nvec4 tcol;\nif (hasColor) {\ncol = vColor;\n}\nif (isCircle) {\ntcol = texture2D(uSampler, gl_PointCoord.st);\ncol *= tcol;\nif (tcol.r < 0.0) {\ndiscard;\n} else {\ngl_FragColor = col;\n}\n} else {\ngl_FragColor = col;\n}\n}","fragment");if(!k||!e)return b=!1, c(),!1;b=d.createProgram();d.attachShader(b,k);d.attachShader(b,e);d.linkProgram(b);if(!d.getProgramParameter(b,d.LINK_STATUS))return v.push(d.getProgramInfoLog(b)),c(),b=!1;d.useProgram(b);d.bindAttribLocation(b,0,"aVertexPosition");N=g("uPMatrix");p=g("pSize");n=g("fillColor");l=g("isBubble");D=g("bubbleSizeAbs");G=g("bubbleSizeByArea");M=g("uSampler");a=g("skipTranslation");t=g("isCircle");H=g("isInverted");return!0}function q(a,c){d&&b&&(a=h[a]=h[a]||d.getUniformLocation(b,a),d.uniform1f(a,c))} var h={},b,N,p,n,l,D,G,a,t,H,v=[],M;return d&&!r()?!1:{psUniform:function(){return p},pUniform:function(){return N},fillColorUniform:function(){return n},setBubbleUniforms:function(a,c,e){var g=a.options,p=Number.MAX_VALUE,H=-Number.MAX_VALUE;d&&b&&"bubble"===a.type&&(p=C(g.zMin,k(c,!1===g.displayNegative?g.zThreshold:-Number.MAX_VALUE,p)),H=C(g.zMax,Math.max(H,e)),d.uniform1i(l,1),d.uniform1i(t,1),d.uniform1i(G,"width"!==a.options.sizeBy),d.uniform1i(D,a.options.sizeByAbsoluteValue),q("bubbleZMin", p),q("bubbleZMax",H),q("bubbleZThreshold",a.options.zThreshold),q("bubbleMinSize",a.minPxSize),q("bubbleMaxSize",a.maxPxSize))},bind:function(){d&&b&&d.useProgram(b)},program:function(){return b},create:r,setUniform:q,setPMatrix:function(a){d&&b&&d.uniformMatrix4fv(N,!1,a)},setColor:function(a){d&&b&&d.uniform4f(n,a[0]/255,a[1]/255,a[2]/255,a[3])},setPointSize:function(a){d&&b&&d.uniform1f(p,a)},setSkipTranslation:function(g){d&&b&&d.uniform1i(a,!0===g?1:0)},setTexture:function(a){d&&b&&d.uniform1i(M, a)},setDrawAsCircle:function(a){d&&b&&d.uniform1i(t,a?1:0)},reset:function(){d&&b&&(d.uniform1i(l,0),d.uniform1i(t,0))},setInverted:function(a){d&&b&&d.uniform1i(H,a)},destroy:function(){d&&b&&(d.deleteProgram(b),b=!1)}}}});m(c,"modules/boost/wgl-vbuffer.js",[],function(){return function(c,E,f){function k(){d&&(c.deleteBuffer(d),A=d=!1);q=0;w=f||2;h=[]}var d=!1,A=!1,w=f||2,r=!1,q=0,h;return{destroy:k,bind:function(){if(!d)return!1;c.vertexAttribPointer(A,w,c.FLOAT,!1,0,0)},data:h,build:function(b, f,p){var n;h=b||[];if(!(h&&0!==h.length||r))return k(),!1;w=p||w;d&&c.deleteBuffer(d);r||(n=new Float32Array(h));d=c.createBuffer();c.bindBuffer(c.ARRAY_BUFFER,d);c.bufferData(c.ARRAY_BUFFER,r||n,c.STATIC_DRAW);A=c.getAttribLocation(E.program(),f);c.enableVertexAttribArray(A);return!0},render:function(b,k,p){var n=r?r.length:h.length;if(!d||!n)return!1;if(!b||b>n||0>b)b=0;if(!k||k>n)k=n;c.drawArrays(c[(p||"points").toUpperCase()],b/w,(k-b)/w);return!0},allocate:function(b){q=-1;r=new Float32Array(4* b)},push:function(b,c,d,n){r&&(r[++q]=b,r[++q]=c,r[++q]=d,r[++q]=n)}}}});m(c,"modules/boost/wgl-renderer.js",[c["parts/Globals.js"],c["modules/boost/wgl-shader.js"],c["modules/boost/wgl-vbuffer.js"],c["parts/Color.js"],c["parts/Utilities.js"]],function(c,E,f,C,d){var k=C.parse,w=d.isNumber,r=d.isObject,q=d.merge,h=d.objectEach,b=d.pick,N=c.win.document;return function(d){function p(a){if(a.isSeriesBoosting){var b=!!a.options.stacking;var R=a.xData||a.options.xData||a.processedXData;b=(b?a.data:R|| a.options.data).length;"treemap"===a.type?b*=12:"heatmap"===a.type?b*=6:U[a.type]&&(b*=2);return b}return 0}function l(){e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT)}function D(a,b){function c(a){a&&(b.colorData.push(a[0]),b.colorData.push(a[1]),b.colorData.push(a[2]),b.colorData.push(a[3]))}function e(a,b,e,g,d){c(d);z.usePreallocated?A.push(a,b,e?1:0,g||1):(O.push(a),O.push(b),O.push(e?1:0),O.push(g||1))}function g(){b.segments.length&&(b.segments[b.segments.length-1].to=O.length)}function d(){b.segments.length&& b.segments[b.segments.length-1].from===O.length||(g(),b.segments.push({from:O.length}))}function p(a,b,g,d,y){c(y);e(a+g,b);c(y);e(a,b);c(y);e(a,b+d);c(y);e(a,b+d);c(y);e(a+g,b+d);c(y);e(a+g,b)}function t(a,c){z.useGPUTranslations||(b.skipTranslation=!0,a.x=m.toPixels(a.x,!0),a.y=q.toPixels(a.y,!0));c?O=[a.x,a.y,0,2].concat(O):e(a.x,a.y,0,2)}var R=a.pointArrayMap&&"low,high"===a.pointArrayMap.join(","),H=a.chart,y=a.options,n=!!y.stacking,w=y.data,l=a.xAxis.getExtremes(),v=l.min;l=l.max;var h=a.yAxis.getExtremes(), M=h.min;h=h.max;var f=a.xData||y.xData||a.processedXData,G=a.yData||y.yData||a.processedYData,D=a.zData||y.zData||a.processedZData,q=a.yAxis,m=a.xAxis,E=a.chart.plotWidth,N=!f||0===f.length,K=y.connectNulls,u=a.points||!1,J=!1,L=!1,S;f=n?a.data:f||w;var P={x:Number.MAX_VALUE,y:0},Q={x:-Number.MAX_VALUE,y:0},Y=0,la=!1,I=-1,T=!1,W=!1,ba="undefined"===typeof H.index,ha=!1,ia=!1;var x=!1;var va=U[a.type],ja=!1,ra=!0,sa=!0,aa=y.zones||!1,X=!1,ta=y.threshold,ka=!1;if(!(y.boostData&&0b.node.levelDynamic)return 1;if(a.node.levelDynamicb.zMax&&(b.zMax=F[2]);F[2]b.zMax&&(b.zMax=D[I]),D[I]=v&&W<=l&&(ha=!0);T&&T>=v&&T<=l&&(ia=!0);if(R){N&&(B=F.slice(1,3));var ca= B[0];B=B[1]}else n&&(u=F.x,B=F.stackY,ca=B-F.y);null!==M&&"undefined"!==typeof M&&null!==h&&"undefined"!==typeof h&&(ra=B>=M&&B<=h);u>l&&Q.xv&&(P.x=u,P.y=B);if(null!==B||!K)if(null!==B&&(ra||ha||ia)){if((W>=v||u>=v)&&(T<=l||u<=l)&&(ja=!0),ja||ha||ia){ka&&u-T>ka&&d();aa&&(x=X.rgba,aa.some(function(a,b){b=aa[b-1];if("undefined"!==typeof a.value&&B<=a.value){if(!b||B>=b.value)x=k(a.color).rgba;return!0}return!1}),x[0]/=255,x[1]/=255,x[2]/=255);if(!z.useGPUTranslations&&(b.skipTranslation= !0,u=m.toPixels(u,!0),B=q.toPixels(B,!0),u>E&&"points"===b.drawMode))continue;if(va){F=ca;if(!1===ca||"undefined"===typeof ca)F=0>B?B:0;R||n||(F=Math.max(null===ta?M:ta,M));z.useGPUTranslations||(F=q.toPixels(F,!0));e(u,F,0,0,x)}b.hasMarkers&&ja&&!1!==J&&(a.closestPointRangePx=Math.min(a.closestPointRangePx,Math.abs(u-J)));!z.useGPUTranslations&&!z.usePreallocated&&J&&1>Math.abs(u-J)&&L&&1>Math.abs(B-L)?z.debug.showSkipSummary&&++Y:(y.step&&!sa&&e(u,L,0,2,x),e(u,B,0,"bubble"===a.type?ua||1:2,x),J= u,L=B,la=!0,sa=!1)}}else d()}else d()}z.debug.showSkipSummary&&console.log("skipped points:",Y);la||!1===K||"line_strip"!==a.drawMode||(P.x-Number.MAX_VALUE&&t(Q))}g()}}function G(){K=[];Q.data=O=[];Y=[];A&&A.destroy()}function a(a){g&&(g.setUniform("xAxisTrans",a.transA),g.setUniform("xAxisMin",a.min),g.setUniform("xAxisMinPad",a.minPixelPadding),g.setUniform("xAxisPointRange",a.pointRange),g.setUniform("xAxisLen",a.len),g.setUniform("xAxisPos",a.pos),g.setUniform("xAxisCVSCoord", !a.horiz),g.setUniform("xAxisIsLog",!!a.logarithmic),g.setUniform("xAxisReversed",!!a.reversed))}function t(a){g&&(g.setUniform("yAxisTrans",a.transA),g.setUniform("yAxisMin",a.min),g.setUniform("yAxisMinPad",a.minPixelPadding),g.setUniform("yAxisPointRange",a.pointRange),g.setUniform("yAxisLen",a.len),g.setUniform("yAxisPos",a.pos),g.setUniform("yAxisCVSCoord",!a.horiz),g.setUniform("yAxisIsLog",!!a.logarithmic),g.setUniform("yAxisReversed",!!a.reversed))}function H(a,b){g.setUniform("hasThreshold", a);g.setUniform("translatedThreshold",b)}function v(p){if(p)m=p.chartWidth||800,J=p.chartHeight||400;else return!1;if(!(e&&m&&J&&g))return!1;z.debug.timeRendering&&console.time("gl rendering");e.canvas.width=m;e.canvas.height=J;g.bind();e.viewport(0,0,m,J);g.setPMatrix([2/m,0,0,0,0,-(2/J),0,0,0,0,-2,0,-1,1,-1,1]);12*((n.marker?n.marker.radius:10)||10));l=L[l&&l.symbol||c.series.symbol]||L.circle;if(!(0===c.segments.length||c.segmentslength&&c.segments[0].from===c.segments[0].to)){l.isReady&&(e.bindTexture(e.TEXTURE_2D,l.handle),g.setTexture(l.handle));p.styledMode?l=c.series.markerGroup&&c.series.markerGroup.getStyle("fill"): (l=c.series.pointAttribs&&c.series.pointAttribs().fill||c.series.color,n.colorByPoint&&(l=c.series.chart.options.colors[d]));c.series.fillOpacity&&n.fillOpacity&&(l=(new C(l)).setOpacity(b(n.fillOpacity,1)).get());l=k(l).rgba;z.useAlpha||(l[3]=1);"lines"===c.drawMode&&z.useAlpha&&1>l[3]&&(l[3]/=10);"add"===n.boostBlending?(e.blendFunc(e.SRC_ALPHA,e.ONE),e.blendEquation(e.FUNC_ADD)):"mult"===n.boostBlending||"multiply"===n.boostBlending?e.blendFunc(e.DST_COLOR,e.ZERO):"darken"===n.boostBlending?(e.blendFunc(e.ONE, e.ONE),e.blendEquation(e.FUNC_MIN)):e.blendFuncSeparate(e.SRC_ALPHA,e.ONE_MINUS_SRC_ALPHA,e.ONE,e.ONE_MINUS_SRC_ALPHA);g.reset();0=(a.options.boostThreshold||Number.MAX_VALUE)&&++c)}b.boostForceChartBoost=k&&(f===b.series.length&&0=D&&t<=N);if(null!==t&&h>=r&&h<=A&&f)if(a=k.toPixels(h,!0),ba){if("undefined"===typeof V||a===U){y||(c=t);if("undefined"===typeof Z||t>ea)ea=t,Z=b;if("undefined"===typeof V||c=(c.options.boostThreshold||Number.MAX_VALUE)}var c=this,d=this.options.data;p(this.chart)&&A[this.type]?(b(d)&&"heatmap"!==this.type&&"treemap"!==this.type&& !this.options.stacking&&this.hasExtremes&&this.hasExtremes(!0)||(a.apply(this,Array.prototype.slice.call(arguments,1)),d=this.processedXData),(this.isSeriesBoosting=b(d))?(d=this.getFirstValidPoint(this.options.data),h(d)||q(d)||r(12,!1,this.chart),this.enterBoost()):this.exitBoost&&this.exitBoost()):a.apply(this,Array.prototype.slice.call(arguments,1))});k(l,"hide",function(){this.canvas&&this.renderTarget&&(this.ogl&&this.ogl.clear(),this.boostClear())});l.prototype.enterBoost=function(){this.alteredByBoost= [];["allowDG","directTouch","stickyTracking"].forEach(function(a){this.alteredByBoost.push({prop:a,val:this[a],own:Object.hasOwnProperty.call(this,a)})},this);this.directTouch=this.allowDG=!1;this.stickyTracking=!0;this.labelBySeries&&(this.labelBySeries=this.labelBySeries.destroy())};l.prototype.exitBoost=function(){(this.alteredByBoost||[]).forEach(function(a){a.own?this[a.prop]=a.val:delete this[a.prop]},this);this.boostClear&&this.boostClear()};l.prototype.hasExtremes=function(a){var b=this.options, c=this.xAxis&&this.xAxis.options,d=this.yAxis&&this.yAxis.options,f=this.colorAxis&&this.colorAxis.options;return b.data.length>(b.boostThreshold||Number.MAX_VALUE)&&h(d.min)&&h(d.max)&&(!a||h(c.min)&&h(c.max))&&(!f||h(f.min)&&h(f.max))};l.prototype.destroyGraphics=function(){var a=this,b=this.points,c,d;if(b)for(d=0;d