Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhanced color space support #1719

Merged
merged 10 commits into from
Nov 11, 2024
2 changes: 2 additions & 0 deletions scripts/run-graphics-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ fi

npm install
npm run $BUILD_SCRIPT
# Remove existing merge-base-dist if it exists
rm -rf ./merge-base-dist
mv ./dist ./merge-base-dist

echo "Checkout to HEAD back and build..."
Expand Down
11 changes: 11 additions & 0 deletions src/api/chart-api.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/// <reference types="_build-time-constants" />
import { ChartWidget, MouseEventParamsImpl, MouseEventParamsImplSupplier } from '../gui/chart-widget';

import { assert, ensure, ensureDefined } from '../helpers/assertions';
Expand Down Expand Up @@ -298,6 +299,16 @@ export class ChartApi<HorzScaleItem> implements IChartApiBase<HorzScaleItem>, Da
}

public applyOptions(options: DeepPartial<ChartOptionsImpl<HorzScaleItem>>): void {
if (process.env.NODE_ENV === 'development') {
const colorSpace = options.layout?.colorSpace;
if (colorSpace !== undefined && colorSpace !== this.options().layout.colorSpace) {
throw new Error(`colorSpace option should not be changed once the chart has been created.`);
}
const colorParsers = options.layout?.colorParsers;
if (colorParsers !== undefined && colorParsers !== this.options().layout.colorParsers) {
throw new Error(`colorParsers option should not be changed once the chart has been created.`);
}
}
this._chartWidget.applyOptions(toInternalOptions(options));
}

Expand Down
2 changes: 2 additions & 0 deletions src/api/options/layout-options-defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ export const layoutOptionsDefaults: LayoutOptions = {
separatorHoverColor: 'rgba(178, 181, 189, 0.2)',
},
attributionLogo: true,
colorSpace: 'srgb',
colorParsers: [],
};
9 changes: 6 additions & 3 deletions src/gui/attribution-logo-widget.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { colorStringToGrayscale } from '../helpers/color';

import { IChartWidgetBase } from './chart-widget';

type LogoTheme = 'dark' | 'light';
Expand Down Expand Up @@ -44,7 +42,12 @@ export class AttributionLogoWidget {
}

private _themeToUse(): LogoTheme {
return colorStringToGrayscale(this._chart.options()['layout'].textColor) > 160 ? 'dark' : 'light';
return this._chart
.model()
.colorParser()
.colorStringToGrayscale(this._chart.options()['layout'].textColor) > 160
? 'dark'
: 'light';
}

private _shouldBeVisible(): boolean {
Expand Down
8 changes: 6 additions & 2 deletions src/gui/pane-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -484,9 +484,13 @@ export class PaneWidget implements IDestroyable, MouseEventHandlers {
this._rightPriceAxisWidget.paint(type);
}

const canvasOptions: CanvasRenderingContext2DSettings = {
colorSpace: this._chart.options().layout.colorSpace,
};

if (type !== InvalidationLevel.Cursor) {
this._canvasBinding.applySuggestedBitmapSize();
const target = tryCreateCanvasRenderingTarget2D(this._canvasBinding);
const target = tryCreateCanvasRenderingTarget2D(this._canvasBinding, canvasOptions);
if (target !== null) {
target.useBitmapCoordinateSpace((scope: BitmapCoordinatesRenderingScope) => {
this._drawBackground(scope);
Expand All @@ -501,7 +505,7 @@ export class PaneWidget implements IDestroyable, MouseEventHandlers {
}

this._topCanvasBinding.applySuggestedBitmapSize();
const topTarget = tryCreateCanvasRenderingTarget2D(this._topCanvasBinding);
const topTarget = tryCreateCanvasRenderingTarget2D(this._topCanvasBinding, canvasOptions);
if (topTarget !== null) {
topTarget.useBitmapCoordinateSpace(({ context: ctx, bitmapSize }: BitmapCoordinatesRenderingScope) => {
ctx.clearRect(0, 0, bitmapSize.width, bitmapSize.height);
Expand Down
4 changes: 3 additions & 1 deletion src/gui/price-axis-stub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ export class PriceAxisStub implements IDestroyable {
this._invalidated = false;

this._canvasBinding.applySuggestedBitmapSize();
const target = tryCreateCanvasRenderingTarget2D(this._canvasBinding);
const target = tryCreateCanvasRenderingTarget2D(this._canvasBinding, {
colorSpace: this._options.layout.colorSpace,
});
if (target !== null) {
target.useBitmapCoordinateSpace((scope: BitmapCoordinatesRenderingScope) => {
this._drawBackground(scope);
Expand Down
14 changes: 10 additions & 4 deletions src/gui/price-axis-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,11 @@ export class PriceAxisWidget implements IDestroyable {
let tickMarkMaxWidth = 0;
const rendererOptions = this.rendererOptions();

const ctx = ensureNotNull(this._canvasBinding.canvasElement.getContext('2d'));
const ctx = ensureNotNull(
this._canvasBinding.canvasElement.getContext('2d', {
colorSpace: this._pane.chart().options().layout.colorSpace,
})
);
ctx.save();

const tickMarks = this._priceScale.marks();
Expand Down Expand Up @@ -345,11 +349,13 @@ export class PriceAxisWidget implements IDestroyable {
if (this._size === null) {
return;
}

const canvasOptions: CanvasRenderingContext2DSettings = {
colorSpace: this._pane.chart().options().layout.colorSpace,
};
if (type !== InvalidationLevel.Cursor) {
this._alignLabels();
this._canvasBinding.applySuggestedBitmapSize();
const target = tryCreateCanvasRenderingTarget2D(this._canvasBinding);
const target = tryCreateCanvasRenderingTarget2D(this._canvasBinding, canvasOptions);
if (target !== null) {
target.useBitmapCoordinateSpace((scope: BitmapCoordinatesRenderingScope) => {
this._drawBackground(scope);
Expand All @@ -363,7 +369,7 @@ export class PriceAxisWidget implements IDestroyable {
}

this._topCanvasBinding.applySuggestedBitmapSize();
const topTarget = tryCreateCanvasRenderingTarget2D(this._topCanvasBinding);
const topTarget = tryCreateCanvasRenderingTarget2D(this._topCanvasBinding, canvasOptions);
if (topTarget !== null) {
topTarget.useBitmapCoordinateSpace(({ context: ctx, bitmapSize }: BitmapCoordinatesRenderingScope) => {
ctx.clearRect(0, 0, bitmapSize.width, bitmapSize.height);
Expand Down
8 changes: 5 additions & 3 deletions src/gui/time-axis-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,10 +298,12 @@ export class TimeAxisWidget<HorzScaleItem> implements MouseEventHandlers, IDestr
if (type === InvalidationLevel.None) {
return;
}

const canvasOptions: CanvasRenderingContext2DSettings = {
colorSpace: this._options.colorSpace,
};
if (type !== InvalidationLevel.Cursor) {
this._canvasBinding.applySuggestedBitmapSize();
const target = tryCreateCanvasRenderingTarget2D(this._canvasBinding);
const target = tryCreateCanvasRenderingTarget2D(this._canvasBinding, canvasOptions);
if (target !== null) {
target.useBitmapCoordinateSpace((scope: BitmapCoordinatesRenderingScope) => {
this._drawBackground(scope);
Expand All @@ -324,7 +326,7 @@ export class TimeAxisWidget<HorzScaleItem> implements MouseEventHandlers, IDestr
}

this._topCanvasBinding.applySuggestedBitmapSize();
const topTarget = tryCreateCanvasRenderingTarget2D(this._topCanvasBinding);
const topTarget = tryCreateCanvasRenderingTarget2D(this._topCanvasBinding, canvasOptions);
if (topTarget !== null) {
topTarget.useBitmapCoordinateSpace(({ context: ctx, bitmapSize }: BitmapCoordinatesRenderingScope) => {
ctx.clearRect(0, 0, bitmapSize.width, bitmapSize.height);
Expand Down
Loading
Loading