messenger-gtk

Gtk+3 graphical user interfaces for GNUnet Messenger
Log | Files | Refs | Submodules | README | LICENSE

media_preview.c (3877B)


      1 /*
      2    This file is part of GNUnet.
      3    Copyright (C) 2024 GNUnet e.V.
      4 
      5    GNUnet is free software: you can redistribute it and/or modify it
      6    under the terms of the GNU Affero General Public License as published
      7    by the Free Software Foundation, either version 3 of the License,
      8    or (at your option) any later version.
      9 
     10    GNUnet is distributed in the hope that it will be useful, but
     11    WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13    Affero General Public License for more details.
     14 
     15    You should have received a copy of the GNU Affero General Public License
     16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18    SPDX-License-Identifier: AGPL3.0-or-later
     19  */
     20 /*
     21  * @author Tobias Frisch
     22  * @file ui/media_preview.c
     23  */
     24 
     25 #include "media_preview.h"
     26 
     27 #include "../application.h"
     28 #include "../file.h"
     29 #include "../ui.h"
     30 
     31 static gboolean
     32 handle_preview_drawing_area_draw(GtkWidget* drawing_area,
     33                                  cairo_t* cairo,
     34                                  gpointer user_data)
     35 {
     36   g_assert((drawing_area) && (cairo) && (user_data));
     37 
     38   UI_MEDIA_PREVIEW_Handle *handle = (UI_MEDIA_PREVIEW_Handle*) user_data;
     39 
     40   GtkStyleContext* context = gtk_widget_get_style_context(drawing_area);
     41 
     42   const guint width = gtk_widget_get_allocated_width(drawing_area);
     43   const guint height = gtk_widget_get_allocated_height(drawing_area);
     44 
     45   gtk_render_background(context, cairo, 0, 0, width, height);
     46 
     47   if (!(handle->file))
     48     return FALSE;
     49 
     50   GdkPixbuf *image = file_get_current_preview_image(handle->file);
     51 
     52   if (!image)
     53     return FALSE;
     54 
     55   int swidth = gdk_pixbuf_get_width(image);
     56   int sheight = gdk_pixbuf_get_height(image);
     57 
     58   int sx = 0;
     59   int sy = 0;
     60 
     61   if (swidth > sheight)
     62   {
     63     sx = swidth - sheight;
     64     swidth -= sx;
     65     sx /= 2;
     66   }
     67   else
     68   {
     69     sy = sheight - swidth;
     70     sheight -= sy;
     71     sy /= 2;
     72   }
     73 
     74   double ratio_width = 1.0 * width / swidth;
     75   double ratio_height = 1.0 * height / sheight;
     76 
     77   const double ratio = ratio_width < ratio_height? ratio_width : ratio_height;
     78 
     79   const int interp_type = (ratio >= 1.0?
     80     GDK_INTERP_NEAREST :
     81     GDK_INTERP_BILINEAR
     82   );
     83 
     84   GdkPixbuf* subimage = gdk_pixbuf_new_subpixbuf(
     85     image,
     86     sx,
     87     sy,
     88     swidth,
     89     sheight
     90   );
     91 
     92   GdkPixbuf* scaled = gdk_pixbuf_scale_simple(
     93     subimage,
     94     width,
     95     height,
     96     interp_type
     97   );
     98 
     99   g_object_unref(subimage);
    100   gtk_render_icon(context, cairo, scaled, 0, 0);
    101 
    102   cairo_fill(cairo);
    103   g_object_unref(scaled);
    104 
    105   return FALSE;
    106 }
    107 
    108 UI_MEDIA_PREVIEW_Handle*
    109 ui_media_preview_new(MESSENGER_Application *app)
    110 {
    111   g_assert(app);
    112 
    113   UI_MEDIA_PREVIEW_Handle* handle = g_malloc(sizeof(UI_MEDIA_PREVIEW_Handle));
    114 
    115   handle->file = NULL;
    116 
    117   handle->builder = ui_builder_from_resource(
    118     application_get_resource_path(app, "ui/media_preview.ui")
    119   );
    120 
    121   handle->media_box = GTK_WIDGET(
    122     gtk_builder_get_object(handle->builder, "media_box")
    123   );
    124 
    125   handle->preview_drawing_area = GTK_DRAWING_AREA(
    126     gtk_builder_get_object(handle->builder, "preview_drawing_area")
    127   );
    128 
    129   handle->app = app;
    130 
    131   g_signal_connect(
    132     handle->preview_drawing_area,
    133     "draw",
    134     G_CALLBACK(handle_preview_drawing_area_draw),
    135     handle
    136   );
    137 
    138   return handle;
    139 }
    140 
    141 void
    142 ui_media_preview_update(UI_MEDIA_PREVIEW_Handle *handle,
    143                         struct GNUNET_CHAT_File *file)
    144 {
    145   g_assert(handle);
    146 
    147   if (handle->file)
    148     file_remove_widget_from_preview(handle->file, GTK_WIDGET(handle->preview_drawing_area));
    149 
    150   if (file)
    151   {
    152     file_load_preview_image(file);
    153     file_add_widget_to_preview(file, GTK_WIDGET(handle->preview_drawing_area));
    154   }
    155 
    156   handle->file = file;
    157 }
    158 
    159 void
    160 ui_media_preview_delete(UI_MEDIA_PREVIEW_Handle *handle)
    161 {
    162   g_assert(handle);
    163 
    164   ui_media_preview_update(handle, NULL);
    165 
    166   g_object_unref(handle->builder);
    167 
    168   g_free(handle);
    169 }