Skip to content

feat: GPUView widget, vector icons, enterprise icon quality, deps cascade v0.50.11 - #200

Merged
kolkov merged 8 commits into
mainfrom
feat/gpuview-icons-v0.1.49
Aug 2, 2026
Merged

feat: GPUView widget, vector icons, enterprise icon quality, deps cascade v0.50.11#200
kolkov merged 8 commits into
mainfrom
feat/gpuview-icons-v0.1.49

Conversation

@kolkov

@kolkov kolkov commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Summary

GPUView widget (Flutter Texture pattern), vector icon rendering, enterprise icon quality improvements, and full ecosystem deps cascade.

Added

  • GPUView widget (feat: 3D compositing — PreRender hook, Canvas.DrawGPUTexture, Viewport3D widget (ADR-048) #150) — renamed from Viewport3D (38 frameworks researched). ExternalTextureLayer in Layer Tree, GPUTextureProvider interface, SetOnCreateGPUTexture wiring. Examples: gpuview, filedrop.
  • Vector icon rendering (gg#464) — SVG → scene geometry via RenderToSceneWithColor. Resolution-independent, no bitmap pre-rasterization.
  • JetBrains @20x20 SVG icons — native tool window icons from IntelliJ reference (1:1 scale).
  • SVG window controls — minimize, maximize, restore, close from JetBrains reference (pixel-perfect filled rects). Both default and DevTools painters.
  • OS file drag-and-drop bridge (drag file to app #189) — KindFile, FilePayload, Manager.DropExternal.

Fixed

  • Stripe label overflow — PushClip/PopClip around label DrawText.
  • Icon pixel-snap — math.Round on center positions (BUG-ICON-002).
  • Icon foreground color — #9DA0A8 → #CED0D6 (JetBrains dark variant).
  • Toolbar icon size — maxIconSize 20→16 for 1:1 viewBox rendering.

Changed

  • deps: gg v0.50.11, gogpu v0.48.4, gpucontext v0.24.0, wgpu v0.30.34, naga v0.18.0

Test plan

  • go build ./... — pass
  • go test ./... -count=1 — 0 failures
  • golangci-lint run --timeout=5m — 0 issues
  • Visual: IDE example — icons crisp, labels clipped, window controls SVG
  • Visual: hello, gallery, signals, taskmanager, filedrop — all working

kolkov added 7 commits August 2, 2026 13:12
- Renamed viewport3d → gpuview (enterprise naming, 38 frameworks researched)
- ExternalTextureLayer wired into Layer Tree build/update
- SetOnCreateGPUTexture wired in desktop.initCanvas
- GPUTextureProvider interface on widget.Context
- FontSmoothing mock for gpucontext v0.23.0
- Examples: gpuview, filedrop
- DnD bridge: KindFile, FilePayload, Manager.DropExternal
- 7 ExternalTextureLayer tests, 14 GPUView tests, 7 DnD tests
Replace bitmap pre-rasterization in SceneCanvas.RenderSVG with direct
vector scene emission via svg.Document.RenderToSceneWithColor.
Icons are resolution-independent scene geometry, rendered at display
resolution. Matches Skia/Jewel architecture.
…ins colors

- Native @20x20 JetBrains SVGs for stripe tool window icons (1:1 scale)
- Pixel-snap icon positions via math.Round (BUG-ICON-002)
- Stroke-width 1.5→1 for crisp rendering (documented tradeoff vs JetBrains)
- DevTools stripe foreground #9DA0A8→#CED0D6 (JetBrains dark variant)
- ToolTerminal converted from PathOps 24x24 to SVGXML 16x16
- Tests: pixel-snap, containment, JetBrains reference size
- PushClip/PopClip around label DrawText prevents overflow into panels
- Window controls: procedural DrawLine/StrokeRect → JetBrains SVG icons
- Both default and DevTools titlebar painters updated
- Tests: label containment, SVG renderer assertions
CHANGELOG [Unreleased], README, ROADMAP, ARCHITECTURE updated.
…v0.18.0

Major ecosystem cascade:
- gg: vector icons (RenderToSceneWithColor), stroke hinting, text quality
- gogpu: PollInputEvent, FontSmoothing, OS DnD, CommandEncoder
- wgpu: ADR-056 resource lifecycle, @samyfodil queue pin fix
- naga: shader compiler improvements
- CHANGELOG and ARCHITECTURE deps updated
@codecov

codecov Bot commented Aug 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 70.83333% with 21 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
theme/devtools/stripe.go 0.00% 8 Missing ⚠️
desktop/desktop.go 0.00% 5 Missing ⚠️
core/gpuview/widget.go 42.85% 4 Missing ⚠️
app/layer_tree.go 86.66% 1 Missing and 1 partial ⚠️
core/stripe/painter.go 75.00% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@kolkov
kolkov merged commit 707bbf3 into main Aug 2, 2026
9 checks passed
samyfodil added a commit to samyfodil/ui that referenced this pull request Aug 3, 2026
RenderSVG on the scene canvas positions a document with a transform built from
the bounds it is handed, but never constrains it to them. Anything the document
draws past its own viewBox therefore lands on whatever surrounds the icon.

That is not an unusual document. An SVG may draw anywhere, and every renderer
that follows the spec clips to the viewport; icon sets rely on it, since a
stroke centred on the viewBox edge puts half its width outside. So the common
case is a bleed of a pixel or two, invisible wherever another widget paints
afterwards and covers it. It becomes visible on the last icon in a row, or one
against the edge of a window, where nothing paints over the spill: in a terminal
emulator on this toolkit a 16x16 gear in the tab bar's trailing cluster painted
a block from its own origin to the corner of the window, over the tab bar.

This arrived with the switch to vector re-emission (gogpu#200). The previous path
rasterised the document into a bitmap sized from those same bounds, so the
bounds were enforced by construction — nothing could escape a raster that size.
Emitting geometry into the scene removed that, and nothing took its place.

Two changes, both making RenderSVG behave like its neighbours:

  - Push a clip of the given bounds around the emission, so the document is
    bounded the way the raster used to bound it.
  - Honour the current clip. Every other draw method on this canvas returns
    early when isVisible is false; RenderSVG was the one that did not, so an
    icon with no pixels on screen still emitted its whole document.

Tests cover both, using a document that deliberately draws four times its
viewBox — the visible version of the stroke case. Scene.Bounds() is the union
of the shapes and does not narrow for a clip, so the test checks the emitted
commands instead.
kolkov pushed a commit that referenced this pull request Aug 3, 2026
RenderSVG on the scene canvas positions a document with a transform built from
the bounds it is handed, but never constrains it to them. Anything the document
draws past its own viewBox therefore lands on whatever surrounds the icon.

That is not an unusual document. An SVG may draw anywhere, and every renderer
that follows the spec clips to the viewport; icon sets rely on it, since a
stroke centred on the viewBox edge puts half its width outside. So the common
case is a bleed of a pixel or two, invisible wherever another widget paints
afterwards and covers it. It becomes visible on the last icon in a row, or one
against the edge of a window, where nothing paints over the spill: in a terminal
emulator on this toolkit a 16x16 gear in the tab bar's trailing cluster painted
a block from its own origin to the corner of the window, over the tab bar.

This arrived with the switch to vector re-emission (#200). The previous path
rasterised the document into a bitmap sized from those same bounds, so the
bounds were enforced by construction — nothing could escape a raster that size.
Emitting geometry into the scene removed that, and nothing took its place.

Two changes, both making RenderSVG behave like its neighbours:

  - Push a clip of the given bounds around the emission, so the document is
    bounded the way the raster used to bound it.
  - Honour the current clip. Every other draw method on this canvas returns
    early when isVisible is false; RenderSVG was the one that did not, so an
    icon with no pixels on screen still emitted its whole document.

Tests cover both, using a document that deliberately draws four times its
viewBox — the visible version of the stroke case. Scene.Bounds() is the union
of the shapes and does not narrow for a clip, so the test checks the emitted
commands instead.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant