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