scichart
Version:
Fast WebGL JavaScript Charting Library and Framework
382 lines (381 loc) • 23.8 kB
JavaScript
"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;