UNPKG

scichart

Version:

Fast WebGL JavaScript Charting Library and Framework

382 lines (381 loc) 23.8 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.PolarAxisRenderer = void 0; var Rect_1 = require("../../../../Core/Rect"); var TextPosition_1 = require("../../../../types/TextPosition"); var logger_1 = require("../../../../utils/logger"); var parseColor_1 = require("../../../../utils/parseColor"); var WebGlRenderContext2D_1 = require("../../../Drawing/WebGlRenderContext2D"); var labelHelper_1 = require("../../Helpers/labelHelper"); var NativeObject_1 = require("../../Helpers/NativeObject"); var polarChartHelper_1 = require("../../Helpers/polarChartHelper"); var SciChartSurfaceBase_1 = require("../../SciChartSurfaceBase"); var DpiHelper_1 = require("../../TextureManager/DpiHelper"); var AxisRenderer_1 = require("../AxisRenderer"); var PolarLabelMode_1 = require("./types/PolarLabelMode"); /** * Draws a polar axis using our WebGL Rendering engine */ var PolarAxisRenderer = /** @class */ (function (_super) { __extends(PolarAxisRenderer, _super); function PolarAxisRenderer() { return _super !== null && _super.apply(this, arguments) || this; } /** @inheritDoc */ PolarAxisRenderer.prototype.layout = function (rect) { this.outerRadius = rect.width; }; /** @inheritDoc */ PolarAxisRenderer.prototype.measure = function (isHorizontalAxis, labelStyle, majorTickLabels, ticksSize, labelProvider, drawLabels, drawTicks, labelInfos) { var pAxis = this.parentAxis; var ctx = this.measureTextCanvas.getContext("2d"); this.desiredTicksSize = drawTicks ? ticksSize : 0; if (drawLabels) { if (pAxis.isAngular) { if (pAxis.isInnerAxis) { this.desiredHeight = 0; this.desiredWidth = 0; } else { if (pAxis.polarLabelMode === PolarLabelMode_1.EPolarLabelMode.Parallel) { this.desiredHeight = labelProvider.getMaxLabelHeightForHorizontalAxis(majorTickLabels, ctx, labelStyle, labelInfos) + this.desiredTicksSize; this.desiredWidth = this.desiredHeight; } else if (pAxis.polarLabelMode === PolarLabelMode_1.EPolarLabelMode.Perpendicular) { this.desiredHeight = labelProvider.getMaxLabelWidthForVerticalAxis(majorTickLabels, ctx, labelStyle, labelInfos) + this.desiredTicksSize; this.desiredWidth = this.desiredHeight; } else { this.desiredHeight = labelProvider.getMaxLabelHeightForHorizontalAxis(majorTickLabels, ctx, labelStyle, labelInfos) + this.desiredTicksSize; this.desiredWidth = labelProvider.getMaxLabelWidthForVerticalAxis(majorTickLabels, ctx, labelStyle, labelInfos) + this.desiredTicksSize; } } } } }; /** @inheritDoc */ PolarAxisRenderer.prototype.drawLabels = function (renderContext, axisAlignment, isInnerAxis, tickLabels, tickCoords, axisOffset, labelStyle, isVerticalChart, isFlippedCoordinates, labelProvider, labelInfos) { if (SciChartSurfaceBase_1.DebugForDpi) { console.log("AxisRenderer.drawLabels. fontSize: ".concat(labelStyle.fontSize)); } var _a = this, viewRect = _a.viewRect, textureManager = _a.textureManager; var nativeContext = renderContext.getNativeContext(); var ctx; var padding = labelStyle.padding, alignment = labelStyle.alignment, multilineAlignment = labelStyle.multilineAlignment; var axis = this.parentAxis; // TODO probably need to intersect with surface.clipRect var svr = axis.parentSurface.seriesViewRect; renderContext.resetAndClip(svr); // for debug var labelRects = []; var textColor = (0, parseColor_1.parseColorToUIntArgb)(labelStyle.color); var nativeFont = labelProvider.useNativeText ? renderContext.getFont(labelStyle, true) : null; var textBounds = labelProvider.useNativeText ? (0, NativeObject_1.getTextBounds)(this.webAssemblyContext) : null; ctx = this.getMeasureContext(); if (!nativeFont) { if (axis.polarLabelMode !== PolarLabelMode_1.EPolarLabelMode.Horizontal) { throw new Error("Original text drawing only supports EPolarLabelMode.Horizontal. To use rotated labels, set useNativeText: true"); } } //?? tickCoords = tickCoords.map(function (t) { return t - axisOffset; }); var mlaNative = (0, TextPosition_1.convertMultiLineAlignment)(multilineAlignment, this.webAssemblyContext); var nativeLineSpacing = labelProvider.lineSpacing; var lineHeight = this.calculateLineHightForNativeFont(nativeFont, textBounds); var vec = new this.webAssemblyContext.TSRVector2(); if (axis.isAngular) { var labelWidthPadding = (labelStyle.padding.left + labelStyle.padding.right) / 2; var labelHeights = []; var labelWidths = []; if (!labelProvider.useCache && labelProvider.useNativeText) { // Scenario with disabled cache, for testing purpose only for (var _i = 0, tickLabels_1 = tickLabels; _i < tickLabels_1.length; _i++) { var label = tickLabels_1[_i]; nativeFont.CalculateStringBounds(label !== null && label !== void 0 ? label : "", textBounds, nativeLineSpacing); labelHeights.push(textBounds.m_fHeight); labelWidths.push(textBounds.m_fWidth); } } else if (labelProvider.useNativeText) { labelHeights = labelInfos.map(function (l) { return l.textHeight; }); labelWidths = labelInfos.map(function (l) { return l.textWidth; }); } else { // Not Native text supports only horizontal mode labelHeights = tickLabels.map(function (label, i) { return labelProvider.getLabelHeight(ctx, label, labelStyle, labelInfos === null || labelInfos === void 0 ? void 0 : labelInfos[i]); }); labelWidths = tickLabels.map(function (label, i) { return labelProvider.getLabelWidth(ctx, label, labelStyle, labelInfos === null || labelInfos === void 0 ? void 0 : labelInfos[i]); }); } var radius = isInnerAxis ? this.outerRadius * Math.min(axis.otherAxis.lengthScale, 1) - this.desiredTicksSize : this.outerRadius * Math.min(axis.otherAxis.lengthScale, 1) + this.desiredTicksSize; var transform = axis.getTransform(); var cardinalAngle = 10; // * Math.PI / 180; // Special handling around cardinal points var tickCount = polarChartHelper_1.polarChartHelper.checkPolarLabelsOverlap(tickCoords) ? tickCoords.length - 1 : tickCoords.length; for (var index = 0; index < tickCount; index++) { var angle = tickCoords[index]; var labelText = tickLabels[index]; var labelHeight = labelHeights[index]; var labelWidth = labelWidths[index]; var labelRadius = radius; if (axis.polarLabelMode === PolarLabelMode_1.EPolarLabelMode.Parallel) { // This shows how we use paddings for outer and inner labels for Native Text for the Parallel mode // paddingTop // outerLabel // paddingBottom // radius // paddingTop // innerLabel // paddingBottom var paddingFromRadius = isInnerAxis ? -labelStyle.padding.top : labelStyle.padding.bottom; // multiply by 0.5 because calculation distance to the center of the label labelRadius = radius + (isInnerAxis ? -1 : 1) * 0.5 * labelHeight + paddingFromRadius; } else if (axis.polarLabelMode === PolarLabelMode_1.EPolarLabelMode.Perpendicular) { var shift = Math.cos(angle + axis.startAngle) < 0 ? (isInnerAxis ? 0 : 1) : isInnerAxis ? -1 : 0; // add shift to respect different orientation labelRadius = radius + shift * labelWidth + (isInnerAxis ? -1 : 1) * labelWidthPadding; } else if (axis.polarLabelMode === PolarLabelMode_1.EPolarLabelMode.Horizontal) { // This is the only mode which works both for Native and NOT Native text if (labelProvider.useNativeText) { labelRadius = radius + (isInnerAxis ? -labelStyle.padding.top : labelStyle.padding.bottom); } } transform.TransformPoint(labelRadius, angle, vec); angle += axis.startAngle; var xCoord = vec.x; var yCoord = vec.y; var rxc = 0; var ryc = 0; if (axis.polarLabelMode === PolarLabelMode_1.EPolarLabelMode.Horizontal) { if (isInnerAxis) { angle = angle + Math.PI; } var aDeg = Math.round((angle * 180) / Math.PI); // if within 10% from cardinal points var isCardinal = Math.abs(aDeg) % 90 < cardinalAngle || Math.abs(aDeg) % 90 > 90 - cardinalAngle; // To make it return always positive number var quadrant = ((((aDeg + cardinalAngle) / 90) % 4) + 4) % 4; if (isCardinal) { if (quadrant < 1) { yCoord -= labelHeight / 2; } else if (quadrant < 2) { xCoord -= labelWidth / 2; yCoord -= labelHeight; } else if (quadrant < 3) { xCoord -= labelWidth; yCoord -= labelHeight / 2; } else { xCoord -= labelWidth / 2; } } else { if (Math.cos(angle) < 0) { xCoord -= labelWidth; } if (Math.sin(angle) > 0) { yCoord -= labelHeight; } } } else if (axis.polarLabelMode === PolarLabelMode_1.EPolarLabelMode.Parallel) { rxc = xCoord + svr.left; ryc = yCoord + svr.top; // adjusting the angel xCoord -= labelWidth / 2; if (Math.sin(angle) >= 0) { yCoord -= labelHeight / 2; } else { yCoord += labelHeight / 2 - lineHeight; } } else if (axis.polarLabelMode === PolarLabelMode_1.EPolarLabelMode.Perpendicular) { rxc = xCoord + svr.left; ryc = yCoord + svr.top; yCoord -= labelHeight / 2; } var rotationRad = labelHelper_1.labelHelper.getPolarLabelRotation(axis.polarLabelMode, angle); try { if (nativeFont) { var tx = xCoord + svr.left; // + padding.left; var ty = yCoord + svr.top + lineHeight; // + padding.top; var _b = labelProvider.adjustLabel(index, labelText, labelWidth, labelHeight, tx, ty, rxc, ryc, rotationRad), text = _b.text, x = _b.x, y = _b.y, rx = _b.rx, ry = _b.ry, rotationRadians = _b.rotationRadians, color = _b.color; if (this.drawDebug) { labelRects.push(Rect_1.Rect.create(x, y, labelWidth, labelHeight)); } nativeFont.DrawStringAdvanced(text !== null && text !== void 0 ? text : "", color !== null && color !== void 0 ? color : textColor, Math.round(x), Math.round(y), (0, NativeObject_1.getVector4)(this.webAssemblyContext, rx, ry, rotationRadians, 0), mlaNative, nativeLineSpacing); } else { var cachedLabelInfo = labelInfos === null || labelInfos === void 0 ? void 0 : labelInfos[index]; var _c = cachedLabelInfo ? { bitmapTexture: cachedLabelInfo.bitmapTexture, textureHeight: cachedLabelInfo.textureHeight, textureWidth: cachedLabelInfo.textureWidth } : labelProvider.getCachedLabelTexture(labelText, textureManager, labelStyle), bitmapTexture = _c.bitmapTexture, textureHeight = _c.textureHeight, textureWidth = _c.textureWidth; var _d = labelProvider.adjustLabel(index, labelText, labelWidth, labelHeight, xCoord + svr.left, yCoord + svr.top, 0, 0, 0), x = _d.x, y = _d.y; if (bitmapTexture) { renderContext.drawTexture(bitmapTexture, Math.round(x), Math.round(y), textureWidth, textureHeight); if (!labelProvider.useCache) { bitmapTexture.delete(); } } } } catch (err) { logger_1.Logger.debug(err); // webgl context probably lost. Clear the label cache labelProvider.delete(); } } } else { var _e = polarChartHelper_1.polarChartHelper.calcLabelPosition(isInnerAxis, axis.otherAxis.flippedCoordinates, axis.startAngle, axis.otherAxis.totalAngle), isAntiClockWiseLabelPosition = _e.isAntiClockWise, labelRotation = _e.labelRotation, axisStartAngle = _e.startAngle; var angle = axisStartAngle; var transform = axis.getTransform(); var labelHeights = []; var labelWidths = []; if (!labelProvider.useCache && labelProvider.useNativeText) { for (var _f = 0, tickLabels_2 = tickLabels; _f < tickLabels_2.length; _f++) { var label = tickLabels_2[_f]; nativeFont.CalculateStringBounds(label !== null && label !== void 0 ? label : "", textBounds, nativeLineSpacing); labelHeights.push(textBounds.m_fHeight + labelStyle.padding.top + labelStyle.padding.bottom); labelWidths.push(textBounds.m_fWidth + labelStyle.padding.left + labelStyle.padding.right); } } else { labelHeights = tickLabels.map(function (label, i) { return labelProvider.getLabelHeight(ctx, label, labelStyle, labelInfos === null || labelInfos === void 0 ? void 0 : labelInfos[i]); }); labelWidths = tickLabels.map(function (label, i) { return labelProvider.getLabelWidth(ctx, label, labelStyle, labelInfos === null || labelInfos === void 0 ? void 0 : labelInfos[i]); }); } var tickSize = this.desiredTicksSize; for (var index = 0; index < tickCoords.length; index++) { var radius = tickCoords[index] + axisOffset; var labelText = tickLabels[index]; var labelWidth = labelWidths[index]; var labelHeight = labelHeights[index]; transform.TransformPoint(radius, labelRotation, vec); var xCoord = vec.x; var yCoord = vec.y; if (isAntiClockWiseLabelPosition) { angle = axisStartAngle + Math.PI; } xCoord += (Math.sin(angle) / 2 - 0.5) * labelWidth; xCoord += Math.sin(angle) * tickSize; var a = (angle < 0 ? 2 * Math.PI - angle : angle) % (2 * Math.PI); var yadj = a < Math.PI ? a / Math.PI : 2 - a / Math.PI; //console.log(labelText, aDeg, radius, xCoord, ((Math.sin(angle) / 2) - 0.5) * labelWidth, yCoord, yadj); yCoord -= yadj * labelHeight; yCoord += Math.cos(angle) * tickSize; if (this.drawDebug) { labelRects.push(Rect_1.Rect.create(xCoord, yCoord, labelWidth, labelHeight)); } try { if (nativeFont) { var tx = xCoord + svr.left + padding.left; var ty = yCoord + svr.top + lineHeight + padding.top; var _g = labelProvider.adjustLabel(index, labelText, labelWidth, labelHeight, tx, ty, tx, ty, 0), text = _g.text, x = _g.x, y = _g.y, rx = _g.rx, ry = _g.ry, rotationRadians = _g.rotationRadians, color = _g.color; nativeFont.DrawStringAdvanced(text !== null && text !== void 0 ? text : "", color !== null && color !== void 0 ? color : textColor, Math.round(x), Math.round(y), (0, NativeObject_1.getVector4)(this.webAssemblyContext, rx, ry, rotationRadians, 0), mlaNative, nativeLineSpacing); } else { var cachedLabelInfo = labelInfos === null || labelInfos === void 0 ? void 0 : labelInfos[index]; var _h = cachedLabelInfo ? { bitmapTexture: cachedLabelInfo.bitmapTexture, textureHeight: cachedLabelInfo.textureHeight, textureWidth: cachedLabelInfo.textureWidth } : labelProvider.getCachedLabelTexture(labelText, textureManager, labelStyle), bitmapTexture = _h.bitmapTexture, textureHeight = _h.textureHeight, textureWidth = _h.textureWidth; if (bitmapTexture) { var _j = labelProvider.adjustLabel(index, labelText, labelWidth, labelHeight, xCoord + svr.left, yCoord + svr.top, 0, 0, 0), x = _j.x, y = _j.y; renderContext.drawTexture(bitmapTexture, Math.round(x), Math.round(y), textureWidth, textureHeight); if (!labelProvider.useCache) { bitmapTexture.delete(); } } } } catch (err) { logger_1.Logger.debug(err); // webgl context probably lost. Clear the label cache labelProvider.delete(); } } } vec.delete(); if (this.drawDebug) { this.drawLabelViewRects(renderContext, new Rect_1.Rect(0, 0, 0, 0), labelRects); } if (nativeFont) { nativeFont.End(); } }; /** @inheritDoc */ PolarAxisRenderer.prototype.drawTicks = function (renderContext, axisAlignment, isInnerAxis, tickCoords, axisOffset, pen, tickStyle) { var _a, _b, _c, _d; if (!tickCoords || tickCoords.length === 0) return; var leftPad = DpiHelper_1.DpiHelper.PIXEL_RATIO * ((_b = (_a = this.parentAxis.parentSurface.padding) === null || _a === void 0 ? void 0 : _a.left) !== null && _b !== void 0 ? _b : 0); var topPad = DpiHelper_1.DpiHelper.PIXEL_RATIO * ((_d = (_c = this.parentAxis.parentSurface.padding) === null || _c === void 0 ? void 0 : _c.top) !== null && _d !== void 0 ? _d : 0); var axis = this.parentAxis; var tickSize = tickStyle.tickSize; var transform = axis.getTransform(); var clipRect = Rect_1.Rect.intersect(this.parentAxis.parentSurface.viewRect, this.parentAxis.parentSurface.seriesViewRect); if (axis.isAngular) { var otherAxisOffset = axis.otherAxis.offset; var startRadius_1 = axis.otherAxis.axisLength + otherAxisOffset; var endRadius_1 = isInnerAxis ? startRadius_1 - tickSize * DpiHelper_1.DpiHelper.PIXEL_RATIO : startRadius_1 + tickSize * DpiHelper_1.DpiHelper.PIXEL_RATIO; var vertices_1 = (0, NativeObject_1.getVectorColorVertex)(this.webAssemblyContext); var vertex_1 = (0, NativeObject_1.getVertex)(this.webAssemblyContext, 0, 0); var vec_1 = (0, NativeObject_1.getVector2)(this.webAssemblyContext); tickCoords.forEach(function (tc) { transform.TransformPoint(startRadius_1, tc, vec_1); vertex_1.SetPosition(vec_1.x, vec_1.y); vertices_1.push_back(vertex_1); transform.TransformPoint(endRadius_1, tc, vec_1); vertex_1.SetPosition(vec_1.x, vec_1.y); vertices_1.push_back(vertex_1); }); renderContext.drawLinesNative(vertices_1, pen, WebGlRenderContext2D_1.ELineDrawMode.DiscontinuousLine, clipRect, leftPad, topPad); } else { var vertices_2 = (0, NativeObject_1.getVectorColorVertex)(this.webAssemblyContext); var vertex_2 = (0, NativeObject_1.getVertex)(this.webAssemblyContext, 0, 0); var vec_2 = (0, NativeObject_1.getVector2)(this.webAssemblyContext); var _e = polarChartHelper_1.polarChartHelper.calcTickDirection(isInnerAxis, axis.otherAxis.flippedCoordinates, axis.startAngle, axis.otherAxis.totalAngle), direction = _e.direction, tickRotation_1 = _e.tickRotation, startAngle = _e.startAngle; var sinTick_1 = direction * Math.sin(startAngle) * tickSize; var cosTick_1 = direction * Math.cos(startAngle) * tickSize; tickCoords.forEach(function (tc) { transform.TransformPoint(tc, tickRotation_1, vec_2); vertex_2.SetPosition(vec_2.x, vec_2.y); vertices_2.push_back(vertex_2); vertex_2.SetPosition(vec_2.x + sinTick_1, vec_2.y + cosTick_1); vertices_2.push_back(vertex_2); }); renderContext.drawLinesNative(vertices_2, pen, WebGlRenderContext2D_1.ELineDrawMode.DiscontinuousLine, clipRect, leftPad, topPad); } }; return PolarAxisRenderer; }(AxisRenderer_1.AxisRenderer)); exports.PolarAxisRenderer = PolarAxisRenderer;