Merge branch 'fix-ft-foreground' into 'master'
Fix foreground colors in FT/SVG/COLRv1 See merge request cairo/cairo!430
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) &&
|
||||
|
|
|
|||
|
|
@ -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() */
|
||||
|
|
|
|||
|
|
@ -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? */
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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,
|
||||
|
|
@ -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',
|
||||
|
|
|
|||
BIN
test/reference/ft-svg-render-color.ref.png
Normal file
|
After Width: | Height: | Size: 4 KiB |
|
Before Width: | Height: | Size: 485 B |
|
Before Width: | Height: | Size: 149 B After Width: | Height: | Size: 149 B |
|
Before Width: | Height: | Size: 150 B After Width: | Height: | Size: 150 B |
4
test/svg/color.2.foreground-solid.svg
Normal 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 |
4
test/svg/color.3.foreground-alpha.svg
Normal 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 |
10
test/svg/color.4.foreground-linear.svg
Normal 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 |
10
test/svg/color.5.foreground-linear-alpha.svg
Normal 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 |
10
test/svg/color.6.foreground-radial.svg
Normal 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 |
10
test/svg/color.7.foreground-radial-alpha.svg
Normal 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 |