/* SinglePhotoPage.c generated by valac 0.56.19, the Vala compiler
 * generated from SinglePhotoPage.vala, do not modify */

/*
* Copyright (c) 2018 elementary, Inc. (https://elementary.io),
*               2009-2013 Yorba Foundation
*
* This program 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 program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*/

#include "io.elementary.photos.h"
#include <glib.h>
#include <cairo-gobject.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include <string.h>
#include <glib-object.h>
#include <stdlib.h>
#include <float.h>
#include <math.h>
#include <pango/pango.h>
#include <pango/pangocairo.h>
#include <granite.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif

enum  {
	SINGLE_PHOTO_PAGE_0_PROPERTY,
	SINGLE_PHOTO_PAGE_SCALE_UP_TO_VIEWPORT_PROPERTY,
	SINGLE_PHOTO_PAGE_NUM_PROPERTIES
};
static GParamSpec* single_photo_page_properties[SINGLE_PHOTO_PAGE_NUM_PROPERTIES];
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _transition_clock_unref0(var) ((var == NULL) ? NULL : (var = (transition_clock_unref (var), NULL)))
#define _cairo_surface_destroy0(var) ((var == NULL) ? NULL : (var = (cairo_surface_destroy (var), NULL)))
#define _cairo_destroy0(var) ((var == NULL) ? NULL : (var = (cairo_destroy (var), NULL)))
#define _transition_effects_manager_unref0(var) ((var == NULL) ? NULL : (var = (transition_effects_manager_unref (var), NULL)))
#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);

struct _SinglePhotoPagePrivate {
	TransitionClock* transition_clock;
	gint transition_duration_msec;
	cairo_surface_t* pixmap;
	cairo_t* pixmap_ctx;
	cairo_t* text_ctx;
	Dimensions pixmap_dim;
	GdkPixbuf* unscaled;
	Dimensions max_dim;
	GdkPixbuf* scaled;
	GdkPixbuf* old_scaled;
	GdkRectangle scaled_pos;
	ZoomState static_zoom_state;
	gboolean zoom_high_quality;
	ZoomState saved_zoom_state;
	gboolean has_saved_zoom_state;
	guint32 last_nav_key;
	gboolean _scale_up_to_viewport;
};

static gint SinglePhotoPage_private_offset;
static gpointer single_photo_page_parent_class = NULL;

static void single_photo_page_cancel_transition (SinglePhotoPage* self);
static void single_photo_page_render_zoomed_to_pixmap (SinglePhotoPage* self,
                                                ZoomState* zoom_state);
static gboolean single_photo_page_real_is_zoom_supported (SinglePhotoPage* self);
static void single_photo_page_real_cancel_zoom (SinglePhotoPage* self);
static void single_photo_page_real_save_zoom_state (SinglePhotoPage* self);
static void single_photo_page_real_restore_zoom_state (SinglePhotoPage* self);
static ZoomBuffer* single_photo_page_real_get_zoom_buffer (SinglePhotoPage* self);
static void single_photo_page_real_switched_to (Page* base);
static void single_photo_page_real_set_container (Page* base,
                                           GtkWindow* container);
static void single_photo_page_invalidate_all (SinglePhotoPage* self);
VALA_EXTERN gboolean coord_in_rectangle (gint x,
                             gint y,
                             GdkRectangle* rect);
static void single_photo_page_on_viewport_resize (SinglePhotoPage* self);
static void single_photo_page_internal_repaint (SinglePhotoPage* self,
                                         gboolean fast,
                                         Direction* direction);
static void single_photo_page_real_on_resize_finished (Page* base,
                                                GdkRectangle* rect);
static gboolean single_photo_page_on_canvas_exposed (SinglePhotoPage* self,
                                              cairo_t* exposed_ctx);
static void single_photo_page_real_new_surface (SinglePhotoPage* self,
                                         cairo_t* ctx,
                                         Dimensions* ctx_dim);
static void single_photo_page_real_updated_pixbuf (SinglePhotoPage* self,
                                            GdkPixbuf* pixbuf,
                                            SinglePhotoPageUpdateReason reason,
                                            Dimensions* old_dim);
static void single_photo_page_real_paint (SinglePhotoPage* self,
                                   cairo_t* ctx,
                                   Dimensions* ctx_dim);
static void single_photo_page_repaint_pixmap (SinglePhotoPage* self);
static void single_photo_page_init_pixmap (SinglePhotoPage* self,
                                    gint width,
                                    gint height);
VALA_EXTERN GdkPixbuf* resize_pixbuf (GdkPixbuf* pixbuf,
                          Dimensions* resized,
                          GdkInterpType interp);
VALA_EXTERN void parse_color (const gchar* spec,
                  GdkRGBA* result);
static void _single_photo_page_repaint_pixmap_transition_clock_repaint_callback (gpointer self);
VALA_EXTERN void set_source_color_from_string (cairo_t* ctx,
                                   const gchar* spec);
static gboolean single_photo_page_real_on_context_keypress (Page* base);
static void single_photo_page_real_on_previous_photo (SinglePhotoPage* self);
static void single_photo_page_real_on_next_photo (SinglePhotoPage* self);
static gboolean single_photo_page_real_key_press_event (GtkWidget* base,
                                                 GdkEventKey* event);
static GObject * single_photo_page_constructor (GType type,
                                         guint n_construct_properties,
                                         GObjectConstructParam * construct_properties);
static void _single_photo_page_on_viewport_resize_gtk_widget_size_allocate (GtkWidget* _sender,
                                                                     GtkAllocation* allocation,
                                                                     gpointer self);
static gboolean _single_photo_page_on_canvas_exposed_gtk_widget_draw (GtkWidget* _sender,
                                                               cairo_t* cr,
                                                               gpointer self);
static void single_photo_page_finalize (GObject * obj);
static GType single_photo_page_get_type_once (void);
static void _vala_single_photo_page_get_property (GObject * object,
                                           guint property_id,
                                           GValue * value,
                                           GParamSpec * pspec);
static void _vala_single_photo_page_set_property (GObject * object,
                                           guint property_id,
                                           const GValue * value,
                                           GParamSpec * pspec);
static inline gpointer _vala_memdup2 (gconstpointer mem,
                        gsize byte_size);

static inline gpointer
single_photo_page_get_instance_private (SinglePhotoPage* self)
{
	return G_STRUCT_MEMBER_P (self, SinglePhotoPage_private_offset);
}

static GType
single_photo_page_update_reason_get_type_once (void)
{
	static const GEnumValue values[] = {{SINGLE_PHOTO_PAGE_UPDATE_REASON_NEW_PIXBUF, "SINGLE_PHOTO_PAGE_UPDATE_REASON_NEW_PIXBUF", "new-pixbuf"}, {SINGLE_PHOTO_PAGE_UPDATE_REASON_QUALITY_IMPROVEMENT, "SINGLE_PHOTO_PAGE_UPDATE_REASON_QUALITY_IMPROVEMENT", "quality-improvement"}, {SINGLE_PHOTO_PAGE_UPDATE_REASON_RESIZED_CANVAS, "SINGLE_PHOTO_PAGE_UPDATE_REASON_RESIZED_CANVAS", "resized-canvas"}, {0, NULL, NULL}};
	GType single_photo_page_update_reason_type_id;
	single_photo_page_update_reason_type_id = g_enum_register_static ("SinglePhotoPageUpdateReason", values);
	return single_photo_page_update_reason_type_id;
}

GType
single_photo_page_update_reason_get_type (void)
{
	static volatile gsize single_photo_page_update_reason_type_id__once = 0;
	if (g_once_init_enter (&single_photo_page_update_reason_type_id__once)) {
		GType single_photo_page_update_reason_type_id;
		single_photo_page_update_reason_type_id = single_photo_page_update_reason_get_type_once ();
		g_once_init_leave (&single_photo_page_update_reason_type_id__once, single_photo_page_update_reason_type_id);
	}
	return single_photo_page_update_reason_type_id__once;
}

SinglePhotoPage*
single_photo_page_construct (GType object_type,
                             const gchar* page_name,
                             gboolean scale_up_to_viewport)
{
	SinglePhotoPage * self = NULL;
	g_return_val_if_fail (page_name != NULL, NULL);
	self = (SinglePhotoPage*) g_object_new (object_type, "page-name", page_name, "scale-up-to-viewport", scale_up_to_viewport, NULL);
	return self;
}

gboolean
single_photo_page_is_transition_in_progress (SinglePhotoPage* self)
{
	TransitionClock* _tmp0_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->priv->transition_clock;
	result = transition_clock_is_in_progress (_tmp0_);
	return result;
}

static void
single_photo_page_cancel_transition (SinglePhotoPage* self)
{
	TransitionClock* _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->transition_clock;
	if (transition_clock_is_in_progress (_tmp0_)) {
		TransitionClock* _tmp1_;
		_tmp1_ = self->priv->transition_clock;
		transition_clock_cancel (_tmp1_);
	}
}

void
single_photo_page_set_transition (SinglePhotoPage* self,
                                  const gchar* effect_id,
                                  gint duration_msec)
{
	TransitionEffectsManager* _tmp0_;
	TransitionEffectsManager* _tmp1_;
	TransitionClock* _tmp2_;
	TransitionClock* _tmp3_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (effect_id != NULL);
	single_photo_page_cancel_transition (self);
	_tmp0_ = transition_effects_manager_get_instance ();
	_tmp1_ = _tmp0_;
	_tmp2_ = transition_effects_manager_create_transition_clock (_tmp1_, effect_id);
	_transition_clock_unref0 (self->priv->transition_clock);
	self->priv->transition_clock = _tmp2_;
	_transition_effects_manager_unref0 (_tmp1_);
	_tmp3_ = self->priv->transition_clock;
	if (_tmp3_ == NULL) {
		TransitionEffectsManager* _tmp4_;
		TransitionEffectsManager* _tmp5_;
		TransitionClock* _tmp6_;
		_tmp4_ = transition_effects_manager_get_instance ();
		_tmp5_ = _tmp4_;
		_tmp6_ = transition_effects_manager_create_null_transition_clock (_tmp5_);
		_transition_clock_unref0 (self->priv->transition_clock);
		self->priv->transition_clock = _tmp6_;
		_transition_effects_manager_unref0 (_tmp5_);
	}
	self->priv->transition_duration_msec = duration_msec;
}

static void
single_photo_page_render_zoomed_to_pixmap (SinglePhotoPage* self,
                                           ZoomState* zoom_state)
{
	GdkRectangle view_rect = {0};
	GdkRectangle _tmp0_ = {0};
	GdkPixbuf* zoomed = NULL;
	ZoomBuffer* _tmp1_;
	ZoomBuffer* _tmp2_;
	gboolean _tmp3_;
	GdkPixbuf* _tmp26_;
	gint draw_x = 0;
	Dimensions _tmp27_;
	GdkRectangle _tmp28_;
	gint draw_y = 0;
	Dimensions _tmp29_;
	GdkRectangle _tmp30_;
	cairo_t* _tmp31_;
	GdkPixbuf* _tmp32_;
	cairo_t* _tmp33_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (zoom_state != NULL);
	_vala_assert (single_photo_page_is_zoom_supported (self), "is_zoom_supported ()");
	zoom_state_get_viewing_rectangle_wrt_content (zoom_state, &_tmp0_);
	view_rect = _tmp0_;
	_tmp1_ = single_photo_page_get_zoom_buffer (self);
	_tmp2_ = _tmp1_;
	_tmp3_ = _tmp2_ != NULL;
	_g_object_unref0 (_tmp2_);
	if (_tmp3_) {
		GdkPixbuf* _tmp4_ = NULL;
		GdkPixbuf* _tmp13_;
		if (self->priv->zoom_high_quality) {
			ZoomBuffer* _tmp5_;
			ZoomBuffer* _tmp6_;
			ZoomState _tmp7_;
			GdkPixbuf* _tmp8_;
			_tmp5_ = single_photo_page_get_zoom_buffer (self);
			_tmp6_ = _tmp5_;
			_tmp7_ = *zoom_state;
			_tmp8_ = zoom_buffer_get_zoomed_image (_tmp6_, &_tmp7_);
			_g_object_unref0 (_tmp4_);
			_tmp4_ = _tmp8_;
			_g_object_unref0 (_tmp6_);
		} else {
			ZoomBuffer* _tmp9_;
			ZoomBuffer* _tmp10_;
			ZoomState _tmp11_;
			GdkPixbuf* _tmp12_;
			_tmp9_ = single_photo_page_get_zoom_buffer (self);
			_tmp10_ = _tmp9_;
			_tmp11_ = *zoom_state;
			_tmp12_ = zoom_buffer_get_zoom_preview_image (_tmp10_, &_tmp11_);
			_g_object_unref0 (_tmp4_);
			_tmp4_ = _tmp12_;
			_g_object_unref0 (_tmp10_);
		}
		_tmp13_ = _tmp4_;
		_tmp4_ = NULL;
		_g_object_unref0 (zoomed);
		zoomed = _tmp13_;
		_g_object_unref0 (_tmp4_);
	} else {
		GdkRectangle view_rect_proj = {0};
		GdkPixbuf* _tmp14_;
		GdkRectangle _tmp15_ = {0};
		GdkPixbuf* proj_subpixbuf = NULL;
		GdkPixbuf* _tmp16_;
		GdkRectangle _tmp17_;
		GdkRectangle _tmp18_;
		GdkRectangle _tmp19_;
		GdkRectangle _tmp20_;
		GdkPixbuf* _tmp21_;
		GdkPixbuf* _tmp22_;
		GdkRectangle _tmp23_;
		GdkRectangle _tmp24_;
		GdkPixbuf* _tmp25_;
		_tmp14_ = self->priv->unscaled;
		zoom_state_get_viewing_rectangle_projection (zoom_state, _tmp14_, &_tmp15_);
		view_rect_proj = _tmp15_;
		_tmp16_ = self->priv->unscaled;
		_tmp17_ = view_rect_proj;
		_tmp18_ = view_rect_proj;
		_tmp19_ = view_rect_proj;
		_tmp20_ = view_rect_proj;
		_tmp21_ = gdk_pixbuf_new_subpixbuf (_tmp16_, _tmp17_.x, _tmp18_.y, _tmp19_.width, _tmp20_.height);
		proj_subpixbuf = _tmp21_;
		_tmp22_ = proj_subpixbuf;
		_tmp23_ = view_rect;
		_tmp24_ = view_rect;
		_tmp25_ = gdk_pixbuf_scale_simple (_tmp22_, _tmp23_.width, _tmp24_.height, GDK_INTERP_BILINEAR);
		_g_object_unref0 (zoomed);
		zoomed = _tmp25_;
		_g_object_unref0 (proj_subpixbuf);
	}
	_tmp26_ = zoomed;
	if (_tmp26_ == NULL) {
		_g_object_unref0 (zoomed);
		return;
	}
	_tmp27_ = self->priv->pixmap_dim;
	_tmp28_ = view_rect;
	draw_x = (_tmp27_.width - _tmp28_.width) / 2;
	draw_x = CLAMP (draw_x, 0, G_MAXINT);
	_tmp29_ = self->priv->pixmap_dim;
	_tmp30_ = view_rect;
	draw_y = (_tmp29_.height - _tmp30_.height) / 2;
	draw_y = CLAMP (draw_y, 0, G_MAXINT);
	_tmp31_ = self->priv->pixmap_ctx;
	_tmp32_ = zoomed;
	gdk_cairo_set_source_pixbuf (_tmp31_, _tmp32_, (gdouble) draw_x, (gdouble) draw_y);
	_tmp33_ = self->priv->pixmap_ctx;
	cairo_paint (_tmp33_);
	_g_object_unref0 (zoomed);
}

void
single_photo_page_on_interactive_pan (SinglePhotoPage* self,
                                      ZoomState* interactive_zoom_state)
{
	cairo_t* canvas_ctx = NULL;
	GtkDrawingArea* _tmp0_;
	GdkWindow* _tmp1_;
	cairo_t* _tmp2_;
	GtkDrawingArea* _tmp3_;
	GtkStyleContext* _tmp4_;
	cairo_t* _tmp5_;
	Dimensions _tmp6_;
	Dimensions _tmp7_;
	gboolean old_quality_setting = FALSE;
	ZoomState _tmp8_;
	gint _tmp9_;
	gint _tmp10_;
	gint _tmp11_;
	gint _tmp12_;
	cairo_surface_t* _tmp13_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (interactive_zoom_state != NULL);
	_vala_assert (single_photo_page_is_zoom_supported (self), "is_zoom_supported ()");
	_tmp0_ = self->canvas;
	_tmp1_ = gtk_widget_get_window ((GtkWidget*) _tmp0_);
	_tmp2_ = gdk_cairo_create (_tmp1_);
	canvas_ctx = _tmp2_;
	_tmp3_ = self->canvas;
	_tmp4_ = gtk_widget_get_style_context ((GtkWidget*) _tmp3_);
	_tmp5_ = self->priv->pixmap_ctx;
	_tmp6_ = self->priv->pixmap_dim;
	_tmp7_ = self->priv->pixmap_dim;
	gtk_render_background (_tmp4_, _tmp5_, (gdouble) 0, (gdouble) 0, (gdouble) _tmp6_.width, (gdouble) _tmp7_.height);
	old_quality_setting = self->priv->zoom_high_quality;
	self->priv->zoom_high_quality = TRUE;
	_tmp8_ = *interactive_zoom_state;
	single_photo_page_render_zoomed_to_pixmap (self, &_tmp8_);
	self->priv->zoom_high_quality = old_quality_setting;
	cairo_save (canvas_ctx);
	_tmp9_ = gtk_widget_get_scale_factor ((GtkWidget*) self);
	_tmp10_ = _tmp9_;
	_tmp11_ = gtk_widget_get_scale_factor ((GtkWidget*) self);
	_tmp12_ = _tmp11_;
	cairo_scale (canvas_ctx, (gdouble) (1.0f / _tmp10_), (gdouble) (1.0f / _tmp12_));
	_tmp13_ = self->priv->pixmap;
	cairo_set_source_surface (canvas_ctx, _tmp13_, (gdouble) 0, (gdouble) 0);
	cairo_paint (canvas_ctx);
	cairo_restore (canvas_ctx);
	_cairo_destroy0 (canvas_ctx);
}

static gboolean
single_photo_page_real_is_zoom_supported (SinglePhotoPage* self)
{
	gboolean result;
	result = FALSE;
	return result;
}

gboolean
single_photo_page_is_zoom_supported (SinglePhotoPage* self)
{
	SinglePhotoPageClass* _klass_;
	g_return_val_if_fail (self != NULL, FALSE);
	_klass_ = SINGLE_PHOTO_PAGE_GET_CLASS (self);
	if (_klass_->is_zoom_supported) {
		return _klass_->is_zoom_supported (self);
	}
	return FALSE;
}

static void
single_photo_page_real_cancel_zoom (SinglePhotoPage* self)
{
	cairo_surface_t* _tmp0_;
	_tmp0_ = self->priv->pixmap;
	if (_tmp0_ != NULL) {
		GtkDrawingArea* _tmp1_;
		GtkStyleContext* _tmp2_;
		cairo_t* _tmp3_;
		Dimensions _tmp4_;
		Dimensions _tmp5_;
		_tmp1_ = self->canvas;
		_tmp2_ = gtk_widget_get_style_context ((GtkWidget*) _tmp1_);
		_tmp3_ = self->priv->pixmap_ctx;
		_tmp4_ = self->priv->pixmap_dim;
		_tmp5_ = self->priv->pixmap_dim;
		gtk_render_background (_tmp2_, _tmp3_, (gdouble) 0, (gdouble) 0, (gdouble) _tmp4_.width, (gdouble) _tmp5_.height);
	}
}

void
single_photo_page_cancel_zoom (SinglePhotoPage* self)
{
	SinglePhotoPageClass* _klass_;
	g_return_if_fail (self != NULL);
	_klass_ = SINGLE_PHOTO_PAGE_GET_CLASS (self);
	if (_klass_->cancel_zoom) {
		_klass_->cancel_zoom (self);
	}
}

static void
single_photo_page_real_save_zoom_state (SinglePhotoPage* self)
{
	ZoomState _tmp0_;
	_tmp0_ = self->priv->static_zoom_state;
	self->priv->saved_zoom_state = _tmp0_;
	self->priv->has_saved_zoom_state = TRUE;
}

void
single_photo_page_save_zoom_state (SinglePhotoPage* self)
{
	SinglePhotoPageClass* _klass_;
	g_return_if_fail (self != NULL);
	_klass_ = SINGLE_PHOTO_PAGE_GET_CLASS (self);
	if (_klass_->save_zoom_state) {
		_klass_->save_zoom_state (self);
	}
}

static void
single_photo_page_real_restore_zoom_state (SinglePhotoPage* self)
{
	ZoomState _tmp0_;
	if (!self->priv->has_saved_zoom_state) {
		return;
	}
	_tmp0_ = self->priv->saved_zoom_state;
	self->priv->static_zoom_state = _tmp0_;
	single_photo_page_repaint (self, NULL);
	self->priv->has_saved_zoom_state = FALSE;
}

void
single_photo_page_restore_zoom_state (SinglePhotoPage* self)
{
	SinglePhotoPageClass* _klass_;
	g_return_if_fail (self != NULL);
	_klass_ = SINGLE_PHOTO_PAGE_GET_CLASS (self);
	if (_klass_->restore_zoom_state) {
		_klass_->restore_zoom_state (self);
	}
}

static ZoomBuffer*
single_photo_page_real_get_zoom_buffer (SinglePhotoPage* self)
{
	ZoomBuffer* result;
	result = NULL;
	return result;
}

ZoomBuffer*
single_photo_page_get_zoom_buffer (SinglePhotoPage* self)
{
	SinglePhotoPageClass* _klass_;
	g_return_val_if_fail (self != NULL, NULL);
	_klass_ = SINGLE_PHOTO_PAGE_GET_CLASS (self);
	if (_klass_->get_zoom_buffer) {
		return _klass_->get_zoom_buffer (self);
	}
	return NULL;
}

void
single_photo_page_get_saved_zoom_state (SinglePhotoPage* self,
                                        ZoomState* result)
{
	ZoomState _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->saved_zoom_state;
	*result = _tmp0_;
	return;
}

void
single_photo_page_set_zoom_state (SinglePhotoPage* self,
                                  ZoomState* zoom_state)
{
	ZoomState _tmp0_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (zoom_state != NULL);
	_vala_assert (single_photo_page_is_zoom_supported (self), "is_zoom_supported ()");
	_tmp0_ = *zoom_state;
	self->priv->static_zoom_state = _tmp0_;
}

void
single_photo_page_get_zoom_state (SinglePhotoPage* self,
                                  ZoomState* result)
{
	ZoomState _tmp0_;
	g_return_if_fail (self != NULL);
	_vala_assert (single_photo_page_is_zoom_supported (self), "is_zoom_supported ()");
	_tmp0_ = self->priv->static_zoom_state;
	*result = _tmp0_;
	return;
}

static void
single_photo_page_real_switched_to (Page* base)
{
	SinglePhotoPage * self;
	GdkPixbuf* _tmp0_;
	self = (SinglePhotoPage*) base;
	PAGE_CLASS (single_photo_page_parent_class)->switched_to (G_TYPE_CHECK_INSTANCE_CAST (self, TYPE_PAGE, Page));
	_tmp0_ = self->priv->unscaled;
	if (_tmp0_ != NULL) {
		single_photo_page_repaint (self, NULL);
	}
}

static void
single_photo_page_real_set_container (Page* base,
                                      GtkWindow* container)
{
	SinglePhotoPage * self;
	self = (SinglePhotoPage*) base;
	g_return_if_fail (container != NULL);
	PAGE_CLASS (single_photo_page_parent_class)->set_container (G_TYPE_CHECK_INSTANCE_CAST (self, TYPE_PAGE, Page), container);
	if (IS_FULLSCREEN_WINDOW (container)) {
		gtk_scrolled_window_set_policy ((GtkScrolledWindow*) self, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
	}
}

static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}

void
single_photo_page_set_pixbuf (SinglePhotoPage* self,
                              GdkPixbuf* unscaled,
                              Dimensions* max_dim,
                              Direction* direction)
{
	Dimensions _tmp0_;
	Dimensions _tmp1_;
	GdkPoint _tmp2_ = {0};
	GdkPixbuf* _tmp3_;
	Dimensions _tmp4_;
	GdkPixbuf* _tmp5_;
	GdkPixbuf* _tmp6_;
	GtkDrawingArea* _tmp7_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (unscaled != NULL);
	g_return_if_fail (max_dim != NULL);
	_tmp0_ = *max_dim;
	_tmp1_ = self->priv->pixmap_dim;
	zoom_state_get_viewport_center (&self->priv->static_zoom_state, &_tmp2_);
	zoom_state_init (&self->priv->static_zoom_state, &_tmp0_, &_tmp1_, zoom_state_get_interpolation_factor (&self->priv->static_zoom_state), &_tmp2_);
	single_photo_page_cancel_transition (self);
	_tmp3_ = _g_object_ref0 (unscaled);
	_g_object_unref0 (self->priv->unscaled);
	self->priv->unscaled = _tmp3_;
	_tmp4_ = *max_dim;
	self->priv->max_dim = _tmp4_;
	_tmp5_ = self->priv->scaled;
	_tmp6_ = _g_object_ref0 (_tmp5_);
	_g_object_unref0 (self->priv->old_scaled);
	self->priv->old_scaled = _tmp6_;
	_g_object_unref0 (self->priv->scaled);
	self->priv->scaled = NULL;
	_tmp7_ = self->canvas;
	gtk_widget_realize ((GtkWidget*) _tmp7_);
	single_photo_page_repaint (self, direction);
}

void
single_photo_page_blank_display (SinglePhotoPage* self)
{
	GtkDrawingArea* _tmp0_;
	g_return_if_fail (self != NULL);
	_g_object_unref0 (self->priv->unscaled);
	self->priv->unscaled = NULL;
	dimensions_init (&self->priv->max_dim, 0, 0);
	_g_object_unref0 (self->priv->scaled);
	self->priv->scaled = NULL;
	_cairo_surface_destroy0 (self->priv->pixmap);
	self->priv->pixmap = NULL;
	_tmp0_ = self->canvas;
	gtk_widget_realize ((GtkWidget*) _tmp0_);
	single_photo_page_invalidate_all (self);
}

void
single_photo_page_get_surface_dim (SinglePhotoPage* self,
                                   Dimensions* result)
{
	Dimensions _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->pixmap_dim;
	*result = _tmp0_;
	return;
}

static gpointer
_cairo_reference0 (gpointer self)
{
	return self ? cairo_reference (self) : NULL;
}

cairo_t*
single_photo_page_get_cairo_context (SinglePhotoPage* self)
{
	cairo_t* _tmp0_;
	cairo_t* _tmp1_;
	cairo_t* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->pixmap_ctx;
	_tmp1_ = _cairo_reference0 (_tmp0_);
	result = _tmp1_;
	return result;
}

void
single_photo_page_paint_text (SinglePhotoPage* self,
                              PangoLayout* pango_layout,
                              gint x,
                              gint y)
{
	cairo_t* _tmp0_;
	cairo_t* _tmp1_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (pango_layout != NULL);
	_tmp0_ = self->priv->text_ctx;
	cairo_move_to (_tmp0_, (gdouble) x, (gdouble) y);
	_tmp1_ = self->priv->text_ctx;
	pango_cairo_show_layout (_tmp1_, pango_layout);
}

void
single_photo_page_get_canvas_scaling (SinglePhotoPage* self,
                                      Scaling* result)
{
	Scaling _tmp0_ = {0};
	GtkWindow* _tmp1_;
	GtkWindow* _tmp2_;
	gboolean _tmp3_;
	g_return_if_fail (self != NULL);
	_tmp1_ = page_get_container ((Page*) self);
	_tmp2_ = _tmp1_;
	_tmp3_ = IS_FULLSCREEN_WINDOW (_tmp2_);
	_g_object_unref0 (_tmp2_);
	if (_tmp3_) {
		AppWindow* _tmp4_;
		AppWindow* _tmp5_;
		gboolean _tmp6_;
		Scaling _tmp7_ = {0};
		_tmp4_ = app_window_get_instance ();
		_tmp5_ = _tmp4_;
		_tmp6_ = self->priv->_scale_up_to_viewport;
		scaling_for_screen ((GtkWindow*) _tmp5_, _tmp6_, &_tmp7_);
		_tmp0_ = _tmp7_;
		_g_object_unref0 (_tmp5_);
	} else {
		GtkViewport* _tmp8_;
		gboolean _tmp9_;
		Scaling _tmp10_ = {0};
		_tmp8_ = self->viewport;
		_tmp9_ = self->priv->_scale_up_to_viewport;
		scaling_for_widget ((GtkWidget*) _tmp8_, _tmp9_, &_tmp10_);
		_tmp0_ = _tmp10_;
	}
	*result = _tmp0_;
	return;
}

GdkPixbuf*
single_photo_page_get_unscaled_pixbuf (SinglePhotoPage* self)
{
	GdkPixbuf* _tmp0_;
	GdkPixbuf* _tmp1_;
	GdkPixbuf* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->unscaled;
	_tmp1_ = _g_object_ref0 (_tmp0_);
	result = _tmp1_;
	return result;
}

GdkPixbuf*
single_photo_page_get_scaled_pixbuf (SinglePhotoPage* self)
{
	GdkPixbuf* _tmp0_;
	GdkPixbuf* _tmp1_;
	GdkPixbuf* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->scaled;
	_tmp1_ = _g_object_ref0 (_tmp0_);
	result = _tmp1_;
	return result;
}

void
single_photo_page_get_scaled_pixbuf_position (SinglePhotoPage* self,
                                              GdkRectangle* result)
{
	GdkRectangle _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->scaled_pos;
	*result = _tmp0_;
	return;
}

gboolean
single_photo_page_is_inside_pixbuf (SinglePhotoPage* self,
                                    gint x,
                                    gint y)
{
	gint _tmp0_;
	gint _tmp1_;
	gint _tmp2_;
	gint _tmp3_;
	GdkRectangle _tmp4_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = gtk_widget_get_scale_factor ((GtkWidget*) self);
	_tmp1_ = _tmp0_;
	_tmp2_ = gtk_widget_get_scale_factor ((GtkWidget*) self);
	_tmp3_ = _tmp2_;
	_tmp4_ = self->priv->scaled_pos;
	result = coord_in_rectangle (x * _tmp1_, y * _tmp3_, &_tmp4_);
	return result;
}

static void
single_photo_page_invalidate_all (SinglePhotoPage* self)
{
	GtkDrawingArea* _tmp0_;
	GdkWindow* _tmp1_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->canvas;
	_tmp1_ = gtk_widget_get_window ((GtkWidget*) _tmp0_);
	if (_tmp1_ != NULL) {
		GtkDrawingArea* _tmp2_;
		GdkWindow* _tmp3_;
		_tmp2_ = self->canvas;
		_tmp3_ = gtk_widget_get_window ((GtkWidget*) _tmp2_);
		gdk_window_invalidate_rect (_tmp3_, NULL, FALSE);
	}
}

static void
single_photo_page_on_viewport_resize (SinglePhotoPage* self)
{
	g_return_if_fail (self != NULL);
	single_photo_page_internal_repaint (self, TRUE, NULL);
}

static void
single_photo_page_real_on_resize_finished (Page* base,
                                           GdkRectangle* rect)
{
	SinglePhotoPage * self;
	GdkRectangle _tmp0_;
	self = (SinglePhotoPage*) base;
	g_return_if_fail (rect != NULL);
	_tmp0_ = *rect;
	PAGE_CLASS (single_photo_page_parent_class)->on_resize_finished (G_TYPE_CHECK_INSTANCE_CAST (self, TYPE_PAGE, Page), &_tmp0_);
	single_photo_page_repaint (self, NULL);
}

static gboolean
single_photo_page_on_canvas_exposed (SinglePhotoPage* self,
                                     cairo_t* exposed_ctx)
{
	cairo_surface_t* _tmp0_;
	gint _tmp8_;
	gint _tmp9_;
	gint _tmp10_;
	gint _tmp11_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (exposed_ctx != NULL, FALSE);
	_tmp0_ = self->priv->pixmap;
	if (_tmp0_ != NULL) {
		gint _tmp1_;
		gint _tmp2_;
		gint _tmp3_;
		gint _tmp4_;
		cairo_surface_t* _tmp5_;
		cairo_save (exposed_ctx);
		_tmp1_ = gtk_widget_get_scale_factor ((GtkWidget*) self);
		_tmp2_ = _tmp1_;
		_tmp3_ = gtk_widget_get_scale_factor ((GtkWidget*) self);
		_tmp4_ = _tmp3_;
		cairo_scale (exposed_ctx, (gdouble) (1.0f / _tmp2_), (gdouble) (1.0f / _tmp4_));
		_tmp5_ = self->priv->pixmap;
		cairo_set_source_surface (exposed_ctx, _tmp5_, (gdouble) 0, (gdouble) 0);
	} else {
		GtkDrawingArea* _tmp6_;
		GtkStyleContext* _tmp7_;
		_tmp6_ = self->canvas;
		_tmp7_ = gtk_widget_get_style_context ((GtkWidget*) _tmp6_);
		gtk_render_background (_tmp7_, exposed_ctx, (gdouble) 0, (gdouble) 0, (gdouble) gtk_widget_get_allocated_width ((GtkWidget*) self), (gdouble) gtk_widget_get_allocated_height ((GtkWidget*) self));
	}
	_tmp8_ = gtk_widget_get_scale_factor ((GtkWidget*) self);
	_tmp9_ = _tmp8_;
	_tmp10_ = gtk_widget_get_scale_factor ((GtkWidget*) self);
	_tmp11_ = _tmp10_;
	cairo_rectangle (exposed_ctx, (gdouble) 0, (gdouble) 0, (gdouble) (gtk_widget_get_allocated_width ((GtkWidget*) self) * _tmp9_), (gdouble) (gtk_widget_get_allocated_height ((GtkWidget*) self) * _tmp11_));
	cairo_paint (exposed_ctx);
	cairo_restore (exposed_ctx);
	result = TRUE;
	return result;
}

static void
single_photo_page_real_new_surface (SinglePhotoPage* self,
                                    cairo_t* ctx,
                                    Dimensions* ctx_dim)
{
	g_return_if_fail (ctx != NULL);
	g_return_if_fail (ctx_dim != NULL);
}

void
single_photo_page_new_surface (SinglePhotoPage* self,
                               cairo_t* ctx,
                               Dimensions* ctx_dim)
{
	SinglePhotoPageClass* _klass_;
	g_return_if_fail (self != NULL);
	_klass_ = SINGLE_PHOTO_PAGE_GET_CLASS (self);
	if (_klass_->new_surface) {
		_klass_->new_surface (self, ctx, ctx_dim);
	}
}

static void
single_photo_page_real_updated_pixbuf (SinglePhotoPage* self,
                                       GdkPixbuf* pixbuf,
                                       SinglePhotoPageUpdateReason reason,
                                       Dimensions* old_dim)
{
	g_return_if_fail (pixbuf != NULL);
	g_return_if_fail (old_dim != NULL);
}

void
single_photo_page_updated_pixbuf (SinglePhotoPage* self,
                                  GdkPixbuf* pixbuf,
                                  SinglePhotoPageUpdateReason reason,
                                  Dimensions* old_dim)
{
	SinglePhotoPageClass* _klass_;
	g_return_if_fail (self != NULL);
	_klass_ = SINGLE_PHOTO_PAGE_GET_CLASS (self);
	if (_klass_->updated_pixbuf) {
		_klass_->updated_pixbuf (self, pixbuf, reason, old_dim);
	}
}

static void
single_photo_page_real_paint (SinglePhotoPage* self,
                              cairo_t* ctx,
                              Dimensions* ctx_dim)
{
	gboolean _tmp0_ = FALSE;
	g_return_if_fail (ctx != NULL);
	g_return_if_fail (ctx_dim != NULL);
	if (single_photo_page_is_zoom_supported (self)) {
		_tmp0_ = !zoom_state_is_default (&self->priv->static_zoom_state);
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		GtkDrawingArea* _tmp1_;
		GtkStyleContext* _tmp2_;
		Dimensions _tmp3_;
		Dimensions _tmp4_;
		ZoomState _tmp5_;
		_tmp1_ = self->canvas;
		_tmp2_ = gtk_widget_get_style_context ((GtkWidget*) _tmp1_);
		_tmp3_ = *ctx_dim;
		_tmp4_ = *ctx_dim;
		gtk_render_background (_tmp2_, ctx, (gdouble) 0, (gdouble) 0, (gdouble) _tmp3_.width, (gdouble) _tmp4_.height);
		_tmp5_ = self->priv->static_zoom_state;
		single_photo_page_render_zoomed_to_pixmap (self, &_tmp5_);
	} else {
		TransitionClock* _tmp6_;
		Dimensions _tmp7_;
		Dimensions _tmp8_;
		_tmp6_ = self->priv->transition_clock;
		_tmp7_ = *ctx_dim;
		_tmp8_ = *ctx_dim;
		if (!transition_clock_paint (_tmp6_, ctx, _tmp7_.width, _tmp8_.height)) {
			GtkDrawingArea* _tmp9_;
			GtkStyleContext* _tmp10_;
			Dimensions _tmp11_;
			Dimensions _tmp12_;
			GdkPixbuf* _tmp13_;
			GdkRectangle _tmp14_;
			GdkRectangle _tmp15_;
			_tmp9_ = self->canvas;
			_tmp10_ = gtk_widget_get_style_context ((GtkWidget*) _tmp9_);
			_tmp11_ = *ctx_dim;
			_tmp12_ = *ctx_dim;
			gtk_render_background (_tmp10_, ctx, (gdouble) 0, (gdouble) 0, (gdouble) _tmp11_.width, (gdouble) _tmp12_.height);
			_tmp13_ = self->priv->scaled;
			_tmp14_ = self->priv->scaled_pos;
			_tmp15_ = self->priv->scaled_pos;
			gdk_cairo_set_source_pixbuf (ctx, _tmp13_, (gdouble) _tmp14_.x, (gdouble) _tmp15_.y);
			cairo_paint (ctx);
		}
	}
}

void
single_photo_page_paint (SinglePhotoPage* self,
                         cairo_t* ctx,
                         Dimensions* ctx_dim)
{
	SinglePhotoPageClass* _klass_;
	g_return_if_fail (self != NULL);
	_klass_ = SINGLE_PHOTO_PAGE_GET_CLASS (self);
	if (_klass_->paint) {
		_klass_->paint (self, ctx, ctx_dim);
	}
}

static void
single_photo_page_repaint_pixmap (SinglePhotoPage* self)
{
	cairo_t* _tmp0_;
	cairo_t* _tmp1_;
	Dimensions _tmp2_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->pixmap_ctx;
	if (_tmp0_ == NULL) {
		return;
	}
	_tmp1_ = self->priv->pixmap_ctx;
	_tmp2_ = self->priv->pixmap_dim;
	single_photo_page_paint (self, _tmp1_, &_tmp2_);
	single_photo_page_invalidate_all (self);
}

void
single_photo_page_repaint (SinglePhotoPage* self,
                           Direction* direction)
{
	g_return_if_fail (self != NULL);
	single_photo_page_internal_repaint (self, FALSE, direction);
}

static void
_single_photo_page_repaint_pixmap_transition_clock_repaint_callback (gpointer self)
{
	single_photo_page_repaint_pixmap ((SinglePhotoPage*) self);
}

static void
single_photo_page_internal_repaint (SinglePhotoPage* self,
                                    gboolean fast,
                                    Direction* direction)
{
	gboolean _tmp0_;
	gboolean _tmp1_;
	gboolean _tmp2_ = FALSE;
	GdkPixbuf* _tmp3_;
	GtkAllocation allocation = {0};
	GtkViewport* _tmp6_;
	GtkAllocation _tmp7_ = {0};
	gint width = 0;
	GtkAllocation _tmp8_;
	gint _tmp9_;
	gint _tmp10_;
	gint height = 0;
	GtkAllocation _tmp11_;
	gint _tmp12_;
	gint _tmp13_;
	gboolean _tmp14_ = FALSE;
	gboolean new_pixbuf = FALSE;
	GdkPixbuf* _tmp15_;
	Dimensions old_scaled_dim = {0};
	GdkRectangle _tmp16_;
	Dimensions _tmp17_ = {0};
	GdkRectangle old_scaled_pos = {0};
	GdkRectangle _tmp18_;
	gboolean _tmp19_ = FALSE;
	Dimensions _tmp20_;
	gboolean new_pixmap = FALSE;
	cairo_surface_t* _tmp22_;
	gboolean _tmp23_ = FALSE;
	GdkInterpType _tmp41_ = 0;
	GdkInterpType interp = 0;
	GdkPixbuf* _tmp42_;
	gboolean _tmp53_ = FALSE;
	TransitionClock* _tmp63_;
	g_return_if_fail (self != NULL);
	_tmp0_ = page_get_in_view ((Page*) self);
	_tmp1_ = _tmp0_;
	if (!_tmp1_) {
		_cairo_surface_destroy0 (self->priv->pixmap);
		self->priv->pixmap = NULL;
		_g_object_unref0 (self->priv->scaled);
		self->priv->scaled = NULL;
		return;
	}
	_tmp3_ = self->priv->unscaled;
	if (_tmp3_ == NULL) {
		_tmp2_ = TRUE;
	} else {
		GtkDrawingArea* _tmp4_;
		GdkWindow* _tmp5_;
		_tmp4_ = self->canvas;
		_tmp5_ = gtk_widget_get_window ((GtkWidget*) _tmp4_);
		_tmp2_ = _tmp5_ == NULL;
	}
	if (_tmp2_) {
		return;
	}
	_tmp6_ = self->viewport;
	gtk_widget_get_allocation ((GtkWidget*) _tmp6_, &_tmp7_);
	allocation = _tmp7_;
	_tmp8_ = allocation;
	_tmp9_ = gtk_widget_get_scale_factor ((GtkWidget*) self);
	_tmp10_ = _tmp9_;
	width = _tmp8_.width * _tmp10_;
	_tmp11_ = allocation;
	_tmp12_ = gtk_widget_get_scale_factor ((GtkWidget*) self);
	_tmp13_ = _tmp12_;
	height = _tmp11_.height * _tmp13_;
	if (width <= 0) {
		_tmp14_ = TRUE;
	} else {
		_tmp14_ = height <= 0;
	}
	if (_tmp14_) {
		return;
	}
	_tmp15_ = self->priv->scaled;
	new_pixbuf = _tmp15_ == NULL;
	_tmp16_ = self->priv->scaled_pos;
	dimensions_for_rectangle (&_tmp16_, &_tmp17_);
	old_scaled_dim = _tmp17_;
	_tmp18_ = self->priv->scaled_pos;
	old_scaled_pos = _tmp18_;
	_tmp20_ = self->priv->pixmap_dim;
	if (_tmp20_.width != width) {
		_tmp19_ = TRUE;
	} else {
		Dimensions _tmp21_;
		_tmp21_ = self->priv->pixmap_dim;
		_tmp19_ = _tmp21_.height != height;
	}
	if (_tmp19_) {
		_cairo_surface_destroy0 (self->priv->pixmap);
		self->priv->pixmap = NULL;
	}
	new_pixmap = FALSE;
	_tmp22_ = self->priv->pixmap;
	if (_tmp22_ == NULL) {
		single_photo_page_init_pixmap (self, width, height);
		new_pixmap = TRUE;
	}
	if (new_pixbuf) {
		_tmp23_ = TRUE;
	} else {
		_tmp23_ = new_pixmap;
	}
	if (_tmp23_) {
		Dimensions unscaled_dim = {0};
		GdkPixbuf* _tmp24_;
		Dimensions _tmp25_ = {0};
		Dimensions scaled_dim = {0};
		gboolean _tmp26_ = FALSE;
		gboolean _tmp27_ = FALSE;
		gboolean _tmp28_ = FALSE;
		gboolean _tmp29_;
		Dimensions _tmp35_;
		Dimensions _tmp36_;
		Dimensions _tmp37_;
		Dimensions _tmp38_;
		Dimensions _tmp39_;
		Dimensions _tmp40_;
		_tmp24_ = self->priv->unscaled;
		dimensions_for_pixbuf (_tmp24_, &_tmp25_);
		unscaled_dim = _tmp25_;
		dimensions_init (&scaled_dim, 0, 0);
		_tmp29_ = self->priv->_scale_up_to_viewport;
		if (!_tmp29_) {
			_tmp28_ = dimensions_has_area (&self->priv->max_dim);
		} else {
			_tmp28_ = FALSE;
		}
		if (_tmp28_) {
			Dimensions _tmp30_;
			_tmp30_ = self->priv->max_dim;
			_tmp27_ = _tmp30_.width < width;
		} else {
			_tmp27_ = FALSE;
		}
		if (_tmp27_) {
			Dimensions _tmp31_;
			_tmp31_ = self->priv->max_dim;
			_tmp26_ = _tmp31_.height < height;
		} else {
			_tmp26_ = FALSE;
		}
		if (_tmp26_) {
			Dimensions _tmp32_;
			_tmp32_ = self->priv->max_dim;
			scaled_dim = _tmp32_;
		} else {
			Dimensions _tmp33_;
			Dimensions _tmp34_ = {0};
			_tmp33_ = self->priv->pixmap_dim;
			dimensions_get_scaled_proportional (&unscaled_dim, &_tmp33_, &_tmp34_);
			scaled_dim = _tmp34_;
		}
		_tmp35_ = scaled_dim;
		_vala_assert (width >= _tmp35_.width, "width >= scaled_dim.width");
		_tmp36_ = scaled_dim;
		_vala_assert (height >= _tmp36_.height, "height >= scaled_dim.height");
		_tmp37_ = scaled_dim;
		self->priv->scaled_pos.x = (width - _tmp37_.width) / 2;
		_tmp38_ = scaled_dim;
		self->priv->scaled_pos.y = (height - _tmp38_.height) / 2;
		_tmp39_ = scaled_dim;
		self->priv->scaled_pos.width = _tmp39_.width;
		_tmp40_ = scaled_dim;
		self->priv->scaled_pos.height = _tmp40_.height;
	}
	if (fast) {
		_tmp41_ = GDK_INTERP_NEAREST;
	} else {
		_tmp41_ = GDK_INTERP_BILINEAR;
	}
	interp = _tmp41_;
	_tmp42_ = self->priv->scaled;
	if (_tmp42_ == NULL) {
		GdkPixbuf* _tmp43_;
		GdkRectangle _tmp44_;
		Dimensions _tmp45_ = {0};
		GdkPixbuf* _tmp46_;
		SinglePhotoPageUpdateReason reason = 0;
		Dimensions _tmp48_;
		Dimensions _tmp49_;
		GdkPoint _tmp50_ = {0};
		GdkPixbuf* _tmp51_;
		Dimensions _tmp52_;
		_tmp43_ = self->priv->unscaled;
		_tmp44_ = self->priv->scaled_pos;
		dimensions_for_rectangle (&_tmp44_, &_tmp45_);
		_tmp46_ = resize_pixbuf (_tmp43_, &_tmp45_, interp);
		_g_object_unref0 (self->priv->scaled);
		self->priv->scaled = _tmp46_;
		reason = SINGLE_PHOTO_PAGE_UPDATE_REASON_RESIZED_CANVAS;
		if (new_pixbuf) {
			reason = SINGLE_PHOTO_PAGE_UPDATE_REASON_NEW_PIXBUF;
		} else {
			gboolean _tmp47_ = FALSE;
			if (!new_pixmap) {
				_tmp47_ = interp == GDK_INTERP_BILINEAR;
			} else {
				_tmp47_ = FALSE;
			}
			if (_tmp47_) {
				reason = SINGLE_PHOTO_PAGE_UPDATE_REASON_QUALITY_IMPROVEMENT;
			}
		}
		_tmp48_ = self->priv->max_dim;
		_tmp49_ = self->priv->pixmap_dim;
		zoom_state_get_viewport_center (&self->priv->static_zoom_state, &_tmp50_);
		zoom_state_init (&self->priv->static_zoom_state, &_tmp48_, &_tmp49_, zoom_state_get_interpolation_factor (&self->priv->static_zoom_state), &_tmp50_);
		_tmp51_ = self->priv->scaled;
		_tmp52_ = old_scaled_dim;
		single_photo_page_updated_pixbuf (self, _tmp51_, reason, &_tmp52_);
	}
	self->priv->zoom_high_quality = !fast;
	if (direction != NULL) {
		TransitionClock* _tmp54_;
		_tmp54_ = self->priv->transition_clock;
		_tmp53_ = !transition_clock_is_in_progress (_tmp54_);
	} else {
		_tmp53_ = FALSE;
	}
	if (_tmp53_) {
		SpitTransitionsVisuals* visuals = NULL;
		GdkPixbuf* _tmp55_;
		GdkRectangle _tmp56_;
		GdkPixbuf* _tmp57_;
		GdkRectangle _tmp58_;
		GdkRGBA _tmp59_ = {0};
		SpitTransitionsVisuals* _tmp60_;
		TransitionClock* _tmp61_;
		SpitTransitionsVisuals* _tmp62_;
		_tmp55_ = self->priv->old_scaled;
		_tmp56_ = old_scaled_pos;
		_tmp57_ = self->priv->scaled;
		_tmp58_ = self->priv->scaled_pos;
		parse_color ("#000", &_tmp59_);
		_tmp60_ = spit_transitions_visuals_new (_tmp55_, &_tmp56_, _tmp57_, &_tmp58_, &_tmp59_);
		visuals = _tmp60_;
		_tmp61_ = self->priv->transition_clock;
		_tmp62_ = visuals;
		transition_clock_start (_tmp61_, _tmp62_, direction_to_transition_direction (*direction), self->priv->transition_duration_msec, _single_photo_page_repaint_pixmap_transition_clock_repaint_callback, self);
		_g_object_unref0 (visuals);
	}
	_tmp63_ = self->priv->transition_clock;
	if (!transition_clock_is_in_progress (_tmp63_)) {
		single_photo_page_repaint_pixmap (self);
	}
}

static void
single_photo_page_init_pixmap (SinglePhotoPage* self,
                               gint width,
                               gint height)
{
	GdkPixbuf* _tmp0_;
	GtkDrawingArea* _tmp1_;
	GdkWindow* _tmp2_;
	cairo_surface_t* _tmp3_;
	cairo_surface_t* _tmp4_;
	cairo_t* _tmp5_;
	cairo_surface_t* _tmp6_;
	cairo_t* _tmp7_;
	cairo_t* _tmp8_;
	cairo_t* _tmp9_;
	Dimensions _tmp10_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->unscaled;
	_vala_assert (_tmp0_ != NULL, "unscaled != null");
	_tmp1_ = self->canvas;
	_tmp2_ = gtk_widget_get_window ((GtkWidget*) _tmp1_);
	_vala_assert (_tmp2_ != NULL, "canvas.get_window () != null");
	_tmp3_ = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
	_cairo_surface_destroy0 (self->priv->pixmap);
	self->priv->pixmap = _tmp3_;
	dimensions_init (&self->priv->pixmap_dim, width, height);
	_tmp4_ = self->priv->pixmap;
	_tmp5_ = cairo_create (_tmp4_);
	_cairo_destroy0 (self->priv->pixmap_ctx);
	self->priv->pixmap_ctx = _tmp5_;
	_g_object_unref0 (self->priv->scaled);
	self->priv->scaled = NULL;
	_tmp6_ = self->priv->pixmap;
	_tmp7_ = cairo_create (_tmp6_);
	_cairo_destroy0 (self->priv->text_ctx);
	self->priv->text_ctx = _tmp7_;
	_tmp8_ = self->priv->text_ctx;
	set_source_color_from_string (_tmp8_, "#fff");
	_tmp9_ = self->priv->pixmap_ctx;
	_tmp10_ = self->priv->pixmap_dim;
	single_photo_page_new_surface (self, _tmp9_, &_tmp10_);
}

static gboolean
single_photo_page_real_on_context_keypress (Page* base)
{
	SinglePhotoPage * self;
	GtkMenu* _tmp0_;
	GtkMenu* _tmp1_;
	gboolean _tmp2_;
	gboolean result;
	self = (SinglePhotoPage*) base;
	_tmp0_ = page_get_page_context_menu ((Page*) self);
	_tmp1_ = _tmp0_;
	_tmp2_ = page_popup_context_menu ((Page*) self, _tmp1_, NULL);
	_g_object_unref0 (_tmp1_);
	result = _tmp2_;
	return result;
}

static void
single_photo_page_real_on_previous_photo (SinglePhotoPage* self)
{
}

void
single_photo_page_on_previous_photo (SinglePhotoPage* self)
{
	SinglePhotoPageClass* _klass_;
	g_return_if_fail (self != NULL);
	_klass_ = SINGLE_PHOTO_PAGE_GET_CLASS (self);
	if (_klass_->on_previous_photo) {
		_klass_->on_previous_photo (self);
	}
}

static void
single_photo_page_real_on_next_photo (SinglePhotoPage* self)
{
}

void
single_photo_page_on_next_photo (SinglePhotoPage* self)
{
	SinglePhotoPageClass* _klass_;
	g_return_if_fail (self != NULL);
	_klass_ = SINGLE_PHOTO_PAGE_GET_CLASS (self);
	if (_klass_->on_next_photo) {
		_klass_->on_next_photo (self);
	}
}

static gboolean
single_photo_page_real_key_press_event (GtkWidget* base,
                                        GdkEventKey* event)
{
	SinglePhotoPage * self;
	gboolean nav_ok = FALSE;
	gboolean handled = FALSE;
	const gchar* _tmp0_;
	const gchar* _tmp1_;
	GQuark _tmp3_ = 0U;
	static GQuark _tmp2_label0 = 0;
	static GQuark _tmp2_label1 = 0;
	static GQuark _tmp2_label2 = 0;
	static GQuark _tmp2_label3 = 0;
	static GQuark _tmp2_label4 = 0;
	gboolean _tmp4_ = FALSE;
	gboolean result;
	self = (SinglePhotoPage*) base;
	g_return_val_if_fail (event != NULL, FALSE);
	nav_ok = (event->time - self->priv->last_nav_key) > ((guint32) 200);
	handled = TRUE;
	_tmp0_ = gdk_keyval_name (event->keyval);
	_tmp1_ = _tmp0_;
	_tmp3_ = (NULL == _tmp1_) ? 0 : g_quark_from_string (_tmp1_);
	if ((_tmp3_ == ((0 != _tmp2_label0) ? _tmp2_label0 : (_tmp2_label0 = g_quark_from_static_string ("Left")))) || (_tmp3_ == ((0 != _tmp2_label1) ? _tmp2_label1 : (_tmp2_label1 = g_quark_from_static_string ("KP_Left"))))) {
		switch (0) {
			default:
			{
				if (nav_ok) {
					single_photo_page_on_previous_photo (self);
					self->priv->last_nav_key = event->time;
				}
				break;
			}
		}
	} else if (((_tmp3_ == ((0 != _tmp2_label2) ? _tmp2_label2 : (_tmp2_label2 = g_quark_from_static_string ("Right")))) || (_tmp3_ == ((0 != _tmp2_label3) ? _tmp2_label3 : (_tmp2_label3 = g_quark_from_static_string ("KP_Right"))))) || (_tmp3_ == ((0 != _tmp2_label4) ? _tmp2_label4 : (_tmp2_label4 = g_quark_from_static_string ("space"))))) {
		switch (0) {
			default:
			{
				if (nav_ok) {
					single_photo_page_on_next_photo (self);
					self->priv->last_nav_key = event->time;
				}
				break;
			}
		}
	} else {
		switch (0) {
			default:
			{
				handled = FALSE;
				break;
			}
		}
	}
	if (handled) {
		result = TRUE;
		return result;
	}
	if (GTK_WIDGET_CLASS (single_photo_page_parent_class)->key_press_event != NULL) {
		_tmp4_ = GTK_WIDGET_CLASS (single_photo_page_parent_class)->key_press_event ((GtkWidget*) G_TYPE_CHECK_INSTANCE_CAST (self, TYPE_PAGE, Page), event);
	} else {
		_tmp4_ = TRUE;
	}
	result = _tmp4_;
	return result;
}

gboolean
single_photo_page_get_scale_up_to_viewport (SinglePhotoPage* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	result = self->priv->_scale_up_to_viewport;
	return result;
}

static void
single_photo_page_set_scale_up_to_viewport (SinglePhotoPage* self,
                                            gboolean value)
{
	gboolean old_value;
	g_return_if_fail (self != NULL);
	old_value = single_photo_page_get_scale_up_to_viewport (self);
	if (old_value != value) {
		self->priv->_scale_up_to_viewport = value;
		g_object_notify_by_pspec ((GObject *) self, single_photo_page_properties[SINGLE_PHOTO_PAGE_SCALE_UP_TO_VIEWPORT_PROPERTY]);
	}
}

static void
_single_photo_page_on_viewport_resize_gtk_widget_size_allocate (GtkWidget* _sender,
                                                                GtkAllocation* allocation,
                                                                gpointer self)
{
	single_photo_page_on_viewport_resize ((SinglePhotoPage*) self);
}

static gboolean
_single_photo_page_on_canvas_exposed_gtk_widget_draw (GtkWidget* _sender,
                                                      cairo_t* cr,
                                                      gpointer self)
{
	gboolean result;
	result = single_photo_page_on_canvas_exposed ((SinglePhotoPage*) self, cr);
	return result;
}

static GObject *
single_photo_page_constructor (GType type,
                               guint n_construct_properties,
                               GObjectConstructParam * construct_properties)
{
	GObject * obj;
	GObjectClass * parent_class;
	SinglePhotoPage * self;
	TransitionEffectsManager* _tmp0_;
	TransitionEffectsManager* _tmp1_;
	TransitionClock* _tmp2_;
	GtkDrawingArea* _tmp3_;
	GtkStyleContext* _tmp4_;
	GtkViewport* _tmp5_;
	GtkDrawingArea* _tmp6_;
	GtkViewport* _tmp7_;
	GtkDrawingArea* _tmp8_;
	GtkViewport* _tmp9_;
	GtkDrawingArea* _tmp10_;
	GtkDrawingArea* _tmp11_;
	parent_class = G_OBJECT_CLASS (single_photo_page_parent_class);
	obj = parent_class->constructor (type, n_construct_properties, construct_properties);
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_SINGLE_PHOTO_PAGE, SinglePhotoPage);
	_tmp0_ = transition_effects_manager_get_instance ();
	_tmp1_ = _tmp0_;
	_tmp2_ = transition_effects_manager_create_null_transition_clock (_tmp1_);
	_transition_clock_unref0 (self->priv->transition_clock);
	self->priv->transition_clock = _tmp2_;
	_transition_effects_manager_unref0 (_tmp1_);
	gtk_scrolled_window_set_policy ((GtkScrolledWindow*) self, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
	_tmp3_ = self->canvas;
	_tmp4_ = gtk_widget_get_style_context ((GtkWidget*) _tmp3_);
	gtk_style_context_add_class (_tmp4_, GRANITE_STYLE_CLASS_CHECKERBOARD);
	_tmp5_ = self->viewport;
	_tmp6_ = self->canvas;
	gtk_container_add ((GtkContainer*) _tmp5_, (GtkWidget*) _tmp6_);
	_tmp7_ = self->viewport;
	gtk_container_add ((GtkContainer*) self, (GtkWidget*) _tmp7_);
	_tmp8_ = self->canvas;
	gtk_widget_add_events ((GtkWidget*) _tmp8_, (gint) ((GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK) | GDK_SUBSTRUCTURE_MASK));
	_tmp9_ = self->viewport;
	g_signal_connect_object ((GtkWidget*) _tmp9_, "size-allocate", (GCallback) _single_photo_page_on_viewport_resize_gtk_widget_size_allocate, self, 0);
	_tmp10_ = self->canvas;
	g_signal_connect_object ((GtkWidget*) _tmp10_, "draw", (GCallback) _single_photo_page_on_canvas_exposed_gtk_widget_draw, self, 0);
	_tmp11_ = self->canvas;
	page_set_event_source ((Page*) self, (GtkWidget*) _tmp11_);
	return obj;
}

static void
single_photo_page_class_init (SinglePhotoPageClass * klass,
                              gpointer klass_data)
{
	single_photo_page_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &SinglePhotoPage_private_offset);
	((SinglePhotoPageClass *) klass)->is_zoom_supported = (gboolean (*) (SinglePhotoPage*)) single_photo_page_real_is_zoom_supported;
	((SinglePhotoPageClass *) klass)->cancel_zoom = (void (*) (SinglePhotoPage*)) single_photo_page_real_cancel_zoom;
	((SinglePhotoPageClass *) klass)->save_zoom_state = (void (*) (SinglePhotoPage*)) single_photo_page_real_save_zoom_state;
	((SinglePhotoPageClass *) klass)->restore_zoom_state = (void (*) (SinglePhotoPage*)) single_photo_page_real_restore_zoom_state;
	((SinglePhotoPageClass *) klass)->get_zoom_buffer = (ZoomBuffer* (*) (SinglePhotoPage*)) single_photo_page_real_get_zoom_buffer;
	((PageClass *) klass)->switched_to = (void (*) (Page*)) single_photo_page_real_switched_to;
	((PageClass *) klass)->set_container = (void (*) (Page*, GtkWindow*)) single_photo_page_real_set_container;
	((PageClass *) klass)->on_resize_finished = (void (*) (Page*, GdkRectangle*)) single_photo_page_real_on_resize_finished;
	((SinglePhotoPageClass *) klass)->new_surface = (void (*) (SinglePhotoPage*, cairo_t*, Dimensions*)) single_photo_page_real_new_surface;
	((SinglePhotoPageClass *) klass)->updated_pixbuf = (void (*) (SinglePhotoPage*, GdkPixbuf*, SinglePhotoPageUpdateReason, Dimensions*)) single_photo_page_real_updated_pixbuf;
	((SinglePhotoPageClass *) klass)->paint = (void (*) (SinglePhotoPage*, cairo_t*, Dimensions*)) single_photo_page_real_paint;
	((PageClass *) klass)->on_context_keypress = (gboolean (*) (Page*)) single_photo_page_real_on_context_keypress;
	((SinglePhotoPageClass *) klass)->on_previous_photo = (void (*) (SinglePhotoPage*)) single_photo_page_real_on_previous_photo;
	((SinglePhotoPageClass *) klass)->on_next_photo = (void (*) (SinglePhotoPage*)) single_photo_page_real_on_next_photo;
	((GtkWidgetClass *) klass)->key_press_event = (gboolean (*) (GtkWidget*, GdkEventKey*)) single_photo_page_real_key_press_event;
	G_OBJECT_CLASS (klass)->get_property = _vala_single_photo_page_get_property;
	G_OBJECT_CLASS (klass)->set_property = _vala_single_photo_page_set_property;
	G_OBJECT_CLASS (klass)->constructor = single_photo_page_constructor;
	G_OBJECT_CLASS (klass)->finalize = single_photo_page_finalize;
	g_object_class_install_property (G_OBJECT_CLASS (klass), SINGLE_PHOTO_PAGE_SCALE_UP_TO_VIEWPORT_PROPERTY, single_photo_page_properties[SINGLE_PHOTO_PAGE_SCALE_UP_TO_VIEWPORT_PROPERTY] = g_param_spec_boolean ("scale-up-to-viewport", "scale-up-to-viewport", "scale-up-to-viewport", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
}

static void
single_photo_page_instance_init (SinglePhotoPage * self,
                                 gpointer klass)
{
	GtkDrawingArea* _tmp0_;
	GtkViewport* _tmp1_;
	self->priv = single_photo_page_get_instance_private (self);
	_tmp0_ = (GtkDrawingArea*) gtk_drawing_area_new ();
	g_object_ref_sink (_tmp0_);
	self->canvas = _tmp0_;
	_tmp1_ = (GtkViewport*) gtk_viewport_new (NULL, NULL);
	g_object_ref_sink (_tmp1_);
	self->viewport = _tmp1_;
	self->priv->transition_duration_msec = 0;
	self->priv->pixmap = NULL;
	self->priv->pixmap_ctx = NULL;
	self->priv->text_ctx = NULL;
	dimensions_init (&self->priv->pixmap_dim, 0, 0);
	self->priv->unscaled = NULL;
	dimensions_init (&self->priv->max_dim, 0, 0);
	self->priv->scaled = NULL;
	self->priv->old_scaled = NULL;
	memset (&self->priv->scaled_pos, 0, sizeof (GdkRectangle));
	self->priv->zoom_high_quality = TRUE;
	self->priv->has_saved_zoom_state = FALSE;
	self->priv->last_nav_key = (guint32) 0;
}

static void
single_photo_page_finalize (GObject * obj)
{
	SinglePhotoPage * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_SINGLE_PHOTO_PAGE, SinglePhotoPage);
	_g_object_unref0 (self->canvas);
	_g_object_unref0 (self->viewport);
	_transition_clock_unref0 (self->priv->transition_clock);
	_cairo_surface_destroy0 (self->priv->pixmap);
	_cairo_destroy0 (self->priv->pixmap_ctx);
	_cairo_destroy0 (self->priv->text_ctx);
	_g_object_unref0 (self->priv->unscaled);
	_g_object_unref0 (self->priv->scaled);
	_g_object_unref0 (self->priv->old_scaled);
	G_OBJECT_CLASS (single_photo_page_parent_class)->finalize (obj);
}

static GType
single_photo_page_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (SinglePhotoPageClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) single_photo_page_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (SinglePhotoPage), 0, (GInstanceInitFunc) single_photo_page_instance_init, NULL };
	GType single_photo_page_type_id;
	single_photo_page_type_id = g_type_register_static (TYPE_PAGE, "SinglePhotoPage", &g_define_type_info, G_TYPE_FLAG_ABSTRACT);
	SinglePhotoPage_private_offset = g_type_add_instance_private (single_photo_page_type_id, sizeof (SinglePhotoPagePrivate));
	return single_photo_page_type_id;
}

GType
single_photo_page_get_type (void)
{
	static volatile gsize single_photo_page_type_id__once = 0;
	if (g_once_init_enter (&single_photo_page_type_id__once)) {
		GType single_photo_page_type_id;
		single_photo_page_type_id = single_photo_page_get_type_once ();
		g_once_init_leave (&single_photo_page_type_id__once, single_photo_page_type_id);
	}
	return single_photo_page_type_id__once;
}

static void
_vala_single_photo_page_get_property (GObject * object,
                                      guint property_id,
                                      GValue * value,
                                      GParamSpec * pspec)
{
	SinglePhotoPage * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, TYPE_SINGLE_PHOTO_PAGE, SinglePhotoPage);
	switch (property_id) {
		case SINGLE_PHOTO_PAGE_SCALE_UP_TO_VIEWPORT_PROPERTY:
		g_value_set_boolean (value, single_photo_page_get_scale_up_to_viewport (self));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
_vala_single_photo_page_set_property (GObject * object,
                                      guint property_id,
                                      const GValue * value,
                                      GParamSpec * pspec)
{
	SinglePhotoPage * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, TYPE_SINGLE_PHOTO_PAGE, SinglePhotoPage);
	switch (property_id) {
		case SINGLE_PHOTO_PAGE_SCALE_UP_TO_VIEWPORT_PROPERTY:
		single_photo_page_set_scale_up_to_viewport (self, g_value_get_boolean (value));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static inline gpointer
_vala_memdup2 (gconstpointer mem,
               gsize byte_size)
{
	gpointer new_mem;
	if (mem && byte_size != 0) {
		new_mem = g_malloc (byte_size);
		memcpy (new_mem, mem, byte_size);
	} else {
		new_mem = NULL;
	}
	return new_mem;
}

