Commit 500ecb7c authored by Moritz Lipp's avatar Moritz Lipp

Split source code in multiple files

parent b8b5da73
......@@ -4,3 +4,6 @@
pdf.so
*.swp
zathura-version-check
.ycm_extra_conf.*
compile_commands.json
tags
/* See LICENSE file for license and copyright information */
#define _POSIX_C_SOURCE 1
#include <mupdf/fitz.h>
#include <mupdf/xps.h>
#include <mupdf/pdf.h>
#include "plugin.h"
zathura_error_t
pdf_document_open(zathura_document_t* document)
{
zathura_error_t error = ZATHURA_ERROR_OK;
if (document == NULL) {
error = ZATHURA_ERROR_INVALID_ARGUMENTS;
goto error_ret;
}
mupdf_document_t* mupdf_document = calloc(1, sizeof(mupdf_document_t));
if (mupdf_document == NULL) {
error = ZATHURA_ERROR_OUT_OF_MEMORY;
goto error_ret;
}
mupdf_document->ctx = fz_new_context(NULL, NULL, FZ_STORE_DEFAULT);
if (mupdf_document->ctx == NULL) {
error = ZATHURA_ERROR_UNKNOWN;
goto error_free;
}
/* open document */
const char* path = zathura_document_get_path(document);
const char* password = zathura_document_get_password(document);
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);
}
if (mupdf_document->document == NULL) {
error = ZATHURA_ERROR_UNKNOWN;
goto error_free;
}
/* 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) {
error = ZATHURA_ERROR_INVALID_PASSWORD;
goto error_free;
}
}
zathura_document_set_number_of_pages(document, fz_count_pages(mupdf_document->document));
zathura_document_set_data(document, mupdf_document);
return error;
error_free:
if (mupdf_document != NULL) {
if (mupdf_document->document != NULL) {
fz_close_document(mupdf_document->document);
}
if (mupdf_document->ctx != NULL) {
fz_free_context(mupdf_document->ctx);
}
free(mupdf_document);
}
zathura_document_set_data(document, NULL);
error_ret:
return error;
}
zathura_error_t
pdf_document_free(zathura_document_t* document, mupdf_document_t* mupdf_document)
{
if (document == NULL || mupdf_document == NULL) {
return ZATHURA_ERROR_INVALID_ARGUMENTS;
}
fz_close_document(mupdf_document->document);
fz_free_context(mupdf_document->ctx);
free(mupdf_document);
zathura_document_set_data(document, NULL);
return ZATHURA_ERROR_OK;
}
zathura_error_t
pdf_document_save_as(zathura_document_t* document, mupdf_document_t*
mupdf_document, const char* path)
{
if (document == NULL || mupdf_document == NULL || path == NULL) {
return ZATHURA_ERROR_INVALID_ARGUMENTS;
}
fz_try (mupdf_document->ctx) {
/* fz_write_document claims to accepts NULL as third argument but doesn't.
* pdf_write_document does not check if the third arguments is NULL for some
* options. */
fz_write_options opts = { 0 }; /* just use the default options */
fz_write_document(mupdf_document->document, (char*) path, &opts);
} fz_catch (mupdf_document->ctx) {
return ZATHURA_ERROR_UNKNOWN;
}
return ZATHURA_ERROR_OK;
}
/* See LICENSE file for license and copyright information */
#define _POSIX_C_SOURCE 1
#include <glib.h>
#include <girara/datastructures.h>
#include <mupdf/pdf.h>
#include "plugin.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)
{
if (page == NULL) {
if (error != NULL) {
*error = ZATHURA_ERROR_INVALID_ARGUMENTS;
}
goto error_ret;
}
girara_list_t* list = NULL;
zathura_document_t* document = zathura_page_get_document(page);
if (document == NULL) {
goto error_ret;
}
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;
}
list = girara_list_new();
if (list == NULL) {
if (error != NULL) {
*error = ZATHURA_ERROR_OUT_OF_MEMORY;
}
goto error_free;
}
girara_list_set_free_function(list, (girara_free_function_t) pdf_zathura_image_free);
get_resources(resource, list);
return list;
error_free:
if (error != NULL && *error == ZATHURA_ERROR_OK) {
*error = ZATHURA_ERROR_UNKNOWN;
}
if (list != NULL) {
girara_list_free(list);
}
error_ret:
return NULL;
}
static void
pdf_zathura_image_free(zathura_image_t* image)
{
if (image == NULL) {
return;
}
g_free(image);
}
static void
get_images(pdf_obj* dict, girara_list_t* list)
{
if (dict == NULL || list == NULL) {
return;
}
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;
}
pdf_obj* type = pdf_dict_gets(image_dict, "Subtype");
if (strcmp(pdf_to_name(type), "Image") != 0) {
continue;
}
bool duplicate = false;
GIRARA_LIST_FOREACH(list, zathura_image_t*, iter, image)
if (image->data == image_dict) {
duplicate = true;
break;
}
GIRARA_LIST_FOREACH_END(list, zathura_image_t*, iter, image);
if (duplicate == true) {
continue;
}
pdf_obj* width = pdf_dict_gets(image_dict, "Width");
pdf_obj* height = pdf_dict_gets(image_dict, "Height");
zathura_image_t* zathura_image = g_malloc(sizeof(zathura_image_t));
fprintf(stderr, "image\n");
// 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);
girara_list_append(list, zathura_image);
}
}
static void
get_resources(pdf_obj* resource, girara_list_t* list)
{
if (resource == NULL || list == NULL) {
return;
}
pdf_obj* x_object = pdf_dict_gets(resource, "XObject");
if (x_object == 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);
}
}
}
/* See LICENSE file for license and copyright information */
#define _POSIX_C_SOURCE 1
#include <girara/datastructures.h>
#include "plugin.h"
static void build_index(fz_outline* outline, girara_tree_node_t* root);
girara_tree_node_t*
pdf_document_index_generate(zathura_document_t* document, mupdf_document_t* mupdf_document, zathura_error_t* error)
{
if (document == NULL || mupdf_document == NULL) {
if (error != NULL) {
*error = ZATHURA_ERROR_INVALID_ARGUMENTS;
}
return NULL;
}
/* get outline */
fz_outline* outline = fz_load_outline(mupdf_document->document);
if (outline == NULL) {
if (error != NULL) {
*error = ZATHURA_ERROR_UNKNOWN;
}
return NULL;
}
/* generate index */
girara_tree_node_t* root = girara_node_new(zathura_index_element_new("ROOT"));
build_index(outline, root);
/* free outline */
fz_free_outline(mupdf_document->ctx, outline);
return root;
}
static void
build_index(fz_outline* outline, girara_tree_node_t* root)
{
if (outline == NULL || root == NULL) {
return;
}
while (outline != NULL) {
zathura_index_element_t* index_element = zathura_index_element_new(outline->title);
zathura_link_target_t target;
zathura_link_type_t type;
zathura_rectangle_t rect;
switch (outline->dest.kind) {
case FZ_LINK_NONE:
type = ZATHURA_LINK_NONE;
break;
case FZ_LINK_URI:
type = ZATHURA_LINK_URI;
target.value = outline->dest.ld.uri.uri;
break;
case FZ_LINK_GOTO:
type = ZATHURA_LINK_GOTO_DEST;
target.page_number = outline->dest.ld.gotor.page;
target.destination_type = ZATHURA_LINK_DESTINATION_XYZ;
target.left = 0;
target.top = 0;
target.scale = 0.0;
break;
default:
continue;
}
index_element->link = zathura_link_new(type, rect, target);
if (index_element->link == NULL) {
continue;
}
girara_tree_node_t* node = girara_node_append_data(root, index_element);
if (outline->down != NULL) {
build_index(outline->down, node);
}
outline = outline->next;
}
}
/* See LICENSE file for license and copyright information */
#define _POSIX_C_SOURCE 1
#include <glib.h>
#include "plugin.h"
girara_list_t*
pdf_page_links_get(zathura_page_t* page, mupdf_page_t* mupdf_page, zathura_error_t* error)
{
if (page == NULL) {
if (error != NULL) {
*error = ZATHURA_ERROR_INVALID_ARGUMENTS;
}
goto error_ret;
}
zathura_document_t* document = zathura_page_get_document(page);
if (document == NULL || mupdf_page == NULL || mupdf_page->page == NULL) {
goto error_ret;
}
mupdf_document_t* mupdf_document = zathura_document_get_data(document);;
girara_list_t* list = girara_list_new2((girara_free_function_t) zathura_link_free);
if (list == NULL) {
if (error != NULL) {
*error = ZATHURA_ERROR_OUT_OF_MEMORY;
}
goto error_free;
}
fz_link* link = fz_load_links(mupdf_document->document, mupdf_page->page);
for (; link != NULL; link = link->next) {
/* extract position */
zathura_rectangle_t position;
position.x1 = link->rect.x0;
position.x2 = link->rect.x1;
position.y1 = link->rect.y0;
position.y2 = link->rect.y1;
zathura_link_type_t type = ZATHURA_LINK_INVALID;
zathura_link_target_t target = { 0 };
char* buffer = NULL;
switch (link->dest.kind) {
case FZ_LINK_NONE:
type = ZATHURA_LINK_NONE;
break;
case FZ_LINK_URI:
type = ZATHURA_LINK_URI;
target.value = link->dest.ld.uri.uri;
break;
case FZ_LINK_GOTO:
type = ZATHURA_LINK_GOTO_DEST;
target.page_number = link->dest.ld.gotor.page;
target.destination_type = ZATHURA_LINK_DESTINATION_XYZ;
target.left = 0;
target.top = 0;
target.scale = 0.0;
break;
default:
continue;
}
zathura_link_t* zathura_link = zathura_link_new(type, position, target);
if (zathura_link != NULL) {
girara_list_append(list, zathura_link);
}
if (buffer != NULL) {
g_free(buffer);
}
}
return list;
error_free:
if (list != NULL) {
girara_list_free(list);
}
error_ret:
return NULL;
}
/* See LICENSE file for license and copyright information */
#define _POSIX_C_SOURCE 1
#include "plugin.h"
zathura_error_t
pdf_page_init(zathura_page_t* page)
{
if (page == NULL) {
return ZATHURA_ERROR_INVALID_ARGUMENTS;
}
zathura_document_t* document = zathura_page_get_document(page);
mupdf_document_t* mupdf_document = zathura_document_get_data(document);
mupdf_page_t* mupdf_page = calloc(1, sizeof(mupdf_page_t));
unsigned int index = zathura_page_get_index(page);
if (mupdf_page == NULL) {
return ZATHURA_ERROR_OUT_OF_MEMORY;
}
zathura_page_set_data(page, mupdf_page);
mupdf_page->ctx = mupdf_document->ctx;
if (mupdf_page->ctx == NULL) {
goto error_free;
}
/* load page */
fz_try (mupdf_page->ctx) {
mupdf_page->page = fz_load_page(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);
/* get page dimensions */
zathura_page_set_width(page, mupdf_page->bbox.x1 - mupdf_page->bbox.x0);
zathura_page_set_height(page, mupdf_page->bbox.y1 - mupdf_page->bbox.y0);
/* setup text */
mupdf_page->extracted_text = false;
mupdf_page->text = fz_new_text_page(mupdf_page->ctx);
if (mupdf_page->text == NULL) {
goto error_free;
}
mupdf_page->sheet = fz_new_text_sheet(mupdf_page->ctx);
if (mupdf_page->sheet == NULL) {
goto error_free;
}
return ZATHURA_ERROR_OK;
error_free:
pdf_page_clear(page, mupdf_page);
return ZATHURA_ERROR_UNKNOWN;
}
zathura_error_t
pdf_page_clear(zathura_page_t* page, mupdf_page_t* mupdf_page)
{
if (page == NULL) {
return ZATHURA_ERROR_INVALID_ARGUMENTS;
}
zathura_document_t* document = zathura_page_get_document(page);
mupdf_document_t* mupdf_document = zathura_document_get_data(document);
if (mupdf_page != NULL) {
if (mupdf_page->text != NULL) {
fz_free_text_page(mupdf_page->ctx, mupdf_page->text);
}
if (mupdf_page->sheet != NULL) {
fz_free_text_sheet(mupdf_page->ctx, mupdf_page->sheet);
}
if (mupdf_page->page != NULL) {
fz_free_page(mupdf_document->document, mupdf_page->page);
}
free(mupdf_page);
}
return ZATHURA_ERROR_UNKNOWN;
}
This diff is collapsed.
/* See LICENSE file for license and copyright information */
#define _POSIX_C_SOURCE 1
#include "plugin.h"
void
register_functions(zathura_plugin_functions_t* functions)
{
functions->document_open = (zathura_plugin_document_open_t) pdf_document_open;
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->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;
#endif
}
ZATHURA_PLUGIN_REGISTER(
"pdf-mupdf",
VERSION_MAJOR, VERSION_MINOR, VERSION_REV,
register_functions,
ZATHURA_PLUGIN_MIMETYPES({
"application/pdf",
"application/oxps"
})
)
/* See LICENSE file for license and copyright information */
#define _POSIX_C_SOURCE 1
#include <glib.h>
#include "plugin.h"
static zathura_error_t
pdf_page_render_to_buffer(mupdf_document_t* mupdf_document, mupdf_page_t* mupdf_page,
unsigned char* image, int rowstride, int components,
unsigned int page_width, unsigned int page_height,
double scalex, double scaley)
{
if (mupdf_document == NULL ||
mupdf_document->ctx == NULL ||
mupdf_page == NULL ||
mupdf_page->page == NULL ||
image == NULL) {
return ZATHURA_ERROR_UNKNOWN;
}
fz_display_list* display_list = fz_new_display_list(mupdf_page->ctx);
fz_device* device = fz_new_list_device(mupdf_page->ctx, display_list);
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_catch (mupdf_document->ctx) {
return ZATHURA_ERROR_UNKNOWN;
}
fz_free_device(device);
fz_irect irect = { .x1 = page_width, .y1 = page_height };
fz_rect rect = { .x1 = page_width, .y1 = page_height };
fz_colorspace* colorspace = fz_device_rgb(mupdf_document->ctx);
fz_pixmap* pixmap = fz_new_pixmap_with_bbox(mupdf_page->ctx, colorspace, &irect);
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);
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 = image + y * rowstride + x * components;
p[0] = s[2];
p[1] = s[1];
p[2] = s[0];
s += n;
}
}
fz_drop_pixmap(mupdf_page->ctx, pixmap);
fz_drop_display_list(mupdf_page->ctx, display_list);
return ZATHURA_ERROR_OK;
}
zathura_image_buffer_t*
pdf_page_render(zathura_page_t* page, mupdf_page_t* mupdf_page, zathura_error_t* error)
{
if (page == NULL || mupdf_page == NULL) {
if (error != NULL) {
*error = ZATHURA_ERROR_INVALID_ARGUMENTS;
}
return NULL;
}
zathura_document_t* document = zathura_page_get_document(page);
if (document == NULL) {
return NULL;
}
/* calculate sizes */
double scalex = zathura_document_get_scale(document);
double scaley = scalex;
unsigned int page_width = scalex * zathura_page_get_width(page);
unsigned int page_height = scaley * zathura_page_get_height(page);
/* create image buffer */
zathura_image_buffer_t* image_buffer = zathura_image_buffer_create(page_width, page_height);
if (image_buffer == NULL) {
if (error != NULL) {
*error = ZATHURA_ERROR_OUT_OF_MEMORY;
}
return NULL;
}
int rowstride = image_buffer->rowstride;
unsigned char* image = image_buffer->data;
mupdf_document_t* mupdf_document = zathura_document_get_data(document);
zathura_error_t error_render = pdf_page_render_to_buffer(mupdf_document, mupdf_page, image, rowstride, 3,
page_width, page_height, scalex, scaley);
if (error_render != ZATHURA_ERROR_OK) {
zathura_image_buffer_free(image_buffer);
if (error != NULL) {
*error = error_render;
}
return NULL;
}
return image_buffer;
}
#if HAVE_CAIRO
zathura_error_t
pdf_page_render_cairo(zathura_page_t* page, mupdf_page_t* mupdf_page, cairo_t* cairo, bool GIRARA_UNUSED(printing))
{
if (page == NULL || mupdf_page == NULL) {
return ZATHURA_ERROR_INVALID_ARGUMENTS;
}
cairo_surface_t* surface = cairo_get_target(cairo);
if (surface == NULL ||
cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS ||
cairo_surface_get_type(surface) != CAIRO_SURFACE_TYPE_IMAGE) {
return ZATHURA_ERROR_UNKNOWN;
}
zathura_document_t* document = zathura_page_get_document(page);
if (document == NULL) {
return ZATHURA_ERROR_UNKNOWN;
}
unsigned int page_width = cairo_image_surface_get_width(surface);
unsigned int page_height = cairo_image_surface_get_height(surface);
double scalex = ((double) page_width) / zathura_page_get_width(page);
double scaley = ((double) page_height) /zathura_page_get_height(page);
int rowstride = cairo_image_surface_get_stride(surface);
unsigned char* image = cairo_image_surface_get_data(surface);
mupdf_document_t* mupdf_document = zathura_document_get_data(document);
return pdf_page_render_to_buffer(mupdf_document, mupdf_page, image, rowstride, 4,