UNPKG

scichart

Version:

Fast WebGL JavaScript Charting Library and Framework

677 lines (676 loc) 34.6 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.WebGlRenderContext2D = exports.ELineDrawMode = exports.calculateAbsoluteRenderLayer = void 0; var app_1 = require("../../constants/app"); var Guard_1 = require("../../Core/Guard"); var Rect_1 = require("../../Core/Rect"); var createNativeRect_1 = require("../Visuals/Helpers/createNativeRect"); var NativeObject_1 = require("../Visuals/Helpers/NativeObject"); var DeletableEntity_1 = require("../../Core/DeletableEntity"); var performance_1 = require("../../utils/performance"); var Point_1 = require("../../Core/Point"); var AnchorPoint_1 = require("../../types/AnchorPoint"); var TextPosition_1 = require("../../types/TextPosition"); var colorUtil_1 = require("../../utils/colorUtil"); var parseColor_1 = require("../../utils/parseColor"); var text_1 = require("../../utils/text"); var SURFACE_LAYER_STEP = 1000; /** * @param surfaceOrder layer z-order offset of the surface * @param layerStep specifies the capacity of layers that could be potentially added between the default chart layers * @param relativeRenderLayer layer number relative to the specific surface layers * @returns absolute order of the layer on the chart (considering parent chart and previous subChart surface layers) */ var calculateAbsoluteRenderLayer = function (surfaceOrder, layerStep, relativeRenderLayer) { return surfaceOrder * SURFACE_LAYER_STEP + relativeRenderLayer * layerStep; }; exports.calculateAbsoluteRenderLayer = calculateAbsoluteRenderLayer; /** * Defines enumeration constants for Line Drawing modes */ var ELineDrawMode; (function (ELineDrawMode) { /** * Points provided define a poly-line (continuous line) */ ELineDrawMode["PolyLine"] = "PolyLine"; /** * Points provided define discontinuous lines, e.g. x1y1 x2y2 is one line, x3y3 x4y4 is the next */ ELineDrawMode["DiscontinuousLine"] = "DiscontinuousLine"; })(ELineDrawMode = exports.ELineDrawMode || (exports.ELineDrawMode = {})); /** * The WebGlRenderContext2D provides methods for drawing to a WebGL2 / WebAssembly canvas powered by SciChart's Visual Xccelerator engine. * This context class is used in SciChart's High Performance Realtime {@link https://www.scichart.com/javascript-chart-features | JavaScript Charts} * to draw shapes, lines, fills, images and more */ var WebGlRenderContext2D = /** @class */ (function (_super) { __extends(WebGlRenderContext2D, _super); /** * Creates an instance of the WebGlRenderContext2D * @param webAssemblyContext The {@link TSciChart | SciChart WebAssembly Context} containing native methods and access to our WebGL2 Engine * @param viewportSize The Viewport {@link Size} */ function WebGlRenderContext2D(webAssemblyContext, viewportSize, canvasId) { var _this = _super.call(this) || this; _this.layers = new Map(); _this.effects = []; _this.webAssemblyContext = webAssemblyContext; _this.viewportSize = viewportSize; _this.canvasId = canvasId; _this.currentClipRect = Rect_1.Rect.create(0, 0, viewportSize.width, viewportSize.height); _this.currentRotation = 0; _this.currentTranslationX = 0; _this.currentTranslationY = 0; return _this; } /** * Get the native {@link SCRTRenderContext} for direct access to SciChart's WebAssembly Visual Xccelerator engine */ WebGlRenderContext2D.prototype.getNativeContext = function () { if (!this.nativeContext) { this.nativeContext = this.webAssemblyContext.SCRTGetMainRenderContext2D(); } return this.nativeContext; }; /** * Draw lines: grid lines, etc. * @param vertices * @param pen * @param lineDrawMode * @param left - offset in pixels from left, typically used for axes * @param top - offset in pixels from top, typically used for axes */ WebGlRenderContext2D.prototype.drawLinesNative = function (vertices, pen, lineDrawMode, clipRect, left, top) { if (left === void 0) { left = 0; } if (top === void 0) { top = 0; } var isStrips = lineDrawMode === ELineDrawMode.PolyLine; var nativeContext = this.getNativeContext(); this.resetTransform(); this.translate(left, top); this.setClipRect(clipRect); var drawLineParams = new this.webAssemblyContext.SCRTDrawLinesParams(); drawLineParams.m_Type = isStrips ? this.webAssemblyContext.SCRTLineType.Strip : this.webAssemblyContext.SCRTLineType.List; drawLineParams.SetPen(pen); drawLineParams.SetPointsVec(vertices); nativeContext.DrawLines(drawLineParams); drawLineParams.delete(); }; /** * Draw rectangles: grid bands, etc. * @param vertices * @param brush * @param left - offset in pixels from left, typically used for axes * @param top - offset in pixels from top, typically used for axes */ WebGlRenderContext2D.prototype.drawRects = function (vertices, brush, clipRect, left, top) { if (left === void 0) { left = 0; } if (top === void 0) { top = 0; } var anchorParams = (0, NativeObject_1.getVector4)(this.webAssemblyContext, 0, 0, 0, 0); var nativeContext = this.getNativeContext(); this.resetTransform(); this.translate(left, top); this.setClipRect(clipRect); // this.EnsureContextTransform(left, top, clipRect); var drawRectsParams = new this.webAssemblyContext.SCRTDrawRectsParams(); drawRectsParams.SetVerticesVec(vertices); drawRectsParams.SetBrush(brush); drawRectsParams.m_vAnchorParams = anchorParams; nativeContext.DrawRects(drawRectsParams); drawRectsParams === null || drawRectsParams === void 0 ? void 0 : drawRectsParams.delete(); }; WebGlRenderContext2D.prototype.drawEllipses = function (vertices, pen, left, top) { if (left === void 0) { left = 0; } if (top === void 0) { top = 0; } var nativeContext = this.getNativeContext(); this.resetTransform(); this.translate(left, top); var drawRectsParams = new this.webAssemblyContext.SCRTDrawRectsParams(); drawRectsParams.SetVerticesVec(vertices); drawRectsParams.SetPen(pen); drawRectsParams.SetBrush(null); drawRectsParams.m_bIsEllipses = true; nativeContext.DrawRects(drawRectsParams); drawRectsParams === null || drawRectsParams === void 0 ? void 0 : drawRectsParams.delete(); }; /** * * @param vertices * @param xCenter * @param yCenter It is viewport height minus Y coordinate * @param rotation Rotation in Radians * @param clipRect * @param pen * @param brush * @param left * @param top */ WebGlRenderContext2D.prototype.drawArcs = function (vertices, xCenter, yCenter, rotation, clipRect, pen, brush, left, top) { if (left === void 0) { left = 0; } if (top === void 0) { top = 0; } var nativeContext = this.getNativeContext(); var dx = 0; var dy = 0; if (rotation !== 0) { var l = Math.sqrt(xCenter * xCenter + yCenter * yCenter); var a = Math.atan2(yCenter, xCenter); dx = xCenter - l * Math.cos(a + rotation); dy = yCenter - l * Math.sin(a + rotation); } this.resetTransform(); this.translate(dx + left, dy - top); this.rotate((rotation * 180) / Math.PI); this.setClipRect(clipRect); var drawArcsParams = new this.webAssemblyContext.SCRTDrawArcsParams(); drawArcsParams.SetVerticesVec(vertices); drawArcsParams.SetPen(pen ? pen : null); drawArcsParams.SetBrush(brush ? brush : null); nativeContext.DrawArcs(drawArcsParams); drawArcsParams === null || drawArcsParams === void 0 ? void 0 : drawArcsParams.delete(); }; /** * Enqueues a draw operation to the specified layer. Use in combination with {@link drawLayers} to flush layered draws * @param drawFunction the {@link TDrawFunction | Draw Function} to enqueue * @param layer the {@link ERenderLayer | Layer} to draw to */ WebGlRenderContext2D.prototype.enqueueLayeredDraw = function (drawFunction, layer) { if (!this.layers.has(layer)) { this.layers.set(layer, []); } this.layers.get(layer).push(drawFunction); }; /** * Flushes the {@link layers} which have been enqueued with drawing operations in order. * Use this in combination with {@link enqueueLayeredDraw} to draw in layers */ WebGlRenderContext2D.prototype.drawLayers = function () { var _a, _b; var parentContextId = this.canvasId; var allLayersDrawStartMark = performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.AllLayersDrawStart, { parentContextId: parentContextId, level: performance_1.EPerformanceDebugLevel.Verbose }); var keys = Array.from(this.layers.keys()).sort(function (a, b) { return a - b; }); for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { var key = keys_1[_i]; var layerDrawStartMark = performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.SingleLayerDrawStart, { contextId: "Layer-".concat(key), parentContextId: parentContextId, level: performance_1.EPerformanceDebugLevel.Verbose }); var drawFunctionsInCurrentLayer = this.layers.get(key); for (var _c = 0, drawFunctionsInCurrentLayer_1 = drawFunctionsInCurrentLayer; _c < drawFunctionsInCurrentLayer_1.length; _c++) { var drawFunc = drawFunctionsInCurrentLayer_1[_c]; drawFunc(); } performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.SingleLayerDrawEnd, { relatedId: (_a = layerDrawStartMark === null || layerDrawStartMark === void 0 ? void 0 : layerDrawStartMark.detail) === null || _a === void 0 ? void 0 : _a.relatedId, contextId: "Layer-".concat(key), parentContextId: parentContextId, level: performance_1.EPerformanceDebugLevel.Verbose }); } performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.AllLayersDrawEnd, { relatedId: (_b = allLayersDrawStartMark === null || allLayersDrawStartMark === void 0 ? void 0 : allLayersDrawStartMark.detail) === null || _b === void 0 ? void 0 : _b.relatedId, parentContextId: parentContextId, level: performance_1.EPerformanceDebugLevel.Verbose }); }; /** * Applies a {@link ShaderEffect} to the rendering pipeline. Calling {@link WebGL2RenderingContext.popShaderEffect} pops the effect from the stack * reverting to normal drawing * @param effect the {@link ShaderEffect} to apply to subsequent draw operations */ WebGlRenderContext2D.prototype.pushShaderEffect = function (effect) { if (effect) { this.effects.push(effect); if (!app_1.IS_TEST_ENV) { this.getNativeContext().AddSeriesEffect(effect.getNativeEffect()); } } }; /** * Pops a {@link ShaderEffect} from the rendering pipeline. Call {@link WebGL2RenderingContext.pushShaderEffect} to apply an effect */ WebGlRenderContext2D.prototype.popShaderEffect = function () { var effect = this.effects.pop(); if (effect && !app_1.IS_TEST_ENV) { this.getNativeContext().RemoveSeriesEffect(effect.getNativeEffect()); } }; /** * @inheritDoc */ WebGlRenderContext2D.prototype.createPen = function (stroke, strokeThickness, strokeDashArray, antiAliased) { if (strokeDashArray === void 0) { strokeDashArray = []; } if (antiAliased === void 0) { antiAliased = true; } throw new Error("Use Pen2DCache for creating pens instead!"); }; /** * @inheritDoc */ WebGlRenderContext2D.prototype.createSolidBrush = function (fill, opacity) { throw new Error("Use BrushCache for creating brushes instead!"); }; /** * @inheritDoc */ WebGlRenderContext2D.prototype.delete = function () { // Todo: Any cached items delete here }; /** * @inheritDoc */ WebGlRenderContext2D.prototype.drawLine = function (x1, y1, x2, y2, pen, offsetRect, clipRect) { if (!x1 && !y1 && !x2 && !y2) { return; } Guard_1.Guard.notNull(pen, "pen"); Guard_1.Guard.isTrue(pen.getPenType() === "WasmPen", "pen must be an instance of WasmPen to be used with the WasmRenderContext"); var scrtPen = pen.scrtPen; Guard_1.Guard.notNull(scrtPen, "WasmPen.scrtPen"); var isStrips = true; var nativeContext = this.getNativeContext(); var vertices = (0, NativeObject_1.getVectorColorVertex)(this.webAssemblyContext); var vertex0 = (0, NativeObject_1.getVertex)(this.webAssemblyContext, x1, y1); vertices.push_back(vertex0); var vertex1 = (0, NativeObject_1.getVertex)(this.webAssemblyContext, x2, y2); vertices.push_back(vertex1); this.resetTransform(); this.translate(offsetRect.x, offsetRect.y); this.setClipRect(clipRect); var drawLineParams = new this.webAssemblyContext.SCRTDrawLinesParams(); drawLineParams.m_Type = isStrips ? this.webAssemblyContext.SCRTLineType.Strip : this.webAssemblyContext.SCRTLineType.List; drawLineParams.SetPen(scrtPen); drawLineParams.SetPointsVec(vertices); nativeContext.DrawLines(drawLineParams); drawLineParams.delete(); }; /** * @inheritDoc */ WebGlRenderContext2D.prototype.drawLines = function (xyValues, strokePen, offsetRect, clipRect, lineDrawMode) { if (lineDrawMode === void 0) { lineDrawMode = ELineDrawMode.PolyLine; } Guard_1.Guard.notNull(strokePen, "pen"); Guard_1.Guard.notNull(xyValues, "xyValues"); Guard_1.Guard.isTrue(strokePen.getPenType() === "WasmPen", "pen must be an instance of WasmPen to be used with the WasmRenderContext"); Guard_1.Guard.isTrue(xyValues.length > 0 && xyValues.length % 2 === 0, "xyValues length must be a multiple of 2, values arranged as x0y0 x1y1 x2y2..."); var scrtPen = strokePen.scrtPen; Guard_1.Guard.notNull(scrtPen, "WebGlPen.scrtPen"); var isStrips = lineDrawMode === ELineDrawMode.PolyLine; var nativeContext = this.getNativeContext(); var vertices = (0, NativeObject_1.getVectorColorVertex)(this.webAssemblyContext); for (var i = 0; i < xyValues.length; i += 2) { var vertex = (0, NativeObject_1.getVertex)(this.webAssemblyContext, xyValues[i], xyValues[i + 1]); // Setting a sub-property directly MUST BE AVOIDED because it creates a copy of an object and leaks the memory // Never do this: vertex.m_vPosition.z = 0; vertices.push_back(vertex); } this.resetTransform(); this.translate(offsetRect.x, offsetRect.y); this.setClipRect(clipRect); var drawLineParams = new this.webAssemblyContext.SCRTDrawLinesParams(); drawLineParams.m_Type = isStrips ? this.webAssemblyContext.SCRTLineType.Strip : this.webAssemblyContext.SCRTLineType.List; drawLineParams.SetPen(scrtPen); drawLineParams.SetPointsVec(vertices); nativeContext.DrawLines(drawLineParams); drawLineParams.delete(); }; /** * @inheritDoc */ WebGlRenderContext2D.prototype.drawTriangleStrip = function (xValues, yValues, offsetRect, clipRect, fillBrush) { if (fillBrush) { Guard_1.Guard.arraysSameLength(xValues, "xValues", yValues, "yValues"); var nativeContext = this.getNativeContext(); var scrtBrush = fillBrush.scrtBrush; Guard_1.Guard.notNull(scrtBrush, "WebGlBrush.scrtBrush"); var vertices = (0, NativeObject_1.getVectorColorTextureVertex)(this.webAssemblyContext); var size = xValues.length; for (var i = 0; i < size; i++) { var x = xValues[i]; var y = yValues[i]; var vertex = (0, NativeObject_1.getTextureVertex)(this.webAssemblyContext, x, y); vertices.push_back(vertex); } this.resetTransform(); this.translate(offsetRect.x, offsetRect.y); this.setClipRect(clipRect); var drawParams = new this.webAssemblyContext.SCRTDrawPrimitivesParams(); drawParams.SetVerticesVec(vertices); drawParams.SetBrush(scrtBrush); nativeContext.DrawPrimitives(drawParams); drawParams.delete(); } }; /** * Helper function to draw a texture a {@link SCRTRectVertex} * @param webAssemblyContext The {@link TSciChart | SciChart 2D WebAssembly Context} containing native methods and * access to our WebGL2 Engine and WebAssembly numerical methods * @param texture * @param x * @param y * @param width * @param height */ WebGlRenderContext2D.prototype.drawTexture = function (texture, x, y, width, height) { var nativeContext = this.getNativeContext(); var brush = new this.webAssemblyContext.SCRTTextureBrush(texture, this.webAssemblyContext.eSCRTBrushMappingMode.PerPrimitive, 1); // draw as a single strip with 4 verts var quadVerts = (0, NativeObject_1.getVectorColorTextureVertex)(this.webAssemblyContext); var bottomLeft = (0, NativeObject_1.getTextureVertex)(this.webAssemblyContext, x, y, app_1.NEUTRAL_COLOR, 0, 0); quadVerts.push_back(bottomLeft); var topLeft = (0, NativeObject_1.getTextureVertex)(this.webAssemblyContext, x + width, y, app_1.NEUTRAL_COLOR, 1, 0); quadVerts.push_back(topLeft); var bottomRight = (0, NativeObject_1.getTextureVertex)(this.webAssemblyContext, x, y + height, app_1.NEUTRAL_COLOR, 0, 1); quadVerts.push_back(bottomRight); var topRight = (0, NativeObject_1.getTextureVertex)(this.webAssemblyContext, x + width, y + height, app_1.NEUTRAL_COLOR, 1, 1); quadVerts.push_back(topRight); var drawParams = new this.webAssemblyContext.SCRTDrawPrimitivesParams(); drawParams.SetVerticesVec(quadVerts); drawParams.SetBrush(brush); nativeContext.DrawPrimitives(drawParams); brush === null || brush === void 0 ? void 0 : brush.delete(); drawParams.delete(); }; WebGlRenderContext2D.prototype.drawRotatedRect = function (width, height, baselineHeight, padding, verticalAnchorPoint, horizontalAnchorPoint, position, rotation, clipRect, fillBrush) { var scrtBrush = fillBrush.scrtBrush; Guard_1.Guard.notNull(scrtBrush, "WebGlBrush.scrtBrush"); var fromCenterToTop; var fromCenterToBottom; switch (verticalAnchorPoint) { case AnchorPoint_1.EVerticalAnchorPoint.Bottom: fromCenterToTop = baselineHeight + padding.bottom + padding.top; fromCenterToBottom = height - baselineHeight; break; case AnchorPoint_1.EVerticalAnchorPoint.Top: fromCenterToTop = 0; fromCenterToBottom = height + padding.bottom + padding.top; break; default: fromCenterToTop = baselineHeight / 2 + (padding.bottom + padding.top) / 2; fromCenterToBottom = height - baselineHeight / 2 + (padding.bottom + padding.top) / 2; } var fromCenterToLeft; var fromCenterToRight; switch (horizontalAnchorPoint) { case AnchorPoint_1.EHorizontalAnchorPoint.Right: fromCenterToLeft = width + padding.left + padding.right; fromCenterToRight = 0; break; case AnchorPoint_1.EHorizontalAnchorPoint.Left: fromCenterToLeft = 0; fromCenterToRight = width + padding.left + padding.right; break; default: fromCenterToLeft = width / 2 + padding.left; fromCenterToRight = width / 2 + padding.right; } var rect = Rect_1.Rect.createWithPoints(new Point_1.Point(-fromCenterToLeft, -fromCenterToTop), new Point_1.Point(fromCenterToRight, fromCenterToBottom)); var nativeContext = this.getNativeContext(); var vertices = (0, NativeObject_1.getVectorRectVertex)(this.webAssemblyContext); var anchorParams = (0, NativeObject_1.getVector4)(this.webAssemblyContext, 0, 0, 0, 0); var nativeRect = (0, createNativeRect_1.createNativeRect)(this.webAssemblyContext, rect.x, rect.y, rect.right, rect.bottom); vertices.push_back(nativeRect); this.resetTransform(); this.translate(position.x, position.y); this.rotate(rotation); this.setClipRect(clipRect); var drawRectsParams = new this.webAssemblyContext.SCRTDrawRectsParams(); drawRectsParams.SetVerticesVec(vertices); drawRectsParams.SetBrush(scrtBrush); drawRectsParams.m_vAnchorParams = anchorParams; nativeContext.DrawRects(drawRectsParams); drawRectsParams === null || drawRectsParams === void 0 ? void 0 : drawRectsParams.delete(); }; /** * @inheritDoc */ WebGlRenderContext2D.prototype.drawRect = function (rect, offsetRect, clipRect, strokePen, fillBrush, bevelCorners, strokeThickness) { if (fillBrush) { var nativeContext = this.getNativeContext(); var scrtBrush = fillBrush.scrtBrush; Guard_1.Guard.notNull(scrtBrush, "WebGlBrush.scrtBrush"); var vertices = (0, NativeObject_1.getVectorRectVertex)(this.webAssemblyContext); var anchorParams = (0, NativeObject_1.getVector4)(this.webAssemblyContext, 0, 0, 0, 0); var nativeRect = (0, createNativeRect_1.createNativeRect)(this.webAssemblyContext, rect.x, rect.y, rect.right, rect.bottom); vertices.push_back(nativeRect); this.resetTransform(); this.translate(offsetRect.x, offsetRect.y); this.setClipRect(clipRect); var drawRectsParams = new this.webAssemblyContext.SCRTDrawRectsParams(); drawRectsParams.SetVerticesVec(vertices); drawRectsParams.SetBrush(scrtBrush); drawRectsParams.m_vAnchorParams = anchorParams; nativeContext.DrawRects(drawRectsParams); drawRectsParams === null || drawRectsParams === void 0 ? void 0 : drawRectsParams.delete(); } if (strokePen) { if (bevelCorners) { this.drawLines([ rect.right, rect.top, rect.right, rect.bottom, rect.left, rect.bottom, rect.left, rect.top, rect.right, rect.top, rect.right, rect.bottom ], strokePen, offsetRect, clipRect, ELineDrawMode.PolyLine); } else { var hst = Math.round(strokeThickness / 2) - 1; this.drawLines([ rect.right, rect.top - hst, rect.right, rect.bottom + hst, rect.right, rect.bottom, rect.left, rect.bottom, rect.left, rect.bottom + hst, rect.left, rect.top - hst, rect.left, rect.top, rect.right, rect.top ], strokePen, offsetRect, clipRect, ELineDrawMode.DiscontinuousLine); } } }; WebGlRenderContext2D.prototype.drawTextBackground = function (textWidth, textHeight, rotation, rotationCenter, chartViewRect, verticalAnchorPoint, horizontalAnchorPoint, padding, fillBrush) { this.drawRotatedRect(textWidth, textHeight, textHeight, padding, verticalAnchorPoint, horizontalAnchorPoint, rotationCenter, rotation, chartViewRect, fillBrush); }; WebGlRenderContext2D.prototype.drawNativeText = function (rotationRadians, xCoord, yCoord, offsetRect, chartViewRect, fontFamily, fontSize, textColor, textColorOpacity, backgroundFillBrush, verticalAnchorPoint, horizontalAnchorPoint, text, padding, scale, lineSpacing) { if (scale === void 0) { scale = 1; } if (lineSpacing === void 0) { lineSpacing = 3; } var colorNum = (0, parseColor_1.parseColorToUIntArgb)(textColor); var colorNumWithOpacity = (0, colorUtil_1.uintArgbColorOverrideOpacity)(colorNum, textColorOpacity); var style = { fontFamily: fontFamily, fontSize: fontSize }; var font = this.getFont(style, false, false); var textBounds = (0, NativeObject_1.getTextBounds)(this.webAssemblyContext); font.CalculateStringBounds(text !== null && text !== void 0 ? text : "", textBounds, lineSpacing); var rotationCenterX = xCoord + offsetRect.x; var rotationCenterY = yCoord + offsetRect.y; var _a = (0, text_1.getNativeTextPosition)(xCoord, yCoord, horizontalAnchorPoint, verticalAnchorPoint, textBounds, padding), textPositionX = _a.x, textPositionY = _a.y; var textWidth = textBounds.m_fWidth; var textHeight = textBounds.m_fHeight; var alignMode = (0, TextPosition_1.convertMultiLineAlignment)(TextPosition_1.EMultiLineAlignment.Center, this.webAssemblyContext); var oldScale = font.GetScale(); var scaleChanged = false; if (oldScale !== scale) { font.SetScale(scale); scaleChanged = true; } var x = textPositionX + offsetRect.x; var y = textPositionY + offsetRect.y; if (backgroundFillBrush) { this.drawTextBackground(textWidth, textHeight, -((rotationRadians * 180) / Math.PI), new Point_1.Point(rotationCenterX, rotationCenterY), chartViewRect, verticalAnchorPoint, horizontalAnchorPoint, padding, backgroundFillBrush); this.resetTransform(); } var rotationVector = (0, NativeObject_1.getVector4)(this.webAssemblyContext, rotationCenterX, rotationCenterY, rotationRadians, 0); font.DrawStringAdvanced(text, colorNumWithOpacity, Math.round(x), Math.round(y), rotationVector, alignMode, lineSpacing); if (scaleChanged) { font.SetScale(oldScale); } // always drawing immediately font.End(); }; WebGlRenderContext2D.prototype.printBlendMode = function () { var blendMode = this.getNativeContext().GetBlendMode(); switch (blendMode) { case this.webAssemblyContext.eSCRTBlendMode.BlendDefault: console.log("BlendDefault"); break; case this.webAssemblyContext.eSCRTBlendMode.BlendAdditiveOneAlpha: console.log("BlendAdditiveOneAlpha"); break; case this.webAssemblyContext.eSCRTBlendMode.BlendAdditiveColor: console.log("BlendAdditiveColor"); break; case this.webAssemblyContext.eSCRTBlendMode.BlendAdditiveAlpha: console.log("BlendAdditiveAlpha"); break; case this.webAssemblyContext.eSCRTBlendMode.BlendDisabled: console.log("BlendDisabled"); break; default: throw new Error("Unhandled blendmode "); } }; /** * Get a native font. Fonts are cached and shared within webassembly so there is no need to cache them in JS. * Set advanced: true if you are planning to rotate or scale the text. * Set drawEarly: true if you are planning to call font.End() early. Otherwise all native text will be drawn at the end of the render cycle. */ WebGlRenderContext2D.prototype.getFont = function (labelStyle, advanced, drawEarly) { var _this = this; if (advanced === void 0) { advanced = false; } if (drawEarly === void 0) { drawEarly = false; } var fontKey = (0, NativeObject_1.getFontKey)(this.webAssemblyContext, labelStyle, advanced, drawEarly); var nativeContext = this.getNativeContext(); var nativeFont = nativeContext.AquireFont(fontKey); if (!nativeFont) { throw new Error("Could not create font " + fontKey.m_strName); } else { if (!nativeFont.m_isDrawing) { nativeFont.Begin(); } } var currentFontName = nativeFont.GetFaceName(); if (currentFontName === "SCRT_Loading") { setTimeout(function () { var _a; performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.Invalidate, { parentContextId: _this.canvasId }); _this.webAssemblyContext.TSRRequestCanvasDraw((_a = _this.canvasId) !== null && _a !== void 0 ? _a : "undefinedCanvasId"); }, 100); } else if (currentFontName !== fontKey.m_strName) { // @ts-ignore if (!fontKey.warned) { console.warn("Font ".concat(fontKey.m_strName, " could not be found on the server and has not been registered. Falling back to default font.\n Use await scichartSurface.registerFont if you need to load the font from a remote url")); // @ts-ignore fontKey.warned = true; } } return nativeFont; }; /** End all fonts, causing text to be drawn */ WebGlRenderContext2D.prototype.endFonts = function (force) { var _a; if (force === void 0) { force = false; } var mark = performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.DrawNativeTextStart, { contextId: this.canvasId, level: performance_1.EPerformanceDebugLevel.Verbose }); var nativeContext = this.getNativeContext(); var keys = (0, NativeObject_1.getAllFontKeys)(this.webAssemblyContext); for (var _i = 0, keys_2 = keys; _i < keys_2.length; _i++) { var fontKey = keys_2[_i]; var nativeFont = nativeContext.AquireFont(fontKey); if (nativeFont && nativeFont.m_isDrawing) { nativeFont.End(); } } performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.DrawNativeTextEnd, { contextId: this.canvasId, relatedId: (_a = mark === null || mark === void 0 ? void 0 : mark.detail) === null || _a === void 0 ? void 0 : _a.relatedId, level: performance_1.EPerformanceDebugLevel.Verbose }); }; WebGlRenderContext2D.prototype.setClipRect = function (clipRect) { var nativeContext = this.getNativeContext(); nativeContext.SetClipRect(clipRect.x, clipRect.y, clipRect.width, clipRect.height); this.currentClipRect = clipRect; }; /** * * @param clipRect Clipping rectangle * @param translationX Translation on X axis in pixels * @param translationY Translation on Y axis in pixels * @param angle Angle in degrees */ WebGlRenderContext2D.prototype.setTranslationRotationAndClip = function (clipRect, translationX, translationY, angle) { if (angle === void 0) { angle = 0; } this.resetTransform(); this.translate(translationX, translationY); if (angle !== 0) this.rotate(angle); this.setClipRect(clipRect); }; WebGlRenderContext2D.prototype.resetAndClip = function (clipRect) { this.resetTransform(); this.setClipRect(clipRect); }; WebGlRenderContext2D.prototype.rotate = function (rotationAngle) { var nativeContext = this.getNativeContext(); nativeContext.Rotate(rotationAngle); }; WebGlRenderContext2D.prototype.translate = function (translationX, translationY) { var nativeContext = this.getNativeContext(); nativeContext.Translate(translationX, translationY); }; WebGlRenderContext2D.prototype.resetTransform = function () { var nativeContext = this.getNativeContext(); nativeContext.ResetTransform(); }; /** * Should store references to all cached WebGlResources {@link ICacheable} * Is used to invalidate the resources when the WebGL context is lost. */ WebGlRenderContext2D.webGlResourcesRefs = new Set(); return WebGlRenderContext2D; }(DeletableEntity_1.DeletableEntity)); exports.WebGlRenderContext2D = WebGlRenderContext2D;