|
1 | | -use gtk::glib; |
2 | 1 | use gtk::prelude::*; |
3 | 2 | use gtk::subclass::prelude::*; |
| 3 | +use gtk::{glib, graphene, gsk}; |
4 | 4 |
|
5 | 5 | use tdlib::types::ClosedVectorPath; |
6 | 6 |
|
7 | 7 | mod imp { |
8 | 8 | use super::*; |
9 | | - use gtk::graphene; |
10 | 9 | use std::cell::RefCell; |
11 | | - use tdlib::enums::VectorPathCommand::{CubicBezierCurve, Line}; |
12 | | - use tdlib::types::VectorPathCommandCubicBezierCurve as Curve; |
13 | 10 |
|
14 | 11 | #[derive(Default)] |
15 | | - pub struct StickerPreview { |
16 | | - pub(super) path: RefCell<Vec<ClosedVectorPath>>, |
| 12 | + pub struct VectorPath { |
| 13 | + pub(super) node: RefCell<Option<gsk::RenderNode>>, |
17 | 14 | } |
18 | 15 |
|
19 | 16 | #[glib::object_subclass] |
20 | | - impl ObjectSubclass for StickerPreview { |
| 17 | + impl ObjectSubclass for VectorPath { |
21 | 18 | const NAME: &'static str = "ComponentsVectorPath"; |
22 | | - type Type = super::StickerPreview; |
| 19 | + type Type = super::VectorPath; |
23 | 20 | type ParentType = gtk::Widget; |
| 21 | + |
| 22 | + fn class_init(klass: &mut Self::Class) { |
| 23 | + klass.set_css_name("vectorpath"); |
| 24 | + } |
24 | 25 | } |
25 | 26 |
|
26 | | - impl ObjectImpl for StickerPreview {} |
| 27 | + impl ObjectImpl for VectorPath {} |
27 | 28 |
|
28 | | - impl WidgetImpl for StickerPreview { |
| 29 | + impl WidgetImpl for VectorPath { |
29 | 30 | fn snapshot(&self, snapshot: >k::Snapshot) { |
30 | 31 | let widget = self.obj(); |
31 | 32 |
|
32 | | - let context = snapshot.append_cairo(&graphene::Rect::new(0.0, 0.0, 512.0, 512.0)); |
33 | | - |
34 | | - let scale = widget.width().max(widget.height()) as f64 / 512.0; |
35 | | - context.scale(scale, scale); |
36 | | - |
37 | | - context.set_source_rgba(0.5, 0.5, 0.5, 0.4); |
38 | | - |
39 | | - let outline = &*self.path.borrow(); |
| 33 | + let factor = (widget.width() as f32).max(widget.height() as f32) / 512.0; |
| 34 | + snapshot.scale(factor, factor); |
40 | 35 |
|
41 | | - for closed_path in outline { |
42 | | - for command in &closed_path.commands { |
43 | | - match command { |
44 | | - Line(line) => { |
45 | | - let e = &line.end_point; |
46 | | - context.line_to(e.x, e.y); |
47 | | - } |
48 | | - CubicBezierCurve(curve) => { |
49 | | - let Curve { |
50 | | - start_control_point: sc, |
51 | | - end_control_point: ec, |
52 | | - end_point: e, |
53 | | - } = curve; |
54 | | - |
55 | | - context.curve_to(sc.x, sc.y, ec.x, ec.y, e.x, e.y); |
56 | | - } |
57 | | - } |
58 | | - } |
59 | | - _ = context.fill(); |
| 36 | + if let Some(node) = &*self.node.borrow() { |
| 37 | + snapshot.append_node(node); |
60 | 38 | } |
61 | 39 | } |
62 | 40 | } |
63 | 41 | } |
64 | 42 |
|
65 | 43 | glib::wrapper! { |
66 | | - pub struct StickerPreview(ObjectSubclass<imp::StickerPreview>) |
| 44 | + pub struct VectorPath(ObjectSubclass<imp::VectorPath>) |
67 | 45 | @extends gtk::Widget; |
68 | 46 | } |
69 | 47 |
|
70 | | -impl StickerPreview { |
71 | | - pub fn new(outline: Vec<ClosedVectorPath>) -> Self { |
| 48 | +impl VectorPath { |
| 49 | + pub fn new(outline: &[ClosedVectorPath]) -> Self { |
72 | 50 | let obj: Self = glib::Object::new(&[]); |
73 | | - obj.imp().path.replace(outline); |
| 51 | + obj.imp().node.replace(Self::path_node(outline)); |
74 | 52 | obj |
75 | 53 | } |
| 54 | + |
| 55 | + fn path_node(outline: &[ClosedVectorPath]) -> Option<gsk::RenderNode> { |
| 56 | + use tdlib::enums::VectorPathCommand::{CubicBezierCurve, Line}; |
| 57 | + use tdlib::types::VectorPathCommandCubicBezierCurve as Curve; |
| 58 | + |
| 59 | + let snapshot = gtk::Snapshot::new(); |
| 60 | + let context = snapshot.append_cairo(&graphene::Rect::new(0.0, 0.0, 512.0, 512.0)); |
| 61 | + |
| 62 | + context.set_source_rgba(0.5, 0.5, 0.5, 0.4); |
| 63 | + |
| 64 | + for closed_path in outline { |
| 65 | + context.new_sub_path(); |
| 66 | + for command in &closed_path.commands { |
| 67 | + match command { |
| 68 | + Line(line) => { |
| 69 | + let e = &line.end_point; |
| 70 | + context.line_to(e.x, e.y); |
| 71 | + } |
| 72 | + CubicBezierCurve(curve) => { |
| 73 | + let Curve { |
| 74 | + start_control_point: sc, |
| 75 | + end_control_point: ec, |
| 76 | + end_point: e, |
| 77 | + } = curve; |
| 78 | + |
| 79 | + context.curve_to(sc.x, sc.y, ec.x, ec.y, e.x, e.y); |
| 80 | + } |
| 81 | + } |
| 82 | + } |
| 83 | + context.close_path(); |
| 84 | + } |
| 85 | + _ = context.fill(); |
| 86 | + |
| 87 | + snapshot.to_node() |
| 88 | + } |
76 | 89 | } |
0 commit comments