[pango/pango2-color-palette] wip: support color palettes in fonts




commit de2cf0afae7f5e488f54515b789665091a738c45
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Jun 24 19:24:19 2022 -0400

    wip: support color palettes in fonts
    
    Add a pango_context_set_palette to select whether
    we prefer the default palette, the palette for light
    background, or the palette for dark background. Wire
    this through PangoFontSetCached and PangoFont, and
    apply in when we create a scaled font for cairo.
    
    To try this, use the new --palette option of
    pango-view.
    
    The only font I've found with such color palettes
    is Amiri Quran Colored.

 pango/pango-context-private.h        |  2 +
 pango/pango-context.c                | 17 ++++++++
 pango/pango-context.h                |  7 ++++
 pango/pango-font-private.h           |  9 +++++
 pango/pango-fontmap.c                |  4 ++
 pango/pango-fontset-cached-private.h |  2 +
 pango/pango-fontset-cached.c         | 77 +++++++++++++++---------------------
 pango/pango-types.h                  |  6 +++
 pango/pangocairo-font.c              | 51 +++++++++++++++++++++++-
 utils/viewer-pangocairo.c            | 22 +++++++++++
 10 files changed, 150 insertions(+), 47 deletions(-)
---
diff --git a/pango/pango-context-private.h b/pango/pango-context-private.h
index d9d07712b..1af412be5 100644
--- a/pango/pango-context-private.h
+++ b/pango/pango-context-private.h
@@ -48,6 +48,8 @@ struct _PangoContext
 
   gboolean round_glyph_positions;
 
+  PangoColorPalette palette;
+
 #ifdef HAVE_CAIRO
   gboolean set_options_explicit;
 
diff --git a/pango/pango-context.c b/pango/pango-context.c
index 915dd032c..f62d15389 100644
--- a/pango/pango-context.c
+++ b/pango/pango-context.c
@@ -1066,3 +1066,20 @@ pango_context_get_round_glyph_positions (PangoContext *context)
 {
   return context->round_glyph_positions;
 }
+
+void
+pango_context_set_color_palette (PangoContext      *context,
+                                 PangoColorPalette  palette)
+{
+  g_return_if_fail (PANGO_IS_CONTEXT (context));
+
+  context->palette = palette;
+}
+
+PangoColorPalette
+pango_context_get_color_palette (PangoContext *context)
+{
+  g_return_val_if_fail (PANGO_IS_CONTEXT (context), PANGO_COLOR_PALETTE_DEFAULT);
+
+  return context->palette;
+}
diff --git a/pango/pango-context.h b/pango/pango-context.h
index 99400fefc..5f63088c1 100644
--- a/pango/pango-context.h
+++ b/pango/pango-context.h
@@ -99,4 +99,11 @@ void                    pango_context_set_round_glyph_positions (PangoContext
 PANGO_AVAILABLE_IN_ALL
 gboolean                pango_context_get_round_glyph_positions (PangoContext                 *context);
 
+PANGO_AVAILABLE_IN_ALL
+void                    pango_context_set_color_palette         (PangoContext                 *context,
+                                                                 PangoColorPalette             palette);
+PANGO_AVAILABLE_IN_ALL
+PangoColorPalette       pango_context_get_color_palette         (PangoContext                 *context);
+
+
 G_END_DECLS
diff --git a/pango/pango-font-private.h b/pango/pango-font-private.h
index db4720dcf..cd98cb7e3 100644
--- a/pango/pango-font-private.h
+++ b/pango/pango-font-private.h
@@ -22,6 +22,7 @@
 #include <pango/pango-font-family.h>
 #include <pango/pango-font.h>
 #include <pango/pango-types.h>
+#include <pango/pango-context.h>
 
 #include <glib-object.h>
 
@@ -42,6 +43,7 @@ struct _PangoFont
   PangoGravity gravity;
   PangoMatrix ctm;
 
+  PangoColorPalette palette;
 #ifdef HAVE_CAIRO
   cairo_font_options_t *options;
 #endif
@@ -107,6 +109,13 @@ pango_font_set_ctm (PangoFont         *font,
   font->ctm = ctm ? *ctm : matrix_init;
 }
 
+static inline void
+pango_font_set_color_palette (PangoFont         *font,
+                              PangoColorPalette  palette)
+{
+  font->palette = palette;
+}
+
 gboolean pango_font_is_hinted         (PangoFont *font);
 void     pango_font_get_scale_factors (PangoFont *font,
                                        double    *x_scale,
diff --git a/pango/pango-fontmap.c b/pango/pango-fontmap.c
index cefc3b203..5355f19f8 100644
--- a/pango/pango-fontmap.c
+++ b/pango/pango-fontmap.c
@@ -167,6 +167,7 @@ pango_fontset_cached_hash (const PangoFontsetCached *fontset)
 
   return (hash ^
           GPOINTER_TO_UINT (fontset->language) ^
+          fontset->palette ^
 #ifdef HAVE_CAIRO
           cairo_font_options_hash (fontset->font_options) ^
 #endif
@@ -178,6 +179,7 @@ pango_fontset_cached_equal (const PangoFontsetCached *a,
                             const PangoFontsetCached *b)
 {
   return a->language == b->language &&
+         a->palette == b->palette &&
 #ifdef HAVE_CAIRO
          cairo_font_options_equal (a->font_options, b->font_options) &&
 #endif
@@ -528,6 +530,7 @@ pango_font_map_default_load_fontset (PangoFontMap               *self,
   lookup.language = language;
   lookup.description = (PangoFontDescription *)description;
   lookup.ctm = ctm;
+  lookup.palette = pango_context_get_color_palette (context);
 #ifdef HAVE_CAIRO
   lookup.font_options = (cairo_font_options_t *)pango_cairo_context_get_merged_font_options (context);
 #endif
@@ -537,6 +540,7 @@ pango_font_map_default_load_fontset (PangoFontMap               *self,
     goto done;
 
   fontset = pango_fontset_cached_new (description, language, self->dpi, ctm);
+  fontset->palette = pango_context_get_color_palette (context);
 #ifdef HAVE_CAIRO
   fontset->font_options = cairo_font_options_copy (pango_cairo_context_get_merged_font_options (context));
 #endif
diff --git a/pango/pango-fontset-cached-private.h b/pango/pango-fontset-cached-private.h
index 2f3c7ac3f..00fad4808 100644
--- a/pango/pango-fontset-cached-private.h
+++ b/pango/pango-fontset-cached-private.h
@@ -44,6 +44,8 @@ struct _PangoFontsetCached
   GList cache_link;
   GHashTable *cache;
 
+  PangoColorPalette palette;
+
 #ifdef HAVE_CAIRO
   cairo_font_options_t *font_options;
 #endif
diff --git a/pango/pango-fontset-cached.c b/pango/pango-fontset-cached.c
index 2692ac24b..09a48c587 100644
--- a/pango/pango-fontset-cached.c
+++ b/pango/pango-fontset-cached.c
@@ -27,6 +27,7 @@
 #include "pango-font-private.h"
 #include "pango-font-face-private.h"
 #include "pango-generic-family-private.h"
+#include "pango-context.h"
 
 #ifdef HAVE_CAIRO
 #include "pangocairo-font.h"
@@ -40,6 +41,7 @@ pango_fontset_cached_init (PangoFontsetCached *fontset)
   fontset->items = g_ptr_array_new_with_free_func (g_object_unref);
   fontset->cache = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref);
   fontset->language = NULL;
+  fontset->palette = PANGO_COLOR_PALETTE_DEFAULT;
 #ifdef HAVE_CAIRO
   fontset->font_options = NULL;
 #endif
@@ -81,6 +83,31 @@ find_font_for_face (PangoFontsetCached *self,
   return NULL;
 }
 
+static PangoFont *
+create_font_for_face (PangoFontsetCached *self,
+                      PangoFontFace      *face)
+{
+  PangoFont *font;
+
+  font = pango_font_face_create_font (face,
+                                      self->description,
+                                      self->dpi,
+                                      self->ctm);
+  pango_font_set_color_palette (font, self->palette);
+#ifdef HAVE_CAIRO
+  pango_cairo_font_set_font_options (font, self->font_options);
+#endif
+
+  return font;
+}
+
+void
+pango_fontset_cached_add_face (PangoFontsetCached *self,
+                               PangoFontFace      *face)
+{
+  g_ptr_array_add (self->items, create_font_for_face (self, face));
+}
+
 static PangoFont *
 pango_fontset_cached_get_font (PangoFontset *fontset,
                                guint         wc)
@@ -129,19 +156,9 @@ pango_fontset_cached_get_font (PangoFontset *fontset,
 
               font = find_font_for_face (self, face);
               if (font)
-                {
-                  retval = g_object_ref (font);
-                }
+                retval = g_object_ref (font);
               else
-                {
-                  retval = pango_font_face_create_font (face,
-                                                        self->description,
-                                                        self->dpi,
-                                                        self->ctm);
-#ifdef HAVE_CAIRO
-                  pango_cairo_font_set_font_options (retval, self->font_options);
-#endif
-                }
+                retval = create_font_for_face (self, face);
               break;
             }
         }
@@ -175,15 +192,7 @@ pango_fontset_cached_get_first_font (PangoFontsetCached *self)
       if (font)
         g_object_ref (font);
       else
-        {
-          font = pango_font_face_create_font (face,
-                                              self->description,
-                                              self->dpi,
-                                              self->ctm);
-#ifdef HAVE_CAIRO
-          pango_cairo_font_set_font_options (font, self->font_options);
-#endif
-        }
+        font = create_font_for_face (self, face);
 
       return font;
     }
@@ -249,15 +258,7 @@ pango_fontset_cached_foreach (PangoFontset            *fontset,
           if (font)
             g_object_ref (font);
           else
-            {
-              font = pango_font_face_create_font (face,
-                                                  self->description,
-                                                  self->dpi,
-                                                  self->ctm);
-#ifdef HAVE_CAIRO
-              pango_cairo_font_set_font_options (font, self->font_options);
-#endif
-            }
+            font = create_font_for_face (self, face);
         }
 
       if ((*func) (fontset, font, data))
@@ -300,22 +301,6 @@ pango_fontset_cached_new (const PangoFontDescription *description,
   return self;
 }
 
-void
-pango_fontset_cached_add_face (PangoFontsetCached *self,
-                               PangoFontFace      *face)
-{
-  PangoFont *font;
-
-  font = pango_font_face_create_font (face,
-                                      self->description,
-                                      self->dpi,
-                                      self->ctm);
-#ifdef HAVE_CAIRO
-  pango_cairo_font_set_font_options (font, self->font_options);
-#endif
-  g_ptr_array_add (self->items, font);
-}
-
 void
 pango_fontset_cached_add_family (PangoFontsetCached *self,
                                  PangoGenericFamily *family)
diff --git a/pango/pango-types.h b/pango/pango-types.h
index f39f35b29..250409a3f 100644
--- a/pango/pango-types.h
+++ b/pango/pango-types.h
@@ -319,6 +319,12 @@ typedef enum
  */
 #define PANGO_LEADING_TRIM_BOTH (PANGO_LEADING_TRIM_START|PANGO_LEADING_TRIM_END)
 
+typedef enum {
+  PANGO_COLOR_PALETTE_DEFAULT,
+  PANGO_COLOR_PALETTE_FOR_LIGHT_BACKGROUND,
+  PANGO_COLOR_PALETTE_FOR_DARK_BACKGROUND
+} PangoColorPalette;
+
 /*
  * PANGO_DECLARE_INTERNAL_TYPE:
  * @ModuleObjName: The name of the new type, in camel case (like GtkWidget)
diff --git a/pango/pangocairo-font.c b/pango/pangocairo-font.c
index d23d006a8..b87194388 100644
--- a/pango/pangocairo-font.c
+++ b/pango/pangocairo-font.c
@@ -268,10 +268,51 @@ create_cairo_font_face_for_hb_font (PangoFont *font)
 
 #endif
 
+static int
+find_palette_for_font (PangoFont *font)
+{
+  hb_font_t *hbfont = pango_font_get_hb_font (font);
+  hb_face_t *hbface = hb_font_get_face (hbfont);
+
+  if (hb_ot_color_has_palettes (hbface))
+    {
+      for (int i = 0; i < hb_ot_color_palette_get_count (hbface); i++)
+        {
+          hb_ot_color_palette_flags_t flags;
+
+          flags = hb_ot_color_palette_get_flags (hbface, i);
+
+          switch (font->palette)
+            {
+            case PANGO_COLOR_PALETTE_DEFAULT:
+              if (flags & HB_OT_COLOR_PALETTE_FLAG_DEFAULT)
+                return i;
+              break;
+
+            case PANGO_COLOR_PALETTE_FOR_LIGHT_BACKGROUND:
+              if (flags & HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND)
+                return i;
+              break;
+
+            case PANGO_COLOR_PALETTE_FOR_DARK_BACKGROUND:
+              if (flags & HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND)
+                return i;
+              break;
+
+            default:
+              break;
+            }
+        }
+    }
+
+  return CAIRO_COLOR_PALETTE_DEFAULT;
+}
+
 static cairo_scaled_font_t *
 _pango_cairo_font_private_get_scaled_font (PangoCairoFontPrivate *cf_priv)
 {
   cairo_font_face_t *font_face;
+  cairo_font_options_t *options;
 
   if (G_LIKELY (cf_priv->scaled_font))
     return cf_priv->scaled_font;
@@ -292,10 +333,18 @@ _pango_cairo_font_private_get_scaled_font (PangoCairoFontPrivate *cf_priv)
   if (G_UNLIKELY (font_face == NULL))
     goto done;
 
+  options = cairo_font_options_copy (cf_priv->data->options);
+
+  if (cairo_font_options_get_color_palette (options) == CAIRO_COLOR_PALETTE_DEFAULT)
+    cairo_font_options_set_color_palette (options,
+                                          find_palette_for_font (cf_priv->cfont));
+
   cf_priv->scaled_font = cairo_scaled_font_create (font_face,
                                                    &cf_priv->data->font_matrix,
                                                    &cf_priv->data->ctm,
-                                                   cf_priv->data->options);
+                                                   options);
+
+  cairo_font_options_destroy (options);
 
   cairo_font_face_destroy (font_face);
 
diff --git a/utils/viewer-pangocairo.c b/utils/viewer-pangocairo.c
index 2bf2e0d69..a7aee380f 100644
--- a/utils/viewer-pangocairo.c
+++ b/utils/viewer-pangocairo.c
@@ -34,6 +34,24 @@
 static int opt_annotate = 0;
 static gboolean opt_userfont = 0;
 static char **opt_font_file = NULL;
+static char *opt_palette = NULL;
+
+static PangoColorPalette
+parse_palette (const char *palette)
+{
+  if (palette == NULL ||
+      strcmp (palette, "default") == 0)
+    return PANGO_COLOR_PALETTE_DEFAULT;
+  else if (strcmp (palette, "for-dark-bg") == 0)
+    return PANGO_COLOR_PALETTE_FOR_DARK_BACKGROUND;
+  else if (strcmp (palette, "for-light-bg") == 0)
+    return PANGO_COLOR_PALETTE_FOR_LIGHT_BACKGROUND;
+  else
+    {
+      g_warning ("Unsupported palette value: %s", palette);
+      return PANGO_COLOR_PALETTE_DEFAULT;
+    }
+}
 
 typedef struct
 {
@@ -44,6 +62,7 @@ typedef struct
   PangoFontMap *fontmap;
   cairo_font_options_t *font_options;
   gboolean subpixel_positions;
+  PangoColorPalette palette;
 } CairoViewer;
 
 static gpointer
@@ -119,6 +138,7 @@ pangocairo_view_create (const PangoViewer *klass G_GNUC_UNUSED)
     cairo_font_options_set_antialias (instance->font_options, (cairo_antialias_t)opt_antialias);
 
   instance->subpixel_positions = opt_subpixel_positions;
+  instance->palette = parse_palette (opt_palette);
 
   return instance;
 }
@@ -146,6 +166,7 @@ pangocairo_view_get_context (gpointer instance)
   context = pango_context_new_with_font_map (c->fontmap);
   pango_cairo_context_set_font_options (context, c->font_options);
   pango_context_set_round_glyph_positions (context, !c->subpixel_positions);
+  pango_context_set_color_palette (context, c->palette);
 
   return context;
 }
@@ -973,6 +994,7 @@ pangocairo_view_get_option_group (const PangoViewer *klass G_GNUC_UNUSED)
     {"annotate", 0, 0, G_OPTION_ARG_CALLBACK, parse_annotate_arg, annotate_arg_help, "FLAGS"},
     { "font-file", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_font_file, "Create a fontmap with this font", 
"FILE" },
     { "userfont", 0, 0, G_OPTION_ARG_NONE, &opt_userfont, "Add userfont" },
+    { "palette", 0, 0, G_OPTION_ARG_STRING, &opt_palette, "Preferred palette", "PALETTE" },
     {NULL}
   };
   GOptionGroup *group;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]