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