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
This commit is contained in:
Moritz Lipp 2009-08-29 16:07:58 +02:00
parent 01e613adc0
commit 54149584f1
4 changed files with 204 additions and 57 deletions

21
LICENSE Normal file
View file

@ -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.

9
README
View file

@ -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 <file>

View file

@ -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},

228
zathura.c
View file

@ -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)
{
@ -725,24 +798,72 @@ cmd_open(int argc, char** argv)
}
void
cmd_export(int argc, char** argv)
cmd_print(int argc, char** argv)
{
if(argc == 0)
if(argc == 0 || !Zathura.PDF.document)
return;
if(strcmp(argv[0], "image") == 0)
{
char* print_command;
char* sites;
}
else if(strcmp(argv[0], "links") == 0)
{
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 || !Zathura.PDF.document)
return;
if(argc < 2)
{
notify(WARNING, "No export path specified");
return;
}
/* 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);
}
}
}