image.c 4.29 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
/* 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);
Moritz Lipp's avatar
Moritz Lipp committed
12 13
static void get_images(zathura_page_t* page, pdf_obj* dict, girara_list_t* list);
static void get_resources(zathura_page_t* page, pdf_obj* resource, girara_list_t* list);
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

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

Moritz Lipp's avatar
Moritz Lipp committed
33
  pdf_obj* page_object = pdf_load_object(mupdf_document->ctx, (pdf_document*) mupdf_document->document, zathura_page_get_index(page), 0);
34 35 36 37
  if (page_object == NULL) {
    goto error_free;
  }

Moritz Lipp's avatar
Moritz Lipp committed
38
  pdf_obj* resource = pdf_dict_gets(mupdf_document->ctx, page_object, "Resources");
39 40 41 42 43 44 45 46 47 48 49 50 51 52
  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);

Moritz Lipp's avatar
Moritz Lipp committed
53
  get_resources(page, resource, list);
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83

  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
Moritz Lipp's avatar
Moritz Lipp committed
84
get_images(zathura_page_t* page, pdf_obj* dict, girara_list_t* list)
85 86 87 88 89
{
  if (dict == NULL || list == NULL) {
    return;
  }

Moritz Lipp's avatar
Moritz Lipp committed
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
  if (page == NULL) {
    return;
  }

  zathura_document_t* document = zathura_page_get_document(page);

  if (document == NULL) {
    return;
  }

  mupdf_document_t* mupdf_document = zathura_document_get_data(document);

  for (int i = 0; i < pdf_dict_len(mupdf_document->ctx, dict); i++) {
    pdf_obj* image_dict = pdf_dict_get_val(mupdf_document->ctx, dict, i);
    if (pdf_is_dict(mupdf_document->ctx, image_dict) == 0) {
105 106 107
      continue;
    }

Moritz Lipp's avatar
Moritz Lipp committed
108 109
    pdf_obj* type = pdf_dict_gets(mupdf_document->ctx, image_dict, "Subtype");
    if (strcmp(pdf_to_name(mupdf_document->ctx, type), "Image") != 0) {
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
      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;
    }

Moritz Lipp's avatar
Moritz Lipp committed
125 126
    pdf_obj* width  = pdf_dict_gets(mupdf_document->ctx, image_dict, "Width");
    pdf_obj* height = pdf_dict_gets(mupdf_document->ctx, image_dict, "Height");
127 128 129 130 131 132 133 134

    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;
Moritz Lipp's avatar
Moritz Lipp committed
135
    zathura_image->position.x2 = pdf_to_int(mupdf_document->ctx, width);
136
    zathura_image->position.y1 = 0;
Moritz Lipp's avatar
Moritz Lipp committed
137
    zathura_image->position.y2 = pdf_to_int(mupdf_document->ctx, height);
138 139 140 141 142 143

    girara_list_append(list, zathura_image);
  }
}

static void
Moritz Lipp's avatar
Moritz Lipp committed
144
get_resources(zathura_page_t* page, pdf_obj* resource, girara_list_t* list)
145 146 147 148 149
{
  if (resource == NULL || list == NULL) {
    return;
  }

Moritz Lipp's avatar
Moritz Lipp committed
150 151 152 153 154 155 156 157 158 159 160 161 162
  if (page == NULL) {
    return;
  }

  zathura_document_t* document = zathura_page_get_document(page);

  if (document == NULL) {
    return;
  }

  mupdf_document_t* mupdf_document = zathura_document_get_data(document);

  pdf_obj* x_object = pdf_dict_gets(mupdf_document->ctx, resource, "XObject");
163 164 165 166
  if (x_object == NULL) {
    return;
  }

Moritz Lipp's avatar
Moritz Lipp committed
167
  get_images(page, x_object, list);
168

Moritz Lipp's avatar
Moritz Lipp committed
169 170 171 172 173
  for (int i = 0; i < pdf_dict_len(mupdf_document->ctx, x_object); i++) {
    pdf_obj* obj = pdf_dict_get_val(mupdf_document->ctx, x_object, i);
    pdf_obj* subsrc = pdf_dict_gets(mupdf_document->ctx, obj, "Resources");
    if (subsrc != NULL && pdf_objcmp(mupdf_document->ctx, resource, subsrc)) {
      get_resources(page, subsrc, list);
174 175 176 177
    }
  }
}