Read more of this story at Slashdot.
Read more of this story at Slashdot.
Read more of this story at Slashdot.
Read more of this story at Slashdot.
With the release of 4.23.1, GTK’s renderer will come with a new feature that we’ve called snapping.
How does it work?Snapping is enabled by calling gtk_snapshot_set_snap(). If enabled, it will slightly adjust the placement of rectangles when drawing so that they align with the pixel grid and don’t cover half a pixel.
Content drawn with GTK is scaled automatically by the desktop’s scale factor. But with the arrival of native fractional scaling, it is no longer possible to know if content is aligned to the pixel grid.
While that is usually not a problem, there are a few cases where it is:
Sprite gridsGameeky is a learning game that plays on a grid. Unfortunately, on a fractionally scaled machine, it can end up looking like this:
Once those sprites are snapped to the pixel grid by rounding to the nearest pixel, the same image looks like this
Often Applications want to display images in a way that matches the pixels of the image 1:1 with pixels of the monitor. This is a challenge on a fractionally scaled display. Not only is it important to get the scale factor right, it’s also important to align the pixels correctly, or they will appear slightly blurry.
The use case is not just image viewers that want to offer a 1:1 zoom factor, but all applications that redirect drawing, from game emulators to viewers like Boxes or Connections.
Hardware optimizationsAnd finally, there are optimizations like graphics offload that rely on content being aligned to the pixel grid or the hardware cannot optimize them. So it is important to snap content to the pixel grid for those cases.
Why don’t we just always snap to the grid?There is one big problem with automatic snapping: smoothness. Because snapping only works on full pixels, doing slow animations causes content to jump from one pixel to the next. And that causes jitter.
The main situation where one can see this is smooth scrolling, like in this example:
https://blogs.gnome.org/gtk/files/2026/04/jitter.webm SummaryThe next GTK release will offer a new way to tame the effects of fractional scaling. Please try it out and let us know how it works!
Read more of this story at Slashdot.
Read more of this story at Slashdot.
Read more of this story at Slashdot.
Read more of this story at Slashdot.
Read more of this story at Slashdot.
Read more of this story at Slashdot.
Read more of this story at Slashdot.
Read more of this story at Slashdot.
Read more of this story at Slashdot.
Read more of this story at Slashdot.
Read more of this story at Slashdot.
Read more of this story at Slashdot.
While working on my GSoC project (rewriting the Pitivi timeline in Rust), I ran into an issue getting precise UI ticks that map to the absolute nanosecond timestamps of the video frames. Initially I hardcoded NTSC fractional math (24000/1001) to calculate the boundaries of frames.
This led to issues with truncated timestamps, and had a glaring issue with other framerates (like 30fps). I needed a more robust solution that could handle any framerate and provide accurate tick positions.
I assumed that I could extract the framerate directly from ges::Timeline, however there is no direct getter in the Rust bindings. After some digging, I discovered that the framerate is actually stored in the gst::Caps of the timeline's video stream as a gst::Fraction.
My ApproachThe steps I used:
I wrote a helper function to extract the framerate from the timeline:
pub fn get_fps(&self, timeline: &ges::Timeline) -> Option<(i128, i128)> { timeline .tracks() .into_iter() .find(|track| track.track_type().contains(ges::TrackType::VIDEO)) .and_then(|track| { let caps = track.restriction_caps().or_else(|| track.caps())?; let structure = caps.structure(0)?; let fps = structure.get::<gst::Fraction>("framerate").ok()?; // Extract the safe numerator and denominator Some((fps.numer() as i128, fps.denom() as i128)) }) } // ... inside the timeline injection logic: if let Some((fps_num, fps_denom)) = self.get_fps(timeline) { self.fps_num.set(fps_num.max(1) as i32); self.fps_denom.set(fps_denom.max(1) as i32); } else { // Default to 23.976 if we can't find a valid framerate caps self.fps_num.set(24_000); self.fps_denom.set(1_001); }I make some assumptions here, such as only one video track existing, and that the framerate is always present in the caps. This solution made the tick spacing and labels line up with the timeline’s actual frame boundaries at any framerate.
Read more of this story at Slashdot.