Skip to content

Commit 550b4e3

Browse files
committed
rlottie: Improve VectorPath
1 parent 4722427 commit 550b4e3

File tree

3 files changed

+57
-44
lines changed

3 files changed

+57
-44
lines changed

src/components/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ mod vector_path;
66
pub(crate) use self::avatar::Avatar;
77
pub(crate) use self::message_entry::MessageEntry;
88
pub(crate) use self::snow::Snow;
9-
pub(crate) use self::vector_path::StickerPreview;
9+
pub(crate) use self::vector_path::VectorPath;

src/components/vector_path.rs

Lines changed: 54 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,89 @@
1-
use gtk::glib;
21
use gtk::prelude::*;
32
use gtk::subclass::prelude::*;
3+
use gtk::{glib, graphene, gsk};
44

55
use tdlib::types::ClosedVectorPath;
66

77
mod imp {
88
use super::*;
9-
use gtk::graphene;
109
use std::cell::RefCell;
11-
use tdlib::enums::VectorPathCommand::{CubicBezierCurve, Line};
12-
use tdlib::types::VectorPathCommandCubicBezierCurve as Curve;
1310

1411
#[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>>,
1714
}
1815

1916
#[glib::object_subclass]
20-
impl ObjectSubclass for StickerPreview {
17+
impl ObjectSubclass for VectorPath {
2118
const NAME: &'static str = "ComponentsVectorPath";
22-
type Type = super::StickerPreview;
19+
type Type = super::VectorPath;
2320
type ParentType = gtk::Widget;
21+
22+
fn class_init(klass: &mut Self::Class) {
23+
klass.set_css_name("vectorpath");
24+
}
2425
}
2526

26-
impl ObjectImpl for StickerPreview {}
27+
impl ObjectImpl for VectorPath {}
2728

28-
impl WidgetImpl for StickerPreview {
29+
impl WidgetImpl for VectorPath {
2930
fn snapshot(&self, snapshot: &gtk::Snapshot) {
3031
let widget = self.obj();
3132

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);
4035

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);
6038
}
6139
}
6240
}
6341
}
6442

6543
glib::wrapper! {
66-
pub struct StickerPreview(ObjectSubclass<imp::StickerPreview>)
44+
pub struct VectorPath(ObjectSubclass<imp::VectorPath>)
6745
@extends gtk::Widget;
6846
}
6947

70-
impl StickerPreview {
71-
pub fn new(outline: Vec<ClosedVectorPath>) -> Self {
48+
impl VectorPath {
49+
pub fn new(outline: &[ClosedVectorPath]) -> Self {
7250
let obj: Self = glib::Object::new(&[]);
73-
obj.imp().path.replace(outline);
51+
obj.imp().node.replace(Self::path_node(outline));
7452
obj
7553
}
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+
}
7689
}

src/session/content/message_row/sticker.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::io::Cursor;
88
use tdlib::enums::{MessageContent, StickerFormat, StickerFullType};
99
use tdlib::types::File;
1010

11-
use crate::components::StickerPreview;
11+
use crate::components::VectorPath;
1212
use crate::session::content::message_row::{MessageBase, MessageBaseImpl, MessageIndicators};
1313
use crate::tdlib::Message;
1414
use crate::utils::spawn;
@@ -178,7 +178,7 @@ impl MessageBaseExt for MessageSticker {
178178
imp.aspect_ratio
179179
.set(sticker.width as f64 / sticker.height as f64);
180180

181-
let preview = StickerPreview::new(sticker.outline.clone());
181+
let preview = VectorPath::new(&sticker.outline);
182182
self.imp().bin.set_child(Some(&preview));
183183

184184
if sticker.sticker.local.is_downloading_completed {

0 commit comments

Comments
 (0)