summaryrefslogtreecommitdiff
path: root/glib
diff options
context:
space:
mode:
authorNelson Benítez León <nbenitezl@gmail.com>2022-05-11 21:07:30 -0400
committerAlbert Astals Cid <tsdgeos@yahoo.es>2022-07-03 21:48:47 +0000
commita0e4ff30be462cae010d22d291ab282f5d86a5e3 (patch)
tree7ec9f5e1ec0e89c5b6d5898cc705d44ea01bd5ee /glib
parent40762b05b73ec790c8cbe33ab76770f181f67aee (diff)
glib: add support for stamp annotation
Creates new PopplerAnnotStamp type with the following public api: PopplerAnnot *poppler_annot_stamp_new(PopplerDocument *doc, PopplerRectangle *rect); PopplerAnnotStampIcon poppler_annot_stamp_get_icon(PopplerAnnotStamp *poppler_annot); void poppler_annot_stamp_set_icon(PopplerAnnotStamp *poppler_annot, PopplerAnnotStampIcon icon); gboolean poppler_annot_stamp_set_custom_image(PopplerAnnotStamp *poppler_annot, cairo_surface_t *image, GError **error); Updates poppler-glib-demo to test PopplerAnnotStamp including the custom image support.
Diffstat (limited to 'glib')
-rw-r--r--glib/demo/annots.c171
-rw-r--r--glib/poppler-annot.cc288
-rw-r--r--glib/poppler-annot.h35
-rw-r--r--glib/poppler-page.cc3
-rw-r--r--glib/poppler-private.h2
-rw-r--r--glib/poppler.h1
-rw-r--r--glib/reference/poppler-sections.txt10
-rw-r--r--glib/reference/poppler.types1
8 files changed, 507 insertions, 4 deletions
diff --git a/glib/demo/annots.c b/glib/demo/annots.c
index 799fe434..645a7210 100644
--- a/glib/demo/annots.c
+++ b/glib/demo/annots.c
@@ -22,6 +22,8 @@
#include "annots.h"
#include "utils.h"
+#define STAMP_CUSTOM_IMAGE "Custom image"
+
enum
{
ANNOTS_TYPE_COLUMN,
@@ -47,10 +49,26 @@ typedef struct
} Annotations;
static const Annotations supported_annots[] = {
- { POPPLER_ANNOT_TEXT, "Text" }, { POPPLER_ANNOT_LINE, "Line" }, { POPPLER_ANNOT_SQUARE, "Square" }, { POPPLER_ANNOT_CIRCLE, "Circle" },
- { POPPLER_ANNOT_HIGHLIGHT, "Highlight" }, { POPPLER_ANNOT_UNDERLINE, "Underline" }, { POPPLER_ANNOT_SQUIGGLY, "Squiggly" }, { POPPLER_ANNOT_STRIKE_OUT, "Strike Out" },
+ { POPPLER_ANNOT_TEXT, "Text" }, { POPPLER_ANNOT_LINE, "Line" }, { POPPLER_ANNOT_SQUARE, "Square" }, { POPPLER_ANNOT_CIRCLE, "Circle" }, { POPPLER_ANNOT_HIGHLIGHT, "Highlight" },
+ { POPPLER_ANNOT_UNDERLINE, "Underline" }, { POPPLER_ANNOT_SQUIGGLY, "Squiggly" }, { POPPLER_ANNOT_STRIKE_OUT, "Strike Out" }, { POPPLER_ANNOT_STAMP, "Stamp" },
};
+static const char *stamp_types[] = { [POPPLER_ANNOT_STAMP_ICON_UNKNOWN] = "Unknown",
+ [POPPLER_ANNOT_STAMP_ICON_APPROVED] = "APPROVED",
+ [POPPLER_ANNOT_STAMP_ICON_AS_IS] = "AS_IS",
+ [POPPLER_ANNOT_STAMP_ICON_CONFIDENTIAL] = "CONFIDENTIAL",
+ [POPPLER_ANNOT_STAMP_ICON_FINAL] = "FINAL",
+ [POPPLER_ANNOT_STAMP_ICON_EXPERIMENTAL] = "EXPERIMENTAL",
+ [POPPLER_ANNOT_STAMP_ICON_EXPIRED] = "EXPIRED",
+ [POPPLER_ANNOT_STAMP_ICON_NOT_APPROVED] = "NOT_APPROVED",
+ [POPPLER_ANNOT_STAMP_ICON_NOT_FOR_PUBLIC_RELEASE] = "NOT_FOR_PUBLIC_RELEASE",
+ [POPPLER_ANNOT_STAMP_ICON_SOLD] = "SOLD",
+ [POPPLER_ANNOT_STAMP_ICON_DEPARTMENTAL] = "DEPARTMENTAL",
+ [POPPLER_ANNOT_STAMP_ICON_FOR_COMMENT] = "FOR_COMMENT",
+ [POPPLER_ANNOT_STAMP_ICON_FOR_PUBLIC_RELEASE] = "FOR_PUBLIC_RELEASE",
+ [POPPLER_ANNOT_STAMP_ICON_TOP_SECRET] = "TOP_SECRET",
+ [POPPLER_ANNOT_STAMP_ICON_NONE] = "None" };
+
typedef enum
{
MODE_NORMAL, /* Regular use as pointer in the page */
@@ -72,10 +90,12 @@ typedef struct
GtkWidget *timer_label;
GtkWidget *remove_button;
GtkWidget *type_selector;
+ GtkWidget *stamp_selector;
GtkWidget *main_box;
gint num_page;
gint annot_type;
+ char *custom_image_filename;
ModeType mode;
cairo_surface_t *surface;
@@ -460,6 +480,14 @@ static void pgd_annot_view_set_annot_free_text(GtkWidget *table, PopplerAnnotFre
g_free(text);
}
+static void pgd_annot_view_set_annot_stamp(GtkWidget *table, PopplerAnnotStamp *annot, gint *row)
+{
+ PopplerAnnotStampIcon icon;
+
+ icon = poppler_annot_stamp_get_icon(annot);
+ pgd_table_add_property(GTK_GRID(table), "<b>Icon Name:</b>", stamp_types[icon], row);
+}
+
static void pgd_annots_file_attachment_save_dialog_response(GtkFileChooser *file_chooser, gint response, PopplerAttachment *attachment)
{
gchar *filename;
@@ -614,6 +642,9 @@ static void pgd_annot_view_set_annot(PgdAnnotsDemo *demo, PopplerAnnot *annot)
case POPPLER_ANNOT_SCREEN:
pgd_annot_view_set_annot_screen(table, POPPLER_ANNOT_SCREEN(annot), &row);
break;
+ case POPPLER_ANNOT_STAMP:
+ pgd_annot_view_set_annot_stamp(table, POPPLER_ANNOT_STAMP(annot), &row);
+ break;
default:
break;
}
@@ -791,6 +822,19 @@ static GArray *pgd_annots_create_quads_array_for_rectangle(PopplerRectangle *rec
return quads_array;
}
+static PopplerAnnotStampIcon get_icon_from_stamp_text(gchar *icon_text)
+{
+ int i;
+
+ for (i = 1; i < G_N_ELEMENTS(stamp_types) - 1; i++) {
+ if (strcmp(stamp_types[i], icon_text) == 0) {
+ return (PopplerAnnotStampIcon)i;
+ }
+ }
+
+ return POPPLER_ANNOT_STAMP_ICON_UNKNOWN;
+}
+
static void pgd_annots_add_annot(PgdAnnotsDemo *demo)
{
PopplerRectangle rect;
@@ -860,13 +904,35 @@ static void pgd_annots_add_annot(PgdAnnotsDemo *demo)
annot = poppler_annot_text_markup_new_strikeout(demo->doc, &rect, quads_array);
g_array_free(quads_array, TRUE);
} break;
+ case POPPLER_ANNOT_STAMP: {
+ annot = poppler_annot_stamp_new(demo->doc, &rect);
+ gchar *stamp_type = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(demo->stamp_selector));
+ GError *error = NULL;
+
+ if (strcmp(stamp_type, STAMP_CUSTOM_IMAGE) == 0 && demo->custom_image_filename) {
+ cairo_surface_t *img = cairo_image_surface_create_from_png(demo->custom_image_filename);
+ if (cairo_surface_status(img) == CAIRO_STATUS_SUCCESS) {
+ poppler_annot_stamp_set_custom_image(POPPLER_ANNOT_STAMP(annot), img, &error);
+ if (error) {
+ g_warning("%s", error->message);
+ g_error_free(error);
+ }
+ }
+ cairo_surface_destroy(img);
+ } else {
+ poppler_annot_stamp_set_icon(POPPLER_ANNOT_STAMP(annot), get_icon_from_stamp_text(stamp_type));
+ }
+ g_free(stamp_type);
+ } break;
default:
g_assert_not_reached();
}
demo->active_annot = annot;
- poppler_annot_set_color(annot, &color);
+ if (demo->annot_type != POPPLER_ANNOT_STAMP) {
+ poppler_annot_set_color(annot, &color);
+ }
poppler_page_add_annot(demo->page, annot);
pgd_annots_add_annot_to_model(demo, annot, rect, TRUE);
g_object_unref(annot);
@@ -1056,6 +1122,83 @@ static gboolean pgd_annots_drawing_area_button_press(GtkWidget *area, GdkEventBu
return TRUE;
}
+static void choose_custom_image(PgdAnnotsDemo *demo)
+{
+ GtkFileChooser *chooser_dialog;
+ gint response;
+ const gchar *chooser_dir = "/usr/share/pixmaps";
+ const gchar *pics_dir;
+ GtkFileFilter *filter;
+
+ chooser_dialog = GTK_FILE_CHOOSER(gtk_file_chooser_dialog_new("Select PNG Image", NULL, GTK_FILE_CHOOSER_ACTION_OPEN, "gtk-cancel", GTK_RESPONSE_CANCEL, "gtk-open", GTK_RESPONSE_ACCEPT, NULL));
+ gtk_window_set_modal(GTK_WINDOW(chooser_dialog), TRUE);
+ gtk_dialog_set_default_response(GTK_DIALOG(chooser_dialog), GTK_RESPONSE_ACCEPT);
+
+ gtk_file_chooser_add_shortcut_folder(chooser_dialog, chooser_dir, NULL);
+ pics_dir = g_get_user_special_dir(G_USER_DIRECTORY_PICTURES);
+ if (pics_dir != NULL) {
+ gtk_file_chooser_add_shortcut_folder(chooser_dialog, pics_dir, NULL);
+ }
+
+ if (!g_file_test(chooser_dir, G_FILE_TEST_IS_DIR)) {
+ chooser_dir = g_get_home_dir();
+ }
+
+ gtk_file_chooser_set_current_folder(chooser_dialog, chooser_dir);
+
+ filter = gtk_file_filter_new();
+ gtk_file_filter_set_name(filter, "PNG images");
+ gtk_file_filter_add_mime_type(filter, "image/png");
+ gtk_file_chooser_add_filter(chooser_dialog, filter);
+ filter = gtk_file_filter_new();
+ gtk_file_filter_set_name(filter, "All Files");
+ gtk_file_filter_add_pattern(filter, "*");
+ gtk_file_chooser_add_filter(chooser_dialog, filter);
+
+ response = gtk_dialog_run(GTK_DIALOG(chooser_dialog));
+
+ if (response == GTK_RESPONSE_ACCEPT) {
+ if (demo->custom_image_filename) {
+ g_free(demo->custom_image_filename);
+ }
+
+ demo->custom_image_filename = gtk_file_chooser_get_filename(chooser_dialog);
+ } else {
+ if (demo->custom_image_filename) {
+ g_free(demo->custom_image_filename);
+ demo->custom_image_filename = NULL;
+ }
+ }
+
+ gtk_widget_destroy(GTK_WIDGET(chooser_dialog));
+}
+
+static void stamp_selector_changed(GtkComboBox *combo_box, PgdAnnotsDemo *demo)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gchar *active;
+
+ model = gtk_combo_box_get_model(combo_box);
+ gtk_combo_box_get_active_iter(combo_box, &iter);
+ gtk_tree_model_get(model, &iter, 0, &active, -1);
+ if (strcmp(active, STAMP_CUSTOM_IMAGE) == 0) {
+ choose_custom_image(demo);
+ }
+}
+
+static void type_selector_changed(GtkComboBox *combo_box, PgdAnnotsDemo *demo)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ int active;
+
+ model = gtk_combo_box_get_model(combo_box);
+ gtk_combo_box_get_active_iter(combo_box, &iter);
+ gtk_tree_model_get(model, &iter, SELECTED_TYPE_COLUMN, &active, -1);
+ gtk_widget_set_sensitive(demo->stamp_selector, active == POPPLER_ANNOT_STAMP);
+}
+
static gboolean pgd_annots_drawing_area_motion_notify(GtkWidget *area, GdkEventMotion *event, PgdAnnotsDemo *demo)
{
PopplerRectangle rect;
@@ -1114,7 +1257,7 @@ GtkWidget *pgd_annots_create_widget(PopplerDocument *document)
GtkWidget *label;
GtkWidget *vbox, *vbox2;
GtkWidget *button;
- GtkWidget *hbox, *page_selector;
+ GtkWidget *hbox, *hbox2, *page_selector;
GtkWidget *hpaned;
GtkWidget *swindow, *treeview;
GtkTreeSelection *selection;
@@ -1138,6 +1281,7 @@ GtkWidget *pgd_annots_create_widget(PopplerDocument *document)
vbox2 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
+ hbox2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 12);
label = gtk_label_new("Page:");
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0);
@@ -1161,6 +1305,7 @@ GtkWidget *pgd_annots_create_widget(PopplerDocument *document)
gtk_widget_show(demo->remove_button);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, TRUE, 0);
button = gtk_button_new_with_mnemonic("_Add");
g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(pgd_annots_start_add_annot), (gpointer)demo);
@@ -1175,8 +1320,25 @@ GtkWidget *pgd_annots_create_widget(PopplerDocument *document)
}
demo->type_selector = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model));
+ g_signal_connect(demo->type_selector, "changed", G_CALLBACK(type_selector_changed), (gpointer)demo);
g_object_unref(model);
+ demo->stamp_selector = gtk_combo_box_text_new();
+ for (i = 1; i < G_N_ELEMENTS(stamp_types) - 1; i++) {
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(demo->stamp_selector), stamp_types[i]);
+ }
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(demo->stamp_selector), STAMP_CUSTOM_IMAGE);
+
+ gtk_combo_box_set_active(GTK_COMBO_BOX(demo->stamp_selector), 0);
+ g_signal_connect(demo->stamp_selector, "changed", G_CALLBACK(stamp_selector_changed), (gpointer)demo);
+ gtk_widget_set_sensitive(demo->stamp_selector, FALSE);
+ label = gtk_label_new("Stamp type: ");
+ gtk_widget_set_sensitive(label, FALSE);
+ g_object_bind_property(demo->stamp_selector, "sensitive", label, "sensitive", 0);
+ gtk_box_pack_end(GTK_BOX(hbox2), demo->stamp_selector, FALSE, FALSE, 0);
+ gtk_box_pack_end(GTK_BOX(hbox2), label, FALSE, TRUE, 0);
+ gtk_widget_show_all(hbox2);
+
renderer = gtk_cell_renderer_text_new();
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(demo->type_selector), renderer, TRUE);
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(demo->type_selector), renderer, "text", SELECTED_LABEL_COLUMN, NULL);
@@ -1193,6 +1355,7 @@ GtkWidget *pgd_annots_create_widget(PopplerDocument *document)
gtk_widget_show(button);
gtk_widget_show(hbox);
+ gtk_widget_show(hbox2);
demo->timer_label = gtk_label_new(NULL);
gtk_label_set_markup(GTK_LABEL(demo->timer_label), "<i>No annotations found</i>");
diff --git a/glib/poppler-annot.cc b/glib/poppler-annot.cc
index 2c9a7607..b995f037 100644
--- a/glib/poppler-annot.cc
+++ b/glib/poppler-annot.cc
@@ -26,6 +26,7 @@
#define ZERO_CROPBOX(c) (!(c && (c->x1 > 0.01 || c->y1 > 0.01)))
const PDFRectangle *_poppler_annot_get_cropbox_and_page(PopplerAnnot *poppler_annot, Page **page_out);
+AnnotStampImageHelper *_poppler_convert_cairo_image_to_stamp_image_helper(cairo_surface_t *image, PDFDoc *doc, GError **error);
/**
* SECTION:poppler-annot
@@ -44,6 +45,7 @@ typedef struct _PopplerAnnotScreenClass PopplerAnnotScreenClass;
typedef struct _PopplerAnnotLineClass PopplerAnnotLineClass;
typedef struct _PopplerAnnotCircleClass PopplerAnnotCircleClass;
typedef struct _PopplerAnnotSquareClass PopplerAnnotSquareClass;
+typedef struct _PopplerAnnotStampClass PopplerAnnotStampClass;
struct _PopplerAnnotClass
{
@@ -153,6 +155,14 @@ struct _PopplerAnnotSquareClass
{
PopplerAnnotMarkupClass parent_class;
};
+struct _PopplerAnnotStamp
+{
+ PopplerAnnot parent_instance;
+};
+struct _PopplerAnnotStampClass
+{
+ PopplerAnnotClass parent_class;
+};
G_DEFINE_TYPE(PopplerAnnot, poppler_annot, G_TYPE_OBJECT)
G_DEFINE_TYPE(PopplerAnnotMarkup, poppler_annot_markup, POPPLER_TYPE_ANNOT)
@@ -165,6 +175,7 @@ G_DEFINE_TYPE(PopplerAnnotScreen, poppler_annot_screen, POPPLER_TYPE_ANNOT)
G_DEFINE_TYPE(PopplerAnnotLine, poppler_annot_line, POPPLER_TYPE_ANNOT_MARKUP)
G_DEFINE_TYPE(PopplerAnnotCircle, poppler_annot_circle, POPPLER_TYPE_ANNOT_MARKUP)
G_DEFINE_TYPE(PopplerAnnotSquare, poppler_annot_square, POPPLER_TYPE_ANNOT_MARKUP)
+G_DEFINE_TYPE(PopplerAnnotStamp, poppler_annot_stamp, POPPLER_TYPE_ANNOT)
static PopplerAnnot *_poppler_create_annot(GType annot_type, Annot *annot)
{
@@ -598,6 +609,141 @@ PopplerAnnot *poppler_annot_square_new(PopplerDocument *doc, PopplerRectangle *r
return _poppler_annot_square_new(annot);
}
+static void poppler_annot_stamp_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(poppler_annot_stamp_parent_class)->finalize(object);
+}
+
+static void poppler_annot_stamp_init(PopplerAnnotStamp *poppler_annot) { }
+
+static void poppler_annot_stamp_class_init(PopplerAnnotStampClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+
+ gobject_class->finalize = poppler_annot_stamp_finalize;
+}
+
+PopplerAnnot *_poppler_annot_stamp_new(Annot *annot)
+{
+ PopplerAnnot *poppler_annot;
+
+ poppler_annot = _poppler_create_annot(POPPLER_TYPE_ANNOT_STAMP, annot);
+
+ return poppler_annot;
+}
+
+/**
+ * poppler_annot_stamp_new:
+ * @doc: a #PopplerDocument
+ * @rect: a #PopplerRectangle
+ *
+ * Creates a new Stamp annotation that will be
+ * located on @rect when added to a page. See
+ * poppler_page_add_annot()
+ *
+ * Return value: a newly created #PopplerAnnotStamp annotation
+ *
+ * Since: 22.07.0
+ **/
+PopplerAnnot *poppler_annot_stamp_new(PopplerDocument *doc, PopplerRectangle *rect)
+{
+ Annot *annot;
+ PDFRectangle pdf_rect(rect->x1, rect->y1, rect->x2, rect->y2);
+
+ annot = new AnnotStamp(doc->doc, &pdf_rect);
+
+ return _poppler_annot_stamp_new(annot);
+}
+
+static gboolean get_raw_data_from_cairo_image(cairo_surface_t *image, cairo_format_t format, const int width, const int height, const size_t rowstride_c, GByteArray *data, GByteArray *soft_mask_data)
+{
+ gboolean has_alpha = format == CAIRO_FORMAT_ARGB32;
+
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ static const size_t CAIRO_B = 0;
+ static const size_t CAIRO_G = 1;
+ static const size_t CAIRO_R = 2;
+ static const size_t CAIRO_A = 3;
+#elif G_BYTE_ORDER == G_BIG_ENDIAN
+ static const size_t CAIRO_A = 0;
+ static const size_t CAIRO_R = 1;
+ static const size_t CAIRO_G = 2;
+ static const size_t CAIRO_B = 3;
+#else
+# error "Unsupported endian type"
+#endif
+
+ cairo_surface_flush(image);
+ unsigned char *pixels_c = cairo_image_surface_get_data(image);
+
+ if (format == CAIRO_FORMAT_ARGB32 || format == CAIRO_FORMAT_RGB24) {
+ unsigned char pixel[3];
+
+ for (int h = 0; h < height; h++) {
+ unsigned char *iter_c = pixels_c + h * rowstride_c;
+ for (int w = 0; w < width; w++) {
+ pixel[0] = iter_c[CAIRO_R];
+ pixel[1] = iter_c[CAIRO_G];
+ pixel[2] = iter_c[CAIRO_B];
+ iter_c += 4;
+
+ g_byte_array_append(data, (guint8 *)pixel, 3);
+ if (has_alpha) {
+ g_byte_array_append(soft_mask_data, (guint8 *)&iter_c[CAIRO_A], 1);
+ }
+ }
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+AnnotStampImageHelper *_poppler_convert_cairo_image_to_stamp_image_helper(cairo_surface_t *image, PDFDoc *doc, GError **error)
+{
+ AnnotStampImageHelper *annotImg;
+ GByteArray *data;
+ GByteArray *sMaskData;
+
+ int bitsPerComponent;
+ const int width = cairo_image_surface_get_width(image);
+ const int height = cairo_image_surface_get_height(image);
+ const size_t rowstride_c = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
+ cairo_format_t format = cairo_image_surface_get_format(image);
+
+ ColorSpace colorSpace;
+
+ if (format == CAIRO_FORMAT_ARGB32 || format == CAIRO_FORMAT_RGB24) {
+ colorSpace = ColorSpace::DeviceRGB;
+ bitsPerComponent = 8;
+ } else {
+ g_set_error(error, POPPLER_ERROR, POPPLER_ERROR_INVALID, "Invalid or unsupported cairo image type %u", (unsigned int)format);
+ return nullptr;
+ }
+
+ data = g_byte_array_sized_new((guint)((width * 4) + rowstride_c) * height);
+ sMaskData = g_byte_array_sized_new((guint)((width * 4) + rowstride_c) * height);
+
+ if (!get_raw_data_from_cairo_image(image, format, width, height, rowstride_c, data, sMaskData)) {
+ g_set_error(error, POPPLER_ERROR, POPPLER_ERROR_INVALID, "Failed to get raw data from cairo image");
+ g_byte_array_unref(data);
+ g_byte_array_unref(sMaskData);
+ return nullptr;
+ }
+
+ if (sMaskData->len > 0) {
+ AnnotStampImageHelper sMask(doc, width, height, ColorSpace::DeviceGray, 8, (char *)sMaskData->data, (int)sMaskData->len);
+ annotImg = new AnnotStampImageHelper(doc, width, height, colorSpace, bitsPerComponent, (char *)data->data, (int)data->len, sMask.getRef());
+ } else {
+ annotImg = new AnnotStampImageHelper(doc, width, height, colorSpace, bitsPerComponent, (char *)data->data, (int)data->len);
+ }
+
+ g_byte_array_unref(data);
+ g_byte_array_unref(sMaskData);
+
+ return annotImg;
+}
+
/* Public methods */
/**
* poppler_annot_get_annot_type:
@@ -1911,3 +2057,145 @@ void poppler_annot_square_set_interior_color(PopplerAnnotSquare *poppler_annot,
poppler_annot_geometry_set_interior_color(POPPLER_ANNOT(poppler_annot), poppler_color);
}
+
+/**
+ * poppler_annot_stamp_get_icon:
+ * @poppler_annot: a #PopplerAnnotStamp
+ *
+ * Return value: the corresponding #PopplerAnnotStampIcon of the icon
+ *
+ * Since: 22.07.0
+ */
+PopplerAnnotStampIcon poppler_annot_stamp_get_icon(PopplerAnnotStamp *poppler_annot)
+{
+ AnnotStamp *annot;
+ const GooString *text;
+
+ g_return_val_if_fail(POPPLER_IS_ANNOT_STAMP(poppler_annot), POPPLER_ANNOT_STAMP_ICON_UNKNOWN);
+
+ annot = static_cast<AnnotStamp *>(POPPLER_ANNOT(poppler_annot)->annot);
+
+ text = annot->getIcon();
+
+ if (!text) {
+ return POPPLER_ANNOT_STAMP_ICON_NONE;
+ }
+
+ if (!text->cmp("Approved")) {
+ return POPPLER_ANNOT_STAMP_ICON_APPROVED;
+ } else if (!text->cmp("AsIs")) {
+ return POPPLER_ANNOT_STAMP_ICON_AS_IS;
+ } else if (!text->cmp("Confidential")) {
+ return POPPLER_ANNOT_STAMP_ICON_CONFIDENTIAL;
+ } else if (!text->cmp("Final")) {
+ return POPPLER_ANNOT_STAMP_ICON_FINAL;
+ } else if (!text->cmp("Experimental")) {
+ return POPPLER_ANNOT_STAMP_ICON_EXPERIMENTAL;
+ } else if (!text->cmp("Expired")) {
+ return POPPLER_ANNOT_STAMP_ICON_EXPIRED;
+ } else if (!text->cmp("NotApproved")) {
+ return POPPLER_ANNOT_STAMP_ICON_NOT_APPROVED;
+ } else if (!text->cmp("NotForPublicRelease")) {
+ return POPPLER_ANNOT_STAMP_ICON_NOT_FOR_PUBLIC_RELEASE;
+ } else if (!text->cmp("Sold")) {
+ return POPPLER_ANNOT_STAMP_ICON_SOLD;
+ } else if (!text->cmp("Departmental")) {
+ return POPPLER_ANNOT_STAMP_ICON_DEPARTMENTAL;
+ } else if (!text->cmp("ForComment")) {
+ return POPPLER_ANNOT_STAMP_ICON_FOR_COMMENT;
+ } else if (!text->cmp("ForPublicRelease")) {
+ return POPPLER_ANNOT_STAMP_ICON_FOR_PUBLIC_RELEASE;
+ } else if (!text->cmp("TopSecret")) {
+ return POPPLER_ANNOT_STAMP_ICON_TOP_SECRET;
+ }
+
+ return POPPLER_ANNOT_STAMP_ICON_UNKNOWN;
+}
+
+/**
+ * poppler_annot_stamp_set_icon:
+ * @poppler_annot: a #PopplerAnnotStamp
+ * @icon: the #PopplerAnnotStampIcon type of the icon
+ *
+ * Sets the icon of @poppler_annot to be one of the predefined values in #PopplerAnnotStampIcon
+ *
+ * Since: 22.07.0
+ */
+void poppler_annot_stamp_set_icon(PopplerAnnotStamp *poppler_annot, PopplerAnnotStampIcon icon)
+{
+ AnnotStamp *annot;
+ GooString *goo_str;
+ const gchar *text;
+
+ g_return_if_fail(POPPLER_IS_ANNOT_STAMP(poppler_annot));
+
+ annot = static_cast<AnnotStamp *>(POPPLER_ANNOT(poppler_annot)->annot);
+
+ if (icon == POPPLER_ANNOT_STAMP_ICON_NONE) {
+ annot->setIcon(nullptr);
+ return;
+ }
+
+ if (icon == POPPLER_ANNOT_STAMP_ICON_APPROVED) {
+ text = "Approved";
+ } else if (icon == POPPLER_ANNOT_STAMP_ICON_AS_IS) {
+ text = "AsIs";
+ } else if (icon == POPPLER_ANNOT_STAMP_ICON_CONFIDENTIAL) {
+ text = "Confidential";
+ } else if (icon == POPPLER_ANNOT_STAMP_ICON_FINAL) {
+ text = "Final";
+ } else if (icon == POPPLER_ANNOT_STAMP_ICON_EXPERIMENTAL) {
+ text = "Experimental";
+ } else if (icon == POPPLER_ANNOT_STAMP_ICON_EXPIRED) {
+ text = "Expired";
+ } else if (icon == POPPLER_ANNOT_STAMP_ICON_NOT_APPROVED) {
+ text = "NotApproved";
+ } else if (icon == POPPLER_ANNOT_STAMP_ICON_NOT_FOR_PUBLIC_RELEASE) {
+ text = "NotForPublicRelease";
+ } else if (icon == POPPLER_ANNOT_STAMP_ICON_SOLD) {
+ text = "Sold";
+ } else if (icon == POPPLER_ANNOT_STAMP_ICON_DEPARTMENTAL) {
+ text = "Departmental";
+ } else if (icon == POPPLER_ANNOT_STAMP_ICON_FOR_COMMENT) {
+ text = "ForComment";
+ } else if (icon == POPPLER_ANNOT_STAMP_ICON_FOR_PUBLIC_RELEASE) {
+ text = "ForPublicRelease";
+ } else if (icon == POPPLER_ANNOT_STAMP_ICON_TOP_SECRET) {
+ text = "TopSecret";
+ } else {
+ return; /* POPPLER_ANNOT_STAMP_ICON_UNKNOWN */
+ }
+
+ goo_str = new GooString(text);
+ annot->setIcon(goo_str);
+ delete goo_str;
+}
+
+/**
+ * poppler_annot_stamp_set_custom_image:
+ * @poppler_annot: a #PopplerAnnotStamp
+ * @image: an image cairo surface
+ * @error: (nullable): return location for error, or %NULL.
+ *
+ * Sets the custom image of @poppler_annot to be @image
+ *
+ * Return value: %TRUE on success, %FALSE otherwise.
+ *
+ * Since: 22.07.0
+ */
+gboolean poppler_annot_stamp_set_custom_image(PopplerAnnotStamp *poppler_annot, cairo_surface_t *image, GError **error)
+{
+ AnnotStamp *annot;
+ AnnotStampImageHelper *annot_image_helper;
+
+ g_return_val_if_fail(POPPLER_IS_ANNOT_STAMP(poppler_annot), FALSE);
+
+ annot = static_cast<AnnotStamp *>(POPPLER_ANNOT(poppler_annot)->annot);
+ annot_image_helper = _poppler_convert_cairo_image_to_stamp_image_helper(image, annot->getDoc(), error);
+ if (!annot_image_helper) {
+ return FALSE;
+ }
+ annot->setCustomImage(annot_image_helper);
+
+ return TRUE;
+}
diff --git a/glib/poppler-annot.h b/glib/poppler-annot.h
index da55172d..509ecdff 100644
--- a/glib/poppler-annot.h
+++ b/glib/poppler-annot.h
@@ -72,6 +72,10 @@ G_BEGIN_DECLS
#define POPPLER_ANNOT_SQUARE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), POPPLER_TYPE_ANNOT_SQUARE, PopplerAnnotSquare))
#define POPPLER_IS_ANNOT_SQUARE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), POPPLER_TYPE_ANNOT_SQUARE))
+#define POPPLER_TYPE_ANNOT_STAMP (poppler_annot_stamp_get_type())
+#define POPPLER_ANNOT_STAMP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), POPPLER_TYPE_ANNOT_STAMP, PopplerAnnotStamp))
+#define POPPLER_IS_ANNOT_STAMP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), POPPLER_TYPE_ANNOT_STAMP))
+
typedef enum
{
POPPLER_ANNOT_UNKNOWN,
@@ -169,6 +173,25 @@ struct _PopplerAnnotCalloutLine
gdouble y3;
};
+typedef enum
+{
+ POPPLER_ANNOT_STAMP_ICON_UNKNOWN = 0,
+ POPPLER_ANNOT_STAMP_ICON_APPROVED,
+ POPPLER_ANNOT_STAMP_ICON_AS_IS,
+ POPPLER_ANNOT_STAMP_ICON_CONFIDENTIAL,
+ POPPLER_ANNOT_STAMP_ICON_FINAL,
+ POPPLER_ANNOT_STAMP_ICON_EXPERIMENTAL,
+ POPPLER_ANNOT_STAMP_ICON_EXPIRED,
+ POPPLER_ANNOT_STAMP_ICON_NOT_APPROVED,
+ POPPLER_ANNOT_STAMP_ICON_NOT_FOR_PUBLIC_RELEASE,
+ POPPLER_ANNOT_STAMP_ICON_SOLD,
+ POPPLER_ANNOT_STAMP_ICON_DEPARTMENTAL,
+ POPPLER_ANNOT_STAMP_ICON_FOR_COMMENT,
+ POPPLER_ANNOT_STAMP_ICON_FOR_PUBLIC_RELEASE,
+ POPPLER_ANNOT_STAMP_ICON_TOP_SECRET,
+ POPPLER_ANNOT_STAMP_ICON_NONE
+} PopplerAnnotStampIcon;
+
POPPLER_PUBLIC
GType poppler_annot_get_type(void) G_GNUC_CONST;
POPPLER_PUBLIC
@@ -328,6 +351,18 @@ void poppler_annot_square_set_interior_color(PopplerAnnotSquare *poppler_annot,
POPPLER_PUBLIC
PopplerColor *poppler_annot_square_get_interior_color(PopplerAnnotSquare *poppler_annot);
+/* PopplerAnnotStamp */
+POPPLER_PUBLIC
+GType poppler_annot_stamp_get_type(void) G_GNUC_CONST;
+POPPLER_PUBLIC
+PopplerAnnot *poppler_annot_stamp_new(PopplerDocument *doc, PopplerRectangle *rect);
+POPPLER_PUBLIC
+PopplerAnnotStampIcon poppler_annot_stamp_get_icon(PopplerAnnotStamp *poppler_annot);
+POPPLER_PUBLIC
+void poppler_annot_stamp_set_icon(PopplerAnnotStamp *poppler_annot, PopplerAnnotStampIcon icon);
+POPPLER_PUBLIC
+gboolean poppler_annot_stamp_set_custom_image(PopplerAnnotStamp *poppler_annot, cairo_surface_t *image, GError **error);
+
G_END_DECLS
#endif /* __POPPLER_ANNOT_H__ */
diff --git a/glib/poppler-page.cc b/glib/poppler-page.cc
index 8e361a58..7f47cd5b 100644
--- a/glib/poppler-page.cc
+++ b/glib/poppler-page.cc
@@ -1337,6 +1337,9 @@ GList *poppler_page_get_annot_mapping(PopplerPage *page)
case Annot::typeStrikeOut:
mapping->annot = _poppler_annot_text_markup_new(annot);
break;
+ case Annot::typeStamp:
+ mapping->annot = _poppler_annot_stamp_new(annot);
+ break;
default:
mapping->annot = _poppler_annot_new(annot);
break;
diff --git a/glib/poppler-private.h b/glib/poppler-private.h
index ce2c4733..758c7021 100644
--- a/glib/poppler-private.h
+++ b/glib/poppler-private.h
@@ -156,6 +156,7 @@ PopplerAnnot *_poppler_annot_screen_new(PopplerDocument *doc, Annot *annot);
PopplerAnnot *_poppler_annot_line_new(Annot *annot);
PopplerAnnot *_poppler_annot_circle_new(Annot *annot);
PopplerAnnot *_poppler_annot_square_new(Annot *annot);
+PopplerAnnot *_poppler_annot_stamp_new(Annot *annot);
const PDFRectangle *_poppler_annot_get_cropbox(PopplerAnnot *poppler_annot);
@@ -163,6 +164,7 @@ char *_poppler_goo_string_to_utf8(const GooString *s);
gboolean _poppler_convert_pdf_date_to_gtime(const GooString *date, time_t *gdate);
GDateTime *_poppler_convert_pdf_date_to_date_time(const GooString *date);
GooString *_poppler_convert_date_time_to_pdf_date(GDateTime *datetime);
+AnnotStampImageHelper *_poppler_convert_cairo_image_to_stamp_image_helper(const cairo_surface_t *image);
void _poppler_error_cb(ErrorCategory category, Goffset pos, const char *message);
diff --git a/glib/poppler.h b/glib/poppler.h
index e2001504..710b7b23 100644
--- a/glib/poppler.h
+++ b/glib/poppler.h
@@ -219,6 +219,7 @@ typedef struct _PopplerStructureElementIter PopplerStructureElementIter;
typedef struct _PopplerTextSpan PopplerTextSpan;
typedef struct _PopplerPageRange PopplerPageRange;
typedef struct _PopplerSignatureInfo PopplerSignatureInfo;
+typedef struct _PopplerAnnotStamp PopplerAnnotStamp;
/**
* PopplerBackend:
diff --git a/glib/reference/poppler-sections.txt b/glib/reference/poppler-sections.txt
index 0a20ffae..f027cd03 100644
--- a/glib/reference/poppler-sections.txt
+++ b/glib/reference/poppler-sections.txt
@@ -455,6 +455,7 @@ PopplerAnnotMarkup
PopplerAnnotMovie
PopplerAnnotScreen
PopplerAnnotSquare
+PopplerAnnotStamp
PopplerAnnotText
PopplerAnnotTextMarkup
PopplerAnnotExternalDataType
@@ -462,6 +463,7 @@ PopplerAnnotFlag
PopplerAnnotFreeTextQuadding
PopplerAnnotMarkupReplyType
PopplerAnnotTextState
+PopplerAnnotStampIcon
PopplerAnnotType
poppler_annot_get_annot_type
POPPLER_ANNOT_TEXT_ICON_CIRCLE
@@ -516,6 +518,10 @@ poppler_annot_set_rectangle
poppler_annot_square_get_interior_color
poppler_annot_square_new
poppler_annot_square_set_interior_color
+poppler_annot_stamp_get_icon
+poppler_annot_stamp_new
+poppler_annot_stamp_set_custom_image
+poppler_annot_stamp_set_icon
poppler_annot_text_get_icon
poppler_annot_text_get_is_open
poppler_annot_text_get_state
@@ -539,6 +545,7 @@ POPPLER_ANNOT_MARKUP
POPPLER_ANNOT_MOVIE
POPPLER_ANNOT_SCREEN
POPPLER_ANNOT_SQUARE
+POPPLER_ANNOT_STAMP
POPPLER_ANNOT_TEXT
POPPLER_ANNOT_TEXT_MARKUP
POPPLER_IS_ANNOT
@@ -550,6 +557,7 @@ POPPLER_IS_ANNOT_MARKUP
POPPLER_IS_ANNOT_MOVIE
POPPLER_IS_ANNOT_SCREEN
POPPLER_IS_ANNOT_SQUARE
+POPPLER_IS_ANNOT_STAMP
POPPLER_IS_ANNOT_TEXT
POPPLER_IS_ANNOT_TEXT_MARKUP
POPPLER_TYPE_ANNOT
@@ -566,6 +574,7 @@ POPPLER_TYPE_ANNOT_MARKUP_REPLY_TYPE
POPPLER_TYPE_ANNOT_MOVIE
POPPLER_TYPE_ANNOT_SCREEN
POPPLER_TYPE_ANNOT_SQUARE
+POPPLER_TYPE_ANNOT_STAMP
POPPLER_TYPE_ANNOT_TEXT
POPPLER_TYPE_ANNOT_TEXT_MARKUP
POPPLER_TYPE_ANNOT_TEXT_STATE
@@ -584,6 +593,7 @@ poppler_annot_markup_reply_type_get_type
poppler_annot_movie_get_type
poppler_annot_screen_get_type
poppler_annot_square_get_type
+poppler_annot_stamp_get_type
poppler_annot_text_get_type
poppler_annot_text_markup_get_type
poppler_annot_text_state_get_type
diff --git a/glib/reference/poppler.types b/glib/reference/poppler.types
index da524e0e..1ab636b3 100644
--- a/glib/reference/poppler.types
+++ b/glib/reference/poppler.types
@@ -18,6 +18,7 @@ poppler_annot_markup_reply_type_get_type
poppler_annot_movie_get_type
poppler_annot_screen_get_type
poppler_annot_square_get_type
+poppler_annot_stamp_get_type
poppler_annot_text_get_type
poppler_annot_text_markup_get_type
poppler_annot_text_state_get_type