Commit 748f626e authored by Moritz Lipp's avatar Moritz Lipp

Merge branch 'release/0.2.8'

parents 309bc0d4 82caf6bd
Pipeline #93 skipped
......@@ -7,7 +7,7 @@ Requirements
------------
zathura (>= 0.2.0)
girara
mupdf (>= 1.3)
mupdf (>= 1.7)
openjpeg (>= 2.0)
Installation
......
......@@ -2,7 +2,7 @@
VERSION_MAJOR = 0
VERSION_MINOR = 2
VERSION_REV = 7
VERSION_REV = 8
VERSION = ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REV}
# minimum required zathura version
......
......@@ -6,8 +6,12 @@
#include <mupdf/xps.h>
#include <mupdf/pdf.h>
#include <glib-2.0/glib.h>
#include "plugin.h"
#define LENGTH(x) (sizeof(x)/sizeof((x)[0]))
zathura_error_t
pdf_document_open(zathura_document_t* document)
{
......@@ -34,11 +38,9 @@ pdf_document_open(zathura_document_t* document)
const char* password = zathura_document_get_password(document);
fz_try(mupdf_document->ctx){
if (strstr(path, ".xps") != 0 || strstr(path, ".XPS") != 0 || strstr(path, ".rels") != 0) {
mupdf_document->document = (fz_document*) xps_open_document(mupdf_document->ctx, (char*) path);
} else {
mupdf_document->document = (fz_document*) pdf_open_document(mupdf_document->ctx, (char*) path);
}
fz_register_document_handlers(mupdf_document->ctx);
mupdf_document->document = fz_open_document(mupdf_document->ctx, path);
}
fz_catch(mupdf_document->ctx){
error = ZATHURA_ERROR_UNKNOWN;
......@@ -51,14 +53,14 @@ pdf_document_open(zathura_document_t* document)
}
/* authenticate if password is required and given */
if (fz_needs_password(mupdf_document->document) != 0) {
if (password == NULL || fz_authenticate_password(mupdf_document->document, (char*) password) == 0) {
if (fz_needs_password(mupdf_document->ctx, mupdf_document->document) != 0) {
if (password == NULL || fz_authenticate_password(mupdf_document->ctx, mupdf_document->document, (char*) password) == 0) {
error = ZATHURA_ERROR_INVALID_PASSWORD;
goto error_free;
}
}
zathura_document_set_number_of_pages(document, fz_count_pages(mupdf_document->document));
zathura_document_set_number_of_pages(document, fz_count_pages(mupdf_document->ctx, mupdf_document->document));
zathura_document_set_data(document, mupdf_document);
return error;
......@@ -67,10 +69,10 @@ error_free:
if (mupdf_document != NULL) {
if (mupdf_document->document != NULL) {
fz_close_document(mupdf_document->document);
fz_drop_document(mupdf_document->ctx, mupdf_document->document);
}
if (mupdf_document->ctx != NULL) {
fz_free_context(mupdf_document->ctx);
fz_drop_context(mupdf_document->ctx);
}
free(mupdf_document);
......@@ -90,8 +92,8 @@ pdf_document_free(zathura_document_t* document, mupdf_document_t* mupdf_document
return ZATHURA_ERROR_INVALID_ARGUMENTS;
}
fz_close_document(mupdf_document->document);
fz_free_context(mupdf_document->ctx);
fz_drop_document(mupdf_document->ctx, mupdf_document->document);
fz_drop_context(mupdf_document->ctx);
free(mupdf_document);
zathura_document_set_data(document, NULL);
......@@ -112,7 +114,7 @@ pdf_document_save_as(zathura_document_t* document, mupdf_document_t*
* options. */
fz_write_options opts = { 0 }; /* just use the default options */
fz_write_document(mupdf_document->document, (char*) path, &opts);
fz_write_document(mupdf_document->ctx, mupdf_document->document, (char*) path, &opts);
} fz_catch (mupdf_document->ctx) {
return ZATHURA_ERROR_UNKNOWN;
}
......@@ -120,3 +122,97 @@ pdf_document_save_as(zathura_document_t* document, mupdf_document_t*
return ZATHURA_ERROR_OK;
}
girara_list_t*
pdf_document_get_information(zathura_document_t* document, mupdf_document_t*
mupdf_document, zathura_error_t* error)
{
if (document == NULL || mupdf_document == NULL || error == NULL) {
if (error != NULL) {
*error = ZATHURA_ERROR_INVALID_ARGUMENTS;
}
}
girara_list_t* list = zathura_document_information_entry_list_new();
if (list == NULL) {
if (error != NULL) {
*error = ZATHURA_ERROR_UNKNOWN;
}
return NULL;
}
fz_try (mupdf_document->ctx) {
pdf_obj* trailer = pdf_trailer(mupdf_document->ctx, (pdf_document*) mupdf_document->document);
pdf_obj* info_dict = pdf_dict_get(mupdf_document->ctx, trailer, PDF_NAME_Info);
/* get string values */
typedef struct info_value_s {
const char* property;
zathura_document_information_type_t type;
} info_value_t;
static const info_value_t string_values[] = {
{ "Title", ZATHURA_DOCUMENT_INFORMATION_TITLE },
{ "Author", ZATHURA_DOCUMENT_INFORMATION_AUTHOR },
{ "Subject", ZATHURA_DOCUMENT_INFORMATION_SUBJECT },
{ "Keywords", ZATHURA_DOCUMENT_INFORMATION_KEYWORDS },
{ "Creator", ZATHURA_DOCUMENT_INFORMATION_CREATOR },
{ "Producer", ZATHURA_DOCUMENT_INFORMATION_PRODUCER }
};
for (unsigned int i = 0; i < LENGTH(string_values); i++) {
pdf_obj* value = pdf_dict_gets(mupdf_document->ctx, info_dict, string_values[i].property);
if (value == NULL) {
continue;
}
char* str_value = pdf_to_str_buf(mupdf_document->ctx, value);
if (str_value == NULL || strlen(str_value) == 0) {
continue;
}
zathura_document_information_entry_t* entry =
zathura_document_information_entry_new(
string_values[i].type,
str_value
);
if (entry != NULL) {
girara_list_append(list, entry);
}
}
static const info_value_t time_values[] = {
{ "CreationDate", ZATHURA_DOCUMENT_INFORMATION_CREATION_DATE },
{ "ModDate", ZATHURA_DOCUMENT_INFORMATION_MODIFICATION_DATE }
};
for (unsigned int i = 0; i < LENGTH(time_values); i++) {
pdf_obj* value = pdf_dict_gets(mupdf_document->ctx, info_dict, time_values[i].property);
if (value == NULL) {
continue;
}
char* str_value = pdf_to_str_buf(mupdf_document->ctx, value);
if (str_value == NULL || strlen(str_value) == 0) {
continue;
}
zathura_document_information_entry_t* entry =
zathura_document_information_entry_new(
time_values[i].type,
str_value // FIXME: Convert to common format
);
if (entry != NULL) {
girara_list_append(list, entry);
}
}
} fz_catch (mupdf_document->ctx) {
if (error != NULL) {
*error = ZATHURA_ERROR_UNKNOWN;
}
return NULL;
}
return list;
}
......@@ -7,10 +7,9 @@
#include <mupdf/pdf.h>
#include "plugin.h"
#include "utils.h"
static void pdf_zathura_image_free(zathura_image_t* image);
static void get_images(pdf_obj* dict, girara_list_t* list);
static void get_resources(pdf_obj* resource, girara_list_t* list);
girara_list_t*
pdf_page_images_get(zathura_page_t* page, mupdf_page_t* mupdf_page, zathura_error_t* error)
......@@ -30,16 +29,7 @@ pdf_page_images_get(zathura_page_t* page, mupdf_page_t* mupdf_page, zathura_erro
mupdf_document_t* mupdf_document = zathura_document_get_data(document);
pdf_obj* page_object = pdf_load_object((pdf_document*) mupdf_document->document, zathura_page_get_index(page), 0);
if (page_object == NULL) {
goto error_free;
}
pdf_obj* resource = pdf_dict_gets(page_object, "Resources");
if (resource == NULL) {
goto error_free;
}
/* Setup image list */
list = girara_list_new();
if (list == NULL) {
if (error != NULL) {
......@@ -50,7 +40,25 @@ pdf_page_images_get(zathura_page_t* page, mupdf_page_t* mupdf_page, zathura_erro
girara_list_set_free_function(list, (girara_free_function_t) pdf_zathura_image_free);
get_resources(resource, list);
/* Extract images */
mupdf_page_extract_text(mupdf_document, mupdf_page);
fz_page_block* block;
for (block = mupdf_page->text->blocks; block < mupdf_page->text->blocks + mupdf_page->text->len; block++) {
if (block->type == FZ_PAGE_BLOCK_IMAGE) {
fz_image_block *image_block = block->u.image;
zathura_image_t* zathura_image = g_malloc(sizeof(zathura_image_t));
zathura_image->position.x1 = image_block->bbox.x0;
zathura_image->position.y1 = image_block->bbox.y0;
zathura_image->position.x2 = image_block->bbox.x1;
zathura_image->position.y2 = image_block->bbox.y1;
zathura_image->data = image_block->image;
girara_list_append(list, zathura_image);
}
}
return list;
......@@ -69,85 +77,82 @@ error_ret:
return NULL;
}
static void
pdf_zathura_image_free(zathura_image_t* image)
cairo_surface_t*
pdf_page_image_get_cairo(zathura_page_t* page, mupdf_page_t* mupdf_page,
zathura_image_t* image, zathura_error_t* error)
{
if (image == NULL) {
return;
if (page == NULL || mupdf_page == NULL || image == NULL || image->data == NULL) {
if (error != NULL) {
*error = ZATHURA_ERROR_INVALID_ARGUMENTS;
}
goto error_ret;
}
g_free(image);
}
fz_image* mupdf_image = (fz_image*) image->data;
static void
get_images(pdf_obj* dict, girara_list_t* list)
{
if (dict == NULL || list == NULL) {
return;
}
fz_pixmap* pixmap = NULL;
cairo_surface_t* surface = NULL;
for (int i = 0; i < pdf_dict_len(dict); i++) {
pdf_obj* image_dict = pdf_dict_get_val(dict, i);
if (pdf_is_dict(image_dict) == 0) {
continue;
}
pixmap = fz_new_pixmap_from_image(mupdf_page->ctx, mupdf_image, 0, 0);
if (pixmap == NULL) {
goto error_free;
}
pdf_obj* type = pdf_dict_gets(image_dict, "Subtype");
if (strcmp(pdf_to_name(type), "Image") != 0) {
continue;
}
surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, mupdf_image->w, mupdf_image->h);
if (surface == NULL) {
goto error_free;
}
bool duplicate = false;
GIRARA_LIST_FOREACH(list, zathura_image_t*, iter, image)
if (image->data == image_dict) {
duplicate = true;
break;
unsigned char* surface_data = cairo_image_surface_get_data(surface);
int rowstride = cairo_image_surface_get_stride(surface);
unsigned char* s = fz_pixmap_samples(mupdf_page->ctx, pixmap);
unsigned int n = fz_pixmap_components(mupdf_page->ctx, pixmap);
for (unsigned int y = 0; y < fz_pixmap_height(mupdf_page->ctx, pixmap); y++) {
for (unsigned int x = 0; x < fz_pixmap_width(mupdf_page->ctx, pixmap); x++) {
guchar* p = surface_data + y * rowstride + x * 4;
// RGB
if (n == 4) {
p[0] = s[2];
p[1] = s[1];
p[2] = s[0];
// Gray-scale or mask
} else {
p[0] = s[0];
p[1] = s[0];
p[2] = s[0];
}
GIRARA_LIST_FOREACH_END(list, zathura_image_t*, iter, image);
if (duplicate == true) {
continue;
s += n;
}
}
pdf_obj* width = pdf_dict_gets(image_dict, "Width");
pdf_obj* height = pdf_dict_gets(image_dict, "Height");
fz_drop_pixmap(mupdf_page->ctx, pixmap);
zathura_image_t* zathura_image = g_malloc(sizeof(zathura_image_t));
return surface;
fprintf(stderr, "image\n");
error_free:
// FIXME: Get correct image coordinates
zathura_image->data = image_dict;
zathura_image->position.x1 = 0;
zathura_image->position.x2 = pdf_to_int(width);
zathura_image->position.y1 = 0;
zathura_image->position.y2 = pdf_to_int(height);
if (pixmap != NULL) {
fz_drop_pixmap(mupdf_page->ctx, pixmap);
}
girara_list_append(list, zathura_image);
if (surface != NULL) {
cairo_surface_destroy(surface);
}
error_ret:
return NULL;
}
static void
get_resources(pdf_obj* resource, girara_list_t* list)
pdf_zathura_image_free(zathura_image_t* image)
{
if (resource == NULL || list == NULL) {
return;
}
pdf_obj* x_object = pdf_dict_gets(resource, "XObject");
if (x_object == NULL) {
if (image == NULL) {
return;
}
get_images(x_object, list);
for (int i = 0; i < pdf_dict_len(x_object); i++) {
pdf_obj* obj = pdf_dict_get_val(x_object, i);
pdf_obj* subsrc = pdf_dict_gets(obj, "Resources");
if (subsrc != NULL && pdf_objcmp(resource, subsrc)) {
get_resources(subsrc, list);
}
}
g_free(image);
}
......@@ -19,7 +19,7 @@ pdf_document_index_generate(zathura_document_t* document, mupdf_document_t* mupd
}
/* get outline */
fz_outline* outline = fz_load_outline(mupdf_document->document);
fz_outline* outline = fz_load_outline(mupdf_document->ctx, mupdf_document->document);
if (outline == NULL) {
if (error != NULL) {
*error = ZATHURA_ERROR_UNKNOWN;
......@@ -32,7 +32,7 @@ pdf_document_index_generate(zathura_document_t* document, mupdf_document_t* mupd
build_index(outline, root);
/* free outline */
fz_free_outline(mupdf_document->ctx, outline);
fz_drop_outline(mupdf_document->ctx, outline);
return root;
}
......@@ -73,17 +73,31 @@ build_index(fz_outline* outline, girara_tree_node_t* root)
if (gflags & fz_link_flag_t_valid) {
target.top = outline->dest.ld.gotor.lt.y;
}
if (gflags & fz_link_flag_r_is_zoom) {
target.scale = outline->dest.ld.gotor.rb.x;
}
/* if (gflags & fz_link_flag_r_is_zoom) { */
/* target.scale = outline->dest.ld.gotor.rb.x; */
/* } */
}
break;
case FZ_LINK_LAUNCH:
type = ZATHURA_LINK_LAUNCH;
target.value = outline->dest.ld.launch.file_spec;
break;
case FZ_LINK_NAMED:
type = ZATHURA_LINK_NAMED;
target.value = outline->dest.ld.named.named;
break;
case FZ_LINK_GOTOR:
type = ZATHURA_LINK_GOTO_REMOTE;
target.value = outline->dest.ld.gotor.file_spec;
break;
default:
outline = outline->next; // TODO: Don't skip unknown type
continue;
}
index_element->link = zathura_link_new(type, rect, target);
if (index_element->link == NULL) {
outline = outline->next;
continue;
}
......
......@@ -31,7 +31,7 @@ pdf_page_links_get(zathura_page_t* page, mupdf_page_t* mupdf_page, zathura_error
goto error_free;
}
fz_link* link = fz_load_links(mupdf_document->document, mupdf_page->page);
fz_link* link = fz_load_links(mupdf_document->ctx, mupdf_page->page);
for (; link != NULL; link = link->next) {
/* extract position */
zathura_rectangle_t position;
......
......@@ -29,12 +29,12 @@ pdf_page_init(zathura_page_t* page)
/* load page */
fz_try (mupdf_page->ctx) {
mupdf_page->page = fz_load_page(mupdf_document->document, index);
mupdf_page->page = fz_load_page(mupdf_document->ctx, mupdf_document->document, index);
} fz_catch (mupdf_page->ctx) {
goto error_free;
}
fz_bound_page(mupdf_document->document, (fz_page*) mupdf_page->page, &mupdf_page->bbox);
fz_bound_page(mupdf_document->ctx, (fz_page*) mupdf_page->page, &mupdf_page->bbox);
/* get page dimensions */
zathura_page_set_width(page, mupdf_page->bbox.x1 - mupdf_page->bbox.x0);
......@@ -74,15 +74,15 @@ pdf_page_clear(zathura_page_t* page, mupdf_page_t* mupdf_page)
if (mupdf_page != NULL) {
if (mupdf_page->text != NULL) {
fz_free_text_page(mupdf_page->ctx, mupdf_page->text);
fz_drop_text_page(mupdf_page->ctx, mupdf_page->text);
}
if (mupdf_page->sheet != NULL) {
fz_free_text_sheet(mupdf_page->ctx, mupdf_page->sheet);
fz_drop_text_sheet(mupdf_page->ctx, mupdf_page->sheet);
}
if (mupdf_page->page != NULL) {
fz_free_page(mupdf_document->document, mupdf_page->page);
fz_drop_page(mupdf_document->ctx, mupdf_page->page);
}
free(mupdf_page);
......
......@@ -11,18 +11,17 @@ register_functions(zathura_plugin_functions_t* functions)
functions->document_free = (zathura_plugin_document_free_t) pdf_document_free;
functions->document_save_as = (zathura_plugin_document_save_as_t) pdf_document_save_as;
functions->document_index_generate = (zathura_plugin_document_index_generate_t) pdf_document_index_generate;
functions->document_get_information = (zathura_plugin_document_get_information_t) pdf_document_get_information;
functions->page_init = (zathura_plugin_page_init_t) pdf_page_init;
functions->page_clear = (zathura_plugin_page_clear_t) pdf_page_clear;
functions->page_search_text = (zathura_plugin_page_search_text_t) pdf_page_search_text;
functions->page_links_get = (zathura_plugin_page_links_get_t) pdf_page_links_get;
#if 0
functions->document_get_information = (zathura_plugin_document_get_information_t) pdf_document_get_information;
functions->page_images_get = (zathura_plugin_page_images_get_t) pdf_page_images_get;
#endif
functions->page_get_text = (zathura_plugin_page_get_text_t) pdf_page_get_text;
functions->page_render = (zathura_plugin_page_render_t) pdf_page_render;
#if HAVE_CAIRO
functions->page_render_cairo = (zathura_plugin_page_render_cairo_t) pdf_page_render_cairo;
functions->page_image_get_cairo = (zathura_plugin_page_image_get_cairo_t) pdf_page_image_get_cairo;
#endif
}
......@@ -32,6 +31,7 @@ ZATHURA_PLUGIN_REGISTER(
register_functions,
ZATHURA_PLUGIN_MIMETYPES({
"application/pdf",
"application/oxps"
"application/oxps",
"application/epub+zip"
})
)
......@@ -113,6 +113,20 @@ girara_list_t* pdf_page_links_get(zathura_page_t* page, mupdf_page_t* mupdf_page
*/
girara_list_t* pdf_page_images_get(zathura_page_t* page, mupdf_page_t* mupdf_page, zathura_error_t* error);
#if HAVE_CAIRO
/**
* Gets the content of the image in a cairo surface
*
* @param page Page
* @param image Image identifier
* @param error Set to an error value (see \ref zathura_error_t) if an
* error occured
* @return The cairo image surface or NULL if an error occured
*/
cairo_surface_t* pdf_page_image_get_cairo(zathura_page_t* page, mupdf_page_t*
mupdf_page, zathura_image_t* image, zathura_error_t* error);
#endif
/**
* Get text for selection
* @param page Page
......
......@@ -26,12 +26,12 @@ pdf_page_render_to_buffer(mupdf_document_t* mupdf_document, mupdf_page_t* mupdf_
fz_try (mupdf_document->ctx) {
fz_matrix m;
fz_scale(&m, scalex, scaley);
fz_run_page(mupdf_document->document, mupdf_page->page, device, &m, NULL);
fz_run_page(mupdf_document->ctx, mupdf_page->page, device, &m, NULL);
} fz_catch (mupdf_document->ctx) {
return ZATHURA_ERROR_UNKNOWN;
}
fz_free_device(device);
fz_drop_device(mupdf_page->ctx, device);
fz_irect irect = { .x1 = page_width, .y1 = page_height };
fz_rect rect = { .x1 = page_width, .y1 = page_height };
......@@ -41,8 +41,8 @@ pdf_page_render_to_buffer(mupdf_document_t* mupdf_document, mupdf_page_t* mupdf_
fz_clear_pixmap_with_value(mupdf_page->ctx, pixmap, 0xFF);
device = fz_new_draw_device(mupdf_page->ctx, pixmap);
fz_run_display_list(display_list, device, &fz_identity, &rect, NULL);
fz_free_device(device);
fz_run_display_list(mupdf_page->ctx, display_list, device, &fz_identity, &rect, NULL);
fz_drop_device(mupdf_page->ctx, device);
unsigned char* s = fz_pixmap_samples(mupdf_page->ctx, pixmap);
unsigned int n = fz_pixmap_components(mupdf_page->ctx, pixmap);
......
......@@ -26,7 +26,7 @@ pdf_page_search_text(zathura_page_t* page, mupdf_page_t* mupdf_page, const char*
mupdf_document_t* mupdf_document = zathura_document_get_data(document);;
girara_list_t* list = girara_list_new2((girara_free_function_t) zathura_link_free);
girara_list_t* list = girara_list_new2(g_free);
if (list == NULL) {
if (error != NULL) {
*error = ZATHURA_ERROR_OUT_OF_MEMORY;
......
......@@ -7,9 +7,6 @@
#include "plugin.h"
#include "utils.h"
void mupdf_page_extract_text(mupdf_document_t* mupdf_document,
mupdf_page_t* mupdf_page);
char*
pdf_page_get_text(zathura_page_t* page, mupdf_page_t* mupdf_page, zathura_rectangle_t rectangle, zathura_error_t* error)
{
......
......@@ -15,11 +15,15 @@ mupdf_page_extract_text(mupdf_document_t* mupdf_document, mupdf_page_t* mupdf_pa
fz_try (mupdf_page->ctx) {
text_device = fz_new_text_device(mupdf_page->ctx, mupdf_page->sheet, mupdf_page->text);
/* Disable FZ_IGNORE_IMAGE to collect image blocks */
fz_disable_device_hints(mupdf_page->ctx, text_device, FZ_IGNORE_IMAGE);
fz_matrix ctm;
fz_scale(&ctm, 1.0, 1.0);
fz_run_page(mupdf_document->document, mupdf_page->page, text_device, &ctm, NULL);
fz_run_page(mupdf_page->ctx, mupdf_page->page, text_device, &ctm, NULL);
} fz_always (mupdf_document->ctx) {
fz_free_device(text_device);
fz_drop_device(mupdf_page->ctx, text_device);
} fz_catch(mupdf_document->ctx) {
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment