[pango/font-palette-api] wip: Add an api to select palettes for color glyphs




commit d4cf0b1c8dcdef31644879d6fbae11002828b927
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Feb 13 13:19:45 2022 -0600

    wip: Add an api to select palettes for color glyphs
    
    This commit adds a light-background attribute that can
    be used to influence which palette will be used to render
    COLRv0 layered glyphs with color fonts that have multiple
    palettes. This needs a way for cairo to invalidate its
    glyph cache when the selected palette changes, which
    needs new freetype api.

 pango/pango-attributes.c      | 14 ++++++++++++++
 pango/pango-attributes.h      |  3 +++
 pango/pango-markup.c          | 12 ++++++++++++
 pango/pangocairo-fc-private.h |  6 ++++++
 pango/pangocairo-fcfont.c     | 43 +++++++++++++++++++++++++++++++++++++++++++
 pango/pangocairo-font.c       | 18 +++++++++++++++++-
 pango/pangocairo-private.h    |  5 ++++-
 pango/pangocairo-render.c     | 36 +++++++++++++++++++++++++++++++++---
 8 files changed, 132 insertions(+), 5 deletions(-)
---
diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c
index 60d14706..59966575 100644
--- a/pango/pango-attributes.c
+++ b/pango/pango-attributes.c
@@ -1556,6 +1556,20 @@ pango_attr_text_transform_new (PangoTextTransform transform)
 
   return pango_attr_int_new (&klass, transform);
 }
+
+PangoAttribute *
+pango_attr_light_background_new (gboolean light_background)
+{
+  static const PangoAttrClass klass = {
+    PANGO_ATTR_LIGHT_BACKGROUND,
+    pango_attr_int_copy,
+    pango_attr_int_destroy,
+    pango_attr_int_equal
+  };
+
+  return pango_attr_int_new (&klass, light_background);
+}
+
 /* }}} */
 /* {{{ Binding helpers */
 
diff --git a/pango/pango-attributes.h b/pango/pango-attributes.h
index 69ff9e52..964e594a 100644
--- a/pango/pango-attributes.h
+++ b/pango/pango-attributes.h
@@ -129,6 +129,7 @@ typedef enum
   PANGO_ATTR_SENTENCE,          /* PangoAttrInt */
   PANGO_ATTR_BASELINE_SHIFT,    /* PangoAttrSize */
   PANGO_ATTR_FONT_SCALE,        /* PangoAttrInt */
+  PANGO_ATTR_LIGHT_BACKGROUND,  /* PangoAttrInt */
 } PangoAttrType;
 
 /**
@@ -609,6 +610,8 @@ PANGO_AVAILABLE_IN_1_50
 PangoAttribute *        pango_attr_line_height_new_absolute     (int                          height);
 PANGO_AVAILABLE_IN_1_50
 PangoAttribute *        pango_attr_text_transform_new           (PangoTextTransform transform);
+PANGO_AVAILABLE_IN_1_50
+PangoAttribute *        pango_attr_light_background_new         (gboolean light_background);
 
 PANGO_AVAILABLE_IN_1_50
 PangoAttrString       * pango_attribute_as_string               (PangoAttribute              *attr);
diff --git a/pango/pango-markup.c b/pango/pango-markup.c
index 9a3bde55..12b1533e 100644
--- a/pango/pango-markup.c
+++ b/pango/pango-markup.c
@@ -1233,6 +1233,7 @@ span_parse_func     (MarkupData            *md G_GNUC_UNUSED,
   const char *text_transform = NULL;
   const char *segment = NULL;
   const char *font_scale = NULL;
+  const char *light_background = NULL;
 
   g_markup_parse_context_get_position (context,
                                       &line_number, &char_number);
@@ -1318,6 +1319,7 @@ span_parse_func     (MarkupData            *md G_GNUC_UNUSED,
        CHECK_ATTRIBUTE (lang);
        CHECK_ATTRIBUTE (letter_spacing);
         CHECK_ATTRIBUTE (line_height);
+        CHECK_ATTRIBUTE (light_background);
        break;
       case 'o':
        CHECK_ATTRIBUTE (overline);
@@ -1784,6 +1786,16 @@ span_parse_func     (MarkupData            *md G_GNUC_UNUSED,
         }
     }
 
+  if (G_UNLIKELY (light_background))
+    {
+      gboolean b = FALSE;
+
+      if (!span_parse_boolean ("light_background", light_background, &b, line_number, error))
+        goto error;
+
+      add_attribute (tag, pango_attr_light_background_new (b));
+    }
+
   return TRUE;
 
  error:
diff --git a/pango/pangocairo-fc-private.h b/pango/pangocairo-fc-private.h
index 370ecbea..78404ce1 100644
--- a/pango/pangocairo-fc-private.h
+++ b/pango/pangocairo-fc-private.h
@@ -39,6 +39,12 @@ struct _PangoCairoFcFontMap
 PangoFcFont *_pango_cairo_fc_font_new (PangoCairoFcFontMap *cffontmap,
                                       PangoFcFontKey      *key);
 
+void pango_cairo_fc_font_install   (PangoFcFont *font,
+                                    cairo_t     *cr,
+                                    gboolean     has_light_background);
+void pango_cairo_fc_font_uninstall (PangoFcFont *font,
+                                    cairo_t     *cr);
+
 G_END_DECLS
 
 #endif /* __PANGOCAIRO_FC_PRIVATE_H__ */
diff --git a/pango/pangocairo-fcfont.c b/pango/pangocairo-fcfont.c
index 4453b5ab..1e5b8c3e 100644
--- a/pango/pangocairo-fcfont.c
+++ b/pango/pangocairo-fcfont.c
@@ -35,6 +35,7 @@
 
 #include <hb-ot.h>
 #include <freetype/ftmm.h>
+#include <freetype/ftcolor.h>
 
 #define PANGO_TYPE_CAIRO_FC_FONT           (pango_cairo_fc_font_get_type ())
 #define PANGO_CAIRO_FC_FONT(object)        (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_FC_FONT, 
PangoCairoFcFont))
@@ -275,3 +276,45 @@ _pango_cairo_fc_font_new (PangoCairoFcFontMap *cffontmap,
 
   return (PangoFcFont *) cffont;
 }
+
+void
+pango_cairo_fc_font_install (PangoFcFont *font,
+                             cairo_t     *cr,
+                             gboolean     has_light_background)
+{
+  FT_Face face = pango_fc_font_lock_face (font);
+  FT_Palette_Data palettes;
+  int index = 0;
+  FT_Color *palette;
+
+  FT_Palette_Data_Get (face, &palettes);
+  for (int i = 0; i < palettes.num_palettes; i++)
+    {
+      if (has_light_background)
+        {
+          if (palettes.palette_flags[i] & FT_PALETTE_FOR_LIGHT_BACKGROUND)
+            {
+              index = i;
+              break;
+            }
+        }
+      else
+        {
+          if (palettes.palette_flags[i] & FT_PALETTE_FOR_DARK_BACKGROUND)
+            {
+              index = i;
+              break;
+            }
+        }
+    }
+
+  FT_Palette_Select (face, index, &palette);
+}
+
+void
+pango_cairo_fc_font_uninstall (PangoFcFont *font,
+                               cairo_t     *cr)
+{
+  pango_fc_font_unlock_face (font);
+}
+
diff --git a/pango/pangocairo-font.c b/pango/pangocairo-font.c
index 598065c0..9d1fca2e 100644
--- a/pango/pangocairo-font.c
+++ b/pango/pangocairo-font.c
@@ -26,6 +26,7 @@
 
 #include "pangocairo.h"
 #include "pangocairo-private.h"
+#include "pangocairo-fc-private.h"
 #include "pango-font-private.h"
 #include "pango-impl-utils.h"
 
@@ -164,6 +165,7 @@ pango_cairo_font_get_scaled_font (PangoCairoFont *cfont)
 /**
  * _pango_cairo_font_install:
  * @font: a `PangoCairoFont`
+ * @renderer: a `PangoCairoRenderer`
  * @cr: a #cairo_t
  *
  * Makes @font the current font for rendering in the specified
@@ -173,18 +175,32 @@ pango_cairo_font_get_scaled_font (PangoCairoFont *cfont)
  */
 gboolean
 _pango_cairo_font_install (PangoFont *font,
-                          cairo_t   *cr)
+                          cairo_t   *cr,
+                           gboolean   has_light_background)
 {
   cairo_scaled_font_t *scaled_font = pango_cairo_font_get_scaled_font ((PangoCairoFont *)font);
 
   if (G_UNLIKELY (scaled_font == NULL || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS))
     return FALSE;
 
+  if (PANGO_IS_FC_FONT (font))
+    pango_cairo_fc_font_install (PANGO_FC_FONT (font), cr, has_light_background);
+
   cairo_set_scaled_font (cr, scaled_font);
 
   return TRUE;
 }
 
+gboolean
+_pango_cairo_font_uninstall (PangoFont *font,
+                             cairo_t   *cr)
+{
+  if (PANGO_IS_FC_FONT (font))
+    pango_cairo_fc_font_uninstall (PANGO_FC_FONT (font), cr);
+
+  return TRUE;
+}
+
 
 static int
 max_glyph_width (PangoLayout *layout)
diff --git a/pango/pangocairo-private.h b/pango/pangocairo-private.h
index 704ae497..7c86d950 100644
--- a/pango/pangocairo-private.h
+++ b/pango/pangocairo-private.h
@@ -102,7 +102,10 @@ struct _PangoCairoFontIface
 };
 
 gboolean _pango_cairo_font_install (PangoFont *font,
-                                   cairo_t   *cr);
+                                    cairo_t   *cr,
+                                    gboolean   has_light_background);
+gboolean _pango_cairo_font_uninstall (PangoFont *font,
+                                      cairo_t   *cr);
 PangoFontMetrics * _pango_cairo_font_get_metrics (PangoFont     *font,
                                                  PangoLanguage *language);
 PangoCairoFontHexBoxInfo *_pango_cairo_font_get_hex_box_info (PangoCairoFont *cfont);
diff --git a/pango/pangocairo-render.c b/pango/pangocairo-render.c
index 2c552ba1..964d8a53 100644
--- a/pango/pangocairo-render.c
+++ b/pango/pangocairo-render.c
@@ -43,6 +43,8 @@ struct _PangoCairoRenderer
   gboolean has_show_text_glyphs;
   double x_offset, y_offset;
 
+  gboolean has_light_background;
+
   /* house-keeping options */
   gboolean is_cached_renderer;
   gboolean cr_had_current_point;
@@ -250,10 +252,11 @@ _pango_cairo_renderer_draw_unknown_glyph (PangoCairoRenderer *crenderer,
   invalid_input = G_UNLIKELY (gi->glyph == PANGO_GLYPH_INVALID_INPUT || ch > 0x10FFFF);
 
   hbi = _pango_cairo_font_get_hex_box_info ((PangoCairoFont *)font);
-  if (!hbi || !_pango_cairo_font_install ((PangoFont *)(hbi->font), crenderer->cr))
+  if (!hbi || !_pango_cairo_font_install ((PangoFont *)(hbi->font), crenderer->cr, 
crenderer->has_light_background))
     {
       _pango_cairo_renderer_draw_box_glyph (crenderer, gi, cx, cy, invalid_input);
-      goto done;
+      cairo_restore (crenderer->cr);
+      return;
     }
 
   if (G_UNLIKELY (invalid_input))
@@ -392,6 +395,7 @@ _pango_cairo_renderer_draw_unknown_glyph (PangoCairoRenderer *crenderer,
     }
 
 done:
+  _pango_cairo_font_uninstall ((PangoFont *)(hbi->font), crenderer->cr);
   cairo_restore (crenderer->cr);
 }
 
@@ -426,7 +430,7 @@ pango_cairo_renderer_show_text_glyphs (PangoRenderer        *renderer,
   if (!crenderer->do_path)
     set_color (crenderer, PANGO_RENDER_PART_FOREGROUND);
 
-  if (!_pango_cairo_font_install (font, crenderer->cr))
+  if (!_pango_cairo_font_install (font, crenderer->cr, crenderer->has_light_background))
     {
       for (i = 0; i < glyphs->num_glyphs; i++)
        {
@@ -497,6 +501,8 @@ pango_cairo_renderer_show_text_glyphs (PangoRenderer        *renderer,
   if (cairo_glyphs != stack_glyphs)
     g_free (cairo_glyphs);
 
+  _pango_cairo_font_uninstall (font, crenderer->cr);
+
 done:
   cairo_restore (crenderer->cr);
 }
@@ -813,11 +819,35 @@ pango_cairo_renderer_init (PangoCairoRenderer *renderer G_GNUC_UNUSED)
 {
 }
 
+static void
+pango_cairo_renderer_prepare_run (PangoRenderer  *renderer,
+                                  PangoLayoutRun *run)
+{
+  PangoCairoRenderer *crenderer = (PangoCairoRenderer *) renderer;
+
+  PANGO_RENDERER_CLASS (pango_cairo_renderer_parent_class)->prepare_run (renderer, run);
+
+  for (GSList *l = run->item->analysis.extra_attrs; l; l = l->next)
+    {
+      PangoAttribute *attr = l->data;
+
+      switch ((int) attr->klass->type)
+        {
+        case PANGO_ATTR_LIGHT_BACKGROUND:
+          crenderer->has_light_background = ((PangoAttrInt *)attr)->value;
+          break;
+        default:
+          break;
+        }
+    }
+}
+
 static void
 pango_cairo_renderer_class_init (PangoCairoRendererClass *klass)
 {
   PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
 
+  renderer_class->prepare_run = pango_cairo_renderer_prepare_run;
   renderer_class->draw_glyphs = pango_cairo_renderer_draw_glyphs;
   renderer_class->draw_glyph_item = pango_cairo_renderer_draw_glyph_item;
   renderer_class->draw_rectangle = pango_cairo_renderer_draw_rectangle;


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