diff --git a/src/gtk-tpdfv.c b/src/gtk-tpdfv.c
index b04d2c6f9cb3ffb177e039dc45f10fa268b3f84d..ee68357d1253de739f77b7002a4785f2b3f4346b 100644 (file)
--- a/src/gtk-tpdfv.c
+++ b/src/gtk-tpdfv.c
#include <stdlib.h>
#include <string.h>
+#define TPDFV_MIN(a, b) ((a) <= (b) ? (a) : (b))
+#define TPDFV_MAX(a, b) ((a) >= (b) ? (a) : (b))
+
+typedef enum {
+ TPDFV_ZOOM_CUSTOM = 0,
+ TPDFV_ZOOM_WIDTH,
+ TPDFV_ZOOM_HEIGHT,
+ TPDFV_ZOOM_FIT,
+} tpdfv_zoommode_t;
+
typedef struct {
char *filename;
int current_page_no;
int total_pages;
+ tpdfv_zoommode_t zoom_mode;
double zoom_factor;
double delta_x;
* Private helper functions.
*/
-static gboolean
-tpdfv_init(gtk_tpdfv_t *pdf, const char *filename)
+static void
+tpdfv_open(gtk_tpdfv_t *pdf)
{
GError *err = NULL;
+ if ((! pdf) || (! pdf->filename))
+ return;
+
+ pdf->doc = poppler_document_new_from_file(pdf->filename,
+ /* password = */ NULL, &err);
+ if (! pdf->doc) {
+ fprintf(stderr, "Failed to open PDF: %s.\n", err->message);
+ return;
+ }
+
+ pdf->total_pages = poppler_document_get_n_pages(pdf->doc);
+ if (pdf->current_page_no >= pdf->total_pages)
+ pdf->current_page_no = pdf->total_pages - 1;
+} /* tpdfv_open */
+
+static void
+tpdfv_close(gtk_tpdfv_t *pdf)
+{
+ if (! pdf)
+ return;
+
+ g_object_unref(pdf->doc);
+ pdf->doc = NULL;
+ pdf->current_page = NULL;
+} /* tpdfv_close */
+
+static gboolean
+tpdfv_init(gtk_tpdfv_t *pdf, const char *filename)
+{
if (strstr(filename, "://"))
pdf->filename = strdup(filename);
else {
return FALSE;
}
- pdf->doc = poppler_document_new_from_file(pdf->filename,
- /* password = */ NULL, &err);
- if (! pdf->doc) {
- fprintf(stderr, "Failed to open PDF: %s.\n", err->message);
- return FALSE;
- }
+ pdf->doc = NULL;
+ tpdfv_open(pdf);
pdf->current_page_no = 0;
pdf->current_page = poppler_document_get_page(pdf->doc,
return FALSE;
}
- pdf->total_pages = poppler_document_get_n_pages(pdf->doc);
-
+ pdf->zoom_mode = TPDFV_ZOOM_CUSTOM;
pdf->zoom_factor = 1.0;
pdf->delta_x = pdf->delta_y = 0.0;
return TRUE;
if (! pdf)
return;
- g_object_unref(pdf->doc);
- pdf->doc = NULL;
+ tpdfv_close(pdf);
pdf->current_page = NULL;
free(pdf->filename);
pdf->filename = NULL;
pdf = GTK_TPDFV_GET_PRIVATE(widget);
- if (poppler_page_get_index(pdf->current_page)
- != pdf->current_page_no) {
+ if ((! pdf->current_page) || (poppler_page_get_index(pdf->current_page)
+ != pdf->current_page_no)) {
pdf->current_page = poppler_document_get_page(pdf->doc,
pdf->current_page_no);
gtk_tpdfv_t *pdf;
cairo_t *cr;
+ gdouble width, height;
+
+ gdouble page_width = 0.0;
+ gdouble page_height = 0.0;
+
+ double zoom_factor = 1.0;
+ double x, y;
+
pdf = GTK_TPDFV_GET_PRIVATE(tpdfv);
if (! pdf)
event->area.width, event->area.height);
cairo_clip(cr);
- /* zoom, scrolling */
- cairo_scale(cr, pdf->zoom_factor, pdf->zoom_factor);
- cairo_translate(cr, pdf->delta_x, pdf->delta_y);
+ poppler_page_get_size(pdf->current_page, &page_width, &page_height);
+ width = (gdouble)tpdfv->allocation.width;
+ height = (gdouble)tpdfv->allocation.height;
+
+ /* zoom */
+ if (pdf->zoom_mode == TPDFV_ZOOM_CUSTOM) {
+ zoom_factor = pdf->zoom_factor;
+ }
+ else {
+ if (pdf->zoom_mode == TPDFV_ZOOM_WIDTH) {
+ zoom_factor = (double)(width / page_width);
+ }
+ else if (pdf->zoom_mode == TPDFV_ZOOM_HEIGHT) {
+ zoom_factor = (double)(height / page_height);
+ }
+ else if (pdf->zoom_mode == TPDFV_ZOOM_FIT) {
+ zoom_factor = (double)TPDFV_MIN(width / page_width,
+ height / page_height);
+ }
+ else {
+ assert(0);
+ }
+ }
+ cairo_scale(cr, zoom_factor, zoom_factor);
+
+ /* centered position / scrolling */
+ x = (double)(width - page_width * zoom_factor) / 2.0 / zoom_factor;
+ y = (double)(height - page_height * zoom_factor) / 2.0 / zoom_factor;
+
+ cairo_translate(cr, x + pdf->delta_x, y + pdf->delta_y);
poppler_page_render(pdf->current_page, cr);
return GTK_WIDGET(tpdfv);
} /* gtk_tpdfv_new */
+void
+gtk_tpdfv_reload(GtkWidget *widget)
+{
+ gtk_tpdfv_t *pdf;
+
+ pdf = GTK_TPDFV_GET_PRIVATE(widget);
+ tpdfv_close(pdf);
+ tpdfv_open(pdf);
+ do_redraw(widget);
+} /* gtk_tpdfv_reload */
+
void
gtk_tpdfv_page_up(GtkWidget *widget)
{
pdf = GTK_TPDFV_GET_PRIVATE(widget);
pdf->zoom_factor *= 1.2;
+ pdf->zoom_mode = TPDFV_ZOOM_CUSTOM;
do_redraw(widget);
} /* gtk_tpdfv_zoom_in */
if (pdf->zoom_factor > DBL_EPSILON * 2.0) {
pdf->zoom_factor /= 1.2;
+ pdf->zoom_mode = TPDFV_ZOOM_CUSTOM;
do_redraw(widget);
}
} /* gtk_tpdfv_zoom_out */
pdf = GTK_TPDFV_GET_PRIVATE(widget);
pdf->zoom_factor = 1.0;
+ pdf->zoom_mode = TPDFV_ZOOM_CUSTOM;
do_redraw(widget);
} /* gtk_tpdfv_zoom_1 */
+void
+gtk_tpdfv_zoom_width(GtkWidget *widget)
+{
+ gtk_tpdfv_t *pdf;
+
+ pdf = GTK_TPDFV_GET_PRIVATE(widget);
+ pdf->zoom_mode = TPDFV_ZOOM_WIDTH;
+ do_redraw(widget);
+} /* gtk_tpdfv_zoom_width */
+
+void
+gtk_tpdfv_zoom_height(GtkWidget *widget)
+{
+ gtk_tpdfv_t *pdf;
+
+ pdf = GTK_TPDFV_GET_PRIVATE(widget);
+ pdf->zoom_mode = TPDFV_ZOOM_HEIGHT;
+ do_redraw(widget);
+} /* gtk_tpdfv_zoom_width */
+
+void
+gtk_tpdfv_zoom_fit(GtkWidget *widget)
+{
+ gtk_tpdfv_t *pdf;
+
+ pdf = GTK_TPDFV_GET_PRIVATE(widget);
+ pdf->zoom_mode = TPDFV_ZOOM_FIT;
+ do_redraw(widget);
+} /* gtk_tpdfv_zoom_width */
+
void
gtk_tpdfv_scroll_up(GtkWidget *widget)
{