efl

Форк
0
/
main.cpp 
400 строк · 9.4 Кб
1
#ifdef HAVE_CONFIG_H
2
# include <config.h>
3
#endif
4

5
#include <fcntl.h>
6
#include <stdio.h>
7
#include <unistd.h>
8
#include <libgen.h>
9

10
#include <Eina.h>
11

12
#include <poppler-global.h>
13
#include <poppler-rectangle.h>
14
#include <poppler-document.h>
15
#include <poppler-page.h>
16
#include <poppler-page-renderer.h>
17

18
#include "shmfile.h"
19
#include "timeout.h"
20

21
#ifndef _WIN32
22
# include <unistd.h>
23
# include <signal.h>
24
#endif
25

26
#define DATA32 unsigned int
27
typedef char RGB24[3];
28

29
//#define PDF_DBG
30

31
#ifdef PDF_DBG
32
#define D(fmt, args...) fprintf(stderr, fmt, ## args)
33
#else
34
#define D(fmt, args...)
35
#endif
36

37
using namespace poppler;
38

39
bool locked = false;
40

41
document *doc;
42
page *doc_page;
43
int width = 0, height = 0;
44
int crop_width = 0, crop_height = 0;
45
void *data = NULL;
46
double dpi = -1.0;
47

48
#define DEF_DPI 72.0
49

50
Eina_Bool poppler_init(const char *file, int page_nbr, int size_w, int size_h)
51
{
52
   double w, h, cw, ch;
53

54
   if (!file || !*file)
55
     return EINA_FALSE;
56

57
   if (page_nbr < 0)
58
     return EINA_FALSE;
59

60
   if (!eina_init())
61
     return EINA_FALSE;
62

63

64
   doc = document::load_from_file(file);
65

66
   if (!doc)
67
     return EINA_FALSE;
68

69
   if (page_nbr >= doc->pages())
70
     goto del_pdfdoc;
71

72
   /* load the page */
73

74
   doc_page = doc->create_page(page_nbr);
75
   if (!doc_page)
76
     goto del_pdfdoc;
77

78
   w = doc_page->page_rect(media_box).width();
79
   h = doc_page->page_rect(media_box).height();
80
   cw = doc_page->page_rect().width();
81
   ch = doc_page->page_rect().height();
82

83
   if (cw > w) cw = w;
84
   if (ch > h) ch = h;
85

86
   if ((size_w > 0) || (size_h > 0))
87
     {
88
        double w2 = cw, h2 = ch;
89

90
        w2 = size_w;
91
        h2 = (size_w * ch) / cw;
92
        if (h2 > size_h)
93
          {
94
             h2 = size_h;
95
             w2 = (size_h * cw) / ch;
96
          }
97
        D("XXXXXXXXXXXXXXXXXXXXx %3.3fx%3.3f\n", w2, h2);
98
        if (w2 > h2) dpi = (w2 * DEF_DPI) / cw;
99
        else dpi = (h2 * DEF_DPI) / ch;
100
     }
101

102
   if (dpi > 0.0)
103
     {
104
        cw = (cw * dpi) / DEF_DPI;
105
        ch = (ch * dpi) / DEF_DPI;
106
        w = (w * dpi) / DEF_DPI;
107
        h = (h * dpi) / DEF_DPI;
108
     }
109
   width = w;
110
   height = h;
111
   crop_width = cw;
112
   crop_height = ch;
113

114
   return EINA_TRUE;
115

116
 del_pdfdoc:
117
   delete doc;
118

119
   return EINA_FALSE;
120
}
121

122
void poppler_shutdown()
123
{
124
   delete doc;
125
   eina_shutdown();
126
}
127

128

129
void poppler_load_image(int size_w EINA_UNUSED, int size_h EINA_UNUSED)
130
{
131
   page_renderer *renderer;
132
   image out;
133
   DATA32 *dst;
134
   int y, x;
135

136
   if (dpi <= 0.0) dpi = DEF_DPI;
137

138
   renderer = new page_renderer();
139

140
   renderer->set_render_hint(page_renderer::text_antialiasing, 1);
141
   renderer->set_render_hint(page_renderer::antialiasing, 1);
142

143
   out = renderer->render_page(doc_page, dpi, dpi,
144
                               0, 0, width, height,
145
                               rotate_0);
146

147
   shm_alloc(crop_width * crop_height * sizeof(DATA32));
148
   if (!shm_addr) goto end;
149
   data = shm_addr;
150
   dst = (DATA32 *)data;
151

152
#define IMAGE_PIXEL_ITERATOR \
153
   for (y = 0; y < crop_height; y++) \
154
     for (x = 0; x < crop_width; x++)
155

156
#define ARGB_JOIN(a,r,g,b) \
157
        (((a) << 24) + ((r) << 16) + ((g) << 8) + (b))
158

159
   if (out.format() == image::format_mono)
160
     {
161
        // Looks like this is 1 bit per pixel, padded to a single byte.
162
        // The problem is testing. I have no sample (and no doc).
163

164
        uint8_t *src;
165
        for (y = 0; y < crop_height; y++)
166
          {
167
             src = (uint8_t *) out.data() + y * crop_width;
168
             for (x = 0; x < crop_width; x++)
169
               {
170
                  int bit = x & 0x7;
171
                  int c = (*src & (1 << bit)) ? 0xFF : 0x00;
172
                  *dst++ = ARGB_JOIN(0xFF, c, c, c);
173
                  if ((x & 0x7) == 0x7) src++;
174
               }
175
          }
176
     }
177
   if (out.format() == image::format_rgb24)
178
     {
179
        RGB24 *src;
180
        src = (RGB24*) out.data();
181
        IMAGE_PIXEL_ITERATOR
182
          {
183
             int pos = x+y*crop_width;
184
             dst[pos] = ARGB_JOIN(0xFF, src[pos][0], src[pos][1], src[pos][2]);
185
          }
186
      }
187
    else if (out.format() == image::format_argb32)
188
      {
189
         DATA32 *src;
190

191
         src = (DATA32*) out.data();
192
         IMAGE_PIXEL_ITERATOR
193
           *dst++ = *src++;
194
      }
195

196
 end:
197
   delete renderer;
198
}
199

200
static Eina_Tmpstr *tmpdir = NULL;
201
static Eina_Tmpstr *generated = NULL;
202

203
static void
204
tmp_cleanup(void)
205
{
206
   if (tmpdir)
207
     {
208
        if (generated)
209
          {
210
             unlink(generated);
211
          }
212
        if (rmdir(tmpdir) < 0)
213
          {
214
             D("Failed to delete tmpdir %s\n", tmpdir);
215
          }
216
        eina_tmpstr_del(tmpdir);
217
        tmpdir = NULL;
218
        if (generated)
219
          {
220
             eina_tmpstr_del(generated);
221
             generated = NULL;
222
          }
223
     }
224
}
225

226
static void
227
_crash(int val)
228
{
229
   D("Crash\n");
230
   tmp_cleanup();
231
   _exit(-1 | val);
232
}
233

234
int
235
main(int argc, char **argv)
236
{
237
   char *extension;
238
   char *dir;
239
   char *file;
240
   int i;
241
   int size_w = 0, size_h = 0;
242
   int head_only = 0;
243
   int page_num = 0;
244
   int ret = 0;
245

246
   if (argc < 2) return -1;
247
   // file is ALWAYS first arg, other options come after
248
   file = argv[1];
249
   for (i = 2; i < argc; i++)
250
     {
251
        if      (!strcmp(argv[i], "-head"))
252
           // asked to only load header, not body/data
253
           head_only = 1;
254
        else if (!strcmp(argv[i], "-key"))
255
          {
256
             i++;
257
             page_num = atoi(argv[i]);
258
             i++;
259
          }
260
        else if (!strcmp(argv[i], "-opt-scale-down-by"))
261
          { // not used by pdf loader
262
             i++;
263
             // int scale_down = atoi(argv[i]);
264
          }
265
        else if (!strcmp(argv[i], "-opt-dpi"))
266
          {
267
             i++;
268
             dpi = ((double)atoi(argv[i])) / 1000.0; // dpi is an int multiplied by 1000 (so 72dpi is 72000)
269
             i++;
270
          }
271
        else if (!strcmp(argv[i], "-opt-size"))
272
          { // not used by pdf loader
273
             i++;
274
             size_w = atoi(argv[i]);
275
             i++;
276
             size_h = atoi(argv[i]);
277
          }
278
     }
279

280
   D("dpi....: %f\n", dpi);
281
   D("page...: %d\n", page_num);
282

283
   // This is a funny hack to call an external tool to generate a pdf that will then be processed by poppler
284
   extension = strrchr(file, '.');
285
   dir = dirname(argv[0]);
286
   if (extension && dir && (!(!strcasecmp(extension, ".pdf"))))
287
     {
288
#ifndef _WIN32
289
        signal(SIGSEGV, _crash);
290
        signal(SIGBUS, _crash);
291
        signal(SIGFPE, _crash);
292
        signal(SIGABRT, _crash);
293
        signal(SIGILL, _crash);
294
        signal(SIGSYS, _crash);
295
        signal(SIGINT, _crash);
296
        signal(SIGTERM, _crash);
297
        signal(SIGQUIT, _crash);
298
#endif
299
        timeout_func_set(tmp_cleanup);
300
        if (eina_file_mkdtemp("evas_generic_pdf_loaderXXXXXX", &tmpdir))
301
          {
302
             Eina_Strbuf *tmp;
303
             FILE *cmd;
304

305
             tmp = eina_strbuf_new();
306
             eina_strbuf_append_printf(tmp, "%s/evas_generic_pdf_loader.%s '%s' %s", dir, extension + 1, file, tmpdir);
307

308
             cmd = popen(eina_strbuf_string_get(tmp), "r");
309
             D("running preprocessing process '%s'...\n", eina_strbuf_string_get(tmp));
310
             eina_strbuf_reset(tmp);
311

312
             if (cmd)
313
               {
314
                  struct stat st;
315
                  const char *filename;
316
                  char buf[1024];
317

318
                  while (fgets(buf, sizeof (buf), cmd))
319
                    ;
320
                  pclose(cmd);
321

322
                  filename = basename(file);
323

324
                  generated = eina_tmpstr_add_length(filename, strlen(filename) - strlen(extension));
325

326
                  eina_strbuf_append_printf(tmp, "%s/%s.pdf", tmpdir, generated);
327

328
                  eina_tmpstr_del(generated);
329
                  generated = NULL;
330

331
                  if (stat(eina_strbuf_string_get(tmp), &st) == 0)
332
                    {
333
                       generated = eina_tmpstr_add_length(eina_strbuf_string_get(tmp),
334
                                                          eina_strbuf_length_get(tmp));
335
                       file = (char*) generated;
336
                    }
337
               }
338

339
             D("generated file: '%s'\n", generated);
340
             eina_strbuf_free(tmp);
341
          }
342
     }
343

344
   // Let's force a timeout if things go wrong
345
   timeout_init(30);
346

347
   // Now process the pdf (or the generated pdf)
348
   D("poppler_file_init\n");
349
   if (!poppler_init(file, page_num, size_w, size_h))
350
     {
351
        ret = 1;
352
        goto cleanup;
353
     }
354
   D("poppler_file_init done\n");
355

356
   D("dpi2...: %f\n", dpi);
357
   if (!head_only)
358
     {
359
        poppler_load_image(size_w, size_h);
360
     }
361

362
   D("size...: %ix%i\n", width, height);
363
   D("crop...: %ix%i\n", crop_width, crop_height);
364
   D("alpha..: 1\n");
365

366
   printf("size %i %i\n", crop_width, crop_height);
367
   printf("alpha 0\n");
368

369
   if (!head_only)
370
     {
371
#ifdef _WIN32
372
        if (shm_fd)
373
#else
374
        if (shm_fd >= 0)
375
#endif
376
          printf("shmfile %s\n", shmfile);
377
        else
378
          {
379
             // could also to "tmpfile %s\n" like shmfile but just
380
             // a mmaped tmp file on the system
381
             printf("data\n");
382
             if (fwrite(data, crop_width * crop_height * sizeof(DATA32), 1, stdout) != 1)
383
               {
384
                  // nothing much to do, the receiver will simply ignore the
385
                  // data as it's too short
386
                  D("fwrite failed (%d bytes): %m\n", crop_width * crop_height * sizeof(DATA32));
387
               }
388
          }
389
        shm_free();
390
     }
391
   else
392
     printf("done\n");
393

394
   poppler_shutdown();
395
cleanup:
396
   timeout_func_set(NULL);
397
   tmp_cleanup();
398
   fflush(stdout);
399
   return ret;
400
}
401

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.