Allow user fonts to use the foreground color
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -172,6 +172,11 @@ cairo_private cairo_status_t
|
|||
_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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
@ -73,6 +74,10 @@ cairo_private void
|
|||
_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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -591,6 +612,14 @@ _cairo_surface_wrapper_set_clip (cairo_surface_wrapper_t *wrapper,
|
|||
wrapper->clip = clip;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
16
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.
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.2 KiB |
|
|
@ -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);
|
||||
|
||||
|
|
|
|||