summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2023-01-28 04:54:26 +0000
committerAdrian Johnson <ajohnson@redneon.com>2023-01-28 04:54:26 +0000
commitb67afda591f90a40ba7eafcf42dbf36ed7a746e6 (patch)
treefabd55a3e7d5f38dc67327afca3247cfcc297c1c /src
parentffabca7924ac57cb808a6a05fa1b00e038f068b5 (diff)
parentbdf97dd2a16886f53f840f1d76922a28e4f36e63 (diff)
downloadcairo-b67afda591f90a40ba7eafcf42dbf36ed7a746e6.tar.gz
Merge branch 'fix-ft-foreground' into 'master'
Fix foreground colors in FT/SVG/COLRv1 See merge request cairo/cairo!430
Diffstat (limited to 'src')
-rw-r--r--src/cairo-colr-glyph-render.c86
-rw-r--r--src/cairo-ft-font.c141
-rw-r--r--src/cairo-ft-private.h9
-rw-r--r--src/cairo-gstate.c2
-rw-r--r--src/cairo-pattern-private.h5
-rw-r--r--src/cairo-pattern.c20
-rw-r--r--src/cairo-recording-surface.c2
-rw-r--r--src/cairo-scaled-font-private.h6
-rwxr-xr-xsrc/cairo-scaled-font.c26
-rw-r--r--src/cairo-surface.c14
-rw-r--r--src/cairo-svg-glyph-render.c77
-rw-r--r--src/cairo-user-font.c17
12 files changed, 234 insertions, 171 deletions
diff --git a/src/cairo-colr-glyph-render.c b/src/cairo-colr-glyph-render.c
index 104942b78..28254fd51 100644
--- a/src/cairo-colr-glyph-render.c
+++ b/src/cairo-colr-glyph-render.c
@@ -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;
}
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index e6a8d20e3..75d6f8c16 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -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,
diff --git a/src/cairo-ft-private.h b/src/cairo-ft-private.h
index 312f65454..836f7e523 100644
--- a/src/cairo-ft-private.h
+++ b/src/cairo-ft-private.h
@@ -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
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 0d52491c9..0f4fd541a 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -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))
{
diff --git a/src/cairo-pattern-private.h b/src/cairo-pattern-private.h
index 0a5e41e8b..d061b39c4 100644
--- a/src/cairo-pattern-private.h
+++ b/src/cairo-pattern-private.h
@@ -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);
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 070309ac6..d16ed2836 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -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);
@@ -625,6 +625,14 @@ _cairo_pattern_create_solid (const cairo_color_t *color)
}
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)
{
cairo_pattern_t *pattern;
diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c
index a7de8df5b..e87320523 100644
--- a/src/cairo-recording-surface.c
+++ b/src/cairo-recording-surface.c
@@ -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",
diff --git a/src/cairo-scaled-font-private.h b/src/cairo-scaled-font-private.h
index 8c10b60c7..64abbe0f5 100644
--- a/src/cairo-scaled-font-private.h
+++ b/src/cairo-scaled-font-private.h
@@ -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;
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index d7e3f1e4b..415b45f78 100755
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -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;
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 503a9a1c1..e9e6233a6 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -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) &&
diff --git a/src/cairo-svg-glyph-render.c b/src/cairo-svg-glyph-render.c
index 9b953687d..3c14f8c59 100644
--- a/src/cairo-svg-glyph-render.c
+++ b/src/cairo-svg-glyph-render.c
@@ -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() */
diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c
index 913395fd9..e7a1d0211 100644
--- a/src/cairo-user-font.c
+++ b/src/cairo-user-font.c
@@ -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? */