UNPKG

openalgo-charts

Version:

From-scratch, dependency-free canvas charting engine for OpenAlgo: professional-grade interactive rendering, advanced on-chart trading, and a one-call widget tier that adds the toolbar, drawing rail, dialogs and shortcuts.

3 lines (2 loc) 21.5 kB
import{registeredChartTypes as e,getChartType as t,registerRenderBackend as o}from"./openalgo-charts.mjs";const r={upColor:"#26a69a",downColor:"#ef5350",borderUpColor:"#26a69a",borderDownColor:"#ef5350",wickUpColor:"#26a69a",wickDownColor:"#ef5350",borderVisible:!0,wickVisible:!0};function i(e,t){const o=Math.floor(e*t*.8);let r=Math.max(1,o);if(r>=2){r%2!=Math.max(1,Math.floor(t))%2&&(r-=1)}return Math.max(1,r)}function n(e,t,o){return o.wickVisible?!0===o.hollow||!1===o.bodyVisible||e>t||o.borderVisible&&e>=3||o.upColor!==o.wickUpColor||o.downColor!==o.wickDownColor?"full":"wick":"full"}function l(e,t,o,r=1){const n=i(t,o),l=Math.max(1,Math.floor(o)),a=Math.round(e*o),s=Math.max(.05,Math.min(1,r)),c=1===s?n:Math.max(1,Math.round(n*s));return{cx:a,bodyX:a-Math.floor(c/2),bodyW:c,wickX:a-Math.floor(l/2),wickW:l}}function a(e,t,o){const r=e.bar;return{cx:Math.round(e.x*o),yOpen:Math.round(t(r.open)*o),yClose:Math.round(t(r.close)*o),yHigh:Math.round(t(r.high)*o),yLow:Math.round(t(r.low)*o),up:r.close>=r.open}}function s(e,t,o=e=>e.close){return e.map(e=>({x:e.x,y:t(o(e.bar))}))}const c=11,u=1e6,h=e=>e===Math.round(e);class b{constructor(e=256){Object.defineProperty(this,"vertices",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"indices",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"quadCount",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_capacity",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this._capacity=Math.max(1,e),this.vertices=new Float32Array(4*this._capacity*c),this.indices=new Uint32Array(6*this._capacity),this._fillIndices(0)}get capacity(){return this._capacity}get vertexCount(){return 4*this.quadCount}get indexCount(){return 6*this.quadCount}get floatCount(){return this.vertexCount*c}reset(){this.quadCount=0}rect(e,t,o,r,i){if(!(o>0&&r>0))return;const n=o/2,l=r/2,a=e+n,s=t+l,u=h(e)&&h(t)&&h(e+o)&&h(t+r)?0:1,b=n+u,f=l+u,d=this._claim(),_=this.vertices;this._vertex(_,d,a-b,s-f,i,-b,-f,n,l,0),this._vertex(_,d+c,a+b,s-f,i,b,-f,n,l,0),this._vertex(_,d+22,a-b,s+f,i,-b,f,n,l,0),this._vertex(_,d+33,a+b,s+f,i,b,f,n,l,0)}segment(e,t,o,r,i,n,l){if(!(i>0))return;const a=o-e,s=r-t,u=Math.hypot(a,s);if(!Number.isFinite(u))return;if(0===u&&!l)return;const h=0===u?1:a/u,b=0===u?0:s/u,f=(e+o)/2,d=(t+r)/2,_=u/2,m=_,p=l?0:i,g=l?i:0,v=_+i+1,w=i+1,x=this._claim(),y=this.vertices;this._vertex(y,x,f-h*v+b*w,d-b*v-h*w,n,-v,-w,m,p,g),this._vertex(y,x+c,f+h*v+b*w,d+b*v-h*w,n,v,-w,m,p,g),this._vertex(y,x+22,f-h*v-b*w,d-b*v+h*w,n,-v,w,m,p,g),this._vertex(y,x+33,f+h*v-b*w,d+b*v+h*w,n,v,w,m,p,g)}quad(e,t,o,r,i,n,l,a,s,h,b,f){const d=this._claim(),_=this.vertices;this._vertex(_,d,e,t,o,0,0,u,u,0),this._vertex(_,d+c,r,i,n,0,0,u,u,0),this._vertex(_,d+22,l,a,s,0,0,u,u,0),this._vertex(_,d+33,h,b,f,0,0,u,u,0)}triangle(e,t,o,r,i,n,l,a,s){this.quad(e,t,o,r,i,n,l,a,s,l,a,s)}_claim(){this.quadCount===this._capacity&&this._grow();const e=4*this.quadCount*c;return this.quadCount++,e}_vertex(e,t,o,r,i,n,l,a,s,c){e[t]=o,e[t+1]=r,e[t+2]=i[0],e[t+3]=i[1],e[t+4]=i[2],e[t+5]=i[3],e[t+6]=n,e[t+7]=l,e[t+8]=a,e[t+9]=s,e[t+10]=c}_grow(){const e=this._capacity;this._capacity*=2;const t=new Float32Array(4*this._capacity*c);t.set(this.vertices),this.vertices=t;const o=new Uint32Array(6*this._capacity);o.set(this.indices),this.indices=o,this._fillIndices(e)}_fillIndices(e){const t=this.indices;for(let o=e;o<this._capacity;o++){const e=4*o,r=6*o;t[r]=e,t[r+1]=e+1,t[r+2]=e+2,t[r+3]=e+2,t[r+4]=e+1,t[r+5]=e+3}}}const f=[0,0,0,0];function d(e){return e>0?e<1?e:1:0}function _(e){const t=function(e){const t=e.trim();if(t.startsWith("#")){const e=t.slice(1);if(3===e.length||4===e.length){const[t,o,r,i]=[...e].map(e=>parseInt(e+e,16));return[t,o,r].some(Number.isNaN)?null:{r:t,g:o,b:r,a:4===e.length?i/255:1}}if(6===e.length||8===e.length){const t=parseInt(e.slice(0,6),16);if(Number.isNaN(t))return null;const o=8===e.length?parseInt(e.slice(6,8),16)/255:1;return{r:t>>16&255,g:t>>8&255,b:255&t,a:Number.isNaN(o)?1:o}}return null}const o=/^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*(?:,\s*([\d.]+)\s*)?\)$/i.exec(t);return null===o?null:{r:Number(o[1]),g:Number(o[2]),b:Number(o[3]),a:void 0===o[4]?1:Number(o[4])}}(e);if(null===t)return null;const o=d(t.a);return[d(t.r/255)*o,d(t.g/255)*o,d(t.b/255)*o,o]}function m(e,t,o){return[e[0]+(t[0]-e[0])*o,e[1]+(t[1]-e[1])*o,e[2]+(t[2]-e[2])*o,e[3]+(t[3]-e[3])*o]}class p{constructor(){Object.defineProperty(this,"_map",{enumerable:!0,configurable:!0,writable:!0,value:new Map})}get(e,t){let o=this._map.get(e);if(void 0!==o)return o;if(o=_(e)??void 0,void 0===o&&void 0!==t){const r=t(e);null!==r&&(o=_(r)??void 0)}return void 0===o&&(o=f),this._map.size>=4096&&this._map.clear(),this._map.set(e,o),o}get size(){return this._map.size}clear(){this._map.clear()}}function g(e,t,o){const r=e.createShader(t);if(null===r)throw new Error("openalgo-charts: could not create a WebGL shader");if(e.shaderSource(r,o),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)&&!e.isContextLost()){const t=e.getShaderInfoLog(r)??"";throw e.deleteShader(r),new Error(`openalgo-charts: WebGL shader failed to compile: ${t}`)}return r}const v={alpha:!0,antialias:!1,premultipliedAlpha:!0,preserveDrawingBuffer:!1,depth:!1,stencil:!1};function w(){const e=globalThis.document;if(void 0!==e&&"function"==typeof e.createElement)return e.createElement("canvas");const t=globalThis.OffscreenCanvas;return void 0!==t?new t(1,1):null}class x{constructor(e=w){Object.defineProperty(this,"colors",{enumerable:!0,configurable:!0,writable:!0,value:new p}),Object.defineProperty(this,"_createSurface",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_surface",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_gl",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_program",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_vao",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_vbo",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_ibo",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_indexCapacity",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_refs",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_lost",{enumerable:!0,configurable:!0,writable:!0,value:!1}),Object.defineProperty(this,"_probed",{enumerable:!0,configurable:!0,writable:!0,value:!1}),Object.defineProperty(this,"_onLost",{enumerable:!0,configurable:!0,writable:!0,value:e=>{e.preventDefault(),this._lost=!0,this._program=null,this._vao=null,this._vbo=null,this._ibo=null,this._indexCapacity=0}}),Object.defineProperty(this,"_onRestored",{enumerable:!0,configurable:!0,writable:!0,value:()=>{this._lost=!1}}),this._createSurface=e}get available(){if(!this._probed){this._probed=!0,this._surface=this._createSurface();const e=this._surface?.getContext("webgl2",v)??null;null!==e&&(this._gl=e,this._surface?.addEventListener?.("webglcontextlost",this._onLost),this._surface?.addEventListener?.("webglcontextrestored",this._onRestored))}return null!==this._gl}get lost(){return this._lost||null!==this._gl&&this._gl.isContextLost()}get surface(){return this._surface}get refs(){return this._refs}get gl(){return this._gl}acquire(){return!!this.available&&(this._refs++,!0)}release(){0!==this._refs&&(this._refs--,0===this._refs&&null!==this._surface&&(this._surface.width=1,this._surface.height=1))}ensureSize(e,t){const o=this._surface;null!==o&&(o.width<e&&(o.width=e),o.height<t&&(o.height=t))}render(e,t,o){if(null===this._gl||null===this._surface||this.lost)return!1;const r=this._gl;if(null===this._program&&!this._setup(r))return!1;const i=this._program;this.ensureSize(t,o);const n=this._surface.height-o;return r.viewport(0,n,t,o),r.enable(r.SCISSOR_TEST),r.scissor(0,n,t,o),r.clearColor(0,0,0,0),r.clear(r.COLOR_BUFFER_BIT),0===e.quadCount||(r.useProgram(i.program),r.uniform2f(i.uResolution,t,o),r.bindVertexArray(this._vao),r.bindBuffer(r.ARRAY_BUFFER,this._vbo),r.bufferData(r.ARRAY_BUFFER,e.vertices,r.STREAM_DRAW,0,e.floatCount),e.indices.length>this._indexCapacity&&(r.bindBuffer(r.ELEMENT_ARRAY_BUFFER,this._ibo),r.bufferData(r.ELEMENT_ARRAY_BUFFER,e.indices,r.STATIC_DRAW),this._indexCapacity=e.indices.length),r.drawElements(r.TRIANGLES,e.indexCount,r.UNSIGNED_INT,0),r.bindVertexArray(null)),!0}_setup(e){let t;try{t=function(e){const t=g(e,e.VERTEX_SHADER,"#version 300 es\nprecision highp float;\nuniform vec2 u_resolution;\nin vec2 a_pos;\nin vec4 a_color;\nin vec2 a_local;\nin vec3 a_shape;\nout vec4 v_color;\nout vec2 v_local;\nflat out vec3 v_shape;\nvoid main() {\n vec2 clip = vec2(a_pos.x / u_resolution.x * 2.0 - 1.0, 1.0 - a_pos.y / u_resolution.y * 2.0);\n gl_Position = vec4(clip, 0.0, 1.0);\n v_color = a_color;\n v_local = a_local;\n v_shape = a_shape;\n}\n"),o=g(e,e.FRAGMENT_SHADER,"#version 300 es\nprecision highp float;\nin vec4 v_color;\nin vec2 v_local;\nflat in vec3 v_shape;\nout vec4 fragColor;\nvoid main() {\n vec2 q = abs(v_local) - v_shape.xy;\n float d = length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - v_shape.z;\n float cov = clamp(0.5 - d, 0.0, 1.0);\n fragColor = clamp(v_color, 0.0, 1.0) * cov;\n}\n"),r=e.createProgram();if(null===r)throw new Error("openalgo-charts: could not create a WebGL program");if(e.attachShader(r,t),e.attachShader(r,o),e.linkProgram(r),e.deleteShader(t),e.deleteShader(o),!e.getProgramParameter(r,e.LINK_STATUS)&&!e.isContextLost()){const t=e.getProgramInfoLog(r)??"";throw e.deleteProgram(r),new Error(`openalgo-charts: WebGL program failed to link: ${t}`)}return{program:r,aPos:e.getAttribLocation(r,"a_pos"),aColor:e.getAttribLocation(r,"a_color"),aLocal:e.getAttribLocation(r,"a_local"),aShape:e.getAttribLocation(r,"a_shape"),uResolution:e.getUniformLocation(r,"u_resolution")}}(e)}catch{return this._gl=null,!1}return this._program=t,this._vao=e.createVertexArray(),this._vbo=e.createBuffer(),this._ibo=e.createBuffer(),this._indexCapacity=0,e.bindVertexArray(this._vao),e.bindBuffer(e.ARRAY_BUFFER,this._vbo),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this._ibo),function(e,t){e.enableVertexAttribArray(t.aPos),e.vertexAttribPointer(t.aPos,2,e.FLOAT,!1,44,0),e.enableVertexAttribArray(t.aColor),e.vertexAttribPointer(t.aColor,4,e.FLOAT,!1,44,8),e.enableVertexAttribArray(t.aLocal),e.vertexAttribPointer(t.aLocal,2,e.FLOAT,!1,44,24),e.enableVertexAttribArray(t.aShape),e.vertexAttribPointer(t.aShape,3,e.FLOAT,!1,44,32)}(e,t),e.bindVertexArray(null),e.disable(e.DEPTH_TEST),e.disable(e.CULL_FACE),e.enable(e.BLEND),e.blendFunc(e.ONE,e.ONE_MINUS_SRC_ALPHA),!0}}let y=null;function C(){return null===y&&(y=new x),y}function M(){return void 0!==globalThis.WebGL2RenderingContext&&C().available}function P(e,t,o={}){return{...r,upColor:e.upColor??t.upColor,downColor:e.downColor??t.downColor,borderUpColor:e.borderUpColor??t.upColor,borderDownColor:e.borderDownColor??t.downColor,wickUpColor:e.wickUpColor??t.wickUpColor,wickDownColor:e.wickDownColor??t.wickDownColor,borderVisible:e.borderVisible??r.borderVisible,bodyVisible:e.bodyVisible??!0,wickVisible:e.wickVisible??r.wickVisible,colorByPreviousClose:e.colorByPreviousClose,...o}}function A(e,t,o,r,i,n,l){const a=t-n/2,s=o-n/2,c=r+n,u=i+n;r-n<=0||i-n<=0?e.rect(a,s,c,u,l):(e.rect(a,s,c,n,l),e.rect(a,s+u-n,c,n,l),e.rect(a,s+n,n,u-2*n,l),e.rect(a+c-n,s+n,n,u-2*n,l))}function S(e,t,o,r,a,s,c){const u=i(r,a),h=Math.max(1,Math.floor(a)),b=s.widthScale?null:n(u,h,s);for(let i=0;i<t.length;i++){const{x:u,bar:f}=t[i],d=i>0?t[i-1].bar.close:t[i].prevClose,_=!0===s.colorByPreviousClose&&void 0!==d&&Number.isFinite(d)?f.close>=d:f.close>=f.open,m=Math.round(o(f.open)*a),p=Math.round(o(f.close)*a),g=Math.round(o(f.high)*a),v=Math.round(o(f.low)*a),w=l(u,r,a,s.widthScale?s.widthScale(f):1),x=w.cx,y=w.bodyW,C=x-w.bodyX,M=f.color;if(s.wickVisible&&e.rect(w.wickX,g,w.wickW,Math.max(1,v-g),c(M??(_?s.wickUpColor:s.wickDownColor))),"wick"===(b??n(y,h,s)))continue;const P=Math.min(m,p),S=Math.max(1,Math.abs(p-m)),k=M??(_?s.upColor:s.downColor),N=M??(_?s.borderUpColor:s.borderDownColor);if(s.hollow&&_)A(e,x-C+.5,P+.5,y-1,S-1,Math.max(1,h),c(s.borderVisible?N:k));else{const t=!1!==s.bodyVisible;t&&e.rect(x-C,P,y,S,c(k)),s.borderVisible&&(!t||y>=3)&&A(e,x-C+.5,P+.5,y-1,S-1,1,c(N))}}}function k(e,t,o,r,i,n,l,a,s){const c=Math.hypot(r-t,i-o);if(0===c)return;const u=(r-t)/c,h=(i-o)/c;let b=0;for(;b<c;){const r=Math.min(s.rem,c-b);s.idx%2==0&&r>0&&e.segment(t+u*b,o+h*b,t+u*(b+r),o+h*(b+r),n,l,!0),b+=r,s.rem-=r,s.rem<=1e-9&&(s.idx=(s.idx+1)%a.length,s.rem=a[s.idx])}}function N(e,t,o,r,i,n,l,a){let s=l;s.length%2==1&&(s=s.concat(s));let c=0;for(const e of s)c+=e;const u=s.length>0&&c>0,h={idx:0,rem:u?s[0]:0};let b,f,d=a(i);for(let l=0;l<t.length;l++){const c=t[l];if(!Number.isFinite(c.x)||!Number.isFinite(c.y)){b=void 0;continue}if(void 0===b){b=c,h.idx=0,h.rem=u?s[0]:0;continue}const _=void 0===n?f:n[l];_!==f&&(f=_,d=a(_??i),h.idx=0,h.rem=u?s[0]:0),u?k(e,b.x*o,b.y*o,c.x*o,c.y*o,r,d,s,h):e.segment(b.x*o,b.y*o,c.x*o,c.y*o,r,d,!0),b=c}}function F(e,t,o,r,i,n){const l=s(t,o),a=i.step?function(e){if(0===e.length)return[];const t=[{...e[0]}];for(let o=1;o<e.length;o++)t.push({x:e[o].x,y:e[o-1].y}),t.push({x:e[o].x,y:e[o].y});return t}(l):l,c=function(e,t){let o=!1;for(const t of e)if(void 0!==t.bar.color){o=!0;break}if(!o)return;const r=[];for(const o of e)t&&r.length>0&&r.push(o.bar.color),r.push(o.bar.color);return r}(t,!0===i.step),u=i.color??"#4f8cff",h=Math.max(1,(i.lineWidth??1.5)*r)/2;if(i.markersOnly||N(e,a,r,h,u,c,function(e,t){return"dashed"===e.lineStyle?[6*t,4*t]:"dotted"===e.lineStyle?[1*t,3*t]:[]}(i,r),n),i.markers||i.markersOnly){const o=(i.markerRadius??2)*r;for(let i=0;i<l.length;i++){const a=l[i];if(!Number.isFinite(a.x)||!Number.isFinite(a.y))continue;const s=n(void 0!==c?t[i].bar.color??u:u);e.segment(a.x*r,a.y*r,a.x*r,a.y*r,o,s,!0)}}}function O(e,t,o,r,i,n){const l=i(r);let a=NaN,s=NaN;for(const c of t){const t=c.x*o,u=c.y*o;if(Number.isFinite(t)&&Number.isFinite(u)){if(Number.isFinite(a)){const o=s<=r,c=u<=r;if(o===c)"both"!==n&&"above"===n!==o||e.quad(a,s,i(s),t,u,i(u),a,r,l,t,r,l);else{const h=a+(t-a)*(r-s)/(u-s);"both"!==n&&"above"===n!==o||e.triangle(a,s,i(s),h,r,l,a,r,l),"both"!==n&&"above"===n!==c||e.triangle(t,u,i(u),h,r,l,t,r,l)}}a=t,s=u}}}const E=["candlestick","hollow-candle","volume-candle","bar","high-low","line","line-markers","step","area","hlc-area","baseline","column","histogram"],L=new WeakMap;class T{constructor(e=C()){Object.defineProperty(this,"kind",{enumerable:!0,configurable:!0,writable:!0,value:"webgl2"}),Object.defineProperty(this,"device",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_batch",{enumerable:!0,configurable:!0,writable:!0,value:new b}),Object.defineProperty(this,"_canvas",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_ctx",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_widthPx",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_heightPx",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"_acquired",{enumerable:!0,configurable:!0,writable:!0,value:!1}),Object.defineProperty(this,"_frame2d",{enumerable:!0,configurable:!0,writable:!0,value:!1}),Object.defineProperty(this,"_color",{enumerable:!0,configurable:!0,writable:!0,value:e=>this.device.colors.get(e,this._normalise)}),Object.defineProperty(this,"_normalise",{enumerable:!0,configurable:!0,writable:!0,value:e=>null===this._ctx?null:function(e,t){const o=e.fillStyle;e.fillStyle="#000000",e.fillStyle=t;const r=e.fillStyle;e.fillStyle="#ffffff",e.fillStyle=t;const i=e.fillStyle;return e.fillStyle=o,"string"==typeof r&&r===i?r:null}(this._ctx,e)}),this.device=e}get batch(){return this._batch}mount(e,t){if(this._canvas=e,this._ctx=t??e.getContext("2d"),null===this._ctx)throw new Error("openalgo-charts: 2D canvas context is not available");this._widthPx=e.width,this._heightPx=e.height,this._acquired=this.device.acquire(),this.device.ensureSize(this._widthPx,this._heightPx)}resize(e,t,o){this._widthPx=Math.round(e*o),this._heightPx=Math.round(t*o),this.device.ensureSize(this._widthPx,this._heightPx)}beginFrame(e){this._batch.reset(),this._frame2d=this.device.lost||null===this.device.gl,e&&null!==this._ctx&&null!==this._canvas&&(this._ctx.setTransform(1,0,0,1,0,0),this._ctx.clearRect(0,0,this._canvas.width,this._canvas.height))}drawSeries(o,r,n,l,c,u,h){if(null===this._ctx)return;!this._frame2d&&this.device.lost&&(this._frame2d=!0,this._batch.reset());const b=this._frame2d?null:function(o){let r=L.get(o);if(void 0===r){r=null;const i=new Set(e());for(const e of E)if(i.has(e)&&t(e)===o){r=e;break}L.set(o,r)}return r}(o);if(null===b)return this._flush(),void o.draw(this._ctx,r,n,l,c,u,h);const d=this._batch,_=this._color,p=h.theme;switch(b){case"candlestick":S(d,r,n,l,c,P(u,p),_);break;case"hollow-candle":S(d,r,n,l,c,P(u,p,{hollow:!0}),_);break;case"volume-candle":{const e=h.maxVolume;S(d,r,n,l,c,P(u,p,{widthScale:t=>e>0?(t.volume??0)/e:1}),_);break}case"bar":case"high-low":!function(e,t,o,r,n,l,s,c){const u=Math.max(1,Math.floor(i(r,n)/2)),h=Math.max(1,Math.floor(n));for(let r=0;r<t.length;r++){const i=t[r],b=a(i,o,n),f=r>0?t[r-1].bar.close:i.prevClose,d=!0===l.colorByPreviousClose&&void 0!==f&&Number.isFinite(f)?i.bar.close>=f:b.up,_=c(i.bar.color??(d?l.upColor??"#26a69a":l.downColor??"#ef5350"));e.rect(b.cx-Math.floor(h/2),b.yHigh,h,Math.max(1,b.yLow-b.yHigh),_),s||(e.rect(b.cx-u,b.yOpen,u,h,_),e.rect(b.cx,b.yClose,u,h,_))}}(d,r,n,l,c,{...u,upColor:u.upColor??p.upColor,downColor:u.downColor??p.downColor},"high-low"===b,_);break;case"line":F(d,r,n,c,{...u,color:u.color??p.lineColor},_);break;case"line-markers":F(d,r,n,c,{...u,color:u.color??p.lineColor,markers:!0},_);break;case"step":F(d,r,n,c,{...u,color:u.color??p.lineColor,step:!0},_);break;case"area":!function(e,t,o,r,i,n,l){const a=s(t,o);if(0===a.length)return;const c=i*r;if(c>0){const t=l(n.areaTopColor??"rgba(79,140,255,0.40)"),o=l(n.areaBottomColor??"rgba(79,140,255,0.00)");O(e,a,r,c,e=>m(t,o,e/c),"both")}F(e,t,o,r,{color:n.color??"#4f8cff",lineWidth:n.lineWidth??1.5,lineStyle:n.lineStyle},l)}(d,r,n,c,h.plotHeight,{...u,color:u.color??p.lineColor,areaTopColor:u.areaTopColor??p.areaTopColor,areaBottomColor:u.areaBottomColor??p.areaBottomColor},_);break;case"hlc-area":!function(e,t,o,r,i,n){if(0===t.length)return;const l=s(t,o,e=>e.high),a=s(t,o,e=>e.low),c=n(i.areaTopColor??"rgba(79,140,255,0.15)");let u=-1;for(let o=0;o<t.length;o++){const t=l[o],i=a[o];if(Number.isFinite(t.x)&&Number.isFinite(t.y)&&Number.isFinite(i.y)){if(u>=0){const o=l[u],n=a[u];e.quad(o.x*r,o.y*r,c,t.x*r,t.y*r,c,n.x*r,n.y*r,c,i.x*r,i.y*r,c)}u=o}}const h=Math.max(1,Math.round((i.lineWidth??1.5)*r))/2;for(const[t,o]of[[i.highColor,l],[i.lowColor,a]])void 0!==t&&N(e,o,r,h,t,void 0,[],n);F(e,t,o,r,{color:i.closeColor??"#4f8cff",lineWidth:i.lineWidth??1.5},n)}(d,r,n,c,{...u,closeColor:u.closeColor??p.lineColor},_);break;case"baseline":!function(e,t,o,r,i,n){const l=o(i.baseValue??0)*r,a=s(t,o);if(0===a.length||!Number.isFinite(l))return;if(l>0){const t=n(i.areaTopColor??"rgba(38,166,154,0.20)");O(e,a,r,l,e=>m(t,f,e/l),"above")}const c=n(i.areaBottomColor??"rgba(239,83,80,0.20)");O(e,a,r,l,()=>c,"below");const u=Math.max(1,Math.round((i.lineWidth??1.5)*r))/2,h=n(i.topColor??"#26a69a"),b=n(i.bottomColor??"#ef5350");for(let t=1;t<a.length;t++){const o=a[t-1],i=a[t];if(!(Number.isFinite(o.x)&&Number.isFinite(o.y)&&Number.isFinite(i.x)&&Number.isFinite(i.y)))continue;const n=(o.y+i.y)/2<=l/r;e.segment(o.x*r,o.y*r,i.x*r,i.y*r,u,n?h:b,!1)}}(d,r,n,c,{...u,topColor:u.topColor??p.baselineTopLine,bottomColor:u.bottomColor??p.baselineBottomLine,areaTopColor:u.areaTopColor??p.baselineTopFill,areaBottomColor:u.areaBottomColor??p.baselineBottomFill},_);break;case"column":!function(e,t,o,r,n,l,s){const c=i(r,n),u=Math.floor(c/2),h=Math.round(o(l.base??0)*n);for(const r of t){const t=a(r,o,n),i=r.bar.color??l.color??(t.up?l.upColor??"#26a69a":l.downColor??"#ef5350"),b=Math.min(h,t.yClose);e.rect(t.cx-u,b,c,Math.max(1,Math.abs(h-t.yClose)),s(i))}}(d,r,n,l,c,{...u,upColor:u.upColor??p.upColor,downColor:u.downColor??p.downColor},_);break;case"histogram":!function(e,t,o,r,n,l,a,s){const c=i(r,n),u=Math.floor(c/2),h=Math.round(o(a)*n);for(const{x:r,bar:i}of t){const t=Math.round(r*n),a=Math.round(o(i.close)*n),b=Math.min(h,a);e.rect(t-u,b,c,Math.max(1,Math.abs(h-a)),s(i.color??l))}}(d,r,n,l,c,u.color??"#3a4666",u.base??0,_)}}endFrame(){this._flush()}overlay2d(){return this._ctx}destroy(){this._acquired&&this.device.release(),this._acquired=!1,this._batch.reset(),this._ctx=null,this._canvas=null}_flush(){const e=this._batch;if(0===e.quadCount||null===this._ctx)return;const t=this._widthPx,o=this._heightPx,r=this.device.surface;t>0&&o>0&&null!==r&&this.device.render(e,t,o)&&this._ctx.drawImage(r,0,0,t,o,0,0,t,o),e.reset()}}function R(e){return void 0===e?M()?new T(C()):null:e.available?new T(e):null}const j="webgl";let B=!1;function V(){B||(B=!0,o("webgl2",()=>R()))}V();export{x as GlDevice,j as WEBGL_TIER,T as WebGL2Backend,R as createWebGL2Backend,M as isWebGL2Supported,V as registerWebGL2Renderer,C as sharedGlDevice}; //# sourceMappingURL=openalgo-charts.webgl.mjs.map