From 54149584f1e77021a4e34e892dc0761a97bd851d Mon Sep 17 00:00:00 2001 From: Moritz Lipp Date: Sat, 29 Aug 2009 16:07:58 +0200 Subject: [PATCH] Printing, Image and attachment export Added following functionality: * Save images * Save attachments * Simple printing support Fixes and other changes: * Additional rectangle calculation function * Search and link clicking fix Other: * Added license file --- LICENSE | 21 +++++ README | 9 +-- config.h | 5 +- zathura.c | 226 ++++++++++++++++++++++++++++++++++++++++++------------ 4 files changed, 204 insertions(+), 57 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8f3c571 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) 2009 ML, JY + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + diff --git a/README b/README index 794abdb..5659d45 100644 --- a/README +++ b/README @@ -1,12 +1,11 @@ zathura - pdf viewer -------------------- -zathura is an pdf viewer based on the poppler pdf rendering library +zathura is a pdf viewer based on the poppler pdf rendering library Requirements ------------ -poppler (0.10.7-2) -poppler-glib (0.10.7-1) -gtk2 (2.16.5-1) +poppler-glib (0.10.7) +gtk2 (2.17.2) Configuration ------------- @@ -30,5 +29,3 @@ Use zathura Just run: zathura - - diff --git a/config.h b/config.h index d8c4e3d..373c11e 100644 --- a/config.h +++ b/config.h @@ -6,7 +6,7 @@ static const int SHOW_NOTIFICATION = 5; static const int DEFAULT_WIDTH = 800; static const int DEFAULT_HEIGHT = 600; static const char BROWSER[] = "firefox %s"; - +static const char PRINTER[] = "EPSON_AL-CX11_192.168.88.80"; /* look */ static const char font[] = "monospace normal 9"; static const char default_bgcolor[] = "#000000"; @@ -39,7 +39,7 @@ Shortcut shortcuts[] = { {GDK_CONTROL_MASK, GDK_0, sc_zoom, { ZOOM_ORIGINAL } }, {GDK_CONTROL_MASK, GDK_r, sc_rotate, { RIGHT } }, {GDK_CONTROL_MASK, GDK_e, sc_rotate, { LEFT } }, - {GDK_CONTROL_MASK, GDK_p, sc_print, {0} }, + {GDK_CONTROL_MASK, GDK_p, sc_focus_inputbar, { .data = ":print all" } }, {GDK_CONTROL_MASK, GDK_q, sc_quit, {0} }, {0, GDK_n, sc_search, { FORWARD } }, {0, GDK_N, sc_search, { BACKWARD } }, @@ -67,6 +67,7 @@ Command commands[] = { {"info", cmd_info}, {"links", cmd_links}, {"open", cmd_open}, + {"print", cmd_print}, {"rotate", cmd_rotate}, {"quit", cmd_quit}, {"zoom", cmd_zoom}, diff --git a/zathura.c b/zathura.c index bdfa90a..01f690c 100644 --- a/zathura.c +++ b/zathura.c @@ -13,8 +13,8 @@ /* enums */ enum { UP, DOWN, LEFT, RIGHT, ZOOM_IN, ZOOM_OUT, ZOOM_ORIGINAL, - NEXT, PREVIOUS, HIDE, ERROR, WARNING, DEFAULT, TOP, BOTTOM, - ADJUST_BESTFIT, ADJUST_WIDTH, FORWARD, BACKWARD }; + NEXT, PREVIOUS, HIDE, ERROR, WARNING, DEFAULT, TOP, BOTTOM, + ADJUST_BESTFIT, ADJUST_WIDTH, FORWARD, BACKWARD }; struct { @@ -87,6 +87,8 @@ void set_page(int); void draw(); void highlight_result(PopplerRectangle*); void open_link(char*); +void save_images(int, char*); +void save_attachments(char*); gboolean complete(Argument*); gboolean delete_widget(gpointer); @@ -94,6 +96,8 @@ gboolean delete_widget(gpointer); GtkWidget* notify(int, char*); GtkWidget* update_notification(GtkWidget*, int, char*); +PopplerRectangle* recalcRectangle(PopplerRectangle*); + /* shortcut declarations */ void sc_focus_inputbar(Argument*); void sc_scroll(Argument*); @@ -102,7 +106,6 @@ void sc_zoom(Argument*); void sc_adjust_window(Argument*); void sc_rotate(Argument*); void sc_search(Argument*); -void sc_print(Argument*); void sc_quit(Argument*); /* command declarations */ @@ -111,6 +114,7 @@ void cmd_goto(int, char**); void cmd_info(int, char**); void cmd_links(int, char**); void cmd_open(int, char**); +void cmd_print(int, char**); void cmd_rotate(int, char**); void cmd_quit(int, char**); void cmd_zoom(int, char**); @@ -258,7 +262,6 @@ update_notification(GtkWidget* view, int level, char* text) { gtk_widget_modify_fg(GTK_WIDGET(message), GTK_STATE_NORMAL, &(Zathura.Settings.notification_fg)); gtk_widget_modify_bg(GTK_WIDGET(view), GTK_STATE_NORMAL, &(Zathura.Settings.notification_bg)); - } if(gtk_bin_get_child(GTK_BIN(view))) @@ -269,6 +272,47 @@ update_notification(GtkWidget* view, int level, char* text) return GTK_WIDGET(view); } +PopplerRectangle* +recalcRectangle(PopplerRectangle* rectangle) +{ + double page_width, page_height; + double x1 = rectangle->x1; + double x2 = rectangle->x2; + double y1 = rectangle->y1; + double y2 = rectangle->y2; + + poppler_page_get_size(Zathura.PDF.page, &page_width, &page_height); + + switch(Zathura.PDF.rotate) + { + case 90: + rectangle->x1 = (page_height - y2) * Zathura.PDF.scale; + rectangle->y1 = x1 * Zathura.PDF.scale; + rectangle->x2 = (page_height - y1) * Zathura.PDF.scale; + rectangle->y2 = x2 * Zathura.PDF.scale; + break; + case 180: + rectangle->x1 = (page_width - x2) * Zathura.PDF.scale; + rectangle->y1 = (page_height - y2) * Zathura.PDF.scale; + rectangle->x2 = (page_width - x1) * Zathura.PDF.scale; + rectangle->y2 = (page_height - y1) * Zathura.PDF.scale; + break; + case 270: + rectangle->x1 = y1 * Zathura.PDF.scale; + rectangle->y1 = (page_width - x2) * Zathura.PDF.scale; + rectangle->x2 = y2 * Zathura.PDF.scale; + rectangle->y2 = (page_width - x1) * Zathura.PDF.scale; + break; + default: + rectangle->x1 = x1 * Zathura.PDF.scale; + rectangle->y1 = y1 * Zathura.PDF.scale; + rectangle->x2 = x2 * Zathura.PDF.scale; + rectangle->y2 = y2 * Zathura.PDF.scale; + } + + return rectangle; +} + void update_status() { @@ -361,34 +405,13 @@ draw() void highlight_result(PopplerRectangle* rectangle) { - double page_height, page_width; - double width, height; - double scale; - - poppler_page_get_size(Zathura.PDF.page, &page_width, &page_height); - scale = Zathura.PDF.scale; - width = (rectangle->x2 - rectangle->x1) * scale; - height = (rectangle->y2 - rectangle->y1) * scale; - cairo_t *cairo = cairo_create(Zathura.PDF.surface); cairo_set_source_rgba(cairo, Zathura.Settings.search_highlight.red, Zathura.Settings.search_highlight.green, Zathura.Settings.search_highlight.blue, HL_TRANSPARENCY); - switch(Zathura.PDF.rotate) - { - case 90: - cairo_rectangle(cairo, scale * rectangle->y1, scale * rectangle->x1, height, width); - break; - case 180: - cairo_rectangle(cairo, scale * (page_width - rectangle->x1) - width, scale * rectangle->y1, width, height); - break; - case 270: - cairo_rectangle(cairo, scale * (page_height - rectangle->y1) - height, scale * (page_width - rectangle->x1) - width, height, width); - break; - default: - cairo_rectangle(cairo, scale * rectangle->x1, scale * (page_height - rectangle->y1) - height, width, height); - } - + rectangle = recalcRectangle(rectangle); + + cairo_rectangle(cairo, rectangle->x1, rectangle->y1, (rectangle->x2 - rectangle->x1), (rectangle->y2 - rectangle->y1)); cairo_fill(cairo); } @@ -399,6 +422,57 @@ open_link(char* link) system(start_browser); } +void +save_images(int page, char* directory) +{ + GList *image_list; + GList *images; + cairo_surface_t *image; + PopplerPage *document_page; + + document_page = poppler_document_get_page(Zathura.PDF.document, page); + image_list = poppler_page_get_image_mapping(document_page); + + for(images = image_list; images; images = g_list_next(images)) + { + PopplerImageMapping *image_mapping; + PopplerRectangle image_field; + gint image_id; + char* file; + + image_mapping = (PopplerImageMapping*) images->data; + image_field = image_mapping->area; + image_id = image_mapping->image_id; + + image = poppler_page_get_image(document_page, image_id); + file = g_strdup_printf("%sp%i_i%i.png", directory, page + 1, image_id); + + cairo_surface_write_to_png(image, file); + + g_free(file); + } +} + +void +save_attachments(char* directory) +{ + GList *attachment_list; + GList *attachments; + char *file; + + attachment_list = poppler_document_get_attachments(Zathura.PDF.document); + + for(attachments = attachment_list; attachments; attachments = g_list_next(attachments)) + { + PopplerAttachment *attachment = (PopplerAttachment*) attachments->data; + file = g_strdup_printf("%s%s", directory, attachment->name); + + poppler_attachment_save(attachment, file, NULL); + + g_free(file); + } +} + gboolean delete_widget(gpointer data) { @@ -661,6 +735,8 @@ sc_search(Argument *argument) /* draw results */ if(results) { + double page_width, page_height; + poppler_page_get_size(Zathura.PDF.page, &page_width, &page_height); draw(); update_notification(GTK_WIDGET(search_status), DEFAULT, g_strdup_printf("%s found on page %i for %i time(s)", @@ -668,19 +744,16 @@ sc_search(Argument *argument) for(list = results; list && list->data; list = g_list_next(list)) { - highlight_result((PopplerRectangle*) list->data); + PopplerRectangle* result = (PopplerRectangle*) list->data; + result->y1 = page_height - result->y1; + result->y2 = page_height - result->y2; + highlight_result(result); } } else update_notification(search_status, DEFAULT, g_strdup_printf("No match for %s", search_item)); } -void -sc_print(Argument *argument) -{ - -} - void sc_quit(Argument *argument) { @@ -719,30 +792,78 @@ cmd_open(int argc, char** argv) set_page(0); draw(); - + update_status(); update_title(); } +void +cmd_print(int argc, char** argv) +{ + if(argc == 0 || !Zathura.PDF.document) + return; + + char* print_command; + char* sites; + + if(strcmp(argv[0], "all") == 0) + sites = g_strdup_printf("%i", Zathura.PDF.number_of_pages); + else + sites = argv[0]; + + print_command = g_strdup_printf("lp -d '%s' -P %s %s", PRINTER, sites, Zathura.PDF.file); + + system(print_command); +} + void cmd_export(int argc, char** argv) { - if(argc == 0) + if(argc == 0 || !Zathura.PDF.document) return; - if(strcmp(argv[0], "image") == 0) + if(argc < 2) { - + notify(WARNING, "No export path specified"); + return; } - else if(strcmp(argv[0], "links") == 0) + + /* export images */ + if(strcmp(argv[0], "images") == 0) { + int page_counter; + + if(argc == 3) + { + int page_number = atoi(argv[2]) - 1; + if(page_number < 0 || page_number > Zathura.PDF.number_of_pages) + notify(WARNING, "Page does not exist"); + else + save_images(page_number, argv[1]); + + return; + } + + for(page_counter = 0; page_counter < Zathura.PDF.number_of_pages; page_counter++) + { + save_images(page_counter, argv[1]); + } } + + /* export attachments */ else if(strcmp(argv[0], "attachments") == 0) { - + if(!poppler_document_has_attachments(Zathura.PDF.document)) + notify(WARNING, "PDF file has no attachments"); + else + save_attachments(argv[1]); + } + else + { + notify(DEFAULT, "export [images|attachments]"); + return; } - } void @@ -889,6 +1010,7 @@ cb_draw(GtkWidget *widget, gpointer data) void cb_destroy(GtkWidget *widget, gpointer data) { + pango_font_description_free(Zathura.Settings.font); gtk_main_quit(); } @@ -994,16 +1116,22 @@ cb_drawing_area_button_pressed(GtkWidget* widget, GdkEventButton* event, gpointe { double page_width, page_height; poppler_page_get_size(Zathura.PDF.page, &page_width, &page_height); + PopplerRectangle* link_rectangle = &link_mapping->area; + if(Zathura.PDF.rotate == 0 || Zathura.PDF.rotate == 180) + event->y = page_height - event->y; + else if(Zathura.PDF.rotate == 90 || Zathura.PDF.rotate == 270) + event->x = page_height - event->x; + + link_rectangle = recalcRectangle(link_rectangle); + // check if click is in url area - if( (link_mapping->area.x1 <= event->x) - && (link_mapping->area.x2 >= event->x) - && (link_mapping->area.y1 <= (page_height - event->y)) - && (link_mapping->area.y2 >= (page_height - event->y)) - ) - { + if( (link_rectangle->x1 <= event->x) + && (link_rectangle->x2 >= event->x) + && (link_rectangle->y1 <= event->y) + && (link_rectangle->y2 >= event->y) + ) open_link(action->uri.uri); - } } }