Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@cameronwhite
Copy link
Member

@cameronwhite cameronwhite commented May 23, 2025

  • Rewrite the canvas widget to render to a Gdk.Texture at the original image size, and then apply scaling at render time via Gtk.Snapshot. This avoids allocating huge textures for zoomed in images, which happens in GTK4 with the DrawingArea widget.
  • This would be a bit cleaner to implement as a custom widget once gir.core supports virtual functions, but for now a Gtk.Picture widget suffices. For example, we could more easily react to size changes to simplify updates to the ruler, etc
  • Since we don't have a 'resize' event from the DrawingArea widget anymore, some of the event handlers now look at the scroll area's adjustments, which have suitable events when they are modified
  • The workspace offset is no longer needed with the switch to Gtk.Pciture and configuring the H/Valign properties to avoid expansion. This greatly simplifies translating between original and zoomed coordinates. The one exception is the ruler widget, which still needs to figure out the offset from the corner of the viewport to the canvas
  • The canvas drop shadow is now applied via CSS rather than being manually implemented
  • Tools can now indicate whether they manipulate selections (and should display a filled selection rather than an outline), cleaning up some hacky code

Tasks

  • Render the canvas to a Gdk.Texture
  • Port tool handles to render to a Gtk.Snapshot
  • Port selections to render to a Gtk.Snapshot
  • Port the pixel grid to render to a Gtk.Snapshot
  • Fix the transparent grid pattern to render at a constant screen space size
  • Investigate whether partial updates to the canvas texture can be performed
  • Profile performance (e.g. caching the pixel grid's path)
  • Queue updates to the canvas when there are multiple Invalidate() calls (e.g. in the text tool)
  • Test on different platforms
  • Verify whether we can increase the minimum GTK version to 4.16+, or find alternative APIs to use

Bug: #1020

@cameronwhite cameronwhite force-pushed the feature/texture-canvas branch 3 times, most recently from 785f791 to bcb6099 Compare May 26, 2025 03:24
- Rewrite the canvas widget to render to a Gdk.Texture at the original image size, and then apply scaling at render time via Gtk.Snapshot. This avoids allocating huge textures for zoomed in images, which happens in GTK4 with the previous DrawingArea widget.

- This would be a bit cleaner to implement as a custom widget once gir.core supports virtual functions, but for now a Gtk.Picture widget suffices. For example, we could more easily react to size changes to simplify updates to the ruler, etc

- Since we don't have a 'resize' event from the DrawingArea widget anymore, some of the event handlers now look at the scroll area's adjustments, which have suitable events when they are modified

- The workspace offset is no longer needed with the switch to Gtk.Pciture and configuring the H/Valign properties to avoid expansion. This greatly simplifies translating between original and zoomed coordinates. The one exception is the ruler widget, which still needs to figure out the offset from the corner of the viewport to the canvas

Bug: #1020
This eliminates hacky code in the canvas which compared against the tool's type name to decide whether to show a filled selection.
The magic wand tool also now shows a filled selection to match the other selection tools
This can easily be done by adding a CSS style to the widget rather than drawing it manually, and this also looks nicer since a smooth blur can be added
This implementation ends up being a lot simpler by rendering a scaled Gsk.Path, and performance seems good in my testing.
This can't be done in the canvas renderer since it would scale along with the zoomed image. Instead, we draw a tiled texture into the widget before drawing the scaled canvas texture
@cameronwhite cameronwhite force-pushed the feature/texture-canvas branch from 013123e to 0699449 Compare May 27, 2025 02:34
- Provide a clip area to the canvas renderer to limit the updated area for Cairo operations. This avoids the old code's approach of allocating a new surface whenever the area changes

- Use the 'update-texture' property of Gdk.MemoryTextureBuilder to apply updates to an area of the texture

- Change the "CanvasInvalidated" event to use a canvas-space rectangle, which makes more sense for the new implementation
These can extend beyond the canvas, so this avoids the widget stretching out
…pdate

This happened in the eraser tool - since we no longer draw a checkboard background in the canvas renderer (and instead overlay the canvas texture on the background), we need to ensure the existing canvas image surface is cleared out in case the layer now has some transparent pixels
@cameronwhite cameronwhite marked this pull request as ready for review May 28, 2025 03:01
@cameronwhite
Copy link
Member Author

I think this is in a pretty good place now and could use some wider testing
Probably the most risky change is that this switched back to doing partial updates of the canvas (which was disabled when porting the old canvas widget to GTK4), so it's possible this might expose some bugs that slipped in if the canvas isn't being correctly invalidated

@JGCarroll - for the snap package, do you know which GTK version (and libadwaita version) would be available? For these changes I think we'll need to bump up to at least GTK 4.16

@JGCarroll
Copy link
Contributor

JGCarroll commented May 28, 2025

@JGCarroll - for the snap package, do you know which GTK version (and libadwaita version) would be available? For these changes I think we'll need to bump up to at least GTK 4.16

GTK is 4.18
Adwaita is 1.7.2
You can check the latest versions here: https://github.com/ubuntu/gnome-sdk/blob/gnome-46-2404-sdk/snapcraft.yaml

@cameronwhite
Copy link
Member Author

@JGCarroll - for the snap package, do you know which GTK version (and libadwaita version) would be available? For these changes I think we'll need to bump up to at least GTK 4.16

GTK is 4.18 Adwaita is 1.7.2 You can check the latest versions here: https://github.com/ubuntu/gnome-sdk/blob/gnome-46-2404-sdk/snapcraft.yaml

That's great, thank you!
I'll likely just bump the requirement to 4.18 then since that's available for all our target platforms

We need at least GTK 4.16 for the new canvas widget, but we may as well jump to 4.18 which is widely available on our target platforms.
@cameronwhite cameronwhite force-pushed the feature/texture-canvas branch from 1045a4e to 93fc609 Compare May 29, 2025 02:48
@cameronwhite cameronwhite linked an issue May 30, 2025 that may be closed by this pull request
@cameronwhite cameronwhite merged commit ef47a61 into master May 30, 2025
11 checks passed
@cameronwhite cameronwhite deleted the feature/texture-canvas branch May 30, 2025 03:39
@pedropaulosuzuki
Copy link
Contributor

Testing a little bit, it seems there is a white border on the bottom and right sides of the canvas after this patch, at least on low zoom.

image

Before:

image

@cameronwhite
Copy link
Member Author

Thanks, yeah I could reproduce that after turning on the canvas grid to 16x16 on the default 800x600 image

cameronwhite added a commit that referenced this pull request May 31, 2025
This avoids expanding the widget's size (e.g. from the stroke's antialiasing) when the lines extend to the edge of the canvas

Bug: #1485
@cameronwhite
Copy link
Member Author

I think we just needed to clip the canvas grid to the bounds to make sure it doesn't expand the widget's size by an extra pixel: 601c250

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.

Crash when zooming in max (3,600%)

4 participants