Skip to content

Commit 2189dc3

Browse files
examples: Add fill & stroke copy of the C gtk-demo
1 parent e4e714c commit 2189dc3

File tree

7 files changed

+157
-1
lines changed

7 files changed

+157
-1
lines changed

examples/Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ im-rc = { version = "15", optional = true }
1717
[dependencies.gtk]
1818
path = "../gtk4"
1919
package = "gtk4"
20-
features = ["v4_10"]
20+
features = ["v4_14"]
2121

2222
# used by gif-paintable example
2323
[dependencies.image]
@@ -167,6 +167,10 @@ path = "squares/main.rs"
167167
name = "squeezer_bin"
168168
path = "squeezer_bin/main.rs"
169169

170+
[[bin]]
171+
name = "fill_and_stroke"
172+
path = "fill_and_stroke/main.rs"
173+
170174
[[bin]]
171175
name = "text_viewer"
172176
path = "text_viewer/main.rs"

examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ cargo run --bin basics
3434
- [Entry Undo](./entry_undo/)
3535
- [Expressions](./expressions/)
3636
- [FemtoVG Area](./femtovg_area/)
37+
- [Fill and Stroke](./fill_and_stroke/)
3738
- [FlowBox](./flow_box/)
3839
- [Glium GL-Area](./glium_gl_area/)
3940
- [Grid Packing](./grid_packing)

examples/fill_and_stroke/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Fill and Stroke
2+
3+
This example shows how to create a custom `gdk::Paintable` that uses the new Path APIs
4+
5+
![Screenshot](screenshot.png)

examples/fill_and_stroke/main.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
mod paintable;
2+
3+
use gtk::glib;
4+
use gtk::prelude::*;
5+
6+
fn main() -> glib::ExitCode {
7+
let application = gtk::Application::builder()
8+
.application_id("com.github.gtk-rs.examples.fill_and_stroke")
9+
.build();
10+
11+
application.connect_activate(|app| {
12+
let win = gtk::ApplicationWindow::builder()
13+
.application(app)
14+
.title("Fill and Stroke")
15+
.build();
16+
17+
let picture = gtk::Picture::builder()
18+
.content_fit(gtk::ContentFit::ScaleDown)
19+
.build();
20+
let paintable = paintable::CustomPaintable::new();
21+
picture.set_paintable(Some(&paintable));
22+
win.set_child(Some(&picture));
23+
24+
win.present();
25+
});
26+
27+
application.run()
28+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
use gtk::prelude::*;
2+
use gtk::subclass::prelude::*;
3+
use gtk::{gdk, glib, graphene, gsk};
4+
5+
pub struct CustomPaintable {
6+
pub(super) height: i32,
7+
pub(super) width: i32,
8+
pub(super) paths: Vec<gsk::Path>,
9+
pub(super) colors: Vec<gdk::RGBA>,
10+
pub(super) stroke_path: gsk::Path,
11+
pub(super) stroke1: gsk::Stroke,
12+
pub(super) stroke2: gsk::Stroke,
13+
pub(super) stroke_color: gdk::RGBA,
14+
}
15+
16+
impl Default for CustomPaintable {
17+
fn default() -> Self {
18+
/* Paths and colors extracted from gtk-logo.svg */
19+
let paths = vec![
20+
gsk::Path::parse("m3.12,66.17 -2.06,-51.46 32.93,24.7 v55.58 l-30.87,-28.82 z")
21+
.unwrap(),
22+
gsk::Path::parse("m34,95 49.4,-20.58 4.12,-51.46 -53.52,16.47 v55.58 z").unwrap(),
23+
gsk::Path::parse("m1.06,14.71 32.93,24.7 53.52,-16.47 -36.75,-21.88 -49.7,13.65 z")
24+
.unwrap(),
25+
];
26+
let colors = vec![
27+
gdk::RGBA::parse("#e40000").unwrap(),
28+
gdk::RGBA::parse("#7fe719").unwrap(),
29+
gdk::RGBA::parse("#729fcf").unwrap(),
30+
];
31+
let stroke_path = gsk::Path::parse("m50.6,51.3 -47.3,14 z l33,23 z v-50").unwrap();
32+
let stroke1 = gsk::Stroke::new(2.12);
33+
let stroke2 = gsk::Stroke::new(1.25);
34+
let stroke_color = gdk::RGBA::WHITE;
35+
36+
let mut bounds = paths[0].stroke_bounds(&stroke1).unwrap();
37+
let bounds2 = paths[1].stroke_bounds(&stroke1).unwrap();
38+
bounds = bounds.union(&bounds2);
39+
let bounds3 = paths[2].stroke_bounds(&stroke1).unwrap();
40+
bounds = bounds.union(&bounds3);
41+
let bounds_path = stroke_path.stroke_bounds(&stroke2).unwrap();
42+
bounds = bounds.union(&bounds_path);
43+
let width = bounds.x() + bounds.width();
44+
let height = bounds.y() + bounds.height();
45+
Self {
46+
height: height as i32,
47+
width: width as i32,
48+
paths,
49+
colors,
50+
stroke_path,
51+
stroke1,
52+
stroke2,
53+
stroke_color,
54+
}
55+
}
56+
}
57+
58+
#[glib::object_subclass]
59+
impl ObjectSubclass for CustomPaintable {
60+
const NAME: &'static str = "CustomPaintable";
61+
type Type = super::CustomPaintable;
62+
type Interfaces = (gdk::Paintable,);
63+
}
64+
65+
impl ObjectImpl for CustomPaintable {}
66+
67+
impl PaintableImpl for CustomPaintable {
68+
fn flags(&self) -> gdk::PaintableFlags {
69+
// Fixed size and content
70+
gdk::PaintableFlags::SIZE | gdk::PaintableFlags::CONTENTS
71+
}
72+
73+
fn intrinsic_width(&self) -> i32 {
74+
self.width
75+
}
76+
77+
fn intrinsic_height(&self) -> i32 {
78+
self.height
79+
}
80+
81+
fn snapshot(&self, snapshot: &gdk::Snapshot, width: f64, height: f64) {
82+
let bounds = graphene::Rect::new(0., 0., width as f32, height as f32);
83+
for (i, path) in self.paths.iter().enumerate() {
84+
snapshot.push_fill(path, gsk::FillRule::Winding);
85+
snapshot.append_color(&self.colors[i], &bounds);
86+
snapshot.pop();
87+
}
88+
89+
for _ in 0..3 {
90+
snapshot.push_stroke(&self.stroke_path, &self.stroke1);
91+
snapshot.append_color(&self.stroke_color, &bounds);
92+
snapshot.pop();
93+
}
94+
95+
snapshot.push_stroke(&self.stroke_path, &self.stroke2);
96+
snapshot.append_color(&self.stroke_color, &bounds);
97+
snapshot.pop();
98+
}
99+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
mod imp;
2+
3+
use gtk::{gdk, glib};
4+
5+
glib::wrapper! {
6+
pub struct CustomPaintable(ObjectSubclass<imp::CustomPaintable>) @implements gdk::Paintable;
7+
}
8+
9+
impl Default for CustomPaintable {
10+
fn default() -> Self {
11+
Self::new()
12+
}
13+
}
14+
15+
impl CustomPaintable {
16+
pub fn new() -> Self {
17+
glib::Object::new()
18+
}
19+
}
10 KB
Loading

0 commit comments

Comments
 (0)