diff options
-rw-r--r-- | src/cairo-pattern-private.h | 1 | ||||
-rw-r--r-- | src/cairo-pattern.c | 6 | ||||
-rw-r--r-- | src/cairo-recording-surface-private.h | 5 | ||||
-rw-r--r-- | src/cairo-recording-surface.c | 149 | ||||
-rw-r--r-- | src/cairo-scaled-font-private.h | 5 | ||||
-rw-r--r-- | src/cairo-surface-wrapper-private.h | 5 | ||||
-rw-r--r-- | src/cairo-surface-wrapper.c | 33 | ||||
-rw-r--r-- | src/cairo-user-font.c | 23 | ||||
-rw-r--r-- | src/cairo.h | 16 | ||||
-rw-r--r-- | test/reference/user-font-color.image16.ref.png | bin | 3496 -> 3527 bytes | |||
-rw-r--r-- | test/reference/user-font-color.pdf.ref.png | bin | 4156 -> 4234 bytes | |||
-rw-r--r-- | test/reference/user-font-color.quartz.ref.png | bin | 4061 -> 4163 bytes | |||
-rw-r--r-- | test/reference/user-font-color.ref.png | bin | 4155 -> 4233 bytes | |||
-rw-r--r-- | test/reference/user-font-color.script.xfail.png | bin | 1964 -> 1969 bytes | |||
-rw-r--r-- | test/reference/user-font-color.svg.ref.png | bin | 4152 -> 4289 bytes | |||
-rw-r--r-- | test/user-font-color.c | 8 |
16 files changed, 195 insertions, 56 deletions
diff --git a/src/cairo-pattern-private.h b/src/cairo-pattern-private.h index f03dedd9e..f6138fb70 100644 --- a/src/cairo-pattern-private.h +++ b/src/cairo-pattern-private.h @@ -72,6 +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_matrix_t matrix; double opacity; diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c index e7af5ff5e..6bd3edfd8 100644 --- a/src/cairo-pattern.c +++ b/src/cairo-pattern.c @@ -76,6 +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 */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ 1.0 /* opacity */ } @@ -92,6 +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 */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ 1.0 /* opacity */ } @@ -108,6 +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 */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ 1.0 /* opacity */ }, @@ -125,6 +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 */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ 1.0 /* opacity */ }, @@ -142,6 +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 */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ 1.0 /* opacity */ }, @@ -233,6 +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; cairo_matrix_init_identity (&pattern->matrix); diff --git a/src/cairo-recording-surface-private.h b/src/cairo-recording-surface-private.h index e8d98e8fa..63b7a1de6 100644 --- a/src/cairo-recording-surface-private.h +++ b/src/cairo-recording-surface-private.h @@ -173,6 +173,11 @@ _cairo_recording_surface_replay (cairo_surface_t *surface, cairo_surface_t *target); cairo_private cairo_status_t +_cairo_recording_surface_replay_with_foreground_color (cairo_surface_t *surface, + cairo_surface_t *target, + const cairo_color_t *color); + +cairo_private cairo_status_t _cairo_recording_surface_replay_with_clip (cairo_surface_t *surface, const cairo_matrix_t *surface_transform, cairo_surface_t *target, diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c index 86caf9029..065e62c46 100644 --- a/src/cairo-recording-surface.c +++ b/src/cairo-recording-surface.c @@ -96,6 +96,17 @@ typedef enum { CAIRO_RECORDING_CREATE_REGIONS } cairo_recording_replay_type_t; +typedef struct _cairo_recording_surface_replay_params { + const cairo_rectangle_int_t *surface_extents; + const cairo_matrix_t *surface_transform; + cairo_surface_t *target; + const cairo_clip_t *target_clip; + cairo_bool_t surface_is_unbounded; + cairo_recording_replay_type_t type; + cairo_recording_region_type_t region; + const cairo_color_t *foreground_color; +} cairo_recording_surface_replay_params_t; + static const cairo_surface_backend_t cairo_recording_surface_backend; /** @@ -1782,18 +1793,12 @@ _cairo_recording_surface_merge_source_attributes (cairo_recording_surface_t *su static cairo_status_t _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, - const cairo_rectangle_int_t *surface_extents, - const cairo_matrix_t *surface_transform, - cairo_surface_t *target, - const cairo_clip_t *target_clip, - cairo_bool_t surface_is_unbounded, - cairo_recording_replay_type_t type, - cairo_recording_region_type_t region) + cairo_recording_surface_replay_params_t *params) { cairo_surface_wrapper_t wrapper; cairo_command_t **elements; cairo_bool_t replay_all = - type == CAIRO_RECORDING_CREATE_REGIONS || region == CAIRO_RECORDING_REGION_ALL; + params->type == CAIRO_RECORDING_CREATE_REGIONS || params->region == CAIRO_RECORDING_REGION_ALL; cairo_int_status_t status = CAIRO_STATUS_SUCCESS; cairo_rectangle_int_t extents; cairo_bool_t use_indices = FALSE; @@ -1803,8 +1808,8 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, if (unlikely (surface->base.status)) return surface->base.status; - if (unlikely (target->status)) - return target->status; + if (unlikely (params->target->status)) + return params->target->status; if (unlikely (surface->base.finished)) return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED); @@ -1814,19 +1819,20 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, assert (_cairo_surface_is_recording (&surface->base)); - _cairo_surface_wrapper_init (&wrapper, target); - if (surface_extents) - _cairo_surface_wrapper_intersect_extents (&wrapper, surface_extents); + _cairo_surface_wrapper_init (&wrapper, params->target); + if (params->surface_extents) + _cairo_surface_wrapper_intersect_extents (&wrapper, params->surface_extents); r = &_cairo_unbounded_rectangle; - if (! surface->unbounded && !surface_is_unbounded) { + if (! surface->unbounded && !params->surface_is_unbounded) { _cairo_surface_wrapper_intersect_extents (&wrapper, &surface->extents); r = &surface->extents; } - _cairo_surface_wrapper_set_inverse_transform (&wrapper, surface_transform); - _cairo_surface_wrapper_set_clip (&wrapper, target_clip); + _cairo_surface_wrapper_set_inverse_transform (&wrapper, params->surface_transform); + _cairo_surface_wrapper_set_clip (&wrapper, params->target_clip); + _cairo_surface_wrapper_set_foreground_color (&wrapper, params->foreground_color); /* Compute the extents of the target clip in recorded device space */ - if (! _cairo_surface_wrapper_get_target_extents (&wrapper, surface_is_unbounded, &extents)) + if (! _cairo_surface_wrapper_get_target_extents (&wrapper, params->surface_is_unbounded, &extents)) goto done; surface->has_bilevel_alpha = TRUE; @@ -1843,7 +1849,7 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, for (i = 0; i < num_elements; i++) { cairo_command_t *command = elements[use_indices ? surface->indices[i] : i]; - if (! replay_all && command->header.region != region) + if (! replay_all && command->header.region != params->region) continue; if (! _cairo_rectangle_intersects (&extents, &command->header.extents)) { @@ -1857,7 +1863,7 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, command->header.op, &command->paint.source.base, command->header.clip); - if (type == CAIRO_RECORDING_CREATE_REGIONS) { + if (params->type == CAIRO_RECORDING_CREATE_REGIONS) { _cairo_recording_surface_merge_source_attributes (surface, command->header.op, &command->paint.source.base); @@ -1870,7 +1876,7 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, &command->mask.source.base, &command->mask.mask.base, command->header.clip); - if (type == CAIRO_RECORDING_CREATE_REGIONS) { + if (params->type == CAIRO_RECORDING_CREATE_REGIONS) { _cairo_recording_surface_merge_source_attributes (surface, command->header.op, &command->mask.source.base); @@ -1891,7 +1897,7 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, command->stroke.tolerance, command->stroke.antialias, command->header.clip); - if (type == CAIRO_RECORDING_CREATE_REGIONS) { + if (params->type == CAIRO_RECORDING_CREATE_REGIONS) { _cairo_recording_surface_merge_source_attributes (surface, command->header.op, &command->stroke.source.base); @@ -1904,14 +1910,14 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, cairo_command_t *stroke_command; stroke_command = NULL; - if (type != CAIRO_RECORDING_CREATE_REGIONS && i < num_elements - 1) + if (params->type != CAIRO_RECORDING_CREATE_REGIONS && i < num_elements - 1) stroke_command = elements[i + 1]; if (stroke_command != NULL && - type == CAIRO_RECORDING_REPLAY && - region != CAIRO_RECORDING_REGION_ALL) + params->type == CAIRO_RECORDING_REPLAY && + params->region != CAIRO_RECORDING_REGION_ALL) { - if (stroke_command->header.region != region) + if (stroke_command->header.region != params->region) stroke_command = NULL; } @@ -1937,7 +1943,7 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, stroke_command->stroke.tolerance, stroke_command->stroke.antialias, command->header.clip); - if (type == CAIRO_RECORDING_CREATE_REGIONS) { + if (params->type == CAIRO_RECORDING_CREATE_REGIONS) { _cairo_recording_surface_merge_source_attributes (surface, command->header.op, &command->fill.source.base); @@ -1957,7 +1963,7 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, command->fill.tolerance, command->fill.antialias, command->header.clip); - if (type == CAIRO_RECORDING_CREATE_REGIONS) { + if (params->type == CAIRO_RECORDING_CREATE_REGIONS) { _cairo_recording_surface_merge_source_attributes (surface, command->header.op, &command->fill.source.base); @@ -1975,7 +1981,7 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, command->show_text_glyphs.cluster_flags, command->show_text_glyphs.scaled_font, command->header.clip); - if (type == CAIRO_RECORDING_CREATE_REGIONS) { + if (params->type == CAIRO_RECORDING_CREATE_REGIONS) { _cairo_recording_surface_merge_source_attributes (surface, command->header.op, &command->show_text_glyphs.source.base); @@ -1997,7 +2003,7 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO)) status = CAIRO_INT_STATUS_SUCCESS; - if (type == CAIRO_RECORDING_CREATE_REGIONS && command->header.region != CAIRO_RECORDING_REGION_NATIVE) { + if (params->type == CAIRO_RECORDING_CREATE_REGIONS && command->header.region != CAIRO_RECORDING_REGION_NATIVE) { if (status == CAIRO_INT_STATUS_SUCCESS) { command->header.region = CAIRO_RECORDING_REGION_NATIVE; } else if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) { @@ -2130,10 +2136,37 @@ cairo_status_t _cairo_recording_surface_replay (cairo_surface_t *surface, cairo_surface_t *target) { - return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, NULL, NULL, - target, NULL, FALSE, - CAIRO_RECORDING_REPLAY, - CAIRO_RECORDING_REGION_ALL); + cairo_recording_surface_replay_params_t params; + + params.surface_extents = NULL; + params.surface_transform = NULL; + params.target = target; + params.target_clip = NULL; + params.surface_is_unbounded = FALSE; + params.type = CAIRO_RECORDING_REPLAY; + params.region = CAIRO_RECORDING_REGION_ALL; + params.foreground_color = NULL; + + return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, ¶ms); +} + +cairo_status_t +_cairo_recording_surface_replay_with_foreground_color (cairo_surface_t *surface, + cairo_surface_t *target, + const cairo_color_t *color) +{ + cairo_recording_surface_replay_params_t params; + + params.surface_extents = NULL; + params.surface_transform = NULL; + params.target = target; + params.target_clip = NULL; + params.surface_is_unbounded = FALSE; + params.type = CAIRO_RECORDING_REPLAY; + params.region = CAIRO_RECORDING_REGION_ALL; + params.foreground_color = color; + + return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, ¶ms); } cairo_status_t @@ -2142,10 +2175,18 @@ _cairo_recording_surface_replay_with_clip (cairo_surface_t *surface, cairo_surface_t *target, const cairo_clip_t *target_clip) { - return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, NULL, surface_transform, - target, target_clip, FALSE, - CAIRO_RECORDING_REPLAY, - CAIRO_RECORDING_REGION_ALL); + cairo_recording_surface_replay_params_t params; + + params.surface_extents = NULL; + params.surface_transform = surface_transform; + params.target = target; + params.target_clip = target_clip; + params.surface_is_unbounded = FALSE; + params.type = CAIRO_RECORDING_REPLAY; + params.region = CAIRO_RECORDING_REGION_ALL; + params.foreground_color = NULL; + + return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, ¶ms); } /* Replay recording to surface. When the return status of each operation is @@ -2160,11 +2201,18 @@ _cairo_recording_surface_replay_and_create_regions (cairo_surface_t *surface, cairo_surface_t *target, cairo_bool_t surface_is_unbounded) { - return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, NULL, surface_transform, - target, NULL, - surface_is_unbounded, - CAIRO_RECORDING_CREATE_REGIONS, - CAIRO_RECORDING_REGION_ALL); + cairo_recording_surface_replay_params_t params; + + params.surface_extents = NULL; + params.surface_transform = surface_transform; + params.target = target; + params.target_clip = NULL; + params.surface_is_unbounded = surface_is_unbounded; + params.type = CAIRO_RECORDING_CREATE_REGIONS; + params.region = CAIRO_RECORDING_REGION_ALL; + params.foreground_color = NULL; + + return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, ¶ms); } cairo_status_t @@ -2173,11 +2221,18 @@ _cairo_recording_surface_replay_region (cairo_surface_t *surface, cairo_surface_t *target, cairo_recording_region_type_t region) { - return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, - surface_extents, NULL, - target, NULL, FALSE, - CAIRO_RECORDING_REPLAY, - region); + cairo_recording_surface_replay_params_t params; + + params.surface_extents = surface_extents; + params.surface_transform = NULL; + params.target = target; + params.target_clip = NULL; + params.surface_is_unbounded = FALSE; + params.type = CAIRO_RECORDING_REPLAY; + params.region = region; + params.foreground_color = NULL; + + return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, ¶ms); } static cairo_status_t diff --git a/src/cairo-scaled-font-private.h b/src/cairo-scaled-font-private.h index 42e9b0913..3b2fe586d 100644 --- a/src/cairo-scaled-font-private.h +++ b/src/cairo-scaled-font-private.h @@ -148,13 +148,14 @@ struct _cairo_scaled_glyph { cairo_list_t dev_privates; cairo_color_t foreground_color; /* only used for color glyphs */ - /* TRUE if the color_surface used the foreground_color to render. */ + /* TRUE if the color_surface required the foreground_color to render. */ unsigned uses_foreground_color : 1; /* TRUE if this is not a color glyph, FALSE if is a color glyph or unknown. */ unsigned not_color_glyph : 1; - unsigned has_color : 1; + /* TRUE if recording_surface is a color glyph */ + unsigned recording_is_color : 1; }; struct _cairo_scaled_glyph_private { diff --git a/src/cairo-surface-wrapper-private.h b/src/cairo-surface-wrapper-private.h index 380ba099d..7c3bc56ba 100644 --- a/src/cairo-surface-wrapper-private.h +++ b/src/cairo-surface-wrapper-private.h @@ -53,6 +53,7 @@ struct _cairo_surface_wrapper { cairo_bool_t has_extents; cairo_rectangle_int_t extents; const cairo_clip_t *clip; + cairo_pattern_t *foreground_source; cairo_bool_t needs_transform; }; @@ -74,6 +75,10 @@ _cairo_surface_wrapper_set_clip (cairo_surface_wrapper_t *wrapper, const cairo_clip_t *clip); cairo_private void +_cairo_surface_wrapper_set_foreground_color (cairo_surface_wrapper_t *wrapper, + const cairo_color_t *color); + +cairo_private void _cairo_surface_wrapper_fini (cairo_surface_wrapper_t *wrapper); static inline cairo_bool_t diff --git a/src/cairo-surface-wrapper.c b/src/cairo-surface-wrapper.c index 7fb417a20..8ba82bd40 100644 --- a/src/cairo-surface-wrapper.c +++ b/src/cairo-surface-wrapper.c @@ -144,6 +144,9 @@ _cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper, if (_cairo_clip_is_all_clipped (dev_clip)) return CAIRO_INT_STATUS_NOTHING_TO_DO; + if (source->is_userfont_foreground && wrapper->foreground_source) + source = wrapper->foreground_source; + if (wrapper->needs_transform) { cairo_matrix_t m; @@ -182,6 +185,9 @@ _cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper, if (_cairo_clip_is_all_clipped (dev_clip)) return CAIRO_INT_STATUS_NOTHING_TO_DO; + if (source->is_userfont_foreground && wrapper->foreground_source) + source = wrapper->foreground_source; + if (wrapper->needs_transform) { cairo_matrix_t m; @@ -229,6 +235,9 @@ _cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper, if (_cairo_clip_is_all_clipped (dev_clip)) return CAIRO_INT_STATUS_NOTHING_TO_DO; + if (source->is_userfont_foreground && wrapper->foreground_source) + source = wrapper->foreground_source; + if (wrapper->needs_transform) { cairo_matrix_t m; @@ -297,6 +306,12 @@ _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper, if (_cairo_clip_is_all_clipped (dev_clip)) return CAIRO_INT_STATUS_NOTHING_TO_DO; + if (fill_source->is_userfont_foreground && wrapper->foreground_source) + fill_source = wrapper->foreground_source; + + if (stroke_source->is_userfont_foreground && wrapper->foreground_source) + stroke_source = wrapper->foreground_source; + if (wrapper->needs_transform) { cairo_matrix_t m; @@ -362,6 +377,9 @@ _cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper, if (_cairo_clip_is_all_clipped (dev_clip)) return CAIRO_INT_STATUS_NOTHING_TO_DO; + if (source->is_userfont_foreground && wrapper->foreground_source) + source = wrapper->foreground_source; + if (wrapper->needs_transform) { cairo_matrix_t m; @@ -425,6 +443,9 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper, cairo_surface_get_font_options (wrapper->target, &options); cairo_font_options_merge (&options, &scaled_font->options); + if (source->is_userfont_foreground && wrapper->foreground_source) + source = wrapper->foreground_source; + if (wrapper->needs_transform) { cairo_matrix_t m; int i; @@ -592,6 +613,14 @@ _cairo_surface_wrapper_set_clip (cairo_surface_wrapper_t *wrapper, } void +_cairo_surface_wrapper_set_foreground_color (cairo_surface_wrapper_t *wrapper, + const cairo_color_t *color) +{ + if (color) + wrapper->foreground_source = _cairo_pattern_create_solid (color); +} + +void _cairo_surface_wrapper_get_font_options (cairo_surface_wrapper_t *wrapper, cairo_font_options_t *options) { @@ -622,6 +651,7 @@ _cairo_surface_wrapper_init (cairo_surface_wrapper_t *wrapper, wrapper->has_extents = FALSE; wrapper->extents.x = wrapper->extents.y = 0; wrapper->clip = NULL; + wrapper->foreground_source = NULL; wrapper->needs_transform = FALSE; if (target) { @@ -633,6 +663,9 @@ _cairo_surface_wrapper_init (cairo_surface_wrapper_t *wrapper, void _cairo_surface_wrapper_fini (cairo_surface_wrapper_t *wrapper) { + if (wrapper->foreground_source) + cairo_pattern_destroy (wrapper->foreground_source); + cairo_surface_destroy (wrapper->target); } diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c index 47b9f0422..d6427f060 100644 --- a/src/cairo-user-font.c +++ b/src/cairo-user-font.c @@ -171,15 +171,21 @@ _cairo_user_scaled_glyph_init (void *abstract_font, status = CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED; if (face->scaled_font_methods.render_color_glyph) { + cairo_pattern_t *pattern; + recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, TRUE); cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface, TRUE); + pattern = cairo_pattern_create_rgb (0, 0, 0); + pattern->is_userfont_foreground = TRUE; + cairo_set_source (cr, pattern); + cairo_pattern_destroy (pattern); status = face->scaled_font_methods.render_color_glyph ((cairo_scaled_font_t *)scaled_font, _cairo_scaled_glyph_index(scaled_glyph), cr, &extents); if (status == CAIRO_INT_STATUS_SUCCESS) { status = cairo_status (cr); - scaled_glyph->has_color = TRUE; + scaled_glyph->recording_is_color = TRUE; } } @@ -260,7 +266,7 @@ _cairo_user_scaled_glyph_init (void *abstract_font, height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y); - if (scaled_glyph->has_color) { + if (scaled_glyph->recording_is_color) { format = CAIRO_FORMAT_ARGB32; } else { switch (scaled_font->base.options.antialias) { @@ -285,20 +291,27 @@ _cairo_user_scaled_glyph_init (void *abstract_font, cairo_surface_set_device_offset (surface, - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x), - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y)); - status = _cairo_recording_surface_replay (recording_surface, surface); + + if (scaled_glyph->recording_is_color) { + status = _cairo_recording_surface_replay_with_foreground_color (recording_surface, + surface, + foreground_color); + } else { + status = _cairo_recording_surface_replay (recording_surface, surface); + } if (unlikely (status)) { cairo_surface_destroy(surface); return status; } - if (!scaled_glyph->has_color && (info & CAIRO_SCALED_GLYPH_INFO_SURFACE)) { + if (!scaled_glyph->recording_is_color && (info & CAIRO_SCALED_GLYPH_INFO_SURFACE)) { _cairo_scaled_glyph_set_surface (scaled_glyph, &scaled_font->base, (cairo_image_surface_t *) surface); } - if (scaled_glyph->has_color && (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) { + if (scaled_glyph->recording_is_color && (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) { _cairo_scaled_glyph_set_color_surface (scaled_glyph, &scaled_font->base, (cairo_image_surface_t *)surface, diff --git a/src/cairo.h b/src/cairo.h index a3c5bc11f..fb1da4146 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -1763,6 +1763,22 @@ typedef cairo_status_t (*cairo_user_scaled_font_init_func_t) (cairo_scaled_font_ * cairo_user_font_face_set_render_color_glyph_func(), setting the * source is a valid operation. * + * When this callback is set with + * cairo_user_font_face_set_render_color_glyph_func(), the default + * source is the current source color of the context that is rendering + * the user font. That is, the same color a non-color user font will + * be rendered in. In most cases the callback will want to set a + * specific color. If the callback wishes to use the current context + * color after using another source, it should retain a reference to + * the source or use cairo_save()/cairo_restore() prior to changing + * the source. Note that the default source contains an internal + * marker to indicate that it is to be substituted with the current + * context source color when rendered to a surface. Querying the + * default source pattern will reveal a solid black color, however + * this is not representative of the color that will actually be + * used. Similarly, setting a solid black color will render black, not + * the current context source when the glyph is painted to a surface. + * * Other non-default settings on @cr include a font size of 1.0 (given that * it is set up to be in font space), and font options corresponding to * @scaled_font. diff --git a/test/reference/user-font-color.image16.ref.png b/test/reference/user-font-color.image16.ref.png Binary files differindex 8b29f0b38..404fbf948 100644 --- a/test/reference/user-font-color.image16.ref.png +++ b/test/reference/user-font-color.image16.ref.png diff --git a/test/reference/user-font-color.pdf.ref.png b/test/reference/user-font-color.pdf.ref.png Binary files differindex 849614f0d..674d1a4d6 100644 --- a/test/reference/user-font-color.pdf.ref.png +++ b/test/reference/user-font-color.pdf.ref.png diff --git a/test/reference/user-font-color.quartz.ref.png b/test/reference/user-font-color.quartz.ref.png Binary files differindex 86ce77e38..fc976e8ea 100644 --- a/test/reference/user-font-color.quartz.ref.png +++ b/test/reference/user-font-color.quartz.ref.png diff --git a/test/reference/user-font-color.ref.png b/test/reference/user-font-color.ref.png Binary files differindex bce2f000b..c4294c5f7 100644 --- a/test/reference/user-font-color.ref.png +++ b/test/reference/user-font-color.ref.png diff --git a/test/reference/user-font-color.script.xfail.png b/test/reference/user-font-color.script.xfail.png Binary files differindex 6b1f7ddc6..472a16e16 100644 --- a/test/reference/user-font-color.script.xfail.png +++ b/test/reference/user-font-color.script.xfail.png diff --git a/test/reference/user-font-color.svg.ref.png b/test/reference/user-font-color.svg.ref.png Binary files differindex 9e9bf7d58..4ce8882f8 100644 --- a/test/reference/user-font-color.svg.ref.png +++ b/test/reference/user-font-color.svg.ref.png diff --git a/test/user-font-color.c b/test/user-font-color.c index 437e57a27..781d6945d 100644 --- a/test/user-font-color.c +++ b/test/user-font-color.c @@ -57,13 +57,15 @@ test_scaled_font_init (cairo_scaled_font_t *scaled_font, static void render_glyph_solid (cairo_t *cr, double width, double height, cairo_bool_t color) { + cairo_pattern_t *pattern = cairo_pattern_reference(cairo_get_source (cr)); + if (color) cairo_set_source_rgba (cr, 0, 1, 1, 0.5); cairo_rectangle (cr, 0, 0, width/2, height/2); cairo_fill (cr); if (color) - cairo_set_source_rgba (cr, 1, 0, 1, 0.5); + cairo_set_source (cr, pattern); cairo_rectangle (cr, width/4, height/4, width/2, height/2); cairo_fill (cr); @@ -71,6 +73,8 @@ render_glyph_solid (cairo_t *cr, double width, double height, cairo_bool_t color cairo_set_source_rgba (cr, 1, 1, 0, 0.5); cairo_rectangle (cr, width/2, height/2, width/2, height/2); cairo_fill (cr); + + cairo_pattern_destroy (pattern); } static void @@ -236,7 +240,7 @@ draw (cairo_t *cr, int width, int height) cairo_stroke (cr); /* text in color */ - cairo_set_source_rgb (cr, 0, 0, 0); + cairo_set_source_rgb (cr, 0, 0.3, 0); cairo_move_to (cr, BORDER, BORDER + font_extents.ascent); cairo_show_text (cr, text); |