Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: 🐛 memory access out of range on resize #76

Merged
merged 1 commit into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions dotlottie-ffi/emscripten_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ EMSCRIPTEN_BINDINGS(DotLottiePlayer)
// .field("version", &Manifest::version);

class_<DotLottiePlayer>("DotLottiePlayer")
.smart_ptr<std::shared_ptr<DotLottiePlayer>>("DotLottiePlayer")
.constructor(&DotLottiePlayer::init, allow_raw_pointers())
.function("buffer", &buffer)
.function("clear", &DotLottiePlayer::clear)
Expand All @@ -98,7 +99,7 @@ EMSCRIPTEN_BINDINGS(DotLottiePlayer)
.function("setFrame", &DotLottiePlayer::set_frame)
.function("stop", &DotLottiePlayer::stop)
.function("totalFrames", &DotLottiePlayer::total_frames)
.function("subscribe", &DotLottiePlayer::subscribe)
.function("unsubscribe", &DotLottiePlayer::unsubscribe)
// .function("subscribe", &DotLottiePlayer::subscribe)
// .function("unsubscribe", &DotLottiePlayer::unsubscribe)
.function("isComplete", &DotLottiePlayer::is_complete);
}
94 changes: 47 additions & 47 deletions dotlottie-ffi/src/dotlottie_player_cpp.udl
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
namespace dotlottie_player {
};

[Trait]
interface Observer {
void on_load();
void on_load_error();
void on_play();
void on_pause();
void on_stop();
void on_frame(f32 frame_no);
void on_render(f32 frame_no);
void on_loop(u32 loop_count);
void on_complete();
};
///[Trait]
///interface Observer {
/// void on_load();
/// void on_load_error();
/// void on_play();
/// void on_pause();
/// void on_stop();
/// void on_frame(f32 frame_no);
/// void on_render(f32 frame_no);
/// void on_loop(u32 loop_count);
/// void on_complete();
///};

enum Mode {
"Forward",
Expand All @@ -31,49 +31,49 @@ dictionary Config {
u32 background_color;
};

dictionary ManifestTheme {
string id;
sequence<string> values;
};
///dictionary ManifestTheme {
/// string id;
/// sequence<string> values;
///};

dictionary ManifestThemes {
sequence<ManifestTheme>? value;
};
///dictionary ManifestThemes {
/// sequence<ManifestTheme>? value;
///};

dictionary ManifestAnimation {
boolean? autoplay;
string? defaultTheme;
i8? direction;
boolean? hover;
string id;
u32? intermission;
boolean? loop;
u32? loop_count;
string? playMode;
u32? speed;
string? themeColor;
};
///dictionary ManifestAnimation {
/// boolean? autoplay;
/// string? defaultTheme;
/// i8? direction;
/// boolean? hover;
/// string id;
/// u32? intermission;
/// boolean? loop;
/// u32? loop_count;
/// string? playMode;
/// u32? speed;
/// string? themeColor;
///};

dictionary Manifest {
string? active_animation_id;
sequence<ManifestAnimation> animations;
string? author;
string? description;
string? generator;
string? keywords;
u32? revision;
ManifestThemes? themes;
sequence<string>? states;
string? version;
};
///dictionary Manifest {
/// string? active_animation_id;
/// sequence<ManifestAnimation> animations;
/// string? author;
/// string? description;
/// string? generator;
/// string? keywords;
/// u32? revision;
/// ManifestThemes? themes;
/// sequence<string>? states;
/// string? version;
///};

interface DotLottiePlayer {
constructor(Config config);
boolean load_animation_data([ByRef] string animation_data, u32 width, u32 height);
boolean load_animation_path([ByRef] string animation_path, u32 width, u32 height);
boolean load_dotlottie_data([ByRef] bytes file_data, u32 width, u32 height);
boolean load_animation([ByRef] string animation_id, u32 width, u32 height);
Manifest? manifest();
/// Manifest? manifest();
string manifest_string();
u64 buffer_ptr();
u64 buffer_len();
Expand All @@ -95,7 +95,7 @@ interface DotLottiePlayer {
boolean render();
boolean resize(u32 width, u32 height);
void clear();
void subscribe(Observer observer);
void unsubscribe([ByRef] Observer observer);
/// void subscribe(Observer observer);
/// void unsubscribe([ByRef] Observer observer);
boolean is_complete();
};
51 changes: 22 additions & 29 deletions dotlottie-rs/src/lottie_renderer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub struct LottieRenderer {
thorvg_animation: Option<thorvg::Animation>,
thorvg_canvas: Option<thorvg::Canvas>,
thorvg_background_shape: Option<thorvg::Shape>,
thorvg_picture: Option<thorvg::Picture>,
picture_width: f32,
picture_height: f32,
pub width: u32,
Expand All @@ -37,6 +38,7 @@ impl LottieRenderer {
thorvg_animation: None,
thorvg_canvas: None,
thorvg_background_shape: None,
thorvg_picture: None,
buffer: vec![],
width: 0,
height: 0,
Expand All @@ -52,18 +54,16 @@ impl LottieRenderer {
width: u32,
height: u32,
) -> Result<(), LottieRendererError> {
self.thorvg_animation = Some(thorvg::Animation::new());
let thorvg_animation = thorvg::Animation::new();
self.thorvg_picture = thorvg_animation.new_picture();
self.thorvg_animation = Some(thorvg_animation);
self.thorvg_background_shape = Some(thorvg::Shape::new());
self.thorvg_canvas = Some(thorvg::Canvas::new(thorvg::TvgEngine::TvgEngineSw, 0));

self.buffer = vec![0; (width * height * 4) as usize];
self.width = width;
self.height = height;

let thorvg_animation = self
.thorvg_animation
.as_mut()
.ok_or(LottieRendererError::AnimationNotLoaded)?;
self.buffer
.resize((self.width * self.height * 4) as usize, 0);

let thorvg_canvas = self
.thorvg_canvas
Expand All @@ -85,7 +85,7 @@ impl LottieRenderer {
)
.map_err(LottieRendererError::ThorvgError)?;

if let Some(picture) = &mut thorvg_animation.get_picture() {
if let Some(picture) = &mut self.thorvg_picture {
picture.load(path)?;

let (pw, ph) = picture.get_size()?;
Expand Down Expand Up @@ -115,18 +115,16 @@ impl LottieRenderer {
height: u32,
copy: bool,
) -> Result<(), LottieRendererError> {
self.thorvg_animation = Some(thorvg::Animation::new());
let thorvg_animation = thorvg::Animation::new();
self.thorvg_picture = thorvg_animation.new_picture();
self.thorvg_animation = Some(thorvg_animation);
self.thorvg_background_shape = Some(thorvg::Shape::new());
self.thorvg_canvas = Some(thorvg::Canvas::new(thorvg::TvgEngine::TvgEngineSw, 0));

self.buffer = vec![0; (width * height * 4) as usize];
self.width = width;
self.height = height;

let thorvg_animation = self
.thorvg_animation
.as_mut()
.ok_or(LottieRendererError::AnimationNotLoaded)?;
self.buffer
.resize((self.width * self.height * 4) as usize, 0);

let thorvg_canvas = self
.thorvg_canvas
Expand All @@ -148,7 +146,7 @@ impl LottieRenderer {
)
.map_err(LottieRendererError::ThorvgError)?;

if let Some(picture) = &mut thorvg_animation.get_picture() {
if let Some(picture) = &mut self.thorvg_picture {
picture.load_data(data.as_bytes(), "lottie", copy)?;

let (pw, ph) = picture.get_size()?;
Expand Down Expand Up @@ -249,11 +247,6 @@ impl LottieRenderer {
.as_mut()
.ok_or(LottieRendererError::AnimationNotLoaded)?;

let thorvg_animation = self
.thorvg_animation
.as_mut()
.ok_or(LottieRendererError::AnimationNotLoaded)?;

if (width, height) == (self.width, self.height) {
return Ok(());
}
Expand All @@ -267,25 +260,25 @@ impl LottieRenderer {
self.width = width;
self.height = height;

let mut buffer = vec![0; (width * height * 4) as usize];
self.buffer
.resize((self.width * self.height * 4) as usize, 0);

thorvg_canvas
.set_target(
&mut buffer,
width,
width,
height,
&mut self.buffer,
self.width,
self.width,
self.height,
thorvg::TvgColorspace::ABGR8888,
)
.map_err(LottieRendererError::ThorvgError)?;

if let Some(picture) = &mut thorvg_animation.get_picture() {
if let Some(picture) = &mut self.thorvg_picture {
let (pw, ph) = picture.get_size()?;
let (scale, shift_x, shift_y) = calculate_scale_and_shift(pw, ph, width, height);

picture.scale(scale)?;
picture.translate(shift_x, shift_y)?;

self.buffer = buffer;
}

Ok(())
Expand Down
2 changes: 1 addition & 1 deletion dotlottie-rs/src/thorvg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ impl Animation {
}
}

pub fn get_picture(&self) -> Option<Picture> {
pub fn new_picture(&self) -> Option<Picture> {
let raw_picture = unsafe { tvg_animation_get_picture(self.raw_animation) };

if raw_picture.is_null() {
Expand Down
Loading