Skip to content

Instantly share code, notes, and snippets.

@feliwir
Created March 29, 2022 19:32
Show Gist options
  • Save feliwir/501879186d5c9b3a65ccfdfaee302e88 to your computer and use it in GitHub Desktop.
Save feliwir/501879186d5c9b3a65ccfdfaee302e88 to your computer and use it in GitHub Desktop.
/*
* Copyright (C) 2022 Stephan Vedder <[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <https://www.gnu.org/licenses/>.
*/
#include "voyager-image.h"
#include <gexiv2/gexiv2.h>
#include <graphene.h>
#include <gtk/gtk.h>
struct _VoyagerImage
{
GObject parent_instance;
GExiv2Orientation orientation;
GdkTexture *texture;
GExiv2Metadata *metadata;
};
static void
voyager_image_snapshot (GdkPaintable *paintable, GdkSnapshot *snapshot, double width, double height)
{
VoyagerImage *image = VOYAGER_IMAGE (paintable);
// TODO: use rotation
gtk_snapshot_save (snapshot);
int tex_width = width;
int tex_height = height;
switch (image->orientation)
{
case GEXIV2_ORIENTATION_ROT_90_HFLIP:
case GEXIV2_ORIENTATION_ROT_90:
case GEXIV2_ORIENTATION_ROT_90_VFLIP:
tex_width = height;
tex_height = width;
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (height / 2, width / 2));
gtk_snapshot_rotate (snapshot, 90);
break;
case GEXIV2_ORIENTATION_ROT_270:
tex_width = height;
tex_height = width;
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (height / 2, width / 2));
gtk_snapshot_rotate (snapshot, 270);
break;
default:
break;
}
gtk_snapshot_append_texture (snapshot, image->texture,
&GRAPHENE_RECT_INIT (0, 0, tex_width, tex_height));
gtk_snapshot_restore (snapshot);
}
static GdkPaintableFlags
voyager_image_get_flags (GdkPaintable *paintable)
{
return GDK_PAINTABLE_STATIC_CONTENTS | GDK_PAINTABLE_STATIC_SIZE;
}
static int
voyager_image_get_intrinsic_width (GdkPaintable *paintable)
{
VoyagerImage *image = VOYAGER_IMAGE (paintable);
switch (image->orientation)
{
case GEXIV2_ORIENTATION_ROT_90_HFLIP:
case GEXIV2_ORIENTATION_ROT_90:
case GEXIV2_ORIENTATION_ROT_90_VFLIP:
case GEXIV2_ORIENTATION_ROT_270:
return gdk_texture_get_height (image->texture);
default:
return gdk_texture_get_width (image->texture);
}
}
static int
voyager_image_get_intrinsic_height (GdkPaintable *paintable)
{
VoyagerImage *image = VOYAGER_IMAGE (paintable);
switch (image->orientation)
{
case GEXIV2_ORIENTATION_ROT_90_HFLIP:
case GEXIV2_ORIENTATION_ROT_90:
case GEXIV2_ORIENTATION_ROT_90_VFLIP:
case GEXIV2_ORIENTATION_ROT_270:
return gdk_texture_get_width (image->texture);
default:
return gdk_texture_get_height (image->texture);
}
}
static void
voyager_image_paintable_init (GdkPaintableInterface *iface)
{
iface->snapshot = voyager_image_snapshot;
iface->get_flags = voyager_image_get_flags;
iface->get_intrinsic_width = voyager_image_get_intrinsic_width;
iface->get_intrinsic_height = voyager_image_get_intrinsic_height;
}
/* When defining the GType, we need to implement the GdkPaintable interface */
G_DEFINE_TYPE_WITH_CODE (VoyagerImage,
voyager_image,
G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE, voyager_image_paintable_init))
static void
voyager_image_class_init (VoyagerImageClass *klass)
{
}
static void
voyager_image_init (VoyagerImage *image)
{
image->orientation = GEXIV2_ORIENTATION_UNSPECIFIED;
image->metadata = gexiv2_metadata_new ();
}
VoyagerImage *
voyager_image_new_from_file (GFile *file)
{
VoyagerImage *image;
image = g_object_new (VOYAGER_TYPE_IMAGE, NULL);
voyager_image_set_from_file (image, file);
return image;
}
void
voyager_image_set_from_file (VoyagerImage *image, GFile *file)
{
g_return_if_fail (VOYAGER_IS_IMAGE (image));
g_object_freeze_notify (G_OBJECT (image));
if (file == NULL)
{
g_object_thaw_notify (G_OBJECT (image));
return;
}
GError *error = NULL;
gchar *filepath = g_file_get_path (file);
if (! gexiv2_metadata_open_path (image->metadata, filepath, &error))
{
g_object_thaw_notify (G_OBJECT (image));
return;
}
image->orientation = gexiv2_metadata_try_get_orientation (image->metadata, &error);
GdkTexture *texture = gdk_texture_new_from_file (file, &error);
if (texture == NULL)
{
g_object_thaw_notify (G_OBJECT (texture));
return;
}
voyager_image_set_from_texture (image, texture);
g_object_unref (texture);
g_object_thaw_notify (G_OBJECT (image));
}
void
voyager_image_set_from_texture (VoyagerImage *image, GdkTexture *texture)
{
g_return_if_fail (VOYAGER_IS_IMAGE (image));
g_return_if_fail (texture == NULL || GDK_IS_TEXTURE (texture));
g_object_freeze_notify (G_OBJECT (image));
if (texture)
g_object_ref (texture);
if (texture)
{
image->texture = texture;
}
g_object_thaw_notify (G_OBJECT (image));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment