[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