scichart
Version:
Fast WebGL JavaScript Charting Library and Framework
384 lines (383 loc) • 23.6 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.BaseSeriesDrawingProvider = void 0;
var DeletableEntity_1 = require("../../../../Core/DeletableEntity");
var Deleter_1 = require("../../../../Core/Deleter");
var Guard_1 = require("../../../../Core/Guard");
var colorUtil_1 = require("../../../../utils/colorUtil");
var number_1 = require("../../../../utils/number");
var parseColor_1 = require("../../../../utils/parseColor");
var PaletteCache_1 = require("../../../Drawing/PaletteCache");
var IPaletteProvider_1 = require("../../../Model/IPaletteProvider");
var createSolidBrush_1 = require("../../Helpers/createSolidBrush");
var constants_1 = require("../constants");
/**
* Used internally - a drawing provider performs drawing for a specific chart-type or series using
* our WebAssembly WebGL rendering engine
*/
var BaseSeriesDrawingProvider = /** @class */ (function (_super) {
__extends(BaseSeriesDrawingProvider, _super);
/**
* Creates an instance of the {@link BaseSeriesDrawingProvider}
* @param webAssemblyContext The {@link TSciChart | SciChart 2D WebAssembly Context} containing native methods and
* access to our WebGL2 Engine and WebAssembly numerical methods
* @param parentSeries the parent {@link IRenderableSeries | Renderable Series} which this drawing provider is attached to
*/
function BaseSeriesDrawingProvider(webAssemblyContext, parentSeries, ySelector, xSelector) {
var _this = this;
var _a;
_this = _super.call(this) || this;
Guard_1.Guard.notNull(webAssemblyContext, "webAssemblyContext");
Guard_1.Guard.notNull(parentSeries, "parentSeries");
_this.webAssemblyContext = webAssemblyContext;
_this.parentSeries = parentSeries;
_this.ySelector = ySelector !== null && ySelector !== void 0 ? ySelector : (function (ps) { return ps.yValues; });
_this.xSelector = xSelector !== null && xSelector !== void 0 ? xSelector : (function (ps) { return ps.xValues; });
_this.palettingState = {
palettedColors: undefined,
palettedColorsHashCode: 0,
gradientPaletting: false,
paletteTextureCache: new PaletteCache_1.PaletteCache(webAssemblyContext),
requiresUpdate: true
};
_this.seriesHasDataChanges = _this.seriesHasDataChanges.bind(_this);
_this.parentDataSeries = _this.parentSeries.dataSeries;
(_a = _this.parentDataSeries) === null || _a === void 0 ? void 0 : _a.dataChanged.subscribe(_this.seriesHasDataChanges);
return _this;
}
/**
* Returns the startIndex and count to be passed to the native drawing provider.
* If renderPassData exists and contains an indexRange, this will be used, otherwise the full size of the xValues will be used
* @param renderPassData
* @param xValues
* @returns
*/
BaseSeriesDrawingProvider.prototype.getStartAndCount = function (renderPassData, xValues) {
var _a, _b, _c;
var pointSeries = renderPassData === null || renderPassData === void 0 ? void 0 : renderPassData.pointSeries;
var xAxis = (_a = this.parentSeries) === null || _a === void 0 ? void 0 : _a.xAxis;
var shouldClip = (_b = xAxis === null || xAxis === void 0 ? void 0 : xAxis.clipToXRange) !== null && _b !== void 0 ? _b : true; // fo the sake of tests
var xCount = xValues.size();
var count = Math.min(pointSeries ? pointSeries.xValues.size() : xCount, xCount);
var startIndex = 0;
if (shouldClip && !(pointSeries === null || pointSeries === void 0 ? void 0 : pointSeries.resampled) && ((_c = renderPassData === null || renderPassData === void 0 ? void 0 : renderPassData.indexRange) === null || _c === void 0 ? void 0 : _c.diff) >= 0) {
if (renderPassData.indexRange.diff + 1 < count) {
startIndex = renderPassData.indexRange.min;
}
count = Math.min(renderPassData.indexRange.diff + 1, count);
}
return { startIndex: startIndex, count: count };
};
/**
* Helper function to apply color-paletting to a {@link UIntVector} - where each element in the vector
* is an ARGB color that defines stroke of the series
* @param strokePen the current pen, as type {@link SCRTPen}
* @param renderPassData optional renderPassData. If not supplied, the current renderPassData for the parent series will be used
* @returns the new {@link UIntVector} with ARGB colors
*/
BaseSeriesDrawingProvider.prototype.applyStrokePaletting = function (strokePen, renderPassData) {
var _a, _b, _c, _d;
var advancedPP = this.parentSeries.paletteProvider;
if (this.parentSeries.hasStrokePaletteProvider() || advancedPP.applyPaletting !== undefined) {
var strokeColorArgb = (0, colorUtil_1.uintArgbColorMultiplyOpacity)((0, parseColor_1.parseColorToUIntArgb)(this.parentSeries.stroke), this.parentSeries.opacity);
if (isNaN(strokeColorArgb)) {
throw Error("applyStrokePaletting(): renderSeries.stroke " +
this.parentSeries.stroke +
" cannot be converted to a valid color");
}
var strokePaletteProvider = this.parentSeries.paletteProvider;
var dataSeries = this.parentSeries.dataSeries;
renderPassData = renderPassData !== null && renderPassData !== void 0 ? renderPassData : this.parentSeries.getCurrentRenderPassData();
var pointSeries = renderPassData === null || renderPassData === void 0 ? void 0 : renderPassData.pointSeries;
var xValues = (_a = (pointSeries ? this.xSelector(pointSeries) : undefined)) !== null && _a !== void 0 ? _a : dataSeries.getNativeXValues();
var yValues = (_b = (pointSeries ? this.ySelector(pointSeries) : undefined)) !== null && _b !== void 0 ? _b : dataSeries.getNativeYValues();
var _e = this.getStartAndCount(renderPassData, xValues), startIndex = _e.startIndex, count = _e.count;
if (!this.palettingState.palettedColors) {
this.palettingState.palettedColors = new this.webAssemblyContext.UIntVector();
}
// For paletted series, we must pass 0xFFFFFFFF (white) to pen line
this.palettingState.originalPenColor = strokePen.m_uiColor;
strokePen.m_uiColor = 0xffffffff;
strokePen.m_bGradient = strokePaletteProvider.strokePaletteMode === IPaletteProvider_1.EStrokePaletteMode.GRADIENT;
if (advancedPP.applyPaletting) {
advancedPP.applyPaletting(this.palettingState, xValues, yValues, (_c = pointSeries === null || pointSeries === void 0 ? void 0 : pointSeries.indexes) !== null && _c !== void 0 ? _c : dataSeries.getNativeIndexes(), startIndex, count);
return;
}
this.shouldUpdatePalette(renderPassData, strokePaletteProvider, startIndex, count, false);
if (!this.palettingState.requiresUpdate) {
return;
}
this.palettingState.palettedColors.clear();
this.palettingState.palettedColors.reserve(count);
var hasPSIndexes = pointSeries && pointSeries.indexes.size() > 0;
for (var index = startIndex; index < startIndex + count; index++) {
var originalDataIndex = hasPSIndexes ? pointSeries.indexes.get(index) : index;
if (originalDataIndex < 0)
originalDataIndex = 0;
else if (originalDataIndex >= dataSeries.count())
originalDataIndex = dataSeries.count() - 1;
var xValue = xValues.get(index);
var yValue = yValues.get(index);
var overrideColor = strokePaletteProvider.overrideStrokeArgb(xValue, yValue, originalDataIndex, this.parentSeries.opacity, dataSeries.getMetadataAt(originalDataIndex));
this.parentSeries.pushPalettedColors(overrideColor ? overrideColor : strokeColorArgb, this.palettingState);
}
this.palettingState.requiresUpdate = false;
}
else {
if (this.palettingState.originalPenColor) {
strokePen.m_uiColor = this.palettingState.originalPenColor;
this.palettingState.originalPenColor = undefined;
}
(_d = this.palettingState.palettedColors) === null || _d === void 0 ? void 0 : _d.clear();
}
// Due to pass-by-pointer limitations of WASM binding, we pass an empty vector rather than null
if (!this.palettingState.palettedColors) {
this.palettingState.palettedColors = new this.webAssemblyContext.UIntVector();
}
};
BaseSeriesDrawingProvider.prototype.applyStrokeFillPaletting = function (stroke, strokePen, fill, fillBrush, opacity, usePalette, resetPenBrushColors, renderPassData) {
var _a, _b, _c, _d, _e, _f;
if (usePalette === void 0) { usePalette = false; }
if (resetPenBrushColors === void 0) { resetPenBrushColors = true; }
var hasStrokePaletteProvider = this.parentSeries.hasStrokePaletteProvider();
var hasFillPaletteProvider = this.parentSeries.hasFillPaletteProvider();
var hasPointMarkerPaletteProvider = this.parentSeries.hasPointMarkerPaletteProvider();
var strokePaletteProvider = this.parentSeries.paletteProvider;
var advancedPP = this.parentSeries.paletteProvider;
var hasAdvancedPP = (advancedPP === null || advancedPP === void 0 ? void 0 : advancedPP.applyPaletting) !== undefined;
if (hasStrokePaletteProvider || hasFillPaletteProvider || hasPointMarkerPaletteProvider || hasAdvancedPP) {
var strokeColor = void 0;
var fillColor = void 0;
// Palette (this.palettingState.paletteTextureCache) is used only for band and mountain series
if (usePalette) {
strokeColor = fillColor = this.webAssemblyContext.SCRTPalette.GetNoOverrideColorCode();
}
else {
var hasOpacity = opacity !== undefined;
strokeColor =
stroke && hasOpacity ? (0, colorUtil_1.uintArgbColorMultiplyOpacity)((0, parseColor_1.parseColorToUIntArgb)(stroke), 1) : 0xffffffff;
fillColor =
fill && hasOpacity ? (0, colorUtil_1.uintArgbColorMultiplyOpacity)((0, parseColor_1.parseColorToUIntArgb)(fill), 1) : 0xffffffff;
}
if (isNaN(strokeColor)) {
throw Error("updatePalette(): parentSeries.stroke " + stroke + " cannot be converted to a valid color");
}
if (isNaN(fillColor)) {
throw Error("updatePalette(): fillColor " + fillColor + " cannot be converted to a valid color");
}
var dataSeries = this.parentSeries.dataSeries;
renderPassData = renderPassData !== null && renderPassData !== void 0 ? renderPassData : this.parentSeries.getCurrentRenderPassData();
var pointSeries = renderPassData === null || renderPassData === void 0 ? void 0 : renderPassData.pointSeries;
var xValues = (_a = (pointSeries ? this.xSelector(pointSeries) : undefined)) !== null && _a !== void 0 ? _a : dataSeries.getNativeXValues();
var yValues = (_b = (pointSeries ? this.ySelector(pointSeries) : undefined)) !== null && _b !== void 0 ? _b : dataSeries.getNativeYValues();
var _g = this.getStartAndCount(renderPassData, xValues), startIndex = _g.startIndex, count = _g.count;
if (!this.palettingState.palettedColors) {
this.palettingState.palettedColors = new this.webAssemblyContext.UIntVector();
}
if (advancedPP.applyPaletting) {
advancedPP.applyPaletting(this.palettingState, xValues, yValues, (_c = pointSeries === null || pointSeries === void 0 ? void 0 : pointSeries.indexes) !== null && _c !== void 0 ? _c : dataSeries.getNativeIndexes(), startIndex, count);
return;
}
this.shouldUpdatePalette(renderPassData, strokePaletteProvider, startIndex, count, true);
if (!this.palettingState.requiresUpdate) {
return;
}
this.palettingState.paletteTextureCache.reset();
this.palettingState.palettedColors.clear();
this.palettingState.palettedColors.reserve(count * 2);
if (resetPenBrushColors) {
if (strokePen && hasStrokePaletteProvider) {
// For paletted series, we must pass 0xFFFFFFFF (white) to pen line
this.palettingState.originalPenColor = strokePen.m_uiColor;
strokePen.m_uiColor = 0xffffffff;
this.palettingState.originalPenGradient = strokePen.m_bGradient;
strokePen.m_bGradient = strokePaletteProvider.strokePaletteMode === IPaletteProvider_1.EStrokePaletteMode.GRADIENT;
}
if (fillBrush) {
this.palettingState.originalBrushColor = fillBrush.GetColor();
fillBrush.SetColor(0xffffffff);
}
}
// Override stroke and fill colors
var hashCode = 0;
var hasPSIndexes = pointSeries && pointSeries.indexes.size() > 0;
for (var index = startIndex; index < startIndex + count; index++) {
var originalDataIndex = hasPSIndexes ? pointSeries.indexes.get(index) : index;
if (originalDataIndex < 0)
originalDataIndex = 0;
else if (originalDataIndex >= dataSeries.count())
originalDataIndex = dataSeries.count() - 1;
var xValue = xValues.get(index);
var yValue = yValues.get(index);
var overriddenColors = this.overridePaletteProviderColors(this.parentSeries, xValue, yValue, originalDataIndex, opacity, dataSeries.getMetadataAt(originalDataIndex));
var overrideStrokeColor = (_d = overriddenColors.stroke) !== null && _d !== void 0 ? _d : strokeColor;
var overrideFillColor = (_e = overriddenColors.fill) !== null && _e !== void 0 ? _e : fillColor;
this.palettingState.palettedColors.push_back(overrideStrokeColor);
this.palettingState.palettedColors.push_back(overrideFillColor);
if (usePalette) {
hashCode = (0, number_1.numericHashCode)(hashCode, overrideStrokeColor);
hashCode = (0, number_1.numericHashCode)(hashCode, overrideFillColor);
}
}
// Palette is used only for band and mountain series
if (usePalette) {
if (this.palettingState.palettedColorsHashCode !== hashCode) {
this.palettingState.paletteTextureCache.reset();
}
this.palettingState.paletteTextureCache.create(this.palettingState.palettedColors);
this.palettingState.palettedColorsHashCode = hashCode;
}
this.palettingState.requiresUpdate = false;
}
else {
this.palettingState.paletteTextureCache.reset();
(_f = this.palettingState.palettedColors) === null || _f === void 0 ? void 0 : _f.clear();
if (strokePen) {
if (this.palettingState.originalPenColor) {
strokePen.m_uiColor = this.palettingState.originalPenColor;
this.palettingState.originalPenColor = undefined;
}
if (this.palettingState.originalPenGradient) {
strokePen.m_bGradient = this.palettingState.originalPenGradient;
this.palettingState.originalPenGradient = undefined;
}
}
if (fillBrush && this.palettingState.originalBrushColor) {
fillBrush.SetColor(this.palettingState.originalBrushColor);
this.palettingState.originalBrushColor = undefined;
}
}
// Due to pass-by-pointer limitations of WASM binding, we pass an empty vector rather than null
if (!this.palettingState.palettedColors) {
this.palettingState.palettedColors = new this.webAssemblyContext.UIntVector();
}
// Set gradient for the fill color
this.palettingState.gradientPaletting = this.isGradientFillPaletting(this.parentSeries);
};
/**
* Creates a native {@link SCRTBrush} Solid Color Brush from html color code string passed in
* @param htmlColorCode The HTML Color code
* @param opacity The opacity factor
*/
BaseSeriesDrawingProvider.prototype.createSolidBrush = function (htmlColorCode, opacity) {
return (0, createSolidBrush_1.createSolidBrush)(this.webAssemblyContext, htmlColorCode, opacity);
};
/**
* @inheritDoc
*/
BaseSeriesDrawingProvider.prototype.delete = function () {
if (this.palettingState.palettedColors) {
this.palettingState.palettedColors = (0, Deleter_1.deleteSafe)(this.palettingState.palettedColors);
}
this.palettingState.paletteTextureCache = (0, Deleter_1.deleteSafe)(this.palettingState.paletteTextureCache);
};
/**
* @inheritDoc
*/
BaseSeriesDrawingProvider.prototype.onSeriesPropertyChange = function (propertyName) {
var _a, _b;
if (propertyName === constants_1.PROPERTY.DATA_SERIES) {
(_a = this.parentDataSeries) === null || _a === void 0 ? void 0 : _a.dataChanged.unsubscribe(this.seriesHasDataChanges);
this.parentDataSeries = this.parentSeries.dataSeries;
(_b = this.parentDataSeries) === null || _b === void 0 ? void 0 : _b.dataChanged.subscribe(this.seriesHasDataChanges);
this.palettingState.requiresUpdate = true;
}
};
/**
* @inheritDoc
*/
BaseSeriesDrawingProvider.prototype.onDpiChanged = function (args) {
// Override in derived class to be notified of Dpi changes
};
/**
* @inheritDoc
*/
BaseSeriesDrawingProvider.prototype.onAttachSeries = function () {
// Override in derived class to be notified of series being attached to sciChartSurface
};
/**
* @inheritDoc
*/
BaseSeriesDrawingProvider.prototype.onDetachSeries = function () {
// Override in derived class to be notified of series being detached from sciChartSurface
};
BaseSeriesDrawingProvider.prototype.seriesHasDataChanges = function () {
this.palettingState.requiresUpdate = true;
// TODO override in derived class.
};
BaseSeriesDrawingProvider.prototype.shouldUpdatePalette = function (renderPassData, paletteProvider, startIndex, count, isDoubled) {
var _a, _b, _c, _d, _e, _f;
if (((_a = renderPassData === null || renderPassData === void 0 ? void 0 : renderPassData.pointSeries) === null || _a === void 0 ? void 0 : _a.resampled) &&
(renderPassData === null || renderPassData === void 0 ? void 0 : renderPassData.resamplingHash) !== this.palettingState.lastResamplingHash) {
this.palettingState.lastResamplingHash = renderPassData === null || renderPassData === void 0 ? void 0 : renderPassData.resamplingHash;
this.palettingState.requiresUpdate = true;
}
if (!((_b = paletteProvider.isRangeIndependant) !== null && _b !== void 0 ? _b : false)) {
// Range dependant (the default) so recalculate if start and count have changed
if (((_c = this.palettingState.lastStartIndex) !== null && _c !== void 0 ? _c : 0) !== startIndex ||
((_d = this.palettingState.lastCount) !== null && _d !== void 0 ? _d : 0) !== count) {
this.palettingState.lastStartIndex = startIndex;
this.palettingState.lastCount = count;
this.palettingState.requiresUpdate = true;
this.palettingState.paletteStartIndex = 0;
}
}
else {
if (((_e = this.palettingState.lastStartIndex) !== null && _e !== void 0 ? _e : Number.MAX_SAFE_INTEGER) > startIndex ||
((_f = this.palettingState.lastCount) !== null && _f !== void 0 ? _f : 0) < count ||
startIndex + count > this.palettingState.lastStartIndex + this.palettingState.lastCount) {
// Range has grown so recalcualte and start from 0
this.palettingState.lastStartIndex = startIndex;
this.palettingState.lastCount = count;
this.palettingState.requiresUpdate = true;
this.palettingState.paletteStartIndex = 0;
}
else {
// Range is same or smaller so adjust palette startIndex
this.palettingState.paletteStartIndex =
startIndex * (isDoubled ? 2 : 1) - this.palettingState.lastStartIndex;
}
}
// Default to always update for back compatability
if (!paletteProvider.shouldUpdatePalette || paletteProvider.shouldUpdatePalette()) {
this.palettingState.requiresUpdate = true;
}
};
BaseSeriesDrawingProvider.prototype.overridePaletteProviderColors = function (rs, xValue, yValue, index, opacity, metadata) {
var stroke;
var fill;
if (rs.hasStrokePaletteProvider()) {
var strokePaletteProvider = rs.paletteProvider;
stroke = strokePaletteProvider.overrideStrokeArgb(xValue, yValue, index, opacity, metadata);
}
if (rs.hasFillPaletteProvider()) {
var fillPaletteProvider = rs.paletteProvider;
fill = fillPaletteProvider.overrideFillArgb(xValue, yValue, index, opacity, metadata);
}
return { stroke: stroke, fill: fill };
};
BaseSeriesDrawingProvider.prototype.isGradientFillPaletting = function (rs) {
if (rs.hasFillPaletteProvider()) {
var fillPaletteProvider = rs.paletteProvider;
return fillPaletteProvider.fillPaletteMode === IPaletteProvider_1.EFillPaletteMode.GRADIENT;
}
return false;
};
return BaseSeriesDrawingProvider;
}(DeletableEntity_1.DeletableEntity));
exports.BaseSeriesDrawingProvider = BaseSeriesDrawingProvider;