Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 384903
Collapse All | Expand All

(-)a/plug-ins/common/file-pdf.c (-41 / +283 lines)
Lines 4-9 Link Here
4
 *
4
 *
5
 * Copyright (C) 2005 Nathan Summers
5
 * Copyright (C) 2005 Nathan Summers
6
 *
6
 *
7
 * Some code in render_page_to_surface() borrowed from
8
 * poppler.git/glib/poppler-page.cc.
9
 *
7
 * This program is free software; you can redistribute it and/or modify
10
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
11
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2 of the License, or
12
 * the Free Software Foundation; either version 2 of the License, or
Lines 80-95 static gboolean load_dialog (PopplerDocument *doc, Link Here
80
static PopplerDocument * open_document     (const gchar            *filename,
83
static PopplerDocument * open_document     (const gchar            *filename,
81
                                            GError                **error);
84
                                            GError                **error);
82
85
83
static GdkPixbuf *       get_thumbnail     (PopplerDocument        *doc,
86
static cairo_surface_t * get_thumb_surface (PopplerDocument        *doc,
87
                                            gint                    page,
88
                                            gint                    preferred_size);
89
90
static GdkPixbuf *       get_thumb_pixbuf  (PopplerDocument        *doc,
84
                                            gint                    page,
91
                                            gint                    page,
85
                                            gint                    preferred_size);
92
                                            gint                    preferred_size);
86
93
87
static gint32            layer_from_pixbuf (gint32                  image,
94
static gint32            layer_from_pixbuf (gint32                  image,
88
                                            const gchar            *layer_name,
95
					                        const gchar            *layer_name,
89
                                            gint                    position,
96
					                        gint                    position,
90
                                            GdkPixbuf              *buf,
97
					                        GdkPixbuf              *pixbuf,
91
                                            gdouble                 progress_start,
98
					                        gdouble                 progress_start,
92
                                            gdouble                 progress_scale);
99
					                        gdouble                 progress_scale);
93
100
94
/**
101
/**
95
 ** the following was formerly part of
102
 ** the following was formerly part of
Lines 433-443 run (const gchar *name, Link Here
433
        }
440
        }
434
      else
441
      else
435
        {
442
        {
436
          gdouble      width  = 0;
443
          gdouble    width     = 0;
437
          gdouble      height = 0;
444
          gdouble    height    = 0;
438
          gdouble      scale;
445
          gdouble    scale;
439
          gint32       image  = -1;
446
          gint32     image     = -1;
440
          GdkPixbuf   *pixbuf = NULL;
447
          gint       num_pages = 0;
448
          GdkPixbuf *pixbuf    = NULL;
441
449
442
          /* Possibly retrieve last settings */
450
          /* Possibly retrieve last settings */
443
          gimp_get_data (LOAD_PROC, &loadvals);
451
          gimp_get_data (LOAD_PROC, &loadvals);
Lines 455-461 run (const gchar *name, Link Here
455
                  g_object_unref (page);
463
                  g_object_unref (page);
456
                }
464
                }
457
465
458
              pixbuf = get_thumbnail (doc, 0, param[1].data.d_int32);
466
              num_pages = poppler_document_get_n_pages (doc);
467
468
              pixbuf = get_thumb_pixbuf (doc, 0, param[1].data.d_int32);
469
459
              g_object_unref (doc);
470
              g_object_unref (doc);
460
            }
471
            }
461
472
Lines 548-553 open_document (const gchar *filename, Link Here
548
  return doc;
559
  return doc;
549
}
560
}
550
561
562
/* FIXME: Remove this someday when we depend fully on GTK+ >= 3 */
563
564
#if (!GTK_CHECK_VERSION (3, 0, 0))
565
566
static cairo_format_t
567
gdk_cairo_format_for_content (cairo_content_t content)
568
{
569
  switch (content)
570
    {
571
    case CAIRO_CONTENT_COLOR:
572
      return CAIRO_FORMAT_RGB24;
573
    case CAIRO_CONTENT_ALPHA:
574
      return CAIRO_FORMAT_A8;
575
    case CAIRO_CONTENT_COLOR_ALPHA:
576
    default:
577
      return CAIRO_FORMAT_ARGB32;
578
    }
579
}
580
581
static cairo_surface_t *
582
gdk_cairo_surface_coerce_to_image (cairo_surface_t *surface,
583
                                   cairo_content_t  content,
584
                                   int              src_x,
585
                                   int              src_y,
586
                                   int              width,
587
                                   int              height)
588
{
589
  cairo_surface_t *copy;
590
  cairo_t *cr;
591
592
  copy = cairo_image_surface_create (gdk_cairo_format_for_content (content),
593
                                     width,
594
                                     height);
595
596
  cr = cairo_create (copy);
597
  cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
598
  cairo_set_source_surface (cr, surface, -src_x, -src_y);
599
  cairo_paint (cr);
600
  cairo_destroy (cr);
601
602
  return copy;
603
}
604
605
static void
606
convert_alpha (guchar *dest_data,
607
               int     dest_stride,
608
               guchar *src_data,
609
               int     src_stride,
610
               int     src_x,
611
               int     src_y,
612
               int     width,
613
               int     height)
614
{
615
  int x, y;
616
617
  src_data += src_stride * src_y + src_x * 4;
618
619
  for (y = 0; y < height; y++) {
620
    guint32 *src = (guint32 *) src_data;
621
622
    for (x = 0; x < width; x++) {
623
      guint alpha = src[x] >> 24;
624
625
      if (alpha == 0)
626
        {
627
          dest_data[x * 4 + 0] = 0;
628
          dest_data[x * 4 + 1] = 0;
629
          dest_data[x * 4 + 2] = 0;
630
        }
631
      else
632
        {
633
          dest_data[x * 4 + 0] = (((src[x] & 0xff0000) >> 16) * 255 + alpha / 2) / alpha;
634
          dest_data[x * 4 + 1] = (((src[x] & 0x00ff00) >>  8) * 255 + alpha / 2) / alpha;
635
          dest_data[x * 4 + 2] = (((src[x] & 0x0000ff) >>  0) * 255 + alpha / 2) / alpha;
636
        }
637
      dest_data[x * 4 + 3] = alpha;
638
    }
639
640
    src_data += src_stride;
641
    dest_data += dest_stride;
642
  }
643
}
644
645
static void
646
convert_no_alpha (guchar *dest_data,
647
                  int     dest_stride,
648
                  guchar *src_data,
649
                  int     src_stride,
650
                  int     src_x,
651
                  int     src_y,
652
                  int     width,
653
                  int     height)
654
{
655
  int x, y;
656
657
  src_data += src_stride * src_y + src_x * 4;
658
659
  for (y = 0; y < height; y++) {
660
    guint32 *src = (guint32 *) src_data;
661
662
    for (x = 0; x < width; x++) {
663
      dest_data[x * 3 + 0] = src[x] >> 16;
664
      dest_data[x * 3 + 1] = src[x] >>  8;
665
      dest_data[x * 3 + 2] = src[x];
666
    }
667
668
    src_data += src_stride;
669
    dest_data += dest_stride;
670
  }
671
}
672
673
/**
674
 * gdk_pixbuf_get_from_surface:
675
 * @surface: surface to copy from
676
 * @src_x: Source X coordinate within @surface
677
 * @src_y: Source Y coordinate within @surface
678
 * @width: Width in pixels of region to get
679
 * @height: Height in pixels of region to get
680
 *
681
 * Transfers image data from a #cairo_surface_t and converts it to an RGB(A)
682
 * representation inside a #GdkPixbuf. This allows you to efficiently read
683
 * individual pixels from cairo surfaces. For #GdkWindows, use
684
 * gdk_pixbuf_get_from_window() instead.
685
 *
686
 * This function will create an RGB pixbuf with 8 bits per channel.
687
 * The pixbuf will contain an alpha channel if the @surface contains one.
688
 *
689
 * Return value: (transfer full): A newly-created pixbuf with a reference
690
 *     count of 1, or %NULL on error
691
 */
692
static GdkPixbuf *
693
gdk_pixbuf_get_from_surface  (cairo_surface_t *surface,
694
                              gint             src_x,
695
                              gint             src_y,
696
                              gint             width,
697
                              gint             height)
698
{
699
  cairo_content_t content;
700
  GdkPixbuf *dest;
701
702
  /* General sanity checks */
703
  g_return_val_if_fail (surface != NULL, NULL);
704
  g_return_val_if_fail (width > 0 && height > 0, NULL);
705
706
  content = cairo_surface_get_content (surface) | CAIRO_CONTENT_COLOR;
707
  dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
708
                         !!(content & CAIRO_CONTENT_ALPHA),
709
                         8,
710
                         width, height);
711
712
  surface = gdk_cairo_surface_coerce_to_image (surface, content,
713
                                               src_x, src_y,
714
                                               width, height);
715
  cairo_surface_flush (surface);
716
  if (cairo_surface_status (surface) || dest == NULL)
717
    {
718
      cairo_surface_destroy (surface);
719
      return NULL;
720
    }
721
722
  if (gdk_pixbuf_get_has_alpha (dest))
723
    convert_alpha (gdk_pixbuf_get_pixels (dest),
724
                   gdk_pixbuf_get_rowstride (dest),
725
                   cairo_image_surface_get_data (surface),
726
                   cairo_image_surface_get_stride (surface),
727
                   0, 0,
728
                   width, height);
729
  else
730
    convert_no_alpha (gdk_pixbuf_get_pixels (dest),
731
                      gdk_pixbuf_get_rowstride (dest),
732
                      cairo_image_surface_get_data (surface),
733
                      cairo_image_surface_get_stride (surface),
734
                      0, 0,
735
                      width, height);
736
737
  cairo_surface_destroy (surface);
738
  return dest;
739
}
740
741
#endif
742
551
static gint32
743
static gint32
552
layer_from_pixbuf (gint32        image,
744
layer_from_pixbuf (gint32        image,
553
                   const gchar  *layer_name,
745
                   const gchar  *layer_name,
Lines 566-571 layer_from_pixbuf (gint32 image, Link Here
566
  return layer;
758
  return layer;
567
}
759
}
568
760
761
static cairo_surface_t *
762
render_page_to_surface (PopplerPage *page,
763
                        int          width,
764
                        int          height,
765
                        double       scale)
766
{
767
  cairo_surface_t *surface;
768
  cairo_t *cr;
769
770
  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
771
  cr = cairo_create (surface);
772
773
  cairo_save (cr);
774
  cairo_translate (cr, 0.0, 0.0);
775
776
  if (scale != 1.0)
777
    cairo_scale (cr, scale, scale);
778
779
  poppler_page_render (page, cr);
780
  cairo_restore (cr);
781
782
  cairo_set_operator (cr, CAIRO_OPERATOR_DEST_OVER);
783
  cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
784
  cairo_paint (cr);
785
786
  cairo_destroy (cr);
787
788
  return surface;
789
}
790
791
static GdkPixbuf *
792
render_page_to_pixbuf (PopplerPage *page,
793
                       int          width,
794
                       int          height,
795
                       double       scale)
796
{
797
  GdkPixbuf *pixbuf;
798
  cairo_surface_t *surface;
799
800
  surface = render_page_to_surface (page, width, height, scale);
801
  pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0,
802
                                        cairo_image_surface_get_width (surface),
803
                                        cairo_image_surface_get_height (surface));
804
  cairo_surface_destroy (surface);
805
806
  return pixbuf;
807
}
808
569
static gint32
809
static gint32
570
load_image (PopplerDocument        *doc,
810
load_image (PopplerDocument        *doc,
571
            const gchar            *filename,
811
            const gchar            *filename,
Lines 597-603 load_image (PopplerDocument *doc, Link Here
597
      gdouble      page_width;
837
      gdouble      page_width;
598
      gdouble      page_height;
838
      gdouble      page_height;
599
839
600
      GdkPixbuf   *buf;
840
      GdkPixbuf   *pixbuf;
601
      gint         width;
841
      gint         width;
602
      gint         height;
842
      gint         height;
603
843
Lines 627-641 load_image (PopplerDocument *doc, Link Here
627
          gimp_image_set_resolution (image_ID, resolution, resolution);
867
          gimp_image_set_resolution (image_ID, resolution, resolution);
628
        }
868
        }
629
869
630
      buf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height);
870
      pixbuf = render_page_to_pixbuf (page, width, height, scale);
631
632
      poppler_page_render_to_pixbuf (page, 0, 0, width, height, scale, 0, buf);
633
871
634
      layer_from_pixbuf (image_ID, page_label, i, buf,
872
      layer_from_pixbuf (image_ID, page_label, i, pixbuf,
635
                         doc_progress, 1.0 / pages->n_pages);
873
                         doc_progress, 1.0 / pages->n_pages);
636
874
637
      g_free (page_label);
875
      g_free (page_label);
638
      g_object_unref (buf);
876
      g_object_unref(pixbuf);
639
877
640
      doc_progress = (double) (i + 1) / pages->n_pages;
878
      doc_progress = (double) (i + 1) / pages->n_pages;
641
      gimp_progress_update (doc_progress);
879
      gimp_progress_update (doc_progress);
Lines 676-705 load_image (PopplerDocument *doc, Link Here
676
  return image_ID;
914
  return image_ID;
677
}
915
}
678
916
679
static GdkPixbuf *
917
static cairo_surface_t *
680
get_thumbnail (PopplerDocument *doc,
918
get_thumb_surface (PopplerDocument *doc,
681
               gint             page_num,
919
                   gint             page_num,
682
               gint             preferred_size)
920
                   gint             preferred_size)
683
{
921
{
684
  PopplerPage *page;
922
  PopplerPage *page;
685
  GdkPixbuf   *pixbuf;
923
  cairo_surface_t *surface;
686
924
687
  page = poppler_document_get_page (doc, page_num);
925
  page = poppler_document_get_page (doc, page_num);
688
926
689
  if (! page)
927
  if (! page)
690
    return NULL;
928
    return NULL;
691
929
692
  /* XXX: Remove conditional when we depend on poppler 0.8.0, but also
930
  surface = poppler_page_get_thumbnail (page);
693
   * add configure check to make sure POPPLER_WITH_GDK is enabled!
694
   */
695
#ifdef POPPLER_WITH_GDK
696
  pixbuf = poppler_page_get_thumbnail_pixbuf (page);
697
#else
698
  pixbuf = poppler_page_get_thumbnail (page);
699
#endif
700
701
931
702
  if (! pixbuf)
932
  if (! surface)
703
    {
933
    {
704
      gdouble width;
934
      gdouble width;
705
      gdouble height;
935
      gdouble height;
Lines 712-726 get_thumbnail (PopplerDocument *doc, Link Here
712
      width  *= scale;
942
      width  *= scale;
713
      height *= scale;
943
      height *= scale;
714
944
715
      pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
945
      surface = render_page_to_surface (page, width, height, scale);
716
                               width, height);
717
718
      poppler_page_render_to_pixbuf (page,
719
                                     0, 0, width, height, scale, 0, pixbuf);
720
    }
946
    }
721
947
722
  g_object_unref (page);
948
  g_object_unref (page);
723
949
950
  return surface;
951
}
952
953
static GdkPixbuf *
954
get_thumb_pixbuf (PopplerDocument *doc,
955
                  gint             page_num,
956
                  gint             preferred_size)
957
{
958
  cairo_surface_t *surface;
959
  GdkPixbuf *pixbuf;
960
961
  surface = get_thumb_surface (doc, page_num, preferred_size);
962
  pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0,
963
                                        cairo_image_surface_get_width (surface),
964
                                        cairo_image_surface_get_height (surface));
965
  cairo_surface_destroy (surface);
966
724
  return pixbuf;
967
  return pixbuf;
725
}
968
}
726
969
Lines 769-776 thumbnail_thread (gpointer data) Link Here
769
      idle_data->page_no  = i;
1012
      idle_data->page_no  = i;
770
1013
771
      /* FIXME get preferred size from somewhere? */
1014
      /* FIXME get preferred size from somewhere? */
772
      idle_data->pixbuf = get_thumbnail (thread_data->document, i,
1015
      idle_data->pixbuf = get_thumb_pixbuf (thread_data->document, i,
773
                                         THUMBNAIL_SIZE);
1016
                                            THUMBNAIL_SIZE);
774
1017
775
      g_idle_add (idle_set_thumbnail, idle_data);
1018
      g_idle_add (idle_set_thumbnail, idle_data);
776
1019
777
- 

Return to bug 384903