@@ -34,7 +34,7 @@ struct _NemoPreviewImage {
3434};
3535
3636typedef struct {
37- GtkWidget * image ;
37+ GtkWidget * drawing_area ;
3838 GtkWidget * message_label ;
3939 NemoFile * file ;
4040
@@ -45,12 +45,16 @@ typedef struct {
4545
4646 /* Keep reference to current pixbuf for quick scaling */
4747 GdkPixbuf * current_pixbuf ;
48+
49+ /* Current surface to draw */
50+ cairo_surface_t * current_surface ;
4851} NemoPreviewImagePrivate ;
4952
5053G_DEFINE_TYPE_WITH_PRIVATE (NemoPreviewImage , nemo_preview_image , GTK_TYPE_BOX )
5154
5255/* Forward declarations */
5356static void on_size_allocate (GtkWidget * widget , GtkAllocation * allocation , gpointer user_data );
57+ static gboolean on_drawing_area_draw (GtkWidget * widget , cairo_t * cr , gpointer user_data );
5458
5559static void
5660nemo_preview_image_finalize (GObject * object )
@@ -71,6 +75,11 @@ nemo_preview_image_finalize (GObject *object)
7175 priv -> current_pixbuf = NULL ;
7276 }
7377
78+ if (priv -> current_surface != NULL ) {
79+ cairo_surface_destroy (priv -> current_surface );
80+ priv -> current_surface = NULL ;
81+ }
82+
7483 if (priv -> file != NULL ) {
7584 nemo_file_unref (priv -> file );
7685 priv -> file = NULL ;
@@ -91,12 +100,17 @@ nemo_preview_image_init (NemoPreviewImage *preview)
91100 priv -> current_width = 0 ;
92101 priv -> current_height = 0 ;
93102 priv -> current_pixbuf = NULL ;
94-
95- /* Create image widget */
96- priv -> image = gtk_image_new ();
97- gtk_widget_set_halign (priv -> image , GTK_ALIGN_CENTER );
98- gtk_widget_set_valign (priv -> image , GTK_ALIGN_CENTER );
99- gtk_box_pack_start (GTK_BOX (preview ), priv -> image , TRUE, TRUE, 0 );
103+ priv -> current_surface = NULL ;
104+
105+ /* Create drawing area widget */
106+ priv -> drawing_area = gtk_drawing_area_new ();
107+ gtk_widget_set_halign (priv -> drawing_area , GTK_ALIGN_FILL );
108+ gtk_widget_set_valign (priv -> drawing_area , GTK_ALIGN_FILL );
109+ gtk_widget_set_hexpand (priv -> drawing_area , TRUE);
110+ gtk_widget_set_vexpand (priv -> drawing_area , TRUE);
111+ g_signal_connect (priv -> drawing_area , "draw" ,
112+ G_CALLBACK (on_drawing_area_draw ), preview );
113+ gtk_box_pack_start (GTK_BOX (preview ), priv -> drawing_area , TRUE, TRUE, 0 );
100114
101115 /* Create message label (hidden by default) */
102116 priv -> message_label = gtk_label_new ("" );
@@ -129,6 +143,42 @@ nemo_preview_image_new (void)
129143 NULL );
130144}
131145
146+ static gboolean
147+ on_drawing_area_draw (GtkWidget * widget ,
148+ cairo_t * cr ,
149+ gpointer user_data )
150+ {
151+ NemoPreviewImage * preview = NEMO_PREVIEW_IMAGE (user_data );
152+ NemoPreviewImagePrivate * priv ;
153+ gint widget_width , widget_height ;
154+ gint surface_width , surface_height ;
155+ gdouble x_offset , y_offset ;
156+ gint scale_factor ;
157+
158+ priv = nemo_preview_image_get_instance_private (preview );
159+
160+ if (priv -> current_surface == NULL ) {
161+ return FALSE;
162+ }
163+
164+ widget_width = gtk_widget_get_allocated_width (widget );
165+ widget_height = gtk_widget_get_allocated_height (widget );
166+
167+ /* Get surface dimensions - works for image surfaces created from pixbufs */
168+ scale_factor = gtk_widget_get_scale_factor (widget );
169+ surface_width = cairo_image_surface_get_width (priv -> current_surface ) / scale_factor ;
170+ surface_height = cairo_image_surface_get_height (priv -> current_surface ) / scale_factor ;
171+
172+ /* Center the image in the drawing area */
173+ x_offset = (widget_width - surface_width ) / 2.0 ;
174+ y_offset = (widget_height - surface_height ) / 2.0 ;
175+
176+ cairo_set_source_surface (cr , priv -> current_surface , x_offset , y_offset );
177+ cairo_paint (cr );
178+
179+ return TRUE;
180+ }
181+
132182static gboolean
133183is_image_file (NemoFile * file )
134184{
@@ -196,9 +246,13 @@ load_image_at_size (NemoPreviewImage *widget,
196246 surface = gdk_cairo_surface_create_from_pixbuf (pixbuf , ui_scale , NULL );
197247
198248 if (surface != NULL ) {
199- gtk_image_set_from_surface (GTK_IMAGE (priv -> image ), surface );
200- gtk_widget_show (priv -> image );
201- cairo_surface_destroy (surface );
249+ /* Replace old surface with new one */
250+ if (priv -> current_surface != NULL ) {
251+ cairo_surface_destroy (priv -> current_surface );
252+ }
253+ priv -> current_surface = surface ;
254+ gtk_widget_show (priv -> drawing_area );
255+ gtk_widget_queue_draw (priv -> drawing_area );
202256 }
203257
204258 g_object_unref (pixbuf );
@@ -212,7 +266,7 @@ load_image_at_size (NemoPreviewImage *widget,
212266 gtk_label_set_text (GTK_LABEL (priv -> message_label ),
213267 _ ("(Failed to load image)" ));
214268 gtk_widget_show (priv -> message_label );
215- gtk_widget_hide (priv -> image );
269+ gtk_widget_hide (priv -> drawing_area );
216270 }
217271
218272 g_free (path );
@@ -265,8 +319,12 @@ scale_current_pixbuf_to_size (NemoPreviewImage *widget,
265319 surface = gdk_cairo_surface_create_from_pixbuf (scaled_pixbuf , ui_scale , NULL );
266320
267321 if (surface != NULL ) {
268- gtk_image_set_from_surface (GTK_IMAGE (priv -> image ), surface );
269- cairo_surface_destroy (surface );
322+ /* Replace old surface with new one */
323+ if (priv -> current_surface != NULL ) {
324+ cairo_surface_destroy (priv -> current_surface );
325+ }
326+ priv -> current_surface = surface ;
327+ gtk_widget_queue_draw (priv -> drawing_area );
270328 }
271329
272330 g_object_unref (scaled_pixbuf );
@@ -357,9 +415,12 @@ nemo_preview_image_set_file (NemoPreviewImage *widget,
357415 priv -> file = file ;
358416
359417 /* Clear current image */
360- gtk_image_clear (GTK_IMAGE (priv -> image ));
418+ if (priv -> current_surface != NULL ) {
419+ cairo_surface_destroy (priv -> current_surface );
420+ priv -> current_surface = NULL ;
421+ }
361422 gtk_widget_hide (priv -> message_label );
362- gtk_widget_hide (priv -> image );
423+ gtk_widget_hide (priv -> drawing_area );
363424 priv -> current_width = 0 ;
364425 priv -> current_height = 0 ;
365426
@@ -385,14 +446,17 @@ nemo_preview_image_set_file (NemoPreviewImage *widget,
385446 if (icon_pixbuf != NULL ) {
386447 surface = gdk_cairo_surface_create_from_pixbuf (icon_pixbuf , ui_scale , NULL );
387448 if (surface != NULL ) {
388- gtk_image_set_from_surface (GTK_IMAGE (priv -> image ), surface );
389- cairo_surface_destroy (surface );
449+ if (priv -> current_surface != NULL ) {
450+ cairo_surface_destroy (priv -> current_surface );
451+ }
452+ priv -> current_surface = surface ;
390453 }
391454 g_object_unref (icon_pixbuf );
392455 }
393456
394457 gtk_label_set_text (GTK_LABEL (priv -> message_label ), _ ("(Folder)" ));
395- gtk_widget_show (priv -> image );
458+ gtk_widget_show (priv -> drawing_area );
459+ gtk_widget_queue_draw (priv -> drawing_area );
396460 gtk_widget_show (priv -> message_label );
397461 } else {
398462 /* Non-image file: show file icon */
@@ -404,15 +468,18 @@ nemo_preview_image_set_file (NemoPreviewImage *widget,
404468 if (icon_pixbuf != NULL ) {
405469 surface = gdk_cairo_surface_create_from_pixbuf (icon_pixbuf , ui_scale , NULL );
406470 if (surface != NULL ) {
407- gtk_image_set_from_surface (GTK_IMAGE (priv -> image ), surface );
408- cairo_surface_destroy (surface );
471+ if (priv -> current_surface != NULL ) {
472+ cairo_surface_destroy (priv -> current_surface );
473+ }
474+ priv -> current_surface = surface ;
409475 }
410476 g_object_unref (icon_pixbuf );
411477 }
412478
413479 gtk_label_set_text (GTK_LABEL (priv -> message_label ),
414480 _ ("(Not an image file)" ));
415- gtk_widget_show (priv -> image );
481+ gtk_widget_show (priv -> drawing_area );
482+ gtk_widget_queue_draw (priv -> drawing_area );
416483 gtk_widget_show (priv -> message_label );
417484 }
418485 }
@@ -438,13 +505,17 @@ nemo_preview_image_clear (NemoPreviewImage *widget)
438505 priv -> current_pixbuf = NULL ;
439506 }
440507
508+ if (priv -> current_surface != NULL ) {
509+ cairo_surface_destroy (priv -> current_surface );
510+ priv -> current_surface = NULL ;
511+ }
512+
441513 if (priv -> file != NULL ) {
442514 nemo_file_unref (priv -> file );
443515 priv -> file = NULL ;
444516 }
445517
446- gtk_image_clear (GTK_IMAGE (priv -> image ));
447- gtk_widget_hide (priv -> image );
518+ gtk_widget_hide (priv -> drawing_area );
448519 gtk_widget_hide (priv -> message_label );
449520 priv -> current_width = 0 ;
450521 priv -> current_height = 0 ;
0 commit comments