[cairo-commit] 6 commits - src/cairo-colr-glyph-render.c src/cairo-font-options.c src/cairo-ft-font.c src/cairo-ft-private.h src/cairo.h src/cairo-types-private.h

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Sat Jan 21 02:13:08 UTC 2023


 src/cairo-colr-glyph-render.c |   15 +----
 src/cairo-font-options.c      |  119 ++++++++++++++++++++++++++++++++++++++++--
 src/cairo-ft-font.c           |   23 ++++++--
 src/cairo-ft-private.h        |    3 -
 src/cairo-types-private.h     |    7 ++
 src/cairo.h                   |   12 ++++
 6 files changed, 156 insertions(+), 23 deletions(-)

New commits:
commit 7072f62611f43cc1311b76f111fdd1e96278b4e4
Merge: 45a1317aa 733e298be
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sat Jan 21 02:13:06 2023 +0000

    Merge branch 'custom-color-palette-2' into 'master'
    
    Add custom palettes for COLRv1 and SVG fonts
    
    See merge request cairo/cairo!417

commit 733e298beaa3a0fad23c8979ef7379750669cb84
Author: Matthias Clasen <mclasen at redhat.com>
Date:   Fri Jan 20 20:39:23 2023 -0500

    Reshuffle code for clarity
    
    Only loop over custom colors if we got
    a palette selected successfully.

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 06baf7dbe..7518ab430 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2531,24 +2531,24 @@ _cairo_ft_scaled_glyph_set_palette (cairo_ft_scaled_font_t  *scaled_font,
 
     num_entries = 0;
     entries = NULL;
+
     if (FT_Palette_Data_Get (face, &palette_data) == 0 && palette_data.num_palettes > 0) {
 	FT_UShort palette_index = CAIRO_COLOR_PALETTE_DEFAULT;
 	if (scaled_font->base.options.palette_index < palette_data.num_palettes)
 	    palette_index = scaled_font->base.options.palette_index;
 
-	num_entries = palette_data.num_palette_entries;
-	if (FT_Palette_Select (face, palette_index, &entries) != 0) {
-	    num_entries = 0;
-	    entries = NULL;
-    	}
-
-        for (unsigned int i = 0; i < scaled_font->base.options.custom_palette_size; i++) {
-            cairo_palette_color_t *entry = &scaled_font->base.options.custom_palette[i];
-            if (entry->index < num_entries) {
-                entries[entry->index].red = 255 * entry->red;
-                entries[entry->index].green = 255 * entry->green;
-                entries[entry->index].blue = 255 * entry->blue;
-                entries[entry->index].alpha = 255 * entry->alpha;
+	if (FT_Palette_Select (face, palette_index, &entries) == 0) {
+	    num_entries = palette_data.num_palette_entries;
+
+            /* Overlay custom colors */
+            for (unsigned int i = 0; i < scaled_font->base.options.custom_palette_size; i++) {
+                cairo_palette_color_t *entry = &scaled_font->base.options.custom_palette[i];
+                if (entry->index < num_entries) {
+                    entries[entry->index].red = 255 * entry->red;
+                    entries[entry->index].green = 255 * entry->green;
+                    entries[entry->index].blue = 255 * entry->blue;
+                    entries[entry->index].alpha = 255 * entry->alpha;
+                }
             }
         }
     }
commit be1d41f001d52f9f07de009d1af6de182cdf2ed1
Author: Matthias Clasen <mclasen at redhat.com>
Date:   Thu Jan 19 08:43:13 2023 -0500

    Use the custom palette for COLv1 renderer
    
    When the font options contain a custom palette,
    overwrite the palette we got from freetype with
    the custom entries.

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 836ceb0a3..06baf7dbe 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2540,7 +2540,17 @@ _cairo_ft_scaled_glyph_set_palette (cairo_ft_scaled_font_t  *scaled_font,
 	if (FT_Palette_Select (face, palette_index, &entries) != 0) {
 	    num_entries = 0;
 	    entries = NULL;
-	}
+    	}
+
+        for (unsigned int i = 0; i < scaled_font->base.options.custom_palette_size; i++) {
+            cairo_palette_color_t *entry = &scaled_font->base.options.custom_palette[i];
+            if (entry->index < num_entries) {
+                entries[entry->index].red = 255 * entry->red;
+                entries[entry->index].green = 255 * entry->green;
+                entries[entry->index].blue = 255 * entry->blue;
+                entries[entry->index].alpha = 255 * entry->alpha;
+            }
+        }
     }
     if (num_entries_ret)
 	*num_entries_ret = num_entries;
commit 67eeed44cd5499b654088eb7e6c964d60a011139
Author: Matthias Clasen <mclasen at redhat.com>
Date:   Wed Jan 18 23:00:41 2023 -0500

    Add a custom palette to font options
    
    Add a way to define a custom color palette as
    part of cairo_font_options_t. To use the custom
    palette when rendering color fonts, set the palette
    index to CAIRO_COLOR_PALETTE_CUSTOM.

diff --git a/src/cairo-font-options.c b/src/cairo-font-options.c
index 30d695894..4eac64da9 100644
--- a/src/cairo-font-options.c
+++ b/src/cairo-font-options.c
@@ -58,7 +58,8 @@ static const cairo_font_options_t _cairo_font_options_nil = {
     CAIRO_ROUND_GLYPH_POS_DEFAULT,
     NULL, /* variations */
     CAIRO_COLOR_MODE_DEFAULT,
-    CAIRO_COLOR_PALETTE_DEFAULT
+    CAIRO_COLOR_PALETTE_DEFAULT,
+    NULL, 0, /* custom palette */
 };
 
 /**
@@ -79,6 +80,8 @@ _cairo_font_options_init_default (cairo_font_options_t *options)
     options->variations = NULL;
     options->color_mode = CAIRO_COLOR_MODE_DEFAULT;
     options->palette_index = CAIRO_COLOR_PALETTE_DEFAULT;
+    options->custom_palette = NULL;
+    options->custom_palette_size = 0;
 }
 
 void
@@ -94,6 +97,12 @@ _cairo_font_options_init_copy (cairo_font_options_t		*options,
     options->variations = other->variations ? strdup (other->variations) : NULL;
     options->color_mode = other->color_mode;
     options->palette_index = other->palette_index;
+    options->custom_palette_size = other->custom_palette_size;
+    options->custom_palette = NULL;
+    if (other->custom_palette) {
+        options->custom_palette = (cairo_palette_color_t *) malloc (sizeof (cairo_palette_color_t) * options->custom_palette_size);
+        memcpy (options->custom_palette, other->custom_palette, sizeof (cairo_palette_color_t) * options->custom_palette_size);
+    }
 }
 
 /**
@@ -164,6 +173,7 @@ void
 _cairo_font_options_fini (cairo_font_options_t *options)
 {
     free (options->variations);
+    free (options->custom_palette);
 }
 
 /**
@@ -266,6 +276,12 @@ cairo_font_options_merge (cairo_font_options_t       *options,
 	options->color_mode = other->color_mode;
     if (other->palette_index != CAIRO_COLOR_PALETTE_DEFAULT)
 	options->palette_index = other->palette_index;
+    if (other->custom_palette) {
+        options->custom_palette_size = other->custom_palette_size;
+        free (options->custom_palette);
+        options->custom_palette = (cairo_palette_color_t *) malloc (sizeof (cairo_palette_color_t) * options->custom_palette_size);
+        memcpy (options->custom_palette, other->custom_palette, sizeof (cairo_palette_color_t) * options->custom_palette_size);
+    }
 }
 slim_hidden_def (cairo_font_options_merge);
 
@@ -304,7 +320,12 @@ cairo_font_options_equal (const cairo_font_options_t *options,
              (options->variations != NULL && other->variations != NULL &&
               strcmp (options->variations, other->variations) == 0)) &&
 	    options->color_mode == other->color_mode &&
-	    options->palette_index == other->palette_index);
+	    options->palette_index == other->palette_index &&
+            ((options->custom_palette == NULL && other->custom_palette == NULL) ||
+             (options->custom_palette != NULL && other->custom_palette != NULL &&
+              options->custom_palette_size == other->custom_palette_size &&
+              memcmp (options->custom_palette, other->custom_palette,
+                      sizeof (cairo_palette_color_t) * options->custom_palette_size) == 0)));
 }
 slim_hidden_def (cairo_font_options_equal);
 
@@ -686,8 +707,12 @@ cairo_font_options_get_color_mode (const cairo_font_options_t *options)
  *
  * Sets the OpenType font color palette for the font options
  * object. OpenType color fonts with a CPAL table may contain multiple
- * palettes. The default color palette index is %CAIRO_COLOR_PALETTE_DEFAULT. If
- * @palette_index is invalid, the default palette is used.
+ * palettes. The default color palette index is %CAIRO_COLOR_PALETTE_DEFAULT.
+ *
+ * #cairo_font_options_t can also contain a custom palette, which will
+ * be used if @palette_index is %CAIRO_COLOR_PALETTE_CUSTOM.
+ *
+ * If @palette_index is invalid, the default palette is used.
  *
  * Since: 1.18
  **/
@@ -719,3 +744,89 @@ cairo_font_options_get_color_palette (const cairo_font_options_t *options)
 
     return options->palette_index;
 }
+
+/**
+ * cairo_font_options_set_custom_palette_color:
+ * @options: a #cairo_font_options_t
+ * @index: the index of the color to set
+ * @red: red component of color
+ * @green: green component of color
+ * @blue: blue component of color
+ * @alpha: alpha component of color
+ *
+ * Sets a custom palette color for the font options object.
+ *
+ * The custom colors will be used in preference to the selected
+ * color palette from the font (see cairo_font_options_set_color_palette()).
+ * It is possible to override only selected colors from the font palette.
+ *
+ * Since: 1.18
+ */
+void
+cairo_font_options_set_custom_palette_color (cairo_font_options_t *options,
+                                             unsigned int index,
+                                             double red, double green,
+                                             double blue, double alpha)
+{
+    unsigned int idx;
+
+    for (idx = 0; idx < options->custom_palette_size; idx++) {
+        if (options->custom_palette[idx].index == index) {
+            break;
+        }
+    }
+
+    if (idx == options->custom_palette_size) {
+        options->custom_palette_size++;
+        options->custom_palette = (cairo_palette_color_t *)
+            _cairo_realloc_ab (options->custom_palette,
+                               sizeof (cairo_palette_color_t),
+                               options->custom_palette_size);
+    }
+
+    /* beware of holes */
+    memset (&options->custom_palette[idx], 0, sizeof (cairo_palette_color_t));
+
+    options->custom_palette[idx].index = index;
+    options->custom_palette[idx].red = red;
+    options->custom_palette[idx].green = green;
+    options->custom_palette[idx].blue = blue;
+    options->custom_palette[idx].alpha = alpha;
+}
+
+/**
+ * cairo_font_options_get_custom_palette_color:
+ * @options: a #cairo_font_options_t
+ * @index: the index of the color to get
+ * @red: return location for red component of color
+ * @green: return location for green component of color
+ * @blue: return location for blue component of color
+ * @alpha: return location for alpha component of color
+ *
+ * Gets a custom palette color for the font options object.
+ *
+ * Returns: `CAIRO_STATUS_SUCCESS` if a custom palette color is returned,
+ *     `CAIRO_STATUS_INVALID_INDEX` otherwise.
+ *
+ * Since: 1.18
+ */
+cairo_status_t
+cairo_font_options_get_custom_palette_color (cairo_font_options_t *options,
+                                             unsigned int index,
+                                             double *red, double *green,
+                                             double *blue, double *alpha)
+{
+    unsigned int idx;
+
+    for (idx = 0; idx < options->custom_palette_size; idx++) {
+        if (options->custom_palette[idx].index == index) {
+            *red = options->custom_palette[idx].red;
+            *green = options->custom_palette[idx].green;
+            *blue = options->custom_palette[idx].blue;
+            *alpha = options->custom_palette[idx].alpha;
+            return CAIRO_STATUS_SUCCESS;
+        }
+    }
+
+    return CAIRO_STATUS_INVALID_INDEX;
+}
diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h
index a9980f3b9..736a1bcb3 100644
--- a/src/cairo-types-private.h
+++ b/src/cairo-types-private.h
@@ -187,6 +187,11 @@ typedef enum _cairo_round_glyph_positions {
     CAIRO_ROUND_GLYPH_POS_OFF
 } cairo_round_glyph_positions_t;
 
+typedef struct {
+    unsigned int index;
+    double red, green, blue, alpha;
+} cairo_palette_color_t;
+
 struct _cairo_font_options {
     cairo_antialias_t antialias;
     cairo_subpixel_order_t subpixel_order;
@@ -197,6 +202,8 @@ struct _cairo_font_options {
     char *variations;
     cairo_color_mode_t color_mode;
     unsigned int palette_index;
+    cairo_palette_color_t *custom_palette;
+    unsigned int custom_palette_size;
 };
 
 struct _cairo_glyph_text_info {
diff --git a/src/cairo.h b/src/cairo.h
index 82e2c69d8..7f3461534 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -1485,6 +1485,18 @@ cairo_public void
 cairo_font_options_set_color_palette (cairo_font_options_t *options,
                                       unsigned int          palette_index);
 
+cairo_public void
+cairo_font_options_set_custom_palette_color (cairo_font_options_t *options,
+                                             unsigned int index,
+                                             double red, double green,
+                                             double blue, double alpha);
+
+cairo_public cairo_status_t
+cairo_font_options_get_custom_palette_color (cairo_font_options_t *options,
+                                             unsigned int index,
+                                             double *red, double *green,
+                                             double *blue, double *alpha);
+
 /* This interface is for dealing with text as text, not caring about the
    font object inside the the cairo_t. */
 
commit 2e4afeb4bc88a9eefdf926f547776466493f6832
Author: Matthias Clasen <mclasen at redhat.com>
Date:   Thu Jan 19 09:02:10 2023 -0500

    cairo-ft: Pass the palette to the COLRv1 renderer
    
    It an unnecessary complication for use to pass
    the palette index, and have the COLRv1 renderer
    pull the palette out of the FT_Face, after we
    just selected it.

diff --git a/src/cairo-colr-glyph-render.c b/src/cairo-colr-glyph-render.c
index 66a496417..3b345f111 100644
--- a/src/cairo-colr-glyph-render.c
+++ b/src/cairo-colr-glyph-render.c
@@ -1188,29 +1188,20 @@ draw_colr_glyph (cairo_colr_glyph_render_t *render,
 cairo_status_t
 _cairo_render_colr_v1_glyph (FT_Face               face,
                              unsigned long         glyph,
-                             FT_UShort             palette_index,
+                             FT_Color             *palette,
+                             int                   num_palette_entries,
                              cairo_t              *cr)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_colr_glyph_render_t colr_render;
-    FT_Color *palette = NULL;
-    FT_Palette_Data palette_data;
 
 #if DEBUG_COLR
     printf ("_cairo_render_colr_glyph  glyph index: %ld\n", glyph);
 #endif
 
-    if (FT_Palette_Data_Get (face, &palette_data) == 0 && palette_data.num_palettes > 0) {
-	if (palette_index >= palette_data.num_palettes)
-	    palette_index = CAIRO_COLOR_PALETTE_DEFAULT;
-
-	if (FT_Palette_Select (face, palette_index, &palette) != 0)
-	    palette = NULL;
-    }
-
     colr_render.face = face;
     colr_render.palette = palette;
-    colr_render.num_palette_entries = palette_data.num_palette_entries;
+    colr_render.num_palette_entries = num_palette_entries;
     colr_render.foreground_color = cairo_pattern_reference (cairo_get_source (cr));
     colr_render.level = 0;
 
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 8fb16876c..836ceb0a3 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2831,7 +2831,8 @@ _cairo_ft_scaled_glyph_init_record_colr_v1_glyph (cairo_ft_scaled_font_t *scaled
     if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
 	status = _cairo_render_colr_v1_glyph (face,
 					      _cairo_scaled_glyph_index (scaled_glyph),
-					      scaled_font->base.options.palette_index,
+                                              palette,
+                                              num_palette_entries,
 					      cr);
 	if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
 	    status = CAIRO_INT_STATUS_UNSUPPORTED;
diff --git a/src/cairo-ft-private.h b/src/cairo-ft-private.h
index 4775d8135..312f65454 100644
--- a/src/cairo-ft-private.h
+++ b/src/cairo-ft-private.h
@@ -81,7 +81,8 @@ _cairo_render_svg_glyph (const char           *svg_document,
 cairo_private cairo_status_t
 _cairo_render_colr_v1_glyph (FT_Face                 face,
                              unsigned long           glyph,
-                             FT_UShort               palette_index,
+                             FT_Color               *palette,
+                             int                     num_palette_entries,
                              cairo_t                *cr);
 #endif
 
commit 8992e26f07ae13fa9700d93ba4766f474f7d68f5
Author: Matthias Clasen <mclasen at redhat.com>
Date:   Thu Jan 19 09:00:45 2023 -0500

    cairo-ft: Fix palette handling
    
    We were returning the number of palettes where
    the number of palette entries was expected,
    leading to array overruns. Oops

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 6ff142f76..8fb16876c 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2536,7 +2536,7 @@ _cairo_ft_scaled_glyph_set_palette (cairo_ft_scaled_font_t  *scaled_font,
 	if (scaled_font->base.options.palette_index < palette_data.num_palettes)
 	    palette_index = scaled_font->base.options.palette_index;
 
-	num_entries = palette_data.num_palettes;
+	num_entries = palette_data.num_palette_entries;
 	if (FT_Palette_Select (face, palette_index, &entries) != 0) {
 	    num_entries = 0;
 	    entries = NULL;


More information about the cairo-commit mailing list