[g-canvas] Path lineWidth can be rendered incorrectly with enableRenderingOptimization
- 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
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