document.c 3.37 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
/* 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);

36 37 38 39 40 41 42 43 44 45
  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_catch(mupdf_document->ctx){
    error = ZATHURA_ERROR_UNKNOWN;
    return error;
46 47 48 49 50 51 52 53
  }

  if (mupdf_document->document == NULL) {
    error = ZATHURA_ERROR_UNKNOWN;
    goto error_free;
  }

  /* authenticate if password is required and given */
Moritz Lipp's avatar
Moritz Lipp committed
54 55
  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) {
56 57 58 59 60
      error = ZATHURA_ERROR_INVALID_PASSWORD;
      goto error_free;
    }
  }

Moritz Lipp's avatar
Moritz Lipp committed
61
  zathura_document_set_number_of_pages(document, fz_count_pages(mupdf_document->ctx, mupdf_document->document));
62 63 64 65 66 67 68 69
  zathura_document_set_data(document, mupdf_document);

  return error;

error_free:

  if (mupdf_document != NULL) {
    if (mupdf_document->document != NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
70
      fz_drop_document(mupdf_document->ctx, mupdf_document->document);
71 72
    }
    if (mupdf_document->ctx != NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
73
      fz_drop_context(mupdf_document->ctx);
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
    }

    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;
  }

Moritz Lipp's avatar
Moritz Lipp committed
93 94
  fz_drop_document(mupdf_document->ctx, mupdf_document->document);
  fz_drop_context(mupdf_document->ctx);
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
  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 */
Moritz Lipp's avatar
Moritz Lipp committed
115
    fz_write_document(mupdf_document->ctx, mupdf_document->document, (char*) path, &opts);
116 117 118 119 120 121 122
  } fz_catch (mupdf_document->ctx) {
    return ZATHURA_ERROR_UNKNOWN;
  }

  return ZATHURA_ERROR_OK;
}