antvis / antvis/G

[g-canvas] Path lineWidth can be rendered incorrectly with enableRenderingOptimization

Open
#2,251 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
1.2k
Forks
230
PR merge metrics
No merged PRs in 30d

Description

- OS: macOS
- Browser: Chrome 150
- Version: `@antv/g@6.3.1`, `@antv/g-canvas@2.2.0`

## Steps To Reproduce

1. Create a Canvas renderer with `enableRenderingOptimization: true`.
2. In the same frame, render a `Path` with `lineWidth: 3`, a fill-only `Text`, and another `Path` with `lineWidth: 3`.
3. Inspect each Path’s `parsedStyle.lineWidth` and `CanvasRenderingContext2D.lineWidth` when `context.stroke()` is called.

Minimal scene order:

```ts
new Path({ style: { d: "M 0 0 L 100 0", stroke: "#000", lineWidth: 3 } })
new Text({ style: { text: "label", fill: "#000" } })
new Path({ style: { d: "M 0 20 L 100 20", stroke: "#000", lineWidth: 3 } })
```

Observed state in one full render:

| Object | Desired lineWidth | Cached lineWidth | Actual ctx.lineWidth at stroke |
| --- | ---: | ---: | ---: |
| First Path | 3 | 3 | 3 |
| Fill-only Text | — | remains 3 | changes from 3 to 1 |
| Second Path | 3 | 3 | 1 |

With `enableRenderingOptimization: false`, both Paths are stroked with `lineWidth: 3`.

The issue is reproducible when consecutive Paths have the same requested width. If the requested width changes, the actual canvas value is updated, so visually identical edge sizes can be rendered at different widths depending on render order.

Link to code example: minimal scene shown above.

## The current behavior

The second Path has `parsedStyle.lineWidth === 3`, but `context.lineWidth === 1` when `context.stroke()` runs, so it is rendered at the wrong width.

## The expected behavior

Every Path should be stroked using its parsed `lineWidth`, regardless of previously rendered Text or other display objects.

Contributor guide

Open the contributing guide

Research direction

Start with the minimal scene using the Canvas renderer and enableRenderingOptimization, then inspect Path and Text rendering around parsedStyle.lineWidth, CanvasRenderingContext2D.lineWidth, and context.stroke(). Trace how the fill-only Text changes canvas state and how consecutive Paths reuse it. Done means every Path is stroked with its parsed lineWidth regardless of render order, while the optimization remains enabled.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
computer-graphics
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.