Compare commits
2 Commits
bafad1a67e
...
8c89759325
Author | SHA1 | Date | |
---|---|---|---|
8c89759325 | |||
dd8461cebf |
32
fastiv-io.c
32
fastiv-io.c
@ -994,8 +994,14 @@ open_gdkpixbuf(const gchar *data, gsize len, GError **error)
|
||||
cairo_surface_t *surface =
|
||||
gdk_cairo_surface_create_from_pixbuf(pixbuf, 1, NULL);
|
||||
|
||||
// TODO(p): Also pass the pre-decoded Exif "orientation" option,
|
||||
// which is an ASCII digit from 1 to 8.
|
||||
const char *orientation = gdk_pixbuf_get_option(pixbuf, "orientation");
|
||||
if (orientation && strlen(orientation) == 1) {
|
||||
int n = *orientation - '0';
|
||||
if (n >= 1 && n <= 8)
|
||||
cairo_surface_set_user_data(surface, &fastiv_io_key_orientation,
|
||||
(void *) (uintptr_t) n, NULL);
|
||||
}
|
||||
|
||||
const char *icc_profile = gdk_pixbuf_get_option(pixbuf, "icc-profile");
|
||||
if (icc_profile) {
|
||||
gsize out_len = 0;
|
||||
@ -1014,6 +1020,7 @@ open_gdkpixbuf(const gchar *data, gsize len, GError **error)
|
||||
#endif // HAVE_GDKPIXBUF ------------------------------------------------------
|
||||
|
||||
cairo_user_data_key_t fastiv_io_key_exif;
|
||||
cairo_user_data_key_t fastiv_io_key_orientation;
|
||||
cairo_user_data_key_t fastiv_io_key_icc;
|
||||
|
||||
cairo_user_data_key_t fastiv_io_key_frame_next;
|
||||
@ -1120,6 +1127,19 @@ fastiv_io_open_from_data(const char *data, size_t len, const gchar *path,
|
||||
|
||||
set_error(error, "unsupported file type");
|
||||
}
|
||||
|
||||
// gdk-pixbuf only gives out this single field--cater to its limitations,
|
||||
// since we'd really like to have it.
|
||||
GBytes *exif = NULL;
|
||||
gsize exif_len = 0;
|
||||
gconstpointer exif_data = NULL;
|
||||
if (surface &&
|
||||
(exif = cairo_surface_get_user_data(surface, &fastiv_io_key_exif)) &&
|
||||
(exif_data = g_bytes_get_data(exif, &exif_len))) {
|
||||
cairo_surface_set_user_data(surface, &fastiv_io_key_orientation,
|
||||
(void *) (uintptr_t) fastiv_io_exif_orientation(
|
||||
exif_data, exif_len), NULL);
|
||||
}
|
||||
return surface;
|
||||
}
|
||||
|
||||
@ -1160,11 +1180,11 @@ fastiv_io_exif_orientation(const guint8 *tiff, gsize len)
|
||||
SBYTE, UNDEFINED, SSHORT, SLONG, SRATIONAL, FLOAT, DOUBLE };
|
||||
enum { Orientation = 274 };
|
||||
for (const guint8 *p = ifd0 + 2; fields-- && p + 12 <= end; p += 12) {
|
||||
uint16_t tag = u16(p), type = u16(p + 2);
|
||||
uint32_t count = u32(p + 4), value = u32(p + 8);
|
||||
uint16_t tag = u16(p), type = u16(p + 2), value16 = u16(p + 8);
|
||||
uint32_t count = u32(p + 4);
|
||||
if (tag == Orientation && type == SHORT && count == 1 &&
|
||||
value >= 1 && value <= 8)
|
||||
return value;
|
||||
value16 >= 1 && value16 <= 8)
|
||||
return value16;
|
||||
}
|
||||
return FastivIoOrientationUnknown;
|
||||
}
|
||||
|
@ -29,6 +29,8 @@ char **fastiv_io_all_supported_media_types(void);
|
||||
|
||||
/// GBytes with plain Exif data.
|
||||
extern cairo_user_data_key_t fastiv_io_key_exif;
|
||||
/// FastivIoOrientation, as a uintptr_t.
|
||||
extern cairo_user_data_key_t fastiv_io_key_orientation;
|
||||
/// GBytes with plain ICC profile data.
|
||||
extern cairo_user_data_key_t fastiv_io_key_icc;
|
||||
|
||||
|
@ -31,7 +31,8 @@
|
||||
|
||||
struct _FastivView {
|
||||
GtkWidget parent_instance;
|
||||
cairo_surface_t *surface;
|
||||
cairo_surface_t *surface; ///< The loaded image (sequence)
|
||||
cairo_surface_t *frame; ///< Current frame within, unreferenced
|
||||
bool scale_to_fit;
|
||||
double scale;
|
||||
};
|
||||
@ -237,12 +238,12 @@ fastiv_view_draw(GtkWidget *widget, cairo_t *cr)
|
||||
|
||||
// FIXME: Recording surfaces do not work well with CAIRO_SURFACE_TYPE_XLIB,
|
||||
// we always get a shitty pixmap, where transparency contains junk.
|
||||
if (cairo_surface_get_type(self->surface) == CAIRO_SURFACE_TYPE_RECORDING) {
|
||||
if (cairo_surface_get_type(self->frame) == CAIRO_SURFACE_TYPE_RECORDING) {
|
||||
cairo_surface_t *image =
|
||||
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h);
|
||||
cairo_t *tcr = cairo_create(image);
|
||||
cairo_scale(tcr, self->scale, self->scale);
|
||||
cairo_set_source_surface(tcr, self->surface, 0, 0);
|
||||
cairo_set_source_surface(tcr, self->frame, 0, 0);
|
||||
cairo_paint(tcr);
|
||||
cairo_destroy(tcr);
|
||||
|
||||
@ -259,7 +260,7 @@ fastiv_view_draw(GtkWidget *widget, cairo_t *cr)
|
||||
|
||||
cairo_scale(cr, self->scale, self->scale);
|
||||
cairo_set_source_surface(
|
||||
cr, self->surface, x / self->scale, y / self->scale);
|
||||
cr, self->frame, x / self->scale, y / self->scale);
|
||||
|
||||
cairo_pattern_t *pattern = cairo_get_source(cr);
|
||||
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
|
||||
@ -339,6 +340,8 @@ fastiv_view_key_press_event(GtkWidget *widget, GdkEventKey *event)
|
||||
FastivView *self = FASTIV_VIEW(widget);
|
||||
if (event->state & ~GDK_SHIFT_MASK & gtk_accelerator_get_default_mod_mask())
|
||||
return FALSE;
|
||||
if (!self->surface)
|
||||
return FALSE;
|
||||
|
||||
switch (event->keyval) {
|
||||
case GDK_KEY_1:
|
||||
@ -349,6 +352,13 @@ fastiv_view_key_press_event(GtkWidget *widget, GdkEventKey *event)
|
||||
return set_scale(self, self->scale / SCALE_STEP);
|
||||
case GDK_KEY_F:
|
||||
return set_scale_to_fit(self, !self->scale_to_fit);
|
||||
case GDK_KEY_greater: {
|
||||
if (!(self->frame = cairo_surface_get_user_data(
|
||||
self->frame, &fastiv_io_key_frame_next)))
|
||||
self->frame = self->surface;
|
||||
gtk_widget_queue_draw(widget);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@ -404,7 +414,7 @@ fastiv_view_open(FastivView *self, const gchar *path, GError **error)
|
||||
if (self->surface)
|
||||
cairo_surface_destroy(self->surface);
|
||||
|
||||
self->surface = surface;
|
||||
self->frame = self->surface = surface;
|
||||
set_scale_to_fit(self, true);
|
||||
return TRUE;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user