From b6a783b3954de7d1dc756c039b2bc8f9656d22f7 Mon Sep 17 00:00:00 2001 From: lbaudin1 Date: Fri, 8 Nov 2024 14:24:30 +0000 Subject: [PATCH] glib: Add free text annotations support --- glib/demo/annots.c | 45 ++- glib/poppler-annot.cc | 490 +++++++++++++++++++++++++--- glib/poppler-annot.h | 87 +++++ glib/poppler-document.cc | 6 +- glib/poppler-private.h | 2 + glib/poppler.h | 1 + glib/reference/poppler-sections.txt | 33 ++ glib/reference/poppler.types | 3 +- 8 files changed, 613 insertions(+), 54 deletions(-) diff --git a/glib/demo/annots.c b/glib/demo/annots.c index 645a72107..b8dcd420d 100644 --- a/glib/demo/annots.c +++ b/glib/demo/annots.c @@ -49,8 +49,8 @@ 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_STAMP, "Stamp" }, + { POPPLER_ANNOT_TEXT, "Text" }, { POPPLER_ANNOT_FREE_TEXT, "Free 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", @@ -478,6 +478,27 @@ static void pgd_annot_view_set_annot_free_text(GtkWidget *table, PopplerAnnotFre text = get_free_text_callout_line(annot); pgd_table_add_property(GTK_GRID(table), "Callout:", text, row); g_free(text); + + PopplerColor *color = poppler_annot_get_color(POPPLER_ANNOT(annot)); + + if (color) { + text = g_strdup_printf("(%d, %d, %d)", color->red, color->green, color->blue); + } else { + text = g_strdup("null"); + } + pgd_table_add_property(GTK_GRID(table), "Color:", text, row); + g_free(text); + + PopplerFontDescription *font_desc = poppler_annot_free_text_get_font_desc(annot); + PangoFontDescription *p = pango_font_description_new(); + pango_font_description_set_family(p, font_desc->font_name); + pango_font_description_set_stretch(p, (PangoStretch)font_desc->stretch); + pango_font_description_set_weight(p, (PangoWeight)font_desc->weight); + pango_font_description_set_style(p, (PangoStyle)font_desc->style); + pango_font_description_set_size(p, font_desc->size_pt * PANGO_SCALE); + text = pango_font_description_to_string(p); + pgd_table_add_property(GTK_GRID(table), "Font:", text, row); + g_free(text); } static void pgd_annot_view_set_annot_stamp(GtkWidget *table, PopplerAnnotStamp *annot, gint *row) @@ -616,6 +637,15 @@ static void pgd_annot_view_set_annot(PgdAnnotsDemo *demo, PopplerAnnot *annot) pgd_table_add_property(GTK_GRID(table), "Coords:", text, &row); g_free(text); + double border_width; + if (poppler_annot_get_border_width(POPPLER_ANNOT(annot), &border_width)) { + text = g_strdup_printf("%f", border_width); + } else { + text = g_strdup("unset"); + } + pgd_table_add_property(GTK_GRID(table), "Border Width:", text, &row); + g_free(text); + if (POPPLER_IS_ANNOT_MARKUP(annot)) { pgd_annot_view_set_annot_markup(table, POPPLER_ANNOT_MARKUP(annot), &row); } @@ -859,6 +889,17 @@ static void pgd_annots_add_annot(PgdAnnotsDemo *demo) case POPPLER_ANNOT_TEXT: annot = poppler_annot_text_new(demo->doc, &rect); + break; + case POPPLER_ANNOT_FREE_TEXT: + annot = poppler_annot_free_text_new(demo->doc, &rect); + poppler_annot_set_contents(annot, "Free Text"); + PopplerFontDescription *font_desc = poppler_font_description_new("DejaVu Sans"); + font_desc->size_pt = 17; + font_desc->style = POPPLER_STYLE_OBLIQUE; + font_desc->weight = POPPLER_WEIGHT_BOLD; + font_desc->stretch = POPPLER_STRETCH_CONDENSED; + poppler_annot_free_text_set_font_desc(POPPLER_ANNOT_FREE_TEXT(annot), font_desc); + poppler_font_description_free(font_desc); break; case POPPLER_ANNOT_LINE: { PopplerPoint start, end; diff --git a/glib/poppler-annot.cc b/glib/poppler-annot.cc index b995f0375..0390ed837 100644 --- a/glib/poppler-annot.cc +++ b/glib/poppler-annot.cc @@ -85,6 +85,8 @@ struct _PopplerAnnotTextMarkupClass struct _PopplerAnnotFreeText { PopplerAnnotMarkup parent_instance; + PopplerFontDescription *font_desc; + PopplerColor font_color; }; struct _PopplerAnnotFreeTextClass @@ -420,13 +422,202 @@ PopplerAnnot *poppler_annot_text_markup_new_underline(PopplerDocument *doc, Popp return poppler_annot; } +PopplerColor *_poppler_convert_annot_color_to_poppler_color(const AnnotColor *color) +{ + PopplerColor *poppler_color = nullptr; + + if (color) { + const double *values = color->getValues(); + + switch (color->getSpace()) { + case AnnotColor::colorGray: + poppler_color = g_new(PopplerColor, 1); + + poppler_color->red = CLAMP((guint16)(values[0] * 65535), 0, 65535); + poppler_color->green = poppler_color->red; + poppler_color->blue = poppler_color->red; + + break; + case AnnotColor::colorRGB: + poppler_color = g_new(PopplerColor, 1); + + poppler_color->red = CLAMP((guint16)(values[0] * 65535), 0, 65535); + poppler_color->green = CLAMP((guint16)(values[1] * 65535), 0, 65535); + poppler_color->blue = CLAMP((guint16)(values[2] * 65535), 0, 65535); + + break; + case AnnotColor::colorCMYK: + g_warning("Unsupported Annot Color: colorCMYK"); + break; + case AnnotColor::colorTransparent: + break; + } + } + + return poppler_color; +} + +std::unique_ptr _poppler_convert_poppler_color_to_annot_color(const PopplerColor *poppler_color) +{ + if (!poppler_color) { + return nullptr; + } + + return std::make_unique(CLAMP((double)poppler_color->red / 65535, 0., 1.), CLAMP((double)poppler_color->green / 65535, 0., 1.), CLAMP((double)poppler_color->blue / 65535, 0., 1.)); +} + static void poppler_annot_free_text_init(PopplerAnnotFreeText *poppler_annot) { } static void poppler_annot_free_text_class_init(PopplerAnnotFreeTextClass *klass) { } +// Single map with string keys and enum values +enum FontPropType +{ + TYPE_STYLE, + TYPE_WEIGHT, + TYPE_STRETCH, + TYPE_NORMAL +}; + +typedef std::map> FontstyleMap; + +static const FontstyleMap string_to_fontstyle = { { "UltraCondensed", std::pair(TYPE_STRETCH, POPPLER_STRETCH_ULTRA_CONDENSED) }, + { "ExtraCondensed", std::pair(TYPE_STRETCH, POPPLER_STRETCH_EXTRA_CONDENSED) }, + { "Condensed", std::pair(TYPE_STRETCH, POPPLER_STRETCH_CONDENSED) }, + { "SemiCondensed", std::pair(TYPE_STRETCH, POPPLER_STRETCH_SEMI_CONDENSED) }, + { "SemiExpanded", std::pair(TYPE_STRETCH, POPPLER_STRETCH_SEMI_EXPANDED) }, + { "Expanded", std::pair(TYPE_STRETCH, POPPLER_STRETCH_EXPANDED) }, + { "UltraExpanded", std::pair(TYPE_STRETCH, POPPLER_STRETCH_ULTRA_EXPANDED) }, + { "ExtraExpanded", std::pair(TYPE_STRETCH, POPPLER_STRETCH_EXTRA_EXPANDED) }, + { "Thin", std::pair(TYPE_WEIGHT, POPPLER_WEIGHT_THIN) }, + { "UltraLight", std::pair(TYPE_WEIGHT, POPPLER_WEIGHT_ULTRALIGHT) }, + { "Light", std::pair(TYPE_WEIGHT, POPPLER_WEIGHT_LIGHT) }, + { "Medium", std::pair(TYPE_WEIGHT, POPPLER_WEIGHT_MEDIUM) }, + { "SemiBold", std::pair(TYPE_WEIGHT, POPPLER_WEIGHT_SEMIBOLD) }, + { "Bold", std::pair(TYPE_WEIGHT, POPPLER_WEIGHT_BOLD) }, + { "UltraBold", std::pair(TYPE_WEIGHT, POPPLER_WEIGHT_ULTRABOLD) }, + { "Heavy", std::pair(TYPE_WEIGHT, POPPLER_WEIGHT_HEAVY) }, + { "Italic", std::pair(TYPE_STYLE, POPPLER_STYLE_ITALIC) }, + { "Oblique", std::pair(TYPE_STYLE, POPPLER_STYLE_OBLIQUE) }, + { "Regular", std::pair(TYPE_NORMAL, 0) }, + { "Normal", std::pair(TYPE_NORMAL, 0) } }; + +static const char *stretch_to_str[] = { "UltraCondensed", "ExtraCondensed", "Condensed", "SemiCondensed", /* Normal */ "", "SemiExpanded", "Expanded", "ExtraExpanded", "UltraExpanded" }; + +const std::map fallback_fonts = { + { "/Helvetica", "Helvetica" }, /* iOS */ + { "Helv", "Helvetica" } /* Firefox */ +}; + +static bool update_font_desc_with_word(PopplerFontDescription &font_desc, std::string &word) +{ + FontstyleMap::const_iterator a = string_to_fontstyle.find(word); + if (a != string_to_fontstyle.end()) { + std::pair elt = a->second; + switch (elt.first) { + case TYPE_STYLE: + font_desc.style = (PopplerStyle)elt.second; + return true; + case TYPE_WEIGHT: + font_desc.weight = (PopplerWeight)elt.second; + return true; + case TYPE_STRETCH: + font_desc.stretch = (PopplerStretch)elt.second; + return true; + case TYPE_NORMAL: + return true; + } + } + return false; +} + +static void poppler_font_name_to_description(const std::string &name, PopplerFontDescription &font_desc) +{ + /* Last three words of the font name may be style indications */ + size_t end = name.size(); + size_t start; + + for (int i = 3; i >= 1; --i) { + start = name.find_last_of(' ', end - 1); + if (start == std::string::npos) { + break; + } + std::string word = name.substr(start + 1, end - start - 1); + + if (!update_font_desc_with_word(font_desc, word)) { + break; + } + + end = start; + } + font_desc.font_name = g_strdup(name.substr(0, end).c_str()); +} + PopplerAnnot *_poppler_annot_free_text_new(Annot *annot) { - return _poppler_create_annot(POPPLER_TYPE_ANNOT_FREE_TEXT, annot); + PopplerAnnot *poppler_annot = _poppler_create_annot(POPPLER_TYPE_ANNOT_FREE_TEXT, annot); + PopplerAnnotFreeText *ft_annot = POPPLER_ANNOT_FREE_TEXT(poppler_annot); + std::unique_ptr da = ((AnnotFreeText *)annot)->getDefaultAppearance(); + PopplerFontDescription *desc = nullptr; + if (da->getFontName().isName()) { + desc = poppler_font_description_new(da->getFontName().getName()); + desc->size_pt = da->getFontPtSize(); + + /* Attempt to resolve the actual font name. */ + Form *form = annot->getDoc()->getCatalog()->getCreateForm(); + if (form) { + GfxResources *res = form->getDefaultResources(); + if (res) { + std::shared_ptr font = res->lookupFont(desc->font_name); + if (font && font->getName()) { + poppler_font_name_to_description(font->getName().value(), *desc); + } + } + } + + std::map::const_iterator fallback_font = fallback_fonts.find(std::string(desc->font_name)); + if (fallback_font != fallback_fonts.end()) { + desc->font_name = g_strdup(fallback_font->second.c_str()); + } + } + + ft_annot->font_desc = desc; + + const AnnotColor *ac = da->getFontColor(); + + if (ac) { + PopplerColor *font_color = _poppler_convert_annot_color_to_poppler_color(ac); + ft_annot->font_color = *font_color; + poppler_color_free(font_color); + } + + return poppler_annot; +} + +/** + * poppler_annot_free_text_new: + * @doc: a #PopplerDocument + * @rect: a #PopplerRectangle + * + * Creates a new Free Text annotation that will be + * located on @rect when added to a page. See + * poppler_page_add_annot(). It initially has no content. Font family, size and + * color are initially undefined and must be set, see + * poppler_annot_free_text_set_font_desc() and + * poppler_annot_free_text_set_font_color(). + * + * Returns: (transfer full): A newly created #PopplerAnnotFreeText annotation + */ +PopplerAnnot *poppler_annot_free_text_new(PopplerDocument *doc, PopplerRectangle *rect) +{ + Annot *annot; + PDFRectangle pdf_rect(rect->x1, rect->y1, rect->x2, rect->y2); + + annot = new AnnotFreeText(doc->doc, &pdf_rect); + + PopplerAnnot *poppler_annot = _poppler_annot_free_text_new(annot); + + return poppler_annot; } static void poppler_annot_file_attachment_init(PopplerAnnotFileAttachment *poppler_annot) { } @@ -936,49 +1127,6 @@ void poppler_annot_set_flags(PopplerAnnot *poppler_annot, PopplerAnnotFlag flags poppler_annot->annot->setFlags((guint)flags); } -static PopplerColor *create_poppler_color_from_annot_color(AnnotColor *color) -{ - PopplerColor *poppler_color = nullptr; - - if (color) { - const double *values = color->getValues(); - - switch (color->getSpace()) { - case AnnotColor::colorGray: - poppler_color = g_new(PopplerColor, 1); - - poppler_color->red = (guint16)(values[0] * 65535); - poppler_color->green = poppler_color->red; - poppler_color->blue = poppler_color->red; - - break; - case AnnotColor::colorRGB: - poppler_color = g_new(PopplerColor, 1); - - poppler_color->red = (guint16)(values[0] * 65535); - poppler_color->green = (guint16)(values[1] * 65535); - poppler_color->blue = (guint16)(values[2] * 65535); - - break; - case AnnotColor::colorCMYK: - g_warning("Unsupported Annot Color: colorCMYK"); - case AnnotColor::colorTransparent: - break; - } - } - - return poppler_color; -} - -static std::unique_ptr create_annot_color_from_poppler_color(PopplerColor *poppler_color) -{ - if (!poppler_color) { - return nullptr; - } - - return std::make_unique((double)poppler_color->red / 65535, (double)poppler_color->green / 65535, (double)poppler_color->blue / 65535); -} - /** * poppler_annot_get_color: * @poppler_annot: a #PopplerAnnot @@ -992,7 +1140,7 @@ PopplerColor *poppler_annot_get_color(PopplerAnnot *poppler_annot) { g_return_val_if_fail(POPPLER_IS_ANNOT(poppler_annot), NULL); - return create_poppler_color_from_annot_color(poppler_annot->annot->getColor()); + return _poppler_convert_annot_color_to_poppler_color(poppler_annot->annot->getColor()); } /** @@ -1006,7 +1154,7 @@ PopplerColor *poppler_annot_get_color(PopplerAnnot *poppler_annot) */ void poppler_annot_set_color(PopplerAnnot *poppler_annot, PopplerColor *poppler_color) { - poppler_annot->annot->setColor(create_annot_color_from_poppler_color(poppler_color)); + poppler_annot->annot->setColor(_poppler_convert_poppler_color_to_annot_color(poppler_color)); } /** @@ -1789,6 +1937,147 @@ PopplerAnnotCalloutLine *poppler_annot_free_text_get_callout_line(PopplerAnnotFr return nullptr; } +static std::string poppler_font_description_to_style(PopplerFontDescription *font_desc) +{ + std::string style = ""; + std::function add_style = [&style](const char *a) { + if (strcmp(a, "") != 0) { + if (!style.empty()) { + style += " "; + } + style += a; + } + }; + + /* Stretch */ + add_style(stretch_to_str[font_desc->stretch]); + + /* Don't use a map so that intermediate pango weights are correctly mapped */ + PopplerWeight w = font_desc->weight; + if (w <= POPPLER_WEIGHT_THIN) { + add_style("Thin"); + } else if (w <= POPPLER_WEIGHT_ULTRALIGHT) { + add_style("UltraLight"); + } else if (w <= POPPLER_WEIGHT_LIGHT) { + add_style("Light"); + } else if (w <= POPPLER_WEIGHT_NORMAL) { + add_style(""); + } else if (w <= POPPLER_WEIGHT_MEDIUM) { + add_style("Medium"); + } else if (w <= POPPLER_WEIGHT_SEMIBOLD) { + add_style("SemiBold"); + } else if (w <= POPPLER_WEIGHT_BOLD) { + add_style("Bold"); + } else if (w <= POPPLER_WEIGHT_ULTRABOLD) { + add_style("UltraBold"); + } else { + add_style("Heavy"); + } + + /* Style, i.e. italic, oblique or normal */ + if (font_desc->style == POPPLER_STYLE_ITALIC) { + add_style("Italic"); + } else if (font_desc->style == POPPLER_STYLE_OBLIQUE) { + add_style("Oblique"); + } + + return style; +} + +static void poppler_annot_free_text_set_da_to_native(PopplerAnnotFreeText *poppler_annot) +{ + Annot *annot = POPPLER_ANNOT(poppler_annot)->annot; + + std::string font_name = "Sans"; + double size = 11.; + + if (poppler_annot->font_desc) { + const char *family = poppler_annot->font_desc->font_name; + const std::string style = poppler_font_description_to_style(poppler_annot->font_desc); + + Form *form = annot->getDoc()->getCatalog()->getCreateForm(); + if (form) { + font_name = form->findFontInDefaultResources(family, style); + if (font_name.empty()) { + font_name = form->addFontToDefaultResources(family, style).fontName; + } + + if (!font_name.empty()) { + form->ensureFontsForAllCharacters(annot->getContents(), font_name); + } + } + size = poppler_annot->font_desc->size_pt; + } + + DefaultAppearance da { { objName, font_name.c_str() }, size, _poppler_convert_poppler_color_to_annot_color(&(poppler_annot->font_color)) }; + ((AnnotFreeText *)annot)->setDefaultAppearance(da); +} + +/** + * poppler_annot_free_text_set_font_desc: + * @poppler_annot: a #PopplerAnnotFreeText + * @font_desc: a #PopplerFontDescription + * + * Sets the font description (i.e. font family name, style, weight, stretch and size). + * + * Since: 24.12.0 + **/ +void poppler_annot_free_text_set_font_desc(PopplerAnnotFreeText *poppler_annot, PopplerFontDescription *font_desc) +{ + if (poppler_annot->font_desc) { + poppler_font_description_free(poppler_annot->font_desc); + } + poppler_annot->font_desc = poppler_font_description_copy(font_desc); + poppler_annot_free_text_set_da_to_native(poppler_annot); +} + +/** + * poppler_annot_free_text_get_font_desc: + * @poppler_annot: a #PopplerAnnotFreeText + * + * Gets the font description (i.e. font family name, style, weight, stretch and size). + * + * Returns: (transfer full): a copy of the annotation font description + * + * Since: 24.12.0 + **/ +PopplerFontDescription *poppler_annot_free_text_get_font_desc(PopplerAnnotFreeText *poppler_annot) +{ + return poppler_font_description_copy(poppler_annot->font_desc); +} + +/** + * poppler_annot_free_text_set_font_color: + * @poppler_annot: a #PopplerAnnotFreeText + * @color: a #PopplerColor + * + * Sets the font color. + * + * Since: 24.12.0 + **/ +void poppler_annot_free_text_set_font_color(PopplerAnnotFreeText *poppler_annot, PopplerColor *color) +{ + poppler_annot->font_color = *color; + poppler_annot_free_text_set_da_to_native(poppler_annot); +} + +/** + * poppler_annot_free_text_get_font_color: + * @poppler_annot: a #PopplerAnnotFreeText + * + * Gets the font color. + * + * Returns: (transfer full): a copy of the font's #PopplerColor. + * + * Since: 24.12.0 + **/ +PopplerColor *poppler_annot_free_text_get_font_color(PopplerAnnotFreeText *poppler_annot) +{ + PopplerColor *color = g_new(PopplerColor, 1); + *color = poppler_annot->font_color; + return color; +} + /* PopplerAnnotFileAttachment */ /** * poppler_annot_file_attachment_get_attachment: @@ -1976,7 +2265,7 @@ static PopplerColor *poppler_annot_geometry_get_interior_color(PopplerAnnot *pop annot = static_cast(POPPLER_ANNOT(poppler_annot)->annot); - return create_poppler_color_from_annot_color(annot->getInteriorColor()); + return _poppler_convert_annot_color_to_poppler_color(annot->getInteriorColor()); } static void poppler_annot_geometry_set_interior_color(PopplerAnnot *poppler_annot, PopplerColor *poppler_color) @@ -1985,7 +2274,7 @@ static void poppler_annot_geometry_set_interior_color(PopplerAnnot *poppler_anno annot = static_cast(POPPLER_ANNOT(poppler_annot)->annot); - annot->setInteriorColor(create_annot_color_from_poppler_color(poppler_color)); + annot->setInteriorColor(_poppler_convert_poppler_color_to_annot_color(poppler_color)); } /* PopplerAnnotCircle */ @@ -2199,3 +2488,108 @@ gboolean poppler_annot_stamp_set_custom_image(PopplerAnnotStamp *poppler_annot, return TRUE; } + +/** + * poppler_annot_get_border_width: + * @poppler_annot: a #PopplerAnnot + * @border_width: a valid pointer to a double + * + * Returns the border width of the annotation. Some PDF editors set a border + * width even if the border is not actually drawn. + * + * Returns: true and sets @border_width to the actual border width if a border + * is defined, otherwise returns false and sets @border_width to 0. + * + * Since: 24.12.0 + */ +gboolean poppler_annot_get_border_width(PopplerAnnot *poppler_annot, double *border_width) +{ + Annot *annot = poppler_annot->annot; + AnnotBorder *b = annot->getBorder(); + if (b) { + *border_width = b->getWidth(); + return TRUE; + } else { + *border_width = 0.; + return FALSE; + } +} +/** + * poppler_annot_set_border_width: + * @poppler_annot: a #PopplerAnnot + * @border_width: the new border width + * + * Sets the border width of the annotation. Since there is currently no + * mechanism in the GLib binding to control the appearance of the border width, + * this should generally only be used to disable the border, although the + * API might be completed in the future. + * + * Since: 24.12.0 + */ +void poppler_annot_set_border_width(PopplerAnnot *poppler_annot, double border_width) +{ + Annot *annot = poppler_annot->annot; + std::unique_ptr border = std::make_unique(); + border->setWidth(border_width); + annot->setBorder(std::move(border)); +} + +/** + * SECTION:poppler-font-description + * @short_description: FontDescription + * @title: PopplerFontDescription + */ + +/* PopplerFontDescription type */ +G_DEFINE_BOXED_TYPE(PopplerFontDescription, poppler_font_description, poppler_font_description_copy, poppler_font_description_free) + +/** + * poppler_font_description_new: + * @font_name: the family name of the font + * + * Creates a new #PopplerFontDescriptions + * + * Returns: a new #PopplerFontDescription, use poppler_font_description_free() to free it + */ +PopplerFontDescription *poppler_font_description_new(const char *font_name) +{ + PopplerFontDescription *font_desc = (PopplerFontDescription *)g_new0(PopplerFontDescription, 1); + font_desc->font_name = g_strdup(font_name); + font_desc->size_pt = 11.; + font_desc->stretch = POPPLER_STRETCH_NORMAL; + font_desc->style = POPPLER_STYLE_NORMAL; + font_desc->weight = POPPLER_WEIGHT_NORMAL; + return font_desc; +} + +/** + * poppler_font_description_free: + * @font_desc: a #PopplerFontDescription + * + * Frees the given #PopplerFontDescription + */ +void poppler_font_description_free(PopplerFontDescription *font_desc) +{ + g_free(font_desc->font_name); + g_free(font_desc); +} + +/** + * poppler_font_description_copy: + * @font_desc: a #PopplerFontDescription to copy + * + * Creates a copy of @font_desc + * + * Returns: a new allocated copy of @font_desc + */ +PopplerFontDescription *poppler_font_description_copy(PopplerFontDescription *font_desc) +{ + PopplerFontDescription *new_font_desc; + + new_font_desc = g_new(PopplerFontDescription, 1); + *new_font_desc = *font_desc; + + new_font_desc->font_name = g_strdup(font_desc->font_name); + + return new_font_desc; +} diff --git a/glib/poppler-annot.h b/glib/poppler-annot.h index 9f362b2f9..ab286801a 100644 --- a/glib/poppler-annot.h +++ b/glib/poppler-annot.h @@ -193,6 +193,67 @@ typedef enum POPPLER_ANNOT_STAMP_ICON_NONE } PopplerAnnotStampIcon; +/* The next three enums are value-compatible with pango equivalents. */ + +typedef enum +{ + POPPLER_STRETCH_ULTRA_CONDENSED, + POPPLER_STRETCH_EXTRA_CONDENSED, + POPPLER_STRETCH_CONDENSED, + POPPLER_STRETCH_SEMI_CONDENSED, + POPPLER_STRETCH_NORMAL, + POPPLER_STRETCH_SEMI_EXPANDED, + POPPLER_STRETCH_EXPANDED, + POPPLER_STRETCH_EXTRA_EXPANDED, + POPPLER_STRETCH_ULTRA_EXPANDED +} PopplerStretch; + +typedef enum +{ + POPPLER_WEIGHT_THIN = 100, + POPPLER_WEIGHT_ULTRALIGHT = 200, + POPPLER_WEIGHT_LIGHT = 300, + POPPLER_WEIGHT_NORMAL = 400, + POPPLER_WEIGHT_MEDIUM = 500, + POPPLER_WEIGHT_SEMIBOLD = 600, + POPPLER_WEIGHT_BOLD = 700, + POPPLER_WEIGHT_ULTRABOLD = 800, + POPPLER_WEIGHT_HEAVY = 900 +} PopplerWeight; + +typedef enum +{ + POPPLER_STYLE_NORMAL, + POPPLER_STYLE_OBLIQUE, + POPPLER_STYLE_ITALIC +} PopplerStyle; + +/** + * PopplerFontDescription: + * @font_name: name of font family + * @size_pt: size of font in pt + * @stretch: a #PopplerStretch representing stretch of the font + * @weight: a #PopplerWeight representing weight of the font + * @style: a #PopplerStyle representing style of the font + * + * A #PopplerFontDescription structure represents the description + * of a font. When used together with Pango, all the fields are + * value-compatible with pango equivalent, although Pango font + * descriptions may contain more information. + * + * This type supports g_autoptr + * + * Since: 24.12.0 + */ +struct _PopplerFontDescription +{ + char *font_name; + double size_pt; + PopplerStretch stretch; + PopplerWeight weight; + PopplerStyle style; +}; + POPPLER_PUBLIC GType poppler_annot_get_type(void) G_GNUC_CONST; POPPLER_PUBLIC @@ -219,6 +280,10 @@ POPPLER_PUBLIC void poppler_annot_get_rectangle(PopplerAnnot *poppler_annot, PopplerRectangle *poppler_rect); POPPLER_PUBLIC void poppler_annot_set_rectangle(PopplerAnnot *poppler_annot, PopplerRectangle *poppler_rect); +POPPLER_PUBLIC +gboolean poppler_annot_get_border_width(PopplerAnnot *poppler_annot, double *width); +POPPLER_PUBLIC +void poppler_annot_set_border_width(PopplerAnnot *poppler_annot, double width); /* PopplerAnnotMarkup */ POPPLER_PUBLIC @@ -288,9 +353,29 @@ GArray *poppler_annot_text_markup_get_quadrilaterals(PopplerAnnotTextMarkup *pop POPPLER_PUBLIC GType poppler_annot_free_text_get_type(void) G_GNUC_CONST; POPPLER_PUBLIC +PopplerAnnot *poppler_annot_free_text_new(PopplerDocument *doc, PopplerRectangle *rect); +POPPLER_PUBLIC PopplerAnnotFreeTextQuadding poppler_annot_free_text_get_quadding(PopplerAnnotFreeText *poppler_annot); POPPLER_PUBLIC PopplerAnnotCalloutLine *poppler_annot_free_text_get_callout_line(PopplerAnnotFreeText *poppler_annot); +POPPLER_PUBLIC +void poppler_annot_free_text_set_font_desc(PopplerAnnotFreeText *poppler_annot, PopplerFontDescription *font_desc); +POPPLER_PUBLIC +PopplerFontDescription *poppler_annot_free_text_get_font_desc(PopplerAnnotFreeText *poppler_annot); +POPPLER_PUBLIC +void poppler_annot_free_text_set_font_color(PopplerAnnotFreeText *poppler_annot, PopplerColor *color); +POPPLER_PUBLIC +PopplerColor *poppler_annot_free_text_get_font_color(PopplerAnnotFreeText *poppler_annot); + +/* Fonts Handling for AnnotFreeText */ +POPPLER_PUBLIC +GType poppler_font_description_get_type(void) G_GNUC_CONST; +POPPLER_PUBLIC +PopplerFontDescription *poppler_font_description_new(const char *font_name); +POPPLER_PUBLIC +void poppler_font_description_free(PopplerFontDescription *font_desc); +POPPLER_PUBLIC +PopplerFontDescription *poppler_font_description_copy(PopplerFontDescription *font_desc); /* PopplerAnnotFileAttachment */ POPPLER_PUBLIC @@ -366,4 +451,6 @@ gboolean poppler_annot_stamp_set_custom_image(PopplerAnnotStamp *poppler_annot, G_END_DECLS +G_DEFINE_AUTOPTR_CLEANUP_FUNC(PopplerFontDescription, poppler_font_description_free) + #endif /* __POPPLER_ANNOT_H__ */ diff --git a/glib/poppler-document.cc b/glib/poppler-document.cc index 40739e82f..b19fcca5e 100644 --- a/glib/poppler-document.cc +++ b/glib/poppler-document.cc @@ -3898,9 +3898,9 @@ static void _poppler_sign_document_thread(GTask *task, PopplerDocument *document ret = document->doc->sign(poppler_signing_data_get_destination_filename(signing_data), poppler_certificate_info_get_id((PopplerCertificateInfo *)certificate_info), poppler_signing_data_get_password(signing_data) ? poppler_signing_data_get_password(signing_data) : "", field_partial_name, poppler_signing_data_get_page(signing_data) + 1, PDFRectangle(rect->x1, rect->y1, rect->x2, rect->y2), *signature_text, *signature_text_left, poppler_signing_data_get_font_size(signing_data), poppler_signing_data_get_left_font_size(signing_data), - std::make_unique(font_color->red, font_color->green, font_color->blue), poppler_signing_data_get_border_width(signing_data), - std::make_unique(border_color->red, border_color->green, border_color->blue), std::make_unique(background_color->red, background_color->green, background_color->blue), reason.get(), - location.get(), poppler_signing_data_get_image_path(signing_data) ? poppler_signing_data_get_image_path(signing_data) : "", owner_pwd, user_pwd); + _poppler_convert_poppler_color_to_annot_color(font_color), poppler_signing_data_get_border_width(signing_data), _poppler_convert_poppler_color_to_annot_color(border_color), + _poppler_convert_poppler_color_to_annot_color(background_color), reason.get(), location.get(), poppler_signing_data_get_image_path(signing_data) ? poppler_signing_data_get_image_path(signing_data) : "", + owner_pwd, user_pwd); g_task_return_boolean(task, ret); } diff --git a/glib/poppler-private.h b/glib/poppler-private.h index 758c70214..0dc2e51c6 100644 --- a/glib/poppler-private.h +++ b/glib/poppler-private.h @@ -165,6 +165,8 @@ 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); +PopplerColor *_poppler_convert_annot_color_to_poppler_color(const AnnotColor *color); +std::unique_ptr _poppler_convert_poppler_color_to_annot_color(const PopplerColor *poppler_color); void _poppler_error_cb(ErrorCategory category, Goffset pos, const char *message); diff --git a/glib/poppler.h b/glib/poppler.h index 70f2172a3..435e28c59 100644 --- a/glib/poppler.h +++ b/glib/poppler.h @@ -186,6 +186,7 @@ typedef struct _PopplerPoint PopplerPoint; typedef struct _PopplerRectangle PopplerRectangle; typedef struct _PopplerTextAttributes PopplerTextAttributes; typedef struct _PopplerColor PopplerColor; +typedef struct _PopplerFontDescription PopplerFontDescription; typedef struct _PopplerLinkMapping PopplerLinkMapping; typedef struct _PopplerPageTransition PopplerPageTransition; typedef struct _PopplerImageMapping PopplerImageMapping; diff --git a/glib/reference/poppler-sections.txt b/glib/reference/poppler-sections.txt index 6ed80d30b..95e6426e2 100644 --- a/glib/reference/poppler-sections.txt +++ b/glib/reference/poppler-sections.txt @@ -526,6 +526,7 @@ PopplerAnnotMarkupReplyType PopplerAnnotTextState PopplerAnnotStampIcon PopplerAnnotType +PopplerFontDescription poppler_annot_get_annot_type POPPLER_ANNOT_TEXT_ICON_CIRCLE POPPLER_ANNOT_TEXT_ICON_COMMENT @@ -545,7 +546,12 @@ poppler_annot_circle_set_interior_color poppler_annot_file_attachment_get_attachment poppler_annot_file_attachment_get_name poppler_annot_free_text_get_callout_line +poppler_annot_free_text_get_font_color +poppler_annot_free_text_get_font_desc poppler_annot_free_text_get_quadding +poppler_annot_free_text_new +poppler_annot_free_text_set_font_desc +poppler_annot_free_text_set_font_color poppler_annot_get_color poppler_annot_get_contents poppler_annot_get_flags @@ -553,6 +559,7 @@ poppler_annot_get_modified poppler_annot_get_name poppler_annot_get_page_index poppler_annot_get_rectangle +poppler_annot_get_border_width poppler_annot_line_new poppler_annot_line_set_vertices poppler_annot_markup_get_date @@ -576,6 +583,7 @@ poppler_annot_set_color poppler_annot_set_contents poppler_annot_set_flags poppler_annot_set_rectangle +poppler_annot_set_border_width poppler_annot_square_get_interior_color poppler_annot_square_new poppler_annot_square_set_interior_color @@ -595,6 +603,30 @@ poppler_annot_text_markup_set_quadrilaterals poppler_annot_text_new poppler_annot_text_set_icon poppler_annot_text_set_is_open +poppler_font_description_copy +poppler_font_description_free +poppler_font_description_new +POPPLER_STRETCH_ULTRA_CONDENSED +POPPLER_STRETCH_EXTRA_CONDENSED +POPPLER_STRETCH_CONDENSED +POPPLER_STRETCH_SEMI_CONDENSED +POPPLER_STRETCH_NORMAL +POPPLER_STRETCH_SEMI_EXPANDED +POPPLER_STRETCH_EXPANDED +POPPLER_STRETCH_EXTRA_EXPANDED +POPPLER_STRETCH_ULTRA_EXPANDED +POPPLER_STYLE_NORMAL +POPPLER_STYLE_OBLIQUE +POPPLER_STYLE_ITALIC +POPPLER_WEIGHT_THIN +POPPLER_WEIGHT_ULTRALIGHT +POPPLER_WEIGHT_LIGHT +POPPLER_WEIGHT_NORMAL +POPPLER_WEIGHT_MEDIUM +POPPLER_WEIGHT_SEMIBOLD +POPPLER_WEIGHT_BOLD +POPPLER_WEIGHT_ULTRABOLD +POPPLER_WEIGHT_HEAVY POPPLER_ANNOT @@ -659,6 +691,7 @@ poppler_annot_text_get_type poppler_annot_text_markup_get_type poppler_annot_text_state_get_type poppler_annot_type_get_type +poppler_font_description_get_type
diff --git a/glib/reference/poppler.types b/glib/reference/poppler.types index e5b924e8a..c97ad1789 100644 --- a/glib/reference/poppler.types +++ b/glib/reference/poppler.types @@ -94,4 +94,5 @@ poppler_text_attributes_get_type poppler_text_span_get_type poppler_viewer_preferences_get_type poppler_signing_data_get_type -poppler_certificate_info_get_type \ No newline at end of file +poppler_certificate_info_get_type +poppler_font_description_get_type \ No newline at end of file