Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package pango for openSUSE:Factory checked in at 2026-08-19 17:55:50 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/pango (Old) and /work/SRC/openSUSE:Factory/.pango.new.1258 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "pango" Wed Aug 19 17:55:50 2026 rev:159 rq:1371799 version:1.58.2 Changes: -------- --- /work/SRC/openSUSE:Factory/pango/pango.changes 2026-06-29 17:28:34.874401798 +0200 +++ /work/SRC/openSUSE:Factory/.pango.new.1258/pango.changes 2026-08-19 17:56:32.867173711 +0200 @@ -1,0 +2,12 @@ +Wed Aug 5 22:25:57 UTC 2026 - Bjørn Lie <[email protected]> + +- Update to version 1.58.2: + + Require harfbuzz 11 + + Require glib 2.88 + + CoreText: + - Support variations + - Support font features from descriptions + + Renderer: Keep over/under/through lines in sync + + Fixes for undefined behavior + +------------------------------------------------------------------- Old: ---- pango-1.58.0.tar.xz New: ---- pango-1.58.2.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ pango.spec ++++++ --- /var/tmp/diff_new_pack.qfZi9o/_old 2026-08-19 17:56:33.714204333 +0200 +++ /var/tmp/diff_new_pack.qfZi9o/_new 2026-08-19 17:56:33.717204442 +0200 @@ -17,7 +17,7 @@ Name: pango -Version: 1.58.0 +Version: 1.58.2 Release: 0 Summary: Library for Layout and Rendering of Text License: LGPL-2.1-or-later @@ -34,10 +34,10 @@ BuildRequires: pkgconfig(fontconfig) >= 2.17 BuildRequires: pkgconfig(freetype2) BuildRequires: pkgconfig(fribidi) >= 1.0.6 -BuildRequires: pkgconfig(glib-2.0) >= 2.80 -BuildRequires: pkgconfig(gobject-2.0) >= 2.80 +BuildRequires: pkgconfig(glib-2.0) >= 2.88 +BuildRequires: pkgconfig(gobject-2.0) >= 2.88 BuildRequires: pkgconfig(gobject-introspection-1.0) -BuildRequires: pkgconfig(harfbuzz) >= 8.4 +BuildRequires: pkgconfig(harfbuzz) >= 11.0.0 BuildRequires: pkgconfig(libthai) >= 0.1.9 BuildRequires: pkgconfig(xft) >= 2.0.0 BuildRequires: pkgconfig(xrender) ++++++ _scmsync.obsinfo ++++++ --- /var/tmp/diff_new_pack.qfZi9o/_old 2026-08-19 17:56:33.748205562 +0200 +++ /var/tmp/diff_new_pack.qfZi9o/_new 2026-08-19 17:56:33.751205671 +0200 @@ -1,6 +1,6 @@ -mtime: 1782498731 -commit: fba58d7cd8f0bb1e12f3ba0f4763319eb57c0a2a8aaefafb30af8a78a41e0f04 +mtime: 1785968945 +commit: 89bfae97b6948a89c4fbbbcfda6672f927fe406754aa693a8766ef3e3020bdae url: https://src.opensuse.org/GNOME/pango -revision: fba58d7cd8f0bb1e12f3ba0f4763319eb57c0a2a8aaefafb30af8a78a41e0f04 +revision: 89bfae97b6948a89c4fbbbcfda6672f927fe406754aa693a8766ef3e3020bdae projectscmsync: https://src.opensuse.org/GNOME/_ObsPrj ++++++ _service ++++++ --- /var/tmp/diff_new_pack.qfZi9o/_old 2026-08-19 17:56:33.774206502 +0200 +++ /var/tmp/diff_new_pack.qfZi9o/_new 2026-08-19 17:56:33.777206611 +0200 @@ -3,7 +3,7 @@ <service name="obs_scm" mode="manual"> <param name="url">https://gitlab.gnome.org/GNOME/pango.git</param> <param name="scm">git</param> - <param name="revision">1.58.0</param> + <param name="revision">1.58.2</param> <param name="versionformat">@PARENT_TAG@+@TAG_OFFSET@</param> <param name="versionrewrite-pattern">(.*)\+0</param> <param name="versionrewrite-replacement">\1</param> ++++++ build.specials.obscpio ++++++ ++++++ build.specials.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.gitignore new/.gitignore --- old/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/.gitignore 2026-08-06 00:29:05.000000000 +0200 @@ -0,0 +1,5 @@ +*.obscpio +*.osc +_build.* +.pbuild +osc-collab.* ++++++ pango-1.58.0.tar.xz -> pango-1.58.2.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pango-1.58.0/.gitlab-ci/run-tests.sh new/pango-1.58.2/.gitlab-ci/run-tests.sh --- old/pango-1.58.0/.gitlab-ci/run-tests.sh 2026-06-26 18:39:37.000000000 +0200 +++ new/pango-1.58.2/.gitlab-ci/run-tests.sh 2026-08-05 19:54:07.000000000 +0200 @@ -8,6 +8,8 @@ # Ignore memory leaks lower in dependencies export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp:print_suppressions=0:symbolize=1 +# ubsan only warns by default +export UBSAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_stacktrace=1 export ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer export FONTCONFIG_FILE=/etc/fonts/fonts.conf diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pango-1.58.0/.gitlab-ci.yml new/pango-1.58.2/.gitlab-ci.yml --- old/pango-1.58.0/.gitlab-ci.yml 2026-06-26 18:39:37.000000000 +0200 +++ new/pango-1.58.2/.gitlab-ci.yml 2026-08-05 19:54:07.000000000 +0200 @@ -34,7 +34,7 @@ - meson setup ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} _build - meson compile -C _build - .gitlab-ci/run-tests.sh _build - - meson dist -C _build --include-subprojects --no-tests + - meson dist -C _build --no-tests artifacts: name: "${env:CI_JOB_NAME}-${env:CI_COMMIT_REF_NAME}" when: always @@ -47,14 +47,16 @@ - "${CI_PROJECT_DIR}/_build/hello.png" - "${CI_PROJECT_DIR}/_build/fontlist.txt" -asan-build: +sanitizer-build: extends: .only-default image: $FEDORA_IMAGE tags: [ asan ] stage: analysis needs: [] script: - - CC=clang meson setup --buildtype=debugoptimized -Db_sanitize=address -Db_lundef=false -Dintrospection=disabled _build + # ubsan's 'function' check fires on every GObject call through a generic + # prototype, and glib is built as a subproject here, so it is sanitized too + - CC=clang meson setup --buildtype=debugoptimized -Db_sanitize=address,undefined -Dc_args=-fno-sanitize=function -Db_lundef=false -Dintrospection=disabled _build - meson compile -C _build - .gitlab-ci/run-tests.sh _build artifacts: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pango-1.58.0/NEWS new/pango-1.58.2/NEWS --- old/pango-1.58.0/NEWS 2026-06-26 18:39:37.000000000 +0200 +++ new/pango-1.58.2/NEWS 2026-08-05 19:54:07.000000000 +0200 @@ -1,3 +1,18 @@ +Overview of changes in 1.58.2, 05-08-2026 +========================================= + +* No changes + +Overview of changes in 1.58.1, 03-08-2026 +========================================= + +* Require harfbuzz 11 +* Require glib 2.88 +* CoreText: Support variations +* CoreText: Support font features from descriptions +* Renderer: Keep over/under/through lines in sync +* Fixes for undefined behavior + Overview of changes in 1.58.0, 26-06-2026 ========================================= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pango-1.58.0/meson.build new/pango-1.58.2/meson.build --- old/pango-1.58.0/meson.build 2026-06-26 18:39:37.000000000 +0200 +++ new/pango-1.58.2/meson.build 2026-08-05 19:54:07.000000000 +0200 @@ -1,5 +1,5 @@ project('pango', 'c', 'cpp', - version: '1.58.0', + version: '1.58.2', license: 'LGPLv2.1+', default_options: [ 'buildtype=debugoptimized', @@ -209,13 +209,13 @@ pango_deps = [] glib_major_req = 2 -glib_minor_req = 82 +glib_minor_req = 88 glib_req = '>= @0@.@1@'.format(glib_major_req, glib_minor_req) gi_req = '>= 1.83.2' fribidi_req = '>= 1.0.6' libthai_req = '>= 0.1.9' -harfbuzz_req = '>= 8.4.0' +harfbuzz_req = '>= 11.0.0' fontconfig_req = '>= 2.17.0' xft_req = '>= 2.0.0' cairo_req = '>= 1.18.0' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pango-1.58.0/pango/pango-font.h new/pango-1.58.2/pango/pango-font.h --- old/pango-1.58.0/pango/pango-font.h 2026-06-26 18:39:37.000000000 +0200 +++ new/pango-1.58.2/pango/pango-font.h 2026-08-05 19:54:07.000000000 +0200 @@ -247,7 +247,7 @@ * * Font width is specified. * - * This is an alias for [[email protected]]. + * This is an alias for [[email protected]]. * * 1.58 */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pango-1.58.0/pango/pango-impl-utils.h new/pango-1.58.2/pango/pango-impl-utils.h --- old/pango-1.58.0/pango/pango-impl-utils.h 2026-06-26 18:39:37.000000000 +0200 +++ new/pango-1.58.2/pango/pango-impl-utils.h 2026-08-05 19:54:07.000000000 +0200 @@ -279,6 +279,108 @@ } } +static inline void +pango_maybe_add_feature (GString *str, + const char *features, + const char *feature) +{ + char buf[8] = { 0, }; + + memcpy (buf, feature, 4); + if (features && strstr (features, buf)) + return; + + if (str->len > 0) + g_string_append_c (str, ','); + g_string_append (str, feature); +} + +static inline char * +pango_combine_features (PangoVariant variant, + const char *features) +{ + GString *str = g_string_new (NULL); + + switch (variant) + { + case PANGO_VARIANT_SMALL_CAPS: + pango_maybe_add_feature (str, features, "smcp=1"); + break; + case PANGO_VARIANT_ALL_SMALL_CAPS: + pango_maybe_add_feature (str, features, "smcp=1"); + pango_maybe_add_feature (str, features, "c2sc=1"); + break; + case PANGO_VARIANT_PETITE_CAPS: + pango_maybe_add_feature (str, features, "pcap=1"); + break; + case PANGO_VARIANT_ALL_PETITE_CAPS: + pango_maybe_add_feature (str, features, "pcap=1"); + pango_maybe_add_feature (str, features, "c2pc=1"); + break; + case PANGO_VARIANT_UNICASE: + pango_maybe_add_feature (str, features, "unic=1"); + break; + case PANGO_VARIANT_TITLE_CAPS: + pango_maybe_add_feature (str, features, "titl=1"); + break; + case PANGO_VARIANT_NORMAL: + default: + break; + } + + if (features) + { + if (str->len > 0) + g_string_append_c (str, ','); + g_string_append (str, features); + } + + return g_string_free (str, FALSE); +} + +static inline PangoVariant +pango_features_get_variant (const char *features) +{ + PangoVariant variant = PANGO_VARIANT_NORMAL; + gboolean all_caps = FALSE; + char **tokens; + + if (!features || !*features) + return PANGO_VARIANT_NORMAL; + + tokens = g_strsplit (features, ",", -1); + for (int i = 0; tokens[i]; i++) + { + const char *s = tokens[i]; + + if (strcmp (s, "smcp=1") == 0) + variant = all_caps ? PANGO_VARIANT_ALL_SMALL_CAPS : PANGO_VARIANT_SMALL_CAPS; + else if (strcmp (s, "c2sc=1") == 0) + { + if (variant == PANGO_VARIANT_SMALL_CAPS) + variant = PANGO_VARIANT_ALL_SMALL_CAPS; + else + all_caps = TRUE; + } + else if (strcmp (s, "pcap=1") == 0) + variant = all_caps ? PANGO_VARIANT_ALL_PETITE_CAPS : PANGO_VARIANT_PETITE_CAPS; + else if (strcmp (s, "c2pc=1") == 0) + { + if (variant == PANGO_VARIANT_PETITE_CAPS) + variant = PANGO_VARIANT_ALL_PETITE_CAPS; + else + all_caps = TRUE; + } + else if (strcmp (s, "unic=1") == 0) + variant = PANGO_VARIANT_UNICASE; + else if (strcmp (s, "titl=1") == 0) + variant = PANGO_VARIANT_TITLE_CAPS; + } + g_strfreev (tokens); + + return variant; +} + G_END_DECLS #endif /* __PANGO_IMPL_UTILS_H__ */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pango-1.58.0/pango/pango-layout.c new/pango-1.58.2/pango/pango-layout.c --- old/pango-1.58.0/pango/pango-layout.c 2026-06-26 18:39:37.000000000 +0200 +++ new/pango-1.58.2/pango/pango-layout.c 2026-08-05 19:54:07.000000000 +0200 @@ -6786,7 +6786,13 @@ #endif if (item->analysis.font == NULL) - continue; + { + /* create_run() leaves these uninitialized */ + run->y_offset = 0; + run->start_x_offset = 0; + run->end_x_offset = 0; + continue; + } #if HB_VERSION_ATLEAST(4,0,0) hb_font = pango_font_get_hb_font (item->analysis.font); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pango-1.58.0/pango/pango-renderer.c new/pango-1.58.2/pango/pango-renderer.c --- old/pango-1.58.0/pango/pango-renderer.c 2026-06-26 18:39:37.000000000 +0200 +++ new/pango-1.58.2/pango/pango-renderer.c 2026-08-05 19:54:07.000000000 +0200 @@ -428,8 +428,8 @@ int underline_thickness = pango_font_metrics_get_underline_thickness (metrics); int ascent = pango_font_metrics_get_ascent (metrics); - new_rect.x = base_x + ink_rect->x; - new_rect.width = ink_rect->width; + new_rect.x = base_x + MIN (ink_rect->x, logical_rect->x); + new_rect.width = MAX (ink_rect->width, logical_rect->width); new_rect.height = underline_thickness; new_rect.y = base_y; @@ -483,8 +483,8 @@ int strikethrough_thickness = pango_font_metrics_get_strikethrough_thickness (metrics); int strikethrough_position = pango_font_metrics_get_strikethrough_position (metrics); - new_rect.x = base_x + ink_rect->x; - new_rect.width = ink_rect->width; + new_rect.x = base_x + MIN (ink_rect->x, logical_rect->x); + new_rect.width = MAX (ink_rect->width, logical_rect->width); new_rect.y = (base_y - strikethrough_position) * num_glyphs; new_rect.height = strikethrough_thickness * num_glyphs; @@ -704,12 +704,12 @@ run->item->analysis.language); if (renderer->underline != PANGO_UNDERLINE_NONE) - add_underline (renderer, &state,metrics, + add_underline (renderer, &state, metrics, x + x_off, y - y_off, ink, logical); if (renderer->priv->overline != PANGO_OVERLINE_NONE) - add_overline (renderer, &state,metrics, + add_overline (renderer, &state, metrics, x + x_off, y - y_off, ink, logical); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pango-1.58.0/pango/pangocairo-coretextfont.c new/pango-1.58.2/pango/pangocairo-coretextfont.c --- old/pango-1.58.0/pango/pangocairo-coretextfont.c 2026-06-26 18:39:37.000000000 +0200 +++ new/pango-1.58.2/pango/pangocairo-coretextfont.c 2026-08-05 19:54:07.000000000 +0200 @@ -23,7 +23,8 @@ #include "config.h" -#include <Carbon/Carbon.h> +#include <hb.h> +#include <CoreText/CoreText.h> #include "pango-impl-utils.h" #include "pangocoretext-private.h" @@ -160,6 +161,90 @@ { } +static CFDictionaryRef +create_ct_variations (CTFontRef ctfont, + double point_size, + const char *variations) +{ + CFArrayRef axes; + CFDictionaryRef instance; + CFMutableDictionaryRef result; + CFIndex n_axes; + + axes = CTFontCopyVariationAxes (ctfont); + if (!axes) + return NULL; + + n_axes = CFArrayGetCount (axes); + if (n_axes == 0) + { + CFRelease (axes); + return NULL; + } + + instance = CTFontCopyVariation (ctfont); + result = CFDictionaryCreateMutable (kCFAllocatorDefault, n_axes, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + for (CFIndex i = 0; i < n_axes; i++) + { + CFDictionaryRef axis = CFArrayGetValueAtIndex (axes, i); + CFNumberRef identifier = CFDictionaryGetValue (axis, kCTFontVariationAxisIdentifierKey); + CFNumberRef number; + SInt32 tag = 0; + double value = 0; + + CFNumberGetValue (identifier, kCFNumberSInt32Type, &tag); + CFNumberGetValue (CFDictionaryGetValue (axis, kCTFontVariationAxisDefaultValueKey), + kCFNumberDoubleType, &value); + + if (tag == HB_TAG ('o', 'p', 's', 'z')) + value = point_size; + + if (instance) + { + CFNumberRef pinned = CFDictionaryGetValue (instance, identifier); + if (pinned) + CFNumberGetValue (pinned, kCFNumberDoubleType, &value); + } + + number = CFNumberCreate (kCFAllocatorDefault, kCFNumberDoubleType, &value); + CFDictionarySetValue (result, identifier, number); + CFRelease (number); + } + + if (variations) + { + char **tokens = g_strsplit (variations, ",", -1); + + for (int i = 0; tokens[i]; i++) + { + hb_variation_t var; + + if (hb_variation_from_string (tokens[i], -1, &var)) + { + SInt32 tag = var.tag; + double value = var.value; + CFNumberRef identifier = CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt32Type, &tag); + CFNumberRef number = CFNumberCreate (kCFAllocatorDefault, kCFNumberDoubleType, &value); + + CFDictionarySetValue (result, identifier, number); + CFRelease (identifier); + CFRelease (number); + } + } + + g_strfreev (tokens); + } + + if (instance) + CFRelease (instance); + CFRelease (axes); + + return result; +} + PangoCoreTextFont * _pango_cairo_core_text_font_new (PangoCairoCoreTextFontMap *cafontmap, PangoCoreTextFontKey *key) @@ -174,6 +259,7 @@ cairo_matrix_t font_matrix; cairo_font_options_t *options; const char *variations; + CFDictionaryRef variations_dict; size = pango_units_to_double (pango_core_text_font_key_get_size (key)); @@ -189,6 +275,31 @@ if (!font_id) return NULL; + variations = pango_core_text_font_key_get_variations (key); + + variations_dict = create_ct_variations (font_ref, size, variations); + if (variations_dict) + { + const void *attr_keys[1] = { kCTFontVariationAttribute }; + const void *attr_vals[1] = { variations_dict }; + CFDictionaryRef attributes; + CTFontDescriptorRef var_descriptor; + CTFontRef varied; + + attributes = CFDictionaryCreate (kCFAllocatorDefault, attr_keys, attr_vals, 1, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + var_descriptor = CTFontDescriptorCreateWithAttributes (attributes); + varied = CTFontCreateCopyWithAttributes (font_ref, 0.0, NULL, var_descriptor); + + CFRelease (font_ref); + font_ref = varied; + + CFRelease (var_descriptor); + CFRelease (attributes); + CFRelease (variations_dict); + } + cafont = g_object_new (PANGO_TYPE_CAIRO_CORE_TEXT_FONT, NULL); cfont = PANGO_CORE_TEXT_FONT (cafont); @@ -212,7 +323,6 @@ else options = cairo_font_options_create (); - variations = pango_core_text_font_key_get_variations (key); if (variations) cairo_font_options_set_variations (options, variations); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pango-1.58.0/pango/pangocoretext-fontmap.c new/pango-1.58.2/pango/pangocoretext-fontmap.c --- old/pango-1.58.0/pango/pangocoretext-fontmap.c 2026-06-26 18:39:37.000000000 +0200 +++ new/pango-1.58.2/pango/pangocoretext-fontmap.c 2026-08-05 19:54:07.000000000 +0200 @@ -28,7 +28,8 @@ #include "pangocoretext-private.h" #include "pango-impl-utils.h" -#include <Carbon/Carbon.h> +#include <strings.h> +#include <CoreText/CoreText.h> typedef struct _FontHashKey FontHashKey; @@ -56,6 +57,7 @@ PangoFontFace **faces; gint n_faces; + int is_variable; }; struct _PangoCoreTextFamilyClass @@ -767,6 +769,47 @@ return ctfamily->is_monospace; } +static gboolean +pango_core_text_family_is_variable (PangoFontFamily *family) +{ + PangoCoreTextFamily *ctfamily = PANGO_CORE_TEXT_FAMILY (family); + + if (ctfamily->is_variable == -1) + { + pango_font_family_list_faces (family, NULL, NULL); + + ctfamily->is_variable = 0; + for (int i = 0; i < ctfamily->n_faces && !ctfamily->is_variable; i++) + { + PangoCoreTextFace *face = (PangoCoreTextFace *) ctfamily->faces[i]; + CFArrayRef axes; + + if (face->synthetic_italic || face->synthetic_small_caps) + continue; + + /* kCTFontVariationAxesAttribute is only accurate since macOS 13. */ +#if defined(__MAC_13_0) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_13_0 + axes = CTFontDescriptorCopyAttribute (face->ctfontdescriptor, kCTFontVariationAxesAttribute); +#else + { + CTFontRef ctfont = CTFontCreateWithFontDescriptor (face->ctfontdescriptor, 0.0, NULL); + axes = CTFontCopyVariationAxes (ctfont); + CFRelease (ctfont); + } +#endif + + if (axes) + { + if (CFArrayGetCount (axes) > 0) + ctfamily->is_variable = 1; + CFRelease (axes); + } + } + } + + return ctfamily->is_variable; +} + G_DEFINE_TYPE (PangoCoreTextFamily, pango_core_text_family, PANGO_TYPE_FONT_FAMILY); static void @@ -800,12 +843,14 @@ pfclass->list_faces = pango_core_text_family_list_faces; pfclass->get_name = pango_core_text_family_get_name; pfclass->is_monospace = pango_core_text_family_is_monospace; + pfclass->is_variable = pango_core_text_family_is_variable; } static void pango_core_text_family_init (PangoCoreTextFamily *family) { family->n_faces = -1; + family->is_variable = -1; } @@ -1054,6 +1099,7 @@ gboolean synthetic_small_caps; gpointer context_key; char *variations; + char *features; }; static void @@ -1074,6 +1120,7 @@ key->gravity = pango_core_text_fontset_key_get_gravity (fontset_key); key->context_key = pango_core_text_fontset_key_get_context_key (fontset_key); key->variations = (char *) pango_font_description_get_variations (fontset_key->desc); + key->features = (char *) pango_font_description_get_features (fontset_key->desc); } static void @@ -1090,6 +1137,7 @@ key->gravity = orig->gravity; key->context_key = orig->context_key; key->variations = orig->variations; + key->features = orig->features; } static PangoCoreTextFontKey * @@ -1111,6 +1159,7 @@ else key->context_key = NULL; key->variations = g_strdup (old->variations); + key->features = g_strdup (old->features); return key; } @@ -1125,6 +1174,7 @@ PANGO_CORE_TEXT_FONT_MAP_GET_CLASS (key->fontmap)->context_key_free (key->fontmap, key->context_key); g_free (key->variations); + g_free (key->features); g_slice_free (PangoCoreTextFontKey, key); } @@ -1144,6 +1194,9 @@ if (key->variations) hash ^= g_str_hash (key->variations); + if (key->features) + hash ^= g_str_hash (key->features); + return (hash ^ CFHash (key->ctfontdescriptor)); } @@ -1158,7 +1211,8 @@ key_a->resolution == key_b->resolution && key_a->synthetic_italic == key_b->synthetic_italic && key_a->synthetic_small_caps == key_b->synthetic_small_caps && - g_strcmp0 (key_a->variations, key_b->variations) == 0) + g_strcmp0 (key_a->variations, key_b->variations) == 0 && + g_strcmp0 (key_a->features, key_b->features) == 0) { if (key_a->context_key && key_b->context_key) return PANGO_CORE_TEXT_FONT_MAP_GET_CLASS (key_a->fontmap)->context_key_equal (key_a->fontmap, @@ -1225,6 +1279,12 @@ return key->variations; } +const char * +pango_core_text_font_key_get_features (const PangoCoreTextFontKey *key) +{ + return key->features; +} + static void pango_core_text_font_map_add (PangoCoreTextFontMap *ctfontmap, @@ -1649,7 +1709,7 @@ } if (variations) - g_warning_once ("pango_core_text_font_map_reload_font: variations are ignored"); + key.variations = (char *) variations; scaled = (PangoFont *)pango_core_text_font_map_new_font_from_key (ctfontmap, &key); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pango-1.58.0/pango/pangocoretext-private.h new/pango-1.58.2/pango/pangocoretext-private.h --- old/pango-1.58.0/pango/pangocoretext-private.h 2026-06-26 18:39:37.000000000 +0200 +++ new/pango-1.58.2/pango/pangocoretext-private.h 2026-08-05 19:54:07.000000000 +0200 @@ -153,6 +153,8 @@ CTFontDescriptorRef pango_core_text_font_key_get_ctfontdescriptor (const PangoCoreTextFontKey *key); _PANGO_EXTERN const char * pango_core_text_font_key_get_variations (const PangoCoreTextFontKey *key); +_PANGO_EXTERN +const char * pango_core_text_font_key_get_features (const PangoCoreTextFontKey *key); PangoCoreTextFace * pango_core_text_font_map_find_face (PangoCoreTextFontMap *map, const PangoCoreTextFontKey *key); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pango-1.58.0/pango/pangocoretext.c new/pango-1.58.2/pango/pangocoretext.c --- old/pango-1.58.0/pango/pangocoretext.c 2026-06-26 18:39:37.000000000 +0200 +++ new/pango-1.58.2/pango/pangocoretext.c 2026-08-05 19:54:07.000000000 +0200 @@ -26,7 +26,6 @@ #include "pangocoretext-private.h" #include "pango-impl-utils.h" #include <hb-coretext.h> -#include <hb-ot.h> struct _PangoCoreTextFontPrivate { @@ -38,6 +37,8 @@ PangoCoverage *coverage; PangoFontMap *fontmap; + + char *features; }; G_DEFINE_TYPE_WITH_PRIVATE (PangoCoreTextFont, pango_core_text_font, PANGO_TYPE_FONT) @@ -54,9 +55,30 @@ if (priv->coverage) g_object_unref (priv->coverage); + g_free (priv->features); + G_OBJECT_CLASS (pango_core_text_font_parent_class)->finalize (object); } +static const char * +pango_core_text_font_get_features_string (PangoCoreTextFont *ctfont) +{ + PangoCoreTextFontPrivate *priv = ctfont->priv; + + if (!priv->features) + { + PangoVariant variant = PANGO_VARIANT_NORMAL; + + if (pango_core_text_font_key_get_synthetic_small_caps (priv->key)) + variant = PANGO_VARIANT_SMALL_CAPS; + + priv->features = pango_combine_features (variant, + pango_core_text_font_key_get_features (priv->key)); + } + + return priv->features; +} + static PangoFontDescription * pango_core_text_font_describe (PangoFont *font) { @@ -65,6 +87,7 @@ CTFontDescriptorRef ctfontdesc; PangoFontDescription *desc; const char *variations; + const char *features; ctfontdesc = CTFontCopyFontDescriptor (priv->font_ref); desc = _pango_core_text_font_description_from_ct_font_descriptor (ctfontdesc); @@ -74,8 +97,12 @@ if (variations) pango_font_description_set_variations (desc, variations); - if (pango_core_text_font_key_get_synthetic_small_caps (priv->key)) - pango_font_description_set_variant (desc, PANGO_VARIANT_SMALL_CAPS); + features = pango_core_text_font_get_features_string (ctfont); + if (*features) + { + pango_font_description_set_variant (desc, pango_features_get_variant (features)); + pango_font_description_set_features (desc, features); + } return desc; } @@ -189,46 +216,41 @@ hb_font_t *hb_font; double x_scale, y_scale; int size; - const char *variations; matrix = pango_core_text_font_key_get_matrix (ctfont->priv->key); pango_matrix_get_font_scale_factors (matrix, &x_scale, &y_scale); size = pango_core_text_font_key_get_size (ctfont->priv->key); - variations = pango_core_text_font_key_get_variations (ctfont->priv->key); hb_font = hb_coretext_font_create (ctfont->priv->font_ref); hb_font_set_scale (hb_font, size / x_scale, size / y_scale); - if (variations) - { - hb_face_t *face; - unsigned int n_axes; + return hb_font; + } - face = hb_font_get_face (hb_font); - n_axes = hb_ot_var_get_axis_infos (face, 0, NULL, NULL); - if (n_axes > 0) - { - hb_ot_var_axis_info_t *axes; - float *coords; - - axes = g_newa (hb_ot_var_axis_info_t, n_axes); - coords = g_newa (float, n_axes); - - hb_ot_var_get_axis_infos (face, 0, &n_axes, axes); - for (unsigned int i = 0; i < n_axes; i++) - coords[axes[i].axis_index] = axes[i].default_value; + return hb_font_get_empty (); +} - pango_parse_variations (variations, axes, n_axes, coords); +static void +pango_core_text_font_get_features (PangoFont *font, + hb_feature_t *features, + guint len, + guint *num_features) +{ + PangoCoreTextFont *ctfont = (PangoCoreTextFont *)font; + const char *str = pango_core_text_font_get_features_string (ctfont); - hb_font_set_var_coords_design (hb_font, coords, n_axes); - } - } + if (*str) + { + char **feats = g_strsplit (str, ",", -1); + for (int i = 0; feats[i] && *num_features < len; i++) + { + if (hb_feature_from_string (feats[i], -1, &features[*num_features])) + (*num_features)++; + } - return hb_font; + g_strfreev (feats); } - - return hb_font_get_empty (); } static void @@ -250,6 +272,7 @@ font_class->get_coverage = pango_core_text_font_get_coverage; font_class->get_font_map = pango_core_text_font_get_font_map; font_class->create_hb_font = pango_core_text_font_create_hb_font; + font_class->get_features = pango_core_text_font_get_features; } void @@ -303,6 +326,8 @@ g_object_unref (priv->coverage); priv->coverage = NULL; } + + g_clear_pointer (&priv->features, g_free); } PangoCoreTextFontKey * diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pango-1.58.0/pango/pangocoretext.h new/pango-1.58.2/pango/pangocoretext.h --- old/pango-1.58.0/pango/pangocoretext.h 2026-06-26 18:39:37.000000000 +0200 +++ new/pango-1.58.2/pango/pangocoretext.h 2026-08-05 19:54:07.000000000 +0200 @@ -24,7 +24,7 @@ #define __PANGOCORETEXT_H__ #include <pango/pango.h> -#include <Carbon/Carbon.h> +#include <CoreText/CoreText.h> G_BEGIN_DECLS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pango-1.58.0/pango/pangofc-fontmap.c new/pango-1.58.2/pango/pangofc-fontmap.c --- old/pango-1.58.0/pango/pangofc-fontmap.c 2026-06-26 18:39:37.000000000 +0200 +++ new/pango-1.58.2/pango/pangofc-fontmap.c 2026-08-05 19:54:07.000000000 +0200 @@ -839,7 +839,8 @@ copy = malloc (sizeof (FcFontSet)); copy->sfont = copy->nfont = fontset->nfont; copy->fonts = malloc (sizeof (FcPattern *) * copy->nfont); - memcpy (copy->fonts, fontset->fonts, sizeof (FcPattern *) * copy->nfont); + if (copy->nfont > 0) + memcpy (copy->fonts, fontset->fonts, sizeof (FcPattern *) * copy->nfont); for (i = 0; i < copy->nfont; i++) FcPatternReference (copy->fonts[i]); @@ -2067,24 +2068,6 @@ return (double) pango_width / 10.0; } -static void -maybe_add_feature (FcPattern *pattern, - const char *features, - const char *feature) -{ - if (features) - { - char buf[8] = { 0, }; - - memcpy (buf, feature, 4); - - if (strstr (features, buf)) - return; - } - - FcPatternAddString (pattern, FC_FONT_FEATURES, (FcChar8*) feature); -} - static FcPattern * pango_fc_make_pattern (const PangoFontDescription *description, PangoLanguage *language, @@ -2103,6 +2086,7 @@ char **families; int i; double width; + char *combined_features; prgname = g_get_prgname (); slant = pango_fc_convert_slant_to_fc (pango_font_description_get_style (description)); @@ -2166,37 +2150,10 @@ if (prgname) FcPatternAddString (pattern, FC_PRGNAME, (FcChar8*) prgname); - switch (variant) + combined_features = pango_combine_features (variant, features); + if (*combined_features) { - case PANGO_VARIANT_SMALL_CAPS: - maybe_add_feature (pattern, features, "smcp=1"); - break; - case PANGO_VARIANT_ALL_SMALL_CAPS: - maybe_add_feature (pattern, features, "smcp=1"); - maybe_add_feature (pattern, features, "c2sc=1"); - break; - case PANGO_VARIANT_PETITE_CAPS: - maybe_add_feature (pattern, features, "pcap=1"); - break; - case PANGO_VARIANT_ALL_PETITE_CAPS: - maybe_add_feature (pattern, features, "pcap=1"); - maybe_add_feature (pattern, features, "c2pc=1"); - break; - case PANGO_VARIANT_UNICASE: - maybe_add_feature (pattern, features, "unic=1"); - break; - case PANGO_VARIANT_TITLE_CAPS: - maybe_add_feature (pattern, features, "titl=1"); - break; - case PANGO_VARIANT_NORMAL: - break; - default: - g_assert_not_reached (); - } - - if (features) - { - char **feat = g_strsplit (features, ",", -1); + char **feat = g_strsplit (combined_features, ",", -1); for (int i = 0; feat[i]; i++) FcPatternAddString (pattern, FC_FONT_FEATURES, (FcChar8*) feat[i]); @@ -2204,6 +2161,8 @@ g_strfreev (feat); } + g_free (combined_features); + return pattern; } @@ -3124,8 +3083,6 @@ PangoStretch stretch; double size; PangoGravity gravity; - PangoVariant variant; - gboolean all_caps; const char *s; int i; double d; @@ -3165,9 +3122,6 @@ str = NULL; - variant = PANGO_VARIANT_NORMAL; - all_caps = FALSE; - for (int i = 0; i < 32; i++) { if (FcPatternGetString (pattern, FC_FONT_FEATURES, i, (FcChar8 **)&s) == FcResultMatch) @@ -3177,55 +3131,19 @@ if (str->len > 0) g_string_append_c (str, ','); g_string_append (str, s); - - if (strcmp (s, "smcp=1") == 0) - { - if (all_caps) - variant = PANGO_VARIANT_ALL_SMALL_CAPS; - else - variant = PANGO_VARIANT_SMALL_CAPS; - } - else if (strcmp (s, "c2sc=1") == 0) - { - if (variant == PANGO_VARIANT_SMALL_CAPS) - variant = PANGO_VARIANT_ALL_SMALL_CAPS; - else - all_caps = TRUE; - } - else if (strcmp (s, "pcap=1") == 0) - { - if (all_caps) - variant = PANGO_VARIANT_ALL_PETITE_CAPS; - else - variant = PANGO_VARIANT_PETITE_CAPS; - } - else if (strcmp (s, "c2pc=1") == 0) - { - if (variant == PANGO_VARIANT_PETITE_CAPS) - variant = PANGO_VARIANT_ALL_PETITE_CAPS; - else - all_caps = TRUE; - } - else if (strcmp (s, "unic=1") == 0) - { - variant = PANGO_VARIANT_UNICASE; - } - else if (strcmp (s, "titl=1") == 0) - { - variant = PANGO_VARIANT_TITLE_CAPS; - } } else break; } - pango_font_description_set_variant (desc, variant); - if (str) { + pango_font_description_set_variant (desc, pango_features_get_variant (str->str)); pango_font_description_set_features (desc, str->str); g_string_free (str, TRUE); } + else + pango_font_description_set_variant (desc, PANGO_VARIANT_NORMAL); if (include_size && FcPatternGetDouble (pattern, FC_SIZE, 0, &size) == FcResultMatch) { @@ -3705,7 +3623,8 @@ faces = g_renew (PangoFcFace *, faces, num); - qsort (faces, num, sizeof (PangoFcFace *), compare_face); + if (num > 0) + qsort (faces, num, sizeof (PangoFcFace *), compare_face); fcfamily->n_faces = num; fcfamily->faces = faces; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pango-1.58.0/tests/layouts/valid-20.layout new/pango-1.58.2/tests/layouts/valid-20.layout --- old/pango-1.58.0/tests/layouts/valid-20.layout 2026-06-26 18:39:37.000000000 +0200 +++ new/pango-1.58.2/tests/layouts/valid-20.layout 2026-08-05 19:54:07.000000000 +0200 @@ -139,7 +139,7 @@ { "glyph" : 244, "width" : 18432, - "x-offset" : 14764, + "x-offset" : 12631, "y-offset" : 3845, "is-cluster-start" : true, "log-cluster" : 0 @@ -147,7 +147,7 @@ { "glyph" : 272, "width" : 18432, - "x-offset" : 14764, + "x-offset" : 14486, "y-offset" : 4280, "is-cluster-start" : true, "log-cluster" : 1 @@ -155,7 +155,7 @@ { "glyph" : 273, "width" : 18432, - "x-offset" : 14764, + "x-offset" : 12631, "y-offset" : 3507, "is-cluster-start" : true, "log-cluster" : 2 ++++++ pango.obsinfo ++++++ --- /var/tmp/diff_new_pack.qfZi9o/_old 2026-08-19 17:56:34.454231087 +0200 +++ /var/tmp/diff_new_pack.qfZi9o/_new 2026-08-19 17:56:34.458231232 +0200 @@ -1,5 +1,5 @@ name: pango -version: 1.58.0 -mtime: 1782491977 -commit: f25cbfe376ce2550d89fb7b4eb989b6a6218efc6 +version: 1.58.2 +mtime: 1785952447 +commit: d360f14004e4a4824f2352f6e2722016f9a51dd6
