summaryrefslogtreecommitdiff
path: root/test/gtkpdf.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/gtkpdf.c')
-rw-r--r--test/gtkpdf.c670
1 files changed, 0 insertions, 670 deletions
diff --git a/test/gtkpdf.c b/test/gtkpdf.c
deleted file mode 100644
index 07730b38..00000000
--- a/test/gtkpdf.c
+++ /dev/null
@@ -1,670 +0,0 @@
-/*
-
-TODO:
- - threaded pdf/page loading
- - info dialog
- - resource dialog
- - password dialog
- - outline tree
- - magnifying glass
- - text selection
- - text search
-
-*/
-
-#include <fitz.h>
-#include <mupdf.h>
-
-#include <gtk/gtk.h>
-#include <glib.h>
-#include <pthread.h>
-
-typedef struct PDFApp PDFApp;
-
-enum { ZOOM, FITWIDTH, FITPAGE };
-
-struct PDFApp
-{
- GtkWidget *canvas;
- GtkWidget *status;
- GtkWidget *scroll;
- int statusid;
- int viewmode;
-
- char *filename;
- int pageno;
- int rotate;
- float zoom;
-
- fz_renderer *gc;
- pdf_xref *xref;
- pdf_pagetree *pagetree;
- fz_obj *pageobj;
- pdf_page *page;
- fz_pixmap *image;
-};
-
-static volatile int busy = 0;
-
-PDFApp *gapp;
-
-static void showstatus(char *fmt, ...)
-{
- char msg[256];
- va_list ap;
-
- va_start(ap, fmt);
- vsnprintf(msg, 256, fmt, ap);
- va_end(ap);
-
- gtk_statusbar_pop(GTK_STATUSBAR(gapp->status), gapp->statusid);
- gtk_statusbar_push(GTK_STATUSBAR(gapp->status), gapp->statusid, msg);
-}
-
-static void panic(fz_error *error)
-{
- gapp->filename = "";
- gapp->pageno = 1;
- gapp->rotate = 0;
- gapp->zoom = 1.0;
-
- gapp->gc = nil;
- gapp->xref = nil;
- gapp->pagetree = nil;
- gapp->page = nil;
- gapp->image = nil;
-
- fz_abort(error);
-}
-
-static void forkwork(void*(*func)(void*))
-{
- pthread_t tid;
- if (busy) return;
- pthread_create(&tid, NULL, func, nil);
-}
-
-static void* drawpage(void*args)
-{
- char msg[256];
- fz_error *error;
- float scalex, scaley, scale;
- fz_matrix ctm;
- fz_irect bbox;
- fz_obj *obj;
-
- if (!gapp->xref)
- return nil;
-
- busy = 1;
-
- while (gapp->rotate < 0)
- gapp->rotate += 360;
- gapp->rotate = gapp->rotate % 360;
-
- obj = pdf_getpageobject(gapp->pagetree, gapp->pageno - 1);
- if (obj == gapp->pageobj)
- goto Lskipload;
- gapp->pageobj = obj;
-
- if (gapp->page)
- pdf_droppage(gapp->page);
-
- gdk_threads_enter();
- sprintf(msg, " loading page %d ... ", gapp->pageno);
- showstatus(msg);
- gdk_threads_leave();
-
- error = pdf_loadpage(&gapp->page, gapp->xref, gapp->pageobj);
- if (error)
- panic(error);
-
-Lskipload:
-
- gdk_threads_enter();
- showstatus(" drawing ... ");
-
- ctm = fz_identity();
- ctm = fz_concat(ctm, fz_translate(0, -gapp->page->mediabox.max.y));
- ctm = fz_concat(ctm, fz_rotate(gapp->rotate + gapp->page->rotate));
- bbox = fz_roundrect(fz_transformaabb(ctm, gapp->page->mediabox));
-
- scale = gapp->zoom;
- scalex = scaley = 1.0;
-
- if (gapp->viewmode == FITWIDTH || gapp->viewmode == FITPAGE)
- {
- GtkAdjustment *hadj;
- int w;
- hadj = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(gapp->scroll));
- w = bbox.max.x - bbox.min.x;
- if (w != 0)
- scalex = hadj->page_size / (float)w;
- scale = scalex;
- }
-
- if (gapp->viewmode == FITPAGE)
- {
- GtkAdjustment *vadj;
- int h;
- vadj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(gapp->scroll));
- h = bbox.max.y - bbox.min.y;
- if (h != 0)
- scaley = vadj->page_size / (float)h;
- scale = MIN(scale, scaley);
- }
-
- gapp->zoom = scale;
-
- gdk_threads_leave();
-
- if (gapp->image)
- fz_droppixmap(gapp->image);
- gapp->image = nil;
-
- ctm = fz_identity();
- ctm = fz_concat(ctm, fz_translate(0, -gapp->page->mediabox.max.y));
- ctm = fz_concat(ctm, fz_scale(gapp->zoom, -gapp->zoom));
- ctm = fz_concat(ctm, fz_rotate(gapp->rotate + gapp->page->rotate));
- bbox = fz_roundrect(fz_transformaabb(ctm, gapp->page->mediabox));
-
- error = fz_rendertree(&gapp->image, gapp->gc, gapp->page->tree, ctm, bbox, 1);
- if (error)
- panic(error);
-
- gdk_threads_enter();
- sprintf(msg, " page %d of %d zoom %g rotate %d ",
- gapp->pageno, pdf_getpagecount(gapp->pagetree),
- gapp->zoom, gapp->rotate);
- showstatus(msg);
- gtk_widget_set_usize(gapp->canvas, gapp->image->w, gapp->image->h);
- gtk_widget_queue_draw(gapp->canvas);
- gdk_threads_leave();
-
- busy = 0;
-
- return nil;
-}
-
-static void* openpdf(void*args)
-{
- fz_error *error;
- char msg[256];
-
- busy = 1;
-
- gdk_threads_enter();
- sprintf(msg, " Loading %s...", gapp->filename);
- showstatus(msg);
- gdk_threads_leave();
-
- if (gapp->xref)
- {
- pdf_droppage(gapp->page);
- pdf_droppagetree(gapp->pagetree);
- pdf_closepdf(gapp->xref);
- gapp->page = nil;
- gapp->pagetree = nil;
- gapp->xref = nil;
- }
-
- error = pdf_openpdf(&gapp->xref, gapp->filename);
- if (error) panic(error);
-
- error = pdf_decryptpdf(gapp->xref);
- if (error) panic(error);
-
- /* TODO: ask for password */
- if (gapp->xref->crypt)
- {
- error = pdf_setpassword(gapp->xref->crypt, "");
- if (error) panic(error);
- }
-
- error = pdf_loadpagetree(&gapp->pagetree, gapp->xref);
- if (error) panic(error);
-
- gdk_threads_enter();
- showstatus("");
- gdk_threads_leave();
-
- gapp->pageno = 1;
- drawpage(nil);
-
- busy = 0;
-
- return nil;
-}
-
-/*
- * Handle event callbacks
- */
-
-static void onquit(GtkWidget *widget, void *data)
-{
- exit(0);
-}
-
-static void onopenokay(GtkWidget *w, GtkFileSelection *fs)
-{
- gapp->filename = strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
- gtk_widget_destroy(GTK_WIDGET(fs));
- forkwork(openpdf);
-}
-
-static void onopen(GtkWidget *widget, void *data)
-{
- GtkWidget *filew;
- if (busy) return;
- filew = gtk_file_selection_new ("Open PDF file");
- gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filew)->ok_button),
- "clicked", (GtkSignalFunc)onopenokay, filew);
- gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(filew)->cancel_button),
- "clicked", (GtkSignalFunc)gtk_widget_destroy, GTK_OBJECT(filew));
- gtk_widget_show(filew);
-}
-
-static void oninfo(GtkWidget *widget, void *data)
-{
-}
-
-static void onback10(GtkWidget *widget, void *data)
-{
- if (busy) return;
- if (!gapp->xref) return;
- gapp->pageno -= 10;
- if (gapp->pageno < 1)
- gapp->pageno = 1;
- forkwork(drawpage);
-}
-
-static void onnext10(GtkWidget *widget, void *data)
-{
- if (busy) return;
- if (!gapp->xref) return;
- gapp->pageno += 10;
- if (gapp->pageno > pdf_getpagecount(gapp->pagetree))
- gapp->pageno = pdf_getpagecount(gapp->pagetree);
- forkwork(drawpage);
-}
-
-static void onback(GtkWidget *widget, void *data)
-{
- if (busy) return;
- if (!gapp->xref) return;
- if (gapp->pageno > 1)
- {
- gapp->pageno --;
- forkwork(drawpage);
- }
-}
-
-static void onnext(GtkWidget *widget, void *data)
-{
- if (busy) return;
- if (!gapp->xref) return;
- if (gapp->pageno < pdf_getpagecount(gapp->pagetree))
- {
- gapp->pageno ++;
- forkwork(drawpage);
- }
-}
-
-static void onfirst(GtkWidget *widget, void *data)
-{
- if (busy) return;
- if (!gapp->xref) return;
- gapp->pageno = 1;
- forkwork(drawpage);
-}
-
-static void onlast(GtkWidget *widget, void *data)
-{
- if (busy) return;
- if (!gapp->xref) return;
- gapp->pageno = pdf_getpagecount(gapp->pagetree);
- forkwork(drawpage);
-}
-
-static void onzoomin(GtkWidget * widget, void *data)
-{
- gapp->viewmode = ZOOM;
- gapp->zoom *= 1.25;
- forkwork(drawpage);
-}
-
-static void onzoomout(GtkWidget * widget, void *data)
-{
- gapp->viewmode = ZOOM;
- gapp->zoom *= 0.8;
- forkwork(drawpage);
-}
-
-static void onzoom100(GtkWidget * widget, void *data)
-{
- gapp->viewmode = ZOOM;
- gapp->zoom = 1.0;
- forkwork(drawpage);
-}
-
-static void onrotl(GtkWidget *widget, void *data) { gapp->rotate -= 90; forkwork(drawpage); }
-static void onrotr(GtkWidget *widget, void *data) { gapp->rotate += 90; forkwork(drawpage); }
-
-static void onfitwidth(GtkWidget *widget, void *data)
-{
- gapp->viewmode = FITWIDTH;
- forkwork(drawpage);
-}
-
-static void onfitpage(GtkWidget *widget, void *data)
-{
- gapp->viewmode = FITPAGE;
- forkwork(drawpage);
-}
-
-static int startxpos;
-static int startypos;
-static int dopan = 0;
-guint32 pangrabtime = 0;
-
-static void mousedown(GtkWidget *widget, GdkEventMotion *event, void *data)
-{
- GdkModifierType mods;
- gtk_widget_grab_focus(gapp->scroll);
-
- gdk_window_get_pointer(gapp->scroll->window, &startxpos, &startypos, &mods);
- if (mods & GDK_BUTTON2_MASK) {
- GtkAdjustment *adj;
- adj = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(gapp->scroll));
- startxpos += adj->value;
-
- adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(gapp->scroll));
- startypos += adj->value;
-
- gdk_pointer_grab(gapp->scroll->window, TRUE, GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, NULL, NULL /* TODO: pan cursor */, event->time);
-
- dopan = 1;
- }
- else {
- dopan = 0;
- }
-}
-
-static void mouseup(GtkWidget *widget, GdkEventMotion *event, void *data)
-{
- dopan = 0;
- gdk_pointer_ungrab(event->time);
-}
-
-static void mousemove(GtkWidget *widget, GdkEventMotion *event, void *data)
-{
- int xpos, ypos;
- GdkModifierType mods;
- GtkAdjustment *adj;
-
- if (!dopan) return;
-
- gdk_window_get_pointer(gapp->scroll->window, &xpos, &ypos, &mods);
-
- if (mods & GDK_BUTTON2_MASK) {
- adj = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(gapp->scroll));
- adj->value = startxpos - xpos;
- adj->value = CLAMP(adj->value, adj->lower, adj->upper - adj->page_size);
-
- gtk_adjustment_value_changed(adj);
-
- adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(gapp->scroll));
- adj->value = startypos - ypos;
- adj->value = CLAMP(adj->value, adj->lower, adj->upper - adj->page_size);
-
- /* clamp to viewport... */
-
- gtk_adjustment_value_changed(adj);
- }
- else
- mouseup(widget, event, data);
-}
-
-static void keypress(GtkWidget *widget, GdkEventKey *event, void *data)
-{
- if (busy) return;
- switch (event->string[0])
- {
- case 'q': onquit(widget, data); break;
- case 'g': onlast(widget, data); break;
- case '0': onfirst(widget, data); break;
- case 'b': onback(widget, data); break;
- case 'B': onback10(widget, data); break;
- case ' ': onnext(widget, data); break;
- case 'f': onnext(widget, data); break;
- case 'F': onnext10(widget, data); break;
- case '+': onzoomin(widget, data); break;
- case '-': onzoomout(widget, data); break;
- case '1': onzoom100(widget, data); break;
- case 'l': onrotl(widget, data); break;
- case 'r': onrotr(widget, data); break;
- case 'L': gapp->rotate -= 15; forkwork(drawpage); break;
- case 'R': gapp->rotate += 15; forkwork(drawpage); break;
- }
-}
-
-static void onexpose(GtkWidget *widget, GdkEventExpose *event, void *data)
-{
- PDFApp *app = data;
- if (app->image)
- {
- int x0 = event->area.x;
- int y0 = event->area.y;
- int w = event->area.width;
- int h = event->area.height;
- int x1, y1;
- int x, y;
-
- unsigned char *rgb = fz_malloc(w * h * 3);
- unsigned char *s, *d;
-
- x1 = MIN(x0 + w, app->image->w);
- y1 = MIN(y0 + h, app->image->h);
-
- if (x0 + w > x1 || y0 + h > y1)
- memset(rgb, 200, w * h * 3);
-
- for (y = y0; y < y1; y++)
- {
- s = app->image->samples + (y * app->image->w + x0) * 4;
- d = rgb + (y - y0) * w * 3;
- for (x = x0; x < x1; x++)
- {
- d[0] = s[1];
- d[1] = s[2];
- d[2] = s[3];
- s += 4;
- d += 3;
- }
- }
-
- gdk_draw_rgb_image(widget->window,
- widget->style->black_gc,
- x0, y0, w, h,
- GDK_RGB_DITHER_NONE, rgb,
- w * 3);
-
- fz_free(rgb);
- }
-}
-
-/*
- * Construct widgets
- */
-
-static GtkWidget *
-addmenuitem(GtkWidget *menu, const char *name, GtkSignalFunc callback,
- void *callback_data, GtkAccelGroup *ag, const char *accel)
-{
- GtkWidget *menuitem;
- menuitem = gtk_menu_item_new_with_label(name);
- gtk_menu_append(GTK_MENU(menu), menuitem);
- gtk_widget_show(menuitem);
- if (accel != NULL)
- {
- guint accel_key, accel_mods;
- gtk_accelerator_parse(accel, &accel_key, &accel_mods);
- gtk_widget_add_accelerator(menuitem, "activate", ag,
- accel_key, accel_mods, GTK_ACCEL_VISIBLE);
- }
- gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
- (GtkSignalFunc)callback, callback_data);
- return menuitem;
-}
-
-static void
-addmenuseparator(GtkWidget *menu)
-{
- GtkWidget *menuitem;
- menuitem = gtk_menu_item_new();
- gtk_menu_append(GTK_MENU(menu), menuitem);
- gtk_widget_show(menuitem);
-}
-
-void makeapp(PDFApp *app)
-{
- GtkWidget *frame;
- GtkWidget *menubar;
- GtkWidget *menu;
- GtkWidget *menuitem;
- GtkWidget *da;
- GtkWidget *sb;
- GtkWidget *sv;
- GtkWidget *vbox;
- GtkAccelGroup *ag;
- void *data = app;
-
- frame = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_signal_connect(GTK_OBJECT(frame), "destroy", (GtkSignalFunc)onquit, "WM destroy");
- gtk_window_set_title(GTK_WINDOW(frame), "MuPDF");
- gtk_widget_set_usize(GTK_WIDGET(frame), 300, 200);
-
- vbox = gtk_vbox_new(FALSE, 1);
- gtk_container_add(GTK_CONTAINER(frame), vbox);
- gtk_widget_show(vbox);
-
- menubar = gtk_menu_bar_new();
- ag = gtk_accel_group_new();
- gtk_window_add_accel_group(GTK_WINDOW(frame), ag);
- gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
- gtk_widget_show(menubar);
-
- menu = gtk_menu_new();
- menuitem = gtk_menu_item_new_with_label("File");
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu);
- gtk_menu_bar_append(GTK_MENU_BAR(menubar), menuitem);
- gtk_widget_show(menuitem);
- gtk_menu_set_accel_group(GTK_MENU(menu), ag);
- addmenuitem(menu, "Info...", (GtkSignalFunc)oninfo, data, ag, "<ctrl>I");
- addmenuitem(menu, "Open...", (GtkSignalFunc)onopen, data, ag, "<ctrl>O");
- addmenuseparator(menu);
- addmenuitem(menu, "Quit", (GtkSignalFunc)onquit, data, ag, "<ctrl>Q");
-
- menu = gtk_menu_new();
- menuitem = gtk_menu_item_new_with_label("Go");
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu);
- gtk_menu_bar_append(GTK_MENU_BAR(menubar), menuitem);
- gtk_widget_show(menuitem);
- gtk_menu_set_accel_group(GTK_MENU(menu), ag);
- addmenuitem(menu, "Back", (GtkSignalFunc)onback10, data, ag, "<ctrl>B");
- addmenuitem(menu, "Next", (GtkSignalFunc)onnext10, data, ag, "<ctrl>F");
- addmenuitem(menu, "Back 10", (GtkSignalFunc)onback10, data, ag, nil);
- addmenuitem(menu, "Next 10", (GtkSignalFunc)onnext10, data, ag, nil);
- addmenuseparator(menu);
- addmenuitem(menu, "First", (GtkSignalFunc)onfirst, data, ag, nil);
- addmenuitem(menu, "Last", (GtkSignalFunc)onlast, data, ag, "<ctrl>G");
-
- menu = gtk_menu_new();
- menuitem = gtk_menu_item_new_with_label("View");
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu);
- gtk_menu_bar_append(GTK_MENU_BAR(menubar), menuitem);
- gtk_widget_show(menuitem);
- gtk_menu_set_accel_group(GTK_MENU(menu), ag);
- addmenuitem(menu, "Zoom in", (GtkSignalFunc)onzoomin, data, ag, "<ctrl>'+'");
- addmenuitem(menu, "Zoom out", (GtkSignalFunc)onzoomout, data, ag, "<ctrl>'-'");
- addmenuitem(menu, "Zoom 100%", (GtkSignalFunc)onzoom100, data, ag, "<ctrl>1");
- addmenuitem(menu, "Fit width", (GtkSignalFunc)onfitwidth, data, ag, nil);
- addmenuitem(menu, "Fit page", (GtkSignalFunc)onfitpage, data, ag, nil);
- addmenuseparator(menu);
- addmenuitem(menu, "Rotate left", (GtkSignalFunc)onrotl, data, ag, "<ctrl>L");
- addmenuitem(menu, "Rotate right", (GtkSignalFunc)onrotr, data, ag, "<ctrl>R");
-
- sv = gtk_scrolled_window_new(NULL, NULL);
- app->scroll = sv;
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sv), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- GTK_WIDGET_SET_FLAGS(sv, GTK_CAN_FOCUS);
- gtk_widget_set_extension_events(sv, GDK_EXTENSION_EVENTS_ALL);
- gtk_signal_connect(GTK_OBJECT(sv), "button_press_event", (GtkSignalFunc)mousedown, data);
- gtk_signal_connect(GTK_OBJECT(sv), "motion_notify_event", (GtkSignalFunc)mousemove, data);
- gtk_signal_connect(GTK_OBJECT(sv), "button_release_event", (GtkSignalFunc)mouseup, data);
- gtk_signal_connect(GTK_OBJECT(sv), "key_press_event", (GtkSignalFunc)keypress, data);
- gtk_box_pack_start(GTK_BOX(vbox), sv, TRUE, TRUE, 0);
- gtk_widget_show(sv);
-
- da = gtk_drawing_area_new();
- app->canvas = da;
- gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sv), da);
- gtk_signal_connect(GTK_OBJECT(da), "expose_event", (GtkSignalFunc)onexpose, data);
- gtk_widget_set_events (da,
- GDK_BUTTON_PRESS_MASK
- | GDK_BUTTON_RELEASE_MASK
- | GDK_POINTER_MOTION_MASK);
- gtk_widget_show(da);
-
- sb = gtk_statusbar_new();
- app->status = sb;
- app->statusid = gtk_statusbar_get_context_id(GTK_STATUSBAR(sb), "mupdf");
- gtk_box_pack_start(GTK_BOX(vbox), sb, FALSE, FALSE, 0);
- gtk_widget_show(sb);
-
- gtk_window_set_default_size(GTK_WINDOW(frame), 512, 512);
- gtk_widget_grab_focus(sv);
- gtk_widget_show(frame);
-}
-
-int main(int argc, char **argv)
-{
- fz_error *error;
- PDFApp theapp;
-
- g_thread_init(NULL);
- gtk_init(&argc, &argv);
- gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
- gtk_widget_set_default_visual(gdk_rgb_get_visual());
-
- makeapp(&theapp);
- gapp = &theapp;
-
- gapp->pageno = 1;
- gapp->rotate = 0;
- gapp->zoom = 1.0;
-
- gapp->image = nil;
- gapp->xref = nil;
- gapp->pagetree = nil;
- gapp->page = nil;
-
- fz_cpudetect();
- fz_accelerate();
-
- error = fz_newrenderer(&gapp->gc, pdf_devicergb, 0, 1024 * 512);
- if (error)
- fz_abort(error);
-
- if (argc > 1)
- {
- gapp->filename = argv[1];
- forkwork(openpdf);
- }
-
- gdk_threads_enter();
- gtk_main();
- gdk_threads_leave();
- return 0;
-}
-