diff options
Diffstat (limited to 'fiv-view.c')
-rw-r--r-- | fiv-view.c | 46 |
1 files changed, 45 insertions, 1 deletions
@@ -40,9 +40,12 @@ struct _FivView { FivIoOrientation orientation; ///< Current page orientation bool filter; ///< Smooth scaling toggle bool checkerboard; ///< Show checkerboard background + bool enhance; ///< Try to enhance picture data bool scale_to_fit; ///< Image no larger than the allocation double scale; ///< Scaling factor + cairo_surface_t *enhance_swap; ///< Quick swap in/out + int remaining_loops; ///< Greater than zero if limited gint64 frame_time; ///< Current frame's start, µs precision gulong frame_update_connection; ///< GdkFrameClock::update @@ -95,6 +98,7 @@ enum { PROP_SCALE_TO_FIT, PROP_FILTER, PROP_CHECKERBOARD, + PROP_ENHANCE, PROP_PLAYING, PROP_HAS_IMAGE, PROP_CAN_ANIMATE, @@ -110,6 +114,7 @@ fiv_view_finalize(GObject *gobject) { FivView *self = FIV_VIEW(gobject); cairo_surface_destroy(self->image); + g_clear_pointer(&self->enhance_swap, cairo_surface_destroy); g_free(self->path); G_OBJECT_CLASS(fiv_view_parent_class)->finalize(gobject); @@ -133,6 +138,9 @@ fiv_view_get_property( case PROP_CHECKERBOARD: g_value_set_boolean(value, self->checkerboard); break; + case PROP_ENHANCE: + g_value_set_boolean(value, self->enhance); + break; case PROP_PLAYING: g_value_set_boolean(value, !!self->frame_update_connection); break; @@ -173,6 +181,10 @@ fiv_view_set_property( if (self->checkerboard != g_value_get_boolean(value)) fiv_view_command(self, FIV_VIEW_COMMAND_TOGGLE_CHECKERBOARD); break; + case PROP_ENHANCE: + if (self->enhance != g_value_get_boolean(value)) + fiv_view_command(self, FIV_VIEW_COMMAND_TOGGLE_ENHANCE); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); } @@ -1044,6 +1056,9 @@ fiv_view_class_init(FivViewClass *klass) view_properties[PROP_CHECKERBOARD] = g_param_spec_boolean( "checkerboard", "Show checkerboard", "Highlight transparent background", TRUE, G_PARAM_READWRITE); + view_properties[PROP_ENHANCE] = g_param_spec_boolean( + "enhance", "Enhance JPEG", "Enhance low-quality JPEG", + TRUE, G_PARAM_READWRITE); view_properties[PROP_PLAYING] = g_param_spec_boolean( "playing", "Playing animation", "An animation is running", FALSE, G_PARAM_READABLE); @@ -1095,12 +1110,20 @@ fiv_view_init(FivView *self) gboolean fiv_view_open(FivView *self, const gchar *path, GError **error) { - cairo_surface_t *surface = fiv_io_open(path, error); + cairo_surface_t *surface = fiv_io_open(path, self->enhance, error); if (!surface) return FALSE; if (self->image) cairo_surface_destroy(self->image); + // This is extremely expensive, and only works sometimes. + g_clear_pointer(&self->enhance_swap, cairo_surface_destroy); + if (self->enhance) { + self->enhance = FALSE; + g_object_notify_by_pspec( + G_OBJECT(self), view_properties[PROP_ENHANCE]); + } + self->frame = self->page = NULL; self->image = surface; switch_page(self, self->image); @@ -1134,6 +1157,21 @@ frame_step(FivView *self, int step) gtk_widget_queue_draw(GTK_WIDGET(self)); } +static void +swap_enhanced_image(FivView *self) +{ + GError *error = NULL; + cairo_surface_t *surface = self->enhance_swap; + if (!surface) + surface = fiv_io_open(self->path, self->enhance, &error); + if (!surface) { + show_error_dialog(get_toplevel(GTK_WIDGET(self)), error); + } else { + self->enhance_swap = self->image; + switch_page(self, (self->image = surface)); + } +} + void fiv_view_command(FivView *self, FivViewCommand command) { @@ -1187,6 +1225,12 @@ fiv_view_command(FivView *self, FivViewCommand command) g_object_notify_by_pspec( G_OBJECT(self), view_properties[PROP_CHECKERBOARD]); gtk_widget_queue_draw(widget); + break; case FIV_VIEW_COMMAND_TOGGLE_ENHANCE: + self->enhance = !self->enhance; + g_object_notify_by_pspec( + G_OBJECT(self), view_properties[PROP_ENHANCE]); + swap_enhanced_image(self); + break; case FIV_VIEW_COMMAND_PRINT: print(self); break; case FIV_VIEW_COMMAND_SAVE_PAGE: |