~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/poppler/glib/poppler-page.cc

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* poppler-page.cc: glib wrapper for poppler
 
2
 * Copyright (C) 2005, Red Hat, Inc.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2, or (at your option)
 
7
 * any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
 
17
 */
 
18
 
 
19
#include "config.h"
 
20
#include <math.h>
 
21
 
 
22
#ifndef __GI_SCANNER__
 
23
#include <goo/GooList.h>
 
24
#include <GlobalParams.h>
 
25
#include <PDFDoc.h>
 
26
#include <Outline.h>
 
27
#include <ErrorCodes.h>
 
28
#include <UnicodeMap.h>
 
29
#include <GfxState.h>
 
30
#include <PageTransition.h>
 
31
#endif
 
32
 
 
33
#include "poppler.h"
 
34
#include "poppler-private.h"
 
35
 
 
36
/**
 
37
 * SECTION:poppler-page
 
38
 * @short_description: Information about a page in a document
 
39
 * @title: PopplerPage
 
40
 */
 
41
 
 
42
enum
 
43
{
 
44
  PROP_0,
 
45
  PROP_LABEL
 
46
};
 
47
 
 
48
typedef struct _PopplerPageClass PopplerPageClass;
 
49
struct _PopplerPageClass
 
50
{
 
51
  GObjectClass parent_class;
 
52
};
 
53
 
 
54
G_DEFINE_TYPE (PopplerPage, poppler_page, G_TYPE_OBJECT)
 
55
 
 
56
PopplerPage *
 
57
_poppler_page_new (PopplerDocument *document, Page *page, int index)
 
58
{
 
59
  PopplerPage *poppler_page;
 
60
 
 
61
  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL);
 
62
 
 
63
  poppler_page = (PopplerPage *) g_object_new (POPPLER_TYPE_PAGE, NULL, NULL);
 
64
  poppler_page->document = (PopplerDocument *) g_object_ref (document);
 
65
  poppler_page->page = page;
 
66
  poppler_page->index = index;
 
67
 
 
68
  return poppler_page;
 
69
}
 
70
 
 
71
static void
 
72
poppler_page_finalize (GObject *object)
 
73
{
 
74
  PopplerPage *page = POPPLER_PAGE (object);
 
75
 
 
76
  g_object_unref (page->document);
 
77
  page->document = NULL;
 
78
 
 
79
  if (page->annots != NULL)
 
80
    delete page->annots;
 
81
  if (page->text != NULL) 
 
82
    page->text->decRefCnt();
 
83
  /* page->page is owned by the document */
 
84
}
 
85
 
 
86
/**
 
87
 * poppler_page_get_size:
 
88
 * @page: A #PopplerPage
 
89
 * @width: (out) (allow-none): return location for the width of @page
 
90
 * @height: (out) (allow-none): return location for the height of @page
 
91
 * 
 
92
 * Gets the size of @page at the current scale and rotation.
 
93
 **/
 
94
void
 
95
poppler_page_get_size (PopplerPage *page,
 
96
                       double      *width,
 
97
                       double      *height)
 
98
{
 
99
  double page_width, page_height;
 
100
  int rotate;
 
101
 
 
102
  g_return_if_fail (POPPLER_IS_PAGE (page));
 
103
 
 
104
  rotate = page->page->getRotate ();
 
105
  if (rotate == 90 || rotate == 270) {
 
106
    page_height = page->page->getCropWidth ();
 
107
    page_width = page->page->getCropHeight ();
 
108
  } else {
 
109
    page_width = page->page->getCropWidth ();
 
110
    page_height = page->page->getCropHeight ();
 
111
  }
 
112
 
 
113
  if (width != NULL)
 
114
    *width = page_width;
 
115
  if (height != NULL)
 
116
    *height = page_height;
 
117
}
 
118
 
 
119
/**
 
120
 * poppler_page_get_index:
 
121
 * @page: a #PopplerPage
 
122
 * 
 
123
 * Returns the index of @page
 
124
 * 
 
125
 * Return value: index value of @page
 
126
 **/
 
127
int
 
128
poppler_page_get_index (PopplerPage *page)
 
129
{
 
130
  g_return_val_if_fail (POPPLER_IS_PAGE (page), 0);
 
131
 
 
132
  return page->index;
 
133
}
 
134
 
 
135
/**
 
136
 * poppler_page_get_label:
 
137
 * @page: a #PopplerPage
 
138
 *
 
139
 * Returns the label of @page. Note that page labels
 
140
 * and page indices might not coincide.
 
141
 *
 
142
 * Return value: a new allocated string containing the label of @page,
 
143
 *               or %NULL if @page doesn't have a label
 
144
 *
 
145
 * Since: 0.16
 
146
 **/
 
147
gchar *
 
148
poppler_page_get_label (PopplerPage *page)
 
149
{
 
150
  GooString label;
 
151
 
 
152
  g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL);
 
153
 
 
154
  page->document->doc->getCatalog ()->indexToLabel (page->index, &label);
 
155
  return _poppler_goo_string_to_utf8 (&label);
 
156
}
 
157
 
 
158
/**
 
159
 * poppler_page_get_duration:
 
160
 * @page: a #PopplerPage
 
161
 *
 
162
 * Returns the duration of @page
 
163
 *
 
164
 * Return value: duration in seconds of @page or -1.
 
165
 **/
 
166
double
 
167
poppler_page_get_duration (PopplerPage *page)
 
168
{
 
169
  g_return_val_if_fail (POPPLER_IS_PAGE (page), -1);
 
170
 
 
171
  return page->page->getDuration ();
 
172
}
 
173
 
 
174
/**
 
175
 * poppler_page_get_transition:
 
176
 * @page: a #PopplerPage
 
177
 *
 
178
 * Returns the transition effect of @page
 
179
 *
 
180
 * Return value: a #PopplerPageTransition or NULL.
 
181
 **/
 
182
PopplerPageTransition *
 
183
poppler_page_get_transition (PopplerPage *page)
 
184
{
 
185
  PageTransition *trans;
 
186
  PopplerPageTransition *transition;
 
187
  Object obj;
 
188
  
 
189
  g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL);
 
190
 
 
191
  trans = new PageTransition (page->page->getTrans (&obj));
 
192
  obj.free ();
 
193
 
 
194
  if (!trans->isOk ()) {
 
195
    delete trans;
 
196
    return NULL;
 
197
  }
 
198
 
 
199
  transition = poppler_page_transition_new ();
 
200
 
 
201
  switch (trans->getType ())
 
202
    {
 
203
      case transitionReplace:
 
204
        transition->type = POPPLER_PAGE_TRANSITION_REPLACE;
 
205
        break;
 
206
      case transitionSplit:
 
207
        transition->type = POPPLER_PAGE_TRANSITION_SPLIT;
 
208
        break;
 
209
      case transitionBlinds:
 
210
        transition->type = POPPLER_PAGE_TRANSITION_BLINDS;
 
211
        break;
 
212
      case transitionBox:
 
213
        transition->type = POPPLER_PAGE_TRANSITION_BOX;
 
214
        break;
 
215
      case transitionWipe:
 
216
        transition->type = POPPLER_PAGE_TRANSITION_WIPE;
 
217
        break;
 
218
      case transitionDissolve:
 
219
        transition->type = POPPLER_PAGE_TRANSITION_DISSOLVE;
 
220
        break;
 
221
      case transitionGlitter:
 
222
        transition->type = POPPLER_PAGE_TRANSITION_GLITTER;
 
223
        break;
 
224
      case transitionFly:
 
225
        transition->type = POPPLER_PAGE_TRANSITION_FLY;
 
226
        break;
 
227
      case transitionPush:
 
228
        transition->type = POPPLER_PAGE_TRANSITION_PUSH;
 
229
        break;
 
230
      case transitionCover:
 
231
        transition->type = POPPLER_PAGE_TRANSITION_COVER;
 
232
        break;
 
233
      case transitionUncover:
 
234
        transition->type = POPPLER_PAGE_TRANSITION_UNCOVER;
 
235
        break;
 
236
      case transitionFade:
 
237
        transition->type = POPPLER_PAGE_TRANSITION_FADE;
 
238
        break;
 
239
      default:
 
240
        g_assert_not_reached ();
 
241
    }
 
242
 
 
243
  transition->alignment = (trans->getAlignment() == transitionHorizontal) ?
 
244
          POPPLER_PAGE_TRANSITION_HORIZONTAL :
 
245
          POPPLER_PAGE_TRANSITION_VERTICAL;
 
246
 
 
247
  transition->direction = (trans->getDirection() == transitionInward) ?
 
248
          POPPLER_PAGE_TRANSITION_INWARD :
 
249
          POPPLER_PAGE_TRANSITION_OUTWARD;
 
250
 
 
251
  transition->duration = trans->getDuration();
 
252
  transition->angle = trans->getAngle();
 
253
  transition->scale = trans->getScale();
 
254
  transition->rectangular = trans->isRectangular();
 
255
  
 
256
  delete trans;
 
257
  
 
258
  return transition;
 
259
}
 
260
 
 
261
static TextPage *
 
262
poppler_page_get_text_page (PopplerPage *page)
 
263
{
 
264
  if (page->text == NULL) {
 
265
    TextOutputDev *text_dev;
 
266
    Gfx           *gfx;
 
267
 
 
268
    text_dev = new TextOutputDev (NULL, gTrue, gFalse, gFalse);
 
269
    gfx = page->page->createGfx(text_dev,
 
270
                                72.0, 72.0, 0,
 
271
                                gFalse, /* useMediaBox */
 
272
                                gTrue, /* Crop */
 
273
                                -1, -1, -1, -1,
 
274
                                gFalse, /* printing */
 
275
                                page->document->doc->getCatalog (),
 
276
                                NULL, NULL, NULL, NULL);
 
277
    page->page->display(gfx);
 
278
    text_dev->endPage();
 
279
 
 
280
    page->text = text_dev->takeText();
 
281
    delete gfx;
 
282
    delete text_dev;
 
283
  }
 
284
 
 
285
  return page->text;
 
286
}
 
287
 
 
288
#ifdef POPPLER_WITH_GDK
 
289
static void
 
290
copy_cairo_surface_to_pixbuf (cairo_surface_t *surface,
 
291
                              GdkPixbuf       *pixbuf)
 
292
{
 
293
  int cairo_width, cairo_height, cairo_rowstride;
 
294
  unsigned char *pixbuf_data, *dst, *cairo_data;
 
295
  int pixbuf_rowstride, pixbuf_n_channels;
 
296
  unsigned int *src;
 
297
  int x, y;
 
298
 
 
299
  cairo_width = cairo_image_surface_get_width (surface);
 
300
  cairo_height = cairo_image_surface_get_height (surface);
 
301
  cairo_rowstride = cairo_image_surface_get_stride (surface);
 
302
  cairo_data = cairo_image_surface_get_data (surface);
 
303
 
 
304
  pixbuf_data = gdk_pixbuf_get_pixels (pixbuf);
 
305
  pixbuf_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
 
306
  pixbuf_n_channels = gdk_pixbuf_get_n_channels (pixbuf);
 
307
 
 
308
  if (cairo_width > gdk_pixbuf_get_width (pixbuf))
 
309
    cairo_width = gdk_pixbuf_get_width (pixbuf);
 
310
  if (cairo_height > gdk_pixbuf_get_height (pixbuf))
 
311
    cairo_height = gdk_pixbuf_get_height (pixbuf);
 
312
  for (y = 0; y < cairo_height; y++)
 
313
    {
 
314
      src = (unsigned int *) (cairo_data + y * cairo_rowstride);
 
315
      dst = pixbuf_data + y * pixbuf_rowstride;
 
316
      for (x = 0; x < cairo_width; x++) 
 
317
        {
 
318
          dst[0] = (*src >> 16) & 0xff;
 
319
          dst[1] = (*src >> 8) & 0xff; 
 
320
          dst[2] = (*src >> 0) & 0xff;
 
321
          if (pixbuf_n_channels == 4)
 
322
              dst[3] = (*src >> 24) & 0xff;
 
323
          dst += pixbuf_n_channels;
 
324
          src++;
 
325
        }
 
326
    }
 
327
}       
 
328
#endif /* POPPLER_WITH_GDK */
 
329
 
 
330
static gboolean
 
331
annot_is_markup (Annot *annot)
 
332
{
 
333
  switch (annot->getType())
 
334
    {
 
335
      case Annot::typeLink:
 
336
      case Annot::typePopup:
 
337
      case Annot::typeMovie:
 
338
      case Annot::typeScreen:
 
339
      case Annot::typePrinterMark:
 
340
      case Annot::typeTrapNet:
 
341
      case Annot::typeWatermark:
 
342
      case Annot::type3D:
 
343
      case Annot::typeWidget:
 
344
        return FALSE;
 
345
      default:
 
346
        return TRUE;
 
347
    }
 
348
}
 
349
 
 
350
static GBool
 
351
poppler_print_annot_cb (Annot *annot, void *user_data)
 
352
{
 
353
  PopplerPrintFlags user_print_flags = (PopplerPrintFlags)GPOINTER_TO_INT (user_data);
 
354
 
 
355
  if (annot->getFlags () & Annot::flagHidden)
 
356
    return gFalse;
 
357
 
 
358
  if (user_print_flags & POPPLER_PRINT_STAMP_ANNOTS_ONLY) {
 
359
    return (annot->getType() == Annot::typeStamp) ?
 
360
            (annot->getFlags () & Annot::flagPrint) :
 
361
            (annot->getType() == Annot::typeWidget);
 
362
  }
 
363
 
 
364
  if (user_print_flags & POPPLER_PRINT_MARKUP_ANNOTS) {
 
365
    return annot_is_markup (annot) ?
 
366
            (annot->getFlags () & Annot::flagPrint) :
 
367
            (annot->getType() == Annot::typeWidget);
 
368
  }
 
369
 
 
370
  /* Print document only, form fields are always printed */
 
371
  return (annot->getType() == Annot::typeWidget);
 
372
}
 
373
 
 
374
static void
 
375
_poppler_page_render (PopplerPage      *page,
 
376
                      cairo_t          *cairo,
 
377
                      GBool             printing,
 
378
                      PopplerPrintFlags print_flags)
 
379
{
 
380
  CairoOutputDev *output_dev;
 
381
 
 
382
  g_return_if_fail (POPPLER_IS_PAGE (page));
 
383
 
 
384
  output_dev = page->document->output_dev;
 
385
  output_dev->setCairo (cairo);
 
386
  output_dev->setPrinting (printing);
 
387
 
 
388
  if (!printing)
 
389
    output_dev->setTextPage (page->text);
 
390
 
 
391
  /* NOTE: instead of passing -1 we should/could use cairo_clip_extents()
 
392
   * to get a bounding box */
 
393
  cairo_save (cairo);
 
394
  page->page->displaySlice(output_dev,
 
395
                           72.0, 72.0, 0,
 
396
                           gFalse, /* useMediaBox */
 
397
                           gTrue, /* Crop */
 
398
                           -1, -1,
 
399
                           -1, -1,
 
400
                           printing,
 
401
                           page->document->doc->getCatalog (),
 
402
                           NULL, NULL,
 
403
                           printing ? poppler_print_annot_cb : NULL,
 
404
                           printing ? GINT_TO_POINTER ((gint)print_flags) : NULL);
 
405
  cairo_restore (cairo);
 
406
 
 
407
  output_dev->setCairo (NULL);
 
408
  output_dev->setTextPage (NULL);
 
409
}
 
410
 
 
411
/**
 
412
 * poppler_page_render:
 
413
 * @page: the page to render from
 
414
 * @cairo: cairo context to render to
 
415
 *
 
416
 * Render the page to the given cairo context. This function
 
417
 * is for rendering a page that will be displayed. If you want
 
418
 * to render a page that will be printed use
 
419
 * poppler_page_render_for_printing() instead
 
420
 **/
 
421
void
 
422
poppler_page_render (PopplerPage *page,
 
423
                     cairo_t *cairo)
 
424
{
 
425
  g_return_if_fail (POPPLER_IS_PAGE (page));
 
426
 
 
427
  if (!page->text)
 
428
    page->text = new TextPage(gFalse);
 
429
 
 
430
  _poppler_page_render (page, cairo, gFalse, (PopplerPrintFlags)0);
 
431
}
 
432
 
 
433
/**
 
434
 * poppler_page_render_for_printing_with_options:
 
435
 * @page: the page to render from
 
436
 * @cairo: cairo context to render to
 
437
 * @options: print options
 
438
 *
 
439
 * Render the page to the given cairo context for printing
 
440
 * with the specified options
 
441
 *
 
442
 * Since: 0.16
 
443
 **/
 
444
void
 
445
poppler_page_render_for_printing_with_options (PopplerPage      *page,
 
446
                                               cairo_t          *cairo,
 
447
                                               PopplerPrintFlags options)
 
448
{
 
449
  g_return_if_fail (POPPLER_IS_PAGE (page));
 
450
 
 
451
  _poppler_page_render (page, cairo, gTrue, options);
 
452
}
 
453
 
 
454
/**
 
455
 * poppler_page_render_for_printing:
 
456
 * @page: the page to render from
 
457
 * @cairo: cairo context to render to
 
458
 *
 
459
 * Render the page to the given cairo context for printing.
 
460
 **/
 
461
void
 
462
poppler_page_render_for_printing (PopplerPage *page,
 
463
                                  cairo_t *cairo)
 
464
{
 
465
  g_return_if_fail (POPPLER_IS_PAGE (page));
 
466
 
 
467
  _poppler_page_render (page, cairo, gTrue, POPPLER_PRINT_ALL);
 
468
}
 
469
 
 
470
static cairo_surface_t *
 
471
create_surface_from_thumbnail_data (guchar *data,
 
472
                                    gint    width,
 
473
                                    gint    height,
 
474
                                    gint    rowstride)
 
475
{
 
476
  guchar *cairo_pixels;
 
477
  gint cairo_stride;
 
478
  cairo_surface_t *surface;
 
479
  int j;
 
480
 
 
481
  surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
 
482
  if (cairo_surface_status (surface))
 
483
    return NULL;
 
484
 
 
485
  cairo_pixels = cairo_image_surface_get_data (surface);
 
486
  cairo_stride = cairo_image_surface_get_stride (surface);
 
487
 
 
488
  for (j = height; j; j--) {
 
489
    guchar *p = data;
 
490
    guchar *q = cairo_pixels;
 
491
    guchar *end = p + 3 * width;
 
492
 
 
493
    while (p < end) {
 
494
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
 
495
      q[0] = p[2];
 
496
      q[1] = p[1];
 
497
      q[2] = p[0];
 
498
#else
 
499
      q[1] = p[0];
 
500
      q[2] = p[1];
 
501
      q[3] = p[2];
 
502
#endif
 
503
      p += 3;
 
504
      q += 4;
 
505
    }
 
506
 
 
507
    data += rowstride;
 
508
    cairo_pixels += cairo_stride;
 
509
  }
 
510
 
 
511
  return surface;
 
512
}
 
513
                                    
 
514
 
 
515
/**
 
516
 * poppler_page_get_thumbnail:
 
517
 * @page: the #PopperPage to get the thumbnail for
 
518
 * 
 
519
 * Get the embedded thumbnail for the specified page.  If the document
 
520
 * doesn't have an embedded thumbnail for the page, this function
 
521
 * returns %NULL.
 
522
 * 
 
523
 * Return value: the tumbnail as a cairo_surface_t or %NULL if the document
 
524
 * doesn't have a thumbnail for this page.
 
525
 **/
 
526
cairo_surface_t *
 
527
poppler_page_get_thumbnail (PopplerPage *page)
 
528
{
 
529
  unsigned char *data;
 
530
  int width, height, rowstride;
 
531
  cairo_surface_t *surface;
 
532
 
 
533
  g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL);
 
534
 
 
535
  if (!page->page->loadThumb (&data, &width, &height, &rowstride))
 
536
    return NULL;
 
537
 
 
538
  surface = create_surface_from_thumbnail_data (data, width, height, rowstride);
 
539
  gfree (data);
 
540
  
 
541
  return surface;
 
542
}
 
543
 
 
544
/**
 
545
 * poppler_page_render_selection:
 
546
 * @page: the #PopplerPage for which to render selection
 
547
 * @cairo: cairo context to render to
 
548
 * @selection: start and end point of selection as a rectangle
 
549
 * @old_selection: previous selection
 
550
 * @style: a #PopplerSelectionStyle
 
551
 * @glyph_color: color to use for drawing glyphs
 
552
 * @background_color: color to use for the selection background
 
553
 *
 
554
 * Render the selection specified by @selection for @page to
 
555
 * the given cairo context.  The selection will be rendered, using
 
556
 * @glyph_color for the glyphs and @background_color for the selection
 
557
 * background.
 
558
 *
 
559
 * If non-NULL, @old_selection specifies the selection that is already
 
560
 * rendered to @cairo, in which case this function will (some day)
 
561
 * only render the changed part of the selection.
 
562
 **/
 
563
void
 
564
poppler_page_render_selection (PopplerPage           *page,
 
565
                               cairo_t               *cairo,
 
566
                               PopplerRectangle      *selection,
 
567
                               PopplerRectangle      *old_selection,
 
568
                               PopplerSelectionStyle  style, 
 
569
                               PopplerColor          *glyph_color,
 
570
                               PopplerColor          *background_color)
 
571
{
 
572
  CairoOutputDev *output_dev;
 
573
  TextPage *text;
 
574
  SelectionStyle selection_style = selectionStyleGlyph;
 
575
  PDFRectangle pdf_selection(selection->x1, selection->y1,
 
576
                             selection->x2, selection->y2);
 
577
 
 
578
  GfxColor gfx_background_color = {
 
579
      {
 
580
          background_color->red,
 
581
          background_color->green,
 
582
          background_color->blue
 
583
      }
 
584
  };
 
585
  GfxColor gfx_glyph_color = {
 
586
      {
 
587
          glyph_color->red,
 
588
          glyph_color->green,
 
589
          glyph_color->blue
 
590
      }
 
591
  };
 
592
 
 
593
  switch (style)
 
594
    {
 
595
      case POPPLER_SELECTION_GLYPH:
 
596
        selection_style = selectionStyleGlyph;
 
597
        break;
 
598
      case POPPLER_SELECTION_WORD:
 
599
        selection_style = selectionStyleWord;
 
600
        break;
 
601
      case POPPLER_SELECTION_LINE:
 
602
        selection_style = selectionStyleLine;
 
603
        break;
 
604
    }
 
605
 
 
606
  output_dev = page->document->output_dev;
 
607
  output_dev->setCairo (cairo);
 
608
 
 
609
  text = poppler_page_get_text_page (page);
 
610
  text->drawSelection (output_dev, 1.0, 0,
 
611
                       &pdf_selection, selection_style,
 
612
                       &gfx_glyph_color, &gfx_background_color);
 
613
 
 
614
  output_dev->setCairo (NULL);
 
615
}
 
616
 
 
617
#ifdef POPPLER_WITH_GDK
 
618
static void
 
619
_poppler_page_render_to_pixbuf (PopplerPage *page,
 
620
                                int src_x, int src_y,
 
621
                                int src_width, int src_height,
 
622
                                double scale,
 
623
                                int rotation,
 
624
                                GBool printing,
 
625
                                GdkPixbuf *pixbuf)
 
626
{
 
627
  cairo_t *cr;
 
628
  cairo_surface_t *surface;
 
629
 
 
630
  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
 
631
                                        src_width, src_height);
 
632
  cr = cairo_create (surface);
 
633
  cairo_save (cr);
 
634
  switch (rotation) {
 
635
  case 90:
 
636
          cairo_translate (cr, src_x + src_width, -src_y);
 
637
          break;
 
638
  case 180:
 
639
          cairo_translate (cr, src_x + src_width, src_y + src_height);
 
640
          break;
 
641
  case 270:
 
642
          cairo_translate (cr, -src_x, src_y + src_height);
 
643
          break;
 
644
  default:
 
645
          cairo_translate (cr, -src_x, -src_y);
 
646
  }
 
647
 
 
648
  if (scale != 1.0)
 
649
          cairo_scale (cr, scale, scale);
 
650
 
 
651
  if (rotation != 0)
 
652
          cairo_rotate (cr, rotation * G_PI / 180.0);
 
653
 
 
654
  if (printing)
 
655
          poppler_page_render_for_printing (page, cr);
 
656
  else
 
657
          poppler_page_render (page, cr);
 
658
  cairo_restore (cr);
 
659
 
 
660
  cairo_set_operator (cr, CAIRO_OPERATOR_DEST_OVER);
 
661
  cairo_set_source_rgb (cr, 1., 1., 1.);
 
662
  cairo_paint (cr);
 
663
 
 
664
  cairo_destroy (cr);
 
665
 
 
666
  copy_cairo_surface_to_pixbuf (surface, pixbuf);
 
667
  cairo_surface_destroy (surface);
 
668
}
 
669
 
 
670
/**
 
671
 * poppler_page_render_to_pixbuf:
 
672
 * @page: the page to render from
 
673
 * @src_x: x coordinate of upper left corner  
 
674
 * @src_y: y coordinate of upper left corner  
 
675
 * @src_width: width of rectangle to render  
 
676
 * @src_height: height of rectangle to render
 
677
 * @scale: scale specified as pixels per point
 
678
 * @rotation: rotate the document by the specified degree
 
679
 * @pixbuf: pixbuf to render into
 
680
 *
 
681
 * First scale the document to match the specified pixels per point,
 
682
 * then render the rectangle given by the upper left corner at
 
683
 * (src_x, src_y) and src_width and src_height.
 
684
 * This function is for rendering a page that will be displayed.
 
685
 * If you want to render a page that will be printed use
 
686
 * poppler_page_render_to_pixbuf_for_printing() instead
 
687
 *
 
688
 * Deprecated: 0.16
 
689
 **/
 
690
void
 
691
poppler_page_render_to_pixbuf (PopplerPage *page,
 
692
                               int src_x, int src_y,
 
693
                               int src_width, int src_height,
 
694
                               double scale,
 
695
                               int rotation,
 
696
                               GdkPixbuf *pixbuf)
 
697
{
 
698
  g_return_if_fail (POPPLER_IS_PAGE (page));
 
699
  g_return_if_fail (scale > 0.0);
 
700
  g_return_if_fail (pixbuf != NULL);
 
701
 
 
702
  _poppler_page_render_to_pixbuf (page, src_x, src_y,
 
703
                                  src_width, src_height,
 
704
                                  scale, rotation,
 
705
                                  gFalse,
 
706
                                  pixbuf);
 
707
}
 
708
 
 
709
/**
 
710
 * poppler_page_render_to_pixbuf_for_printing:
 
711
 * @page: the page to render from
 
712
 * @src_x: x coordinate of upper left corner  
 
713
 * @src_y: y coordinate of upper left corner  
 
714
 * @src_width: width of rectangle to render  
 
715
 * @src_height: height of rectangle to render
 
716
 * @scale: scale specified as pixels per point
 
717
 * @rotation: rotate the document by the specified degree
 
718
 * @pixbuf: pixbuf to render into
 
719
 *
 
720
 * First scale the document to match the specified pixels per point,
 
721
 * then render the rectangle given by the upper left corner at
 
722
 * (src_x, src_y) and src_width and src_height.
 
723
 * This function is for rendering a page that will be printed.
 
724
 *
 
725
 * Deprecated: 0.16
 
726
 **/
 
727
void
 
728
poppler_page_render_to_pixbuf_for_printing (PopplerPage *page,
 
729
                                            int src_x, int src_y,
 
730
                                            int src_width, int src_height,
 
731
                                            double scale,
 
732
                                            int rotation,
 
733
                                            GdkPixbuf *pixbuf)
 
734
{
 
735
  g_return_if_fail (POPPLER_IS_PAGE (page));
 
736
  g_return_if_fail (scale > 0.0);
 
737
  g_return_if_fail (pixbuf != NULL);
 
738
 
 
739
  _poppler_page_render_to_pixbuf (page, src_x, src_y,
 
740
                                  src_width, src_height,
 
741
                                  scale, rotation,
 
742
                                  gTrue,
 
743
                                  pixbuf);
 
744
}
 
745
 
 
746
/**
 
747
 * poppler_page_get_thumbnail_pixbuf:
 
748
 * @page: the #PopperPage to get the thumbnail for
 
749
 * 
 
750
 * Get the embedded thumbnail for the specified page.  If the document
 
751
 * doesn't have an embedded thumbnail for the page, this function
 
752
 * returns %NULL.
 
753
 * 
 
754
 * Return value: the tumbnail as a #GdkPixbuf or %NULL if the document
 
755
 * doesn't have a thumbnail for this page.
 
756
 *
 
757
 * Deprecated: 0.16
 
758
 **/
 
759
GdkPixbuf *
 
760
poppler_page_get_thumbnail_pixbuf (PopplerPage *page)
 
761
{
 
762
  unsigned char *data;
 
763
  int width, height, rowstride;
 
764
 
 
765
  g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL);
 
766
 
 
767
  if (!page->page->loadThumb (&data, &width, &height, &rowstride))
 
768
    return NULL;
 
769
 
 
770
  return gdk_pixbuf_new_from_data (data, GDK_COLORSPACE_RGB,
 
771
                                   FALSE, 8, width, height, rowstride,
 
772
                                   (GdkPixbufDestroyNotify)gfree, NULL);
 
773
}
 
774
 
 
775
/**
 
776
 * poppler_page_render_selection_to_pixbuf:
 
777
 * @page: the #PopplerPage for which to render selection
 
778
 * @scale: scale specified as pixels per point
 
779
 * @rotation: rotate the document by the specified degree
 
780
 * @pixbuf: pixbuf to render to
 
781
 * @selection: start and end point of selection as a rectangle
 
782
 * @old_selection: previous selection
 
783
 * @style: a #PopplerSelectionStyle
 
784
 * @glyph_color: color to use for drawing glyphs
 
785
 * @background_color: color to use for the selection background
 
786
 * 
 
787
 * Render the selection specified by @selection for @page into
 
788
 * @pixbuf.  The selection will be rendered at @scale, using
 
789
 * @glyph_color for the glyphs and @background_color for the selection
 
790
 * background.
 
791
 *
 
792
 * If non-NULL, @old_selection specifies the selection that is already
 
793
 * rendered in @pixbuf, in which case this function will (some day)
 
794
 * only render the changed part of the selection.
 
795
 *
 
796
 * Deprecated: 0.16
 
797
 **/
 
798
void
 
799
poppler_page_render_selection_to_pixbuf (PopplerPage           *page,
 
800
                                         gdouble                scale,
 
801
                                         int                    rotation,
 
802
                                         GdkPixbuf             *pixbuf,
 
803
                                         PopplerRectangle      *selection,
 
804
                                         PopplerRectangle      *old_selection,
 
805
                                         PopplerSelectionStyle  style,
 
806
                                         GdkColor              *glyph_color,
 
807
                                         GdkColor              *background_color)
 
808
{
 
809
  cairo_t *cr;
 
810
  cairo_surface_t *surface;
 
811
  double width, height;
 
812
  int cairo_width, cairo_height, rotate;
 
813
  PopplerColor poppler_background_color;
 
814
  PopplerColor poppler_glyph_color;
 
815
 
 
816
  poppler_background_color.red = background_color->red;
 
817
  poppler_background_color.green = background_color->green;
 
818
  poppler_background_color.blue = background_color->blue;
 
819
  poppler_glyph_color.red = glyph_color->red;
 
820
  poppler_glyph_color.green = glyph_color->green;
 
821
  poppler_glyph_color.blue = glyph_color->blue;
 
822
 
 
823
  rotate = rotation + page->page->getRotate ();
 
824
  if (rotate == 90 || rotate == 270) {
 
825
    height = page->page->getCropWidth ();
 
826
    width = page->page->getCropHeight ();
 
827
  } else {
 
828
    width = page->page->getCropWidth ();
 
829
    height = page->page->getCropHeight ();
 
830
  }
 
831
 
 
832
  cairo_width = (int) ceil(width * scale);
 
833
  cairo_height = (int) ceil(height * scale);
 
834
 
 
835
  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
 
836
                                        cairo_width, cairo_height);
 
837
  cr = cairo_create (surface);
 
838
  cairo_set_source_rgba (cr, 0, 0, 0, 0);
 
839
  cairo_paint (cr);
 
840
 
 
841
  switch (rotate) {
 
842
  case 90:
 
843
          cairo_translate (cr, cairo_width, 0);
 
844
          break;
 
845
  case 180:
 
846
          cairo_translate (cr, cairo_width, cairo_height);
 
847
          break;
 
848
  case 270:
 
849
          cairo_translate (cr, 0, cairo_height);
 
850
          break;
 
851
  default:
 
852
          cairo_translate (cr, 0, 0);
 
853
  }
 
854
  if (scale != 1.0)
 
855
          cairo_scale (cr, scale, scale);
 
856
 
 
857
  if (rotate != 0)
 
858
          cairo_rotate (cr, rotation * G_PI / 180.0);
 
859
 
 
860
  poppler_page_render_selection (page, cr, selection, old_selection, style,
 
861
                                 &poppler_glyph_color, &poppler_background_color);
 
862
 
 
863
  cairo_destroy (cr);
 
864
 
 
865
  copy_cairo_surface_to_pixbuf (surface, pixbuf);
 
866
  cairo_surface_destroy (surface);
 
867
}
 
868
 
 
869
#endif /* POPPLER_WITH_GDK */
 
870
 
 
871
/**
 
872
 * poppler_page_get_thumbnail_size:
 
873
 * @page: A #PopplerPage
 
874
 * @width: (out) return location for width
 
875
 * @height: (out) return location for height
 
876
 *
 
877
 * Returns %TRUE if @page has a thumbnail associated with it.  It also
 
878
 * fills in @width and @height with the width and height of the
 
879
 * thumbnail.  The values of width and height are not changed if no
 
880
 * appropriate thumbnail exists.
 
881
 *
 
882
 * Return value: %TRUE, if @page has a thumbnail associated with it.
 
883
 **/
 
884
gboolean
 
885
poppler_page_get_thumbnail_size (PopplerPage *page,
 
886
                                 int         *width,
 
887
                                 int         *height)
 
888
{
 
889
  Object thumb;
 
890
  Dict *dict;
 
891
  gboolean retval = FALSE;
 
892
 
 
893
  g_return_val_if_fail (POPPLER_IS_PAGE (page), FALSE);
 
894
  g_return_val_if_fail (width != NULL, FALSE);
 
895
  g_return_val_if_fail (height != NULL, FALSE);
 
896
 
 
897
  page->page->getThumb (&thumb);
 
898
  if (!thumb.isStream ())
 
899
    {
 
900
      thumb.free ();
 
901
      return FALSE;
 
902
    }
 
903
 
 
904
  dict = thumb.streamGetDict();
 
905
 
 
906
  /* Theoretically, this could succeed and you would still fail when
 
907
   * loading the thumb */
 
908
  if (dict->lookupInt ("Width", "W", width)  &&
 
909
      dict->lookupInt ("Height", "H", height))
 
910
    retval = TRUE;
 
911
 
 
912
  thumb.free ();
 
913
 
 
914
  return retval;
 
915
}
 
916
 
 
917
/**
 
918
 * poppler_page_get_selection_region:
 
919
 * @page: a #PopplerPage
 
920
 * @scale: scale specified as pixels per point
 
921
 * @style: a #PopplerSelectionStyle
 
922
 * @selection: start and end point of selection as a rectangle
 
923
 * 
 
924
 * Returns a region containing the area that would be rendered by
 
925
 * poppler_page_render_selection() or 
 
926
 * poppler_page_render_selection_to_pixbuf() as a #GList of
 
927
 * #PopplerRectangle. The returned list must be freed with
 
928
 * poppler_page_selection_region_free().
 
929
 * 
 
930
 * Return value: (element-type PopplerRectangle) (transfer full): a #GList of #PopplerRectangle
 
931
 *
 
932
 * Deprecated: 0.16: Use poppler_page_get_selected_region() instead.
 
933
 **/
 
934
GList *
 
935
poppler_page_get_selection_region (PopplerPage           *page,
 
936
                                   gdouble                scale,
 
937
                                   PopplerSelectionStyle  style,
 
938
                                   PopplerRectangle      *selection)
 
939
{
 
940
  PDFRectangle poppler_selection;
 
941
  TextPage *text;
 
942
  SelectionStyle selection_style = selectionStyleGlyph;
 
943
  GooList *list;
 
944
  GList *region = NULL;
 
945
  int i;
 
946
 
 
947
  poppler_selection.x1 = selection->x1;
 
948
  poppler_selection.y1 = selection->y1;
 
949
  poppler_selection.x2 = selection->x2;
 
950
  poppler_selection.y2 = selection->y2;
 
951
 
 
952
  switch (style)
 
953
    {
 
954
      case POPPLER_SELECTION_GLYPH:
 
955
        selection_style = selectionStyleGlyph;
 
956
        break;
 
957
      case POPPLER_SELECTION_WORD:
 
958
        selection_style = selectionStyleWord;
 
959
        break;
 
960
      case POPPLER_SELECTION_LINE:
 
961
        selection_style = selectionStyleLine;
 
962
        break;
 
963
    }
 
964
 
 
965
  text = poppler_page_get_text_page (page);
 
966
  list = text->getSelectionRegion(&poppler_selection,
 
967
                                  selection_style, scale);
 
968
 
 
969
  for (i = 0; i < list->getLength(); i++) {
 
970
    PDFRectangle *selection_rect = (PDFRectangle *) list->get(i);
 
971
    PopplerRectangle *rect;
 
972
 
 
973
    rect = poppler_rectangle_new ();
 
974
    
 
975
    rect->x1 = selection_rect->x1;
 
976
    rect->y1 = selection_rect->y1;
 
977
    rect->x2 = selection_rect->x2;
 
978
    rect->y2 = selection_rect->y2;
 
979
    
 
980
    region = g_list_prepend (region, rect);
 
981
    
 
982
    delete selection_rect;
 
983
  }
 
984
 
 
985
  delete list;
 
986
 
 
987
  return g_list_reverse (region);
 
988
}
 
989
 
 
990
/**
 
991
 * poppler_page_selection_region_free:
 
992
 * @region: a #GList of #PopplerRectangle
 
993
 *
 
994
 * Frees @region
 
995
 *
 
996
 * Deprecated: 0.16
 
997
 */
 
998
void
 
999
poppler_page_selection_region_free (GList *region)
 
1000
{
 
1001
  if (G_UNLIKELY (!region))
 
1002
    return;
 
1003
 
 
1004
  g_list_foreach (region, (GFunc)poppler_rectangle_free, NULL);
 
1005
  g_list_free (region);
 
1006
}
 
1007
 
 
1008
/**
 
1009
 * poppler_page_get_selected_region:
 
1010
 * @page: a #PopplerPage
 
1011
 * @scale: scale specified as pixels per point
 
1012
 * @style: a #PopplerSelectionStyle
 
1013
 * @selection: start and end point of selection as a rectangle
 
1014
 *
 
1015
 * Returns a region containing the area that would be rendered by
 
1016
 * poppler_page_render_selection() or
 
1017
 * poppler_page_render_selection_to_pixbuf().
 
1018
 * The returned region must be freed with cairo_region_destroy()
 
1019
 *
 
1020
 * Return value: (transfer full): a cairo_region_t
 
1021
 *
 
1022
 * Since: 0.16
 
1023
 **/
 
1024
cairo_region_t *
 
1025
poppler_page_get_selected_region (PopplerPage           *page,
 
1026
                                  gdouble                scale,
 
1027
                                  PopplerSelectionStyle  style,
 
1028
                                  PopplerRectangle      *selection)
 
1029
{
 
1030
  PDFRectangle poppler_selection;
 
1031
  TextPage *text;
 
1032
  SelectionStyle selection_style = selectionStyleGlyph;
 
1033
  GooList *list;
 
1034
  cairo_region_t *region;
 
1035
  int i;
 
1036
 
 
1037
  poppler_selection.x1 = selection->x1;
 
1038
  poppler_selection.y1 = selection->y1;
 
1039
  poppler_selection.x2 = selection->x2;
 
1040
  poppler_selection.y2 = selection->y2;
 
1041
 
 
1042
  switch (style)
 
1043
    {
 
1044
      case POPPLER_SELECTION_GLYPH:
 
1045
        selection_style = selectionStyleGlyph;
 
1046
        break;
 
1047
      case POPPLER_SELECTION_WORD:
 
1048
        selection_style = selectionStyleWord;
 
1049
        break;
 
1050
      case POPPLER_SELECTION_LINE:
 
1051
        selection_style = selectionStyleLine;
 
1052
        break;
 
1053
    }
 
1054
 
 
1055
  text = poppler_page_get_text_page (page);
 
1056
  list = text->getSelectionRegion(&poppler_selection,
 
1057
                                  selection_style, 1.0);
 
1058
 
 
1059
  region = cairo_region_create ();
 
1060
 
 
1061
  for (i = 0; i < list->getLength(); i++) {
 
1062
    PDFRectangle *selection_rect = (PDFRectangle *) list->get(i);
 
1063
    cairo_rectangle_int_t rect;
 
1064
 
 
1065
    rect.x = (gint) ((selection_rect->x1 * scale) + 0.5);
 
1066
    rect.y = (gint) ((selection_rect->y1 * scale) + 0.5);
 
1067
    rect.width = (gint) (((selection_rect->x2 - selection_rect->x1) * scale) + 0.5);
 
1068
    rect.height = (gint) (((selection_rect->y2 - selection_rect->y1) * scale) + 0.5);
 
1069
    cairo_region_union_rectangle (region, &rect);
 
1070
 
 
1071
    delete selection_rect;
 
1072
  }
 
1073
 
 
1074
  delete list;
 
1075
 
 
1076
  return region;
 
1077
}
 
1078
 
 
1079
/**
 
1080
 * poppler_page_get_selected_text:
 
1081
 * @page: a #PopplerPage
 
1082
 * @style: a #PopplerSelectionStyle
 
1083
 * @selection: the #PopplerRectangle including the text
 
1084
 *
 
1085
 * Retrieves the contents of the specified @selection as text.
 
1086
 *
 
1087
 * Return value: a pointer to the contents of the @selection
 
1088
 *               as a string
 
1089
 * Since: 0.16
 
1090
 **/
 
1091
char *
 
1092
poppler_page_get_selected_text (PopplerPage          *page,
 
1093
                                PopplerSelectionStyle style,
 
1094
                                PopplerRectangle     *selection)
 
1095
{
 
1096
  GooString *sel_text;
 
1097
  char *result;
 
1098
  TextPage *text;
 
1099
  SelectionStyle selection_style = selectionStyleGlyph;
 
1100
  PDFRectangle pdf_selection;
 
1101
 
 
1102
  g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL);
 
1103
  g_return_val_if_fail (selection != NULL, NULL);
 
1104
 
 
1105
  pdf_selection.x1 = selection->x1;
 
1106
  pdf_selection.y1 = selection->y1;
 
1107
  pdf_selection.x2 = selection->x2;
 
1108
  pdf_selection.y2 = selection->y2;
 
1109
 
 
1110
  switch (style)
 
1111
    {
 
1112
      case POPPLER_SELECTION_GLYPH:
 
1113
        selection_style = selectionStyleGlyph;
 
1114
        break;
 
1115
      case POPPLER_SELECTION_WORD:
 
1116
        selection_style = selectionStyleWord;
 
1117
        break;
 
1118
      case POPPLER_SELECTION_LINE:
 
1119
        selection_style = selectionStyleLine;
 
1120
        break;
 
1121
    }
 
1122
 
 
1123
  text = poppler_page_get_text_page (page);
 
1124
  sel_text = text->getSelectionText (&pdf_selection, selection_style);
 
1125
  result = g_strdup (sel_text->getCString ());
 
1126
  delete sel_text;
 
1127
 
 
1128
  return result;
 
1129
}
 
1130
 
 
1131
/**
 
1132
 * poppler_page_get_text:
 
1133
 * @page: a #PopplerPage
 
1134
 *
 
1135
 * Retrieves the text of @page.
 
1136
 *
 
1137
 * Return value: a pointer to the text of the @page
 
1138
 *               as a string
 
1139
 * Since: 0.16
 
1140
 **/
 
1141
char *
 
1142
poppler_page_get_text (PopplerPage *page)
 
1143
{
 
1144
  PopplerRectangle rectangle = {0, 0, 0, 0};
 
1145
 
 
1146
  g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL);
 
1147
 
 
1148
  poppler_page_get_size (page, &rectangle.x2, &rectangle.y2);
 
1149
 
 
1150
  return poppler_page_get_selected_text (page, POPPLER_SELECTION_GLYPH, &rectangle);
 
1151
}
 
1152
 
 
1153
/**
 
1154
 * poppler_page_find_text:
 
1155
 * @page: a #PopplerPage
 
1156
 * @text: the text to search for (UTF-8 encoded)
 
1157
 * 
 
1158
 * A #GList of rectangles for each occurance of the text on the page.
 
1159
 * The coordinates are in PDF points.
 
1160
 * 
 
1161
 * Return value: (element-type PopplerRectangle) (transfer full): a #GList of #PopplerRectangle,
 
1162
 **/
 
1163
GList *
 
1164
poppler_page_find_text (PopplerPage *page,
 
1165
                        const char  *text)
 
1166
{
 
1167
  PopplerRectangle *match;
 
1168
  GList *matches;
 
1169
  double xMin, yMin, xMax, yMax;
 
1170
  gunichar *ucs4;
 
1171
  glong ucs4_len;
 
1172
  double height;
 
1173
  TextPage *text_dev;
 
1174
 
 
1175
  g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL);
 
1176
  g_return_val_if_fail (text != NULL, NULL);
 
1177
 
 
1178
  text_dev = poppler_page_get_text_page (page);
 
1179
 
 
1180
  ucs4 = g_utf8_to_ucs4_fast (text, -1, &ucs4_len);
 
1181
  poppler_page_get_size (page, NULL, &height);
 
1182
  
 
1183
  matches = NULL;
 
1184
  xMin = 0;
 
1185
  yMin = 0;
 
1186
 
 
1187
  while (text_dev->findText (ucs4, ucs4_len,
 
1188
                             gFalse, gTrue, // startAtTop, stopAtBottom
 
1189
                             gFalse, gFalse, // startAtLast, stopAtLast
 
1190
                             gFalse, gFalse, // caseSensitive, backwards
 
1191
                             &xMin, &yMin, &xMax, &yMax))
 
1192
    {
 
1193
      match = poppler_rectangle_new ();
 
1194
      match->x1 = xMin;
 
1195
      match->y1 = height - yMax;
 
1196
      match->x2 = xMax;
 
1197
      match->y2 = height - yMin;
 
1198
      matches = g_list_prepend (matches, match);
 
1199
    }
 
1200
 
 
1201
  g_free (ucs4);
 
1202
 
 
1203
  return g_list_reverse (matches);
 
1204
}
 
1205
 
 
1206
static CairoImageOutputDev *
 
1207
poppler_page_get_image_output_dev (PopplerPage *page,
 
1208
                                   GBool (*imgDrawDeviceCbk)(int img_id, void *data),
 
1209
                                   void *imgDrawCbkData)
 
1210
{
 
1211
  CairoImageOutputDev *image_dev;
 
1212
  Gfx *gfx;
 
1213
  
 
1214
  image_dev = new CairoImageOutputDev ();
 
1215
 
 
1216
  if (imgDrawDeviceCbk) {
 
1217
    image_dev->setImageDrawDecideCbk (imgDrawDeviceCbk,
 
1218
                                      imgDrawCbkData);
 
1219
  }
 
1220
 
 
1221
  gfx = page->page->createGfx(image_dev,
 
1222
                              72.0, 72.0, 0,
 
1223
                              gFalse, /* useMediaBox */
 
1224
                              gTrue, /* Crop */
 
1225
                              -1, -1, -1, -1,
 
1226
                              gFalse, /* printing */
 
1227
                              page->document->doc->getCatalog (),
 
1228
                              NULL, NULL, NULL, NULL);
 
1229
  page->page->display(gfx);
 
1230
  delete gfx;
 
1231
 
 
1232
  return image_dev;
 
1233
}
 
1234
 
 
1235
/**
 
1236
 * poppler_page_get_image_mapping:
 
1237
 * @page: A #PopplerPage
 
1238
 *
 
1239
 * Returns a list of #PopplerImageMapping items that map from a
 
1240
 * location on @page to an image of the page. This list must be freed
 
1241
 * with poppler_page_free_image_mapping() when done.
 
1242
 *
 
1243
 * Return value: (element-type PopplerImageMapping) (transfer full): A #GList of #PopplerImageMapping
 
1244
 **/
 
1245
GList *
 
1246
poppler_page_get_image_mapping (PopplerPage *page)
 
1247
{
 
1248
  GList *map_list = NULL;
 
1249
  CairoImageOutputDev *out;
 
1250
  gint i;
 
1251
  
 
1252
  g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL);
 
1253
 
 
1254
  out = poppler_page_get_image_output_dev (page, NULL, NULL);
 
1255
 
 
1256
  for (i = 0; i < out->getNumImages (); i++) {
 
1257
    PopplerImageMapping *mapping;
 
1258
    CairoImage *image;
 
1259
 
 
1260
    image = out->getImage (i);
 
1261
 
 
1262
    /* Create the mapping */
 
1263
    mapping = poppler_image_mapping_new ();
 
1264
 
 
1265
    image->getRect (&(mapping->area.x1), &(mapping->area.y1),
 
1266
                    &(mapping->area.x2), &(mapping->area.y2));
 
1267
    mapping->image_id = i;
 
1268
    
 
1269
    mapping->area.x1 -= page->page->getCropBox()->x1;
 
1270
    mapping->area.x2 -= page->page->getCropBox()->x1;
 
1271
    mapping->area.y1 -= page->page->getCropBox()->y1;
 
1272
    mapping->area.y2 -= page->page->getCropBox()->y1;
 
1273
 
 
1274
    map_list = g_list_prepend (map_list, mapping);
 
1275
  }
 
1276
 
 
1277
  delete out;
 
1278
 
 
1279
  return map_list;      
 
1280
}
 
1281
 
 
1282
static GBool
 
1283
image_draw_decide_cb (int image_id, void *data)
 
1284
{
 
1285
  return (image_id == GPOINTER_TO_INT (data));
 
1286
}
 
1287
 
 
1288
/**
 
1289
 * poppler_page_get_image:
 
1290
 * @page: A #PopplerPage
 
1291
 * @image_id: The image identificator
 
1292
 *
 
1293
 * Returns a cairo surface for the image of the @page
 
1294
 *
 
1295
 * Return value: A cairo surface for the image
 
1296
 **/
 
1297
cairo_surface_t *
 
1298
poppler_page_get_image (PopplerPage *page,
 
1299
                        gint         image_id)
 
1300
{
 
1301
  CairoImageOutputDev *out;
 
1302
  cairo_surface_t *image;
 
1303
  
 
1304
  g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL);
 
1305
 
 
1306
  out = poppler_page_get_image_output_dev (page,
 
1307
                                           image_draw_decide_cb,
 
1308
                                           GINT_TO_POINTER (image_id));
 
1309
 
 
1310
  if (image_id >= out->getNumImages ()) {
 
1311
    delete out;
 
1312
    
 
1313
    return NULL;
 
1314
  }
 
1315
 
 
1316
  image = out->getImage (image_id)->getImage ();
 
1317
  if (!image) {
 
1318
    delete out;
 
1319
 
 
1320
    return NULL;
 
1321
  }
 
1322
 
 
1323
  cairo_surface_reference (image);
 
1324
  delete out;
 
1325
  
 
1326
  return image;
 
1327
}
 
1328
 
 
1329
/**
 
1330
 * poppler_page_free_image_mapping:
 
1331
 * @list: A list of #PopplerImageMapping<!-- -->s
 
1332
 *
 
1333
 * Frees a list of #PopplerImageMapping<!-- -->s allocated by
 
1334
 * poppler_page_get_image_mapping().
 
1335
 **/
 
1336
void
 
1337
poppler_page_free_image_mapping (GList *list)
 
1338
{
 
1339
  if (G_UNLIKELY (list == NULL))
 
1340
    return;
 
1341
 
 
1342
  g_list_foreach (list, (GFunc)poppler_image_mapping_free, NULL);
 
1343
  g_list_free (list);
 
1344
}
 
1345
 
 
1346
/**
 
1347
 * poppler_page_render_to_ps:
 
1348
 * @page: a #PopplerPage
 
1349
 * @ps_file: the PopplerPSFile to render to
 
1350
 * 
 
1351
 * Render the page on a postscript file
 
1352
 * 
 
1353
 **/
 
1354
void
 
1355
poppler_page_render_to_ps (PopplerPage   *page,
 
1356
                           PopplerPSFile *ps_file)
 
1357
{
 
1358
  g_return_if_fail (POPPLER_IS_PAGE (page));
 
1359
  g_return_if_fail (ps_file != NULL);
 
1360
 
 
1361
  if (!ps_file->out)
 
1362
    ps_file->out = new PSOutputDev (ps_file->filename,
 
1363
                                    ps_file->document->doc,
 
1364
                                    ps_file->document->doc->getXRef(),
 
1365
                                    ps_file->document->doc->getCatalog(),
 
1366
                                    NULL,
 
1367
                                    ps_file->first_page, ps_file->last_page,
 
1368
                                    psModePS, (int)ps_file->paper_width,
 
1369
                                    (int)ps_file->paper_height, ps_file->duplex,
 
1370
                                    0, 0, 0, 0, gFalse, gFalse);
 
1371
 
 
1372
 
 
1373
  ps_file->document->doc->displayPage (ps_file->out, page->index + 1, 72.0, 72.0,
 
1374
                                       0, gFalse, gTrue, gFalse);
 
1375
}
 
1376
 
 
1377
static void
 
1378
poppler_page_get_property (GObject    *object,
 
1379
                           guint       prop_id,
 
1380
                           GValue     *value,
 
1381
                           GParamSpec *pspec)
 
1382
{
 
1383
  PopplerPage *page = POPPLER_PAGE (object);
 
1384
 
 
1385
  switch (prop_id)
 
1386
    {
 
1387
    case PROP_LABEL:
 
1388
      g_value_take_string (value, poppler_page_get_label (page));
 
1389
      break;
 
1390
    default:
 
1391
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
1392
    }
 
1393
}
 
1394
 
 
1395
static void
 
1396
poppler_page_class_init (PopplerPageClass *klass)
 
1397
{
 
1398
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
1399
 
 
1400
  gobject_class->finalize = poppler_page_finalize;
 
1401
  gobject_class->get_property = poppler_page_get_property;
 
1402
 
 
1403
  /**
 
1404
   * PopplerPage:label:
 
1405
   *
 
1406
   * The label of the page or %NULL. See also poppler_page_get_label()
 
1407
   */
 
1408
  g_object_class_install_property (G_OBJECT_CLASS (klass),
 
1409
                                   PROP_LABEL,
 
1410
                                   g_param_spec_string ("label",
 
1411
                                                        "Page Label",
 
1412
                                                        "The label of the page",
 
1413
                                                        NULL,
 
1414
                                                        G_PARAM_READABLE));
 
1415
}
 
1416
 
 
1417
static void
 
1418
poppler_page_init (PopplerPage *page)
 
1419
{
 
1420
}
 
1421
 
 
1422
/**
 
1423
 * poppler_page_get_link_mapping:
 
1424
 * @page: A #PopplerPage
 
1425
 * 
 
1426
 * Returns a list of #PopplerLinkMapping items that map from a
 
1427
 * location on @page to a #PopplerAction.  This list must be freed
 
1428
 * with poppler_page_free_link_mapping() when done.
 
1429
 * 
 
1430
 * Return value: (element-type PopplerLinkMapping) (transfer full): A #GList of #PopplerLinkMapping
 
1431
 **/
 
1432
GList *
 
1433
poppler_page_get_link_mapping (PopplerPage *page)
 
1434
{
 
1435
  GList *map_list = NULL;
 
1436
  gint i;
 
1437
  Links *links;
 
1438
  Object obj;
 
1439
  double width, height;
 
1440
  
 
1441
  g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL);
 
1442
  
 
1443
  links = new Links (page->page->getAnnots (&obj),
 
1444
                     page->document->doc->getCatalog ()->getBaseURI ());
 
1445
  obj.free ();
 
1446
  
 
1447
  if (links == NULL)
 
1448
    return NULL;
 
1449
  
 
1450
  poppler_page_get_size (page, &width, &height);
 
1451
  
 
1452
  for (i = 0; i < links->getNumLinks (); i++)
 
1453
    {
 
1454
      PopplerLinkMapping *mapping;
 
1455
      PopplerRectangle rect;
 
1456
      LinkAction *link_action;
 
1457
      Link *link;
 
1458
      
 
1459
      link = links->getLink (i);
 
1460
      link_action = link->getAction ();
 
1461
      
 
1462
      /* Create the mapping */
 
1463
      mapping = poppler_link_mapping_new ();
 
1464
      mapping->action = _poppler_action_new (page->document, link_action, NULL);
 
1465
 
 
1466
      link->getRect (&rect.x1, &rect.y1, &rect.x2, &rect.y2);
 
1467
 
 
1468
      rect.x1 -= page->page->getCropBox()->x1;
 
1469
      rect.x2 -= page->page->getCropBox()->x1;
 
1470
      rect.y1 -= page->page->getCropBox()->y1;
 
1471
      rect.y2 -= page->page->getCropBox()->y1;
 
1472
      
 
1473
      switch (page->page->getRotate ())
 
1474
        {
 
1475
        case 90:
 
1476
          mapping->area.x1 = rect.y1;
 
1477
          mapping->area.y1 = height - rect.x2;
 
1478
          mapping->area.x2 = mapping->area.x1 + (rect.y2 - rect.y1);
 
1479
          mapping->area.y2 = mapping->area.y1 + (rect.x2 - rect.x1);
 
1480
          
 
1481
          break;
 
1482
        case 180:
 
1483
          mapping->area.x1 = width - rect.x2;
 
1484
          mapping->area.y1 = height - rect.y2;
 
1485
          mapping->area.x2 = mapping->area.x1 + (rect.x2 - rect.x1);
 
1486
          mapping->area.y2 = mapping->area.y1 + (rect.y2 - rect.y1);
 
1487
          
 
1488
          break;
 
1489
        case 270:
 
1490
          mapping->area.x1 = width - rect.y2;
 
1491
          mapping->area.y1 = rect.x1;
 
1492
          mapping->area.x2 = mapping->area.x1 + (rect.y2 - rect.y1);
 
1493
          mapping->area.y2 = mapping->area.y1 + (rect.x2 - rect.x1);
 
1494
          
 
1495
          break;
 
1496
        default:
 
1497
          mapping->area.x1 = rect.x1;
 
1498
          mapping->area.y1 = rect.y1;
 
1499
          mapping->area.x2 = rect.x2;
 
1500
          mapping->area.y2 = rect.y2;
 
1501
        }
 
1502
 
 
1503
      map_list = g_list_prepend (map_list, mapping);
 
1504
    }
 
1505
  
 
1506
  delete links;
 
1507
  
 
1508
  return map_list;
 
1509
}
 
1510
 
 
1511
/**
 
1512
 * poppler_page_free_link_mapping:
 
1513
 * @list: A list of #PopplerLinkMapping<!-- -->s
 
1514
 * 
 
1515
 * Frees a list of #PopplerLinkMapping<!-- -->s allocated by
 
1516
 * poppler_page_get_link_mapping().  It also frees the #PopplerAction<!-- -->s
 
1517
 * that each mapping contains, so if you want to keep them around, you need to
 
1518
 * copy them with poppler_action_copy().
 
1519
 **/
 
1520
void
 
1521
poppler_page_free_link_mapping (GList *list)
 
1522
{
 
1523
  if (G_UNLIKELY (list == NULL))
 
1524
    return;
 
1525
 
 
1526
  g_list_foreach (list, (GFunc)poppler_link_mapping_free, NULL);
 
1527
  g_list_free (list);
 
1528
}
 
1529
 
 
1530
/**
 
1531
 * poppler_page_get_form_field_mapping:
 
1532
 * @page: A #PopplerPage
 
1533
 *
 
1534
 * Returns a list of #PopplerFormFieldMapping items that map from a
 
1535
 * location on @page to a form field.  This list must be freed
 
1536
 * with poppler_page_free_form_field_mapping() when done.
 
1537
 *
 
1538
 * Return value: (element-type PopplerFormFieldMapping) (transfer full): A #GList of #PopplerFormFieldMapping
 
1539
 **/
 
1540
GList *
 
1541
poppler_page_get_form_field_mapping (PopplerPage *page)
 
1542
{
 
1543
  GList *map_list = NULL;
 
1544
  FormPageWidgets *forms;
 
1545
  gint i;
 
1546
  
 
1547
  g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL);
 
1548
 
 
1549
  forms = page->page->getPageWidgets ();
 
1550
  if (forms == NULL)
 
1551
    return NULL;
 
1552
  
 
1553
  for (i = 0; i < forms->getNumWidgets (); i++) {
 
1554
    PopplerFormFieldMapping *mapping;
 
1555
    FormWidget *field;
 
1556
 
 
1557
    mapping = poppler_form_field_mapping_new ();
 
1558
    
 
1559
    field = forms->getWidget (i);
 
1560
 
 
1561
    mapping->field = _poppler_form_field_new (page->document, field);
 
1562
    field->getRect (&(mapping->area.x1), &(mapping->area.y1),
 
1563
                    &(mapping->area.x2), &(mapping->area.y2));
 
1564
 
 
1565
    mapping->area.x1 -= page->page->getCropBox()->x1;
 
1566
    mapping->area.x2 -= page->page->getCropBox()->x1;
 
1567
    mapping->area.y1 -= page->page->getCropBox()->y1;
 
1568
    mapping->area.y2 -= page->page->getCropBox()->y1;
 
1569
    
 
1570
    map_list = g_list_prepend (map_list, mapping);
 
1571
  }
 
1572
  
 
1573
  return map_list;
 
1574
}
 
1575
 
 
1576
/**
 
1577
 * poppler_page_free_form_field_mapping:
 
1578
 * @list: A list of #PopplerFormFieldMapping<!-- -->s
 
1579
 *
 
1580
 * Frees a list of #PopplerFormFieldMapping<!-- -->s allocated by
 
1581
 * poppler_page_get_form_field_mapping().
 
1582
 **/
 
1583
void
 
1584
poppler_page_free_form_field_mapping (GList *list)
 
1585
{
 
1586
  if (G_UNLIKELY (list == NULL))
 
1587
    return;
 
1588
 
 
1589
  g_list_foreach (list, (GFunc) poppler_form_field_mapping_free, NULL);
 
1590
  g_list_free (list);
 
1591
}
 
1592
 
 
1593
/**
 
1594
 * poppler_page_get_annot_mapping:
 
1595
 * @page: A #PopplerPage
 
1596
 *
 
1597
 * Returns a list of #PopplerAnnotMapping items that map from a location on
 
1598
 * @page to a #PopplerAnnot.  This list must be freed with
 
1599
 * poppler_page_free_annot_mapping() when done.
 
1600
 *
 
1601
 * Return value: (element-type PopplerAnnotMapping) (transfer full): A #GList of #PopplerAnnotMapping
 
1602
 **/
 
1603
GList *
 
1604
poppler_page_get_annot_mapping (PopplerPage *page)
 
1605
{
 
1606
  GList *map_list = NULL;
 
1607
  double width, height;
 
1608
  gint i;
 
1609
 
 
1610
  g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL);
 
1611
 
 
1612
  if (!page->annots)
 
1613
    page->annots = page->page->getAnnots (page->document->doc->getCatalog ());
 
1614
  
 
1615
  if (!page->annots)
 
1616
    return NULL;
 
1617
 
 
1618
  poppler_page_get_size (page, &width, &height);
 
1619
 
 
1620
  for (i = 0; i < page->annots->getNumAnnots (); i++) {
 
1621
    PopplerAnnotMapping *mapping;
 
1622
    PopplerRectangle rect;
 
1623
    Annot *annot;
 
1624
    PDFRectangle *annot_rect;
 
1625
    gint rotation = 0;
 
1626
 
 
1627
    annot = page->annots->getAnnot (i);
 
1628
 
 
1629
    /* Create the mapping */
 
1630
    mapping = poppler_annot_mapping_new ();
 
1631
 
 
1632
    switch (annot->getType ())
 
1633
      {
 
1634
      case Annot::typeText:
 
1635
        mapping->annot = _poppler_annot_text_new (annot);
 
1636
        break;
 
1637
      case Annot::typeFreeText:
 
1638
        mapping->annot = _poppler_annot_free_text_new (annot);
 
1639
        break;
 
1640
      case Annot::typeFileAttachment:
 
1641
        mapping->annot = _poppler_annot_file_attachment_new (annot);
 
1642
        break;
 
1643
      case Annot::typeMovie:
 
1644
        mapping->annot = _poppler_annot_movie_new (annot);
 
1645
        break;
 
1646
      case Annot::typeScreen:
 
1647
        mapping->annot = _poppler_annot_screen_new (annot);
 
1648
        break;
 
1649
      default:
 
1650
        mapping->annot = _poppler_annot_new (annot);
 
1651
        break;
 
1652
      }
 
1653
 
 
1654
    annot_rect = annot->getRect ();
 
1655
    rect.x1 = annot_rect->x1 - page->page->getCropBox()->x1;
 
1656
    rect.y1 = annot_rect->y1 - page->page->getCropBox()->y1;
 
1657
    rect.x2 = annot_rect->x2 - page->page->getCropBox()->x1;
 
1658
    rect.y2 = annot_rect->y2 - page->page->getCropBox()->y1;
 
1659
 
 
1660
    if (! (annot->getFlags () & Annot::flagNoRotate))
 
1661
      rotation = page->page->getRotate ();
 
1662
 
 
1663
    switch (rotation)
 
1664
      {
 
1665
      case 90:
 
1666
        mapping->area.x1 = rect.y1;
 
1667
        mapping->area.y1 = height - rect.x2;
 
1668
        mapping->area.x2 = mapping->area.x1 + (rect.y2 - rect.y1);
 
1669
        mapping->area.y2 = mapping->area.y1 + (rect.x2 - rect.x1);
 
1670
        break;
 
1671
      case 180:
 
1672
        mapping->area.x1 = width - rect.x2;
 
1673
        mapping->area.y1 = height - rect.y2;
 
1674
        mapping->area.x2 = mapping->area.x1 + (rect.x2 - rect.x1);
 
1675
        mapping->area.y2 = mapping->area.y1 + (rect.y2 - rect.y1);
 
1676
        break;
 
1677
      case 270:
 
1678
        mapping->area.x1 = width - rect.y2;
 
1679
        mapping->area.y1 = rect.x1;
 
1680
        mapping->area.x2 = mapping->area.x1 + (rect.y2 - rect.y1);
 
1681
        mapping->area.y2 = mapping->area.y1 + (rect.x2 - rect.x1);
 
1682
        break;
 
1683
      default:
 
1684
        mapping->area.x1 = rect.x1;
 
1685
        mapping->area.y1 = rect.y1;
 
1686
        mapping->area.x2 = rect.x2;
 
1687
        mapping->area.y2 = rect.y2;
 
1688
      }
 
1689
 
 
1690
    map_list = g_list_prepend (map_list, mapping);
 
1691
  }
 
1692
 
 
1693
  return g_list_reverse (map_list);
 
1694
}
 
1695
 
 
1696
/**
 
1697
 * poppler_page_free_annot_mapping:
 
1698
 * @list: A list of #PopplerAnnotMapping<!-- -->s
 
1699
 *
 
1700
 * Frees a list of #PopplerAnnotMapping<!-- -->s allocated by
 
1701
 * poppler_page_get_annot_mapping().  It also frees the #PopplerAnnot<!-- -->s
 
1702
 * that each mapping contains, so if you want to keep them around, you need to
 
1703
 * copy them with poppler_annot_copy().
 
1704
 **/
 
1705
void
 
1706
poppler_page_free_annot_mapping (GList *list)
 
1707
{
 
1708
  if (G_UNLIKELY (!list))
 
1709
    return;
 
1710
 
 
1711
  g_list_foreach (list, (GFunc)poppler_annot_mapping_free, NULL);
 
1712
  g_list_free (list);
 
1713
}
 
1714
 
 
1715
/**
 
1716
 * poppler_page_add_annot:
 
1717
 * @page: a #PopplerPage
 
1718
 * @annot: a #PopplerAnnot to add
 
1719
 *
 
1720
 * Adds annotation @annot to @page.
 
1721
 *
 
1722
 * Since: 0.16
 
1723
 */
 
1724
void
 
1725
poppler_page_add_annot (PopplerPage  *page,
 
1726
                        PopplerAnnot *annot)
 
1727
{
 
1728
  g_return_if_fail (POPPLER_IS_PAGE (page));
 
1729
  g_return_if_fail (POPPLER_IS_ANNOT (annot));
 
1730
 
 
1731
  page->page->addAnnot (annot->annot);
 
1732
}
 
1733
 
 
1734
/* PopplerRectangle type */
 
1735
 
 
1736
POPPLER_DEFINE_BOXED_TYPE (PopplerRectangle, poppler_rectangle,
 
1737
                           poppler_rectangle_copy,
 
1738
                           poppler_rectangle_free)
 
1739
 
 
1740
/**
 
1741
 * poppler_rectangle_new:
 
1742
 *
 
1743
 * Creates a new #PopplerRectangle
 
1744
 *
 
1745
 * Returns: a new #PopplerRectangle, use poppler_rectangle_free() to free it
 
1746
 */
 
1747
PopplerRectangle *
 
1748
poppler_rectangle_new (void)
 
1749
{
 
1750
  return g_slice_new0 (PopplerRectangle);
 
1751
}
 
1752
 
 
1753
/**
 
1754
 * poppler_rectangle_copy:
 
1755
 * @rectangle: a #PopplerRectangle to copy
 
1756
 *
 
1757
 * Creates a copy of @rectangle
 
1758
 *
 
1759
 * Returns: a new allocated copy of @rectangle
 
1760
 */
 
1761
PopplerRectangle *
 
1762
poppler_rectangle_copy (PopplerRectangle *rectangle)
 
1763
{
 
1764
  g_return_val_if_fail (rectangle != NULL, NULL);
 
1765
 
 
1766
  return g_slice_dup (PopplerRectangle, rectangle);
 
1767
}
 
1768
 
 
1769
/**
 
1770
 * poppler_rectangle_free:
 
1771
 * @rectangle: a #PopplerRectangle
 
1772
 *
 
1773
 * Frees the given #PopplerRectangle
 
1774
 */
 
1775
void
 
1776
poppler_rectangle_free (PopplerRectangle *rectangle)
 
1777
{
 
1778
  g_slice_free (PopplerRectangle, rectangle);
 
1779
}
 
1780
 
 
1781
/* PopplerColor type */
 
1782
POPPLER_DEFINE_BOXED_TYPE (PopplerColor, poppler_color, poppler_color_copy, poppler_color_free)
 
1783
 
 
1784
/**
 
1785
 * poppler_color_new:
 
1786
 *
 
1787
 * Creates a new #PopplerColor
 
1788
 *
 
1789
 * Returns: a new #PopplerColor, use poppler_color_free() to free it
 
1790
 */
 
1791
PopplerColor *
 
1792
poppler_color_new (void)
 
1793
{
 
1794
  return (PopplerColor *) g_new0 (PopplerColor, 1);
 
1795
}
 
1796
 
 
1797
/**
 
1798
 * poppler_color_copy:
 
1799
 * @color: a #PopplerColor to copy
 
1800
 *
 
1801
 * Creates a copy of @color
 
1802
 *
 
1803
 * Returns: a new allocated copy of @color
 
1804
 */
 
1805
PopplerColor *
 
1806
poppler_color_copy (PopplerColor *color)
 
1807
{
 
1808
  PopplerColor *new_color;
 
1809
 
 
1810
  new_color = g_new (PopplerColor, 1);
 
1811
  *new_color = *color;
 
1812
 
 
1813
  return new_color;
 
1814
}
 
1815
 
 
1816
/**
 
1817
 * poppler_color_free:
 
1818
 * @color: a #PopplerColor
 
1819
 *
 
1820
 * Frees the given #PopplerColor
 
1821
 */
 
1822
void
 
1823
poppler_color_free (PopplerColor *color)
 
1824
{
 
1825
  g_free (color);
 
1826
}
 
1827
 
 
1828
/* PopplerLinkMapping type */
 
1829
POPPLER_DEFINE_BOXED_TYPE (PopplerLinkMapping, poppler_link_mapping,
 
1830
                           poppler_link_mapping_copy,
 
1831
                           poppler_link_mapping_free)
 
1832
 
 
1833
/**
 
1834
 * poppler_link_mapping_new:
 
1835
 *
 
1836
 * Creates a new #PopplerLinkMapping
 
1837
 *
 
1838
 * Returns: a new #PopplerLinkMapping, use poppler_link_mapping_free() to free it
 
1839
 */
 
1840
PopplerLinkMapping *
 
1841
poppler_link_mapping_new (void)
 
1842
{
 
1843
  return g_slice_new0 (PopplerLinkMapping);
 
1844
}
 
1845
 
 
1846
/**
 
1847
 * poppler_link_mapping_copy:
 
1848
 * @mapping: a #PopplerLinkMapping to copy
 
1849
 *
 
1850
 * Creates a copy of @mapping
 
1851
 *
 
1852
 * Returns: a new allocated copy of @mapping
 
1853
 */
 
1854
PopplerLinkMapping *
 
1855
poppler_link_mapping_copy (PopplerLinkMapping *mapping)
 
1856
{
 
1857
  PopplerLinkMapping *new_mapping;
 
1858
 
 
1859
  new_mapping = g_slice_dup (PopplerLinkMapping, mapping);
 
1860
 
 
1861
  if (new_mapping->action)
 
1862
    new_mapping->action = poppler_action_copy (new_mapping->action);
 
1863
 
 
1864
  return new_mapping;
 
1865
}
 
1866
 
 
1867
/**
 
1868
 * poppler_link_mapping_free:
 
1869
 * @mapping: a #PopplerLinkMapping
 
1870
 *
 
1871
 * Frees the given #PopplerLinkMapping
 
1872
 */
 
1873
void
 
1874
poppler_link_mapping_free (PopplerLinkMapping *mapping)
 
1875
{
 
1876
  if (G_UNLIKELY (!mapping))
 
1877
    return;
 
1878
 
 
1879
  if (mapping->action)
 
1880
    poppler_action_free (mapping->action);
 
1881
 
 
1882
  g_slice_free (PopplerLinkMapping, mapping);
 
1883
}
 
1884
 
 
1885
/* Poppler Image mapping type */
 
1886
POPPLER_DEFINE_BOXED_TYPE (PopplerImageMapping, poppler_image_mapping,
 
1887
                           poppler_image_mapping_copy,
 
1888
                           poppler_image_mapping_free)
 
1889
 
 
1890
/**
 
1891
 * poppler_image_mapping_new:
 
1892
 *
 
1893
 * Creates a new #PopplerImageMapping
 
1894
 *
 
1895
 * Returns: a new #PopplerImageMapping, use poppler_image_mapping_free() to free it
 
1896
 */
 
1897
PopplerImageMapping *
 
1898
poppler_image_mapping_new (void)
 
1899
{
 
1900
  return g_slice_new0 (PopplerImageMapping);
 
1901
}
 
1902
 
 
1903
/**
 
1904
 * poppler_image_mapping_copy:
 
1905
 * @mapping: a #PopplerImageMapping to copy
 
1906
 *
 
1907
 * Creates a copy of @mapping
 
1908
 *
 
1909
 * Returns: a new allocated copy of @mapping
 
1910
 */
 
1911
PopplerImageMapping *
 
1912
poppler_image_mapping_copy (PopplerImageMapping *mapping)
 
1913
{
 
1914
  return g_slice_dup (PopplerImageMapping, mapping);
 
1915
}
 
1916
 
 
1917
/**
 
1918
 * poppler_image_mapping_free:
 
1919
 * @mapping: a #PopplerImageMapping
 
1920
 *
 
1921
 * Frees the given #PopplerImageMapping
 
1922
 */
 
1923
void
 
1924
poppler_image_mapping_free (PopplerImageMapping *mapping)
 
1925
{
 
1926
  g_slice_free (PopplerImageMapping, mapping);
 
1927
}
 
1928
 
 
1929
/* Page Transition */
 
1930
POPPLER_DEFINE_BOXED_TYPE (PopplerPageTransition, poppler_page_transition,
 
1931
                           poppler_page_transition_copy,
 
1932
                           poppler_page_transition_free)
 
1933
 
 
1934
/**
 
1935
 * poppler_page_transition_new:
 
1936
 *
 
1937
 * Creates a new #PopplerPageTransition
 
1938
 *
 
1939
 * Returns: a new #PopplerPageTransition, use poppler_page_transition_free() to free it
 
1940
 */
 
1941
PopplerPageTransition *
 
1942
poppler_page_transition_new (void)
 
1943
{
 
1944
  return (PopplerPageTransition *) g_new0 (PopplerPageTransition, 1);
 
1945
}
 
1946
 
 
1947
/**
 
1948
 * poppler_page_transition_copy:
 
1949
 * @transition: a #PopplerPageTransition to copy
 
1950
 *
 
1951
 * Creates a copy of @transition
 
1952
 *
 
1953
 * Returns: a new allocated copy of @transition
 
1954
 */
 
1955
PopplerPageTransition *
 
1956
poppler_page_transition_copy (PopplerPageTransition *transition)
 
1957
{
 
1958
  PopplerPageTransition *new_transition;
 
1959
 
 
1960
  new_transition = poppler_page_transition_new ();
 
1961
  *new_transition = *transition;
 
1962
  
 
1963
  return new_transition;
 
1964
}
 
1965
 
 
1966
/**
 
1967
 * poppler_page_transition_free:
 
1968
 * @transition: a #PopplerPageTransition
 
1969
 *
 
1970
 * Frees the given #PopplerPageTransition
 
1971
 */
 
1972
void
 
1973
poppler_page_transition_free (PopplerPageTransition *transition)
 
1974
{
 
1975
  g_free (transition);
 
1976
}
 
1977
 
 
1978
/* Form Field Mapping Type */
 
1979
POPPLER_DEFINE_BOXED_TYPE (PopplerFormFieldMapping, poppler_form_field_mapping,
 
1980
                           poppler_form_field_mapping_copy,
 
1981
                           poppler_form_field_mapping_free)
 
1982
 
 
1983
/**
 
1984
 * poppler_form_field_mapping_new:
 
1985
 *
 
1986
 * Creates a new #PopplerFormFieldMapping
 
1987
 *
 
1988
 * Returns: a new #PopplerFormFieldMapping, use poppler_form_field_mapping_free() to free it
 
1989
 */
 
1990
PopplerFormFieldMapping *
 
1991
poppler_form_field_mapping_new (void)
 
1992
{
 
1993
  return g_slice_new0 (PopplerFormFieldMapping);
 
1994
}
 
1995
 
 
1996
/**
 
1997
 * poppler_form_field_mapping_copy:
 
1998
 * @mapping: a #PopplerFormFieldMapping to copy
 
1999
 *
 
2000
 * Creates a copy of @mapping
 
2001
 *
 
2002
 * Returns: a new allocated copy of @mapping
 
2003
 */
 
2004
PopplerFormFieldMapping *
 
2005
poppler_form_field_mapping_copy (PopplerFormFieldMapping *mapping)
 
2006
{
 
2007
  PopplerFormFieldMapping *new_mapping;
 
2008
 
 
2009
  new_mapping = g_slice_dup (PopplerFormFieldMapping, mapping);
 
2010
 
 
2011
  if (mapping->field)
 
2012
          new_mapping->field = (PopplerFormField *)g_object_ref (mapping->field);
 
2013
            
 
2014
  return new_mapping;
 
2015
}
 
2016
 
 
2017
/**
 
2018
 * poppler_form_field_mapping_free:
 
2019
 * @mapping: a #PopplerFormFieldMapping
 
2020
 *
 
2021
 * Frees the given #PopplerFormFieldMapping
 
2022
 */
 
2023
void
 
2024
poppler_form_field_mapping_free (PopplerFormFieldMapping *mapping)
 
2025
{
 
2026
  if (G_UNLIKELY (!mapping))
 
2027
    return;
 
2028
 
 
2029
  if (mapping->field)
 
2030
    g_object_unref (mapping->field);
 
2031
 
 
2032
  g_slice_free (PopplerFormFieldMapping, mapping);
 
2033
}
 
2034
 
 
2035
/* PopplerAnnot Mapping Type */
 
2036
POPPLER_DEFINE_BOXED_TYPE (PopplerAnnotMapping, poppler_annot_mapping,
 
2037
                           poppler_annot_mapping_copy,
 
2038
                           poppler_annot_mapping_free)
 
2039
 
 
2040
/**
 
2041
 * poppler_annot_mapping_new:
 
2042
 *
 
2043
 * Creates a new #PopplerAnnotMapping
 
2044
 *
 
2045
 * Returns: a new #PopplerAnnotMapping, use poppler_annot_mapping_free() to free it
 
2046
 */
 
2047
PopplerAnnotMapping *
 
2048
poppler_annot_mapping_new (void)
 
2049
{
 
2050
  return g_slice_new0 (PopplerAnnotMapping);
 
2051
}
 
2052
 
 
2053
/**
 
2054
 * poppler_annot_mapping_copy:
 
2055
 * @mapping: a #PopplerAnnotMapping to copy
 
2056
 *
 
2057
 * Creates a copy of @mapping
 
2058
 *
 
2059
 * Returns: a new allocated copy of @mapping
 
2060
 */
 
2061
PopplerAnnotMapping *
 
2062
poppler_annot_mapping_copy (PopplerAnnotMapping *mapping)
 
2063
{
 
2064
  PopplerAnnotMapping *new_mapping;
 
2065
 
 
2066
  new_mapping = g_slice_dup (PopplerAnnotMapping, mapping);
 
2067
 
 
2068
  if (mapping->annot)
 
2069
    new_mapping->annot = (PopplerAnnot *) g_object_ref (mapping->annot);
 
2070
 
 
2071
  return new_mapping;
 
2072
}
 
2073
 
 
2074
/**
 
2075
 * poppler_annot_mapping_free:
 
2076
 * @mapping: a #PopplerAnnotMapping
 
2077
 *
 
2078
 * Frees the given #PopplerAnnotMapping
 
2079
 */
 
2080
void
 
2081
poppler_annot_mapping_free (PopplerAnnotMapping *mapping)
 
2082
{
 
2083
  if (G_UNLIKELY (!mapping))
 
2084
    return;
 
2085
 
 
2086
  if (mapping->annot)
 
2087
    g_object_unref (mapping->annot);
 
2088
 
 
2089
  g_slice_free (PopplerAnnotMapping, mapping);
 
2090
}
 
2091
 
 
2092
/**
 
2093
 * poppler_page_get_crop_box:
 
2094
 * @page: a #PopplerPage
 
2095
 * @rect: (out): a #PopplerRectangle to fill
 
2096
 *
 
2097
 * Retrurns the crop box of @page
 
2098
 */
 
2099
void
 
2100
poppler_page_get_crop_box (PopplerPage *page, PopplerRectangle *rect)
 
2101
{
 
2102
  PDFRectangle* cropBox = page->page->getCropBox ();
 
2103
  
 
2104
  rect->x1 = cropBox->x1;
 
2105
  rect->x2 = cropBox->x2;
 
2106
  rect->y1 = cropBox->y1;
 
2107
  rect->y2 = cropBox->y2;
 
2108
}
 
2109
 
 
2110
/**
 
2111
 * poppler_page_get_text_layout:
 
2112
 * @page: A #PopplerPage
 
2113
 * @rectangles: (out) (array length=n_rectangles) (transfer container): return location for an array of #PopplerRectangle
 
2114
 * @n_rectangles: (out) length of returned array
 
2115
 *
 
2116
 * Obtains the layout of the text as a list of #PopplerRectangle
 
2117
 * This array must be freed with g_free () when done.
 
2118
 *
 
2119
 * The position in the array represents an offset in the text returned by
 
2120
 * poppler_page_get_text()
 
2121
 *
 
2122
 * Return value: %TRUE if the page contains text, %FALSE otherwise
 
2123
 *
 
2124
 * Since: 0.16
 
2125
 **/
 
2126
gboolean
 
2127
poppler_page_get_text_layout (PopplerPage       *page,
 
2128
                              PopplerRectangle **rectangles,
 
2129
                              guint             *n_rectangles)
 
2130
{
 
2131
  TextPage *text;
 
2132
  TextWordList *wordlist;
 
2133
  TextWord *word, *nextword;
 
2134
  PopplerRectangle *rect;
 
2135
  int i, j, offset = 0;
 
2136
  gdouble x1, y1, x2, y2;
 
2137
  gdouble x3, y3, x4, y4;
 
2138
 
 
2139
  g_return_val_if_fail (POPPLER_IS_PAGE (page), FALSE);
 
2140
 
 
2141
  *n_rectangles = 0;
 
2142
 
 
2143
  text = poppler_page_get_text_page (page);
 
2144
  wordlist = text->makeWordList (gFalse);
 
2145
 
 
2146
  if (wordlist->getLength () <= 0)
 
2147
    {
 
2148
      delete wordlist;
 
2149
      return FALSE;
 
2150
    }
 
2151
 
 
2152
  // Getting the array size
 
2153
  for (i = 0; i < wordlist->getLength (); i++)
 
2154
    {
 
2155
      word = wordlist->get (i);
 
2156
      *n_rectangles += word->getLength () + 1;
 
2157
    }
 
2158
 
 
2159
  *rectangles = g_new (PopplerRectangle, *n_rectangles);
 
2160
 
 
2161
  // Calculating each char position
 
2162
  for (i = 0; i < wordlist->getLength (); i++)
 
2163
    {
 
2164
      word = wordlist->get (i);
 
2165
      for (j = 0; j < word->getLength (); j++)
 
2166
        {
 
2167
          rect = *rectangles + offset;
 
2168
          word->getCharBBox (j,
 
2169
                             &(rect->x1),
 
2170
                             &(rect->y1),
 
2171
                             &(rect->x2),
 
2172
                             &(rect->y2));
 
2173
          offset++;
 
2174
        }
 
2175
 
 
2176
      // adding spaces and break lines
 
2177
      rect = *rectangles + offset;
 
2178
      word->getBBox (&x1, &y1, &x2, &y2);
 
2179
 
 
2180
      nextword = word->getNext ();
 
2181
      if (nextword)
 
2182
        {
 
2183
          nextword->getBBox (&x3, &y3, &x4, &y4);
 
2184
          // space is from one word to other and with the same height as
 
2185
          // first word.
 
2186
          rect->x1 = x2;
 
2187
          rect->y1 = y1;
 
2188
          rect->x2 = x3;
 
2189
          rect->y2 = y2;
 
2190
        }
 
2191
      else
 
2192
        {
 
2193
          // end of line
 
2194
          rect->x1 = x2;
 
2195
          rect->y1 = y2;
 
2196
          rect->x2 = x2;
 
2197
          rect->y2 = y2;
 
2198
        }
 
2199
      offset++;
 
2200
    }
 
2201
 
 
2202
  delete wordlist;
 
2203
 
 
2204
  return TRUE;
 
2205
}