Skip to content

Commit

Permalink
Merge pull request #1585 from tradingview/fix-price-label-rendering-a…
Browse files Browse the repository at this point in the history
…rtefact

fix rendering glitch with drawRoundRectWithInnerBorder
  • Loading branch information
SlicedSilver committed May 8, 2024
2 parents 70827f7 + 289a780 commit 85b8807
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 18 deletions.
8 changes: 4 additions & 4 deletions .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ module.exports = [
{
name: 'CJS',
path: 'dist/lightweight-charts.production.cjs',
limit: '48.15 KB',
limit: '48.16 KB',
},
{
name: 'ESM',
path: 'dist/lightweight-charts.production.mjs',
limit: '48.11 KB',
limit: '48.09 KB',
},
{
name: 'Standalone-ESM',
path: 'dist/lightweight-charts.standalone.production.mjs',
limit: '49.8 KB',
limit: '49.79 KB',
},
{
name: 'Standalone',
path: 'dist/lightweight-charts.standalone.production.js',
limit: '49.85 KB',
limit: '49.83 KB',
},
];
32 changes: 21 additions & 11 deletions src/helpers/canvas-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ export function drawRoundRect(
* be able to switch to the native version soon.
*/
ctx.beginPath();
if (ctx.roundRect) {
ctx.roundRect(x, y, w, h, radii);
return;
}
/*
* Deprecate the rest in v5.
*/
ctx.lineTo(x + w - radii[1], y);
if (radii[1] !== 0) {
ctx.arcTo(x + w, y, x + w, y + radii[1], radii[1]);
Expand All @@ -85,44 +92,47 @@ export function drawRoundRect(
}
}

/**
* Draws a rounded rect with a border.
*
* This function assumes that the colors will be solid, without
* any alpha. (This allows us to fix a rendering artefact.)
*
* @param outerBorderRadius - The radius of the border (outer edge)
*/
// eslint-disable-next-line max-params
export function drawRoundRectWithInnerBorder(
export function drawRoundRectWithBorder(
ctx: CanvasRenderingContext2D,
left: number,
top: number,
width: number,
height: number,
backgroundColor: string,
borderWidth: number = 0,
borderRadius: LeftTopRightTopRightBottomLeftBottomRadii = [0, 0, 0, 0],
outerBorderRadius: LeftTopRightTopRightBottomLeftBottomRadii = [0, 0, 0, 0],
borderColor: string = ''
): void {
ctx.save();

if (!borderWidth || !borderColor || borderColor === backgroundColor) {
drawRoundRect(ctx, left, top, width, height, borderRadius);
drawRoundRect(ctx, left, top, width, height, outerBorderRadius);
ctx.fillStyle = backgroundColor;
ctx.fill();
ctx.restore();
return;
}

const halfBorderWidth = borderWidth / 2;
const radii = changeBorderRadius(outerBorderRadius, - halfBorderWidth);

// Draw body
if (backgroundColor !== 'transparent') {
const innerRadii = changeBorderRadius(borderRadius, - borderWidth);
drawRoundRect(ctx, left + borderWidth, top + borderWidth, width - borderWidth * 2, height - borderWidth * 2, innerRadii);
drawRoundRect(ctx, left + halfBorderWidth, top + halfBorderWidth, width - borderWidth, height - borderWidth, radii);

if (backgroundColor !== 'transparent') {
ctx.fillStyle = backgroundColor;
ctx.fill();
}

// Draw border
if (borderColor !== 'transparent') {
const outerRadii = changeBorderRadius(borderRadius, - halfBorderWidth);
drawRoundRect(ctx, left + halfBorderWidth, top + halfBorderWidth, width - borderWidth, height - borderWidth, outerRadii);

ctx.lineWidth = borderWidth;
ctx.strokeStyle = borderColor;
ctx.closePath();
Expand Down
10 changes: 7 additions & 3 deletions src/renderers/price-axis-view-renderer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BitmapCoordinatesRenderingScope, CanvasRenderingTarget2D, MediaCoordinatesRenderingScope } from 'fancy-canvas';

import { drawRoundRectWithInnerBorder } from '../helpers/canvas-helpers';
import { drawRoundRectWithBorder } from '../helpers/canvas-helpers';

import { TextWidthCache } from '../model/text-width-cache';

Expand Down Expand Up @@ -80,8 +80,12 @@ export class PriceAxisViewRenderer implements IPriceAxisViewRenderer {
const gb = geom.bitmap;

const drawLabelBody = (labelBackgroundColor: string, labelBorderColor?: string): void => {
/*
labelBackgroundColor (and labelBorderColor) will always be a solid color (no alpha) [see generateContrastColors in color.ts].
Therefore we can draw the rounded label using simplified code (drawRoundRectWithBorder) that doesn't need to ensure the background and the border don't overlap.
*/
if (geom.alignRight) {
drawRoundRectWithInnerBorder(
drawRoundRectWithBorder(
ctx,
gb.xOutside,
gb.yTop,
Expand All @@ -93,7 +97,7 @@ export class PriceAxisViewRenderer implements IPriceAxisViewRenderer {
labelBorderColor
);
} else {
drawRoundRectWithInnerBorder(
drawRoundRectWithBorder(
ctx,
gb.xInside,
gb.yTop,
Expand Down

0 comments on commit 85b8807

Please sign in to comment.