Merge branch 'fix-ft-foreground' into 'master'

Fix foreground colors in FT/SVG/COLRv1

See merge request cairo/cairo!430
This commit is contained in:
Adrian Johnson 2023-01-28 04:54:26 +00:00
commit b67afda591
25 changed files with 445 additions and 189 deletions

View file

@ -36,6 +36,7 @@
#include "cairo-array-private.h"
#include "cairo-ft-private.h"
#include "cairo-path-private.h"
#include "cairo-pattern-private.h"
#include <assert.h>
#include <math.h>
@ -55,9 +56,11 @@
typedef struct _cairo_colr_glyph_render {
FT_Face face;
cairo_pattern_t *foreground_color;
FT_Color *palette;
unsigned int num_palette_entries;
cairo_pattern_t *foreground_marker;
cairo_pattern_t *foreground_source;
cairo_bool_t foreground_source_used;
int level;
} cairo_colr_glyph_render_t;
@ -225,29 +228,29 @@ draw_paint_colr_layers (cairo_colr_glyph_render_t *render,
static void
get_palette_color (cairo_colr_glyph_render_t *render,
FT_ColorIndex *ci,
cairo_color_t *color,
cairo_bool_t *is_foreground_color)
FT_ColorIndex *ci,
cairo_color_t *color,
double *colr_alpha,
cairo_bool_t *is_foreground_color)
{
cairo_bool_t foreground = FALSE;
if (ci->palette_index == 0xffff || ci->palette_index >= render->num_palette_entries) {
color->red = 0;
color->green = 0;
color->blue = 0;
color->red = 0;
color->green = 0;
color->blue = 0;
color->alpha = 1;
foreground = TRUE;
foreground = TRUE;
} else {
FT_Color c = render->palette[ci->palette_index];
color->red = c.red / 255.0;
color->green = c.green / 255.0;
color->blue = c.blue / 255.0;
FT_Color c = render->palette[ci->palette_index];
color->red = c.red / 255.0;
color->green = c.green / 255.0;
color->blue = c.blue / 255.0;
color->alpha = c.alpha / 255.0;
}
color->alpha *= double_from_2_14 (ci->alpha);
if (is_foreground_color)
*is_foreground_color = foreground;
*colr_alpha = double_from_2_14 (ci->alpha);
*is_foreground_color = foreground;
}
static cairo_status_t
@ -256,21 +259,19 @@ draw_paint_solid (cairo_colr_glyph_render_t *render,
cairo_t *cr)
{
cairo_color_t color;
double colr_alpha;
cairo_bool_t is_foreground_color;
#if DEBUG_COLR
printf ("%*sDraw PaintSolid\n", 2 * render->level, "");
#endif
get_palette_color (render, &solid->color, &color, &is_foreground_color);
if (is_foreground_color)
{
cairo_set_source (cr, render->foreground_color);
cairo_paint_with_alpha (cr, color.alpha);
}
else
{
cairo_set_source_rgba (cr, color.red, color.green, color.blue, color.alpha);
get_palette_color (render, &solid->color, &color, &colr_alpha, &is_foreground_color);
if (is_foreground_color) {
cairo_set_source (cr, render->foreground_marker);
cairo_paint_with_alpha (cr, colr_alpha);
} else {
cairo_set_source_rgba (cr, color.red, color.green, color.blue, color.alpha * colr_alpha);
cairo_paint (cr);
}
@ -315,6 +316,8 @@ read_colorline (cairo_colr_glyph_render_t *render,
cairo_colr_color_line_t *cl;
FT_ColorStop stop;
int i;
double colr_alpha;
cairo_bool_t is_foreground_color;
cl = calloc (1, sizeof (cairo_colr_color_line_t));
if (unlikely (cl == NULL))
@ -330,7 +333,28 @@ read_colorline (cairo_colr_glyph_render_t *render,
i = 0;
while (FT_Get_Colorline_Stops (render->face, &stop, &colorline->color_stop_iterator)) {
cl->stops[i].position = double_from_16_16 (stop.stop_offset);
get_palette_color (render, &stop.color, &cl->stops[i].color, NULL);
get_palette_color (render, &stop.color, &cl->stops[i].color, &colr_alpha, &is_foreground_color);
if (is_foreground_color) {
double red, green, blue, alpha;
if (cairo_pattern_get_rgba (render->foreground_source,
&red, &green, &blue, &alpha) == CAIRO_STATUS_SUCCESS)
{
cl->stops[i].color.red = red;
cl->stops[i].color.green = green;
cl->stops[i].color.blue = blue;
cl->stops[i].color.alpha = alpha * colr_alpha;
render->foreground_source_used = TRUE;
}
else
{
cl->stops[i].color.red = 0;
cl->stops[i].color.green = 0;
cl->stops[i].color.blue = 0;
cl->stops[i].color.alpha = colr_alpha;
}
} else {
cl->stops[i].color.alpha *= colr_alpha;
}
i++;
}
@ -1190,7 +1214,9 @@ _cairo_render_colr_v1_glyph (FT_Face face,
unsigned long glyph,
FT_Color *palette,
int num_palette_entries,
cairo_t *cr)
cairo_t *cr,
cairo_pattern_t *foreground_source,
cairo_bool_t *foreground_source_used)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_colr_glyph_render_t colr_render;
@ -1202,7 +1228,9 @@ _cairo_render_colr_v1_glyph (FT_Face face,
colr_render.face = face;
colr_render.palette = palette;
colr_render.num_palette_entries = num_palette_entries;
colr_render.foreground_color = cairo_pattern_reference (cairo_get_source (cr));
colr_render.foreground_marker = _cairo_pattern_create_foreground_marker ();
colr_render.foreground_source = cairo_pattern_reference (foreground_source);;
colr_render.foreground_source_used = FALSE;
colr_render.level = 0;
status = draw_colr_glyph (&colr_render,
@ -1210,7 +1238,9 @@ _cairo_render_colr_v1_glyph (FT_Face face,
FT_COLOR_INCLUDE_ROOT_TRANSFORM,
cr);
cairo_pattern_destroy (colr_render.foreground_color);
cairo_pattern_destroy (colr_render.foreground_marker);
cairo_pattern_destroy (colr_render.foreground_source);
*foreground_source_used = colr_render.foreground_source_used;
return status;
}

View file

@ -2707,7 +2707,6 @@ _cairo_ft_scaled_glyph_init_surface (cairo_ft_scaled_font_t *scaled_font,
return status;
}
#ifdef HAVE_FT_PALETTE_SELECT
static cairo_int_status_t
_cairo_ft_scaled_glyph_init_record_colr_v0_glyph (cairo_ft_scaled_font_t *scaled_font,
cairo_scaled_glyph_t *scaled_glyph,
@ -2715,6 +2714,7 @@ _cairo_ft_scaled_glyph_init_record_colr_v0_glyph (cairo_ft_scaled_font_t *scaled
cairo_bool_t vertical_layout,
int load_flags)
{
#ifdef HAVE_FT_PALETTE_SELECT
cairo_surface_t *recording_surface;
cairo_t *cr;
cairo_status_t status;
@ -2755,8 +2755,7 @@ _cairo_ft_scaled_glyph_init_record_colr_v0_glyph (cairo_ft_scaled_font_t *scaled
{
cairo_pattern_t *pattern;
if (layer_color_index == 0xFFFF) {
pattern = cairo_pattern_create_rgb (0, 0, 0);
pattern->is_userfont_foreground = TRUE;
pattern = _cairo_pattern_create_foreground_marker ();
} else {
double r = 0, g = 0, b = 0, a = 1;
if (layer_color_index < num_palette_entries) {
@ -2800,22 +2799,25 @@ _cairo_ft_scaled_glyph_init_record_colr_v0_glyph (cairo_ft_scaled_font_t *scaled
recording_surface,
NULL);
return status;
}
#else
return CAIRO_INT_STATUS_UNSUPPORTED;
#endif
}
#if HAVE_FT_COLR_V1
static cairo_int_status_t
_cairo_ft_scaled_glyph_init_record_colr_v1_glyph (cairo_ft_scaled_font_t *scaled_font,
cairo_scaled_glyph_t *scaled_glyph,
FT_Face face,
const cairo_color_t *foreground_color,
cairo_text_extents_t *extents)
{
#if HAVE_FT_COLR_V1
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_surface_t *recording_surface;
cairo_t *cr;
cairo_pattern_t *pattern;
FT_Color *palette;
unsigned int num_palette_entries;
cairo_bool_t foreground_source_used = FALSE;
recording_surface =
cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL);
@ -2827,11 +2829,6 @@ _cairo_ft_scaled_glyph_init_record_colr_v1_glyph (cairo_ft_scaled_font_t *scaled
cairo_set_font_size (cr, 1.0);
cairo_set_font_options (cr, &scaled_font->base.options);
pattern = cairo_pattern_create_rgb (0, 0, 0);
pattern->is_userfont_foreground = TRUE;
cairo_set_source (cr, pattern);
cairo_pattern_destroy (pattern);
extents->x_bearing = DOUBLE_FROM_26_6(face->bbox.xMin);
extents->y_bearing = DOUBLE_FROM_26_6(face->bbox.yMin);
extents->width = DOUBLE_FROM_26_6(face->bbox.xMax) - extents->x_bearing;
@ -2840,14 +2837,15 @@ _cairo_ft_scaled_glyph_init_record_colr_v1_glyph (cairo_ft_scaled_font_t *scaled
_cairo_ft_scaled_glyph_set_palette (scaled_font, face, &num_palette_entries, &palette);
if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
cairo_pattern_t *foreground_pattern = _cairo_pattern_create_solid (foreground_color);
status = _cairo_render_colr_v1_glyph (face,
_cairo_scaled_glyph_index (scaled_glyph),
palette,
num_palette_entries,
cr);
if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
status = CAIRO_INT_STATUS_UNSUPPORTED;
cr,
foreground_pattern,
&foreground_source_used);
cairo_pattern_destroy (foreground_pattern);
if (status == CAIRO_STATUS_SUCCESS)
status = cairo_status (cr);
}
@ -2864,7 +2862,7 @@ _cairo_ft_scaled_glyph_init_record_colr_v1_glyph (cairo_ft_scaled_font_t *scaled
_cairo_scaled_glyph_set_recording_surface (scaled_glyph,
&scaled_font->base,
recording_surface,
NULL);
foreground_source_used ? foreground_color : NULL);
scaled_glyph->color_glyph = TRUE;
scaled_glyph->color_glyph_set = TRUE;
@ -2937,24 +2935,27 @@ _cairo_ft_scaled_glyph_init_record_colr_v1_glyph (cairo_ft_scaled_font_t *scaled
}
return status;
}
#else
return CAIRO_INT_STATUS_UNSUPPORTED;
#endif
}
#if HAVE_FT_SVG_DOCUMENT
static cairo_int_status_t
_cairo_ft_scaled_glyph_init_record_svg_glyph (cairo_ft_scaled_font_t *scaled_font,
cairo_scaled_glyph_t *scaled_glyph,
FT_Face face,
const cairo_color_t *foreground_color,
cairo_text_extents_t *extents)
{
#if HAVE_FT_SVG_DOCUMENT
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_surface_t *recording_surface;
cairo_t *cr;
cairo_pattern_t *pattern;
FT_SVG_Document svg_doc = face->glyph->other;
char *svg_document;
FT_Color *palette;
unsigned int num_palette_entries;
cairo_bool_t foreground_source_used = FALSE;
/* Create NULL terminated SVG document */
svg_document = _cairo_strndup ((const char*)svg_doc->svg_document, svg_doc->svg_document_length);
@ -2974,11 +2975,6 @@ _cairo_ft_scaled_glyph_init_record_svg_glyph (cairo_ft_scaled_font_t *scaled_fon
cairo_set_font_size (cr, 1.0);
cairo_set_font_options (cr, &scaled_font->base.options);
pattern = cairo_pattern_create_rgb (0, 0, 0);
pattern->is_userfont_foreground = TRUE;
cairo_set_source (cr, pattern);
cairo_pattern_destroy (pattern);
extents->x_bearing = DOUBLE_FROM_26_6(face->bbox.xMin);
extents->y_bearing = DOUBLE_FROM_26_6(face->bbox.yMin);
extents->width = DOUBLE_FROM_26_6(face->bbox.xMax) - extents->x_bearing;
@ -2987,6 +2983,7 @@ _cairo_ft_scaled_glyph_init_record_svg_glyph (cairo_ft_scaled_font_t *scaled_fon
_cairo_ft_scaled_glyph_set_palette (scaled_font, face, &num_palette_entries, &palette);
if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
cairo_pattern_t *foreground_pattern = _cairo_pattern_create_solid (foreground_color);
status = _cairo_render_svg_glyph (svg_document,
svg_doc->start_glyph_id,
svg_doc->end_glyph_id,
@ -2994,7 +2991,10 @@ _cairo_ft_scaled_glyph_init_record_svg_glyph (cairo_ft_scaled_font_t *scaled_fon
svg_doc->units_per_EM,
palette,
num_palette_entries,
cr);
cr,
foreground_pattern,
&foreground_source_used);
cairo_pattern_destroy (foreground_pattern);
if (status == CAIRO_STATUS_SUCCESS)
status = cairo_status (cr);
}
@ -3012,7 +3012,7 @@ _cairo_ft_scaled_glyph_init_record_svg_glyph (cairo_ft_scaled_font_t *scaled_fon
_cairo_scaled_glyph_set_recording_surface (scaled_glyph,
&scaled_font->base,
recording_surface,
NULL);
foreground_source_used ? foreground_color : NULL);
scaled_glyph->color_glyph = TRUE;
scaled_glyph->color_glyph_set = TRUE;
@ -3085,8 +3085,10 @@ _cairo_ft_scaled_glyph_init_record_svg_glyph (cairo_ft_scaled_font_t *scaled_fon
}
return status;
}
#else
return CAIRO_INT_STATUS_UNSUPPORTED;
#endif
}
static cairo_int_status_t
_cairo_ft_scaled_glyph_init_surface_for_recording_surface (cairo_ft_scaled_font_t *scaled_font,
@ -3278,11 +3280,12 @@ _cairo_ft_scaled_glyph_is_colr_v1 (cairo_ft_scaled_font_t *scaled_font,
static const int ft_glyph_private_key;
static cairo_int_status_t
_cairo_ft_scaled_glyph_init_metrics (cairo_ft_scaled_font_t *scaled_font,
cairo_scaled_glyph_t *scaled_glyph,
FT_Face face,
cairo_bool_t vertical_layout,
int load_flags)
_cairo_ft_scaled_glyph_init_metrics (cairo_ft_scaled_font_t *scaled_font,
cairo_scaled_glyph_t *scaled_glyph,
FT_Face face,
cairo_bool_t vertical_layout,
int load_flags,
const cairo_color_t *foreground_color)
{
cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
cairo_text_extents_t fs_metrics;
@ -3348,25 +3351,23 @@ _cairo_ft_scaled_glyph_init_metrics (cairo_ft_scaled_font_t *scaled_font,
&fs_metrics);
/* SVG and COLR v1 glyphs require the bounding box to be obtained from
* the ink extents of the rendering. We need to render glyph to a
* recording surface to obtain these extents. But we also need the
* advance from _cairo_ft_scaled_glyph_get_metrics() before calling
* this function.
*/
/* SVG and COLRv1 glyphs require the bounding box to be obtained
* from the ink extents of the rendering. We need to render glyph
* to a recording surface to obtain these extents. But we also
* need the advance from _cairo_ft_scaled_glyph_get_metrics()
* before calling this function.
*/
#if HAVE_FT_SVG_DOCUMENT
if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG) {
status = (cairo_int_status_t)_cairo_ft_scaled_glyph_init_record_svg_glyph (scaled_font,
scaled_glyph,
face,
foreground_color,
&fs_metrics);
if (unlikely (status))
return status;
}
#endif
#if HAVE_FT_COLR_V1
if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1) {
if (!hint_metrics) {
status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
@ -3382,11 +3383,11 @@ _cairo_ft_scaled_glyph_init_metrics (cairo_ft_scaled_font_t *scaled_font,
status = (cairo_int_status_t)_cairo_ft_scaled_glyph_init_record_colr_v1_glyph (scaled_font,
scaled_glyph,
face,
foreground_color,
&fs_metrics);
if (unlikely (status))
return status;
}
#endif
_cairo_scaled_glyph_set_metrics (scaled_glyph,
&scaled_font->base,
@ -3409,6 +3410,11 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_bool_t scaled_glyph_loaded = FALSE;
cairo_ft_glyph_private_t *glyph_priv;
int color_flag = 0;
#ifdef FT_LOAD_COLOR
color_flag = FT_LOAD_COLOR;
#endif
face = _cairo_ft_unscaled_font_lock_face (unscaled);
if (!face)
@ -3432,12 +3438,14 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
vertical_layout = TRUE;
}
/* Metrics will always be requested when a scaled glyph is created */
if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) {
status = _cairo_ft_scaled_glyph_init_metrics (scaled_font,
scaled_glyph,
face,
vertical_layout,
load_flags);
load_flags,
foreground_color);
if (unlikely (status))
goto FAIL;
}
@ -3447,26 +3455,39 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
assert (glyph_priv != NULL);
if (info & CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE) {
switch (glyph_priv->format) {
case CAIRO_FT_GLYPH_TYPE_BITMAP:
case CAIRO_FT_GLYPH_TYPE_OUTLINE:
break;
case CAIRO_FT_GLYPH_TYPE_SVG:
case CAIRO_FT_GLYPH_TYPE_COLR_V1:
/* The SVG and COLR v1 recording surfaces are
* initialized in _cairo_ft_scaled_glyph_init_metrics()
*/
status = CAIRO_STATUS_SUCCESS;
break;
case CAIRO_FT_GLYPH_TYPE_COLR_V0:
#ifdef HAVE_FT_PALETTE_SELECT
status = CAIRO_INT_STATUS_UNSUPPORTED;
if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG ||
glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V0 ||
glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1)
{
status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
scaled_glyph,
face,
load_flags | color_flag,
FALSE,
vertical_layout);
if (unlikely (status))
goto FAIL;
if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG) {
status = _cairo_ft_scaled_glyph_init_record_svg_glyph (scaled_font,
scaled_glyph,
face,
foreground_color,
&scaled_glyph->fs_metrics);
} else if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1) {
status = _cairo_ft_scaled_glyph_init_record_colr_v1_glyph (scaled_font,
scaled_glyph,
face,
foreground_color,
&scaled_glyph->fs_metrics);
} else if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V0) {
status = _cairo_ft_scaled_glyph_init_record_colr_v0_glyph (scaled_font,
scaled_glyph,
face,
vertical_layout,
load_flags);
#endif
break;
}
}
if (status)
goto FAIL;
@ -3477,8 +3498,8 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1)
{
status = _cairo_ft_scaled_glyph_init_surface_for_recording_surface (scaled_font,
scaled_glyph,
foreground_color);
scaled_glyph,
foreground_color);
} else {
status = _cairo_ft_scaled_glyph_init_surface (scaled_font,
scaled_glyph,

View file

@ -1,3 +1,4 @@
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc
@ -74,7 +75,9 @@ _cairo_render_svg_glyph (const char *svg_document,
double units_per_em,
FT_Color *palette,
int num_palette_entries,
cairo_t *cr);
cairo_t *cr,
cairo_pattern_t *foreground_source,
cairo_bool_t *foreground_source_used);
#endif
#if HAVE_FT_COLR_V1
@ -83,7 +86,9 @@ _cairo_render_colr_v1_glyph (FT_Face face,
unsigned long glyph,
FT_Color *palette,
int num_palette_entries,
cairo_t *cr);
cairo_t *cr,
cairo_pattern_t *foreground_source,
cairo_bool_t *foreground_source_used);
#endif
CAIRO_END_DECLS

View file

@ -1145,7 +1145,7 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
}
_cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
if (source->type == CAIRO_PATTERN_TYPE_SOLID &&
if (source->type == CAIRO_PATTERN_TYPE_SOLID && !source->is_foreground_marker &&
mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID &&
_cairo_operator_bounded_by_source (op))
{

View file

@ -72,7 +72,7 @@ struct _cairo_pattern {
cairo_filter_t filter;
cairo_extend_t extend;
cairo_bool_t has_component_alpha;
cairo_bool_t is_userfont_foreground;
cairo_bool_t is_foreground_marker;
cairo_matrix_t matrix;
double opacity;
@ -240,6 +240,9 @@ _cairo_pattern_fini (cairo_pattern_t *pattern);
cairo_private cairo_pattern_t *
_cairo_pattern_create_solid (const cairo_color_t *color);
cairo_private cairo_pattern_t *
_cairo_pattern_create_foreground_marker (void);
cairo_private void
_cairo_pattern_transform (cairo_pattern_t *pattern,
const cairo_matrix_t *ctm_inverse);

View file

@ -76,7 +76,7 @@ static const cairo_solid_pattern_t _cairo_pattern_nil = {
CAIRO_FILTER_DEFAULT, /* filter */
CAIRO_EXTEND_GRADIENT_DEFAULT, /* extend */
FALSE, /* has component alpha */
FALSE, /* is_userfont_foreground */
FALSE, /* is_foreground_marker */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
1.0 /* opacity */
}
@ -93,7 +93,7 @@ static const cairo_solid_pattern_t _cairo_pattern_nil_null_pointer = {
CAIRO_FILTER_DEFAULT, /* filter */
CAIRO_EXTEND_GRADIENT_DEFAULT, /* extend */
FALSE, /* has component alpha */
FALSE, /* is_userfont_foreground */
FALSE, /* is_foreground_marker */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
1.0 /* opacity */
}
@ -110,7 +110,7 @@ const cairo_solid_pattern_t _cairo_pattern_black = {
CAIRO_FILTER_NEAREST, /* filter */
CAIRO_EXTEND_REPEAT, /* extend */
FALSE, /* has component alpha */
FALSE, /* is_userfont_foreground */
FALSE, /* is_foreground_marker */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
1.0 /* opacity */
},
@ -128,7 +128,7 @@ const cairo_solid_pattern_t _cairo_pattern_clear = {
CAIRO_FILTER_NEAREST, /* filter */
CAIRO_EXTEND_REPEAT, /* extend */
FALSE, /* has component alpha */
FALSE, /* is_userfont_foreground */
FALSE, /* is_foreground_marker */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
1.0 /* opacity */
},
@ -146,7 +146,7 @@ const cairo_solid_pattern_t _cairo_pattern_white = {
CAIRO_FILTER_NEAREST, /* filter */
CAIRO_EXTEND_REPEAT, /* extend */
FALSE, /* has component alpha */
FALSE, /* is_userfont_foreground */
FALSE, /* is_foreground_marker */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
1.0 /* opacity */
},
@ -238,7 +238,7 @@ _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
pattern->opacity = 1.0;
pattern->has_component_alpha = FALSE;
pattern->is_userfont_foreground = FALSE;
pattern->is_foreground_marker = FALSE;
cairo_matrix_init_identity (&pattern->matrix);
@ -624,6 +624,14 @@ _cairo_pattern_create_solid (const cairo_color_t *color)
return &pattern->base;
}
cairo_pattern_t *
_cairo_pattern_create_foreground_marker (void)
{
cairo_pattern_t *pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
pattern->is_foreground_marker = TRUE;
return pattern;
}
cairo_pattern_t *
_cairo_pattern_create_in_error (cairo_status_t status)
{

View file

@ -2706,7 +2706,7 @@ print_pattern (FILE *file,
switch (pattern->type) {
case CAIRO_PATTERN_TYPE_SOLID: {
cairo_solid_pattern_t *p = (cairo_solid_pattern_t *) pattern;
if (pattern->is_userfont_foreground) {
if (pattern->is_foreground_marker) {
fprintf (file, "solid foreground\n");
} else {
fprintf (file, "solid rgba: %f %f %f %f\n",

View file

@ -150,11 +150,11 @@ struct _cairo_scaled_glyph {
cairo_color_t foreground_color; /* only used for color glyphs */
/* TRUE if the recording_surface required the foreground_color to render. */
/* TRUE if the recording_surface used the foreground_source to render. */
unsigned recording_uses_foreground_color : 1;
/* TRUE if the color_surface required the foreground_color to render. */
unsigned image_uses_foreground_color : 1;
/* TRUE if the recording surface uses the foreground marker. */
unsigned recording_uses_foreground_marker : 1;
/* TRUE if color_glyph specifies if glyph is color or non color, FALSE if glyph color type unknown. */
unsigned color_glyph_set : 1;

View file

@ -2688,14 +2688,15 @@ _cairo_scaled_glyph_set_recording_surface (cairo_scaled_glyph_t *scaled_glyph,
* @scaled_glyph: a #cairo_scaled_glyph_t
* @scaled_font: a #cairo_scaled_font_t
* @surface: The image surface
* @foreground_color: The foreground color that was used to render the
* glyph, or NULL if foreground color not required.
* @foreground_marker_color: The foreground color that was used to
* substitute the foreground_marker, or NULL if foreground_marker not
* used when rendering the surface color.
*/
void
_cairo_scaled_glyph_set_color_surface (cairo_scaled_glyph_t *scaled_glyph,
cairo_scaled_font_t *scaled_font,
cairo_image_surface_t *surface,
const cairo_color_t *foreground_color)
const cairo_color_t *foreground_marker_color)
{
if (scaled_glyph->color_surface != NULL)
cairo_surface_destroy (&scaled_glyph->color_surface->base);
@ -2703,9 +2704,9 @@ _cairo_scaled_glyph_set_color_surface (cairo_scaled_glyph_t *scaled_glyph,
/* sanity check the backend glyph contents */
_cairo_debug_check_image_surface_is_defined (&surface->base);
scaled_glyph->color_surface = surface;
scaled_glyph->image_uses_foreground_color = foreground_color != NULL;
if (foreground_color)
scaled_glyph->foreground_color = *foreground_color;
scaled_glyph->recording_uses_foreground_marker = foreground_marker_color != NULL;
if (foreground_marker_color)
scaled_glyph->foreground_color = *foreground_marker_color;
if (surface != NULL)
scaled_glyph->has_info |= CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE;
@ -2935,19 +2936,20 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
return CAIRO_INT_STATUS_UNSUPPORTED;
/* If requesting a color surface or recording for a glyph that has
* used the foreground color to render the color_surface, and the
* foreground color has changed, request a new image and/or
* recording. */
if (info & CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE &&
* used the foreground color to render the recording, and the
* foreground color has changed, request a new recording. */
if ((info & (CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE | CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) &&
scaled_glyph->recording_uses_foreground_color &&
!_cairo_color_equal (foreground_color, &scaled_glyph->foreground_color))
{
need_info |= CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE;
}
/* If requesting a color surface for a glyph that has
* used the foreground color to render the color_surface, and the
* foreground color has changed, request a new image. */
if (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE &&
scaled_glyph->image_uses_foreground_color &&
(scaled_glyph->recording_uses_foreground_marker || scaled_glyph->recording_uses_foreground_color) &&
!_cairo_color_equal (foreground_color, &scaled_glyph->foreground_color))
{
need_info |= CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE;

View file

@ -2204,7 +2204,7 @@ _cairo_surface_paint (cairo_surface_t *surface,
if (unlikely (status))
return status;
if (source->is_userfont_foreground && surface->foreground_source) {
if (source->is_foreground_marker && surface->foreground_source) {
source = surface->foreground_source;
surface->foreground_used = TRUE;
}
@ -2259,7 +2259,7 @@ _cairo_surface_mask (cairo_surface_t *surface,
if (unlikely (status))
return status;
if (source->is_userfont_foreground && surface->foreground_source) {
if (source->is_foreground_marker && surface->foreground_source) {
source = surface->foreground_source;
surface->foreground_used = TRUE;
}
@ -2320,12 +2320,12 @@ _cairo_surface_fill_stroke (cairo_surface_t *surface,
if (unlikely (status))
return status;
if (fill_source->is_userfont_foreground && surface->foreground_source) {
if (fill_source->is_foreground_marker && surface->foreground_source) {
fill_source = surface->foreground_source;
surface->foreground_used = TRUE;
}
if (stroke_source->is_userfont_foreground && surface->foreground_source) {
if (stroke_source->is_foreground_marker && surface->foreground_source) {
stroke_source = surface->foreground_source;
surface->foreground_used = TRUE;
}
@ -2404,7 +2404,7 @@ _cairo_surface_stroke (cairo_surface_t *surface,
if (unlikely (status))
return status;
if (source->is_userfont_foreground && surface->foreground_source) {
if (source->is_foreground_marker && surface->foreground_source) {
source = surface->foreground_source;
surface->foreground_used = TRUE;
}
@ -2454,7 +2454,7 @@ _cairo_surface_fill (cairo_surface_t *surface,
if (unlikely (status))
return status;
if (source->is_userfont_foreground && surface->foreground_source) {
if (source->is_foreground_marker && surface->foreground_source) {
source = surface->foreground_source;
surface->foreground_used = TRUE;
}
@ -2944,7 +2944,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
if (unlikely (status))
return status;
if (source->is_userfont_foreground && surface->foreground_source)
if (source->is_foreground_marker && surface->foreground_source)
source = surface->foreground_source;
if (_cairo_scaled_font_has_color_glyphs (scaled_font) &&

View file

@ -35,8 +35,9 @@
*/
#include "cairoint.h"
#include "cairo-ft-private.h"
#include "cairo-array-private.h"
#include "cairo-ft-private.h"
#include "cairo-pattern-private.h"
#include "cairo-scaled-font-subsets-private.h"
#include <stdarg.h>
@ -239,7 +240,7 @@ typedef struct _cairo_svg_element {
} cairo_svg_element_t;
typedef struct _cairo_svg_color {
enum { RGB, CURRENT_COLOR } type;
enum { RGB, FOREGROUND } type;
double red;
double green;
double blue;
@ -291,7 +292,6 @@ typedef struct _cairo_svg_glyph_render {
cairo_hash_table_t *ids;
cairo_svg_graphics_state_t *graphics_state;
cairo_t *cr;
cairo_pattern_t *foreground_color;
double units_per_em;
struct {
cairo_svg_element_t *paint_server;
@ -307,6 +307,10 @@ typedef struct _cairo_svg_glyph_render {
double height;
cairo_bool_t view_port_set;
cairo_pattern_t *foreground_marker;
cairo_pattern_t *foreground_source;
cairo_bool_t foreground_source_used;
int debug; /* 0 = quiet, 1 = errors, 2 = warnings, 3 = info */
} cairo_svg_glyph_render_t;
@ -745,13 +749,13 @@ get_color (cairo_svg_glyph_render_t *svg_render,
len = strlen(s);
if (string_equal (s, "inherit") ||
string_equal (s, "currentColor") ||
string_equal (s, "context-fill") ||
string_equal (s, "context-stroke"))
if (string_equal (s, "inherit")) {
return FALSE;
} else if (string_equal (s, "currentColor") ||
string_equal (s, "context-fill") ||
string_equal (s, "context-stroke"))
{
color->type = CURRENT_COLOR;
color->red = color->green = color->blue = 0;
*color = svg_render->graphics_state->color;
return TRUE;
} else if (len > 0 && s[0] == '#') {
if (len == 4) {
@ -810,7 +814,7 @@ get_color (cairo_svg_glyph_render_t *svg_render,
end = strpbrk(s, WHITE_SPACE_CHARS ")");
if (!end || end == s)
return FALSE;
return FALSE;
char *fallback = _cairo_strndup (s, end - s);
cairo_bool_t success = get_color (svg_render, fallback, color);
@ -1710,6 +1714,15 @@ render_element_stop (cairo_svg_glyph_render_t *svg_render,
color.green,
color.blue,
opacity);
} else { /* color.type == FOREGROUND */
double red, green, blue, alpha;
if (cairo_pattern_get_rgba (svg_render->foreground_source, &red, &green, &blue, &alpha) == CAIRO_STATUS_SUCCESS) {
svg_render->foreground_source_used = TRUE;
} else {
red = green = blue = 0;
alpha = 1;
}
cairo_pattern_add_color_stop_rgba (pattern, offset, red, green, blue, alpha);
}
return TRUE;
}
@ -1906,12 +1919,10 @@ draw_path (cairo_svg_glyph_render_t *svg_render)
gs->fill.color.green,
gs->fill.color.blue,
gs->fill_opacity);
} else if (gs->fill.color.type == CURRENT_COLOR) {
cairo_set_source_rgba (svg_render->cr,
gs->color.red,
gs->color.green,
gs->color.blue,
gs->fill_opacity);
} else if (gs->fill.color.type == FOREGROUND) {
cairo_set_source (svg_render->cr, svg_render->foreground_marker);
if (gs->fill_opacity < 1.0)
group = TRUE;
}
} else if (gs->fill.type == PAINT_SERVER) {
pattern = create_pattern (svg_render, gs->fill.paint_server);
@ -1942,12 +1953,10 @@ draw_path (cairo_svg_glyph_render_t *svg_render)
gs->stroke.color.green,
gs->stroke.color.blue,
gs->stroke_opacity);
} else if (gs->stroke.color.type == CURRENT_COLOR) {
cairo_set_source_rgba (svg_render->cr,
gs->color.red,
gs->color.green,
gs->color.blue,
gs->stroke_opacity);
} else if (gs->fill.color.type == FOREGROUND) {
cairo_set_source (svg_render->cr, svg_render->foreground_marker);
if (gs->fill_opacity < 1.0)
group = TRUE;
}
} else if (gs->stroke.type == PAINT_SERVER) {
pattern = create_pattern (svg_render, gs->stroke.paint_server);
@ -2579,20 +2588,11 @@ static void
init_graphics_state (cairo_svg_glyph_render_t *svg_render)
{
cairo_svg_graphics_state_t *gs;
double alpha;
gs = _cairo_malloc (sizeof (cairo_svg_graphics_state_t));
get_paint (svg_render, "black", &gs->fill);
get_paint (svg_render, "none", &gs->stroke);
gs->color.type = RGB;
if (cairo_pattern_get_rgba (svg_render->foreground_color,
&gs->color.red,
&gs->color.green,
&gs->color.blue,
&alpha) != CAIRO_STATUS_SUCCESS)
{
get_color (svg_render, "black", &gs->color);
}
gs->color.type = FOREGROUND;
gs->fill_opacity = 1.0;
gs->stroke_opacity = 1.0;
gs->opacity = 1.0;
@ -3096,7 +3096,9 @@ _cairo_render_svg_glyph (const char *svg_document,
double units_per_em,
FT_Color *palette,
int num_palette_entries,
cairo_t *cr)
cairo_t *cr,
cairo_pattern_t *foreground_source,
cairo_bool_t *foreground_source_used)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
@ -3122,7 +3124,6 @@ _cairo_render_svg_glyph (const char *svg_document,
svg_render->cr = cr;
svg_render->units_per_em = units_per_em;
svg_render->foreground_color = cairo_pattern_reference (cairo_get_source (cr));
svg_render->build_pattern.paint_server = NULL;
svg_render->build_pattern.pattern = NULL;
svg_render->build_pattern.type = BUILD_PATTERN_NONE;
@ -3131,6 +3132,10 @@ _cairo_render_svg_glyph (const char *svg_document,
svg_render->num_palette_entries = num_palette_entries;
svg_render->palette = palette;
svg_render->foreground_marker = _cairo_pattern_create_foreground_marker ();
svg_render->foreground_source = cairo_pattern_reference (foreground_source);;
svg_render->foreground_source_used = FALSE;
init_graphics_state (svg_render);
print_info (svg_render, "Glyph ID: %ld", glyph);
@ -3175,7 +3180,9 @@ _cairo_render_svg_glyph (const char *svg_document,
while (svg_render->graphics_state)
restore_graphics_state (svg_render);
cairo_pattern_destroy (svg_render->foreground_color);
cairo_pattern_destroy (svg_render->foreground_marker);
cairo_pattern_destroy (svg_render->foreground_source);
*foreground_source_used = svg_render->foreground_source_used;
/* The hash entry for each element with an id is removed by
* free_elements() */

View file

@ -381,20 +381,8 @@ _cairo_user_scaled_glyph_init (void *abstract_font,
{
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
cairo_user_scaled_font_t *scaled_font = abstract_font;
cairo_bool_t need_recording = FALSE;
if (!scaled_glyph->recording_surface) {
need_recording = TRUE;
} else {
if ((info & (CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE|CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) &&
scaled_glyph->recording_uses_foreground_color &&
!_cairo_color_equal (foreground_color, &scaled_glyph->foreground_color))
{
need_recording = TRUE;
}
}
if (need_recording) {
if (!scaled_glyph->recording_surface || (info & CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE)) {
status = _cairo_user_scaled_glyph_init_record_glyph (scaled_font, scaled_glyph, foreground_color);
if (status)
return status;
@ -598,8 +586,7 @@ _cairo_user_font_face_scaled_font_create (void *abstract_
}
user_scaled_font->foreground_pattern = NULL;
user_scaled_font->foreground_marker = cairo_pattern_create_rgb (0, 0, 0);
user_scaled_font->foreground_marker->is_userfont_foreground = TRUE;
user_scaled_font->foreground_marker = _cairo_pattern_create_foreground_marker ();
/* XXX metrics hinting? */

View file

@ -6,18 +6,24 @@
<GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="zero"/>
<GlyphID id="2" name="one"/>
<GlyphID id="3" name="two"/>
<GlyphID id="4" name="three"/>
<GlyphID id="5" name="four"/>
<GlyphID id="6" name="five"/>
<GlyphID id="7" name="six"/>
<GlyphID id="8" name="seven"/>
</GlyphOrder>
<head>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/>
<fontRevision value="1.0"/>
<checkSumAdjustment value="0xcb6df82"/>
<checkSumAdjustment value="0x1d3a9a74"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/>
<unitsPerEm value="1000"/>
<created value="Wed Jun 15 00:00:00 2022"/>
<modified value="Sat Jan 21 05:46:29 2023"/>
<modified value="Fri Jan 27 08:44:23 2023"/>
<xMin value="0"/>
<yMin value="0"/>
<xMax value="1000"/>
@ -52,7 +58,7 @@
<maxp>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="0x10000"/>
<numGlyphs value="3"/>
<numGlyphs value="9"/>
<maxPoints value="4"/>
<maxContours value="1"/>
<maxCompositePoints value="0"/>
@ -106,7 +112,7 @@
<achVendID value="djr "/>
<fsSelection value="00000000 01000000"/>
<usFirstCharIndex value="48"/>
<usLastCharIndex value="49"/>
<usLastCharIndex value="55"/>
<sTypoAscender value="1000"/>
<sTypoDescender value="0"/>
<sTypoLineGap value="200"/>
@ -123,7 +129,13 @@
<hmtx>
<mtx name=".notdef" width="1100" lsb="0"/>
<mtx name="five" width="1100" lsb="0"/>
<mtx name="four" width="1100" lsb="0"/>
<mtx name="one" width="1100" lsb="0"/>
<mtx name="seven" width="1100" lsb="0"/>
<mtx name="six" width="1100" lsb="0"/>
<mtx name="three" width="1100" lsb="0"/>
<mtx name="two" width="1100" lsb="0"/>
<mtx name="zero" width="1100" lsb="0"/>
</hmtx>
@ -132,6 +144,12 @@
<cmap_format_4 platformID="0" platEncID="3" language="0">
<map code="0x30" name="zero"/><!-- DIGIT ZERO -->
<map code="0x31" name="one"/><!-- DIGIT ONE -->
<map code="0x32" name="two"/><!-- DIGIT TWO -->
<map code="0x33" name="three"/><!-- DIGIT THREE -->
<map code="0x34" name="four"/><!-- DIGIT FOUR -->
<map code="0x35" name="five"/><!-- DIGIT FIVE -->
<map code="0x36" name="six"/><!-- DIGIT SIX -->
<map code="0x37" name="seven"/><!-- DIGIT SEVEN -->
</cmap_format_4>
</cmap>
@ -146,6 +164,26 @@
<TTGlyph name=".notdef"/><!-- contains no outline data -->
<TTGlyph name="five" xMin="0" yMin="0" xMax="1000" yMax="1000">
<contour>
<pt x="0" y="0" on="1"/>
<pt x="0" y="1000" on="1"/>
<pt x="1000" y="1000" on="1"/>
<pt x="1000" y="0" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="four" xMin="0" yMin="0" xMax="1000" yMax="1000">
<contour>
<pt x="0" y="0" on="1"/>
<pt x="0" y="1000" on="1"/>
<pt x="1000" y="1000" on="1"/>
<pt x="1000" y="0" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="one" xMin="0" yMin="0" xMax="1000" yMax="1000">
<contour>
<pt x="0" y="0" on="1"/>
@ -156,6 +194,46 @@
<instructions/>
</TTGlyph>
<TTGlyph name="seven" xMin="0" yMin="0" xMax="1000" yMax="1000">
<contour>
<pt x="0" y="0" on="1"/>
<pt x="0" y="1000" on="1"/>
<pt x="1000" y="1000" on="1"/>
<pt x="1000" y="0" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="six" xMin="0" yMin="0" xMax="1000" yMax="1000">
<contour>
<pt x="0" y="0" on="1"/>
<pt x="0" y="1000" on="1"/>
<pt x="1000" y="1000" on="1"/>
<pt x="1000" y="0" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="three" xMin="0" yMin="0" xMax="1000" yMax="1000">
<contour>
<pt x="0" y="0" on="1"/>
<pt x="0" y="1000" on="1"/>
<pt x="1000" y="1000" on="1"/>
<pt x="1000" y="0" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="two" xMin="0" yMin="0" xMax="1000" yMax="1000">
<contour>
<pt x="0" y="0" on="1"/>
<pt x="0" y="1000" on="1"/>
<pt x="1000" y="1000" on="1"/>
<pt x="1000" y="0" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="zero" xMin="0" yMin="0" xMax="1000" yMax="1000">
<contour>
<pt x="0" y="0" on="1"/>
@ -170,13 +248,13 @@
<name>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
Cairo Svg Test Palette
Cairo Svg Test Color
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
Cairo Svg Test Palette Regular
Cairo Svg Test Color Regular
</namerecord>
</name>
@ -219,6 +297,64 @@
<![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect x="100" y="-750" width="800" height="500"
fill="var(--color1, blue)" />
</svg>]]>
</svgDoc>
<svgDoc endGlyphID="3" startGlyphID="3">
<![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect x="100" y="-750" width="800" height="500"
fill="currentColor" />
</svg>]]>
</svgDoc>
<svgDoc endGlyphID="4" startGlyphID="4">
<![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect x="100" y="-750" width="800" height="500"
fill="currentColor" fill-opacity="0.5" />
</svg>]]>
</svgDoc>
<svgDoc endGlyphID="5" startGlyphID="5">
<![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grad" x1="33%" x21="66%">
<stop offset="0%" stop-color="currentColor" stop-opacity="1" />
<stop offset="100%" stop-color="red" stop-opacity="1" />
</linearGradient>
</defs>
<rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
</svg>]]>
</svgDoc>
<svgDoc endGlyphID="6" startGlyphID="6">
<![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grad" x1="33%" x21="66%">
<stop offset="0%" stop-color="currentColor" stop-opacity="0.3" />
<stop offset="100%" stop-color="red" stop-opacity="0.3" />
</linearGradient>
</defs>
<rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
</svg>]]>
</svgDoc>
<svgDoc endGlyphID="7" startGlyphID="7">
<![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="grad" cx="50%" cy="50%"
fx="0.75" fy="0.35" r="0.5">
<stop offset="0%" stop-color="currentColor" stop-opacity="1" />
<stop offset="100%" stop-color="blue" stop-opacity="1" />
</radialGradient>
</defs>
<rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
</svg>]]>
</svgDoc>
<svgDoc endGlyphID="8" startGlyphID="8">
<![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="grad" cx="50%" cy="50%"
fx="0.75" fy="0.35" r="0.5">
<stop offset="0%" stop-color="currentColor" stop-opacity="0.5" />
<stop offset="100%" stop-color="blue" stop-opacity="0.5" />
</radialGradient>
</defs>
<rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
</svg>]]>
</svgDoc>
</SVG>

View file

@ -30,11 +30,12 @@
#define FONT_SIZE 50
#define MARGIN 5
#define WIDTH (FONT_SIZE*8 + MARGIN*9)
#define HEIGHT (FONT_SIZE + MARGIN*2)
#define HEIGHT (FONT_SIZE*2 + MARGIN*3)
#define FONT_FILE "cairo-svg-test-palette.ttf"
#define FONT_FILE "cairo-svg-test-color.ttf"
#define TEXT "01"
#define PALETTE_TEXT "01"
#define FOREGROUND_TEXT "234567"
static cairo_test_status_t
@ -52,37 +53,45 @@ draw (cairo_t *cr, int width, int height)
return result;
cairo_set_font_size (cr, FONT_SIZE);
cairo_save (cr);
cairo_move_to (cr, MARGIN, FONT_SIZE + MARGIN);
font_options = cairo_font_options_create ();
/* Default palette */
cairo_show_text (cr, TEXT);
cairo_show_text (cr, PALETTE_TEXT);
/* Palette 1 */
cairo_font_options_set_color_palette (font_options, 1);
cairo_set_font_options (cr, font_options);
cairo_show_text (cr, TEXT);
cairo_show_text (cr, PALETTE_TEXT);
/* Palette 0, override color 0 */
cairo_font_options_set_color_palette (font_options, 0);
cairo_font_options_set_custom_palette_color (font_options, 0, 1, 0, 1, 0.5);
cairo_set_font_options (cr, font_options);
cairo_show_text (cr, TEXT);
cairo_show_text (cr, PALETTE_TEXT);
/* Palette 1, override color 1 */
cairo_font_options_set_color_palette (font_options, 1);
cairo_font_options_set_custom_palette_color (font_options, 1, 0, 1, 1, 0.5);
cairo_set_font_options (cr, font_options);
cairo_show_text (cr, TEXT);
cairo_show_text (cr, PALETTE_TEXT);
cairo_font_options_destroy (font_options);
cairo_restore (cr);
cairo_move_to (cr, MARGIN, FONT_SIZE*2 + MARGIN*2);
cairo_set_source_rgb (cr, 0, 1, 0);
cairo_show_text (cr, FOREGROUND_TEXT);
return CAIRO_TEST_SUCCESS;
}
CAIRO_TEST (ft_svg_render_palette,
"Test cairo SVG font palettes",
CAIRO_TEST (ft_svg_render_color,
"Test cairo SVG font colors",
"svgrender", /* keywords */
NULL, /* requirements */
WIDTH, HEIGHT,

View file

@ -436,7 +436,7 @@ test_ft_svg_font_sources = [
test_ft_svg_ttx_font_sources = [
'ft-svg-cairo-logo.c',
'ft-svg-render.c',
'ft-svg-render-palette.c'
'ft-svg-render-color.c'
]
test_gl_sources = [
@ -532,10 +532,10 @@ ps2png_sources = [
test_ttx_fonts = [
'cairo-logo-font.ttx',
'cairo-svg-test-color.ttx',
'cairo-svg-test-doc.ttx',
'cairo-svg-test-fill.ttx',
'cairo-svg-test-gradient.ttx',
'cairo-svg-test-palette.ttx',
'cairo-svg-test-path.ttx',
'cairo-svg-test-shapes.ttx',
'cairo-svg-test-stroke.ttx',

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 485 B

View file

Before

Width:  |  Height:  |  Size: 149 B

After

Width:  |  Height:  |  Size: 149 B

View file

Before

Width:  |  Height:  |  Size: 150 B

After

Width:  |  Height:  |  Size: 150 B

View file

@ -0,0 +1,4 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect x="100" y="-750" width="800" height="500"
fill="currentColor" />
</svg>

After

Width:  |  Height:  |  Size: 143 B

View file

@ -0,0 +1,4 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect x="100" y="-750" width="800" height="500"
fill="currentColor" fill-opacity="0.5" />
</svg>

After

Width:  |  Height:  |  Size: 163 B

View file

@ -0,0 +1,10 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grad" x1="33%" x21="66%">
<stop offset="0%" stop-color="currentColor" stop-opacity="1" />
<stop offset="100%" stop-color="red" stop-opacity="1" />
</linearGradient>
</defs>
<rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
</svg>

After

Width:  |  Height:  |  Size: 358 B

View file

@ -0,0 +1,10 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grad" x1="33%" x21="66%">
<stop offset="0%" stop-color="currentColor" stop-opacity="0.3" />
<stop offset="100%" stop-color="red" stop-opacity="0.3" />
</linearGradient>
</defs>
<rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
</svg>

After

Width:  |  Height:  |  Size: 362 B

View file

@ -0,0 +1,10 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="grad" cx="50%" cy="50%"
fx="0.75" fy="0.35" r="0.5">
<stop offset="0%" stop-color="currentColor" stop-opacity="1" />
<stop offset="100%" stop-color="blue" stop-opacity="1" />
</radialGradient>
</defs>
<rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
</svg>

After

Width:  |  Height:  |  Size: 405 B

View file

@ -0,0 +1,10 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="grad" cx="50%" cy="50%"
fx="0.75" fy="0.35" r="0.5">
<stop offset="0%" stop-color="currentColor" stop-opacity="0.5" />
<stop offset="100%" stop-color="blue" stop-opacity="0.5" />
</radialGradient>
</defs>
<rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
</svg>

After

Width:  |  Height:  |  Size: 409 B