From 259c6a2eb4c7a4924261ade4bbd261791c55c9fe Mon Sep 17 00:00:00 2001 From: Dmitry Karasik Date: Mon, 6 Nov 2023 16:13:29 +0100 Subject: [PATCH] handle loading errors gracefully --- Prima/Image/Animate.pm | 23 +++++++++++++++++++++- Prima/Image/Loader.pm | 44 ++++++++++++++++++++++++++++++------------ 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/Prima/Image/Animate.pm b/Prima/Image/Animate.pm index c03b5f611..d413069a0 100644 --- a/Prima/Image/Animate.pm +++ b/Prima/Image/Animate.pm @@ -176,11 +176,21 @@ sub reset $self-> fixup_rect( $e, $ix); } +sub warning { shift->{warning} } + sub load_next_image { my $self = shift; return unless $self->{loader}; - my ( $i ) = $self->{loader}->next; + $self->{warning} = undef; + my ( $i, $err ) = $self->{loader}->next; + unless ($i) { + $self->{warning} = $err; + $self->{loader}->reload; + ( $i, $err ) = $self->{loader}->next; + $self->{current} = 0; + $self->{warning} = $err unless $i; + } return $i; } @@ -209,6 +219,10 @@ sub advance_frame } else { $self->{image} = $oimg; } + unless ($self->{image}) { + $self->{image} = $oimg; + $self->{info} = $oinfo; + } my $info = $self->{info} = $self-> get_extras; $self-> fixup_rect( $info, $self-> {image}); @@ -758,6 +772,13 @@ Returns the width and height of the composite frame Return the number of frames +=head2 warning + +If an error occured during frame loading, it will be stored in the C +property. The animation will stop at the last successfully loaded frame + +Only available if the C option is off. + =head2 width Returns the width of the composite frame diff --git a/Prima/Image/Loader.pm b/Prima/Image/Loader.pm index bbe818f78..29daea246 100644 --- a/Prima/Image/Loader.pm +++ b/Prima/Image/Loader.pm @@ -15,11 +15,25 @@ sub new $events{$k} = $v if $k =~ /^on/; } - my $img = Prima::Image->new( %events ); - my $ok = $img->load( $source, + my $self = bless { + source => $source, + events => \%events, + options => \%opt, + }; + + my ( $l, $ok ) = $self->reload; + return (undef, $ok) unless $l; + return $self; +} + +sub reload +{ + my $self = shift; + my $img = Prima::Image->new( %{ $self->{events} } ); + my $ok = $img->load( $self->{source}, loadExtras => 1, wantFrames => 1, - %opt, + %{ $self->{options} }, session => 1 ); unless ($ok) { @@ -30,15 +44,12 @@ sub new $img->destroy; return (undef, "cannot read number of frames"); } - - return bless { - source => $source, - image => $img, - extras => $img->{extras}, - frames => $img->{extras}->{frames}, - current => 0, - events => \%events, - }, $class; + $self->{image} = $img; + $self->{extras} = $img->{extras}; + $self->{frames} = $img->{extras}->{frames}; + $self->{current} = 0; + undef $self->{error}; + return $img; } sub next @@ -196,6 +207,15 @@ Loads the next image frame. Returns either a newly loaded image, or C and the error string. +=item reload + +In case an animation file is defect, and cannot be loaded in full, the toolkit +will not allow to continue the loading session and will close it automatically. +If it is desired to work around this limitation, a new session must be opened. +The C method does this by reopening the loading session with all the +parameters supplied to C. The programmer thus has a chance to record how +many successful frames were loaded, and only navigate these after the reload. + =item source Return the filename or the file handle passed to the C call.