зеркало из https://github.com/mozilla/gecko-dev.git
b=462938, Upgrade cairo to 1.8.2 and pixman to 0.12.0 [cairo piece]
This commit is contained in:
Родитель
ad77c191d9
Коммит
b22735849c
|
@ -7,8 +7,8 @@ http://www.cairographics.org/.
|
||||||
|
|
||||||
VERSIONS:
|
VERSIONS:
|
||||||
|
|
||||||
cairo (1.7.4-136-g5ea2555)
|
cairo (1.8.2)
|
||||||
pixman (pixman-0.11.10-8-g7180230)
|
pixman (pixman-0.12.0-19-g95f2af9)
|
||||||
|
|
||||||
***** NOTE FOR VISUAL C++ 6.0 *****
|
***** NOTE FOR VISUAL C++ 6.0 *****
|
||||||
|
|
||||||
|
@ -28,6 +28,8 @@ buggy-repeat.patch: Unconditionally turn on buggy-repeat handling to bandaid bug
|
||||||
|
|
||||||
tmpfile_wince.patch: Make Windows CE use tmpfile() on windows mobile due to the lack of _open_osfhandle and no fs permissions.
|
tmpfile_wince.patch: Make Windows CE use tmpfile() on windows mobile due to the lack of _open_osfhandle and no fs permissions.
|
||||||
|
|
||||||
|
cairo-version-fixes.patch: fix up cairo-version.c/cairo-version.h for in-place builds
|
||||||
|
|
||||||
==== pixman patches ====
|
==== pixman patches ====
|
||||||
|
|
||||||
endian.patch: include cairo-platform.h for endian macros
|
endian.patch: include cairo-platform.h for endian macros
|
||||||
|
|
|
@ -85,6 +85,8 @@ CSRCS = \
|
||||||
cairo-deflate-stream.c \
|
cairo-deflate-stream.c \
|
||||||
cairo-fixed.c \
|
cairo-fixed.c \
|
||||||
cairo-font-face.c \
|
cairo-font-face.c \
|
||||||
|
cairo-font-face-twin.c \
|
||||||
|
cairo-font-face-twin-data.c \
|
||||||
cairo-font-options.c \
|
cairo-font-options.c \
|
||||||
cairo-freelist.c \
|
cairo-freelist.c \
|
||||||
cairo-gstate.c \
|
cairo-gstate.c \
|
||||||
|
|
|
@ -66,6 +66,9 @@ cairo_private void
|
||||||
_cairo_analysis_surface_get_bounding_box (cairo_surface_t *surface,
|
_cairo_analysis_surface_get_bounding_box (cairo_surface_t *surface,
|
||||||
cairo_box_t *bbox);
|
cairo_box_t *bbox);
|
||||||
|
|
||||||
|
cairo_private cairo_int_status_t
|
||||||
|
_cairo_analysis_surface_merge_status (cairo_int_status_t status_a,
|
||||||
|
cairo_int_status_t status_b);
|
||||||
|
|
||||||
cairo_private cairo_surface_t *
|
cairo_private cairo_surface_t *
|
||||||
_cairo_null_surface_create (cairo_content_t content);
|
_cairo_null_surface_create (cairo_content_t content);
|
||||||
|
|
|
@ -62,9 +62,41 @@ typedef struct {
|
||||||
|
|
||||||
} cairo_analysis_surface_t;
|
} cairo_analysis_surface_t;
|
||||||
|
|
||||||
|
cairo_int_status_t
|
||||||
|
_cairo_analysis_surface_merge_status (cairo_int_status_t status_a,
|
||||||
|
cairo_int_status_t status_b)
|
||||||
|
{
|
||||||
|
/* fatal errors should be checked and propagated at source */
|
||||||
|
assert (! _cairo_status_is_error (status_a));
|
||||||
|
assert (! _cairo_status_is_error (status_b));
|
||||||
|
|
||||||
|
/* return the most important status */
|
||||||
|
if (status_a == CAIRO_INT_STATUS_UNSUPPORTED ||
|
||||||
|
status_b == CAIRO_INT_STATUS_UNSUPPORTED)
|
||||||
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
|
if (status_a == CAIRO_INT_STATUS_IMAGE_FALLBACK ||
|
||||||
|
status_b == CAIRO_INT_STATUS_IMAGE_FALLBACK)
|
||||||
|
return CAIRO_INT_STATUS_IMAGE_FALLBACK;
|
||||||
|
|
||||||
|
if (status_a == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN ||
|
||||||
|
status_b == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
|
||||||
|
return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
|
||||||
|
|
||||||
|
if (status_a == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY ||
|
||||||
|
status_b == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY)
|
||||||
|
return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
|
||||||
|
|
||||||
|
/* at this point we have checked all the valid internal codes, so... */
|
||||||
|
assert (status_a == CAIRO_STATUS_SUCCESS &&
|
||||||
|
status_b == CAIRO_STATUS_SUCCESS);
|
||||||
|
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static cairo_int_status_t
|
static cairo_int_status_t
|
||||||
_cairo_analysis_surface_analyze_meta_surface_pattern (cairo_analysis_surface_t *surface,
|
_analyze_meta_surface_pattern (cairo_analysis_surface_t *surface,
|
||||||
cairo_pattern_t *pattern)
|
cairo_pattern_t *pattern)
|
||||||
{
|
{
|
||||||
cairo_surface_t *analysis = &surface->base;
|
cairo_surface_t *analysis = &surface->base;
|
||||||
cairo_surface_pattern_t *surface_pattern;
|
cairo_surface_pattern_t *surface_pattern;
|
||||||
|
@ -118,9 +150,9 @@ _cairo_analysis_surface_analyze_meta_surface_pattern (cairo_analysis_surface_t *
|
||||||
}
|
}
|
||||||
|
|
||||||
static cairo_int_status_t
|
static cairo_int_status_t
|
||||||
_cairo_analysis_surface_add_operation (cairo_analysis_surface_t *surface,
|
_add_operation (cairo_analysis_surface_t *surface,
|
||||||
cairo_rectangle_int_t *rect,
|
cairo_rectangle_int_t *rect,
|
||||||
cairo_int_status_t backend_status)
|
cairo_int_status_t backend_status)
|
||||||
{
|
{
|
||||||
cairo_int_status_t status;
|
cairo_int_status_t status;
|
||||||
cairo_box_t bbox;
|
cairo_box_t bbox;
|
||||||
|
@ -302,8 +334,7 @@ _cairo_analysis_surface_paint (void *abstract_surface,
|
||||||
source);
|
source);
|
||||||
|
|
||||||
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
|
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
|
||||||
backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
|
backend_status = _analyze_meta_surface_pattern (surface, source);
|
||||||
source);
|
|
||||||
|
|
||||||
status = _cairo_surface_get_extents (&surface->base, &extents);
|
status = _cairo_surface_get_extents (&surface->base, &extents);
|
||||||
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
|
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||||
|
@ -320,7 +351,7 @@ _cairo_analysis_surface_paint (void *abstract_surface,
|
||||||
|
|
||||||
_cairo_rectangle_intersect (&extents, &surface->current_clip);
|
_cairo_rectangle_intersect (&extents, &surface->current_clip);
|
||||||
|
|
||||||
status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
|
status = _add_operation (surface, &extents, backend_status);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -332,7 +363,7 @@ _cairo_analysis_surface_mask (void *abstract_surface,
|
||||||
cairo_pattern_t *mask)
|
cairo_pattern_t *mask)
|
||||||
{
|
{
|
||||||
cairo_analysis_surface_t *surface = abstract_surface;
|
cairo_analysis_surface_t *surface = abstract_surface;
|
||||||
cairo_status_t status, backend_status;
|
cairo_int_status_t status, backend_status;
|
||||||
cairo_rectangle_int_t extents;
|
cairo_rectangle_int_t extents;
|
||||||
|
|
||||||
if (!surface->target->backend->mask)
|
if (!surface->target->backend->mask)
|
||||||
|
@ -342,25 +373,32 @@ _cairo_analysis_surface_mask (void *abstract_surface,
|
||||||
source, mask);
|
source, mask);
|
||||||
|
|
||||||
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) {
|
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) {
|
||||||
|
cairo_int_status_t backend_source_status = CAIRO_STATUS_SUCCESS;
|
||||||
|
cairo_int_status_t backend_mask_status = CAIRO_STATUS_SUCCESS;
|
||||||
|
|
||||||
if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
||||||
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source;
|
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source;
|
||||||
if (_cairo_surface_is_meta (surface_pattern->surface))
|
if (_cairo_surface_is_meta (surface_pattern->surface)) {
|
||||||
backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
|
backend_source_status =
|
||||||
source);
|
_analyze_meta_surface_pattern (surface, source);
|
||||||
if (backend_status != CAIRO_STATUS_SUCCESS &&
|
if (_cairo_status_is_error (backend_source_status))
|
||||||
backend_status != CAIRO_INT_STATUS_IMAGE_FALLBACK)
|
return backend_source_status;
|
||||||
return backend_status;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
||||||
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) mask;
|
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) mask;
|
||||||
if (_cairo_surface_is_meta (surface_pattern->surface))
|
if (_cairo_surface_is_meta (surface_pattern->surface)) {
|
||||||
backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
|
backend_mask_status =
|
||||||
mask);
|
_analyze_meta_surface_pattern (surface, mask);
|
||||||
if (backend_status != CAIRO_STATUS_SUCCESS &&
|
if (_cairo_status_is_error (backend_mask_status))
|
||||||
backend_status != CAIRO_INT_STATUS_IMAGE_FALLBACK)
|
return backend_mask_status;
|
||||||
return backend_status;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
backend_status =
|
||||||
|
_cairo_analysis_surface_merge_status (backend_source_status,
|
||||||
|
backend_mask_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = _cairo_surface_get_extents (&surface->base, &extents);
|
status = _cairo_surface_get_extents (&surface->base, &extents);
|
||||||
|
@ -384,7 +422,7 @@ _cairo_analysis_surface_mask (void *abstract_surface,
|
||||||
|
|
||||||
_cairo_rectangle_intersect (&extents, &surface->current_clip);
|
_cairo_rectangle_intersect (&extents, &surface->current_clip);
|
||||||
|
|
||||||
status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
|
status = _add_operation (surface, &extents, backend_status);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -403,7 +441,6 @@ _cairo_analysis_surface_stroke (void *abstract_surface,
|
||||||
cairo_analysis_surface_t *surface = abstract_surface;
|
cairo_analysis_surface_t *surface = abstract_surface;
|
||||||
cairo_status_t status, backend_status;
|
cairo_status_t status, backend_status;
|
||||||
cairo_traps_t traps;
|
cairo_traps_t traps;
|
||||||
cairo_box_t box;
|
|
||||||
cairo_rectangle_int_t extents;
|
cairo_rectangle_int_t extents;
|
||||||
|
|
||||||
if (!surface->target->backend->stroke)
|
if (!surface->target->backend->stroke)
|
||||||
|
@ -415,8 +452,7 @@ _cairo_analysis_surface_stroke (void *abstract_surface,
|
||||||
tolerance, antialias);
|
tolerance, antialias);
|
||||||
|
|
||||||
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
|
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
|
||||||
backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
|
backend_status = _analyze_meta_surface_pattern (surface, source);
|
||||||
source);
|
|
||||||
|
|
||||||
status = _cairo_surface_get_extents (&surface->base, &extents);
|
status = _cairo_surface_get_extents (&surface->base, &extents);
|
||||||
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
|
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||||
|
@ -434,10 +470,9 @@ _cairo_analysis_surface_stroke (void *abstract_surface,
|
||||||
_cairo_rectangle_intersect (&extents, &surface->current_clip);
|
_cairo_rectangle_intersect (&extents, &surface->current_clip);
|
||||||
|
|
||||||
if (_cairo_operator_bounded_by_mask (op)) {
|
if (_cairo_operator_bounded_by_mask (op)) {
|
||||||
box.p1.x = _cairo_fixed_from_int (extents.x);
|
cairo_box_t box;
|
||||||
box.p1.y = _cairo_fixed_from_int (extents.y);
|
|
||||||
box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
|
_cairo_box_from_rectangle (&box, &extents);
|
||||||
box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);
|
|
||||||
|
|
||||||
_cairo_traps_init (&traps);
|
_cairo_traps_init (&traps);
|
||||||
_cairo_traps_limit (&traps, &box);
|
_cairo_traps_limit (&traps, &box);
|
||||||
|
@ -451,22 +486,13 @@ _cairo_analysis_surface_stroke (void *abstract_surface,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (traps.num_traps == 0) {
|
_cairo_traps_extents (&traps, &box);
|
||||||
extents.x = 0;
|
|
||||||
extents.y = 0;
|
|
||||||
extents.width = 0;
|
|
||||||
extents.height = 0;
|
|
||||||
} else {
|
|
||||||
_cairo_traps_extents (&traps, &box);
|
|
||||||
extents.x = _cairo_fixed_integer_floor (box.p1.x);
|
|
||||||
extents.y = _cairo_fixed_integer_floor (box.p1.y);
|
|
||||||
extents.width = _cairo_fixed_integer_ceil (box.p2.x) - extents.x;
|
|
||||||
extents.height = _cairo_fixed_integer_ceil (box.p2.y) - extents.y;
|
|
||||||
}
|
|
||||||
_cairo_traps_fini (&traps);
|
_cairo_traps_fini (&traps);
|
||||||
|
|
||||||
|
_cairo_box_round_to_rectangle (&box, &extents);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
|
status = _add_operation (surface, &extents, backend_status);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -483,7 +509,6 @@ _cairo_analysis_surface_fill (void *abstract_surface,
|
||||||
cairo_analysis_surface_t *surface = abstract_surface;
|
cairo_analysis_surface_t *surface = abstract_surface;
|
||||||
cairo_status_t status, backend_status;
|
cairo_status_t status, backend_status;
|
||||||
cairo_traps_t traps;
|
cairo_traps_t traps;
|
||||||
cairo_box_t box;
|
|
||||||
cairo_rectangle_int_t extents;
|
cairo_rectangle_int_t extents;
|
||||||
|
|
||||||
if (!surface->target->backend->fill)
|
if (!surface->target->backend->fill)
|
||||||
|
@ -494,8 +519,7 @@ _cairo_analysis_surface_fill (void *abstract_surface,
|
||||||
tolerance, antialias);
|
tolerance, antialias);
|
||||||
|
|
||||||
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
|
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
|
||||||
backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
|
backend_status = _analyze_meta_surface_pattern (surface, source);
|
||||||
source);
|
|
||||||
|
|
||||||
status = _cairo_surface_get_extents (&surface->base, &extents);
|
status = _cairo_surface_get_extents (&surface->base, &extents);
|
||||||
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
|
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||||
|
@ -513,10 +537,9 @@ _cairo_analysis_surface_fill (void *abstract_surface,
|
||||||
_cairo_rectangle_intersect (&extents, &surface->current_clip);
|
_cairo_rectangle_intersect (&extents, &surface->current_clip);
|
||||||
|
|
||||||
if (_cairo_operator_bounded_by_mask (op)) {
|
if (_cairo_operator_bounded_by_mask (op)) {
|
||||||
box.p1.x = _cairo_fixed_from_int (extents.x);
|
cairo_box_t box;
|
||||||
box.p1.y = _cairo_fixed_from_int (extents.y);
|
|
||||||
box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
|
_cairo_box_from_rectangle (&box, &extents);
|
||||||
box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);
|
|
||||||
|
|
||||||
_cairo_traps_init (&traps);
|
_cairo_traps_init (&traps);
|
||||||
_cairo_traps_limit (&traps, &box);
|
_cairo_traps_limit (&traps, &box);
|
||||||
|
@ -529,23 +552,13 @@ _cairo_analysis_surface_fill (void *abstract_surface,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (traps.num_traps == 0) {
|
_cairo_traps_extents (&traps, &box);
|
||||||
extents.x = 0;
|
|
||||||
extents.y = 0;
|
|
||||||
extents.width = 0;
|
|
||||||
extents.height = 0;
|
|
||||||
} else {
|
|
||||||
_cairo_traps_extents (&traps, &box);
|
|
||||||
extents.x = _cairo_fixed_integer_floor (box.p1.x);
|
|
||||||
extents.y = _cairo_fixed_integer_floor (box.p1.y);
|
|
||||||
extents.width = _cairo_fixed_integer_ceil (box.p2.x) - extents.x;
|
|
||||||
extents.height = _cairo_fixed_integer_ceil (box.p2.y) - extents.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
_cairo_traps_fini (&traps);
|
_cairo_traps_fini (&traps);
|
||||||
|
|
||||||
|
_cairo_box_round_to_rectangle (&box, &extents);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
|
status = _add_operation (surface, &extents, backend_status);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -582,8 +595,7 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface,
|
||||||
backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
|
backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
|
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
|
||||||
backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
|
backend_status = _analyze_meta_surface_pattern (surface, source);
|
||||||
source);
|
|
||||||
|
|
||||||
status = _cairo_surface_get_extents (&surface->base, &extents);
|
status = _cairo_surface_get_extents (&surface->base, &extents);
|
||||||
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
|
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||||
|
@ -611,7 +623,7 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface,
|
||||||
_cairo_rectangle_intersect (&extents, &glyph_extents);
|
_cairo_rectangle_intersect (&extents, &glyph_extents);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
|
status = _add_operation (surface, &extents, backend_status);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -634,7 +646,7 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
const cairo_text_cluster_t *clusters,
|
const cairo_text_cluster_t *clusters,
|
||||||
int num_clusters,
|
int num_clusters,
|
||||||
cairo_bool_t backward,
|
cairo_text_cluster_flags_t cluster_flags,
|
||||||
cairo_scaled_font_t *scaled_font)
|
cairo_scaled_font_t *scaled_font)
|
||||||
{
|
{
|
||||||
cairo_analysis_surface_t *surface = abstract_surface;
|
cairo_analysis_surface_t *surface = abstract_surface;
|
||||||
|
@ -648,8 +660,7 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface,
|
||||||
source,
|
source,
|
||||||
utf8, utf8_len,
|
utf8, utf8_len,
|
||||||
glyphs, num_glyphs,
|
glyphs, num_glyphs,
|
||||||
clusters, num_clusters,
|
clusters, num_clusters, cluster_flags,
|
||||||
backward,
|
|
||||||
scaled_font);
|
scaled_font);
|
||||||
if (backend_status == CAIRO_INT_STATUS_UNSUPPORTED && surface->target->backend->show_glyphs) {
|
if (backend_status == CAIRO_INT_STATUS_UNSUPPORTED && surface->target->backend->show_glyphs) {
|
||||||
int remaining_glyphs = num_glyphs;
|
int remaining_glyphs = num_glyphs;
|
||||||
|
@ -665,8 +676,7 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
|
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
|
||||||
backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
|
backend_status = _analyze_meta_surface_pattern (surface, source);
|
||||||
source);
|
|
||||||
|
|
||||||
status = _cairo_surface_get_extents (&surface->base, &extents);
|
status = _cairo_surface_get_extents (&surface->base, &extents);
|
||||||
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
|
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||||
|
@ -694,7 +704,7 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface,
|
||||||
_cairo_rectangle_intersect (&extents, &glyph_extents);
|
_cairo_rectangle_intersect (&extents, &glyph_extents);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
|
status = _add_operation (surface, &extents, backend_status);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -742,6 +752,11 @@ _cairo_analysis_surface_create (cairo_surface_t *target,
|
||||||
int height)
|
int height)
|
||||||
{
|
{
|
||||||
cairo_analysis_surface_t *surface;
|
cairo_analysis_surface_t *surface;
|
||||||
|
cairo_status_t status;
|
||||||
|
|
||||||
|
status = target->status;
|
||||||
|
if (status)
|
||||||
|
return _cairo_surface_create_in_error (status);
|
||||||
|
|
||||||
surface = malloc (sizeof (cairo_analysis_surface_t));
|
surface = malloc (sizeof (cairo_analysis_surface_t));
|
||||||
if (surface == NULL)
|
if (surface == NULL)
|
||||||
|
@ -785,17 +800,22 @@ _cairo_analysis_surface_create (cairo_surface_t *target,
|
||||||
return &surface->base;
|
return &surface->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_private void
|
void
|
||||||
_cairo_analysis_surface_set_ctm (cairo_surface_t *abstract_surface,
|
_cairo_analysis_surface_set_ctm (cairo_surface_t *abstract_surface,
|
||||||
cairo_matrix_t *ctm)
|
cairo_matrix_t *ctm)
|
||||||
{
|
{
|
||||||
cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface;
|
cairo_analysis_surface_t *surface;
|
||||||
|
|
||||||
|
if (abstract_surface->status)
|
||||||
|
return;
|
||||||
|
|
||||||
|
surface = (cairo_analysis_surface_t *) abstract_surface;
|
||||||
|
|
||||||
surface->ctm = *ctm;
|
surface->ctm = *ctm;
|
||||||
surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
|
surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_private void
|
void
|
||||||
_cairo_analysis_surface_get_ctm (cairo_surface_t *abstract_surface,
|
_cairo_analysis_surface_get_ctm (cairo_surface_t *abstract_surface,
|
||||||
cairo_matrix_t *ctm)
|
cairo_matrix_t *ctm)
|
||||||
{
|
{
|
||||||
|
|
|
@ -85,6 +85,7 @@ _cairo_array_init_snapshot (cairo_array_t *array,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _cairo_array_fini:
|
* _cairo_array_fini:
|
||||||
|
* @array: A #cairo_array_t
|
||||||
*
|
*
|
||||||
* Free all resources associated with @array. After this call, @array
|
* Free all resources associated with @array. After this call, @array
|
||||||
* should not be used again without a subsequent call to
|
* should not be used again without a subsequent call to
|
||||||
|
@ -104,6 +105,7 @@ _cairo_array_fini (cairo_array_t *array)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _cairo_array_grow_by:
|
* _cairo_array_grow_by:
|
||||||
|
* @array: a #cairo_array_t
|
||||||
*
|
*
|
||||||
* Increase the size of @array (if needed) so that there are at least
|
* Increase the size of @array (if needed) so that there are at least
|
||||||
* @additional free spaces in the array. The actual size of the array
|
* @additional free spaces in the array. The actual size of the array
|
||||||
|
@ -158,6 +160,7 @@ _cairo_array_grow_by (cairo_array_t *array, unsigned int additional)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _cairo_array_truncate:
|
* _cairo_array_truncate:
|
||||||
|
* @array: a #cairo_array_t
|
||||||
*
|
*
|
||||||
* Truncate size of the array to @num_elements if less than the
|
* Truncate size of the array to @num_elements if less than the
|
||||||
* current size. No memory is actually freed. The stored objects
|
* current size. No memory is actually freed. The stored objects
|
||||||
|
@ -174,14 +177,16 @@ _cairo_array_truncate (cairo_array_t *array, unsigned int num_elements)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _cairo_array_index:
|
* _cairo_array_index:
|
||||||
|
* @array: a #cairo_array_t
|
||||||
|
* Returns: A pointer to the object stored at @index.
|
||||||
*
|
*
|
||||||
* Return value: A pointer to object stored at @index. If the
|
* If the resulting value is assigned to a pointer to an object of the same
|
||||||
* resulting value is assigned to a pointer to an object of the same
|
|
||||||
* element_size as initially passed to _cairo_array_init() then that
|
* element_size as initially passed to _cairo_array_init() then that
|
||||||
* pointer may be used for further direct indexing with []. For
|
* pointer may be used for further direct indexing with []. For
|
||||||
* example:
|
* example:
|
||||||
*
|
*
|
||||||
* #cairo_array_t array;
|
* <informalexample><programlisting>
|
||||||
|
* cairo_array_t array;
|
||||||
* double *values;
|
* double *values;
|
||||||
*
|
*
|
||||||
* _cairo_array_init (&array, sizeof(double));
|
* _cairo_array_init (&array, sizeof(double));
|
||||||
|
@ -190,6 +195,7 @@ _cairo_array_truncate (cairo_array_t *array, unsigned int num_elements)
|
||||||
* values = _cairo_array_index (&array, 0);
|
* values = _cairo_array_index (&array, 0);
|
||||||
* for (i = 0; i < _cairo_array_num_elements (&array); i++)
|
* for (i = 0; i < _cairo_array_num_elements (&array); i++)
|
||||||
* ... use values[i] here ...
|
* ... use values[i] here ...
|
||||||
|
* </programlisting></informalexample>
|
||||||
**/
|
**/
|
||||||
void *
|
void *
|
||||||
_cairo_array_index (cairo_array_t *array, unsigned int index)
|
_cairo_array_index (cairo_array_t *array, unsigned int index)
|
||||||
|
@ -215,6 +221,7 @@ _cairo_array_index (cairo_array_t *array, unsigned int index)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _cairo_array_copy_element:
|
* _cairo_array_copy_element:
|
||||||
|
* @array: a #cairo_array_t
|
||||||
*
|
*
|
||||||
* Copy a single element out of the array from index @index into the
|
* Copy a single element out of the array from index @index into the
|
||||||
* location pointed to by @dst.
|
* location pointed to by @dst.
|
||||||
|
@ -227,6 +234,7 @@ _cairo_array_copy_element (cairo_array_t *array, int index, void *dst)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _cairo_array_append:
|
* _cairo_array_append:
|
||||||
|
* @array: a #cairo_array_t
|
||||||
*
|
*
|
||||||
* Append a single item onto the array by growing the array by at
|
* Append a single item onto the array by growing the array by at
|
||||||
* least one element, then copying element_size bytes from @element
|
* least one element, then copying element_size bytes from @element
|
||||||
|
@ -250,6 +258,7 @@ _cairo_array_append (cairo_array_t *array,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _cairo_array_append:
|
* _cairo_array_append:
|
||||||
|
* @array: a #cairo_array_t
|
||||||
*
|
*
|
||||||
* Append one or more items onto the array by growing the array by
|
* Append one or more items onto the array by growing the array by
|
||||||
* @num_elements, then copying @num_elements * element_size bytes from
|
* @num_elements, then copying @num_elements * element_size bytes from
|
||||||
|
@ -280,6 +289,7 @@ _cairo_array_append_multiple (cairo_array_t *array,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _cairo_array_allocate:
|
* _cairo_array_allocate:
|
||||||
|
* @array: a #cairo_array_t
|
||||||
*
|
*
|
||||||
* Allocate space at the end of the array for @num_elements additional
|
* Allocate space at the end of the array for @num_elements additional
|
||||||
* elements, providing the address of the new memory chunk in
|
* elements, providing the address of the new memory chunk in
|
||||||
|
@ -314,8 +324,10 @@ _cairo_array_allocate (cairo_array_t *array,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _cairo_array_num_elements:
|
* _cairo_array_num_elements:
|
||||||
|
* @array: a #cairo_array_t
|
||||||
|
* Returns: The number of elements stored in @array.
|
||||||
*
|
*
|
||||||
* Return value: The number of elements stored in @array.
|
* This space was left intentionally blank, but gtk-doc filled it.
|
||||||
**/
|
**/
|
||||||
int
|
int
|
||||||
_cairo_array_num_elements (cairo_array_t *array)
|
_cairo_array_num_elements (cairo_array_t *array)
|
||||||
|
@ -325,9 +337,11 @@ _cairo_array_num_elements (cairo_array_t *array)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _cairo_array_size:
|
* _cairo_array_size:
|
||||||
|
* @array: a #cairo_array_t
|
||||||
|
* Returns: The number of elements for which there is currently space
|
||||||
|
* allocated in @array.
|
||||||
*
|
*
|
||||||
* Return value: The number of elements for which there is currently
|
* This space was left intentionally blank, but gtk-doc filled it.
|
||||||
* space allocated in array.
|
|
||||||
**/
|
**/
|
||||||
int
|
int
|
||||||
_cairo_array_size (cairo_array_t *array)
|
_cairo_array_size (cairo_array_t *array)
|
||||||
|
|
|
@ -37,15 +37,17 @@
|
||||||
#ifndef CAIRO_ATOMIC_PRIVATE_H
|
#ifndef CAIRO_ATOMIC_PRIVATE_H
|
||||||
#define CAIRO_ATOMIC_PRIVATE_H
|
#define CAIRO_ATOMIC_PRIVATE_H
|
||||||
|
|
||||||
|
# include "cairo-compiler-private.h"
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
#if HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CAIRO_BEGIN_DECLS
|
CAIRO_BEGIN_DECLS
|
||||||
|
|
||||||
#define CAIRO_HAS_ATOMIC_OPS 1
|
#if HAVE_INTEL_ATOMIC_PRIMITIVES
|
||||||
|
|
||||||
#if CAIRO_HAS_INTEL_ATOMIC_PRIMITIVES
|
#define HAS_ATOMIC_OPS 1
|
||||||
|
|
||||||
typedef int cairo_atomic_int_t;
|
typedef int cairo_atomic_int_t;
|
||||||
|
|
||||||
|
@ -53,11 +55,10 @@ typedef int cairo_atomic_int_t;
|
||||||
# define _cairo_atomic_int_dec_and_test(x) (__sync_fetch_and_add(x, -1) == 1)
|
# define _cairo_atomic_int_dec_and_test(x) (__sync_fetch_and_add(x, -1) == 1)
|
||||||
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) __sync_val_compare_and_swap (x, oldv, newv)
|
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) __sync_val_compare_and_swap (x, oldv, newv)
|
||||||
|
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
# include "cairo-compiler-private.h"
|
|
||||||
|
|
||||||
# undef CAIRO_HAS_ATOMIC_OPS
|
#ifndef HAS_ATOMIC_OPS
|
||||||
|
|
||||||
typedef int cairo_atomic_int_t;
|
typedef int cairo_atomic_int_t;
|
||||||
|
|
||||||
|
@ -73,7 +74,7 @@ _cairo_atomic_int_cmpxchg (int *x, int oldv, int newv);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef CAIRO_ATOMIC_OP_NEEDS_MEMORY_BARRIER
|
#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
|
||||||
|
|
||||||
# include "cairo-compiler-private.h"
|
# include "cairo-compiler-private.h"
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
#include "cairo-atomic-private.h"
|
#include "cairo-atomic-private.h"
|
||||||
#include "cairo-mutex-private.h"
|
#include "cairo-mutex-private.h"
|
||||||
|
|
||||||
#ifndef CAIRO_HAS_ATOMIC_OPS
|
#ifndef HAS_ATOMIC_OPS
|
||||||
void
|
void
|
||||||
_cairo_atomic_int_inc (int *x)
|
_cairo_atomic_int_inc (int *x)
|
||||||
{
|
{
|
||||||
|
@ -73,7 +73,7 @@ _cairo_atomic_int_cmpxchg (int *x, int oldv, int newv)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CAIRO_ATOMIC_OP_NEEDS_MEMORY_BARRIER
|
#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
|
||||||
int
|
int
|
||||||
_cairo_atomic_int_get (int *x)
|
_cairo_atomic_int_get (int *x)
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,6 +39,9 @@
|
||||||
#include "cairo-skiplist-private.h"
|
#include "cairo-skiplist-private.h"
|
||||||
#include "cairo-freelist-private.h"
|
#include "cairo-freelist-private.h"
|
||||||
|
|
||||||
|
#define DEBUG_VALIDATE 0
|
||||||
|
#define DEBUG_PRINT_STATE 0
|
||||||
|
|
||||||
typedef cairo_point_t cairo_bo_point32_t;
|
typedef cairo_point_t cairo_bo_point32_t;
|
||||||
|
|
||||||
typedef struct _cairo_bo_point128 {
|
typedef struct _cairo_bo_point128 {
|
||||||
|
@ -198,60 +201,163 @@ _slope_compare (cairo_bo_edge_t *a,
|
||||||
* with respect to x. */
|
* with respect to x. */
|
||||||
if ((adx ^ bdx) < 0) {
|
if ((adx ^ bdx) < 0) {
|
||||||
return adx < 0 ? -1 : +1;
|
return adx < 0 ? -1 : +1;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
int32_t ady = a->bottom.y - a->top.y;
|
int32_t ady = a->bottom.y - a->top.y;
|
||||||
int32_t bdy = b->bottom.y - b->top.y;
|
int32_t bdy = b->bottom.y - b->top.y;
|
||||||
int64_t adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
|
cairo_int64_t adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
|
||||||
int64_t bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
|
cairo_int64_t bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
|
||||||
|
|
||||||
/* if (adx * bdy > bdx * ady) */
|
return _cairo_int64_cmp (adx_bdy, bdx_ady);
|
||||||
if (_cairo_int64_gt (adx_bdy, bdx_ady))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* if (adx * bdy < bdx * ady) */
|
|
||||||
if (_cairo_int64_lt (adx_bdy, bdx_ady))
|
|
||||||
return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static cairo_quorem64_t
|
/*
|
||||||
edge_x_for_y (cairo_bo_edge_t *edge,
|
* We need to compare the x-coordinates of a pair of lines for a particular y,
|
||||||
int32_t y)
|
* without loss of precision.
|
||||||
|
*
|
||||||
|
* The x-coordinate along an edge for a given y is:
|
||||||
|
* X = A_x + (Y - A_y) * A_dx / A_dy
|
||||||
|
*
|
||||||
|
* So the inequality we wish to test is:
|
||||||
|
* A_x + (Y - A_y) * A_dx / A_dy -?- B_x + (Y - B_y) * B_dx / B_dy,
|
||||||
|
* where -?- is our inequality operator.
|
||||||
|
*
|
||||||
|
* By construction, we know that A_dy and B_dy (and (Y - A_y), (Y - B_y)) are
|
||||||
|
* all positive, so we can rearrange it thus without causing a sign change:
|
||||||
|
* A_dy * B_dy * (A_x - B_x) -?- (Y - B_y) * B_dx * A_dy
|
||||||
|
* - (Y - A_y) * A_dx * B_dy
|
||||||
|
*
|
||||||
|
* Given the assumption that all the deltas fit within 32 bits, we can compute
|
||||||
|
* this comparison directly using 128 bit arithmetic.
|
||||||
|
*
|
||||||
|
* (And put the burden of the work on developing fast 128 bit ops, which are
|
||||||
|
* required throughout the tessellator.)
|
||||||
|
*
|
||||||
|
* See the similar discussion for _slope_compare().
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
edges_compare_x_for_y_general (const cairo_bo_edge_t *a,
|
||||||
|
const cairo_bo_edge_t *b,
|
||||||
|
int32_t y)
|
||||||
{
|
{
|
||||||
/* XXX: We're assuming here that dx and dy will still fit in 32
|
/* XXX: We're assuming here that dx and dy will still fit in 32
|
||||||
* bits. That's not true in general as there could be overflow. We
|
* bits. That's not true in general as there could be overflow. We
|
||||||
* should prevent that before the tessellation algorithm
|
* should prevent that before the tessellation algorithm
|
||||||
* begins.
|
* begins.
|
||||||
*/
|
*/
|
||||||
int32_t dx = edge->bottom.x - edge->top.x;
|
int32_t adx, ady;
|
||||||
int32_t dy = edge->bottom.y - edge->top.y;
|
int32_t bdx, bdy;
|
||||||
int64_t numerator;
|
cairo_int128_t L, R;
|
||||||
cairo_quorem64_t quorem;
|
|
||||||
|
|
||||||
if (edge->middle.y == y) {
|
adx = a->bottom.x - a->top.x;
|
||||||
quorem.quo = edge->middle.x;
|
ady = a->bottom.y - a->top.y;
|
||||||
quorem.rem = 0;
|
|
||||||
return quorem;
|
|
||||||
}
|
|
||||||
if (edge->bottom.y == y) {
|
|
||||||
quorem.quo = edge->bottom.x;
|
|
||||||
quorem.rem = 0;
|
|
||||||
return quorem;
|
|
||||||
}
|
|
||||||
if (dy == 0) {
|
|
||||||
quorem.quo = _cairo_int32_to_int64 (edge->top.x);
|
|
||||||
quorem.rem = 0;
|
|
||||||
return quorem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* edge->top.x + (y - edge->top.y) * dx / dy */
|
bdx = b->bottom.x - b->top.x;
|
||||||
numerator = _cairo_int32x32_64_mul ((y - edge->top.y), dx);
|
bdy = b->bottom.y - b->top.y;
|
||||||
quorem = _cairo_int64_divrem (numerator, dy);
|
|
||||||
quorem.quo += edge->top.x;
|
|
||||||
|
|
||||||
return quorem;
|
L = _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (ady, bdy),
|
||||||
|
a->top.x - b->top.x);
|
||||||
|
|
||||||
|
R = _cairo_int128_sub (_cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx,
|
||||||
|
ady),
|
||||||
|
y - b->top.y),
|
||||||
|
_cairo_int64x32_128_mul (_cairo_int32x32_64_mul (adx,
|
||||||
|
bdy),
|
||||||
|
y - a->top.y));
|
||||||
|
|
||||||
|
/* return _cairo_int128_cmp (L, R); */
|
||||||
|
if (_cairo_int128_lt (L, R))
|
||||||
|
return -1;
|
||||||
|
if (_cairo_int128_gt (L, R))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to compare the x-coordinate of a line for a particular y wrt to a
|
||||||
|
* given x, without loss of precision.
|
||||||
|
*
|
||||||
|
* The x-coordinate along an edge for a given y is:
|
||||||
|
* X = A_x + (Y - A_y) * A_dx / A_dy
|
||||||
|
*
|
||||||
|
* So the inequality we wish to test is:
|
||||||
|
* A_x + (Y - A_y) * A_dx / A_dy -?- X
|
||||||
|
* where -?- is our inequality operator.
|
||||||
|
*
|
||||||
|
* By construction, we know that A_dy (and (Y - A_y)) are
|
||||||
|
* all positive, so we can rearrange it thus without causing a sign change:
|
||||||
|
* (Y - A_y) * A_dx -?- (X - A_x) * A_dy
|
||||||
|
*
|
||||||
|
* Given the assumption that all the deltas fit within 32 bits, we can compute
|
||||||
|
* this comparison directly using 64 bit arithmetic.
|
||||||
|
*
|
||||||
|
* See the similar discussion for _slope_compare() and
|
||||||
|
* edges_compare_x_for_y_general().
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
edge_compare_for_y_against_x (const cairo_bo_edge_t *a,
|
||||||
|
int32_t y,
|
||||||
|
int32_t x)
|
||||||
|
{
|
||||||
|
int32_t adx, ady;
|
||||||
|
int32_t dx, dy;
|
||||||
|
cairo_int64_t L, R;
|
||||||
|
|
||||||
|
adx = a->bottom.x - a->top.x;
|
||||||
|
ady = a->bottom.y - a->top.y;
|
||||||
|
|
||||||
|
dy = y - a->top.y;
|
||||||
|
dx = x - a->top.x;
|
||||||
|
|
||||||
|
L = _cairo_int32x32_64_mul (dy, adx);
|
||||||
|
R = _cairo_int32x32_64_mul (dx, ady);
|
||||||
|
|
||||||
|
return _cairo_int64_cmp (L, R);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
edges_compare_x_for_y (const cairo_bo_edge_t *a,
|
||||||
|
const cairo_bo_edge_t *b,
|
||||||
|
int32_t y)
|
||||||
|
{
|
||||||
|
/* If the sweep-line is currently on an end-point of a line,
|
||||||
|
* then we know its precise x value (and considering that we often need to
|
||||||
|
* compare events at end-points, this happens frequently enough to warrant
|
||||||
|
* special casing).
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
HAVE_NEITHER = 0x0,
|
||||||
|
HAVE_AX = 0x1,
|
||||||
|
HAVE_BX = 0x2,
|
||||||
|
HAVE_BOTH = HAVE_AX | HAVE_BX
|
||||||
|
} have_ax_bx = HAVE_BOTH;
|
||||||
|
int32_t ax, bx;
|
||||||
|
|
||||||
|
if (y == a->top.y)
|
||||||
|
ax = a->top.x;
|
||||||
|
else if (y == a->bottom.y)
|
||||||
|
ax = a->bottom.x;
|
||||||
|
else
|
||||||
|
have_ax_bx &= ~HAVE_AX;
|
||||||
|
|
||||||
|
if (y == b->top.y)
|
||||||
|
bx = b->top.x;
|
||||||
|
else if (y == b->bottom.y)
|
||||||
|
bx = b->bottom.x;
|
||||||
|
else
|
||||||
|
have_ax_bx &= ~HAVE_BX;
|
||||||
|
|
||||||
|
switch (have_ax_bx) {
|
||||||
|
default:
|
||||||
|
case HAVE_NEITHER:
|
||||||
|
return edges_compare_x_for_y_general (a, b, y);
|
||||||
|
case HAVE_AX:
|
||||||
|
return - edge_compare_for_y_against_x (b, y, ax);
|
||||||
|
case HAVE_BX:
|
||||||
|
return edge_compare_for_y_against_x (a, y, bx);
|
||||||
|
case HAVE_BOTH:
|
||||||
|
return ax - bx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -259,8 +365,6 @@ _cairo_bo_sweep_line_compare_edges (cairo_bo_sweep_line_t *sweep_line,
|
||||||
cairo_bo_edge_t *a,
|
cairo_bo_edge_t *a,
|
||||||
cairo_bo_edge_t *b)
|
cairo_bo_edge_t *b)
|
||||||
{
|
{
|
||||||
cairo_quorem64_t ax;
|
|
||||||
cairo_quorem64_t bx;
|
|
||||||
int cmp;
|
int cmp;
|
||||||
|
|
||||||
if (a == b)
|
if (a == b)
|
||||||
|
@ -289,18 +393,9 @@ _cairo_bo_sweep_line_compare_edges (cairo_bo_sweep_line_t *sweep_line,
|
||||||
if (amin > bmax) return +1;
|
if (amin > bmax) return +1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ax = edge_x_for_y (a, sweep_line->current_y);
|
cmp = edges_compare_x_for_y (a, b, sweep_line->current_y);
|
||||||
bx = edge_x_for_y (b, sweep_line->current_y);
|
if (cmp)
|
||||||
if (ax.quo > bx.quo)
|
return cmp;
|
||||||
return 1;
|
|
||||||
else if (ax.quo < bx.quo)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* Quotients are identical, test remainder. */
|
|
||||||
if (ax.rem > bx.rem)
|
|
||||||
return 1;
|
|
||||||
else if (ax.rem < bx.rem)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* The two edges intersect exactly at y, so fall back on slope
|
/* The two edges intersect exactly at y, so fall back on slope
|
||||||
* comparison. We know that this compare_edges function will be
|
* comparison. We know that this compare_edges function will be
|
||||||
|
@ -489,17 +584,17 @@ det32_64 (int32_t a,
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline cairo_int128_t
|
static inline cairo_int128_t
|
||||||
det64_128 (cairo_int64_t a,
|
det64x32_128 (cairo_int64_t a,
|
||||||
cairo_int64_t b,
|
int32_t b,
|
||||||
cairo_int64_t c,
|
cairo_int64_t c,
|
||||||
cairo_int64_t d)
|
int32_t d)
|
||||||
{
|
{
|
||||||
cairo_int128_t ad;
|
cairo_int128_t ad;
|
||||||
cairo_int128_t bc;
|
cairo_int128_t bc;
|
||||||
|
|
||||||
/* det = a * d - b * c */
|
/* det = a * d - b * c */
|
||||||
ad = _cairo_int64x64_128_mul (a, d);
|
ad = _cairo_int64x32_128_mul (a, d);
|
||||||
bc = _cairo_int64x64_128_mul (b, c);
|
bc = _cairo_int64x32_128_mul (c, b);
|
||||||
|
|
||||||
return _cairo_int128_sub (ad, bc);
|
return _cairo_int128_sub (ad, bc);
|
||||||
}
|
}
|
||||||
|
@ -532,7 +627,7 @@ intersect_lines (cairo_bo_edge_t *a,
|
||||||
cairo_int64_t den_det = det32_64 (dx1, dy1, dx2, dy2);
|
cairo_int64_t den_det = det32_64 (dx1, dy1, dx2, dy2);
|
||||||
cairo_quorem64_t qr;
|
cairo_quorem64_t qr;
|
||||||
|
|
||||||
if (_cairo_int64_eq (den_det, 0))
|
if (_cairo_int64_is_zero (den_det))
|
||||||
return CAIRO_BO_STATUS_PARALLEL;
|
return CAIRO_BO_STATUS_PARALLEL;
|
||||||
|
|
||||||
a_det = det32_64 (a->top.x, a->top.y,
|
a_det = det32_64 (a->top.x, a->top.y,
|
||||||
|
@ -541,22 +636,22 @@ intersect_lines (cairo_bo_edge_t *a,
|
||||||
b->bottom.x, b->bottom.y);
|
b->bottom.x, b->bottom.y);
|
||||||
|
|
||||||
/* x = det (a_det, dx1, b_det, dx2) / den_det */
|
/* x = det (a_det, dx1, b_det, dx2) / den_det */
|
||||||
qr = _cairo_int_96by64_32x64_divrem (det64_128 (a_det, dx1,
|
qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dx1,
|
||||||
b_det, dx2),
|
b_det, dx2),
|
||||||
den_det);
|
|
||||||
if (_cairo_int64_eq (qr.rem,den_det))
|
|
||||||
return CAIRO_BO_STATUS_NO_INTERSECTION;
|
|
||||||
intersection->x.ordinate = qr.quo;
|
|
||||||
intersection->x.exactness = qr.rem ? INEXACT : EXACT;
|
|
||||||
|
|
||||||
/* y = det (a_det, dy1, b_det, dy2) / den_det */
|
|
||||||
qr = _cairo_int_96by64_32x64_divrem (det64_128 (a_det, dy1,
|
|
||||||
b_det, dy2),
|
|
||||||
den_det);
|
den_det);
|
||||||
if (_cairo_int64_eq (qr.rem, den_det))
|
if (_cairo_int64_eq (qr.rem, den_det))
|
||||||
return CAIRO_BO_STATUS_NO_INTERSECTION;
|
return CAIRO_BO_STATUS_NO_INTERSECTION;
|
||||||
intersection->y.ordinate = qr.quo;
|
intersection->x.ordinate = _cairo_int64_to_int32 (qr.quo);
|
||||||
intersection->y.exactness = qr.rem ? INEXACT : EXACT;
|
intersection->x.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT;
|
||||||
|
|
||||||
|
/* y = det (a_det, dy1, b_det, dy2) / den_det */
|
||||||
|
qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dy1,
|
||||||
|
b_det, dy2),
|
||||||
|
den_det);
|
||||||
|
if (_cairo_int64_eq (qr.rem, den_det))
|
||||||
|
return CAIRO_BO_STATUS_NO_INTERSECTION;
|
||||||
|
intersection->y.ordinate = _cairo_int64_to_int32 (qr.quo);
|
||||||
|
intersection->y.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT;
|
||||||
|
|
||||||
return CAIRO_BO_STATUS_INTERSECTION;
|
return CAIRO_BO_STATUS_INTERSECTION;
|
||||||
}
|
}
|
||||||
|
@ -941,7 +1036,6 @@ _cairo_bo_sweep_line_swap (cairo_bo_sweep_line_t *sweep_line,
|
||||||
left->prev = right;
|
left->prev = right;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEBUG_PRINT_STATE 0
|
|
||||||
#if DEBUG_PRINT_STATE
|
#if DEBUG_PRINT_STATE
|
||||||
static void
|
static void
|
||||||
_cairo_bo_edge_print (cairo_bo_edge_t *edge)
|
_cairo_bo_edge_print (cairo_bo_edge_t *edge)
|
||||||
|
@ -1078,35 +1172,35 @@ _cairo_bo_edge_end_trap (cairo_bo_edge_t *left,
|
||||||
|
|
||||||
/* Only emit trapezoids with positive height. */
|
/* Only emit trapezoids with positive height. */
|
||||||
if (fixed_top < fixed_bot) {
|
if (fixed_top < fixed_bot) {
|
||||||
cairo_point_t left_top, left_bot, right_top, right_bot;
|
cairo_line_t left_line;
|
||||||
|
cairo_line_t right_line;
|
||||||
cairo_fixed_t xmin = bo_traps->xmin;
|
cairo_fixed_t xmin = bo_traps->xmin;
|
||||||
cairo_fixed_t ymin = bo_traps->ymin;
|
cairo_fixed_t ymin = bo_traps->ymin;
|
||||||
fixed_top += ymin;
|
fixed_top += ymin;
|
||||||
fixed_bot += ymin;
|
fixed_bot += ymin;
|
||||||
|
|
||||||
left_top.x = left->top.x + xmin;
|
left_line.p1.x = left->top.x + xmin;
|
||||||
left_top.y = left->top.y + ymin;
|
left_line.p1.y = left->top.y + ymin;
|
||||||
right_top.x = right->top.x + xmin;
|
right_line.p1.x = right->top.x + xmin;
|
||||||
right_top.y = right->top.y + ymin;
|
right_line.p1.y = right->top.y + ymin;
|
||||||
left_bot.x = left->bottom.x + xmin;
|
|
||||||
left_bot.y = left->bottom.y + ymin;
|
left_line.p2.x = left->bottom.x + xmin;
|
||||||
right_bot.x = right->bottom.x + xmin;
|
left_line.p2.y = left->bottom.y + ymin;
|
||||||
right_bot.y = right->bottom.y + ymin;
|
right_line.p2.x = right->bottom.x + xmin;
|
||||||
|
right_line.p2.y = right->bottom.y + ymin;
|
||||||
|
|
||||||
/* Avoid emitting the trapezoid if it is obviously degenerate.
|
/* Avoid emitting the trapezoid if it is obviously degenerate.
|
||||||
* TODO: need a real collinearity test here for the cases
|
* TODO: need a real collinearity test here for the cases
|
||||||
* where the trapezoid is degenerate, yet the top and bottom
|
* where the trapezoid is degenerate, yet the top and bottom
|
||||||
* coordinates aren't equal. */
|
* coordinates aren't equal. */
|
||||||
if (left_top.x != right_top.x ||
|
if (left_line.p1.x != right_line.p1.x ||
|
||||||
left_top.y != right_top.y ||
|
left_line.p1.y != right_line.p1.y ||
|
||||||
left_bot.x != right_bot.x ||
|
left_line.p2.x != right_line.p2.x ||
|
||||||
left_bot.y != right_bot.y)
|
left_line.p2.y != right_line.p2.y)
|
||||||
{
|
{
|
||||||
_cairo_traps_add_trap_from_points (bo_traps->traps,
|
_cairo_traps_add_trap (bo_traps->traps,
|
||||||
fixed_top,
|
fixed_top, fixed_bot,
|
||||||
fixed_bot,
|
&left_line, &right_line);
|
||||||
left_top, left_bot,
|
|
||||||
right_top, right_bot);
|
|
||||||
|
|
||||||
#if DEBUG_PRINT_STATE
|
#if DEBUG_PRINT_STATE
|
||||||
printf ("Deferred trap: left=(%08x, %08x)-(%08x,%08x) "
|
printf ("Deferred trap: left=(%08x, %08x)-(%08x,%08x) "
|
||||||
|
@ -1177,6 +1271,7 @@ _cairo_bo_traps_fini (cairo_bo_traps_t *bo_traps)
|
||||||
_cairo_freelist_fini (&bo_traps->freelist);
|
_cairo_freelist_fini (&bo_traps->freelist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG_VALIDATE
|
||||||
static void
|
static void
|
||||||
_cairo_bo_sweep_line_validate (cairo_bo_sweep_line_t *sweep_line)
|
_cairo_bo_sweep_line_validate (cairo_bo_sweep_line_t *sweep_line)
|
||||||
{
|
{
|
||||||
|
@ -1193,15 +1288,16 @@ _cairo_bo_sweep_line_validate (cairo_bo_sweep_line_t *sweep_line)
|
||||||
{
|
{
|
||||||
if (SKIP_ELT_TO_EDGE (elt) != edge) {
|
if (SKIP_ELT_TO_EDGE (elt) != edge) {
|
||||||
fprintf (stderr, "*** Error: Sweep line fails to validate: Inconsistent data in the two lists.\n");
|
fprintf (stderr, "*** Error: Sweep line fails to validate: Inconsistent data in the two lists.\n");
|
||||||
exit (1);
|
abort ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (edge || elt) {
|
if (edge || elt) {
|
||||||
fprintf (stderr, "*** Error: Sweep line fails to validate: One list ran out before the other.\n");
|
fprintf (stderr, "*** Error: Sweep line fails to validate: One list ran out before the other.\n");
|
||||||
exit (1);
|
abort ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static cairo_status_t
|
static cairo_status_t
|
||||||
|
@ -1324,9 +1420,8 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
|
||||||
#if DEBUG_PRINT_STATE
|
#if DEBUG_PRINT_STATE
|
||||||
print_state ("After processing start", &event_queue, &sweep_line);
|
print_state ("After processing start", &event_queue, &sweep_line);
|
||||||
#endif
|
#endif
|
||||||
_cairo_bo_sweep_line_validate (&sweep_line);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CAIRO_BO_EVENT_TYPE_STOP:
|
case CAIRO_BO_EVENT_TYPE_STOP:
|
||||||
edge = event->e1;
|
edge = event->e1;
|
||||||
|
|
||||||
|
@ -1346,9 +1441,8 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
|
||||||
#if DEBUG_PRINT_STATE
|
#if DEBUG_PRINT_STATE
|
||||||
print_state ("After processing stop", &event_queue, &sweep_line);
|
print_state ("After processing stop", &event_queue, &sweep_line);
|
||||||
#endif
|
#endif
|
||||||
_cairo_bo_sweep_line_validate (&sweep_line);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CAIRO_BO_EVENT_TYPE_INTERSECTION:
|
case CAIRO_BO_EVENT_TYPE_INTERSECTION:
|
||||||
edge1 = event->e1;
|
edge1 = event->e1;
|
||||||
edge2 = event->e2;
|
edge2 = event->e2;
|
||||||
|
@ -1382,10 +1476,11 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
|
||||||
#if DEBUG_PRINT_STATE
|
#if DEBUG_PRINT_STATE
|
||||||
print_state ("After processing intersection", &event_queue, &sweep_line);
|
print_state ("After processing intersection", &event_queue, &sweep_line);
|
||||||
#endif
|
#endif
|
||||||
_cairo_bo_sweep_line_validate (&sweep_line);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#if DEBUG_VALIDATE
|
||||||
|
_cairo_bo_sweep_line_validate (&sweep_line);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
*num_intersections = intersection_count;
|
*num_intersections = intersection_count;
|
||||||
|
@ -1427,12 +1522,16 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
|
||||||
cairo_fixed_t ymin = 0x7FFFFFFF;
|
cairo_fixed_t ymin = 0x7FFFFFFF;
|
||||||
cairo_fixed_t xmax = -0x80000000;
|
cairo_fixed_t xmax = -0x80000000;
|
||||||
cairo_fixed_t ymax = -0x80000000;
|
cairo_fixed_t ymax = -0x80000000;
|
||||||
|
cairo_box_t limit;
|
||||||
|
cairo_bool_t has_limits;
|
||||||
int num_bo_edges;
|
int num_bo_edges;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (0 == polygon->num_edges)
|
if (0 == polygon->num_edges)
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
has_limits = _cairo_traps_get_limit (traps, &limit);
|
||||||
|
|
||||||
if (polygon->num_edges < ARRAY_LENGTH (stack_edges)) {
|
if (polygon->num_edges < ARRAY_LENGTH (stack_edges)) {
|
||||||
edges = stack_edges;
|
edges = stack_edges;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1471,6 +1570,13 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
|
||||||
cairo_point_t top = polygon->edges[i].edge.p1;
|
cairo_point_t top = polygon->edges[i].edge.p1;
|
||||||
cairo_point_t bot = polygon->edges[i].edge.p2;
|
cairo_point_t bot = polygon->edges[i].edge.p2;
|
||||||
|
|
||||||
|
/* Discard the edge if it lies outside the limits of traps. */
|
||||||
|
if (has_limits) {
|
||||||
|
/* Strictly above or below the limits? */
|
||||||
|
if (bot.y <= limit.p1.y || top.y >= limit.p2.y)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Offset coordinates into the non-negative range. */
|
/* Offset coordinates into the non-negative range. */
|
||||||
top.x -= xmin;
|
top.x -= xmin;
|
||||||
top.y -= ymin;
|
top.y -= ymin;
|
||||||
|
|
|
@ -92,6 +92,7 @@ _cairo_cache_fini (cairo_cache_t *cache)
|
||||||
* @keys_equal: a function to return %TRUE if two keys are equal
|
* @keys_equal: a function to return %TRUE if two keys are equal
|
||||||
* @entry_destroy: destroy notifier for cache entries
|
* @entry_destroy: destroy notifier for cache entries
|
||||||
* @max_size: the maximum size for this cache
|
* @max_size: the maximum size for this cache
|
||||||
|
* Returns: the newly created #cairo_cache_t
|
||||||
*
|
*
|
||||||
* Creates a new cache using the keys_equal() function to determine
|
* Creates a new cache using the keys_equal() function to determine
|
||||||
* the equality of entries.
|
* the equality of entries.
|
||||||
|
@ -119,8 +120,6 @@ _cairo_cache_fini (cairo_cache_t *cache)
|
||||||
* _cairo_cache_freeze() and _cairo_cache_thaw() calls can be
|
* _cairo_cache_freeze() and _cairo_cache_thaw() calls can be
|
||||||
* used to establish a window during which no automatic removal of
|
* used to establish a window during which no automatic removal of
|
||||||
* entries will occur.
|
* entries will occur.
|
||||||
*
|
|
||||||
* Return value:
|
|
||||||
**/
|
**/
|
||||||
cairo_cache_t *
|
cairo_cache_t *
|
||||||
_cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal,
|
_cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal,
|
||||||
|
|
|
@ -148,7 +148,10 @@ _cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t *clip_path,
|
||||||
cairo_box_t extents;
|
cairo_box_t extents;
|
||||||
cairo_rectangle_int_t extents_rect;
|
cairo_rectangle_int_t extents_rect;
|
||||||
|
|
||||||
|
_cairo_box_from_rectangle (&extents, rectangle);
|
||||||
|
|
||||||
_cairo_traps_init (&traps);
|
_cairo_traps_init (&traps);
|
||||||
|
_cairo_traps_limit (&traps, &extents);
|
||||||
|
|
||||||
status = _cairo_path_fixed_fill_to_traps (&clip_path->path,
|
status = _cairo_path_fixed_fill_to_traps (&clip_path->path,
|
||||||
clip_path->fill_rule,
|
clip_path->fill_rule,
|
||||||
|
@ -160,11 +163,11 @@ _cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t *clip_path,
|
||||||
}
|
}
|
||||||
|
|
||||||
_cairo_traps_extents (&traps, &extents);
|
_cairo_traps_extents (&traps, &extents);
|
||||||
|
_cairo_traps_fini (&traps);
|
||||||
|
|
||||||
_cairo_box_round_to_rectangle (&extents, &extents_rect);
|
_cairo_box_round_to_rectangle (&extents, &extents_rect);
|
||||||
_cairo_rectangle_intersect (rectangle, &extents_rect);
|
_cairo_rectangle_intersect (rectangle, &extents_rect);
|
||||||
|
|
||||||
_cairo_traps_fini (&traps);
|
|
||||||
|
|
||||||
clip_path = clip_path->prev;
|
clip_path = clip_path->prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,9 +439,8 @@ _cairo_clip_intersect_mask (cairo_clip_t *clip,
|
||||||
|
|
||||||
/* Intersect with the target surface rectangle so we don't use
|
/* Intersect with the target surface rectangle so we don't use
|
||||||
* more memory and time than we need to. */
|
* more memory and time than we need to. */
|
||||||
|
|
||||||
status = _cairo_surface_get_extents (target, &target_rect);
|
status = _cairo_surface_get_extents (target, &target_rect);
|
||||||
if (!status)
|
if (status == CAIRO_STATUS_SUCCESS)
|
||||||
_cairo_rectangle_intersect (&surface_rect, &target_rect);
|
_cairo_rectangle_intersect (&surface_rect, &target_rect);
|
||||||
|
|
||||||
if (surface_rect.width == 0 || surface_rect.height == 0) {
|
if (surface_rect.width == 0 || surface_rect.height == 0) {
|
||||||
|
@ -561,6 +563,7 @@ _cairo_clip_clip (cairo_clip_t *clip,
|
||||||
cairo_surface_t *target)
|
cairo_surface_t *target)
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
cairo_rectangle_int_t rectangle;
|
||||||
cairo_traps_t traps;
|
cairo_traps_t traps;
|
||||||
|
|
||||||
if (clip->all_clipped)
|
if (clip->all_clipped)
|
||||||
|
@ -582,6 +585,17 @@ _cairo_clip_clip (cairo_clip_t *clip,
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
_cairo_traps_init (&traps);
|
_cairo_traps_init (&traps);
|
||||||
|
|
||||||
|
/* Limit the traps to the target surface
|
||||||
|
* - so we don't add more traps than needed. */
|
||||||
|
status = _cairo_surface_get_extents (target, &rectangle);
|
||||||
|
if (status == CAIRO_STATUS_SUCCESS) {
|
||||||
|
cairo_box_t box;
|
||||||
|
|
||||||
|
_cairo_box_from_rectangle (&box, &rectangle);
|
||||||
|
_cairo_traps_limit (&traps, &box);
|
||||||
|
}
|
||||||
|
|
||||||
status = _cairo_path_fixed_fill_to_traps (path,
|
status = _cairo_path_fixed_fill_to_traps (path,
|
||||||
fill_rule,
|
fill_rule,
|
||||||
tolerance,
|
tolerance,
|
||||||
|
@ -676,16 +690,22 @@ _cairo_clip_init_deep_copy (cairo_clip_t *clip,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (other->surface) {
|
if (other->surface) {
|
||||||
|
int dx, dy;
|
||||||
status = _cairo_surface_clone_similar (target, other->surface,
|
status = _cairo_surface_clone_similar (target, other->surface,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
other->surface_rect.width,
|
other->surface_rect.width,
|
||||||
other->surface_rect.height,
|
other->surface_rect.height,
|
||||||
|
&dx, &dy,
|
||||||
&clip->surface);
|
&clip->surface);
|
||||||
if (status)
|
if (status)
|
||||||
goto BAIL;
|
goto BAIL;
|
||||||
|
|
||||||
clip->surface_rect = other->surface_rect;
|
clip->surface_rect = other->surface_rect;
|
||||||
|
|
||||||
|
/* src offset was 0, so we expect an exact replica of the surface */
|
||||||
|
assert (dx == 0);
|
||||||
|
assert (dy == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (other->path) {
|
if (other->path) {
|
||||||
|
|
|
@ -165,6 +165,9 @@ cairo_bool_t
|
||||||
_cairo_color_equal (const cairo_color_t *color_a,
|
_cairo_color_equal (const cairo_color_t *color_a,
|
||||||
const cairo_color_t *color_b)
|
const cairo_color_t *color_b)
|
||||||
{
|
{
|
||||||
|
if (color_a == color_b)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
return color_a->red_short == color_b->red_short &&
|
return color_a->red_short == color_b->red_short &&
|
||||||
color_a->green_short == color_b->green_short &&
|
color_a->green_short == color_b->green_short &&
|
||||||
color_a->blue_short == color_b->blue_short &&
|
color_a->blue_short == color_b->blue_short &&
|
||||||
|
|
|
@ -38,6 +38,8 @@
|
||||||
#ifndef CAIRO_COMPILER_PRIVATE_H
|
#ifndef CAIRO_COMPILER_PRIVATE_H
|
||||||
#define CAIRO_COMPILER_PRIVATE_H
|
#define CAIRO_COMPILER_PRIVATE_H
|
||||||
|
|
||||||
|
#include "cairo.h"
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
#if HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -109,6 +111,34 @@
|
||||||
# define CAIRO_FUNCTION_ALIAS(old, new)
|
# define CAIRO_FUNCTION_ALIAS(old, new)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cairo uses the following function attributes in order to improve the
|
||||||
|
* generated code (effectively by manual inter-procedural analysis).
|
||||||
|
*
|
||||||
|
* 'cairo_pure': The function is only allowed to read from its arguments
|
||||||
|
* and global memory (i.e. following a pointer argument or
|
||||||
|
* accessing a shared variable). The return value should
|
||||||
|
* only depend on its arguments, and for an identical set of
|
||||||
|
* arguments should return the same value.
|
||||||
|
*
|
||||||
|
* 'cairo_const': The function is only allowed to read from its arguments.
|
||||||
|
* It is not allowed to access global memory. The return
|
||||||
|
* value should only depend its arguments, and for an
|
||||||
|
* identical set of arguments should return the same value.
|
||||||
|
* This is currently the most strict function attribute.
|
||||||
|
*
|
||||||
|
* Both these function attributes allow gcc to perform CSE and
|
||||||
|
* constant-folding, with 'cairo_const 'also guaranteeing that pointer contents
|
||||||
|
* do not change across the function call.
|
||||||
|
*/
|
||||||
|
#if __GNUC__ >= 3
|
||||||
|
#define cairo_pure __attribute__((pure))
|
||||||
|
#define cairo_const __attribute__((const))
|
||||||
|
#else
|
||||||
|
#define cairo_pure
|
||||||
|
#define cairo_const
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef __GNUC__
|
#ifndef __GNUC__
|
||||||
#undef __attribute__
|
#undef __attribute__
|
||||||
#define __attribute__(x)
|
#define __attribute__(x)
|
||||||
|
@ -116,6 +146,7 @@
|
||||||
|
|
||||||
#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
|
#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
|
#define popen _popen
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -49,7 +49,7 @@
|
||||||
|
|
||||||
#include "cairo.h"
|
#include "cairo.h"
|
||||||
|
|
||||||
#ifdef CAIRO_HAS_DIRECTFB_SURFACE
|
#if CAIRO_HAS_DIRECTFB_SURFACE
|
||||||
|
|
||||||
#include <directfb.h>
|
#include <directfb.h>
|
||||||
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
#ifndef CAIRO_FEATURES_H
|
|
||||||
#define CAIRO_FEATURES_H
|
|
||||||
|
|
||||||
#define HAVE_WINDOWS_H 1
|
|
||||||
|
|
||||||
#define CAIRO_HAS_SVG_SURFACE 1
|
|
||||||
#define CAIRO_HAS_PDF_SURFACE 1
|
|
||||||
#define CAIRO_HAS_PS_SURFACE 1
|
|
||||||
#define CAIRO_HAS_WIN32_SURFACE 1
|
|
||||||
#define CAIRO_HAS_WIN32_FONT 1
|
|
||||||
#define CAIRO_HAS_PNG_FUNCTIONS 1
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,209 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2004 Keith Packard
|
||||||
|
* Copyright © 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it either under the terms of the GNU Lesser General Public
|
||||||
|
* License version 2.1 as published by the Free Software Foundation
|
||||||
|
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||||
|
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||||
|
* notice, a recipient may use your version of this file under either
|
||||||
|
* the MPL or the LGPL.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the LGPL along with this library
|
||||||
|
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
* You should have received a copy of the MPL along with this library
|
||||||
|
* in the file COPYING-MPL-1.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License
|
||||||
|
* Version 1.1 (the "License"); you may not use this file except in
|
||||||
|
* compliance with the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||||
|
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||||
|
* the specific language governing rights and limitations.
|
||||||
|
*
|
||||||
|
* The Original Code is the cairo graphics library.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Keith Packard
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Keith Packard <keithp@keithp.com>
|
||||||
|
* Behdad Esfahbod <behdad@behdad.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cairoint.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file implements a user-font rendering the decendant of the Hershey
|
||||||
|
* font coded by Keith Packard for use in the Twin window system.
|
||||||
|
* The actual font data is in cairo-font-face-twin-data.c
|
||||||
|
*
|
||||||
|
* Ported to cairo user font by Behdad Esfahbod.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define twin_glyph_left(g) ((g)[0])
|
||||||
|
#define twin_glyph_right(g) ((g)[1])
|
||||||
|
#define twin_glyph_ascent(g) ((g)[2])
|
||||||
|
#define twin_glyph_descent(g) ((g)[3])
|
||||||
|
|
||||||
|
#define twin_glyph_n_snap_x(g) ((g)[4])
|
||||||
|
#define twin_glyph_n_snap_y(g) ((g)[5])
|
||||||
|
#define twin_glyph_snap_x(g) (&g[6])
|
||||||
|
#define twin_glyph_snap_y(g) (twin_glyph_snap_x(g) + twin_glyph_n_snap_x(g))
|
||||||
|
#define twin_glyph_draw(g) (twin_glyph_snap_y(g) + twin_glyph_n_snap_y(g))
|
||||||
|
|
||||||
|
#define SNAPI(p) (p)
|
||||||
|
#define SNAPH(p) (p)
|
||||||
|
|
||||||
|
#define FX(g) ((g) / 64.)
|
||||||
|
#define FY(g) ((g) / 64.)
|
||||||
|
|
||||||
|
|
||||||
|
static cairo_status_t
|
||||||
|
twin_scaled_font_init (cairo_scaled_font_t *scaled_font,
|
||||||
|
cairo_t *cr,
|
||||||
|
cairo_font_extents_t *metrics)
|
||||||
|
{
|
||||||
|
metrics->ascent = FY (50);
|
||||||
|
metrics->descent = FY (14);
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cairo_status_t
|
||||||
|
twin_scaled_font_unicode_to_glyph (cairo_scaled_font_t *scaled_font,
|
||||||
|
unsigned long unicode,
|
||||||
|
unsigned long *glyph)
|
||||||
|
{
|
||||||
|
/* We use an identity charmap. Which means we could live
|
||||||
|
* with no unicode_to_glyph method too. But we define this
|
||||||
|
* to map all unknown chars to a single unknown glyph to
|
||||||
|
* reduce pressure on cache. */
|
||||||
|
|
||||||
|
if (unicode < ARRAY_LENGTH (_cairo_twin_charmap))
|
||||||
|
*glyph = unicode;
|
||||||
|
else
|
||||||
|
*glyph = 0;
|
||||||
|
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SNAPX(p) _twin_snap (p, info.snap_x, info.n_snap_x)
|
||||||
|
#define SNAPY(p) _twin_snap (p, info.snap_y, info.n_snap_y)
|
||||||
|
|
||||||
|
static double
|
||||||
|
_twin_snap (double v, int a, int b)
|
||||||
|
{
|
||||||
|
return v; /* XXX */
|
||||||
|
}
|
||||||
|
|
||||||
|
static cairo_status_t
|
||||||
|
twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
|
||||||
|
unsigned long glyph,
|
||||||
|
cairo_t *cr,
|
||||||
|
cairo_text_extents_t *metrics)
|
||||||
|
{
|
||||||
|
double x1, y1, x2, y2, x3, y3;
|
||||||
|
const int8_t *b = _cairo_twin_outlines +
|
||||||
|
_cairo_twin_charmap[glyph >= ARRAY_LENGTH (_cairo_twin_charmap) ? 0 : glyph];
|
||||||
|
const int8_t *g = twin_glyph_draw(b);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
cairo_bool_t snap;
|
||||||
|
int snap_x;
|
||||||
|
int snap_y;
|
||||||
|
int n_snap_x;
|
||||||
|
int n_snap_y;
|
||||||
|
} info = {FALSE};
|
||||||
|
|
||||||
|
cairo_set_line_width (cr, 0.06);
|
||||||
|
cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
|
||||||
|
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
switch (*g++) {
|
||||||
|
case 'M':
|
||||||
|
cairo_close_path (cr);
|
||||||
|
/* fall through */
|
||||||
|
case 'm':
|
||||||
|
x1 = FX(*g++);
|
||||||
|
y1 = FY(*g++);
|
||||||
|
if (info.snap)
|
||||||
|
{
|
||||||
|
x1 = SNAPX (x1);
|
||||||
|
y1 = SNAPY (y1);
|
||||||
|
}
|
||||||
|
cairo_move_to (cr, x1, y1);
|
||||||
|
continue;
|
||||||
|
case 'L':
|
||||||
|
cairo_close_path (cr);
|
||||||
|
/* fall through */
|
||||||
|
case 'l':
|
||||||
|
x1 = FX(*g++);
|
||||||
|
y1 = FY(*g++);
|
||||||
|
if (info.snap)
|
||||||
|
{
|
||||||
|
x1 = SNAPX (x1);
|
||||||
|
y1 = SNAPY (y1);
|
||||||
|
}
|
||||||
|
cairo_line_to (cr, x1, y1);
|
||||||
|
continue;
|
||||||
|
case 'C':
|
||||||
|
cairo_close_path (cr);
|
||||||
|
/* fall through */
|
||||||
|
case 'c':
|
||||||
|
x1 = FX(*g++);
|
||||||
|
y1 = FY(*g++);
|
||||||
|
x2 = FX(*g++);
|
||||||
|
y2 = FY(*g++);
|
||||||
|
x3 = FX(*g++);
|
||||||
|
y3 = FY(*g++);
|
||||||
|
if (info.snap)
|
||||||
|
{
|
||||||
|
x1 = SNAPX (x1);
|
||||||
|
y1 = SNAPY (y1);
|
||||||
|
x2 = SNAPX (x2);
|
||||||
|
y2 = SNAPY (y2);
|
||||||
|
x3 = SNAPX (x3);
|
||||||
|
y3 = SNAPY (y3);
|
||||||
|
}
|
||||||
|
cairo_curve_to (cr, x1, y1, x2, y2, x3, y3);
|
||||||
|
continue;
|
||||||
|
case 'E':
|
||||||
|
cairo_close_path (cr);
|
||||||
|
/* fall through */
|
||||||
|
case 'e':
|
||||||
|
cairo_stroke (cr);
|
||||||
|
break;
|
||||||
|
case 'X':
|
||||||
|
/* filler */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
metrics->x_advance = FX(twin_glyph_right(b)) + cairo_get_line_width (cr);
|
||||||
|
metrics->x_advance += cairo_get_line_width (cr)/* XXX 2*x.margin */;
|
||||||
|
if (info.snap)
|
||||||
|
metrics->x_advance = SNAPI (SNAPX (metrics->x_advance));
|
||||||
|
|
||||||
|
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_font_face_t *
|
||||||
|
_cairo_font_face_twin_create (cairo_font_slant_t slant,
|
||||||
|
cairo_font_weight_t weight)
|
||||||
|
{
|
||||||
|
cairo_font_face_t *twin_font_face;
|
||||||
|
|
||||||
|
twin_font_face = cairo_user_font_face_create ();
|
||||||
|
cairo_user_font_face_set_init_func (twin_font_face, twin_scaled_font_init);
|
||||||
|
cairo_user_font_face_set_render_glyph_func (twin_font_face, twin_scaled_font_render_glyph);
|
||||||
|
cairo_user_font_face_set_unicode_to_glyph_func (twin_font_face, twin_scaled_font_unicode_to_glyph);
|
||||||
|
|
||||||
|
return twin_font_face;
|
||||||
|
}
|
|
@ -282,6 +282,7 @@ cairo_font_face_get_user_data (cairo_font_face_t *font_face,
|
||||||
return _cairo_user_data_array_get_data (&font_face->user_data,
|
return _cairo_user_data_array_get_data (&font_face->user_data,
|
||||||
key);
|
key);
|
||||||
}
|
}
|
||||||
|
slim_hidden_def (cairo_font_face_get_user_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_font_face_set_user_data:
|
* cairo_font_face_set_user_data:
|
||||||
|
@ -306,11 +307,12 @@ cairo_font_face_set_user_data (cairo_font_face_t *font_face,
|
||||||
cairo_destroy_func_t destroy)
|
cairo_destroy_func_t destroy)
|
||||||
{
|
{
|
||||||
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
|
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
return font_face->status;
|
||||||
|
|
||||||
return _cairo_user_data_array_set_data (&font_face->user_data,
|
return _cairo_user_data_array_set_data (&font_face->user_data,
|
||||||
key, user_data, destroy);
|
key, user_data, destroy);
|
||||||
}
|
}
|
||||||
|
slim_hidden_def (cairo_font_face_set_user_data);
|
||||||
|
|
||||||
static const cairo_font_face_backend_t _cairo_toy_font_face_backend;
|
static const cairo_font_face_backend_t _cairo_toy_font_face_backend;
|
||||||
|
|
||||||
|
@ -566,6 +568,38 @@ _cairo_toy_font_face_destroy (void *abstract_face)
|
||||||
_cairo_toy_font_face_fini (font_face);
|
_cairo_toy_font_face_fini (font_face);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cairo_status_t
|
||||||
|
_cairo_toy_font_face_scaled_font_get_implementation (void *abstract_font_face,
|
||||||
|
cairo_font_face_t **font_face_out)
|
||||||
|
{
|
||||||
|
cairo_toy_font_face_t *font_face = abstract_font_face;
|
||||||
|
cairo_status_t status;
|
||||||
|
|
||||||
|
if (font_face->base.status)
|
||||||
|
return font_face->base.status;
|
||||||
|
|
||||||
|
if (CAIRO_SCALED_FONT_BACKEND_DEFAULT != &_cairo_user_scaled_font_backend)
|
||||||
|
{
|
||||||
|
const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT;
|
||||||
|
|
||||||
|
if (backend->get_implementation == NULL) {
|
||||||
|
*font_face_out = &font_face->base;
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = backend->get_implementation (font_face,
|
||||||
|
font_face_out);
|
||||||
|
|
||||||
|
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||||
|
return _cairo_font_face_set_error (&font_face->base, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = _cairo_user_scaled_font_backend.get_implementation (font_face,
|
||||||
|
font_face_out);
|
||||||
|
|
||||||
|
return _cairo_font_face_set_error (&font_face->base, status);
|
||||||
|
}
|
||||||
|
|
||||||
static cairo_status_t
|
static cairo_status_t
|
||||||
_cairo_toy_font_face_scaled_font_create (void *abstract_font_face,
|
_cairo_toy_font_face_scaled_font_create (void *abstract_font_face,
|
||||||
const cairo_matrix_t *font_matrix,
|
const cairo_matrix_t *font_matrix,
|
||||||
|
@ -574,7 +608,6 @@ _cairo_toy_font_face_scaled_font_create (void *abstract_font_face
|
||||||
cairo_scaled_font_t **scaled_font)
|
cairo_scaled_font_t **scaled_font)
|
||||||
{
|
{
|
||||||
cairo_toy_font_face_t *font_face = abstract_font_face;
|
cairo_toy_font_face_t *font_face = abstract_font_face;
|
||||||
const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT;
|
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
|
||||||
if (font_face->base.status)
|
if (font_face->base.status)
|
||||||
|
@ -584,12 +617,31 @@ _cairo_toy_font_face_scaled_font_create (void *abstract_font_face
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
return _cairo_font_face_set_error (&font_face->base,
|
if (CAIRO_SCALED_FONT_BACKEND_DEFAULT != &_cairo_user_scaled_font_backend)
|
||||||
backend->create_toy (font_face,
|
{
|
||||||
font_matrix,
|
const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT;
|
||||||
ctm,
|
|
||||||
options,
|
*scaled_font = NULL;
|
||||||
scaled_font));
|
status = backend->create_toy (font_face,
|
||||||
|
font_matrix,
|
||||||
|
ctm,
|
||||||
|
options,
|
||||||
|
scaled_font);
|
||||||
|
|
||||||
|
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||||
|
return _cairo_font_face_set_error (&font_face->base, status);
|
||||||
|
|
||||||
|
if (*scaled_font)
|
||||||
|
cairo_scaled_font_destroy (*scaled_font);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = _cairo_user_scaled_font_backend.create_toy (font_face,
|
||||||
|
font_matrix,
|
||||||
|
ctm,
|
||||||
|
options,
|
||||||
|
scaled_font);
|
||||||
|
|
||||||
|
return _cairo_font_face_set_error (&font_face->base, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cairo_bool_t
|
static cairo_bool_t
|
||||||
|
@ -641,6 +693,7 @@ cairo_toy_font_face_get_slant (cairo_font_face_t *font_face)
|
||||||
}
|
}
|
||||||
return toy_font_face->slant;
|
return toy_font_face->slant;
|
||||||
}
|
}
|
||||||
|
slim_hidden_def (cairo_toy_font_face_get_slant);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_toy_font_face_get_weight:
|
* cairo_toy_font_face_get_weight:
|
||||||
|
@ -662,10 +715,12 @@ cairo_toy_font_face_get_weight (cairo_font_face_t *font_face)
|
||||||
}
|
}
|
||||||
return toy_font_face->weight;
|
return toy_font_face->weight;
|
||||||
}
|
}
|
||||||
|
slim_hidden_def (cairo_toy_font_face_get_weight);
|
||||||
|
|
||||||
static const cairo_font_face_backend_t _cairo_toy_font_face_backend = {
|
static const cairo_font_face_backend_t _cairo_toy_font_face_backend = {
|
||||||
CAIRO_FONT_TYPE_TOY,
|
CAIRO_FONT_TYPE_TOY,
|
||||||
_cairo_toy_font_face_destroy,
|
_cairo_toy_font_face_destroy,
|
||||||
|
_cairo_toy_font_face_scaled_font_get_implementation,
|
||||||
_cairo_toy_font_face_scaled_font_create
|
_cairo_toy_font_face_scaled_font_create
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
static const cairo_font_options_t _cairo_font_options_nil = {
|
static const cairo_font_options_t _cairo_font_options_nil = {
|
||||||
CAIRO_ANTIALIAS_DEFAULT,
|
CAIRO_ANTIALIAS_DEFAULT,
|
||||||
CAIRO_SUBPIXEL_ORDER_DEFAULT,
|
CAIRO_SUBPIXEL_ORDER_DEFAULT,
|
||||||
CAIRO_LCD_FILTER_DEFAULT,
|
|
||||||
CAIRO_HINT_STYLE_DEFAULT,
|
CAIRO_HINT_STYLE_DEFAULT,
|
||||||
CAIRO_HINT_METRICS_DEFAULT
|
CAIRO_HINT_METRICS_DEFAULT
|
||||||
};
|
};
|
||||||
|
@ -55,7 +54,6 @@ _cairo_font_options_init_default (cairo_font_options_t *options)
|
||||||
{
|
{
|
||||||
options->antialias = CAIRO_ANTIALIAS_DEFAULT;
|
options->antialias = CAIRO_ANTIALIAS_DEFAULT;
|
||||||
options->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
|
options->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
|
||||||
options->lcd_filter = CAIRO_LCD_FILTER_DEFAULT;
|
|
||||||
options->hint_style = CAIRO_HINT_STYLE_DEFAULT;
|
options->hint_style = CAIRO_HINT_STYLE_DEFAULT;
|
||||||
options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT;
|
options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT;
|
||||||
}
|
}
|
||||||
|
@ -66,7 +64,6 @@ _cairo_font_options_init_copy (cairo_font_options_t *options,
|
||||||
{
|
{
|
||||||
options->antialias = other->antialias;
|
options->antialias = other->antialias;
|
||||||
options->subpixel_order = other->subpixel_order;
|
options->subpixel_order = other->subpixel_order;
|
||||||
options->lcd_filter = other->lcd_filter;
|
|
||||||
options->hint_style = other->hint_style;
|
options->hint_style = other->hint_style;
|
||||||
options->hint_metrics = other->hint_metrics;
|
options->hint_metrics = other->hint_metrics;
|
||||||
}
|
}
|
||||||
|
@ -192,8 +189,6 @@ cairo_font_options_merge (cairo_font_options_t *options,
|
||||||
options->antialias = other->antialias;
|
options->antialias = other->antialias;
|
||||||
if (other->subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT)
|
if (other->subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT)
|
||||||
options->subpixel_order = other->subpixel_order;
|
options->subpixel_order = other->subpixel_order;
|
||||||
if (other->lcd_filter != CAIRO_LCD_FILTER_DEFAULT)
|
|
||||||
options->lcd_filter = other->lcd_filter;
|
|
||||||
if (other->hint_style != CAIRO_HINT_STYLE_DEFAULT)
|
if (other->hint_style != CAIRO_HINT_STYLE_DEFAULT)
|
||||||
options->hint_style = other->hint_style;
|
options->hint_style = other->hint_style;
|
||||||
if (other->hint_metrics != CAIRO_HINT_METRICS_DEFAULT)
|
if (other->hint_metrics != CAIRO_HINT_METRICS_DEFAULT)
|
||||||
|
@ -226,7 +221,6 @@ cairo_font_options_equal (const cairo_font_options_t *options,
|
||||||
|
|
||||||
return (options->antialias == other->antialias &&
|
return (options->antialias == other->antialias &&
|
||||||
options->subpixel_order == other->subpixel_order &&
|
options->subpixel_order == other->subpixel_order &&
|
||||||
options->lcd_filter == other->lcd_filter &&
|
|
||||||
options->hint_style == other->hint_style &&
|
options->hint_style == other->hint_style &&
|
||||||
options->hint_metrics == other->hint_metrics);
|
options->hint_metrics == other->hint_metrics);
|
||||||
}
|
}
|
||||||
|
@ -252,8 +246,7 @@ cairo_font_options_hash (const cairo_font_options_t *options)
|
||||||
|
|
||||||
return ((options->antialias) |
|
return ((options->antialias) |
|
||||||
(options->subpixel_order << 4) |
|
(options->subpixel_order << 4) |
|
||||||
(options->lcd_filter << 8) |
|
(options->hint_style << 8) |
|
||||||
(options->hint_style << 12) |
|
|
||||||
(options->hint_metrics << 16));
|
(options->hint_metrics << 16));
|
||||||
}
|
}
|
||||||
slim_hidden_def (cairo_font_options_hash);
|
slim_hidden_def (cairo_font_options_hash);
|
||||||
|
@ -334,49 +327,6 @@ cairo_font_options_get_subpixel_order (const cairo_font_options_t *options)
|
||||||
return options->subpixel_order;
|
return options->subpixel_order;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* cairo_font_options_set_lcd_filter:
|
|
||||||
* @options: a #cairo_font_options_t
|
|
||||||
* @lcd_filter: the new LCD filter
|
|
||||||
*
|
|
||||||
* Sets the LCD filter for the font options object. The LCD filter
|
|
||||||
* specifies how pixels are filtered when rendered with an antialiasing
|
|
||||||
* mode of %CAIRO_ANTIALIAS_SUBPIXEL. See the documentation for
|
|
||||||
* #cairo_lcd_filter_t for full details.
|
|
||||||
*
|
|
||||||
* Since: 1.8
|
|
||||||
**/
|
|
||||||
void
|
|
||||||
cairo_font_options_set_lcd_filter (cairo_font_options_t *options,
|
|
||||||
cairo_lcd_filter_t lcd_filter)
|
|
||||||
{
|
|
||||||
if (cairo_font_options_status (options))
|
|
||||||
return;
|
|
||||||
|
|
||||||
options->lcd_filter = lcd_filter;
|
|
||||||
}
|
|
||||||
slim_hidden_def (cairo_font_options_set_lcd_filter);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* cairo_font_options_get_lcd_filter:
|
|
||||||
* @options: a #cairo_font_options_t
|
|
||||||
*
|
|
||||||
* Gets the LCD filter for the font options object.
|
|
||||||
* See the documentation for #cairo_lcd_filter_t for full details.
|
|
||||||
*
|
|
||||||
* Return value: the LCD filter for the font options object
|
|
||||||
*
|
|
||||||
* Since: 1.8
|
|
||||||
**/
|
|
||||||
cairo_lcd_filter_t
|
|
||||||
cairo_font_options_get_lcd_filter (const cairo_font_options_t *options)
|
|
||||||
{
|
|
||||||
if (cairo_font_options_status ((cairo_font_options_t *) options))
|
|
||||||
return CAIRO_LCD_FILTER_DEFAULT;
|
|
||||||
|
|
||||||
return options->lcd_filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_font_options_set_hint_style:
|
* cairo_font_options_set_hint_style:
|
||||||
* @options: a #cairo_font_options_t
|
* @options: a #cairo_font_options_t
|
||||||
|
|
|
@ -57,30 +57,6 @@
|
||||||
#include FT_SYNTHESIS_H
|
#include FT_SYNTHESIS_H
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAVE_FT_LIBRARY_SETLCDFILTER
|
|
||||||
#include FT_LCD_FILTER_H
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Fontconfig version older than 2.6 didn't have these options */
|
|
||||||
#ifndef FC_LCD_FILTER
|
|
||||||
#define FC_LCD_FILTER "lcdfilter"
|
|
||||||
#endif
|
|
||||||
/* Some Ubuntu versions defined FC_LCD_FILTER without defining the following */
|
|
||||||
#ifndef FC_LCD_NONE
|
|
||||||
#define FC_LCD_NONE 0
|
|
||||||
#define FC_LCD_DEFAULT 1
|
|
||||||
#define FC_LCD_LIGHT 2
|
|
||||||
#define FC_LCD_LEGACY 3
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* FreeType version older than 2.3.5(?) didn't have these options */
|
|
||||||
#ifndef FT_LCD_FILTER_NONE
|
|
||||||
#define FT_LCD_FILTER_NONE 0
|
|
||||||
#define FT_LCD_FILTER_DEFAULT 1
|
|
||||||
#define FT_LCD_FILTER_LIGHT 2
|
|
||||||
#define FT_LCD_FILTER_LEGACY 16
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0))
|
#define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0))
|
||||||
#define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
|
#define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
|
||||||
#define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
|
#define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
|
||||||
|
@ -767,286 +743,23 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot
|
/* Empirically-derived subpixel filtering values thanks to Keith
|
||||||
* into a different format. For example, we want to convert a
|
* Packard and libXft. */
|
||||||
* FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit
|
static const int filters[3][3] = {
|
||||||
* ARGB or ABGR bitmap.
|
/* red */
|
||||||
*
|
#if 0
|
||||||
* this function prepares a target descriptor for this operation.
|
{ 65538*4/7,65538*2/7,65538*1/7 },
|
||||||
*
|
/* green */
|
||||||
* input :: target bitmap descriptor. The function will set its
|
{ 65536*1/4, 65536*2/4, 65537*1/4 },
|
||||||
* 'width', 'rows' and 'pitch' fields, and only these
|
/* blue */
|
||||||
*
|
{ 65538*1/7,65538*2/7,65538*4/7 },
|
||||||
* slot :: the glyph slot containing the source bitmap. this
|
|
||||||
* function assumes that slot->format == FT_GLYPH_FORMAT_BITMAP
|
|
||||||
*
|
|
||||||
* mode :: the requested final rendering mode. supported values are
|
|
||||||
* MONO, NORMAL (i.e. gray), LCD and LCD_V
|
|
||||||
*
|
|
||||||
* the function returns the size in bytes of the corresponding buffer,
|
|
||||||
* it's up to the caller to allocate the corresponding memory block
|
|
||||||
* before calling _fill_xrender_bitmap
|
|
||||||
*
|
|
||||||
* it also returns -1 in case of error (e.g. incompatible arguments,
|
|
||||||
* like trying to convert a gray bitmap into a monochrome one)
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
_compute_xrender_bitmap_size(FT_Bitmap *target,
|
|
||||||
FT_GlyphSlot slot,
|
|
||||||
FT_Render_Mode mode)
|
|
||||||
{
|
|
||||||
FT_Bitmap *ftbit;
|
|
||||||
int width, height, pitch;
|
|
||||||
|
|
||||||
if (slot->format != FT_GLYPH_FORMAT_BITMAP)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* compute the size of the final bitmap */
|
|
||||||
ftbit = &slot->bitmap;
|
|
||||||
|
|
||||||
width = ftbit->width;
|
|
||||||
height = ftbit->rows;
|
|
||||||
pitch = (width + 3) & ~3;
|
|
||||||
|
|
||||||
switch (ftbit->pixel_mode) {
|
|
||||||
case FT_PIXEL_MODE_MONO:
|
|
||||||
if (mode == FT_RENDER_MODE_MONO) {
|
|
||||||
pitch = (((width + 31) & ~31) >> 3);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* fall-through */
|
|
||||||
|
|
||||||
case FT_PIXEL_MODE_GRAY:
|
|
||||||
if (mode == FT_RENDER_MODE_LCD ||
|
|
||||||
mode == FT_RENDER_MODE_LCD_V)
|
|
||||||
{
|
|
||||||
/* each pixel is replicated into a 32-bit ARGB value */
|
|
||||||
pitch = width * 4;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FT_PIXEL_MODE_LCD:
|
|
||||||
if (mode != FT_RENDER_MODE_LCD)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* horz pixel triplets are packed into 32-bit ARGB values */
|
|
||||||
width /= 3;
|
|
||||||
pitch = width * 4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FT_PIXEL_MODE_LCD_V:
|
|
||||||
if (mode != FT_RENDER_MODE_LCD_V)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* vert pixel triplets are packed into 32-bit ARGB values */
|
|
||||||
height /= 3;
|
|
||||||
pitch = width * 4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: /* unsupported source format */
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
target->width = width;
|
|
||||||
target->rows = height;
|
|
||||||
target->pitch = pitch;
|
|
||||||
target->buffer = NULL;
|
|
||||||
|
|
||||||
return pitch * height;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this functions converts the glyph bitmap found in a FT_GlyphSlot
|
|
||||||
* into a different format (see _compute_xrender_bitmap_size)
|
|
||||||
*
|
|
||||||
* you should call this function after _compute_xrender_bitmap_size
|
|
||||||
*
|
|
||||||
* target :: target bitmap descriptor. Note that its 'buffer' pointer
|
|
||||||
* must point to memory allocated by the caller
|
|
||||||
*
|
|
||||||
* slot :: the glyph slot containing the source bitmap
|
|
||||||
*
|
|
||||||
* mode :: the requested final rendering mode
|
|
||||||
*
|
|
||||||
* bgr :: boolean, set if BGR or VBGR pixel ordering is needed
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
_fill_xrender_bitmap(FT_Bitmap *target,
|
|
||||||
FT_GlyphSlot slot,
|
|
||||||
FT_Render_Mode mode,
|
|
||||||
int bgr)
|
|
||||||
{
|
|
||||||
FT_Bitmap *ftbit = &slot->bitmap;
|
|
||||||
unsigned char *srcLine = ftbit->buffer;
|
|
||||||
unsigned char *dstLine = target->buffer;
|
|
||||||
int src_pitch = ftbit->pitch;
|
|
||||||
int width = target->width;
|
|
||||||
int height = target->rows;
|
|
||||||
int pitch = target->pitch;
|
|
||||||
int subpixel;
|
|
||||||
int h;
|
|
||||||
|
|
||||||
subpixel = (mode == FT_RENDER_MODE_LCD ||
|
|
||||||
mode == FT_RENDER_MODE_LCD_V);
|
|
||||||
|
|
||||||
if (src_pitch < 0)
|
|
||||||
srcLine -= src_pitch * (ftbit->rows - 1);
|
|
||||||
|
|
||||||
target->pixel_mode = ftbit->pixel_mode;
|
|
||||||
|
|
||||||
switch (ftbit->pixel_mode) {
|
|
||||||
case FT_PIXEL_MODE_MONO:
|
|
||||||
if (subpixel) {
|
|
||||||
/* convert mono to ARGB32 values */
|
|
||||||
|
|
||||||
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
|
|
||||||
int x;
|
|
||||||
|
|
||||||
for (x = 0; x < width; x++) {
|
|
||||||
if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
|
|
||||||
((unsigned int *) dstLine)[x] = 0xffffffffU;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
target->pixel_mode = FT_PIXEL_MODE_LCD;
|
|
||||||
|
|
||||||
} else if (mode == FT_RENDER_MODE_NORMAL) {
|
|
||||||
/* convert mono to 8-bit gray */
|
|
||||||
|
|
||||||
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
|
|
||||||
int x;
|
|
||||||
|
|
||||||
for (x = 0; x < width; x++) {
|
|
||||||
if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
|
|
||||||
dstLine[x] = 0xff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
target->pixel_mode = FT_PIXEL_MODE_GRAY;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* copy mono to mono */
|
|
||||||
|
|
||||||
int bytes = (width + 7) >> 3;
|
|
||||||
|
|
||||||
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
|
|
||||||
memcpy (dstLine, srcLine, bytes);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FT_PIXEL_MODE_GRAY:
|
|
||||||
if (subpixel) {
|
|
||||||
/* convert gray to ARGB32 values */
|
|
||||||
|
|
||||||
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
|
|
||||||
int x;
|
|
||||||
unsigned int *dst = (unsigned int *) dstLine;
|
|
||||||
|
|
||||||
for (x = 0; x < width; x++) {
|
|
||||||
unsigned int pix = srcLine[x];
|
|
||||||
|
|
||||||
pix |= (pix << 8);
|
|
||||||
pix |= (pix << 16);
|
|
||||||
|
|
||||||
dst[x] = pix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
target->pixel_mode = FT_PIXEL_MODE_LCD;
|
|
||||||
} else {
|
|
||||||
/* copy gray into gray */
|
|
||||||
|
|
||||||
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
|
|
||||||
memcpy (dstLine, srcLine, width);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FT_PIXEL_MODE_LCD:
|
|
||||||
if (!bgr) {
|
|
||||||
/* convert horizontal RGB into ARGB32 */
|
|
||||||
|
|
||||||
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
|
|
||||||
int x;
|
|
||||||
unsigned char *src = srcLine;
|
|
||||||
unsigned int *dst = (unsigned int *) dstLine;
|
|
||||||
|
|
||||||
for (x = 0; x < width; x++, src += 3) {
|
|
||||||
unsigned int pix;
|
|
||||||
|
|
||||||
pix = ((unsigned int)src[0] << 16) |
|
|
||||||
((unsigned int)src[1] << 8) |
|
|
||||||
((unsigned int)src[2] ) |
|
|
||||||
((unsigned int)src[1] << 24) ;
|
|
||||||
|
|
||||||
dst[x] = pix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* convert horizontal BGR into ARGB32 */
|
|
||||||
|
|
||||||
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
|
|
||||||
|
|
||||||
int x;
|
|
||||||
unsigned char *src = srcLine;
|
|
||||||
unsigned int *dst = (unsigned int *) dstLine;
|
|
||||||
|
|
||||||
for (x = 0; x < width; x++, src += 3) {
|
|
||||||
unsigned int pix;
|
|
||||||
|
|
||||||
pix = ((unsigned int)src[2] << 16) |
|
|
||||||
((unsigned int)src[1] << 8) |
|
|
||||||
((unsigned int)src[0] ) |
|
|
||||||
((unsigned int)src[1] << 24) ;
|
|
||||||
|
|
||||||
dst[x] = pix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: /* FT_PIXEL_MODE_LCD_V */
|
|
||||||
/* convert vertical RGB into ARGB32 */
|
|
||||||
if (!bgr) {
|
|
||||||
|
|
||||||
for (h = height; h > 0; h--, srcLine += 3 * src_pitch, dstLine += pitch) {
|
|
||||||
int x;
|
|
||||||
unsigned char* src = srcLine;
|
|
||||||
unsigned int* dst = (unsigned int *) dstLine;
|
|
||||||
|
|
||||||
for (x = 0; x < width; x++, src += 1) {
|
|
||||||
unsigned int pix;
|
|
||||||
#if 1
|
|
||||||
pix = ((unsigned int)src[0] << 16) |
|
|
||||||
((unsigned int)src[src_pitch] << 8) |
|
|
||||||
((unsigned int)src[src_pitch*2] ) |
|
|
||||||
0xFF000000 ;
|
|
||||||
#else
|
|
||||||
pix = ((unsigned int)src[0] << 16) |
|
|
||||||
((unsigned int)src[src_pitch] << 8) |
|
|
||||||
((unsigned int)src[src_pitch*2] ) |
|
|
||||||
((unsigned int)src[src_pitch] << 24) ;
|
|
||||||
#endif
|
#endif
|
||||||
dst[x] = pix;
|
{ 65538*9/13,65538*3/13,65538*1/13 },
|
||||||
}
|
/* green */
|
||||||
}
|
{ 65538*1/6, 65538*4/6, 65538*1/6 },
|
||||||
} else {
|
/* blue */
|
||||||
|
{ 65538*1/13,65538*3/13,65538*9/13 },
|
||||||
for (h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch) {
|
};
|
||||||
int x;
|
|
||||||
unsigned char *src = srcLine;
|
|
||||||
unsigned int *dst = (unsigned int *) dstLine;
|
|
||||||
|
|
||||||
for (x = 0; x < width; x++, src += 1) {
|
|
||||||
unsigned int pix;
|
|
||||||
|
|
||||||
pix = ((unsigned int)src[src_pitch * 2] << 16) |
|
|
||||||
((unsigned int)src[src_pitch] << 8) |
|
|
||||||
((unsigned int)src[0] ) |
|
|
||||||
((unsigned int)src[src_pitch] << 24) ;
|
|
||||||
|
|
||||||
dst[x] = pix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Fills in val->image with an image surface created from @bitmap
|
/* Fills in val->image with an image surface created from @bitmap
|
||||||
*/
|
*/
|
||||||
|
@ -1059,7 +772,7 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
|
||||||
int width, height, stride;
|
int width, height, stride;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
int format = CAIRO_FORMAT_A8;
|
int format = CAIRO_FORMAT_A8;
|
||||||
cairo_image_surface_t *image;
|
cairo_bool_t subpixel = FALSE;
|
||||||
|
|
||||||
width = bitmap->width;
|
width = bitmap->width;
|
||||||
height = bitmap->rows;
|
height = bitmap->rows;
|
||||||
|
@ -1116,7 +829,11 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
|
||||||
case FT_PIXEL_MODE_LCD:
|
case FT_PIXEL_MODE_LCD:
|
||||||
case FT_PIXEL_MODE_LCD_V:
|
case FT_PIXEL_MODE_LCD_V:
|
||||||
case FT_PIXEL_MODE_GRAY:
|
case FT_PIXEL_MODE_GRAY:
|
||||||
if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) {
|
switch (font_options->antialias) {
|
||||||
|
case CAIRO_ANTIALIAS_DEFAULT:
|
||||||
|
case CAIRO_ANTIALIAS_GRAY:
|
||||||
|
case CAIRO_ANTIALIAS_NONE:
|
||||||
|
default:
|
||||||
stride = bitmap->pitch;
|
stride = bitmap->pitch;
|
||||||
if (own_buffer) {
|
if (own_buffer) {
|
||||||
data = bitmap->buffer;
|
data = bitmap->buffer;
|
||||||
|
@ -1128,16 +845,104 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
|
||||||
memcpy (data, bitmap->buffer, stride * height);
|
memcpy (data, bitmap->buffer, stride * height);
|
||||||
}
|
}
|
||||||
format = CAIRO_FORMAT_A8;
|
format = CAIRO_FORMAT_A8;
|
||||||
} else {
|
break;
|
||||||
/* if we get there, the data from the source bitmap
|
case CAIRO_ANTIALIAS_SUBPIXEL: {
|
||||||
* really comes from _fill_xrender_bitmap, and is
|
int x, y;
|
||||||
* made of 32-bit ARGB or ABGR values */
|
unsigned char *in_line, *out_line, *in;
|
||||||
assert (own_buffer != 0);
|
unsigned int *out;
|
||||||
assert (bitmap->pixel_mode != FT_PIXEL_MODE_GRAY);
|
unsigned int red, green, blue;
|
||||||
|
int rf, gf, bf;
|
||||||
|
int s;
|
||||||
|
int o, os;
|
||||||
|
unsigned char *data_rgba;
|
||||||
|
unsigned int width_rgba, stride_rgba;
|
||||||
|
int vmul = 1;
|
||||||
|
int hmul = 1;
|
||||||
|
|
||||||
data = bitmap->buffer;
|
switch (font_options->subpixel_order) {
|
||||||
|
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
|
||||||
|
case CAIRO_SUBPIXEL_ORDER_RGB:
|
||||||
|
case CAIRO_SUBPIXEL_ORDER_BGR:
|
||||||
|
default:
|
||||||
|
width /= 3;
|
||||||
|
hmul = 3;
|
||||||
|
break;
|
||||||
|
case CAIRO_SUBPIXEL_ORDER_VRGB:
|
||||||
|
case CAIRO_SUBPIXEL_ORDER_VBGR:
|
||||||
|
vmul = 3;
|
||||||
|
height /= 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Filter the glyph to soften the color fringes
|
||||||
|
*/
|
||||||
|
width_rgba = width;
|
||||||
stride = bitmap->pitch;
|
stride = bitmap->pitch;
|
||||||
|
stride_rgba = (width_rgba * 4 + 3) & ~3;
|
||||||
|
data_rgba = calloc (stride_rgba, height);
|
||||||
|
if (data_rgba == NULL) {
|
||||||
|
if (own_buffer)
|
||||||
|
free (bitmap->buffer);
|
||||||
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
os = 1;
|
||||||
|
switch (font_options->subpixel_order) {
|
||||||
|
case CAIRO_SUBPIXEL_ORDER_VRGB:
|
||||||
|
os = stride;
|
||||||
|
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
|
||||||
|
case CAIRO_SUBPIXEL_ORDER_RGB:
|
||||||
|
default:
|
||||||
|
rf = 0;
|
||||||
|
gf = 1;
|
||||||
|
bf = 2;
|
||||||
|
break;
|
||||||
|
case CAIRO_SUBPIXEL_ORDER_VBGR:
|
||||||
|
os = stride;
|
||||||
|
case CAIRO_SUBPIXEL_ORDER_BGR:
|
||||||
|
bf = 0;
|
||||||
|
gf = 1;
|
||||||
|
rf = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
in_line = bitmap->buffer;
|
||||||
|
out_line = data_rgba;
|
||||||
|
for (y = 0; y < height; y++)
|
||||||
|
{
|
||||||
|
in = in_line;
|
||||||
|
out = (unsigned int *) out_line;
|
||||||
|
in_line += stride * vmul;
|
||||||
|
out_line += stride_rgba;
|
||||||
|
for (x = 0; x < width * hmul; x += hmul)
|
||||||
|
{
|
||||||
|
red = green = blue = 0;
|
||||||
|
o = 0;
|
||||||
|
for (s = 0; s < 3; s++)
|
||||||
|
{
|
||||||
|
red += filters[rf][s]*in[x+o];
|
||||||
|
green += filters[gf][s]*in[x+o];
|
||||||
|
blue += filters[bf][s]*in[x+o];
|
||||||
|
o += os;
|
||||||
|
}
|
||||||
|
red = red / 65536;
|
||||||
|
green = green / 65536;
|
||||||
|
blue = blue / 65536;
|
||||||
|
*out++ = (green << 24) | (red << 16) | (green << 8) | blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Images here are stored in native format. The
|
||||||
|
* backend must convert to its own format as needed
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (own_buffer)
|
||||||
|
free (bitmap->buffer);
|
||||||
|
data = data_rgba;
|
||||||
|
stride = stride_rgba;
|
||||||
format = CAIRO_FORMAT_ARGB32;
|
format = CAIRO_FORMAT_ARGB32;
|
||||||
|
subpixel = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FT_PIXEL_MODE_GRAY2:
|
case FT_PIXEL_MODE_GRAY2:
|
||||||
|
@ -1149,20 +954,19 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX */
|
*surface = (cairo_image_surface_t *)
|
||||||
*surface = image = (cairo_image_surface_t *)
|
|
||||||
cairo_image_surface_create_for_data (data,
|
cairo_image_surface_create_for_data (data,
|
||||||
format,
|
format,
|
||||||
width, height, stride);
|
width, height, stride);
|
||||||
if (image->base.status) {
|
if ((*surface)->base.status) {
|
||||||
free (data);
|
free (data);
|
||||||
return (*surface)->base.status;
|
return (*surface)->base.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (font_options->antialias == CAIRO_ANTIALIAS_SUBPIXEL)
|
if (subpixel)
|
||||||
pixman_image_set_component_alpha (image->pixman_image, TRUE);
|
pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE);
|
||||||
|
|
||||||
_cairo_image_surface_assume_ownership_of_data (image);
|
_cairo_image_surface_assume_ownership_of_data ((*surface));
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1187,59 +991,16 @@ _render_glyph_outline (FT_Face face,
|
||||||
cairo_font_options_t *font_options,
|
cairo_font_options_t *font_options,
|
||||||
cairo_image_surface_t **surface)
|
cairo_image_surface_t **surface)
|
||||||
{
|
{
|
||||||
int rgba = FC_RGBA_UNKNOWN;
|
|
||||||
int lcd_filter = FT_LCD_FILTER_LEGACY;
|
|
||||||
FT_GlyphSlot glyphslot = face->glyph;
|
FT_GlyphSlot glyphslot = face->glyph;
|
||||||
FT_Outline *outline = &glyphslot->outline;
|
FT_Outline *outline = &glyphslot->outline;
|
||||||
FT_Bitmap bitmap;
|
FT_Bitmap bitmap;
|
||||||
FT_BBox cbox;
|
FT_BBox cbox;
|
||||||
unsigned int width, height;
|
FT_Matrix matrix;
|
||||||
|
int hmul = 1;
|
||||||
|
int vmul = 1;
|
||||||
|
unsigned int width, height, stride;
|
||||||
|
cairo_bool_t subpixel = FALSE;
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
FT_Error fterror;
|
|
||||||
FT_Library library = glyphslot->library;
|
|
||||||
FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL;
|
|
||||||
|
|
||||||
switch (font_options->antialias) {
|
|
||||||
case CAIRO_ANTIALIAS_NONE:
|
|
||||||
render_mode = FT_RENDER_MODE_MONO;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CAIRO_ANTIALIAS_SUBPIXEL:
|
|
||||||
switch (font_options->subpixel_order) {
|
|
||||||
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
|
|
||||||
case CAIRO_SUBPIXEL_ORDER_RGB:
|
|
||||||
case CAIRO_SUBPIXEL_ORDER_BGR:
|
|
||||||
render_mode = FT_RENDER_MODE_LCD;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CAIRO_SUBPIXEL_ORDER_VRGB:
|
|
||||||
case CAIRO_SUBPIXEL_ORDER_VBGR:
|
|
||||||
render_mode = FT_RENDER_MODE_LCD_V;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (font_options->lcd_filter) {
|
|
||||||
case CAIRO_LCD_FILTER_NONE:
|
|
||||||
lcd_filter = FT_LCD_FILTER_NONE;
|
|
||||||
break;
|
|
||||||
case CAIRO_LCD_FILTER_DEFAULT:
|
|
||||||
case CAIRO_LCD_FILTER_INTRA_PIXEL:
|
|
||||||
lcd_filter = FT_LCD_FILTER_LEGACY;
|
|
||||||
break;
|
|
||||||
case CAIRO_LCD_FILTER_FIR3:
|
|
||||||
lcd_filter = FT_LCD_FILTER_LIGHT;
|
|
||||||
break;
|
|
||||||
case CAIRO_LCD_FILTER_FIR5:
|
|
||||||
lcd_filter = FT_LCD_FILTER_DEFAULT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CAIRO_ANTIALIAS_DEFAULT:
|
|
||||||
case CAIRO_ANTIALIAS_GRAY:
|
|
||||||
render_mode = FT_RENDER_MODE_NORMAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
FT_Outline_Get_CBox (outline, &cbox);
|
FT_Outline_Get_CBox (outline, &cbox);
|
||||||
|
|
||||||
|
@ -1250,21 +1011,20 @@ _render_glyph_outline (FT_Face face,
|
||||||
|
|
||||||
width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
|
width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
|
||||||
height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
|
height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
|
||||||
|
stride = (width * hmul + 3) & ~3;
|
||||||
|
|
||||||
if (width * height == 0) {
|
if (width * height == 0) {
|
||||||
cairo_format_t format;
|
cairo_format_t format;
|
||||||
/* Looks like fb handles zero-sized images just fine */
|
/* Looks like fb handles zero-sized images just fine */
|
||||||
switch (render_mode) {
|
switch (font_options->antialias) {
|
||||||
case FT_RENDER_MODE_MONO:
|
case CAIRO_ANTIALIAS_NONE:
|
||||||
format = CAIRO_FORMAT_A1;
|
format = CAIRO_FORMAT_A1;
|
||||||
break;
|
break;
|
||||||
case FT_RENDER_MODE_LCD:
|
case CAIRO_ANTIALIAS_SUBPIXEL:
|
||||||
case FT_RENDER_MODE_LCD_V:
|
|
||||||
format= CAIRO_FORMAT_ARGB32;
|
format= CAIRO_FORMAT_ARGB32;
|
||||||
break;
|
break;
|
||||||
case FT_RENDER_MODE_LIGHT:
|
case CAIRO_ANTIALIAS_DEFAULT:
|
||||||
case FT_RENDER_MODE_NORMAL:
|
case CAIRO_ANTIALIAS_GRAY:
|
||||||
case FT_RENDER_MODE_MAX:
|
|
||||||
default:
|
default:
|
||||||
format = CAIRO_FORMAT_A8;
|
format = CAIRO_FORMAT_A8;
|
||||||
break;
|
break;
|
||||||
|
@ -1276,74 +1036,74 @@ _render_glyph_outline (FT_Face face,
|
||||||
return (*surface)->base.status;
|
return (*surface)->base.status;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
int bitmap_size;
|
matrix.xx = matrix.yy = 0x10000L;
|
||||||
|
matrix.xy = matrix.yx = 0;
|
||||||
|
|
||||||
switch (render_mode) {
|
switch (font_options->antialias) {
|
||||||
case FT_RENDER_MODE_LCD:
|
case CAIRO_ANTIALIAS_NONE:
|
||||||
if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_BGR) {
|
bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
|
||||||
rgba = FC_RGBA_BGR;
|
bitmap.num_grays = 1;
|
||||||
} else {
|
stride = ((width + 31) & -32) >> 3;
|
||||||
rgba = FC_RGBA_RGB;
|
break;
|
||||||
|
case CAIRO_ANTIALIAS_DEFAULT:
|
||||||
|
case CAIRO_ANTIALIAS_GRAY:
|
||||||
|
bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
|
||||||
|
bitmap.num_grays = 256;
|
||||||
|
stride = (width + 3) & -4;
|
||||||
|
break;
|
||||||
|
case CAIRO_ANTIALIAS_SUBPIXEL:
|
||||||
|
switch (font_options->subpixel_order) {
|
||||||
|
case CAIRO_SUBPIXEL_ORDER_RGB:
|
||||||
|
case CAIRO_SUBPIXEL_ORDER_BGR:
|
||||||
|
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
|
||||||
|
default:
|
||||||
|
matrix.xx *= 3;
|
||||||
|
hmul = 3;
|
||||||
|
subpixel = TRUE;
|
||||||
|
break;
|
||||||
|
case CAIRO_SUBPIXEL_ORDER_VRGB:
|
||||||
|
case CAIRO_SUBPIXEL_ORDER_VBGR:
|
||||||
|
matrix.yy *= 3;
|
||||||
|
vmul = 3;
|
||||||
|
subpixel = TRUE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
FT_Outline_Transform (outline, &matrix);
|
||||||
case FT_RENDER_MODE_LCD_V:
|
|
||||||
if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_VBGR) {
|
bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
|
||||||
rgba = FC_RGBA_VBGR;
|
bitmap.num_grays = 256;
|
||||||
} else {
|
stride = (width * hmul + 3) & -4;
|
||||||
rgba = FC_RGBA_VRGB;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case FT_RENDER_MODE_MONO:
|
|
||||||
case FT_RENDER_MODE_LIGHT:
|
|
||||||
case FT_RENDER_MODE_NORMAL:
|
|
||||||
case FT_RENDER_MODE_MAX:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAVE_FT_LIBRARY_SETLCDFILTER
|
bitmap.pitch = stride;
|
||||||
FT_Library_SetLcdFilter (library, lcd_filter);
|
bitmap.width = width * hmul;
|
||||||
#endif
|
bitmap.rows = height * vmul;
|
||||||
|
bitmap.buffer = calloc (stride, bitmap.rows);
|
||||||
fterror = FT_Render_Glyph (face->glyph, render_mode);
|
|
||||||
|
|
||||||
#if HAVE_FT_LIBRARY_SETLCDFILTER
|
|
||||||
FT_Library_SetLcdFilter (library, FT_LCD_FILTER_NONE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (fterror != 0)
|
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
||||||
|
|
||||||
bitmap_size = _compute_xrender_bitmap_size (&bitmap,
|
|
||||||
face->glyph,
|
|
||||||
render_mode);
|
|
||||||
if (bitmap_size < 0)
|
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
||||||
|
|
||||||
bitmap.buffer = calloc (1, bitmap_size);
|
|
||||||
if (bitmap.buffer == NULL)
|
if (bitmap.buffer == NULL)
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
|
|
||||||
_fill_xrender_bitmap (&bitmap, face->glyph, render_mode,
|
FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul);
|
||||||
(rgba == FC_RGBA_BGR || rgba == FC_RGBA_VBGR));
|
|
||||||
|
if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
|
||||||
|
free (bitmap.buffer);
|
||||||
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
/* Note:
|
|
||||||
* _get_bitmap_surface will free bitmap.buffer if there is an error
|
|
||||||
*/
|
|
||||||
status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
|
status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
/* Note: the font's coordinate system is upside down from ours, so the
|
|
||||||
* Y coordinate of the control box needs to be negated. Moreover, device
|
|
||||||
* offsets are position of glyph origin relative to top left while xMin
|
|
||||||
* and yMax are offsets of top left relative to origin. Another negation.
|
|
||||||
*/
|
|
||||||
cairo_surface_set_device_offset (&(*surface)->base,
|
|
||||||
(double)-glyphslot->bitmap_left,
|
|
||||||
(double)+glyphslot->bitmap_top);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: the font's coordinate system is upside down from ours, so the
|
||||||
|
* Y coordinate of the control box needs to be negated. Moreover, device
|
||||||
|
* offsets are position of glyph origin relative to top left while xMin
|
||||||
|
* and yMax are offsets of top left relative to origin. Another negation.
|
||||||
|
*/
|
||||||
|
cairo_surface_set_device_offset (&(*surface)->base,
|
||||||
|
floor (-(double) cbox.xMin / 64.0),
|
||||||
|
floor (+(double) cbox.yMax / 64.0));
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1562,7 +1322,6 @@ _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
|
||||||
|
|
||||||
if (antialias) {
|
if (antialias) {
|
||||||
cairo_subpixel_order_t subpixel_order;
|
cairo_subpixel_order_t subpixel_order;
|
||||||
int lcd_filter;
|
|
||||||
|
|
||||||
/* disable hinting if requested */
|
/* disable hinting if requested */
|
||||||
if (FcPatternGetBool (pattern,
|
if (FcPatternGetBool (pattern,
|
||||||
|
@ -1598,25 +1357,6 @@ _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
|
||||||
ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
|
ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FcPatternGetInteger (pattern,
|
|
||||||
FC_LCD_FILTER, 0, &lcd_filter) == FcResultMatch)
|
|
||||||
{
|
|
||||||
switch (lcd_filter) {
|
|
||||||
case FC_LCD_NONE:
|
|
||||||
ft_options.base.lcd_filter = CAIRO_LCD_FILTER_NONE;
|
|
||||||
break;
|
|
||||||
case FC_LCD_DEFAULT:
|
|
||||||
ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR5;
|
|
||||||
break;
|
|
||||||
case FC_LCD_LIGHT:
|
|
||||||
ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR3;
|
|
||||||
break;
|
|
||||||
case FC_LCD_LEGACY:
|
|
||||||
ft_options.base.lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef FC_HINT_STYLE
|
#ifdef FC_HINT_STYLE
|
||||||
if (FcPatternGetInteger (pattern,
|
if (FcPatternGetInteger (pattern,
|
||||||
FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch)
|
FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch)
|
||||||
|
@ -1717,12 +1457,6 @@ _cairo_ft_options_merge (cairo_ft_options_t *options,
|
||||||
if (other->base.hint_style == CAIRO_HINT_STYLE_NONE)
|
if (other->base.hint_style == CAIRO_HINT_STYLE_NONE)
|
||||||
options->base.hint_style = CAIRO_HINT_STYLE_NONE;
|
options->base.hint_style = CAIRO_HINT_STYLE_NONE;
|
||||||
|
|
||||||
if (options->base.lcd_filter == CAIRO_LCD_FILTER_DEFAULT)
|
|
||||||
options->base.lcd_filter = other->base.lcd_filter;
|
|
||||||
|
|
||||||
if (other->base.lcd_filter == CAIRO_LCD_FILTER_NONE)
|
|
||||||
options->base.lcd_filter = CAIRO_LCD_FILTER_NONE;
|
|
||||||
|
|
||||||
if (options->base.antialias == CAIRO_ANTIALIAS_NONE) {
|
if (options->base.antialias == CAIRO_ANTIALIAS_NONE) {
|
||||||
if (options->base.hint_style == CAIRO_HINT_STYLE_NONE)
|
if (options->base.hint_style == CAIRO_HINT_STYLE_NONE)
|
||||||
load_flags |= FT_LOAD_NO_HINTING;
|
load_flags |= FT_LOAD_NO_HINTING;
|
||||||
|
@ -1746,11 +1480,11 @@ _cairo_ft_options_merge (cairo_ft_options_t *options,
|
||||||
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
|
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
|
||||||
case CAIRO_SUBPIXEL_ORDER_RGB:
|
case CAIRO_SUBPIXEL_ORDER_RGB:
|
||||||
case CAIRO_SUBPIXEL_ORDER_BGR:
|
case CAIRO_SUBPIXEL_ORDER_BGR:
|
||||||
load_target = FT_LOAD_TARGET_LCD;
|
load_target |= FT_LOAD_TARGET_LCD;
|
||||||
break;
|
break;
|
||||||
case CAIRO_SUBPIXEL_ORDER_VRGB:
|
case CAIRO_SUBPIXEL_ORDER_VRGB:
|
||||||
case CAIRO_SUBPIXEL_ORDER_VBGR:
|
case CAIRO_SUBPIXEL_ORDER_VBGR:
|
||||||
load_target = FT_LOAD_TARGET_LCD_V;
|
load_target |= FT_LOAD_TARGET_LCD_V;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2483,6 +2217,7 @@ _cairo_ft_index_to_ucs4(void *abstract_font,
|
||||||
|
|
||||||
const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
|
const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
|
||||||
CAIRO_FONT_TYPE_FT,
|
CAIRO_FONT_TYPE_FT,
|
||||||
|
NULL,
|
||||||
_cairo_ft_scaled_font_create_toy,
|
_cairo_ft_scaled_font_create_toy,
|
||||||
_cairo_ft_scaled_font_fini,
|
_cairo_ft_scaled_font_fini,
|
||||||
_cairo_ft_scaled_glyph_init,
|
_cairo_ft_scaled_glyph_init,
|
||||||
|
@ -2589,6 +2324,7 @@ _cairo_ft_font_face_scaled_font_create (void *abstract_face,
|
||||||
static const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
|
static const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
|
||||||
CAIRO_FONT_TYPE_FT,
|
CAIRO_FONT_TYPE_FT,
|
||||||
_cairo_ft_font_face_destroy,
|
_cairo_ft_font_face_destroy,
|
||||||
|
NULL, /* direct implementation */
|
||||||
_cairo_ft_font_face_scaled_font_create
|
_cairo_ft_font_face_scaled_font_create
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2693,34 +2429,6 @@ _cairo_ft_font_options_substitute (const cairo_font_options_t *options,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options->lcd_filter != CAIRO_LCD_FILTER_DEFAULT)
|
|
||||||
{
|
|
||||||
if (FcPatternGet (pattern, FC_LCD_FILTER, 0, &v) == FcResultNoMatch)
|
|
||||||
{
|
|
||||||
int lcd_filter;
|
|
||||||
|
|
||||||
switch (options->lcd_filter) {
|
|
||||||
case CAIRO_LCD_FILTER_NONE:
|
|
||||||
lcd_filter = FT_LCD_FILTER_NONE;
|
|
||||||
break;
|
|
||||||
case CAIRO_LCD_FILTER_DEFAULT:
|
|
||||||
case CAIRO_LCD_FILTER_INTRA_PIXEL:
|
|
||||||
lcd_filter = FT_LCD_FILTER_LEGACY;
|
|
||||||
break;
|
|
||||||
case CAIRO_LCD_FILTER_FIR3:
|
|
||||||
lcd_filter = FT_LCD_FILTER_LIGHT;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
case CAIRO_LCD_FILTER_FIR5:
|
|
||||||
lcd_filter = FT_LCD_FILTER_DEFAULT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! FcPatternAddInteger (pattern, FC_LCD_FILTER, lcd_filter))
|
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options->hint_style != CAIRO_HINT_STYLE_DEFAULT)
|
if (options->hint_style != CAIRO_HINT_STYLE_DEFAULT)
|
||||||
{
|
{
|
||||||
if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch)
|
if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch)
|
||||||
|
@ -2861,10 +2569,14 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
|
||||||
* cairo_set_font_face() or cairo_scaled_font_create(). The
|
* cairo_set_font_face() or cairo_scaled_font_create(). The
|
||||||
* #cairo_scaled_font_t returned from cairo_scaled_font_create() is
|
* #cairo_scaled_font_t returned from cairo_scaled_font_create() is
|
||||||
* also for the FreeType backend and can be used with functions such
|
* also for the FreeType backend and can be used with functions such
|
||||||
* as cairo_ft_scaled_font_lock_face().
|
* as cairo_ft_scaled_font_lock_face(). Note that Cairo may keep a reference
|
||||||
|
* to the FT_Face alive in a font-cache and the exact lifetime of the reference
|
||||||
|
* depends highly upon the exact usage pattern and is subject to external
|
||||||
|
* factors. You must not call FT_Done_Face() before the last reference to the
|
||||||
|
* #cairo_font_face_t has been dropped.
|
||||||
*
|
*
|
||||||
* As an example, here is how one might correctly couple the lifetime of
|
* As an example, below is how one might correctly couple the lifetime of
|
||||||
* the FreeType face object to the #cairo_font_face_t:
|
* the FreeType face object to the #cairo_font_face_t.
|
||||||
*
|
*
|
||||||
* <informalexample><programlisting>
|
* <informalexample><programlisting>
|
||||||
* static const cairo_user_data_key_t key;
|
* static const cairo_user_data_key_t key;
|
||||||
|
|
|
@ -511,6 +511,8 @@ _cairo_glitz_surface_clone_similar (void *abstract_surface,
|
||||||
int src_y,
|
int src_y,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
|
int *clone_offset_x,
|
||||||
|
int *clone_offset_y,
|
||||||
cairo_surface_t **clone_out)
|
cairo_surface_t **clone_out)
|
||||||
{
|
{
|
||||||
cairo_glitz_surface_t *surface = abstract_surface;
|
cairo_glitz_surface_t *surface = abstract_surface;
|
||||||
|
@ -522,6 +524,8 @@ _cairo_glitz_surface_clone_similar (void *abstract_surface,
|
||||||
|
|
||||||
if (src->backend == surface->base.backend)
|
if (src->backend == surface->base.backend)
|
||||||
{
|
{
|
||||||
|
*clone_offset_x = 0;
|
||||||
|
*clone_offset_y = 0;
|
||||||
*clone_out = cairo_surface_reference (src);
|
*clone_out = cairo_surface_reference (src);
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
@ -539,6 +543,8 @@ _cairo_glitz_surface_clone_similar (void *abstract_surface,
|
||||||
_cairo_glitz_surface_create_similar (surface, content,
|
_cairo_glitz_surface_create_similar (surface, content,
|
||||||
image_src->width,
|
image_src->width,
|
||||||
image_src->height);
|
image_src->height);
|
||||||
|
if (clone == NULL)
|
||||||
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
if (clone->base.status)
|
if (clone->base.status)
|
||||||
return clone->base.status;
|
return clone->base.status;
|
||||||
|
|
||||||
|
@ -802,8 +808,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
|
||||||
_cairo_surface_create_similar_scratch (&dst->base,
|
_cairo_surface_create_similar_scratch (&dst->base,
|
||||||
CAIRO_CONTENT_COLOR_ALPHA,
|
CAIRO_CONTENT_COLOR_ALPHA,
|
||||||
gradient->n_stops, 1);
|
gradient->n_stops, 1);
|
||||||
if (src->base.status)
|
if (src->base.status) {
|
||||||
{
|
|
||||||
glitz_buffer_destroy (buffer);
|
glitz_buffer_destroy (buffer);
|
||||||
free (data);
|
free (data);
|
||||||
return src->base.status;
|
return src->base.status;
|
||||||
|
@ -1276,8 +1281,13 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
|
||||||
_cairo_glitz_surface_create_similar (&dst->base,
|
_cairo_glitz_surface_create_similar (&dst->base,
|
||||||
CAIRO_CONTENT_ALPHA,
|
CAIRO_CONTENT_ALPHA,
|
||||||
2, 1);
|
2, 1);
|
||||||
if (mask->base.status)
|
if (mask == NULL) {
|
||||||
{
|
_cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
|
||||||
|
if (src_pattern == &tmp_src_pattern.base)
|
||||||
|
_cairo_pattern_fini (&tmp_src_pattern.base);
|
||||||
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
if (mask->base.status) {
|
||||||
_cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
|
_cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
|
||||||
if (src_pattern == &tmp_src_pattern.base)
|
if (src_pattern == &tmp_src_pattern.base)
|
||||||
_cairo_pattern_fini (&tmp_src_pattern.base);
|
_cairo_pattern_fini (&tmp_src_pattern.base);
|
||||||
|
@ -1385,8 +1395,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
|
||||||
_cairo_surface_create_similar_scratch (&dst->base,
|
_cairo_surface_create_similar_scratch (&dst->base,
|
||||||
CAIRO_CONTENT_ALPHA,
|
CAIRO_CONTENT_ALPHA,
|
||||||
width, height);
|
width, height);
|
||||||
if (mask->base.status)
|
if (mask->base.status) {
|
||||||
{
|
|
||||||
_cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
|
_cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
|
||||||
free (data);
|
free (data);
|
||||||
cairo_surface_destroy (&image->base);
|
cairo_surface_destroy (&image->base);
|
||||||
|
@ -2011,7 +2020,7 @@ _cairo_glitz_surface_add_glyph (cairo_glitz_surface_t *surface,
|
||||||
|
|
||||||
if (glyph_surface->width > GLYPH_CACHE_MAX_WIDTH ||
|
if (glyph_surface->width > GLYPH_CACHE_MAX_WIDTH ||
|
||||||
glyph_surface->height > GLYPH_CACHE_MAX_HEIGHT)
|
glyph_surface->height > GLYPH_CACHE_MAX_HEIGHT)
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
if (scaled_font->surface_private == NULL)
|
if (scaled_font->surface_private == NULL)
|
||||||
{
|
{
|
||||||
|
@ -2244,6 +2253,7 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
||||||
if (!glyph_private || !glyph_private->area)
|
if (!glyph_private || !glyph_private->area)
|
||||||
{
|
{
|
||||||
int glyph_width, glyph_height;
|
int glyph_width, glyph_height;
|
||||||
|
int clone_offset_x, clone_offset_y;
|
||||||
|
|
||||||
image = &scaled_glyphs[i]->surface->base;
|
image = &scaled_glyphs[i]->surface->base;
|
||||||
glyph_width = scaled_glyphs[i]->surface->width;
|
glyph_width = scaled_glyphs[i]->surface->width;
|
||||||
|
@ -2255,11 +2265,16 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
||||||
0,
|
0,
|
||||||
glyph_width,
|
glyph_width,
|
||||||
glyph_height,
|
glyph_height,
|
||||||
|
&clone_offset_x,
|
||||||
|
&clone_offset_y,
|
||||||
(cairo_surface_t **)
|
(cairo_surface_t **)
|
||||||
&clone);
|
&clone);
|
||||||
if (status)
|
if (status)
|
||||||
goto UNLOCK;
|
goto UNLOCK;
|
||||||
|
|
||||||
|
assert (clone_offset_x == 0);
|
||||||
|
assert (clone_offset_y == 0);
|
||||||
|
|
||||||
x_offset = scaled_glyphs[i]->surface->base.device_transform.x0;
|
x_offset = scaled_glyphs[i]->surface->base.device_transform.x0;
|
||||||
y_offset = scaled_glyphs[i]->surface->base.device_transform.y0;
|
y_offset = scaled_glyphs[i]->surface->base.device_transform.y0;
|
||||||
x1 = _cairo_lround (glyphs[i].x - x_offset);
|
x1 = _cairo_lround (glyphs[i].x - x_offset);
|
||||||
|
@ -2371,6 +2386,13 @@ _cairo_glitz_surface_is_similar (void *surface_a,
|
||||||
glitz_drawable_t *drawable_a = glitz_surface_get_drawable (a->surface);
|
glitz_drawable_t *drawable_a = glitz_surface_get_drawable (a->surface);
|
||||||
glitz_drawable_t *drawable_b = glitz_surface_get_drawable (b->surface);
|
glitz_drawable_t *drawable_b = glitz_surface_get_drawable (b->surface);
|
||||||
|
|
||||||
|
/* XXX Disable caching of glitz surfaces by the solid pattern cache.
|
||||||
|
* Until glitz has a mechanism for releasing resources on connection
|
||||||
|
* closure, we will attempt to access invalid pointers when evicting
|
||||||
|
* old surfaces from the solid pattern cache.
|
||||||
|
*/
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
return drawable_a == drawable_b;
|
return drawable_a == drawable_b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ _cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate);
|
||||||
static void
|
static void
|
||||||
_cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate);
|
_cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate);
|
||||||
|
|
||||||
static void
|
static cairo_status_t
|
||||||
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
|
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
|
||||||
const cairo_glyph_t *glyphs,
|
const cairo_glyph_t *glyphs,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
|
@ -314,6 +314,8 @@ _cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child)
|
||||||
* _cairo_gstate_is_redirected
|
* _cairo_gstate_is_redirected
|
||||||
* @gstate: a #cairo_gstate_t
|
* @gstate: a #cairo_gstate_t
|
||||||
*
|
*
|
||||||
|
* This space left intentionally blank.
|
||||||
|
*
|
||||||
* Return value: %TRUE if the gstate is redirected to a target
|
* Return value: %TRUE if the gstate is redirected to a target
|
||||||
* different than the original, %FALSE otherwise.
|
* different than the original, %FALSE otherwise.
|
||||||
**/
|
**/
|
||||||
|
@ -372,6 +374,8 @@ _cairo_gstate_get_original_target (cairo_gstate_t *gstate)
|
||||||
* _cairo_gstate_get_clip:
|
* _cairo_gstate_get_clip:
|
||||||
* @gstate: a #cairo_gstate_t
|
* @gstate: a #cairo_gstate_t
|
||||||
*
|
*
|
||||||
|
* This space left intentionally blank.
|
||||||
|
*
|
||||||
* Return value: a pointer to the gstate's #cairo_clip_t structure.
|
* Return value: a pointer to the gstate's #cairo_clip_t structure.
|
||||||
*/
|
*/
|
||||||
cairo_clip_t *
|
cairo_clip_t *
|
||||||
|
@ -945,6 +949,7 @@ _cairo_gstate_in_stroke (cairo_gstate_t *gstate,
|
||||||
cairo_bool_t *inside_ret)
|
cairo_bool_t *inside_ret)
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
cairo_box_t limit;
|
||||||
cairo_traps_t traps;
|
cairo_traps_t traps;
|
||||||
|
|
||||||
if (gstate->stroke_style.line_width <= 0.0) {
|
if (gstate->stroke_style.line_width <= 0.0) {
|
||||||
|
@ -954,7 +959,13 @@ _cairo_gstate_in_stroke (cairo_gstate_t *gstate,
|
||||||
|
|
||||||
_cairo_gstate_user_to_backend (gstate, &x, &y);
|
_cairo_gstate_user_to_backend (gstate, &x, &y);
|
||||||
|
|
||||||
|
limit.p1.x = _cairo_fixed_from_double (x) - 1;
|
||||||
|
limit.p1.y = _cairo_fixed_from_double (y) - 1;
|
||||||
|
limit.p2.x = limit.p1.x + 2;
|
||||||
|
limit.p2.y = limit.p1.y + 2;
|
||||||
|
|
||||||
_cairo_traps_init (&traps);
|
_cairo_traps_init (&traps);
|
||||||
|
_cairo_traps_limit (&traps, &limit);
|
||||||
|
|
||||||
status = _cairo_path_fixed_stroke_to_traps (path,
|
status = _cairo_path_fixed_stroke_to_traps (path,
|
||||||
&gstate->stroke_style,
|
&gstate->stroke_style,
|
||||||
|
@ -1011,11 +1022,18 @@ _cairo_gstate_in_fill (cairo_gstate_t *gstate,
|
||||||
cairo_bool_t *inside_ret)
|
cairo_bool_t *inside_ret)
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
cairo_box_t limit;
|
||||||
cairo_traps_t traps;
|
cairo_traps_t traps;
|
||||||
|
|
||||||
_cairo_gstate_user_to_backend (gstate, &x, &y);
|
_cairo_gstate_user_to_backend (gstate, &x, &y);
|
||||||
|
|
||||||
|
limit.p1.x = _cairo_fixed_from_double (x) - 1;
|
||||||
|
limit.p1.y = _cairo_fixed_from_double (y) - 1;
|
||||||
|
limit.p2.x = limit.p1.x + 2;
|
||||||
|
limit.p2.y = limit.p1.y + 2;
|
||||||
|
|
||||||
_cairo_traps_init (&traps);
|
_cairo_traps_init (&traps);
|
||||||
|
_cairo_traps_limit (&traps, &limit);
|
||||||
|
|
||||||
status = _cairo_path_fixed_fill_to_traps (path,
|
status = _cairo_path_fixed_fill_to_traps (path,
|
||||||
gstate->fill_rule,
|
gstate->fill_rule,
|
||||||
|
@ -1461,16 +1479,16 @@ _cairo_gstate_get_font_extents (cairo_gstate_t *gstate,
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_status_t
|
cairo_status_t
|
||||||
_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
|
_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
|
||||||
double x,
|
double x,
|
||||||
double y,
|
double y,
|
||||||
const char *utf8,
|
const char *utf8,
|
||||||
int utf8_len,
|
int utf8_len,
|
||||||
cairo_glyph_t **glyphs,
|
cairo_glyph_t **glyphs,
|
||||||
int *num_glyphs,
|
int *num_glyphs,
|
||||||
cairo_text_cluster_t **clusters,
|
cairo_text_cluster_t **clusters,
|
||||||
int *num_clusters,
|
int *num_clusters,
|
||||||
cairo_bool_t *backward)
|
cairo_text_cluster_flags_t *cluster_flags)
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
|
||||||
|
@ -1482,7 +1500,7 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
|
||||||
utf8, utf8_len,
|
utf8, utf8_len,
|
||||||
glyphs, num_glyphs,
|
glyphs, num_glyphs,
|
||||||
clusters, num_clusters,
|
clusters, num_clusters,
|
||||||
backward);
|
cluster_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_status_t
|
cairo_status_t
|
||||||
|
@ -1522,12 +1540,6 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
|
||||||
return cairo_scaled_font_status (gstate->scaled_font);
|
return cairo_scaled_font_status (gstate->scaled_font);
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_bool_t
|
|
||||||
_cairo_gstate_has_show_text_glyphs (cairo_gstate_t *gstate)
|
|
||||||
{
|
|
||||||
return cairo_surface_has_show_text_glyphs (gstate->target);
|
|
||||||
}
|
|
||||||
|
|
||||||
cairo_status_t
|
cairo_status_t
|
||||||
_cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
_cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
||||||
const char *utf8,
|
const char *utf8,
|
||||||
|
@ -1536,7 +1548,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
const cairo_text_cluster_t *clusters,
|
const cairo_text_cluster_t *clusters,
|
||||||
int num_clusters,
|
int num_clusters,
|
||||||
cairo_bool_t backward)
|
cairo_text_cluster_flags_t cluster_flags)
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
cairo_pattern_union_t source_pattern;
|
cairo_pattern_union_t source_pattern;
|
||||||
|
@ -1562,10 +1574,12 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
_cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
|
status = _cairo_gstate_transform_glyphs_to_backend (gstate,
|
||||||
transformed_glyphs, &num_glyphs);
|
glyphs, num_glyphs,
|
||||||
|
transformed_glyphs,
|
||||||
|
&num_glyphs);
|
||||||
|
|
||||||
if (!num_glyphs)
|
if (status || num_glyphs == 0)
|
||||||
goto CLEANUP_GLYPHS;
|
goto CLEANUP_GLYPHS;
|
||||||
|
|
||||||
status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
|
status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
|
||||||
|
@ -1586,7 +1600,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
||||||
* fast rasterizer in cairo, we may want to readjust this.
|
* fast rasterizer in cairo, we may want to readjust this.
|
||||||
*
|
*
|
||||||
* Needless to say, do this only if show_text_glyphs is not available. */
|
* Needless to say, do this only if show_text_glyphs is not available. */
|
||||||
if (_cairo_gstate_has_show_text_glyphs (gstate) ||
|
if (cairo_surface_has_show_text_glyphs (gstate->target) ||
|
||||||
_cairo_scaled_font_get_max_scale (gstate->scaled_font) <= 10240) {
|
_cairo_scaled_font_get_max_scale (gstate->scaled_font) <= 10240) {
|
||||||
status = _cairo_surface_show_text_glyphs (gstate->target,
|
status = _cairo_surface_show_text_glyphs (gstate->target,
|
||||||
gstate->op,
|
gstate->op,
|
||||||
|
@ -1594,18 +1608,16 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
||||||
utf8, utf8_len,
|
utf8, utf8_len,
|
||||||
transformed_glyphs, num_glyphs,
|
transformed_glyphs, num_glyphs,
|
||||||
clusters, num_clusters,
|
clusters, num_clusters,
|
||||||
backward,
|
cluster_flags,
|
||||||
gstate->scaled_font);
|
gstate->scaled_font);
|
||||||
} else {
|
} else {
|
||||||
cairo_path_fixed_t path;
|
cairo_path_fixed_t path;
|
||||||
|
|
||||||
_cairo_path_fixed_init (&path);
|
_cairo_path_fixed_init (&path);
|
||||||
|
|
||||||
CAIRO_MUTEX_LOCK (gstate->scaled_font->mutex);
|
|
||||||
status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
|
status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
|
||||||
transformed_glyphs, num_glyphs,
|
transformed_glyphs, num_glyphs,
|
||||||
&path);
|
&path);
|
||||||
CAIRO_MUTEX_UNLOCK (gstate->scaled_font->mutex);
|
|
||||||
|
|
||||||
if (status == CAIRO_STATUS_SUCCESS)
|
if (status == CAIRO_STATUS_SUCCESS)
|
||||||
status = _cairo_surface_fill (gstate->target,
|
status = _cairo_surface_fill (gstate->target,
|
||||||
|
@ -1649,15 +1661,18 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
|
||||||
if (transformed_glyphs == NULL)
|
if (transformed_glyphs == NULL)
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
|
|
||||||
_cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
|
status = _cairo_gstate_transform_glyphs_to_backend (gstate,
|
||||||
transformed_glyphs, NULL);
|
glyphs, num_glyphs,
|
||||||
|
transformed_glyphs,
|
||||||
|
NULL);
|
||||||
|
if (status)
|
||||||
|
goto CLEANUP_GLYPHS;
|
||||||
|
|
||||||
CAIRO_MUTEX_LOCK (gstate->scaled_font->mutex);
|
|
||||||
status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
|
status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
|
||||||
transformed_glyphs, num_glyphs,
|
transformed_glyphs, num_glyphs,
|
||||||
path);
|
path);
|
||||||
CAIRO_MUTEX_UNLOCK (gstate->scaled_font->mutex);
|
|
||||||
|
|
||||||
|
CLEANUP_GLYPHS:
|
||||||
if (transformed_glyphs != stack_transformed_glyphs)
|
if (transformed_glyphs != stack_transformed_glyphs)
|
||||||
cairo_glyph_free (transformed_glyphs);
|
cairo_glyph_free (transformed_glyphs);
|
||||||
|
|
||||||
|
@ -1697,7 +1712,7 @@ _cairo_gstate_get_antialias (cairo_gstate_t *gstate)
|
||||||
* This also uses information from the scaled font and the surface to
|
* This also uses information from the scaled font and the surface to
|
||||||
* cull/drop glyphs that will not be visible.
|
* cull/drop glyphs that will not be visible.
|
||||||
**/
|
**/
|
||||||
static void
|
static cairo_status_t
|
||||||
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
|
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
|
||||||
const cairo_glyph_t *glyphs,
|
const cairo_glyph_t *glyphs,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
|
@ -1710,20 +1725,24 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
|
||||||
cairo_matrix_t *device_transform = &gstate->target->device_transform;
|
cairo_matrix_t *device_transform = &gstate->target->device_transform;
|
||||||
cairo_bool_t drop = FALSE;
|
cairo_bool_t drop = FALSE;
|
||||||
double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
|
double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
|
||||||
|
cairo_status_t status;
|
||||||
|
|
||||||
if (num_transformed_glyphs != NULL) {
|
if (num_transformed_glyphs != NULL) {
|
||||||
cairo_rectangle_int_t surface_extents;
|
cairo_rectangle_int_t surface_extents;
|
||||||
double scale = _cairo_scaled_font_get_max_scale (gstate->scaled_font);
|
double scale = _cairo_scaled_font_get_max_scale (gstate->scaled_font);
|
||||||
|
|
||||||
drop = TRUE;
|
drop = TRUE;
|
||||||
|
status = _cairo_gstate_int_clip_extents (gstate, &surface_extents);
|
||||||
|
if (_cairo_status_is_error (status))
|
||||||
|
return status;
|
||||||
|
|
||||||
if (_cairo_gstate_int_clip_extents (gstate, &surface_extents))
|
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||||
drop = FALSE; /* unbounded surface */
|
drop = FALSE; /* unbounded surface */
|
||||||
else {
|
} else {
|
||||||
if (surface_extents.width == 0 || surface_extents.height == 0) {
|
if (surface_extents.width == 0 || surface_extents.height == 0) {
|
||||||
/* No visible area. Don't draw anything */
|
/* No visible area. Don't draw anything */
|
||||||
*num_transformed_glyphs = 0;
|
*num_transformed_glyphs = 0;
|
||||||
return;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
/* XXX We currently drop any glyphs that has its position outside
|
/* XXX We currently drop any glyphs that has its position outside
|
||||||
* of the surface boundaries by a safety margin depending on the
|
* of the surface boundaries by a safety margin depending on the
|
||||||
|
@ -1803,4 +1822,6 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
|
||||||
}
|
}
|
||||||
*num_transformed_glyphs = j;
|
*num_transformed_glyphs = j;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,13 @@ _cairo_hull_init (cairo_hull_t *hull,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline cairo_int64_t
|
||||||
|
_slope_length (cairo_slope_t *slope)
|
||||||
|
{
|
||||||
|
return _cairo_int64_add (_cairo_int32x32_64_mul (slope->dx, slope->dx),
|
||||||
|
_cairo_int32x32_64_mul (slope->dy, slope->dy));
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_cairo_hull_vertex_compare (const void *av, const void *bv)
|
_cairo_hull_vertex_compare (const void *av, const void *bv)
|
||||||
{
|
{
|
||||||
|
@ -87,21 +94,21 @@ _cairo_hull_vertex_compare (const void *av, const void *bv)
|
||||||
|
|
||||||
ret = _cairo_slope_compare (&a->slope, &b->slope);
|
ret = _cairo_slope_compare (&a->slope, &b->slope);
|
||||||
|
|
||||||
/* In the case of two vertices with identical slope from the
|
/*
|
||||||
extremal point discard the nearer point. */
|
* In the case of two vertices with identical slope from the
|
||||||
|
* extremal point discard the nearer point.
|
||||||
|
*/
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
cairo_fixed_48_16_t a_dist, b_dist;
|
int cmp;
|
||||||
a_dist = ((cairo_fixed_48_16_t) a->slope.dx * a->slope.dx +
|
|
||||||
(cairo_fixed_48_16_t) a->slope.dy * a->slope.dy);
|
cmp = _cairo_int64_cmp (_slope_length (&a->slope),
|
||||||
b_dist = ((cairo_fixed_48_16_t) b->slope.dx * b->slope.dx +
|
_slope_length (&b->slope));
|
||||||
(cairo_fixed_48_16_t) b->slope.dy * b->slope.dy);
|
|
||||||
/*
|
/*
|
||||||
* Use the point's ids to ensure a total ordering.
|
* Use the points' ids to ensure a well-defined ordering,
|
||||||
* a well-defined ordering, and avoid setting discard on
|
* and avoid setting discard on both points.
|
||||||
* both points.
|
|
||||||
*/
|
*/
|
||||||
if (a_dist < b_dist || (a_dist == b_dist && a->id < b->id)) {
|
if (cmp < 0 || (cmp == 0 && a->id < b->id)) {
|
||||||
a->discard = 1;
|
a->discard = 1;
|
||||||
ret = -1;
|
ret = -1;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -60,6 +60,10 @@ _cairo_format_from_pixman_format (pixman_format_code_t pixman_format)
|
||||||
case PIXMAN_a1r1g1b1: case PIXMAN_a1b1g1r1: case PIXMAN_c4:
|
case PIXMAN_a1r1g1b1: case PIXMAN_a1b1g1r1: case PIXMAN_c4:
|
||||||
case PIXMAN_g4: case PIXMAN_g1:
|
case PIXMAN_g4: case PIXMAN_g1:
|
||||||
case PIXMAN_yuy2: case PIXMAN_yv12:
|
case PIXMAN_yuy2: case PIXMAN_yv12:
|
||||||
|
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9)
|
||||||
|
case PIXMAN_x2b10g10r10:
|
||||||
|
case PIXMAN_a2b10g10r10:
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
return CAIRO_FORMAT_INVALID;
|
return CAIRO_FORMAT_INVALID;
|
||||||
}
|
}
|
||||||
|
@ -81,6 +85,9 @@ _cairo_content_from_pixman_format (pixman_format_code_t pixman_format)
|
||||||
case PIXMAN_a2b2g2r2:
|
case PIXMAN_a2b2g2r2:
|
||||||
case PIXMAN_a1r1g1b1:
|
case PIXMAN_a1r1g1b1:
|
||||||
case PIXMAN_a1b1g1r1:
|
case PIXMAN_a1b1g1r1:
|
||||||
|
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9)
|
||||||
|
case PIXMAN_a2b10g10r10:
|
||||||
|
#endif
|
||||||
return CAIRO_CONTENT_COLOR_ALPHA;
|
return CAIRO_CONTENT_COLOR_ALPHA;
|
||||||
case PIXMAN_x8r8g8b8:
|
case PIXMAN_x8r8g8b8:
|
||||||
case PIXMAN_x8b8g8r8:
|
case PIXMAN_x8b8g8r8:
|
||||||
|
@ -103,6 +110,9 @@ _cairo_content_from_pixman_format (pixman_format_code_t pixman_format)
|
||||||
case PIXMAN_g1:
|
case PIXMAN_g1:
|
||||||
case PIXMAN_yuy2:
|
case PIXMAN_yuy2:
|
||||||
case PIXMAN_yv12:
|
case PIXMAN_yv12:
|
||||||
|
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9)
|
||||||
|
case PIXMAN_x2b10g10r10:
|
||||||
|
#endif
|
||||||
return CAIRO_CONTENT_COLOR;
|
return CAIRO_CONTENT_COLOR;
|
||||||
case PIXMAN_a8:
|
case PIXMAN_a8:
|
||||||
case PIXMAN_a1:
|
case PIXMAN_a1:
|
||||||
|
@ -144,7 +154,7 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
|
||||||
return &surface->base;
|
return &surface->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_int_status_t
|
cairo_bool_t
|
||||||
_pixman_format_from_masks (cairo_format_masks_t *masks,
|
_pixman_format_from_masks (cairo_format_masks_t *masks,
|
||||||
pixman_format_code_t *format_ret)
|
pixman_format_code_t *format_ret)
|
||||||
{
|
{
|
||||||
|
@ -166,13 +176,13 @@ _pixman_format_from_masks (cairo_format_masks_t *masks,
|
||||||
} else if (masks->alpha_mask) {
|
} else if (masks->alpha_mask) {
|
||||||
format_type = PIXMAN_TYPE_A;
|
format_type = PIXMAN_TYPE_A;
|
||||||
} else {
|
} else {
|
||||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
format = PIXMAN_FORMAT (masks->bpp, format_type, a, r, g, b);
|
format = PIXMAN_FORMAT (masks->bpp, format_type, a, r, g, b);
|
||||||
|
|
||||||
if (! pixman_format_supported_destination (format))
|
if (! pixman_format_supported_destination (format))
|
||||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
return FALSE;
|
||||||
|
|
||||||
/* Sanity check that we got out of PIXMAN_FORMAT exactly what we
|
/* Sanity check that we got out of PIXMAN_FORMAT exactly what we
|
||||||
* expected. This avoid any problems from something bizarre like
|
* expected. This avoid any problems from something bizarre like
|
||||||
|
@ -185,11 +195,11 @@ _pixman_format_from_masks (cairo_format_masks_t *masks,
|
||||||
masks->green_mask != format_masks.green_mask ||
|
masks->green_mask != format_masks.green_mask ||
|
||||||
masks->blue_mask != format_masks.blue_mask)
|
masks->blue_mask != format_masks.blue_mask)
|
||||||
{
|
{
|
||||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*format_ret = format;
|
*format_ret = format;
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A mask consisting of N bits set to 1. */
|
/* A mask consisting of N bits set to 1. */
|
||||||
|
@ -253,11 +263,9 @@ _cairo_image_surface_create_with_masks (unsigned char *data,
|
||||||
int height,
|
int height,
|
||||||
int stride)
|
int stride)
|
||||||
{
|
{
|
||||||
cairo_int_status_t status;
|
|
||||||
pixman_format_code_t pixman_format;
|
pixman_format_code_t pixman_format;
|
||||||
|
|
||||||
status = _pixman_format_from_masks (masks, &pixman_format);
|
if (! _pixman_format_from_masks (masks, &pixman_format)) {
|
||||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"Error: Cairo %s does not yet support the requested image format:\n"
|
"Error: Cairo %s does not yet support the requested image format:\n"
|
||||||
"\tDepth: %d\n"
|
"\tDepth: %d\n"
|
||||||
|
@ -265,8 +273,11 @@ _cairo_image_surface_create_with_masks (unsigned char *data,
|
||||||
"\tRed mask: 0x%08lx\n"
|
"\tRed mask: 0x%08lx\n"
|
||||||
"\tGreen mask: 0x%08lx\n"
|
"\tGreen mask: 0x%08lx\n"
|
||||||
"\tBlue mask: 0x%08lx\n"
|
"\tBlue mask: 0x%08lx\n"
|
||||||
|
#ifdef PACKAGE_BUGGREPORT
|
||||||
"Please file an enhancement request (quoting the above) at:\n"
|
"Please file an enhancement request (quoting the above) at:\n"
|
||||||
PACKAGE_BUGREPORT "\n",
|
PACKAGE_BUGREPORT"\n"
|
||||||
|
#endif
|
||||||
|
,
|
||||||
cairo_version_string (),
|
cairo_version_string (),
|
||||||
masks->bpp, masks->alpha_mask,
|
masks->bpp, masks->alpha_mask,
|
||||||
masks->red_mask, masks->green_mask, masks->blue_mask);
|
masks->red_mask, masks->green_mask, masks->blue_mask);
|
||||||
|
@ -473,6 +484,7 @@ cairo_image_surface_create_for_data (unsigned char *data,
|
||||||
int stride)
|
int stride)
|
||||||
{
|
{
|
||||||
pixman_format_code_t pixman_format;
|
pixman_format_code_t pixman_format;
|
||||||
|
int minstride;
|
||||||
|
|
||||||
if (! CAIRO_FORMAT_VALID (format))
|
if (! CAIRO_FORMAT_VALID (format))
|
||||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
|
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
|
||||||
|
@ -480,6 +492,17 @@ cairo_image_surface_create_for_data (unsigned char *data,
|
||||||
if ((stride & (CAIRO_STRIDE_ALIGNMENT-1)) != 0)
|
if ((stride & (CAIRO_STRIDE_ALIGNMENT-1)) != 0)
|
||||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
|
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
|
||||||
|
|
||||||
|
minstride = cairo_format_stride_for_width (format, width);
|
||||||
|
if (stride < 0) {
|
||||||
|
if (stride > -minstride) {
|
||||||
|
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (stride < minstride) {
|
||||||
|
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pixman_format = _cairo_format_to_pixman_format_code (format);
|
pixman_format = _cairo_format_to_pixman_format_code (format);
|
||||||
|
|
||||||
return _cairo_image_surface_create_with_pixman_format (data, pixman_format,
|
return _cairo_image_surface_create_with_pixman_format (data, pixman_format,
|
||||||
|
@ -510,7 +533,8 @@ _cairo_image_surface_create_for_data_with_content (unsigned char *data,
|
||||||
* inspection or modification.
|
* inspection or modification.
|
||||||
*
|
*
|
||||||
* Return value: a pointer to the image data of this surface or %NULL
|
* Return value: a pointer to the image data of this surface or %NULL
|
||||||
* if @surface is not an image surface.
|
* if @surface is not an image surface, or if cairo_surface_finish()
|
||||||
|
* has been called.
|
||||||
*
|
*
|
||||||
* Since: 1.2
|
* Since: 1.2
|
||||||
**/
|
**/
|
||||||
|
@ -548,8 +572,6 @@ cairo_image_surface_get_format (cairo_surface_t *surface)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert (CAIRO_FORMAT_VALID (image_surface->format));
|
|
||||||
|
|
||||||
return image_surface->format;
|
return image_surface->format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -766,11 +788,14 @@ _cairo_image_surface_clone_similar (void *abstract_surface,
|
||||||
int src_y,
|
int src_y,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
|
int *clone_offset_x,
|
||||||
|
int *clone_offset_y,
|
||||||
cairo_surface_t **clone_out)
|
cairo_surface_t **clone_out)
|
||||||
{
|
{
|
||||||
cairo_image_surface_t *surface = abstract_surface;
|
cairo_image_surface_t *surface = abstract_surface;
|
||||||
|
|
||||||
if (src->backend == surface->base.backend) {
|
if (src->backend == surface->base.backend) {
|
||||||
|
*clone_offset_x = *clone_offset_y = 0;
|
||||||
*clone_out = cairo_surface_reference (src);
|
*clone_out = cairo_surface_reference (src);
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
|
|
@ -624,6 +624,35 @@ _cairo_matrix_is_integer_translation (const cairo_matrix_t *matrix,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* By pixel exact here, we mean a matrix that is composed only of
|
||||||
|
* 90 degree rotations, flips, and integer translations and produces a 1:1
|
||||||
|
* mapping between source and destination pixels. If we transform an image
|
||||||
|
* with a pixel-exact matrix, filtering is not useful.
|
||||||
|
*/
|
||||||
|
cairo_private cairo_bool_t
|
||||||
|
_cairo_matrix_is_pixel_exact (const cairo_matrix_t *matrix)
|
||||||
|
{
|
||||||
|
cairo_fixed_t x0_fixed, y0_fixed;
|
||||||
|
|
||||||
|
if (matrix->xy == 0.0 && matrix->yx == 0.0) {
|
||||||
|
if (! (matrix->xx == 1.0 || matrix->xx == -1.0))
|
||||||
|
return FALSE;
|
||||||
|
if (! (matrix->yy == 1.0 || matrix->yy == -1.0))
|
||||||
|
return FALSE;
|
||||||
|
} else if (matrix->xx == 0.0 && matrix->yy == 0.0) {
|
||||||
|
if (! (matrix->xy == 1.0 || matrix->xy == -1.0))
|
||||||
|
return FALSE;
|
||||||
|
if (! (matrix->yx == 1.0 || matrix->yx == -1.0))
|
||||||
|
return FALSE;
|
||||||
|
} else
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
x0_fixed = _cairo_fixed_from_double (matrix->x0);
|
||||||
|
y0_fixed = _cairo_fixed_from_double (matrix->y0);
|
||||||
|
|
||||||
|
return _cairo_fixed_is_integer (x0_fixed) && _cairo_fixed_is_integer (y0_fixed);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A circle in user space is transformed into an ellipse in device space.
|
A circle in user space is transformed into an ellipse in device space.
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ typedef struct _cairo_command_show_text_glyphs {
|
||||||
unsigned int num_glyphs;
|
unsigned int num_glyphs;
|
||||||
cairo_text_cluster_t *clusters;
|
cairo_text_cluster_t *clusters;
|
||||||
int num_clusters;
|
int num_clusters;
|
||||||
cairo_bool_t backward;
|
cairo_text_cluster_flags_t cluster_flags;
|
||||||
cairo_scaled_font_t *scaled_font;
|
cairo_scaled_font_t *scaled_font;
|
||||||
} cairo_command_show_text_glyphs_t;
|
} cairo_command_show_text_glyphs_t;
|
||||||
|
|
||||||
|
|
|
@ -216,32 +216,6 @@ _cairo_meta_surface_release_source_image (void *abstract_surface,
|
||||||
cairo_surface_destroy (&image->base);
|
cairo_surface_destroy (&image->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cairo_status_t
|
|
||||||
_init_pattern_with_snapshot (cairo_pattern_t *pattern,
|
|
||||||
const cairo_pattern_t *other)
|
|
||||||
{
|
|
||||||
cairo_status_t status;
|
|
||||||
|
|
||||||
status = _cairo_pattern_init_copy (pattern, other);
|
|
||||||
if (status)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
|
||||||
cairo_surface_pattern_t *surface_pattern =
|
|
||||||
(cairo_surface_pattern_t *) pattern;
|
|
||||||
cairo_surface_t *surface = surface_pattern->surface;
|
|
||||||
|
|
||||||
surface_pattern->surface = _cairo_surface_snapshot (surface);
|
|
||||||
|
|
||||||
cairo_surface_destroy (surface);
|
|
||||||
|
|
||||||
if (surface_pattern->surface->status)
|
|
||||||
return surface_pattern->surface->status;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static cairo_int_status_t
|
static cairo_int_status_t
|
||||||
_cairo_meta_surface_paint (void *abstract_surface,
|
_cairo_meta_surface_paint (void *abstract_surface,
|
||||||
cairo_operator_t op,
|
cairo_operator_t op,
|
||||||
|
@ -259,7 +233,7 @@ _cairo_meta_surface_paint (void *abstract_surface,
|
||||||
command->header.region = CAIRO_META_REGION_ALL;
|
command->header.region = CAIRO_META_REGION_ALL;
|
||||||
command->op = op;
|
command->op = op;
|
||||||
|
|
||||||
status = _init_pattern_with_snapshot (&command->source.base, source);
|
status = _cairo_pattern_init_snapshot (&command->source.base, source);
|
||||||
if (status)
|
if (status)
|
||||||
goto CLEANUP_COMMAND;
|
goto CLEANUP_COMMAND;
|
||||||
|
|
||||||
|
@ -300,11 +274,11 @@ _cairo_meta_surface_mask (void *abstract_surface,
|
||||||
command->header.region = CAIRO_META_REGION_ALL;
|
command->header.region = CAIRO_META_REGION_ALL;
|
||||||
command->op = op;
|
command->op = op;
|
||||||
|
|
||||||
status = _init_pattern_with_snapshot (&command->source.base, source);
|
status = _cairo_pattern_init_snapshot (&command->source.base, source);
|
||||||
if (status)
|
if (status)
|
||||||
goto CLEANUP_COMMAND;
|
goto CLEANUP_COMMAND;
|
||||||
|
|
||||||
status = _init_pattern_with_snapshot (&command->mask.base, mask);
|
status = _cairo_pattern_init_snapshot (&command->mask.base, mask);
|
||||||
if (status)
|
if (status)
|
||||||
goto CLEANUP_SOURCE;
|
goto CLEANUP_SOURCE;
|
||||||
|
|
||||||
|
@ -346,7 +320,7 @@ _cairo_meta_surface_stroke (void *abstract_surface,
|
||||||
command->header.region = CAIRO_META_REGION_ALL;
|
command->header.region = CAIRO_META_REGION_ALL;
|
||||||
command->op = op;
|
command->op = op;
|
||||||
|
|
||||||
status = _init_pattern_with_snapshot (&command->source.base, source);
|
status = _cairo_pattern_init_snapshot (&command->source.base, source);
|
||||||
if (status)
|
if (status)
|
||||||
goto CLEANUP_COMMAND;
|
goto CLEANUP_COMMAND;
|
||||||
|
|
||||||
|
@ -401,7 +375,7 @@ _cairo_meta_surface_fill (void *abstract_surface,
|
||||||
command->header.region = CAIRO_META_REGION_ALL;
|
command->header.region = CAIRO_META_REGION_ALL;
|
||||||
command->op = op;
|
command->op = op;
|
||||||
|
|
||||||
status = _init_pattern_with_snapshot (&command->source.base, source);
|
status = _cairo_pattern_init_snapshot (&command->source.base, source);
|
||||||
if (status)
|
if (status)
|
||||||
goto CLEANUP_COMMAND;
|
goto CLEANUP_COMMAND;
|
||||||
|
|
||||||
|
@ -444,7 +418,7 @@ _cairo_meta_surface_show_text_glyphs (void *abstract_surface,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
const cairo_text_cluster_t *clusters,
|
const cairo_text_cluster_t *clusters,
|
||||||
int num_clusters,
|
int num_clusters,
|
||||||
cairo_bool_t backward,
|
cairo_text_cluster_flags_t cluster_flags,
|
||||||
cairo_scaled_font_t *scaled_font)
|
cairo_scaled_font_t *scaled_font)
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
@ -459,7 +433,7 @@ _cairo_meta_surface_show_text_glyphs (void *abstract_surface,
|
||||||
command->header.region = CAIRO_META_REGION_ALL;
|
command->header.region = CAIRO_META_REGION_ALL;
|
||||||
command->op = op;
|
command->op = op;
|
||||||
|
|
||||||
status = _init_pattern_with_snapshot (&command->source.base, source);
|
status = _cairo_pattern_init_snapshot (&command->source.base, source);
|
||||||
if (status)
|
if (status)
|
||||||
goto CLEANUP_COMMAND;
|
goto CLEANUP_COMMAND;
|
||||||
|
|
||||||
|
@ -495,7 +469,7 @@ _cairo_meta_surface_show_text_glyphs (void *abstract_surface,
|
||||||
memcpy (command->clusters, clusters, sizeof (clusters[0]) * num_clusters);
|
memcpy (command->clusters, clusters, sizeof (clusters[0]) * num_clusters);
|
||||||
}
|
}
|
||||||
|
|
||||||
command->backward = backward;
|
command->cluster_flags = cluster_flags;
|
||||||
|
|
||||||
command->scaled_font = cairo_scaled_font_reference (scaled_font);
|
command->scaled_font = cairo_scaled_font_reference (scaled_font);
|
||||||
|
|
||||||
|
@ -848,7 +822,7 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
|
||||||
if (has_device_transform) {
|
if (has_device_transform) {
|
||||||
cairo_matrix_multiply (&dev_ctm, &dev_ctm, device_transform);
|
cairo_matrix_multiply (&dev_ctm, &dev_ctm, device_transform);
|
||||||
cairo_matrix_multiply (&dev_ctm_inverse,
|
cairo_matrix_multiply (&dev_ctm_inverse,
|
||||||
&surface->device_transform_inverse,
|
&target->device_transform_inverse,
|
||||||
&dev_ctm_inverse);
|
&dev_ctm_inverse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -952,7 +926,7 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
|
||||||
command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len,
|
command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len,
|
||||||
dev_glyphs, num_glyphs,
|
dev_glyphs, num_glyphs,
|
||||||
command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters,
|
command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters,
|
||||||
command->show_text_glyphs.backward,
|
command->show_text_glyphs.cluster_flags,
|
||||||
command->show_text_glyphs.scaled_font);
|
command->show_text_glyphs.scaled_font);
|
||||||
|
|
||||||
free (dev_glyphs);
|
free (dev_glyphs);
|
||||||
|
|
|
@ -240,7 +240,7 @@ slim_hidden_def (cairo_text_cluster_free);
|
||||||
* @num_glyphs: number of glyphs
|
* @num_glyphs: number of glyphs
|
||||||
* @clusters: array of cluster mapping information
|
* @clusters: array of cluster mapping information
|
||||||
* @num_clusters: number of clusters in the mapping
|
* @num_clusters: number of clusters in the mapping
|
||||||
* @backward: whether the text to glyphs mapping goes backward
|
* @cluster_flags: cluster flags
|
||||||
*
|
*
|
||||||
* Check that clusters cover the entire glyphs and utf8 arrays,
|
* Check that clusters cover the entire glyphs and utf8 arrays,
|
||||||
* and that cluster boundaries are UTF-8 boundaries.
|
* and that cluster boundaries are UTF-8 boundaries.
|
||||||
|
@ -257,7 +257,7 @@ _cairo_validate_text_clusters (const char *utf8,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
const cairo_text_cluster_t *clusters,
|
const cairo_text_cluster_t *clusters,
|
||||||
int num_clusters,
|
int num_clusters,
|
||||||
cairo_bool_t backward)
|
cairo_text_cluster_flags_t cluster_flags)
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
unsigned int n_bytes = 0;
|
unsigned int n_bytes = 0;
|
||||||
|
|
|
@ -41,10 +41,15 @@
|
||||||
#ifndef CAIRO_MUTEX_IMPL_PRIVATE_H
|
#ifndef CAIRO_MUTEX_IMPL_PRIVATE_H
|
||||||
#define CAIRO_MUTEX_IMPL_PRIVATE_H
|
#define CAIRO_MUTEX_IMPL_PRIVATE_H
|
||||||
|
|
||||||
|
#include "cairo.h"
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
#if HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_LOCKDEP
|
||||||
|
#include <lockdep.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* A fully qualified no-operation statement */
|
/* A fully qualified no-operation statement */
|
||||||
#define CAIRO_MUTEX_IMPL_NOOP do {/*no-op*/} while (0)
|
#define CAIRO_MUTEX_IMPL_NOOP do {/*no-op*/} while (0)
|
||||||
|
@ -72,6 +77,9 @@
|
||||||
* cairo_mutex_impl_t _cairo_some_mutex;
|
* cairo_mutex_impl_t _cairo_some_mutex;
|
||||||
* </programlisting>
|
* </programlisting>
|
||||||
*
|
*
|
||||||
|
* - #define %CAIRO_MUTEX_IMPL_<NAME> 1 with suitable name for your platform. You
|
||||||
|
* can later use this symbol in cairo-system.c.
|
||||||
|
*
|
||||||
* - #define CAIRO_MUTEX_IMPL_LOCK(mutex) and CAIRO_MUTEX_IMPL_UNLOCK(mutex) to
|
* - #define CAIRO_MUTEX_IMPL_LOCK(mutex) and CAIRO_MUTEX_IMPL_UNLOCK(mutex) to
|
||||||
* proper statement to lock/unlock the mutex object passed in.
|
* proper statement to lock/unlock the mutex object passed in.
|
||||||
* You can (and should) assume that the mutex is already
|
* You can (and should) assume that the mutex is already
|
||||||
|
@ -147,16 +155,13 @@
|
||||||
* poke around cairo-mutex-private.h for possible solutions.
|
* poke around cairo-mutex-private.h for possible solutions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CAIRO_MUTEX_TYPE_PRIVATE_H
|
|
||||||
#error "Do not include cairo-mutex-impl-private.h directly. Include cairo-mutex-type-private.h instead."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CAIRO_NO_MUTEX
|
#if CAIRO_NO_MUTEX
|
||||||
|
|
||||||
/* No mutexes */
|
/* No mutexes */
|
||||||
|
|
||||||
typedef int cairo_mutex_impl_t;
|
typedef int cairo_mutex_impl_t;
|
||||||
|
|
||||||
|
# define CAIRO_MUTEX_IMPL_NO 1
|
||||||
# define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP
|
# define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP
|
||||||
# define CAIRO_MUTEX_IMPL_LOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex)
|
# define CAIRO_MUTEX_IMPL_LOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex)
|
||||||
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex)
|
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex)
|
||||||
|
@ -168,18 +173,30 @@
|
||||||
|
|
||||||
typedef pthread_mutex_t cairo_mutex_impl_t;
|
typedef pthread_mutex_t cairo_mutex_impl_t;
|
||||||
|
|
||||||
|
# define CAIRO_MUTEX_IMPL_PTHREAD 1
|
||||||
|
#if HAVE_LOCKDEP
|
||||||
|
/* expose all mutexes to the validator */
|
||||||
|
# define CAIRO_MUTEX_IMPL_INIT(mutex) pthread_mutex_init (&(mutex), NULL)
|
||||||
|
#endif
|
||||||
# define CAIRO_MUTEX_IMPL_LOCK(mutex) pthread_mutex_lock (&(mutex))
|
# define CAIRO_MUTEX_IMPL_LOCK(mutex) pthread_mutex_lock (&(mutex))
|
||||||
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) pthread_mutex_unlock (&(mutex))
|
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) pthread_mutex_unlock (&(mutex))
|
||||||
|
#if HAVE_LOCKDEP
|
||||||
|
# define CAIRO_MUTEX_IS_LOCKED(mutex) LOCKDEP_IS_LOCKED (&(mutex))
|
||||||
|
# define CAIRO_MUTEX_IS_UNLOCKED(mutex) LOCKDEP_IS_UNLOCKED (&(mutex))
|
||||||
|
#endif
|
||||||
# define CAIRO_MUTEX_IMPL_FINI(mutex) pthread_mutex_destroy (&(mutex))
|
# define CAIRO_MUTEX_IMPL_FINI(mutex) pthread_mutex_destroy (&(mutex))
|
||||||
|
#if ! HAVE_LOCKDEP
|
||||||
# define CAIRO_MUTEX_IMPL_FINALIZE() CAIRO_MUTEX_IMPL_NOOP
|
# define CAIRO_MUTEX_IMPL_FINALIZE() CAIRO_MUTEX_IMPL_NOOP
|
||||||
|
#endif
|
||||||
# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER PTHREAD_MUTEX_INITIALIZER
|
# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER PTHREAD_MUTEX_INITIALIZER
|
||||||
|
|
||||||
#elif HAVE_WINDOWS_H /*******************************************************/
|
#elif defined(HAVE_WINDOWS_H) || defined(_MSC_VER) /*************************/
|
||||||
|
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
|
|
||||||
typedef CRITICAL_SECTION cairo_mutex_impl_t;
|
typedef CRITICAL_SECTION cairo_mutex_impl_t;
|
||||||
|
|
||||||
|
# define CAIRO_MUTEX_IMPL_WIN32 1
|
||||||
# define CAIRO_MUTEX_IMPL_LOCK(mutex) EnterCriticalSection (&(mutex))
|
# define CAIRO_MUTEX_IMPL_LOCK(mutex) EnterCriticalSection (&(mutex))
|
||||||
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) LeaveCriticalSection (&(mutex))
|
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) LeaveCriticalSection (&(mutex))
|
||||||
# define CAIRO_MUTEX_IMPL_INIT(mutex) InitializeCriticalSection (&(mutex))
|
# define CAIRO_MUTEX_IMPL_INIT(mutex) InitializeCriticalSection (&(mutex))
|
||||||
|
@ -194,6 +211,7 @@
|
||||||
|
|
||||||
typedef HMTX cairo_mutex_impl_t;
|
typedef HMTX cairo_mutex_impl_t;
|
||||||
|
|
||||||
|
# define CAIRO_MUTEX_IMPL_OS2 1
|
||||||
# define CAIRO_MUTEX_IMPL_LOCK(mutex) DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT)
|
# define CAIRO_MUTEX_IMPL_LOCK(mutex) DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT)
|
||||||
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) DosReleaseMutexSem(mutex)
|
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) DosReleaseMutexSem(mutex)
|
||||||
# define CAIRO_MUTEX_IMPL_INIT(mutex) DosCreateMutexSem (NULL, &(mutex), 0L, FALSE)
|
# define CAIRO_MUTEX_IMPL_INIT(mutex) DosCreateMutexSem (NULL, &(mutex), 0L, FALSE)
|
||||||
|
@ -204,6 +222,7 @@
|
||||||
|
|
||||||
typedef BLocker* cairo_mutex_impl_t;
|
typedef BLocker* cairo_mutex_impl_t;
|
||||||
|
|
||||||
|
# define CAIRO_MUTEX_IMPL_BEOS 1
|
||||||
# define CAIRO_MUTEX_IMPL_LOCK(mutex) (mutex)->Lock()
|
# define CAIRO_MUTEX_IMPL_LOCK(mutex) (mutex)->Lock()
|
||||||
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) (mutex)->Unlock()
|
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) (mutex)->Unlock()
|
||||||
# define CAIRO_MUTEX_IMPL_INIT(mutex) (mutex) = new BLocker()
|
# define CAIRO_MUTEX_IMPL_INIT(mutex) (mutex) = new BLocker()
|
||||||
|
|
|
@ -31,24 +31,28 @@
|
||||||
* Mathias Hasselmann <mathias.hasselmann@gmx.de>
|
* Mathias Hasselmann <mathias.hasselmann@gmx.de>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef CAIRO_FEATURES_H
|
||||||
|
/* This block is to just make this header file standalone */
|
||||||
|
#define CAIRO_MUTEX_DECLARE(mutex)
|
||||||
|
#endif
|
||||||
|
|
||||||
CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_pattern_cache_lock);
|
CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_pattern_cache_lock)
|
||||||
CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_surface_cache_lock);
|
CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_surface_cache_lock)
|
||||||
|
|
||||||
CAIRO_MUTEX_DECLARE (_cairo_font_face_mutex);
|
CAIRO_MUTEX_DECLARE (_cairo_font_face_mutex)
|
||||||
CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex);
|
CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex)
|
||||||
CAIRO_MUTEX_DECLARE (_cairo_scaled_font_error_mutex);
|
CAIRO_MUTEX_DECLARE (_cairo_scaled_font_error_mutex)
|
||||||
|
|
||||||
#if CAIRO_HAS_FT_FONT
|
#if CAIRO_HAS_FT_FONT
|
||||||
CAIRO_MUTEX_DECLARE (_cairo_ft_unscaled_font_map_mutex);
|
CAIRO_MUTEX_DECLARE (_cairo_ft_unscaled_font_map_mutex)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CAIRO_HAS_XLIB_SURFACE
|
#if CAIRO_HAS_XLIB_SURFACE
|
||||||
CAIRO_MUTEX_DECLARE (_cairo_xlib_display_mutex);
|
CAIRO_MUTEX_DECLARE (_cairo_xlib_display_mutex)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined (CAIRO_HAS_ATOMIC_OPS) || defined (CAIRO_ATOMIC_OP_NEEDS_MEMORY_BARRIER)
|
#if !defined (HAS_ATOMIC_OPS) || defined (ATOMIC_OP_NEEDS_MEMORY_BARRIER)
|
||||||
CAIRO_MUTEX_DECLARE (_cairo_atomic_mutex);
|
CAIRO_MUTEX_DECLARE (_cairo_atomic_mutex)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Undefine, to err on unintended inclusion */
|
/* Undefine, to err on unintended inclusion */
|
||||||
|
|
|
@ -41,10 +41,6 @@
|
||||||
#ifndef CAIRO_MUTEX_PRIVATE_H
|
#ifndef CAIRO_MUTEX_PRIVATE_H
|
||||||
#define CAIRO_MUTEX_PRIVATE_H
|
#define CAIRO_MUTEX_PRIVATE_H
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "cairo-mutex-type-private.h"
|
#include "cairo-mutex-type-private.h"
|
||||||
|
|
||||||
CAIRO_BEGIN_DECLS
|
CAIRO_BEGIN_DECLS
|
||||||
|
@ -62,7 +58,7 @@ cairo_private void _cairo_mutex_finalize (void);
|
||||||
|
|
||||||
/* Finally, extern the static mutexes and undef */
|
/* Finally, extern the static mutexes and undef */
|
||||||
|
|
||||||
#define CAIRO_MUTEX_DECLARE(mutex) cairo_private extern cairo_mutex_t mutex
|
#define CAIRO_MUTEX_DECLARE(mutex) cairo_private extern cairo_mutex_t mutex;
|
||||||
#include "cairo-mutex-list-private.h"
|
#include "cairo-mutex-list-private.h"
|
||||||
#undef CAIRO_MUTEX_DECLARE
|
#undef CAIRO_MUTEX_DECLARE
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,6 @@
|
||||||
|
|
||||||
#endif /* CAIRO_MUTEX_IMPL_INIT */
|
#endif /* CAIRO_MUTEX_IMPL_INIT */
|
||||||
|
|
||||||
|
|
||||||
#ifdef CAIRO_MUTEX_IMPL_FINI
|
#ifdef CAIRO_MUTEX_IMPL_FINI
|
||||||
|
|
||||||
/* If %CAIRO_MUTEX_IMPL_FINI is defined, we may need to finalize all
|
/* If %CAIRO_MUTEX_IMPL_FINI is defined, we may need to finalize all
|
||||||
|
@ -169,6 +168,12 @@ typedef cairo_mutex_impl_t cairo_mutex_t;
|
||||||
#define CAIRO_MUTEX_FINI CAIRO_MUTEX_IMPL_FINI
|
#define CAIRO_MUTEX_FINI CAIRO_MUTEX_IMPL_FINI
|
||||||
#define CAIRO_MUTEX_NIL_INITIALIZER CAIRO_MUTEX_IMPL_NIL_INITIALIZER
|
#define CAIRO_MUTEX_NIL_INITIALIZER CAIRO_MUTEX_IMPL_NIL_INITIALIZER
|
||||||
|
|
||||||
|
#ifndef CAIRO_MUTEX_IS_LOCKED
|
||||||
|
# define CAIRO_MUTEX_IS_LOCKED(name) 1
|
||||||
|
#endif
|
||||||
|
#ifndef CAIRO_MUTEX_IS_UNLOCKED
|
||||||
|
# define CAIRO_MUTEX_IS_UNLOCKED(name) 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Debugging support */
|
/* Debugging support */
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
|
|
||||||
#include "cairo-mutex-private.h"
|
#include "cairo-mutex-private.h"
|
||||||
|
|
||||||
#define CAIRO_MUTEX_DECLARE(mutex) cairo_mutex_t mutex = CAIRO_MUTEX_NIL_INITIALIZER
|
#define CAIRO_MUTEX_DECLARE(mutex) cairo_mutex_t mutex = CAIRO_MUTEX_NIL_INITIALIZER;
|
||||||
#include "cairo-mutex-list-private.h"
|
#include "cairo-mutex-list-private.h"
|
||||||
#undef CAIRO_MUTEX_DECLARE
|
#undef CAIRO_MUTEX_DECLARE
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ void _cairo_mutex_initialize (void)
|
||||||
|
|
||||||
_cairo_mutex_initialized = TRUE;
|
_cairo_mutex_initialized = TRUE;
|
||||||
|
|
||||||
#define CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_INIT (mutex)
|
#define CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_INIT (mutex);
|
||||||
#include "cairo-mutex-list-private.h"
|
#include "cairo-mutex-list-private.h"
|
||||||
#undef CAIRO_MUTEX_DECLARE
|
#undef CAIRO_MUTEX_DECLARE
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ void _cairo_mutex_finalize (void)
|
||||||
|
|
||||||
_cairo_mutex_initialized = FALSE;
|
_cairo_mutex_initialized = FALSE;
|
||||||
|
|
||||||
#define CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_FINI (mutex)
|
#define CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_FINI (mutex);
|
||||||
#include "cairo-mutex-list-private.h"
|
#include "cairo-mutex-list-private.h"
|
||||||
#undef CAIRO_MUTEX_DECLARE
|
#undef CAIRO_MUTEX_DECLARE
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
/* Generated by configure. Do not edit */
|
|
||||||
#ifndef CAIRO_NO_FEATURES_H
|
|
||||||
#define CAIRO_NO_FEATURES_H
|
|
||||||
|
|
||||||
#include <cairo-features.h>
|
|
||||||
|
|
||||||
/* This is a dummy header, to trick gtk-doc only */
|
|
||||||
|
|
||||||
#define CAIRO_HAS_WIN32_FONT 1
|
|
||||||
#define CAIRO_HAS_WIN32_SURFACE 1
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -38,6 +38,9 @@
|
||||||
#ifndef CAIRO_OS2_PRIVATE_H
|
#ifndef CAIRO_OS2_PRIVATE_H
|
||||||
#define CAIRO_OS2_PRIVATE_H
|
#define CAIRO_OS2_PRIVATE_H
|
||||||
|
|
||||||
|
#include "cairo-os2.h"
|
||||||
|
#include "cairoint.h"
|
||||||
|
|
||||||
#define INCL_DOS
|
#define INCL_DOS
|
||||||
#define INCL_DOSSEMAPHORES
|
#define INCL_DOSSEMAPHORES
|
||||||
#define INCL_DOSERRORS
|
#define INCL_DOSERRORS
|
||||||
|
@ -49,9 +52,6 @@
|
||||||
# include <os2emx.h>
|
# include <os2emx.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "cairo-os2.h"
|
|
||||||
#include "cairoint.h"
|
|
||||||
|
|
||||||
typedef struct _cairo_os2_surface
|
typedef struct _cairo_os2_surface
|
||||||
{
|
{
|
||||||
cairo_surface_t base;
|
cairo_surface_t base;
|
||||||
|
|
|
@ -232,6 +232,12 @@ void _buffer_free (void *buffer)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* XXX
|
||||||
|
* The cairo_os2_ini() and cairo_os2_fini() functions should be removed and
|
||||||
|
* the LibMain code moved to cairo-system.c. It should also call
|
||||||
|
* cairo_debug_reset_static_data() instead of duplicating its logic...
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef BUILD_CAIRO_DLL
|
#ifdef BUILD_CAIRO_DLL
|
||||||
/* The main DLL entry for DLL initialization and uninitialization */
|
/* The main DLL entry for DLL initialization and uninitialization */
|
||||||
/* Only include this code if we're about to build a DLL. */
|
/* Only include this code if we're about to build a DLL. */
|
||||||
|
@ -1202,6 +1208,8 @@ cairo_os2_surface_set_manual_window_refresh (cairo_surface_t *surface,
|
||||||
* cairo_os2_surface_get_manual_window_refresh:
|
* cairo_os2_surface_get_manual_window_refresh:
|
||||||
* @surface: the cairo surface to query the refresh mode from
|
* @surface: the cairo surface to query the refresh mode from
|
||||||
*
|
*
|
||||||
|
* This space left intentionally blank.
|
||||||
|
*
|
||||||
* Return value: current refresh mode of the surface (true by default)
|
* Return value: current refresh mode of the surface (true by default)
|
||||||
*
|
*
|
||||||
* Since: 1.4
|
* Since: 1.4
|
||||||
|
|
|
@ -161,6 +161,9 @@ _cairo_memory_stream_copy (cairo_output_stream_t *base,
|
||||||
cairo_private int
|
cairo_private int
|
||||||
_cairo_memory_stream_length (cairo_output_stream_t *stream);
|
_cairo_memory_stream_length (cairo_output_stream_t *stream);
|
||||||
|
|
||||||
|
cairo_private cairo_output_stream_t *
|
||||||
|
_cairo_null_stream_create (void);
|
||||||
|
|
||||||
/* cairo-base85-stream.c */
|
/* cairo-base85-stream.c */
|
||||||
cairo_private cairo_output_stream_t *
|
cairo_private cairo_output_stream_t *
|
||||||
_cairo_base85_stream_create (cairo_output_stream_t *output);
|
_cairo_base85_stream_create (cairo_output_stream_t *output);
|
||||||
|
@ -169,4 +172,5 @@ _cairo_base85_stream_create (cairo_output_stream_t *output);
|
||||||
cairo_private cairo_output_stream_t *
|
cairo_private cairo_output_stream_t *
|
||||||
_cairo_deflate_stream_create (cairo_output_stream_t *output);
|
_cairo_deflate_stream_create (cairo_output_stream_t *output);
|
||||||
|
|
||||||
|
|
||||||
#endif /* CAIRO_OUTPUT_STREAM_PRIVATE_H */
|
#endif /* CAIRO_OUTPUT_STREAM_PRIVATE_H */
|
||||||
|
|
|
@ -116,6 +116,9 @@ closure_write (cairo_output_stream_t *stream,
|
||||||
cairo_output_stream_with_closure_t *stream_with_closure =
|
cairo_output_stream_with_closure_t *stream_with_closure =
|
||||||
(cairo_output_stream_with_closure_t *) stream;
|
(cairo_output_stream_with_closure_t *) stream;
|
||||||
|
|
||||||
|
if (stream_with_closure->write_func == NULL)
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
|
||||||
return stream_with_closure->write_func (stream_with_closure->closure,
|
return stream_with_closure->write_func (stream_with_closure->closure,
|
||||||
data, length);
|
data, length);
|
||||||
}
|
}
|
||||||
|
@ -583,6 +586,9 @@ _cairo_output_stream_create_for_filename (const char *filename)
|
||||||
stdio_stream_t *stream;
|
stdio_stream_t *stream;
|
||||||
FILE *file;
|
FILE *file;
|
||||||
|
|
||||||
|
if (filename == NULL)
|
||||||
|
return _cairo_null_stream_create ();
|
||||||
|
|
||||||
file = fopen (filename, "wb");
|
file = fopen (filename, "wb");
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
|
@ -676,3 +682,26 @@ _cairo_memory_stream_length (cairo_output_stream_t *base)
|
||||||
|
|
||||||
return _cairo_array_num_elements (&stream->array);
|
return _cairo_array_num_elements (&stream->array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cairo_status_t
|
||||||
|
null_write (cairo_output_stream_t *base,
|
||||||
|
const unsigned char *data, unsigned int length)
|
||||||
|
{
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_output_stream_t *
|
||||||
|
_cairo_null_stream_create (void)
|
||||||
|
{
|
||||||
|
cairo_output_stream_t *stream;
|
||||||
|
|
||||||
|
stream = malloc (sizeof *stream);
|
||||||
|
if (stream == NULL) {
|
||||||
|
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
|
||||||
|
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
_cairo_output_stream_init (stream, null_write, NULL);
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ struct _cairo_paginated_surface_backend {
|
||||||
* before the mode is changed to RENDER.
|
* before the mode is changed to RENDER.
|
||||||
*/
|
*/
|
||||||
cairo_warn cairo_int_status_t
|
cairo_warn cairo_int_status_t
|
||||||
(*set_bounding_box) (void *surface,
|
(*set_bounding_box) (void *surface,
|
||||||
cairo_box_t *bbox);
|
cairo_box_t *bbox);
|
||||||
|
|
||||||
/* Optional. Indicates whether the page requires fallback images.
|
/* Optional. Indicates whether the page requires fallback images.
|
||||||
|
@ -73,8 +73,11 @@ struct _cairo_paginated_surface_backend {
|
||||||
* mode is changed to RENDER.
|
* mode is changed to RENDER.
|
||||||
*/
|
*/
|
||||||
cairo_warn cairo_int_status_t
|
cairo_warn cairo_int_status_t
|
||||||
(*set_fallback_images_required)(void *surface,
|
(*set_fallback_images_required) (void *surface,
|
||||||
cairo_bool_t fallbacks_required);
|
cairo_bool_t fallbacks_required);
|
||||||
|
|
||||||
|
cairo_bool_t
|
||||||
|
(*supports_fine_grained_fallbacks) (void *surface);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A #cairo_paginated_surface_t provides a very convenient wrapper that
|
/* A #cairo_paginated_surface_t provides a very convenient wrapper that
|
||||||
|
|
|
@ -108,6 +108,7 @@ _cairo_paginated_surface_create (cairo_surface_t *target,
|
||||||
return &surface->base;
|
return &surface->base;
|
||||||
|
|
||||||
FAIL_CLEANUP_SURFACE:
|
FAIL_CLEANUP_SURFACE:
|
||||||
|
cairo_surface_destroy (target);
|
||||||
free (surface);
|
free (surface);
|
||||||
FAIL:
|
FAIL:
|
||||||
return _cairo_surface_create_in_error (status);
|
return _cairo_surface_create_in_error (status);
|
||||||
|
@ -299,8 +300,10 @@ _paint_page (cairo_paginated_surface_t *surface)
|
||||||
if (analysis->status)
|
if (analysis->status)
|
||||||
return _cairo_surface_set_error (surface->target, analysis->status);
|
return _cairo_surface_set_error (surface->target, analysis->status);
|
||||||
|
|
||||||
surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE);
|
surface->backend->set_paginated_mode (surface->target,
|
||||||
status = _cairo_meta_surface_replay_and_create_regions (surface->meta, analysis);
|
CAIRO_PAGINATED_MODE_ANALYZE);
|
||||||
|
status = _cairo_meta_surface_replay_and_create_regions (surface->meta,
|
||||||
|
analysis);
|
||||||
if (status || analysis->status) {
|
if (status || analysis->status) {
|
||||||
if (status == CAIRO_STATUS_SUCCESS)
|
if (status == CAIRO_STATUS_SUCCESS)
|
||||||
status = analysis->status;
|
status = analysis->status;
|
||||||
|
@ -325,43 +328,31 @@ _paint_page (cairo_paginated_surface_t *surface)
|
||||||
goto FAIL;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER);
|
|
||||||
|
|
||||||
/* Finer grained fallbacks are currently only supported for some
|
/* Finer grained fallbacks are currently only supported for some
|
||||||
* surface types */
|
* surface types */
|
||||||
switch (surface->target->type) {
|
if (surface->backend->supports_fine_grained_fallbacks != NULL &&
|
||||||
case CAIRO_SURFACE_TYPE_PDF:
|
surface->backend->supports_fine_grained_fallbacks (surface->target))
|
||||||
case CAIRO_SURFACE_TYPE_PS:
|
{
|
||||||
case CAIRO_SURFACE_TYPE_WIN32_PRINTING:
|
has_supported = _cairo_analysis_surface_has_supported (analysis);
|
||||||
has_supported = _cairo_analysis_surface_has_supported (analysis);
|
has_page_fallback = FALSE;
|
||||||
has_page_fallback = FALSE;
|
has_finegrained_fallback = _cairo_analysis_surface_has_unsupported (analysis);
|
||||||
has_finegrained_fallback = _cairo_analysis_surface_has_unsupported (analysis);
|
}
|
||||||
break;
|
else
|
||||||
|
{
|
||||||
case CAIRO_SURFACE_TYPE_IMAGE:
|
if (_cairo_analysis_surface_has_unsupported (analysis)) {
|
||||||
case CAIRO_SURFACE_TYPE_XLIB:
|
has_supported = FALSE;
|
||||||
case CAIRO_SURFACE_TYPE_XCB:
|
has_page_fallback = TRUE;
|
||||||
case CAIRO_SURFACE_TYPE_GLITZ:
|
} else {
|
||||||
case CAIRO_SURFACE_TYPE_QUARTZ:
|
has_supported = TRUE;
|
||||||
case CAIRO_SURFACE_TYPE_QUARTZ_IMAGE:
|
has_page_fallback = FALSE;
|
||||||
case CAIRO_SURFACE_TYPE_WIN32:
|
}
|
||||||
case CAIRO_SURFACE_TYPE_BEOS:
|
has_finegrained_fallback = FALSE;
|
||||||
case CAIRO_SURFACE_TYPE_DIRECTFB:
|
|
||||||
case CAIRO_SURFACE_TYPE_SVG:
|
|
||||||
case CAIRO_SURFACE_TYPE_OS2:
|
|
||||||
default:
|
|
||||||
if (_cairo_analysis_surface_has_unsupported (analysis)) {
|
|
||||||
has_supported = FALSE;
|
|
||||||
has_page_fallback = TRUE;
|
|
||||||
} else {
|
|
||||||
has_supported = TRUE;
|
|
||||||
has_page_fallback = FALSE;
|
|
||||||
}
|
|
||||||
has_finegrained_fallback = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_supported) {
|
if (has_supported) {
|
||||||
|
surface->backend->set_paginated_mode (surface->target,
|
||||||
|
CAIRO_PAGINATED_MODE_RENDER);
|
||||||
|
|
||||||
status = _cairo_meta_surface_replay_region (surface->meta,
|
status = _cairo_meta_surface_replay_region (surface->meta,
|
||||||
surface->target,
|
surface->target,
|
||||||
CAIRO_META_REGION_NATIVE);
|
CAIRO_META_REGION_NATIVE);
|
||||||
|
@ -370,10 +361,12 @@ _paint_page (cairo_paginated_surface_t *surface)
|
||||||
goto FAIL;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_page_fallback)
|
if (has_page_fallback) {
|
||||||
{
|
|
||||||
cairo_box_int_t box;
|
cairo_box_int_t box;
|
||||||
|
|
||||||
|
surface->backend->set_paginated_mode (surface->target,
|
||||||
|
CAIRO_PAGINATED_MODE_FALLBACK);
|
||||||
|
|
||||||
box.p1.x = 0;
|
box.p1.x = 0;
|
||||||
box.p1.y = 0;
|
box.p1.y = 0;
|
||||||
box.p2.x = surface->width;
|
box.p2.x = surface->width;
|
||||||
|
@ -383,13 +376,13 @@ _paint_page (cairo_paginated_surface_t *surface)
|
||||||
goto FAIL;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_finegrained_fallback)
|
if (has_finegrained_fallback) {
|
||||||
{
|
|
||||||
cairo_region_t *region;
|
cairo_region_t *region;
|
||||||
cairo_box_int_t *boxes;
|
cairo_box_int_t *boxes;
|
||||||
int num_boxes, i;
|
int num_boxes, i;
|
||||||
|
|
||||||
surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_FALLBACK);
|
surface->backend->set_paginated_mode (surface->target,
|
||||||
|
CAIRO_PAGINATED_MODE_FALLBACK);
|
||||||
|
|
||||||
/* Reset clip region before drawing the fall back images */
|
/* Reset clip region before drawing the fall back images */
|
||||||
status = _cairo_surface_intersect_clip_path (surface->target,
|
status = _cairo_surface_intersect_clip_path (surface->target,
|
||||||
|
@ -622,7 +615,7 @@ _cairo_paginated_surface_show_text_glyphs (void *abstract_surface,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
const cairo_text_cluster_t *clusters,
|
const cairo_text_cluster_t *clusters,
|
||||||
int num_clusters,
|
int num_clusters,
|
||||||
cairo_bool_t backward,
|
cairo_text_cluster_flags_t cluster_flags,
|
||||||
cairo_scaled_font_t *scaled_font)
|
cairo_scaled_font_t *scaled_font)
|
||||||
{
|
{
|
||||||
cairo_paginated_surface_t *surface = abstract_surface;
|
cairo_paginated_surface_t *surface = abstract_surface;
|
||||||
|
@ -644,14 +637,12 @@ _cairo_paginated_surface_show_text_glyphs (void *abstract_surface,
|
||||||
* show_glyphs functions, (which would get less testing and likely
|
* show_glyphs functions, (which would get less testing and likely
|
||||||
* lead to bugs).
|
* lead to bugs).
|
||||||
*/
|
*/
|
||||||
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
|
|
||||||
status = _cairo_surface_show_text_glyphs (surface->meta, op, source,
|
status = _cairo_surface_show_text_glyphs (surface->meta, op, source,
|
||||||
utf8, utf8_len,
|
utf8, utf8_len,
|
||||||
glyphs, num_glyphs,
|
glyphs, num_glyphs,
|
||||||
clusters, num_clusters,
|
clusters, num_clusters,
|
||||||
backward,
|
cluster_flags,
|
||||||
scaled_font);
|
scaled_font);
|
||||||
CAIRO_MUTEX_LOCK (scaled_font->mutex);
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,8 +215,24 @@ _cairo_path_fixed_fill_rectangle (cairo_path_fixed_t *path,
|
||||||
cairo_traps_t *traps)
|
cairo_traps_t *traps)
|
||||||
{
|
{
|
||||||
if (_cairo_path_fixed_is_box (path, NULL)) {
|
if (_cairo_path_fixed_is_box (path, NULL)) {
|
||||||
return _cairo_traps_tessellate_convex_quad (traps,
|
cairo_point_t *p = path->buf_head.base.points;
|
||||||
path->buf_head.base.points);
|
cairo_point_t *top_left, *bot_right;
|
||||||
|
|
||||||
|
top_left = &p[0];
|
||||||
|
bot_right = &p[2];
|
||||||
|
if (top_left->x > bot_right->x || top_left->y > bot_right->y) {
|
||||||
|
int n;
|
||||||
|
|
||||||
|
/* not a simple cairo_rectangle() */
|
||||||
|
for (n = 0; n < 4; n++) {
|
||||||
|
if (p[n].x <= top_left->x && p[n].y <= top_left->y)
|
||||||
|
top_left = &p[n];
|
||||||
|
if (p[n].x >= bot_right->x && p[n].y >= bot_right->y)
|
||||||
|
bot_right = &p[n];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _cairo_traps_tessellate_rectangle (traps, top_left, bot_right);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
|
@ -829,7 +829,6 @@ _cairo_stroker_line_to (void *closure, cairo_point_t *point)
|
||||||
static cairo_status_t
|
static cairo_status_t
|
||||||
_cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
|
_cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
|
||||||
{
|
{
|
||||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
|
||||||
cairo_stroker_t *stroker = closure;
|
cairo_stroker_t *stroker = closure;
|
||||||
double mag, remain, step_length = 0;
|
double mag, remain, step_length = 0;
|
||||||
double slope_dx, slope_dy;
|
double slope_dx, slope_dy;
|
||||||
|
@ -838,17 +837,19 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
|
||||||
cairo_point_t *p1 = &stroker->current_point;
|
cairo_point_t *p1 = &stroker->current_point;
|
||||||
cairo_point_t *p2 = point;
|
cairo_point_t *p2 = point;
|
||||||
cairo_slope_t dev_slope;
|
cairo_slope_t dev_slope;
|
||||||
cairo_bool_t fully_in_bounds = TRUE;
|
|
||||||
cairo_line_t segment;
|
cairo_line_t segment;
|
||||||
|
cairo_bool_t fully_in_bounds;
|
||||||
|
cairo_status_t status;
|
||||||
|
|
||||||
stroker->has_initial_sub_path = stroker->dash_starts_on;
|
stroker->has_initial_sub_path = stroker->dash_starts_on;
|
||||||
|
|
||||||
if (p1->x == p2->x && p1->y == p2->y)
|
if (p1->x == p2->x && p1->y == p2->y)
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
fully_in_bounds = TRUE;
|
||||||
if (stroker->has_bounds &&
|
if (stroker->has_bounds &&
|
||||||
(!_cairo_box_contains_point (&stroker->bounds, p1) ||
|
(! _cairo_box_contains_point (&stroker->bounds, p1) ||
|
||||||
!_cairo_box_contains_point (&stroker->bounds, p2)))
|
! _cairo_box_contains_point (&stroker->bounds, p2)))
|
||||||
{
|
{
|
||||||
fully_in_bounds = FALSE;
|
fully_in_bounds = FALSE;
|
||||||
}
|
}
|
||||||
|
@ -858,8 +859,11 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
|
||||||
slope_dx = _cairo_fixed_to_double (p2->x - p1->x);
|
slope_dx = _cairo_fixed_to_double (p2->x - p1->x);
|
||||||
slope_dy = _cairo_fixed_to_double (p2->y - p1->y);
|
slope_dy = _cairo_fixed_to_double (p2->y - p1->y);
|
||||||
|
|
||||||
if (!_compute_normalized_device_slope (&slope_dx, &slope_dy, stroker->ctm_inverse, &mag))
|
if (! _compute_normalized_device_slope (&slope_dx, &slope_dy,
|
||||||
|
stroker->ctm_inverse, &mag))
|
||||||
|
{
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
remain = mag;
|
remain = mag;
|
||||||
segment.p1 = *p1;
|
segment.p1 = *p1;
|
||||||
|
@ -872,48 +876,57 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
|
||||||
segment.p2.x = _cairo_fixed_from_double (dx2) + p1->x;
|
segment.p2.x = _cairo_fixed_from_double (dx2) + p1->x;
|
||||||
segment.p2.y = _cairo_fixed_from_double (dy2) + p1->y;
|
segment.p2.y = _cairo_fixed_from_double (dy2) + p1->y;
|
||||||
|
|
||||||
if (fully_in_bounds ||
|
if (stroker->dash_on &&
|
||||||
_cairo_box_intersects_line_segment (&stroker->bounds, &segment))
|
(fully_in_bounds ||
|
||||||
|
(! stroker->has_first_face && stroker->dash_starts_on) ||
|
||||||
|
_cairo_box_intersects_line_segment (&stroker->bounds, &segment)))
|
||||||
{
|
{
|
||||||
if (stroker->dash_on) {
|
status = _cairo_stroker_add_sub_edge (stroker,
|
||||||
status = _cairo_stroker_add_sub_edge (stroker, &segment.p1, &segment.p2, &dev_slope, slope_dx, slope_dy, &sub_start, &sub_end);
|
&segment.p1, &segment.p2,
|
||||||
|
&dev_slope,
|
||||||
|
slope_dx, slope_dy,
|
||||||
|
&sub_start, &sub_end);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
if (stroker->has_current_face) {
|
||||||
|
/* Join with final face from previous segment */
|
||||||
|
status = _cairo_stroker_join (stroker,
|
||||||
|
&stroker->current_face,
|
||||||
|
&sub_start);
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
if (stroker->has_current_face) {
|
stroker->has_current_face = FALSE;
|
||||||
/* Join with final face from previous segment */
|
} else if (! stroker->has_first_face && stroker->dash_starts_on) {
|
||||||
status = _cairo_stroker_join (stroker, &stroker->current_face, &sub_start);
|
/* Save sub path's first face in case needed for closing join */
|
||||||
stroker->has_current_face = FALSE;
|
stroker->first_face = sub_start;
|
||||||
if (status)
|
stroker->has_first_face = TRUE;
|
||||||
return status;
|
|
||||||
} else if (!stroker->has_first_face && stroker->dash_starts_on) {
|
|
||||||
/* Save sub path's first face in case needed for closing join */
|
|
||||||
stroker->first_face = sub_start;
|
|
||||||
stroker->has_first_face = TRUE;
|
|
||||||
} else {
|
|
||||||
/* Cap dash start if not connecting to a previous segment */
|
|
||||||
status = _cairo_stroker_add_leading_cap (stroker, &sub_start);
|
|
||||||
if (status)
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remain) {
|
|
||||||
/* Cap dash end if not at end of segment */
|
|
||||||
status = _cairo_stroker_add_trailing_cap (stroker, &sub_end);
|
|
||||||
if (status)
|
|
||||||
return status;
|
|
||||||
} else {
|
|
||||||
stroker->current_face = sub_end;
|
|
||||||
stroker->has_current_face = TRUE;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (stroker->has_current_face) {
|
/* Cap dash start if not connecting to a previous segment */
|
||||||
/* Cap final face from previous segment */
|
status = _cairo_stroker_add_leading_cap (stroker, &sub_start);
|
||||||
status = _cairo_stroker_add_trailing_cap (stroker, &stroker->current_face);
|
if (status)
|
||||||
if (status)
|
return status;
|
||||||
return status;
|
}
|
||||||
stroker->has_current_face = FALSE;
|
|
||||||
}
|
if (remain) {
|
||||||
|
/* Cap dash end if not at end of segment */
|
||||||
|
status = _cairo_stroker_add_trailing_cap (stroker, &sub_end);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
} else {
|
||||||
|
stroker->current_face = sub_end;
|
||||||
|
stroker->has_current_face = TRUE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (stroker->has_current_face) {
|
||||||
|
/* Cap final face from previous segment */
|
||||||
|
status = _cairo_stroker_add_trailing_cap (stroker,
|
||||||
|
&stroker->current_face);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
stroker->has_current_face = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -921,24 +934,32 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
|
||||||
segment.p1 = segment.p2;
|
segment.p1 = segment.p2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stroker->dash_on && !stroker->has_current_face) {
|
if (stroker->dash_on && ! stroker->has_current_face) {
|
||||||
/* This segment ends on a transition to dash_on, compute a new face
|
/* This segment ends on a transition to dash_on, compute a new face
|
||||||
* and add cap for the begining of the next dash_on step.
|
* and add cap for the beginning of the next dash_on step.
|
||||||
*
|
*
|
||||||
* Note: this will create a degenerate cap if this is not the last line
|
* Note: this will create a degenerate cap if this is not the last line
|
||||||
* in the path. Whether this behaviour is desirable or not is debatable.
|
* in the path. Whether this behaviour is desirable or not is debatable.
|
||||||
* On one side these degnerate caps can not be reproduced with regular path stroking.
|
* On one side these degenerate caps can not be reproduced with regular
|
||||||
* On the other side Acroread 7 also produces the degenerate caps. */
|
* path stroking.
|
||||||
_compute_face (point, &dev_slope, slope_dx, slope_dy, stroker, &stroker->current_face);
|
* On the other hand, Acroread 7 also produces the degenerate caps.
|
||||||
stroker->has_current_face = TRUE;
|
*/
|
||||||
status = _cairo_stroker_add_leading_cap (stroker, &stroker->current_face);
|
_compute_face (point, &dev_slope,
|
||||||
|
slope_dx, slope_dy,
|
||||||
|
stroker,
|
||||||
|
&stroker->current_face);
|
||||||
|
|
||||||
|
status = _cairo_stroker_add_leading_cap (stroker,
|
||||||
|
&stroker->current_face);
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
stroker->has_current_face = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
stroker->current_point = *point;
|
stroker->current_point = *point;
|
||||||
|
|
||||||
return status;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cairo_status_t
|
static cairo_status_t
|
||||||
|
@ -1257,12 +1278,12 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
cairo_line_cap_t line_cap = stroker->stroke_style->line_cap;
|
cairo_line_cap_t line_cap = stroker->stroke_style->line_cap;
|
||||||
cairo_fixed_t half_line_width = stroker->half_line_width;
|
cairo_fixed_t half_line_width = stroker->half_line_width;
|
||||||
cairo_bool_t lengthen_initial, shorten_final, lengthen_final;
|
|
||||||
cairo_point_t *a, *b;
|
|
||||||
cairo_point_t r[4];
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < stroker->num_segments; i++) {
|
for (i = 0; i < stroker->num_segments; i++) {
|
||||||
|
cairo_point_t *a, *b;
|
||||||
|
cairo_bool_t lengthen_initial, shorten_final, lengthen_final;
|
||||||
|
|
||||||
a = &stroker->segments[i].p1;
|
a = &stroker->segments[i].p1;
|
||||||
b = &stroker->segments[i].p2;
|
b = &stroker->segments[i].p2;
|
||||||
|
|
||||||
|
@ -1315,6 +1336,14 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
|
||||||
else if (lengthen_final)
|
else if (lengthen_final)
|
||||||
b->x -= half_line_width;
|
b->x -= half_line_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (a->x > b->x) {
|
||||||
|
cairo_point_t *t;
|
||||||
|
|
||||||
|
t = a;
|
||||||
|
a = b;
|
||||||
|
b = t;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (a->y < b->y) {
|
if (a->y < b->y) {
|
||||||
if (lengthen_initial)
|
if (lengthen_initial)
|
||||||
|
@ -1331,27 +1360,27 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
|
||||||
else if (lengthen_final)
|
else if (lengthen_final)
|
||||||
b->y -= half_line_width;
|
b->y -= half_line_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (a->y > b->y) {
|
||||||
|
cairo_point_t *t;
|
||||||
|
|
||||||
|
t = a;
|
||||||
|
a = b;
|
||||||
|
b = t;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Form the rectangle by expanding by half the line width in
|
/* Form the rectangle by expanding by half the line width in
|
||||||
* either perdendicular direction. */
|
* either perpendicular direction. */
|
||||||
r[0] = *a;
|
|
||||||
r[1] = *b;
|
|
||||||
r[2] = *b;
|
|
||||||
r[3] = *a;
|
|
||||||
if (a->y == b->y) {
|
if (a->y == b->y) {
|
||||||
r[0].y -= half_line_width;
|
a->y -= half_line_width;
|
||||||
r[1].y -= half_line_width;
|
b->y += half_line_width;
|
||||||
r[2].y += half_line_width;
|
|
||||||
r[3].y += half_line_width;
|
|
||||||
} else {
|
} else {
|
||||||
r[0].x -= half_line_width;
|
a->x -= half_line_width;
|
||||||
r[1].x -= half_line_width;
|
b->x += half_line_width;
|
||||||
r[2].x += half_line_width;
|
|
||||||
r[3].x += half_line_width;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status = _cairo_traps_tessellate_convex_quad (stroker->traps, r);
|
status = _cairo_traps_tessellate_rectangle (stroker->traps, a, b);
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -1439,7 +1468,7 @@ _cairo_path_fixed_stroke_rectilinear (cairo_path_fixed_t *path,
|
||||||
/* This special-case rectilinear stroker only supports
|
/* This special-case rectilinear stroker only supports
|
||||||
* miter-joined lines (not curves) and no dashing and a
|
* miter-joined lines (not curves) and no dashing and a
|
||||||
* translation-only matrix (though it could probably be extended
|
* translation-only matrix (though it could probably be extended
|
||||||
* to support a matrix with uniform, integer sacling).
|
* to support a matrix with uniform, integer scaling).
|
||||||
*
|
*
|
||||||
* It also only supports horizontal and vertical line_to
|
* It also only supports horizontal and vertical line_to
|
||||||
* elements. But we don't catch that here, but instead return
|
* elements. But we don't catch that here, but instead return
|
||||||
|
@ -1484,11 +1513,10 @@ _cairo_path_fixed_stroke_rectilinear (cairo_path_fixed_t *path,
|
||||||
status = _cairo_rectilinear_stroker_emit_segments (&rectilinear_stroker);
|
status = _cairo_rectilinear_stroker_emit_segments (&rectilinear_stroker);
|
||||||
|
|
||||||
BAIL:
|
BAIL:
|
||||||
|
|
||||||
_cairo_rectilinear_stroker_fini (&rectilinear_stroker);
|
_cairo_rectilinear_stroker_fini (&rectilinear_stroker);
|
||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
_cairo_traps_fini (traps);
|
_cairo_traps_clear (traps);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,6 +192,36 @@ _cairo_pattern_init_copy (cairo_pattern_t *pattern,
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cairo_status_t
|
||||||
|
_cairo_pattern_init_snapshot (cairo_pattern_t *pattern,
|
||||||
|
const cairo_pattern_t *other)
|
||||||
|
{
|
||||||
|
cairo_status_t status;
|
||||||
|
|
||||||
|
/* We don't bother doing any fancy copy-on-write implementation
|
||||||
|
* for the pattern's data. It's generally quite tiny. */
|
||||||
|
status = _cairo_pattern_init_copy (pattern, other);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
/* But we do let the surface snapshot stuff be as fancy as it
|
||||||
|
* would like to be. */
|
||||||
|
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
||||||
|
cairo_surface_pattern_t *surface_pattern =
|
||||||
|
(cairo_surface_pattern_t *) pattern;
|
||||||
|
cairo_surface_t *surface = surface_pattern->surface;
|
||||||
|
|
||||||
|
surface_pattern->surface = _cairo_surface_snapshot (surface);
|
||||||
|
|
||||||
|
cairo_surface_destroy (surface);
|
||||||
|
|
||||||
|
if (surface_pattern->surface->status)
|
||||||
|
return surface_pattern->surface->status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cairo_pattern_fini (cairo_pattern_t *pattern)
|
_cairo_pattern_fini (cairo_pattern_t *pattern)
|
||||||
{
|
{
|
||||||
|
@ -784,7 +814,7 @@ cairo_pattern_set_user_data (cairo_pattern_t *pattern,
|
||||||
cairo_destroy_func_t destroy)
|
cairo_destroy_func_t destroy)
|
||||||
{
|
{
|
||||||
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
|
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
return pattern->status;
|
||||||
|
|
||||||
return _cairo_user_data_array_set_data (&pattern->user_data,
|
return _cairo_user_data_array_set_data (&pattern->user_data,
|
||||||
key, user_data, destroy);
|
key, user_data, destroy);
|
||||||
|
@ -1217,6 +1247,8 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
|
||||||
pixman_gradient_stop_t pixman_stops_static[2];
|
pixman_gradient_stop_t pixman_stops_static[2];
|
||||||
pixman_gradient_stop_t *pixman_stops = pixman_stops_static;
|
pixman_gradient_stop_t *pixman_stops = pixman_stops_static;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
int clone_offset_x, clone_offset_y;
|
||||||
|
cairo_matrix_t matrix = pattern->base.matrix;
|
||||||
|
|
||||||
if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) {
|
if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) {
|
||||||
pixman_stops = _cairo_malloc_ab (pattern->n_stops, sizeof(pixman_gradient_stop_t));
|
pixman_stops = _cairo_malloc_ab (pattern->n_stops, sizeof(pixman_gradient_stop_t));
|
||||||
|
@ -1236,11 +1268,46 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
|
||||||
{
|
{
|
||||||
cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern;
|
cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern;
|
||||||
pixman_point_fixed_t p1, p2;
|
pixman_point_fixed_t p1, p2;
|
||||||
|
cairo_fixed_t xdim, ydim;
|
||||||
|
|
||||||
p1.x = _cairo_fixed_to_16_16 (linear->p1.x);
|
xdim = linear->p2.x - linear->p1.x;
|
||||||
p1.y = _cairo_fixed_to_16_16 (linear->p1.y);
|
ydim = linear->p2.y - linear->p1.y;
|
||||||
p2.x = _cairo_fixed_to_16_16 (linear->p2.x);
|
|
||||||
p2.y = _cairo_fixed_to_16_16 (linear->p2.y);
|
/*
|
||||||
|
* Transform the matrix to avoid overflow when converting between
|
||||||
|
* cairo_fixed_t and pixman_fixed_t (without incurring performance
|
||||||
|
* loss when the transformation is unnecessary).
|
||||||
|
*
|
||||||
|
* XXX: Consider converting out-of-range co-ordinates and transforms.
|
||||||
|
* Having a function to compute the required transformation to
|
||||||
|
* "normalize" a given bounding box would be generally useful -
|
||||||
|
* cf linear patterns, gradient patterns, surface patterns...
|
||||||
|
*/
|
||||||
|
#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
|
||||||
|
if (_cairo_fixed_integer_ceil (xdim) > PIXMAN_MAX_INT ||
|
||||||
|
_cairo_fixed_integer_ceil (ydim) > PIXMAN_MAX_INT)
|
||||||
|
{
|
||||||
|
double sf;
|
||||||
|
|
||||||
|
if (xdim > ydim)
|
||||||
|
sf = PIXMAN_MAX_INT / _cairo_fixed_to_double (xdim);
|
||||||
|
else
|
||||||
|
sf = PIXMAN_MAX_INT / _cairo_fixed_to_double (ydim);
|
||||||
|
|
||||||
|
p1.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.x) * sf);
|
||||||
|
p1.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.y) * sf);
|
||||||
|
p2.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.x) * sf);
|
||||||
|
p2.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.y) * sf);
|
||||||
|
|
||||||
|
cairo_matrix_scale (&matrix, sf, sf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p1.x = _cairo_fixed_to_16_16 (linear->p1.x);
|
||||||
|
p1.y = _cairo_fixed_to_16_16 (linear->p1.y);
|
||||||
|
p2.x = _cairo_fixed_to_16_16 (linear->p2.x);
|
||||||
|
p2.y = _cairo_fixed_to_16_16 (linear->p2.y);
|
||||||
|
}
|
||||||
|
|
||||||
pixman_image = pixman_image_create_linear_gradient (&p1, &p2,
|
pixman_image = pixman_image_create_linear_gradient (&p1, &p2,
|
||||||
pixman_stops,
|
pixman_stops,
|
||||||
|
@ -1284,7 +1351,7 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
|
||||||
}
|
}
|
||||||
|
|
||||||
attr->x_offset = attr->y_offset = 0;
|
attr->x_offset = attr->y_offset = 0;
|
||||||
attr->matrix = pattern->base.matrix;
|
attr->matrix = matrix;
|
||||||
attr->extend = pattern->base.extend;
|
attr->extend = pattern->base.extend;
|
||||||
attr->filter = CAIRO_FILTER_NEAREST;
|
attr->filter = CAIRO_FILTER_NEAREST;
|
||||||
attr->acquired = FALSE;
|
attr->acquired = FALSE;
|
||||||
|
@ -1332,7 +1399,7 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
|
||||||
return image->base.status;
|
return image->base.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
_cairo_matrix_to_pixman_matrix (&pattern->base.matrix, &pixman_transform);
|
_cairo_matrix_to_pixman_matrix (&matrix, &pixman_transform);
|
||||||
if (!pixman_image_set_transform (pixman_image, &pixman_transform)) {
|
if (!pixman_image_set_transform (pixman_image, &pixman_transform)) {
|
||||||
cairo_surface_destroy (&image->base);
|
cairo_surface_destroy (&image->base);
|
||||||
pixman_image_unref (pixman_image);
|
pixman_image_unref (pixman_image);
|
||||||
|
@ -1366,7 +1433,10 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
|
||||||
pixman_image_unref (pixman_image);
|
pixman_image_unref (pixman_image);
|
||||||
|
|
||||||
status = _cairo_surface_clone_similar (dst, &image->base,
|
status = _cairo_surface_clone_similar (dst, &image->base,
|
||||||
0, 0, width, height, out);
|
0, 0, width, height,
|
||||||
|
&clone_offset_x,
|
||||||
|
&clone_offset_y,
|
||||||
|
out);
|
||||||
|
|
||||||
cairo_surface_destroy (&image->base);
|
cairo_surface_destroy (&image->base);
|
||||||
|
|
||||||
|
@ -1628,6 +1698,71 @@ _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _cairo_pattern_analyze_filter:
|
||||||
|
* @pattern: surface pattern
|
||||||
|
* @pad_out: location to store necessary padding in the source image, or %NULL
|
||||||
|
* Returns: the optimized #cairo_filter_t to use with @pattern.
|
||||||
|
*
|
||||||
|
* Analyze the filter to determine how much extra needs to be sampled
|
||||||
|
* from the source image to account for the filter radius and whether
|
||||||
|
* we can optimize the filter to a simpler value.
|
||||||
|
*
|
||||||
|
* XXX: We don't actually have any way of querying the backend for
|
||||||
|
* the filter radius, so we just guess base on what we know that
|
||||||
|
* backends do currently (see bug #10508)
|
||||||
|
*/
|
||||||
|
static cairo_filter_t
|
||||||
|
_cairo_pattern_analyze_filter (cairo_surface_pattern_t *pattern,
|
||||||
|
double *pad_out)
|
||||||
|
{
|
||||||
|
double pad;
|
||||||
|
cairo_filter_t optimized_filter;
|
||||||
|
|
||||||
|
switch (pattern->base.filter) {
|
||||||
|
case CAIRO_FILTER_GOOD:
|
||||||
|
case CAIRO_FILTER_BEST:
|
||||||
|
case CAIRO_FILTER_BILINEAR:
|
||||||
|
/* If source pixels map 1:1 onto destination pixels, we do
|
||||||
|
* not need to filter (and do not want to filter, since it
|
||||||
|
* will cause blurriness)
|
||||||
|
*/
|
||||||
|
if (_cairo_matrix_is_pixel_exact (&pattern->base.matrix)) {
|
||||||
|
pad = 0.;
|
||||||
|
optimized_filter = CAIRO_FILTER_NEAREST;
|
||||||
|
} else {
|
||||||
|
/* 0.5 is enough for a bilinear filter. It's possible we
|
||||||
|
* should defensively use more for CAIRO_FILTER_BEST, but
|
||||||
|
* without a single example, it's hard to know how much
|
||||||
|
* more would be defensive...
|
||||||
|
*/
|
||||||
|
pad = 0.5;
|
||||||
|
optimized_filter = pattern->base.filter;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CAIRO_FILTER_FAST:
|
||||||
|
case CAIRO_FILTER_NEAREST:
|
||||||
|
case CAIRO_FILTER_GAUSSIAN:
|
||||||
|
default:
|
||||||
|
pad = 0.;
|
||||||
|
optimized_filter = pattern->base.filter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pad_out)
|
||||||
|
*pad_out = pad;
|
||||||
|
|
||||||
|
return optimized_filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static double
|
||||||
|
_pixman_nearest_sample (double d)
|
||||||
|
{
|
||||||
|
return ceil (d - .5);
|
||||||
|
}
|
||||||
|
|
||||||
static cairo_int_status_t
|
static cairo_int_status_t
|
||||||
_cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
|
_cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
|
||||||
cairo_surface_t *dst,
|
cairo_surface_t *dst,
|
||||||
|
@ -1640,18 +1775,44 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
|
||||||
{
|
{
|
||||||
cairo_int_status_t status;
|
cairo_int_status_t status;
|
||||||
int tx, ty;
|
int tx, ty;
|
||||||
|
double pad;
|
||||||
|
|
||||||
attr->acquired = FALSE;
|
attr->acquired = FALSE;
|
||||||
|
|
||||||
attr->extend = pattern->base.extend;
|
attr->extend = pattern->base.extend;
|
||||||
attr->filter = pattern->base.filter;
|
attr->filter = _cairo_pattern_analyze_filter (pattern, &pad);
|
||||||
|
|
||||||
if (_cairo_matrix_is_integer_translation (&pattern->base.matrix,
|
if (_cairo_matrix_is_integer_translation (&pattern->base.matrix,
|
||||||
&tx, &ty))
|
&tx, &ty))
|
||||||
{
|
{
|
||||||
cairo_matrix_init_identity (&attr->matrix);
|
cairo_matrix_init_identity (&attr->matrix);
|
||||||
attr->x_offset = tx;
|
attr->x_offset = tx;
|
||||||
attr->y_offset = ty;
|
attr->y_offset = ty;
|
||||||
attr->filter = CAIRO_FILTER_NEAREST;
|
}
|
||||||
|
else if (attr->filter == CAIRO_FILTER_NEAREST)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* For NEAREST, we can remove the fractional translation component
|
||||||
|
* from the transformation - this ensures that the pattern will always
|
||||||
|
* hit fast-paths in the backends for simple transformations that
|
||||||
|
* become (almost) identity, without loss of quality.
|
||||||
|
*/
|
||||||
|
attr->matrix = pattern->base.matrix;
|
||||||
|
attr->matrix.x0 = 0;
|
||||||
|
attr->matrix.y0 = 0;
|
||||||
|
if (_cairo_matrix_is_pixel_exact (&attr->matrix)) {
|
||||||
|
/* The rounding here is rather peculiar as it needs to match the
|
||||||
|
* rounding performed on the sample coordinate used by pixman.
|
||||||
|
*/
|
||||||
|
attr->matrix.x0 = _pixman_nearest_sample (pattern->base.matrix.x0);
|
||||||
|
attr->matrix.y0 = _pixman_nearest_sample (pattern->base.matrix.y0);
|
||||||
|
} else {
|
||||||
|
attr->matrix.x0 = pattern->base.matrix.x0;
|
||||||
|
attr->matrix.y0 = pattern->base.matrix.y0;
|
||||||
|
}
|
||||||
|
|
||||||
|
attr->x_offset = attr->y_offset = 0;
|
||||||
|
tx = ty = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1734,8 +1895,7 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_cairo_surface_is_image (dst))
|
if (_cairo_surface_is_image (dst)) {
|
||||||
{
|
|
||||||
cairo_image_surface_t *image;
|
cairo_image_surface_t *image;
|
||||||
|
|
||||||
status = _cairo_surface_acquire_source_image (pattern->surface,
|
status = _cairo_surface_acquire_source_image (pattern->surface,
|
||||||
|
@ -1746,60 +1906,73 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
|
||||||
|
|
||||||
*out = &image->base;
|
*out = &image->base;
|
||||||
attr->acquired = TRUE;
|
attr->acquired = TRUE;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
cairo_rectangle_int_t extents;
|
cairo_rectangle_int_t extents;
|
||||||
|
|
||||||
status = _cairo_surface_get_extents (pattern->surface, &extents);
|
status = _cairo_surface_get_extents (pattern->surface, &extents);
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
/* If we're repeating, we just play it safe and clone the entire surface. */
|
/* If we're repeating, we just play it safe and clone the
|
||||||
/* If requested width and height are -1, clone the entire surface.
|
* entire surface - i.e. we use the existing extents.
|
||||||
* This is relied on in the svg backend. */
|
*/
|
||||||
if (attr->extend == CAIRO_EXTEND_REPEAT ||
|
if (attr->extend != CAIRO_EXTEND_REPEAT) {
|
||||||
(width == (unsigned int) -1 && height == (unsigned int) -1)) {
|
cairo_rectangle_int_t sampled_area;
|
||||||
x = extents.x;
|
|
||||||
y = extents.y;
|
|
||||||
width = extents.width;
|
|
||||||
height = extents.height;
|
|
||||||
} else {
|
|
||||||
/* Otherwise, we first transform the rectangle to the
|
/* Otherwise, we first transform the rectangle to the
|
||||||
* coordinate space of the source surface so that we can
|
* coordinate space of the source surface so that we can
|
||||||
* clone only that portion of the surface that will be
|
* clone only that portion of the surface that will be
|
||||||
* read. */
|
* read.
|
||||||
if (! _cairo_matrix_is_identity (&attr->matrix)) {
|
*/
|
||||||
|
if (_cairo_matrix_is_identity (&attr->matrix)) {
|
||||||
|
sampled_area.x = x;
|
||||||
|
sampled_area.y = y;
|
||||||
|
sampled_area.width = width;
|
||||||
|
sampled_area.height = height;
|
||||||
|
} else {
|
||||||
double x1 = x;
|
double x1 = x;
|
||||||
double y1 = y;
|
double y1 = y;
|
||||||
double x2 = x + width;
|
double x2 = x + width;
|
||||||
double y2 = y + height;
|
double y2 = y + height;
|
||||||
cairo_bool_t is_tight;
|
|
||||||
|
|
||||||
_cairo_matrix_transform_bounding_box (&attr->matrix,
|
_cairo_matrix_transform_bounding_box (&attr->matrix,
|
||||||
&x1, &y1, &x2, &y2,
|
&x1, &y1, &x2, &y2,
|
||||||
&is_tight);
|
NULL);
|
||||||
|
|
||||||
|
sampled_area.x = floor (x1 - pad);
|
||||||
|
sampled_area.y = floor (y1 - pad);
|
||||||
|
sampled_area.width = ceil (x2 + pad) - sampled_area.x;
|
||||||
|
sampled_area.height = ceil (y2 + pad) - sampled_area.y;
|
||||||
|
|
||||||
/* The transform_bounding_box call may have resulted
|
|
||||||
* in a region larger than the surface, but we never
|
|
||||||
* want to clone more than the surface itself, (we
|
|
||||||
* know we're not repeating at this point due to the
|
|
||||||
* above.
|
|
||||||
*
|
|
||||||
* XXX: The one padding here is to account for filter
|
|
||||||
* radius. It's a workaround right now, until we get a
|
|
||||||
* proper fix. (see bug #10508)
|
|
||||||
*/
|
|
||||||
x = MAX (0, floor (x1) - 1);
|
|
||||||
y = MAX (0, floor (y1) - 1);
|
|
||||||
width = MIN (extents.width, ceil (x2) + 1) - x;
|
|
||||||
height = MIN (extents.height, ceil (y2) + 1) - y;
|
|
||||||
}
|
}
|
||||||
x += tx;
|
|
||||||
y += ty;
|
sampled_area.x += tx;
|
||||||
|
sampled_area.y += ty;
|
||||||
|
|
||||||
|
/* Never acquire a larger area than the source itself */
|
||||||
|
_cairo_rectangle_intersect (&extents, &sampled_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = _cairo_surface_clone_similar (dst, pattern->surface,
|
status = _cairo_surface_clone_similar (dst, pattern->surface,
|
||||||
x, y, width, height, out);
|
extents.x, extents.y,
|
||||||
|
extents.width, extents.height,
|
||||||
|
&x, &y, out);
|
||||||
|
if (status == CAIRO_STATUS_SUCCESS && (x != 0 || y != 0)) {
|
||||||
|
if (_cairo_matrix_is_identity (&attr->matrix)) {
|
||||||
|
attr->x_offset -= x;
|
||||||
|
attr->y_offset -= y;
|
||||||
|
} else {
|
||||||
|
cairo_matrix_t m;
|
||||||
|
|
||||||
|
x -= attr->x_offset;
|
||||||
|
y -= attr->y_offset;
|
||||||
|
attr->x_offset = 0;
|
||||||
|
attr->y_offset = 0;
|
||||||
|
|
||||||
|
cairo_matrix_init_translate (&m, -x, -y);
|
||||||
|
cairo_matrix_multiply (&attr->matrix, &attr->matrix, &m);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
@ -1820,6 +1993,9 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
|
||||||
* A convenience function to obtain a surface to use as the source for
|
* A convenience function to obtain a surface to use as the source for
|
||||||
* drawing on @dst.
|
* drawing on @dst.
|
||||||
*
|
*
|
||||||
|
* Note that this function is only suitable for use when the destination
|
||||||
|
* surface is pixel based and 1 device unit maps to one pixel.
|
||||||
|
*
|
||||||
* Return value: %CAIRO_STATUS_SUCCESS if a surface was stored in @surface_out.
|
* Return value: %CAIRO_STATUS_SUCCESS if a surface was stored in @surface_out.
|
||||||
**/
|
**/
|
||||||
cairo_int_status_t
|
cairo_int_status_t
|
||||||
|
@ -2049,15 +2225,20 @@ _cairo_pattern_get_extents (cairo_pattern_t *pattern,
|
||||||
cairo_surface_t *surface = surface_pattern->surface;
|
cairo_surface_t *surface = surface_pattern->surface;
|
||||||
cairo_matrix_t imatrix;
|
cairo_matrix_t imatrix;
|
||||||
double x1, y1, x2, y2;
|
double x1, y1, x2, y2;
|
||||||
|
double pad;
|
||||||
|
|
||||||
status = _cairo_surface_get_extents (surface, &surface_extents);
|
status = _cairo_surface_get_extents (surface, &surface_extents);
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
x1 = surface_extents.x;
|
/* The filter can effectively enlarge the extents of the
|
||||||
y1 = surface_extents.y;
|
* pattern, so extend as necessary.
|
||||||
x2 = x1 + surface_extents.width;
|
*/
|
||||||
y2 = y1 + surface_extents.height;
|
_cairo_pattern_analyze_filter (surface_pattern, &pad);
|
||||||
|
x1 = surface_extents.x - pad;
|
||||||
|
y1 = surface_extents.y - pad;
|
||||||
|
x2 = surface_extents.x + surface_extents.width + pad;
|
||||||
|
y2 = surface_extents.y + surface_extents.height + pad;
|
||||||
|
|
||||||
imatrix = pattern->matrix;
|
imatrix = pattern->matrix;
|
||||||
status = cairo_matrix_invert (&imatrix);
|
status = cairo_matrix_invert (&imatrix);
|
||||||
|
|
|
@ -159,7 +159,7 @@ _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
const cairo_text_cluster_t *clusters,
|
const cairo_text_cluster_t *clusters,
|
||||||
int num_clusters,
|
int num_clusters,
|
||||||
cairo_bool_t backward,
|
cairo_text_cluster_flags_t cluster_flags,
|
||||||
cairo_scaled_font_t *scaled_font);
|
cairo_scaled_font_t *scaled_font);
|
||||||
|
|
||||||
#endif /* CAIRO_PDF_OPERATORS_H */
|
#endif /* CAIRO_PDF_OPERATORS_H */
|
||||||
|
|
|
@ -571,6 +571,16 @@ _cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
|
||||||
|
|
||||||
for (i = 0; i < num_dashes; i += 2) {
|
for (i = 0; i < num_dashes; i += 2) {
|
||||||
if (dash[i] == 0.0) {
|
if (dash[i] == 0.0) {
|
||||||
|
/* Do not modify the dashes in-place, as we may need to also
|
||||||
|
* replay this stroke to an image fallback.
|
||||||
|
*/
|
||||||
|
if (dash == style->dash) {
|
||||||
|
dash = _cairo_malloc_ab (num_dashes, sizeof (double));
|
||||||
|
if (dash == NULL)
|
||||||
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
|
memcpy (dash, style->dash, num_dashes * sizeof (double));
|
||||||
|
}
|
||||||
|
|
||||||
/* If we're at the front of the list, we first rotate
|
/* If we're at the front of the list, we first rotate
|
||||||
* two elements from the end of the list to the front
|
* two elements from the end of the list to the front
|
||||||
* of the list before folding away the 0.0. Or, if
|
* of the list before folding away the 0.0. Or, if
|
||||||
|
@ -581,10 +591,10 @@ _cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
|
||||||
double last_two[2];
|
double last_two[2];
|
||||||
|
|
||||||
if (num_dashes == 2) {
|
if (num_dashes == 2) {
|
||||||
if (dash != style->dash)
|
free (dash);
|
||||||
free (dash);
|
|
||||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The cases of num_dashes == 0, 1, or 3 elements
|
/* The cases of num_dashes == 0, 1, or 3 elements
|
||||||
* cannot exist, so the rotation of 2 elements
|
* cannot exist, so the rotation of 2 elements
|
||||||
* will always be safe */
|
* will always be safe */
|
||||||
|
@ -1251,7 +1261,7 @@ _cairo_pdf_operators_emit_cluster (cairo_pdf_operators_t *pdf_operators,
|
||||||
int utf8_len,
|
int utf8_len,
|
||||||
cairo_glyph_t *glyphs,
|
cairo_glyph_t *glyphs,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
cairo_bool_t backward,
|
cairo_text_cluster_flags_t cluster_flags,
|
||||||
cairo_scaled_font_t *scaled_font)
|
cairo_scaled_font_t *scaled_font)
|
||||||
{
|
{
|
||||||
cairo_scaled_font_subsets_glyph_t subset_glyph;
|
cairo_scaled_font_subsets_glyph_t subset_glyph;
|
||||||
|
@ -1293,7 +1303,10 @@ _cairo_pdf_operators_emit_cluster (cairo_pdf_operators_t *pdf_operators,
|
||||||
|
|
||||||
/* Fallback to using ActualText to map zero or more glyphs to a
|
/* Fallback to using ActualText to map zero or more glyphs to a
|
||||||
* unicode string. */
|
* unicode string. */
|
||||||
_cairo_pdf_operators_flush_glyphs (pdf_operators);
|
status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
status = _cairo_pdf_operators_begin_actualtext (pdf_operators, utf8, utf8_len);
|
status = _cairo_pdf_operators_begin_actualtext (pdf_operators, utf8, utf8_len);
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
@ -1316,7 +1329,7 @@ _cairo_pdf_operators_emit_cluster (cairo_pdf_operators_t *pdf_operators,
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
if (backward)
|
if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
|
||||||
cur_glyph--;
|
cur_glyph--;
|
||||||
else
|
else
|
||||||
cur_glyph++;
|
cur_glyph++;
|
||||||
|
@ -1338,7 +1351,7 @@ _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
const cairo_text_cluster_t *clusters,
|
const cairo_text_cluster_t *clusters,
|
||||||
int num_clusters,
|
int num_clusters,
|
||||||
cairo_bool_t backward,
|
cairo_text_cluster_flags_t cluster_flags,
|
||||||
cairo_scaled_font_t *scaled_font)
|
cairo_scaled_font_t *scaled_font)
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
@ -1357,7 +1370,9 @@ _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators,
|
||||||
|
|
||||||
pdf_operators->is_new_text_object = FALSE;
|
pdf_operators->is_new_text_object = FALSE;
|
||||||
if (pdf_operators->in_text_object == FALSE) {
|
if (pdf_operators->in_text_object == FALSE) {
|
||||||
_cairo_pdf_operators_begin_text (pdf_operators);
|
status = _cairo_pdf_operators_begin_text (pdf_operators);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
/* Force Tm and Tf to be emitted when starting a new text
|
/* Force Tm and Tf to be emitted when starting a new text
|
||||||
* object.*/
|
* object.*/
|
||||||
|
@ -1376,7 +1391,10 @@ _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators,
|
||||||
if (pdf_operators->is_new_text_object ||
|
if (pdf_operators->is_new_text_object ||
|
||||||
! _cairo_matrix_scale_equal (&pdf_operators->text_matrix, &text_matrix))
|
! _cairo_matrix_scale_equal (&pdf_operators->text_matrix, &text_matrix))
|
||||||
{
|
{
|
||||||
_cairo_pdf_operators_flush_glyphs (pdf_operators);
|
status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
x = glyphs[0].x;
|
x = glyphs[0].x;
|
||||||
y = glyphs[0].y;
|
y = glyphs[0].y;
|
||||||
cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &x, &y);
|
cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &x, &y);
|
||||||
|
@ -1391,25 +1409,25 @@ _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators,
|
||||||
|
|
||||||
if (num_clusters > 0) {
|
if (num_clusters > 0) {
|
||||||
cur_text = utf8;
|
cur_text = utf8;
|
||||||
if (backward)
|
if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
|
||||||
cur_glyph = glyphs + num_glyphs;
|
cur_glyph = glyphs + num_glyphs;
|
||||||
else
|
else
|
||||||
cur_glyph = glyphs;
|
cur_glyph = glyphs;
|
||||||
for (i = 0; i < num_clusters; i++) {
|
for (i = 0; i < num_clusters; i++) {
|
||||||
if (backward)
|
if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
|
||||||
cur_glyph -= clusters[i].num_glyphs;
|
cur_glyph -= clusters[i].num_glyphs;
|
||||||
status = _cairo_pdf_operators_emit_cluster (pdf_operators,
|
status = _cairo_pdf_operators_emit_cluster (pdf_operators,
|
||||||
cur_text,
|
cur_text,
|
||||||
clusters[i].num_bytes,
|
clusters[i].num_bytes,
|
||||||
cur_glyph,
|
cur_glyph,
|
||||||
clusters[i].num_glyphs,
|
clusters[i].num_glyphs,
|
||||||
backward,
|
cluster_flags,
|
||||||
scaled_font);
|
scaled_font);
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
cur_text += clusters[i].num_bytes;
|
cur_text += clusters[i].num_bytes;
|
||||||
if (!backward)
|
if (!(cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
|
||||||
cur_glyph += clusters[i].num_glyphs;
|
cur_glyph += clusters[i].num_glyphs;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -96,7 +96,7 @@ typedef struct _cairo_pdf_smask_group
|
||||||
int num_glyphs;
|
int num_glyphs;
|
||||||
cairo_text_cluster_t *clusters;
|
cairo_text_cluster_t *clusters;
|
||||||
int num_clusters;
|
int num_clusters;
|
||||||
cairo_bool_t backward;
|
cairo_bool_t cluster_flags;
|
||||||
cairo_scaled_font_t *scaled_font;
|
cairo_scaled_font_t *scaled_font;
|
||||||
} cairo_pdf_smask_group_t;
|
} cairo_pdf_smask_group_t;
|
||||||
|
|
||||||
|
|
|
@ -44,10 +44,11 @@
|
||||||
#include "cairo-pdf.h"
|
#include "cairo-pdf.h"
|
||||||
#include "cairo-pdf-surface-private.h"
|
#include "cairo-pdf-surface-private.h"
|
||||||
#include "cairo-pdf-operators-private.h"
|
#include "cairo-pdf-operators-private.h"
|
||||||
#include "cairo-scaled-font-subsets-private.h"
|
#include "cairo-analysis-surface-private.h"
|
||||||
#include "cairo-paginated-private.h"
|
|
||||||
#include "cairo-output-stream-private.h"
|
|
||||||
#include "cairo-meta-surface-private.h"
|
#include "cairo-meta-surface-private.h"
|
||||||
|
#include "cairo-output-stream-private.h"
|
||||||
|
#include "cairo-paginated-private.h"
|
||||||
|
#include "cairo-scaled-font-subsets-private.h"
|
||||||
#include "cairo-type3-glyph-surface-private.h"
|
#include "cairo-type3-glyph-surface-private.h"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
@ -325,7 +326,10 @@ BAIL0:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_pdf_surface_create_for_stream:
|
* cairo_pdf_surface_create_for_stream:
|
||||||
* @write_func: a #cairo_write_func_t to accept the output data
|
* @write_func: a #cairo_write_func_t to accept the output data, may be %NULL
|
||||||
|
* to indicate a no-op @write_func. With a no-op @write_func,
|
||||||
|
* the surface may be queried or used as a source without
|
||||||
|
* generating any temporary files.
|
||||||
* @closure: the closure argument for @write_func
|
* @closure: the closure argument for @write_func
|
||||||
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
|
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
|
||||||
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
|
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
|
||||||
|
@ -362,7 +366,10 @@ cairo_pdf_surface_create_for_stream (cairo_write_func_t write_func,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_pdf_surface_create:
|
* cairo_pdf_surface_create:
|
||||||
* @filename: a filename for the PDF output (must be writable)
|
* @filename: a filename for the PDF output (must be writable), %NULL may be
|
||||||
|
* used to specify no output. This will generate a PDF surface that
|
||||||
|
* may be queried and used as a source, without generating a
|
||||||
|
* temporary file.
|
||||||
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
|
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
|
||||||
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
|
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
|
||||||
*
|
*
|
||||||
|
@ -1276,8 +1283,8 @@ _cairo_pdf_surface_start_page (void *abstract_surface)
|
||||||
}
|
}
|
||||||
|
|
||||||
static cairo_int_status_t
|
static cairo_int_status_t
|
||||||
_cairo_pdf_surface_has_fallback_images (void *abstract_surface,
|
_cairo_pdf_surface_has_fallback_images (void *abstract_surface,
|
||||||
cairo_bool_t has_fallbacks)
|
cairo_bool_t has_fallbacks)
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
cairo_pdf_surface_t *surface = abstract_surface;
|
cairo_pdf_surface_t *surface = abstract_surface;
|
||||||
|
@ -1290,6 +1297,12 @@ _cairo_pdf_surface_has_fallback_images (void *abstract_surface,
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cairo_bool_t
|
||||||
|
_cairo_pdf_surface_supports_fine_grained_fallbacks (void *abstract_surface)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Emit alpha channel from the image into the given data, providing
|
/* Emit alpha channel from the image into the given data, providing
|
||||||
* an id that can be used to reference the resulting SMask object.
|
* an id that can be used to reference the resulting SMask object.
|
||||||
*
|
*
|
||||||
|
@ -2609,13 +2622,11 @@ _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
int alpha;
|
int alpha;
|
||||||
cairo_bool_t is_solid_color = FALSE;
|
cairo_color_t *solid_color = NULL;
|
||||||
cairo_color_t *solid_color;
|
|
||||||
|
|
||||||
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
|
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
|
||||||
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
|
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
|
||||||
|
|
||||||
is_solid_color = TRUE;
|
|
||||||
solid_color = &solid->color;
|
solid_color = &solid->color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2624,13 +2635,11 @@ _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
|
||||||
{
|
{
|
||||||
cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
|
cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
|
||||||
|
|
||||||
if (gradient->n_stops == 1) {
|
if (gradient->n_stops == 1)
|
||||||
is_solid_color = TRUE;
|
|
||||||
solid_color = &gradient->stops[0].color;
|
solid_color = &gradient->stops[0].color;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_solid_color) {
|
if (solid_color != NULL) {
|
||||||
if (surface->current_pattern_is_solid_color == FALSE ||
|
if (surface->current_pattern_is_solid_color == FALSE ||
|
||||||
surface->current_color_red != solid_color->red ||
|
surface->current_color_red != solid_color->red ||
|
||||||
surface->current_color_green != solid_color->green ||
|
surface->current_color_green != solid_color->green ||
|
||||||
|
@ -2960,7 +2969,11 @@ _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface,
|
||||||
"<%02x> ",
|
"<%02x> ",
|
||||||
i + 1);
|
i + 1);
|
||||||
}
|
}
|
||||||
_cairo_pdf_surface_emit_unicode_for_glyph (surface, font_subset->utf8[i + 1]);
|
status = _cairo_pdf_surface_emit_unicode_for_glyph (surface,
|
||||||
|
font_subset->utf8[i + 1]);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
_cairo_output_stream_printf (surface->output,
|
_cairo_output_stream_printf (surface->output,
|
||||||
"\n");
|
"\n");
|
||||||
}
|
}
|
||||||
|
@ -3480,6 +3493,41 @@ _cairo_pdf_emit_imagemask (cairo_image_surface_t *image,
|
||||||
return _cairo_output_stream_get_status (stream);
|
return _cairo_output_stream_get_status (stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cairo_status_t
|
||||||
|
_cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset,
|
||||||
|
void *closure)
|
||||||
|
{
|
||||||
|
cairo_pdf_surface_t *surface = closure;
|
||||||
|
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||||
|
cairo_status_t status2;
|
||||||
|
unsigned int i;
|
||||||
|
cairo_surface_t *type3_surface;
|
||||||
|
cairo_output_stream_t *null_stream;
|
||||||
|
|
||||||
|
null_stream = _cairo_null_stream_create ();
|
||||||
|
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
|
||||||
|
null_stream,
|
||||||
|
_cairo_pdf_emit_imagemask,
|
||||||
|
surface->font_subsets);
|
||||||
|
_cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
|
||||||
|
_cairo_pdf_surface_add_font,
|
||||||
|
surface);
|
||||||
|
|
||||||
|
for (i = 0; i < font_subset->num_glyphs; i++) {
|
||||||
|
status = _cairo_type3_glyph_surface_analyze_glyph (type3_surface,
|
||||||
|
font_subset->glyphs[i]);
|
||||||
|
if (status)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_surface_destroy (type3_surface);
|
||||||
|
status2 = _cairo_output_stream_destroy (null_stream);
|
||||||
|
if (status == CAIRO_STATUS_SUCCESS)
|
||||||
|
status = status2;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
static cairo_status_t
|
static cairo_status_t
|
||||||
_cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
|
_cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
|
||||||
cairo_scaled_font_subset_t *font_subset)
|
cairo_scaled_font_subset_t *font_subset)
|
||||||
|
@ -3512,9 +3560,14 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cairo_pdf_group_resources_clear (&surface->resources);
|
||||||
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
|
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
|
||||||
NULL,
|
NULL,
|
||||||
_cairo_pdf_emit_imagemask);
|
_cairo_pdf_emit_imagemask,
|
||||||
|
surface->font_subsets);
|
||||||
|
_cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
|
||||||
|
_cairo_pdf_surface_add_font,
|
||||||
|
surface);
|
||||||
|
|
||||||
for (i = 0; i < font_subset->num_glyphs; i++) {
|
for (i = 0; i < font_subset->num_glyphs; i++) {
|
||||||
status = _cairo_pdf_surface_open_stream (surface,
|
status = _cairo_pdf_surface_open_stream (surface,
|
||||||
|
@ -3525,18 +3578,11 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
glyphs[i] = surface->pdf_stream.self;
|
glyphs[i] = surface->pdf_stream.self;
|
||||||
if (i == 0) {
|
status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
|
||||||
status = _cairo_type3_glyph_surface_emit_notdef_glyph (type3_surface,
|
surface->output,
|
||||||
surface->output,
|
font_subset->glyphs[i],
|
||||||
&bbox,
|
&bbox,
|
||||||
&widths[i]);
|
&widths[i]);
|
||||||
} else {
|
|
||||||
status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
|
|
||||||
surface->output,
|
|
||||||
font_subset->glyphs[i],
|
|
||||||
&bbox,
|
|
||||||
&widths[i]);
|
|
||||||
}
|
|
||||||
if (status)
|
if (status)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -3642,6 +3688,10 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
|
||||||
"]\n");
|
"]\n");
|
||||||
free (widths);
|
free (widths);
|
||||||
|
|
||||||
|
_cairo_output_stream_printf (surface->output,
|
||||||
|
" /Resources\n");
|
||||||
|
_cairo_pdf_surface_emit_group_resources (surface, &surface->resources);
|
||||||
|
|
||||||
if (to_unicode_stream.id != 0)
|
if (to_unicode_stream.id != 0)
|
||||||
_cairo_output_stream_printf (surface->output,
|
_cairo_output_stream_printf (surface->output,
|
||||||
" /ToUnicode %d 0 R\n",
|
" /ToUnicode %d 0 R\n",
|
||||||
|
@ -3713,6 +3763,12 @@ _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface)
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
|
||||||
|
status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
|
||||||
|
_cairo_pdf_surface_analyze_user_font_subset,
|
||||||
|
surface);
|
||||||
|
if (status)
|
||||||
|
goto BAIL;
|
||||||
|
|
||||||
status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
|
status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
|
||||||
_cairo_pdf_surface_emit_unscaled_font_subset,
|
_cairo_pdf_surface_emit_unscaled_font_subset,
|
||||||
surface);
|
surface);
|
||||||
|
@ -3722,6 +3778,12 @@ _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface)
|
||||||
status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
|
status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
|
||||||
_cairo_pdf_surface_emit_scaled_font_subset,
|
_cairo_pdf_surface_emit_scaled_font_subset,
|
||||||
surface);
|
surface);
|
||||||
|
if (status)
|
||||||
|
goto BAIL;
|
||||||
|
|
||||||
|
status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
|
||||||
|
_cairo_pdf_surface_emit_scaled_font_subset,
|
||||||
|
surface);
|
||||||
|
|
||||||
BAIL:
|
BAIL:
|
||||||
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
|
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
|
||||||
|
@ -3985,7 +4047,7 @@ _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface,
|
||||||
group->utf8, group->utf8_len,
|
group->utf8, group->utf8_len,
|
||||||
group->glyphs, group->num_glyphs,
|
group->glyphs, group->num_glyphs,
|
||||||
group->clusters, group->num_clusters,
|
group->clusters, group->num_clusters,
|
||||||
group->backward,
|
group->cluster_flags,
|
||||||
group->scaled_font);
|
group->scaled_font);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -4414,19 +4476,21 @@ _cairo_pdf_surface_mask (void *abstract_surface,
|
||||||
{
|
{
|
||||||
cairo_pdf_surface_t *surface = abstract_surface;
|
cairo_pdf_surface_t *surface = abstract_surface;
|
||||||
cairo_pdf_smask_group_t *group;
|
cairo_pdf_smask_group_t *group;
|
||||||
cairo_status_t status, status2;
|
cairo_status_t status;
|
||||||
|
|
||||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
|
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
|
||||||
status = _cairo_pdf_surface_analyze_operation (surface, op, source);
|
cairo_status_t source_status, mask_status;
|
||||||
if (status != CAIRO_STATUS_SUCCESS &&
|
|
||||||
status != CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
status2 = _cairo_pdf_surface_analyze_operation (surface, op, mask);
|
source_status = _cairo_pdf_surface_analyze_operation (surface, op, source);
|
||||||
if (status2 != CAIRO_STATUS_SUCCESS)
|
if (_cairo_status_is_error (source_status))
|
||||||
return status2;
|
return source_status;
|
||||||
|
|
||||||
return status;
|
mask_status = _cairo_pdf_surface_analyze_operation (surface, op, mask);
|
||||||
|
if (_cairo_status_is_error (mask_status))
|
||||||
|
return mask_status;
|
||||||
|
|
||||||
|
return _cairo_analysis_surface_merge_status (source_status,
|
||||||
|
mask_status);
|
||||||
} else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
|
} else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
|
||||||
status = _cairo_pdf_surface_start_fallback (surface);
|
status = _cairo_pdf_surface_start_fallback (surface);
|
||||||
if (status)
|
if (status)
|
||||||
|
@ -4756,7 +4820,7 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
const cairo_text_cluster_t *clusters,
|
const cairo_text_cluster_t *clusters,
|
||||||
int num_clusters,
|
int num_clusters,
|
||||||
cairo_bool_t backward,
|
cairo_text_cluster_flags_t cluster_flags,
|
||||||
cairo_scaled_font_t *scaled_font)
|
cairo_scaled_font_t *scaled_font)
|
||||||
{
|
{
|
||||||
cairo_pdf_surface_t *surface = abstract_surface;
|
cairo_pdf_surface_t *surface = abstract_surface;
|
||||||
|
@ -4858,7 +4922,7 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
|
||||||
utf8, utf8_len,
|
utf8, utf8_len,
|
||||||
glyphs, num_glyphs,
|
glyphs, num_glyphs,
|
||||||
clusters, num_clusters,
|
clusters, num_clusters,
|
||||||
backward,
|
cluster_flags,
|
||||||
scaled_font);
|
scaled_font);
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
@ -4922,9 +4986,11 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
|
||||||
_cairo_pdf_surface_show_text_glyphs,
|
_cairo_pdf_surface_show_text_glyphs,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend = {
|
static const cairo_paginated_surface_backend_t
|
||||||
|
cairo_pdf_surface_paginated_backend = {
|
||||||
_cairo_pdf_surface_start_page,
|
_cairo_pdf_surface_start_page,
|
||||||
_cairo_pdf_surface_set_paginated_mode,
|
_cairo_pdf_surface_set_paginated_mode,
|
||||||
NULL, /* set_bounding_box */
|
NULL, /* set_bounding_box */
|
||||||
_cairo_pdf_surface_has_fallback_images,
|
_cairo_pdf_surface_has_fallback_images,
|
||||||
|
_cairo_pdf_surface_supports_fine_grained_fallbacks,
|
||||||
};
|
};
|
||||||
|
|
|
@ -524,7 +524,7 @@ read_png (png_rw_ptr read_func,
|
||||||
png_get_IHDR (png, info,
|
png_get_IHDR (png, info,
|
||||||
&png_width, &png_height, &depth,
|
&png_width, &png_height, &depth,
|
||||||
&color_type, &interlace, NULL, NULL);
|
&color_type, &interlace, NULL, NULL);
|
||||||
if (depth != 8 || interlace != PNG_INTERLACE_NONE ||
|
if (depth != 8 ||
|
||||||
! (color_type == PNG_COLOR_TYPE_RGB ||
|
! (color_type == PNG_COLOR_TYPE_RGB ||
|
||||||
color_type == PNG_COLOR_TYPE_RGB_ALPHA))
|
color_type == PNG_COLOR_TYPE_RGB_ALPHA))
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,11 +36,6 @@
|
||||||
|
|
||||||
#include "cairoint.h"
|
#include "cairoint.h"
|
||||||
|
|
||||||
/* private functions */
|
|
||||||
|
|
||||||
static cairo_status_t
|
|
||||||
_cairo_polygon_grow (cairo_polygon_t *polygon);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_cairo_polygon_init (cairo_polygon_t *polygon)
|
_cairo_polygon_init (cairo_polygon_t *polygon)
|
||||||
{
|
{
|
||||||
|
@ -57,31 +52,17 @@ _cairo_polygon_init (cairo_polygon_t *polygon)
|
||||||
void
|
void
|
||||||
_cairo_polygon_fini (cairo_polygon_t *polygon)
|
_cairo_polygon_fini (cairo_polygon_t *polygon)
|
||||||
{
|
{
|
||||||
if (polygon->edges && polygon->edges != polygon->edges_embedded)
|
if (polygon->edges != polygon->edges_embedded)
|
||||||
free (polygon->edges);
|
free (polygon->edges);
|
||||||
|
|
||||||
polygon->edges = NULL;
|
|
||||||
polygon->edges_size = 0;
|
|
||||||
polygon->num_edges = 0;
|
|
||||||
|
|
||||||
polygon->has_current_point = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
cairo_status_t
|
|
||||||
_cairo_polygon_status (cairo_polygon_t *polygon)
|
|
||||||
{
|
|
||||||
return polygon->status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make room for at least one more edge */
|
/* make room for at least one more edge */
|
||||||
static cairo_status_t
|
static cairo_bool_t
|
||||||
_cairo_polygon_grow (cairo_polygon_t *polygon)
|
_cairo_polygon_grow (cairo_polygon_t *polygon)
|
||||||
{
|
{
|
||||||
cairo_edge_t *new_edges;
|
cairo_edge_t *new_edges;
|
||||||
int old_size = polygon->edges_size;
|
int old_size = polygon->edges_size;
|
||||||
int new_size = 2 * old_size;
|
int new_size = 4 * old_size;
|
||||||
|
|
||||||
assert (polygon->num_edges <= polygon->edges_size);
|
|
||||||
|
|
||||||
if (polygon->edges == polygon->edges_embedded) {
|
if (polygon->edges == polygon->edges_embedded) {
|
||||||
new_edges = _cairo_malloc_ab (new_size, sizeof (cairo_edge_t));
|
new_edges = _cairo_malloc_ab (new_size, sizeof (cairo_edge_t));
|
||||||
|
@ -92,34 +73,34 @@ _cairo_polygon_grow (cairo_polygon_t *polygon)
|
||||||
new_size, sizeof (cairo_edge_t));
|
new_size, sizeof (cairo_edge_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_edges == NULL)
|
if (new_edges == NULL) {
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
polygon->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
polygon->edges = new_edges;
|
polygon->edges = new_edges;
|
||||||
polygon->edges_size = new_size;
|
polygon->edges_size = new_size;
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
_cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_point_t *p2)
|
_cairo_polygon_add_edge (cairo_polygon_t *polygon,
|
||||||
|
const cairo_point_t *p1,
|
||||||
|
const cairo_point_t *p2)
|
||||||
{
|
{
|
||||||
cairo_edge_t *edge;
|
cairo_edge_t *edge;
|
||||||
|
|
||||||
if (polygon->status)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* drop horizontal edges */
|
/* drop horizontal edges */
|
||||||
if (p1->y == p2->y)
|
if (p1->y == p2->y)
|
||||||
goto DONE;
|
goto DONE;
|
||||||
|
|
||||||
if (polygon->num_edges >= polygon->edges_size) {
|
if (polygon->num_edges == polygon->edges_size) {
|
||||||
polygon->status = _cairo_polygon_grow (polygon);
|
if (! _cairo_polygon_grow (polygon))
|
||||||
if (polygon->status)
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
edge = &polygon->edges[polygon->num_edges];
|
edge = &polygon->edges[polygon->num_edges++];
|
||||||
if (p1->y < p2->y) {
|
if (p1->y < p2->y) {
|
||||||
edge->edge.p1 = *p1;
|
edge->edge.p1 = *p1;
|
||||||
edge->edge.p2 = *p2;
|
edge->edge.p2 = *p2;
|
||||||
|
@ -130,18 +111,14 @@ _cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_poin
|
||||||
edge->clockWise = 0;
|
edge->clockWise = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
polygon->num_edges++;
|
|
||||||
|
|
||||||
DONE:
|
DONE:
|
||||||
_cairo_polygon_move_to (polygon, p2);
|
_cairo_polygon_move_to (polygon, p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cairo_polygon_move_to (cairo_polygon_t *polygon, cairo_point_t *point)
|
_cairo_polygon_move_to (cairo_polygon_t *polygon,
|
||||||
|
const cairo_point_t *point)
|
||||||
{
|
{
|
||||||
if (polygon->status)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (! polygon->has_current_point)
|
if (! polygon->has_current_point)
|
||||||
polygon->first_point = *point;
|
polygon->first_point = *point;
|
||||||
|
|
||||||
|
@ -150,24 +127,18 @@ _cairo_polygon_move_to (cairo_polygon_t *polygon, cairo_point_t *point)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cairo_polygon_line_to (cairo_polygon_t *polygon, cairo_point_t *point)
|
_cairo_polygon_line_to (cairo_polygon_t *polygon,
|
||||||
|
const cairo_point_t *point)
|
||||||
{
|
{
|
||||||
if (polygon->status)
|
if (polygon->has_current_point)
|
||||||
return;
|
|
||||||
|
|
||||||
if (polygon->has_current_point) {
|
|
||||||
_cairo_polygon_add_edge (polygon, &polygon->current_point, point);
|
_cairo_polygon_add_edge (polygon, &polygon->current_point, point);
|
||||||
} else {
|
else
|
||||||
_cairo_polygon_move_to (polygon, point);
|
_cairo_polygon_move_to (polygon, point);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cairo_polygon_close (cairo_polygon_t *polygon)
|
_cairo_polygon_close (cairo_polygon_t *polygon)
|
||||||
{
|
{
|
||||||
if (polygon->status)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (polygon->has_current_point) {
|
if (polygon->has_current_point) {
|
||||||
_cairo_polygon_add_edge (polygon,
|
_cairo_polygon_add_edge (polygon,
|
||||||
&polygon->current_point,
|
&polygon->current_point,
|
||||||
|
|
|
@ -72,10 +72,7 @@ typedef struct cairo_ps_surface {
|
||||||
cairo_bool_t use_string_datasource;
|
cairo_bool_t use_string_datasource;
|
||||||
|
|
||||||
cairo_bool_t current_pattern_is_solid_color;
|
cairo_bool_t current_pattern_is_solid_color;
|
||||||
double current_color_red;
|
cairo_color_t current_color;
|
||||||
double current_color_green;
|
|
||||||
double current_color_blue;
|
|
||||||
double current_color_alpha;
|
|
||||||
|
|
||||||
int num_pages;
|
int num_pages;
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,19 @@
|
||||||
* Adrian Johnson <ajohnson@redneon.com>
|
* Adrian Johnson <ajohnson@redneon.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Design of the PS output:
|
||||||
|
*
|
||||||
|
* The PS output is harmonised with the PDF operations using PS procedures
|
||||||
|
* to emulate the PDF operators.
|
||||||
|
*
|
||||||
|
* This has a number of advantages:
|
||||||
|
* 1. A large chunk of code is shared between the PDF and PS backends.
|
||||||
|
* See cairo-pdf-operators.
|
||||||
|
* 2. Using gs to do PS -> PDF and PDF -> PS will always work well.
|
||||||
|
*/
|
||||||
|
|
||||||
#define _BSD_SOURCE /* for ctime_r(), snprintf(), strdup() */
|
#define _BSD_SOURCE /* for ctime_r(), snprintf(), strdup() */
|
||||||
#include "cairoint.h"
|
#include "cairoint.h"
|
||||||
#include "cairo-ps.h"
|
#include "cairo-ps.h"
|
||||||
|
@ -173,6 +186,8 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
|
||||||
"/S { stroke } bind def\n"
|
"/S { stroke } bind def\n"
|
||||||
"/f { fill } bind def\n"
|
"/f { fill } bind def\n"
|
||||||
"/f* { eofill } bind def\n"
|
"/f* { eofill } bind def\n"
|
||||||
|
"/B { fill stroke } bind def\n"
|
||||||
|
"/B* { eofill stroke } bind def\n"
|
||||||
"/n { newpath } bind def\n"
|
"/n { newpath } bind def\n"
|
||||||
"/W { clip } bind def\n"
|
"/W { clip } bind def\n"
|
||||||
"/W* { eoclip } bind def\n"
|
"/W* { eoclip } bind def\n"
|
||||||
|
@ -196,12 +211,12 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
|
||||||
"/cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore\n"
|
"/cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore\n"
|
||||||
" cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def\n"
|
" cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def\n"
|
||||||
"/Tf { pop /cairo_font exch def /cairo_font_matrix where\n"
|
"/Tf { pop /cairo_font exch def /cairo_font_matrix where\n"
|
||||||
" { cairo_selectfont } if } bind def\n"
|
" { pop cairo_selectfont } if } bind def\n"
|
||||||
"/Td { matrix translate cairo_font_matrix matrix concatmatrix dup\n"
|
"/Td { matrix translate cairo_font_matrix matrix concatmatrix dup\n"
|
||||||
" /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point\n"
|
" /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point\n"
|
||||||
" /cairo_font where { cairo_selectfont } if } bind def\n"
|
" /cairo_font where { pop cairo_selectfont } if } bind def\n"
|
||||||
"/Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def\n"
|
"/Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def\n"
|
||||||
" cairo_store_point /cairo_font where { cairo_selectfont } if } bind def\n"
|
" cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def\n"
|
||||||
"/g { setgray } bind def\n"
|
"/g { setgray } bind def\n"
|
||||||
"/rg { setrgbcolor } bind def\n"
|
"/rg { setrgbcolor } bind def\n"
|
||||||
"/d1 { setcachedevice } bind def\n");
|
"/d1 { setcachedevice } bind def\n");
|
||||||
|
@ -426,6 +441,32 @@ _cairo_ps_emit_imagemask (cairo_image_surface_t *image,
|
||||||
return _cairo_output_stream_get_status (stream);
|
return _cairo_output_stream_get_status (stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cairo_status_t
|
||||||
|
_cairo_ps_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset,
|
||||||
|
void *closure)
|
||||||
|
{
|
||||||
|
cairo_ps_surface_t *surface = closure;
|
||||||
|
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||||
|
unsigned int i;
|
||||||
|
cairo_surface_t *type3_surface;
|
||||||
|
|
||||||
|
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
|
||||||
|
NULL,
|
||||||
|
_cairo_ps_emit_imagemask,
|
||||||
|
surface->font_subsets);
|
||||||
|
|
||||||
|
for (i = 0; i < font_subset->num_glyphs; i++) {
|
||||||
|
status = _cairo_type3_glyph_surface_analyze_glyph (type3_surface,
|
||||||
|
font_subset->glyphs[i]);
|
||||||
|
if (status)
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
cairo_surface_destroy (type3_surface);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
static cairo_status_t
|
static cairo_status_t
|
||||||
_cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
|
_cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
|
||||||
cairo_scaled_font_subset_t *font_subset)
|
cairo_scaled_font_subset_t *font_subset)
|
||||||
|
@ -439,6 +480,9 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
|
||||||
cairo_surface_t *type3_surface;
|
cairo_surface_t *type3_surface;
|
||||||
double width;
|
double width;
|
||||||
|
|
||||||
|
if (font_subset->num_glyphs == 0)
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
|
||||||
#if DEBUG_PS
|
#if DEBUG_PS
|
||||||
_cairo_output_stream_printf (surface->final_stream,
|
_cairo_output_stream_printf (surface->final_stream,
|
||||||
"%% _cairo_ps_surface_emit_type3_font_subset\n");
|
"%% _cairo_ps_surface_emit_type3_font_subset\n");
|
||||||
|
@ -453,9 +497,10 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
|
||||||
|
|
||||||
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
|
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
|
||||||
NULL,
|
NULL,
|
||||||
_cairo_ps_emit_imagemask);
|
_cairo_ps_emit_imagemask,
|
||||||
|
surface->font_subsets);
|
||||||
|
|
||||||
for (i = 1; i < font_subset->num_glyphs; i++) {
|
for (i = 0; i < font_subset->num_glyphs; i++) {
|
||||||
if (font_subset->glyph_names != NULL) {
|
if (font_subset->glyph_names != NULL) {
|
||||||
_cairo_output_stream_printf (surface->final_stream,
|
_cairo_output_stream_printf (surface->final_stream,
|
||||||
"Encoding %d /%s put\n",
|
"Encoding %d /%s put\n",
|
||||||
|
@ -472,20 +517,13 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
|
||||||
for (i = 0; i < font_subset->num_glyphs; i++) {
|
for (i = 0; i < font_subset->num_glyphs; i++) {
|
||||||
_cairo_output_stream_printf (surface->final_stream,
|
_cairo_output_stream_printf (surface->final_stream,
|
||||||
" { %% %d\n", i);
|
" { %% %d\n", i);
|
||||||
if (i == 0) {
|
status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
|
||||||
status = _cairo_type3_glyph_surface_emit_notdef_glyph (type3_surface,
|
surface->final_stream,
|
||||||
surface->final_stream,
|
font_subset->glyphs[i],
|
||||||
&bbox,
|
&bbox,
|
||||||
&width);
|
&width);
|
||||||
} else {
|
|
||||||
status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
|
|
||||||
surface->final_stream,
|
|
||||||
font_subset->glyphs[i],
|
|
||||||
&bbox,
|
|
||||||
&width);
|
|
||||||
}
|
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
break;
|
||||||
|
|
||||||
_cairo_output_stream_printf (surface->final_stream,
|
_cairo_output_stream_printf (surface->final_stream,
|
||||||
" }\n");
|
" }\n");
|
||||||
|
@ -506,13 +544,16 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cairo_surface_destroy (type3_surface);
|
cairo_surface_destroy (type3_surface);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
_cairo_output_stream_printf (surface->final_stream,
|
_cairo_output_stream_printf (surface->final_stream,
|
||||||
"] def\n"
|
"] def\n"
|
||||||
"/FontBBox [%f %f %f %f] def\n"
|
"/FontBBox [%f %f %f %f] def\n"
|
||||||
"/BuildChar {\n"
|
"/BuildChar {\n"
|
||||||
" exch /Glyphs get\n"
|
" exch /Glyphs get\n"
|
||||||
" exch get exec\n"
|
" exch get\n"
|
||||||
|
" 10 dict begin exec end\n"
|
||||||
"} bind def\n"
|
"} bind def\n"
|
||||||
"currentdict\n"
|
"currentdict\n"
|
||||||
"end\n"
|
"end\n"
|
||||||
|
@ -586,6 +627,12 @@ _cairo_ps_surface_emit_font_subsets (cairo_ps_surface_t *surface)
|
||||||
"%% _cairo_ps_surface_emit_font_subsets\n");
|
"%% _cairo_ps_surface_emit_font_subsets\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
|
||||||
|
_cairo_ps_surface_analyze_user_font_subset,
|
||||||
|
surface);
|
||||||
|
if (status)
|
||||||
|
goto BAIL;
|
||||||
|
|
||||||
status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
|
status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
|
||||||
_cairo_ps_surface_emit_unscaled_font_subset,
|
_cairo_ps_surface_emit_unscaled_font_subset,
|
||||||
surface);
|
surface);
|
||||||
|
@ -595,7 +642,12 @@ _cairo_ps_surface_emit_font_subsets (cairo_ps_surface_t *surface)
|
||||||
status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
|
status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
|
||||||
_cairo_ps_surface_emit_scaled_font_subset,
|
_cairo_ps_surface_emit_scaled_font_subset,
|
||||||
surface);
|
surface);
|
||||||
|
if (status)
|
||||||
|
goto BAIL;
|
||||||
|
|
||||||
|
status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
|
||||||
|
_cairo_ps_surface_emit_scaled_font_subset,
|
||||||
|
surface);
|
||||||
BAIL:
|
BAIL:
|
||||||
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
|
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
|
||||||
surface->font_subsets = NULL;
|
surface->font_subsets = NULL;
|
||||||
|
@ -734,7 +786,10 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_ps_surface_create:
|
* cairo_ps_surface_create:
|
||||||
* @filename: a filename for the PS output (must be writable)
|
* @filename: a filename for the PS output (must be writable), %NULL may be
|
||||||
|
* used to specify no output. This will generate a PS surface that
|
||||||
|
* may be queried and used as a source, without generating a
|
||||||
|
* temporary file.
|
||||||
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
|
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
|
||||||
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
|
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
|
||||||
*
|
*
|
||||||
|
@ -774,7 +829,10 @@ cairo_ps_surface_create (const char *filename,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_ps_surface_create_for_stream:
|
* cairo_ps_surface_create_for_stream:
|
||||||
* @write_func: a #cairo_write_func_t to accept the output data
|
* @write_func: a #cairo_write_func_t to accept the output data, may be %NULL
|
||||||
|
* to indicate a no-op @write_func. With a no-op @write_func,
|
||||||
|
* the surface may be queried or used as a source without
|
||||||
|
* generating any temporary files.
|
||||||
* @closure: the closure argument for @write_func
|
* @closure: the closure argument for @write_func
|
||||||
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
|
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
|
||||||
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
|
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
|
||||||
|
@ -1422,12 +1480,25 @@ static cairo_bool_t
|
||||||
_gradient_pattern_supported (cairo_ps_surface_t *surface,
|
_gradient_pattern_supported (cairo_ps_surface_t *surface,
|
||||||
cairo_pattern_t *pattern)
|
cairo_pattern_t *pattern)
|
||||||
{
|
{
|
||||||
|
cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
|
||||||
|
uint16_t alpha;
|
||||||
cairo_extend_t extend;
|
cairo_extend_t extend;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
if (surface->ps_level == CAIRO_PS_LEVEL_2)
|
if (surface->ps_level == CAIRO_PS_LEVEL_2)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
surface->ps_level_used = CAIRO_PS_LEVEL_3;
|
if (gradient->n_stops == 0)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* Alpha gradients are only supported (by flattening the alpha)
|
||||||
|
* if there is no variation in the alpha across the gradient. */
|
||||||
|
alpha = gradient->stops[0].color.alpha_short;
|
||||||
|
for (i = 0; i < gradient->n_stops; i++) {
|
||||||
|
if (gradient->stops[i].color.alpha_short != alpha)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
extend = cairo_pattern_get_extend (pattern);
|
extend = cairo_pattern_get_extend (pattern);
|
||||||
|
|
||||||
/* Radial gradients are currently only supported when one circle
|
/* Radial gradients are currently only supported when one circle
|
||||||
|
@ -1454,6 +1525,8 @@ _gradient_pattern_supported (cairo_ps_surface_t *surface,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
surface->ps_level_used = CAIRO_PS_LEVEL_3;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1504,7 +1577,7 @@ _cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface,
|
||||||
* surface. If the analysis surface determines that there is
|
* surface. If the analysis surface determines that there is
|
||||||
* anything drawn under this operation, a fallback image will be
|
* anything drawn under this operation, a fallback image will be
|
||||||
* used. Otherwise the operation will be replayed during the
|
* used. Otherwise the operation will be replayed during the
|
||||||
* render stage and we blend the transarency into the white
|
* render stage and we blend the transparency into the white
|
||||||
* background to convert the pattern to opaque.
|
* background to convert the pattern to opaque.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -2089,21 +2162,19 @@ _cairo_ps_surface_flatten_transparency (cairo_ps_surface_t *surface,
|
||||||
double *green,
|
double *green,
|
||||||
double *blue)
|
double *blue)
|
||||||
{
|
{
|
||||||
*red = color->red;
|
*red = color->red;
|
||||||
*green = color->green;
|
*green = color->green;
|
||||||
*blue = color->blue;
|
*blue = color->blue;
|
||||||
|
|
||||||
if (!CAIRO_COLOR_IS_OPAQUE(color)) {
|
if (! CAIRO_COLOR_IS_OPAQUE (color)) {
|
||||||
|
*red *= color->alpha;
|
||||||
|
*green *= color->alpha;
|
||||||
|
*blue *= color->alpha;
|
||||||
if (surface->content == CAIRO_CONTENT_COLOR_ALPHA) {
|
if (surface->content == CAIRO_CONTENT_COLOR_ALPHA) {
|
||||||
uint8_t one_minus_alpha = 255 - (color->alpha_short >> 8);
|
double one_minus_alpha = 1. - color->alpha;
|
||||||
|
*red += one_minus_alpha;
|
||||||
*red = ((color->red_short >> 8) + one_minus_alpha) / 255.0;
|
*green += one_minus_alpha;
|
||||||
*green = ((color->green_short >> 8) + one_minus_alpha) / 255.0;
|
*blue += one_minus_alpha;
|
||||||
*blue = ((color->blue_short >> 8) + one_minus_alpha) / 255.0;
|
|
||||||
} else {
|
|
||||||
*red = (color->red_short >> 8) / 255.0;
|
|
||||||
*green = (color->green_short >> 8) / 255.0;
|
|
||||||
*blue = (color->blue_short >> 8) / 255.0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2826,10 +2897,7 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface,
|
||||||
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
|
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
|
||||||
|
|
||||||
if (surface->current_pattern_is_solid_color == FALSE ||
|
if (surface->current_pattern_is_solid_color == FALSE ||
|
||||||
surface->current_color_red != solid->color.red ||
|
! _cairo_color_equal (&surface->current_color, &solid->color))
|
||||||
surface->current_color_green != solid->color.green ||
|
|
||||||
surface->current_color_blue != solid->color.blue ||
|
|
||||||
surface->current_color_alpha != solid->color.alpha)
|
|
||||||
{
|
{
|
||||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||||
if (status)
|
if (status)
|
||||||
|
@ -2838,10 +2906,7 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface,
|
||||||
_cairo_ps_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
|
_cairo_ps_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
|
||||||
|
|
||||||
surface->current_pattern_is_solid_color = TRUE;
|
surface->current_pattern_is_solid_color = TRUE;
|
||||||
surface->current_color_red = solid->color.red;
|
surface->current_color = solid->color;
|
||||||
surface->current_color_green = solid->color.green;
|
|
||||||
surface->current_color_blue = solid->color.blue;
|
|
||||||
surface->current_color_alpha = solid->color.alpha;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
@ -3223,6 +3288,12 @@ _cairo_ps_surface_set_bounding_box (void *abstract_surface,
|
||||||
return _cairo_output_stream_get_status (surface->stream);
|
return _cairo_output_stream_get_status (surface->stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cairo_bool_t
|
||||||
|
_cairo_ps_surface_supports_fine_grained_fallbacks (void *abstract_surface)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static const cairo_surface_backend_t cairo_ps_surface_backend = {
|
static const cairo_surface_backend_t cairo_ps_surface_backend = {
|
||||||
CAIRO_SURFACE_TYPE_PS,
|
CAIRO_SURFACE_TYPE_PS,
|
||||||
_cairo_ps_surface_create_similar,
|
_cairo_ps_surface_create_similar,
|
||||||
|
@ -3261,4 +3332,6 @@ static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backen
|
||||||
_cairo_ps_surface_start_page,
|
_cairo_ps_surface_start_page,
|
||||||
_cairo_ps_surface_set_paginated_mode,
|
_cairo_ps_surface_set_paginated_mode,
|
||||||
_cairo_ps_surface_set_bounding_box,
|
_cairo_ps_surface_set_bounding_box,
|
||||||
|
NULL, /* _cairo_ps_surface_has_fallback_images, */
|
||||||
|
_cairo_ps_surface_supports_fine_grained_fallbacks,
|
||||||
};
|
};
|
||||||
|
|
|
@ -225,6 +225,7 @@ FINISH:
|
||||||
static const cairo_font_face_backend_t _cairo_quartz_font_face_backend = {
|
static const cairo_font_face_backend_t _cairo_quartz_font_face_backend = {
|
||||||
CAIRO_FONT_TYPE_QUARTZ,
|
CAIRO_FONT_TYPE_QUARTZ,
|
||||||
_cairo_quartz_font_face_destroy,
|
_cairo_quartz_font_face_destroy,
|
||||||
|
NULL, /* direct implementation */
|
||||||
_cairo_quartz_font_face_scaled_font_create
|
_cairo_quartz_font_face_scaled_font_create
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -277,24 +278,27 @@ _cairo_quartz_scaled_to_face (void *abstract_font)
|
||||||
}
|
}
|
||||||
|
|
||||||
static cairo_status_t
|
static cairo_status_t
|
||||||
_cairo_quartz_font_create_toy(cairo_toy_font_face_t *toy_face,
|
_cairo_quartz_font_get_implementation (cairo_toy_font_face_t *toy_face,
|
||||||
const cairo_matrix_t *font_matrix,
|
cairo_scaled_font_t **font_face_out)
|
||||||
const cairo_matrix_t *ctm,
|
|
||||||
const cairo_font_options_t *options,
|
|
||||||
cairo_scaled_font_t **font_out)
|
|
||||||
{
|
{
|
||||||
|
static cairo_user_data_key_t impl_font_face_key;
|
||||||
|
cairo_font_face_t *face;
|
||||||
|
cairo_status_t status;
|
||||||
const char *family = toy_face->family;
|
const char *family = toy_face->family;
|
||||||
char *full_name = malloc(strlen(family) + 64); // give us a bit of room to tack on Bold, Oblique, etc.
|
char *full_name = malloc(strlen(family) + 64); // give us a bit of room to tack on Bold, Oblique, etc.
|
||||||
CFStringRef cgFontName = NULL;
|
CFStringRef cgFontName = NULL;
|
||||||
CGFontRef cgFont = NULL;
|
CGFontRef cgFont = NULL;
|
||||||
int loop;
|
int loop;
|
||||||
|
|
||||||
cairo_status_t status;
|
face = cairo_font_face_get_user_data (&toy_face->base,
|
||||||
cairo_font_face_t *face;
|
&impl_font_face_key);
|
||||||
cairo_scaled_font_t *scaled_font;
|
if (face) {
|
||||||
|
*font_face_out = face;
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
quartz_font_ensure_symbols();
|
quartz_font_ensure_symbols();
|
||||||
if (!_cairo_quartz_font_symbols_present)
|
if (! _cairo_quartz_font_symbols_present)
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
|
|
||||||
/* handle CSS-ish faces */
|
/* handle CSS-ish faces */
|
||||||
|
@ -345,7 +349,7 @@ _cairo_quartz_font_create_toy(cairo_toy_font_face_t *toy_face,
|
||||||
|
|
||||||
if (!cgFont) {
|
if (!cgFont) {
|
||||||
/* Give up */
|
/* Give up */
|
||||||
return CAIRO_STATUS_NO_MEMORY;
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
face = cairo_quartz_font_face_create_for_cgfont (cgFont);
|
face = cairo_quartz_font_face_create_for_cgfont (cgFont);
|
||||||
|
@ -354,6 +358,35 @@ _cairo_quartz_font_create_toy(cairo_toy_font_face_t *toy_face,
|
||||||
if (face->status)
|
if (face->status)
|
||||||
return face->status;
|
return face->status;
|
||||||
|
|
||||||
|
status = cairo_font_face_set_user_data (&toy_face->base,
|
||||||
|
&impl_font_face_key,
|
||||||
|
face,
|
||||||
|
(cairo_destroy_func_t) cairo_font_face_destroy);
|
||||||
|
|
||||||
|
if (status) {
|
||||||
|
cairo_font_face_destroy (face);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
*font_face_out = face;
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cairo_status_t
|
||||||
|
_cairo_quartz_font_create_toy (cairo_toy_font_face_t *toy_face,
|
||||||
|
const cairo_matrix_t *font_matrix,
|
||||||
|
const cairo_matrix_t *ctm,
|
||||||
|
const cairo_font_options_t *options,
|
||||||
|
cairo_scaled_font_t **font_out)
|
||||||
|
{
|
||||||
|
cairo_font_face_t *face;
|
||||||
|
cairo_scaled_font_t *scaled_font;
|
||||||
|
cairo_status_t status;
|
||||||
|
|
||||||
|
status = _cairo_quartz_font_get_implementation (toy_face, &face);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
status = _cairo_quartz_font_face_scaled_font_create (face,
|
status = _cairo_quartz_font_face_scaled_font_create (face,
|
||||||
font_matrix, ctm,
|
font_matrix, ctm,
|
||||||
options,
|
options,
|
||||||
|
@ -363,7 +396,6 @@ _cairo_quartz_font_create_toy(cairo_toy_font_face_t *toy_face,
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
*font_out = scaled_font;
|
*font_out = scaled_font;
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -743,6 +775,7 @@ _cairo_quartz_ucs4_to_index (void *abstract_font,
|
||||||
|
|
||||||
const cairo_scaled_font_backend_t _cairo_quartz_scaled_font_backend = {
|
const cairo_scaled_font_backend_t _cairo_quartz_scaled_font_backend = {
|
||||||
CAIRO_FONT_TYPE_QUARTZ,
|
CAIRO_FONT_TYPE_QUARTZ,
|
||||||
|
_cairo_quartz_font_get_implementation,
|
||||||
_cairo_quartz_font_create_toy,
|
_cairo_quartz_font_create_toy,
|
||||||
_cairo_quartz_font_fini,
|
_cairo_quartz_font_fini,
|
||||||
_cairo_quartz_font_scaled_glyph_init,
|
_cairo_quartz_font_scaled_glyph_init,
|
||||||
|
|
|
@ -36,99 +36,13 @@
|
||||||
|
|
||||||
#include "cairoint.h"
|
#include "cairoint.h"
|
||||||
|
|
||||||
#ifdef CAIRO_HAS_QUARTZ_IMAGE_SURFACE
|
|
||||||
#include "cairo-quartz-image.h"
|
#include "cairo-quartz-image.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "cairo-quartz-private.h"
|
#include "cairo-quartz-private.h"
|
||||||
|
|
||||||
#define SURFACE_ERROR_NO_MEMORY (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY)))
|
#define SURFACE_ERROR_NO_MEMORY (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY)))
|
||||||
#define SURFACE_ERROR_TYPE_MISMATCH (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_SURFACE_TYPE_MISMATCH)))
|
#define SURFACE_ERROR_TYPE_MISMATCH (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_SURFACE_TYPE_MISMATCH)))
|
||||||
#define SURFACE_ERROR_INVALID_FORMAT (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_INVALID_FORMAT)))
|
#define SURFACE_ERROR_INVALID_FORMAT (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_INVALID_FORMAT)))
|
||||||
|
|
||||||
CGImageRef
|
|
||||||
_cairo_quartz_create_cgimage (cairo_format_t format,
|
|
||||||
unsigned int width,
|
|
||||||
unsigned int height,
|
|
||||||
unsigned int stride,
|
|
||||||
void *data,
|
|
||||||
cairo_bool_t interpolate,
|
|
||||||
CGColorSpaceRef colorSpaceOverride,
|
|
||||||
CGDataProviderReleaseDataCallback releaseCallback,
|
|
||||||
void *releaseInfo)
|
|
||||||
{
|
|
||||||
CGImageRef image = NULL;
|
|
||||||
CGDataProviderRef dataProvider = NULL;
|
|
||||||
CGColorSpaceRef colorSpace = colorSpaceOverride;
|
|
||||||
CGBitmapInfo bitinfo;
|
|
||||||
int bitsPerComponent, bitsPerPixel;
|
|
||||||
|
|
||||||
switch (format) {
|
|
||||||
case CAIRO_FORMAT_ARGB32:
|
|
||||||
if (colorSpace == NULL)
|
|
||||||
colorSpace = CGColorSpaceCreateDeviceRGB();
|
|
||||||
bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
|
|
||||||
bitsPerComponent = 8;
|
|
||||||
bitsPerPixel = 32;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CAIRO_FORMAT_RGB24:
|
|
||||||
if (colorSpace == NULL)
|
|
||||||
colorSpace = CGColorSpaceCreateDeviceRGB();
|
|
||||||
bitinfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
|
|
||||||
bitsPerComponent = 8;
|
|
||||||
bitsPerPixel = 32;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* XXX -- should use CGImageMaskCreate! */
|
|
||||||
case CAIRO_FORMAT_A8:
|
|
||||||
if (colorSpace == NULL)
|
|
||||||
colorSpace = CGColorSpaceCreateDeviceGray();
|
|
||||||
bitinfo = kCGImageAlphaNone;
|
|
||||||
bitsPerComponent = 8;
|
|
||||||
bitsPerPixel = 8;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CAIRO_FORMAT_A1:
|
|
||||||
default:
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
dataProvider = CGDataProviderCreateWithData (releaseInfo,
|
|
||||||
data,
|
|
||||||
height * stride,
|
|
||||||
releaseCallback);
|
|
||||||
|
|
||||||
if (!dataProvider) {
|
|
||||||
// manually release
|
|
||||||
if (releaseCallback)
|
|
||||||
releaseCallback (releaseInfo, data, height * stride);
|
|
||||||
goto FINISH;
|
|
||||||
}
|
|
||||||
|
|
||||||
image = CGImageCreate (width, height,
|
|
||||||
bitsPerComponent,
|
|
||||||
bitsPerPixel,
|
|
||||||
stride,
|
|
||||||
colorSpace,
|
|
||||||
bitinfo,
|
|
||||||
dataProvider,
|
|
||||||
NULL,
|
|
||||||
interpolate,
|
|
||||||
kCGRenderingIntentDefault);
|
|
||||||
|
|
||||||
FINISH:
|
|
||||||
|
|
||||||
CGDataProviderRelease (dataProvider);
|
|
||||||
|
|
||||||
if (colorSpace != colorSpaceOverride)
|
|
||||||
CGColorSpaceRelease (colorSpace);
|
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CAIRO_HAS_QUARTZ_IMAGE_SURFACE
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DataProviderReleaseCallback (void *info, const void *data, size_t size)
|
DataProviderReleaseCallback (void *info, const void *data, size_t size)
|
||||||
{
|
{
|
||||||
|
@ -370,5 +284,3 @@ cairo_quartz_image_surface_get_image (cairo_surface_t *asurface)
|
||||||
|
|
||||||
return (cairo_surface_t*) surface->imageSurface;
|
return (cairo_surface_t*) surface->imageSurface;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CAIRO_HAS_QUARTZ_IMAGE_SURFACE */
|
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
|
|
||||||
#include "cairoint.h"
|
#include "cairoint.h"
|
||||||
|
|
||||||
#ifdef CAIRO_HAS_QUARTZ_SURFACE
|
#if CAIRO_HAS_QUARTZ_SURFACE
|
||||||
#include "cairo-quartz.h"
|
#include "cairo-quartz.h"
|
||||||
|
|
||||||
typedef struct cairo_quartz_surface {
|
typedef struct cairo_quartz_surface {
|
||||||
|
@ -95,11 +95,10 @@ _cairo_quartz_create_cgimage (cairo_format_t format,
|
||||||
CGFontRef
|
CGFontRef
|
||||||
_cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *sfont);
|
_cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *sfont);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
# error Cairo was not compiled with support for the quartz backend
|
||||||
|
|
||||||
#endif /* CAIRO_HAS_QUARTZ_SURFACE */
|
#endif /* CAIRO_HAS_QUARTZ_SURFACE */
|
||||||
|
|
||||||
#if CAIRO_HAS_CGFONT_FONT
|
|
||||||
CGFontRef
|
|
||||||
_cairo_cgfont_scaled_font_get_cg_font_ref (cairo_scaled_font_t *sfont);
|
|
||||||
#endif /* CAIRO_HAS_CGFONT_FONT */
|
|
||||||
|
|
||||||
#endif /* CAIRO_QUARTZ_PRIVATE_H */
|
#endif /* CAIRO_QUARTZ_PRIVATE_H */
|
||||||
|
|
|
@ -160,6 +160,87 @@ static void quartz_ensure_symbols(void)
|
||||||
_cairo_quartz_symbol_lookup_done = TRUE;
|
_cairo_quartz_symbol_lookup_done = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CGImageRef
|
||||||
|
_cairo_quartz_create_cgimage (cairo_format_t format,
|
||||||
|
unsigned int width,
|
||||||
|
unsigned int height,
|
||||||
|
unsigned int stride,
|
||||||
|
void *data,
|
||||||
|
cairo_bool_t interpolate,
|
||||||
|
CGColorSpaceRef colorSpaceOverride,
|
||||||
|
CGDataProviderReleaseDataCallback releaseCallback,
|
||||||
|
void *releaseInfo)
|
||||||
|
{
|
||||||
|
CGImageRef image = NULL;
|
||||||
|
CGDataProviderRef dataProvider = NULL;
|
||||||
|
CGColorSpaceRef colorSpace = colorSpaceOverride;
|
||||||
|
CGBitmapInfo bitinfo;
|
||||||
|
int bitsPerComponent, bitsPerPixel;
|
||||||
|
|
||||||
|
switch (format) {
|
||||||
|
case CAIRO_FORMAT_ARGB32:
|
||||||
|
if (colorSpace == NULL)
|
||||||
|
colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||||
|
bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
|
||||||
|
bitsPerComponent = 8;
|
||||||
|
bitsPerPixel = 32;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CAIRO_FORMAT_RGB24:
|
||||||
|
if (colorSpace == NULL)
|
||||||
|
colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||||
|
bitinfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
|
||||||
|
bitsPerComponent = 8;
|
||||||
|
bitsPerPixel = 32;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* XXX -- should use CGImageMaskCreate! */
|
||||||
|
case CAIRO_FORMAT_A8:
|
||||||
|
if (colorSpace == NULL)
|
||||||
|
colorSpace = CGColorSpaceCreateDeviceGray();
|
||||||
|
bitinfo = kCGImageAlphaNone;
|
||||||
|
bitsPerComponent = 8;
|
||||||
|
bitsPerPixel = 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CAIRO_FORMAT_A1:
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dataProvider = CGDataProviderCreateWithData (releaseInfo,
|
||||||
|
data,
|
||||||
|
height * stride,
|
||||||
|
releaseCallback);
|
||||||
|
|
||||||
|
if (!dataProvider) {
|
||||||
|
// manually release
|
||||||
|
if (releaseCallback)
|
||||||
|
releaseCallback (releaseInfo, data, height * stride);
|
||||||
|
goto FINISH;
|
||||||
|
}
|
||||||
|
|
||||||
|
image = CGImageCreate (width, height,
|
||||||
|
bitsPerComponent,
|
||||||
|
bitsPerPixel,
|
||||||
|
stride,
|
||||||
|
colorSpace,
|
||||||
|
bitinfo,
|
||||||
|
dataProvider,
|
||||||
|
NULL,
|
||||||
|
interpolate,
|
||||||
|
kCGRenderingIntentDefault);
|
||||||
|
|
||||||
|
FINISH:
|
||||||
|
|
||||||
|
CGDataProviderRelease (dataProvider);
|
||||||
|
|
||||||
|
if (colorSpace != colorSpaceOverride)
|
||||||
|
CGColorSpaceRelease (colorSpace);
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
static inline cairo_bool_t
|
static inline cairo_bool_t
|
||||||
_cairo_quartz_is_cgcontext_bitmap_context (CGContextRef cgc) {
|
_cairo_quartz_is_cgcontext_bitmap_context (CGContextRef cgc) {
|
||||||
if (cgc == NULL)
|
if (cgc == NULL)
|
||||||
|
@ -745,10 +826,13 @@ _cairo_surface_to_cgimage (cairo_surface_t *target,
|
||||||
*image_out = NULL;
|
*image_out = NULL;
|
||||||
} else {
|
} else {
|
||||||
cairo_image_surface_t *isurf_snap = NULL;
|
cairo_image_surface_t *isurf_snap = NULL;
|
||||||
isurf_snap = _cairo_surface_snapshot (isurf);
|
isurf_snap = (cairo_image_surface_t*) _cairo_surface_snapshot ((cairo_surface_t*) isurf);
|
||||||
if (isurf_snap == NULL)
|
if (isurf_snap == NULL)
|
||||||
return CAIRO_STATUS_NO_MEMORY;
|
return CAIRO_STATUS_NO_MEMORY;
|
||||||
|
|
||||||
|
if (isurf_snap->base.type != CAIRO_SURFACE_TYPE_IMAGE)
|
||||||
|
return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
|
||||||
|
|
||||||
image = _cairo_quartz_create_cgimage (isurf_snap->format,
|
image = _cairo_quartz_create_cgimage (isurf_snap->format,
|
||||||
isurf_snap->width,
|
isurf_snap->width,
|
||||||
isurf_snap->height,
|
isurf_snap->height,
|
||||||
|
@ -1481,8 +1565,8 @@ _cairo_quartz_surface_create_similar (void *abstract_surface,
|
||||||
|
|
||||||
// verify width and height of surface
|
// verify width and height of surface
|
||||||
if (!_cairo_quartz_verify_surface_size(width, height)) {
|
if (!_cairo_quartz_verify_surface_size(width, height)) {
|
||||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
return _cairo_surface_create_in_error (_cairo_error
|
||||||
return NULL;
|
(CAIRO_STATUS_NO_MEMORY));
|
||||||
}
|
}
|
||||||
|
|
||||||
return cairo_quartz_surface_create (format, width, height);
|
return cairo_quartz_surface_create (format, width, height);
|
||||||
|
@ -1495,6 +1579,8 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface,
|
||||||
int src_y,
|
int src_y,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
|
int *clone_offset_x,
|
||||||
|
int *clone_offset_y,
|
||||||
cairo_surface_t **clone_out)
|
cairo_surface_t **clone_out)
|
||||||
{
|
{
|
||||||
cairo_quartz_surface_t *new_surface = NULL;
|
cairo_quartz_surface_t *new_surface = NULL;
|
||||||
|
@ -1513,6 +1599,8 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface,
|
||||||
*clone_out = (cairo_surface_t*)
|
*clone_out = (cairo_surface_t*)
|
||||||
_cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA,
|
_cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA,
|
||||||
width, height);
|
width, height);
|
||||||
|
*clone_offset_x = 0;
|
||||||
|
*clone_offset_y = 0;
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1523,6 +1611,8 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface,
|
||||||
*clone_out = (cairo_surface_t*)
|
*clone_out = (cairo_surface_t*)
|
||||||
_cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA,
|
_cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA,
|
||||||
qsurf->extents.width, qsurf->extents.height);
|
qsurf->extents.width, qsurf->extents.height);
|
||||||
|
*clone_offset_x = 0;
|
||||||
|
*clone_offset_y = 0;
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1561,7 +1651,9 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface,
|
||||||
|
|
||||||
CGImageRelease (quartz_image);
|
CGImageRelease (quartz_image);
|
||||||
|
|
||||||
FINISH:
|
FINISH:
|
||||||
|
*clone_offset_x = src_x;
|
||||||
|
*clone_offset_y = src_y;
|
||||||
*clone_out = (cairo_surface_t*) new_surface;
|
*clone_out = (cairo_surface_t*) new_surface;
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
|
|
@ -57,12 +57,12 @@ cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext,
|
||||||
cairo_public CGContextRef
|
cairo_public CGContextRef
|
||||||
cairo_quartz_surface_get_cg_context (cairo_surface_t *surface);
|
cairo_quartz_surface_get_cg_context (cairo_surface_t *surface);
|
||||||
|
|
||||||
|
#if CAIRO_HAS_QUARTZ_FONT
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Quartz font support
|
* Quartz font support
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef CAIRO_HAS_QUARTZ_FONT
|
|
||||||
|
|
||||||
cairo_public cairo_font_face_t *
|
cairo_public cairo_font_face_t *
|
||||||
cairo_quartz_font_face_create_for_cgfont (CGFontRef font);
|
cairo_quartz_font_face_create_for_cgfont (CGFontRef font);
|
||||||
|
|
||||||
|
|
|
@ -37,14 +37,8 @@
|
||||||
#ifndef CAIRO_REFRENCE_COUNT_PRIVATE_H
|
#ifndef CAIRO_REFRENCE_COUNT_PRIVATE_H
|
||||||
#define CAIRO_REFRENCE_COUNT_PRIVATE_H
|
#define CAIRO_REFRENCE_COUNT_PRIVATE_H
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "cairo-atomic-private.h"
|
#include "cairo-atomic-private.h"
|
||||||
|
|
||||||
CAIRO_BEGIN_DECLS
|
|
||||||
|
|
||||||
/* Encapsulate operations on the object's reference count */
|
/* Encapsulate operations on the object's reference count */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
cairo_atomic_int_t ref_count;
|
cairo_atomic_int_t ref_count;
|
||||||
|
@ -65,6 +59,4 @@ typedef struct {
|
||||||
|
|
||||||
#define CAIRO_REFERENCE_COUNT_HAS_REFERENCE(RC) (CAIRO_REFERENCE_COUNT_GET_VALUE (RC) > 0)
|
#define CAIRO_REFERENCE_COUNT_HAS_REFERENCE(RC) (CAIRO_REFERENCE_COUNT_GET_VALUE (RC) > 0)
|
||||||
|
|
||||||
CAIRO_END_DECLS
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -37,11 +37,13 @@
|
||||||
#ifndef CAIRO_REGION_PRIVATE_H
|
#ifndef CAIRO_REGION_PRIVATE_H
|
||||||
#define CAIRO_REGION_PRIVATE_H
|
#define CAIRO_REGION_PRIVATE_H
|
||||||
|
|
||||||
#include <pixman.h>
|
|
||||||
|
|
||||||
#include "cairo-compiler-private.h"
|
#include "cairo-compiler-private.h"
|
||||||
#include "cairo-types-private.h"
|
#include "cairo-types-private.h"
|
||||||
|
|
||||||
|
#include <pixman.h>
|
||||||
|
|
||||||
|
CAIRO_BEGIN_DECLS
|
||||||
|
|
||||||
/* #cairo_region_t is defined in cairoint.h */
|
/* #cairo_region_t is defined in cairoint.h */
|
||||||
|
|
||||||
struct _cairo_region {
|
struct _cairo_region {
|
||||||
|
@ -109,4 +111,6 @@ cairo_private pixman_region_overlap_t
|
||||||
_cairo_region_contains_rectangle (cairo_region_t *region, cairo_rectangle_int_t *box);
|
_cairo_region_contains_rectangle (cairo_region_t *region, cairo_rectangle_int_t *box);
|
||||||
|
|
||||||
|
|
||||||
|
CAIRO_END_DECLS
|
||||||
|
|
||||||
#endif /* CAIRO_REGION_PRIVATE_H */
|
#endif /* CAIRO_REGION_PRIVATE_H */
|
||||||
|
|
|
@ -281,6 +281,41 @@ _cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t
|
||||||
cairo_scaled_font_subset_callback_func_t font_subset_callback,
|
cairo_scaled_font_subset_callback_func_t font_subset_callback,
|
||||||
void *closure);
|
void *closure);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _cairo_scaled_font_subsets_foreach_user:
|
||||||
|
* @font_subsets: a #cairo_scaled_font_subsets_t
|
||||||
|
* @font_subset_callback: a function to be called for each font subset
|
||||||
|
* @closure: closure data for the callback function
|
||||||
|
*
|
||||||
|
* Iterate over each unique scaled font subset as created by calls to
|
||||||
|
* _cairo_scaled_font_subsets_map_glyph(). A subset is determined by
|
||||||
|
* unique pairs of (font_id, subset_id) as returned by
|
||||||
|
* _cairo_scaled_font_subsets_map_glyph().
|
||||||
|
*
|
||||||
|
* For each subset, @font_subset_callback will be called and will be
|
||||||
|
* provided with both a #cairo_scaled_font_subset_t object containing
|
||||||
|
* all the glyphs in the subset as well as the value of @closure.
|
||||||
|
*
|
||||||
|
* The #cairo_scaled_font_subset_t object contains the scaled_font,
|
||||||
|
* the font_id, and the subset_id corresponding to all glyphs
|
||||||
|
* belonging to the subset. In addition, it contains an array providing
|
||||||
|
* a mapping between subset glyph indices and the original scaled font
|
||||||
|
* glyph indices.
|
||||||
|
*
|
||||||
|
* The index of the array corresponds to subset_glyph_index values
|
||||||
|
* returned by _cairo_scaled_font_subsets_map_glyph() while the
|
||||||
|
* values of the array correspond to the scaled_font_glyph_index
|
||||||
|
* values passed as input to the same function.
|
||||||
|
*
|
||||||
|
* Return value: %CAIRO_STATUS_SUCCESS if successful, or a non-zero
|
||||||
|
* value indicating an error. Possible errors include
|
||||||
|
* %CAIRO_STATUS_NO_MEMORY.
|
||||||
|
**/
|
||||||
|
cairo_private cairo_status_t
|
||||||
|
_cairo_scaled_font_subsets_foreach_user (cairo_scaled_font_subsets_t *font_subsets,
|
||||||
|
cairo_scaled_font_subset_callback_func_t font_subset_callback,
|
||||||
|
void *closure);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _cairo_scaled_font_subset_create_glyph_names:
|
* _cairo_scaled_font_subset_create_glyph_names:
|
||||||
* @font_subsets: a #cairo_scaled_font_subsets_t
|
* @font_subsets: a #cairo_scaled_font_subsets_t
|
||||||
|
|
|
@ -57,11 +57,18 @@ typedef enum {
|
||||||
CAIRO_SUBSETS_COMPOSITE
|
CAIRO_SUBSETS_COMPOSITE
|
||||||
} cairo_subsets_type_t;
|
} cairo_subsets_type_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CAIRO_SUBSETS_FOREACH_UNSCALED,
|
||||||
|
CAIRO_SUBSETS_FOREACH_SCALED,
|
||||||
|
CAIRO_SUBSETS_FOREACH_USER
|
||||||
|
} cairo_subsets_foreach_type_t;
|
||||||
|
|
||||||
typedef struct _cairo_sub_font {
|
typedef struct _cairo_sub_font {
|
||||||
cairo_hash_entry_t base;
|
cairo_hash_entry_t base;
|
||||||
|
|
||||||
cairo_bool_t is_scaled;
|
cairo_bool_t is_scaled;
|
||||||
cairo_bool_t is_composite;
|
cairo_bool_t is_composite;
|
||||||
|
cairo_bool_t is_user;
|
||||||
cairo_scaled_font_subsets_t *parent;
|
cairo_scaled_font_subsets_t *parent;
|
||||||
cairo_scaled_font_t *scaled_font;
|
cairo_scaled_font_t *scaled_font;
|
||||||
unsigned int font_id;
|
unsigned int font_id;
|
||||||
|
@ -126,7 +133,7 @@ typedef struct _cairo_string_entry {
|
||||||
static cairo_status_t
|
static cairo_status_t
|
||||||
_cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
|
_cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
|
||||||
unsigned long scaled_font_glyph_index,
|
unsigned long scaled_font_glyph_index,
|
||||||
const char * utf8,
|
const char * utf8,
|
||||||
int utf8_len,
|
int utf8_len,
|
||||||
cairo_scaled_font_subsets_glyph_t *subset_glyph);
|
cairo_scaled_font_subsets_glyph_t *subset_glyph);
|
||||||
|
|
||||||
|
@ -265,6 +272,7 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
|
||||||
|
|
||||||
sub_font->is_scaled = is_scaled;
|
sub_font->is_scaled = is_scaled;
|
||||||
sub_font->is_composite = is_composite;
|
sub_font->is_composite = is_composite;
|
||||||
|
sub_font->is_user = _cairo_font_face_is_user (scaled_font->font_face);
|
||||||
_cairo_sub_font_init_key (sub_font, scaled_font);
|
_cairo_sub_font_init_key (sub_font, scaled_font);
|
||||||
|
|
||||||
sub_font->parent = parent;
|
sub_font->parent = parent;
|
||||||
|
@ -282,12 +290,15 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
|
||||||
}
|
}
|
||||||
sub_font->next = NULL;
|
sub_font->next = NULL;
|
||||||
|
|
||||||
/* Reserve first glyph in subset for the .notdef glyph */
|
/* Reserve first glyph in subset for the .notdef glyph except for
|
||||||
status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &subset_glyph);
|
* Type 3 fonts */
|
||||||
if (status) {
|
if (! _cairo_font_face_is_user (scaled_font->font_face)) {
|
||||||
_cairo_hash_table_destroy (sub_font->sub_font_glyphs);
|
status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &subset_glyph);
|
||||||
free (sub_font);
|
if (status) {
|
||||||
return status;
|
_cairo_hash_table_destroy (sub_font->sub_font_glyphs);
|
||||||
|
free (sub_font);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*sub_font_out = sub_font;
|
*sub_font_out = sub_font;
|
||||||
|
@ -437,12 +448,13 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
|
||||||
{
|
{
|
||||||
cairo_sub_font_glyph_t key, *sub_font_glyph;
|
cairo_sub_font_glyph_t key, *sub_font_glyph;
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
cairo_scaled_glyph_t *scaled_glyph;
|
|
||||||
|
|
||||||
_cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index);
|
_cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index);
|
||||||
if (! _cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base,
|
if (! _cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base,
|
||||||
(cairo_hash_entry_t **) &sub_font_glyph))
|
(cairo_hash_entry_t **) &sub_font_glyph))
|
||||||
{
|
{
|
||||||
|
cairo_scaled_glyph_t *scaled_glyph;
|
||||||
|
|
||||||
if (sub_font->num_glyphs_in_current_subset == sub_font->max_glyphs_per_subset)
|
if (sub_font->num_glyphs_in_current_subset == sub_font->max_glyphs_per_subset)
|
||||||
{
|
{
|
||||||
cairo_scaled_font_subsets_glyph_t tmp_subset_glyph;
|
cairo_scaled_font_subsets_glyph_t tmp_subset_glyph;
|
||||||
|
@ -450,25 +462,33 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
|
||||||
sub_font->current_subset++;
|
sub_font->current_subset++;
|
||||||
sub_font->num_glyphs_in_current_subset = 0;
|
sub_font->num_glyphs_in_current_subset = 0;
|
||||||
|
|
||||||
/* Reserve first glyph in subset for the .notdef glyph */
|
/* Reserve first glyph in subset for the .notdef glyph
|
||||||
status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &tmp_subset_glyph);
|
* except for Type 3 fonts */
|
||||||
if (status)
|
if (! _cairo_font_face_is_user (sub_font->scaled_font->font_face)) {
|
||||||
return status;
|
status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &tmp_subset_glyph);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cairo_scaled_font_freeze_cache (sub_font->scaled_font);
|
||||||
status = _cairo_scaled_glyph_lookup (sub_font->scaled_font,
|
status = _cairo_scaled_glyph_lookup (sub_font->scaled_font,
|
||||||
scaled_font_glyph_index,
|
scaled_font_glyph_index,
|
||||||
CAIRO_SCALED_GLYPH_INFO_METRICS,
|
CAIRO_SCALED_GLYPH_INFO_METRICS,
|
||||||
&scaled_glyph);
|
&scaled_glyph);
|
||||||
assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
|
assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
|
||||||
if (status)
|
if (status) {
|
||||||
|
_cairo_scaled_font_thaw_cache (sub_font->scaled_font);
|
||||||
return status;
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index,
|
sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index,
|
||||||
sub_font->current_subset,
|
sub_font->current_subset,
|
||||||
sub_font->num_glyphs_in_current_subset,
|
sub_font->num_glyphs_in_current_subset,
|
||||||
scaled_glyph->metrics.x_advance,
|
scaled_glyph->metrics.x_advance,
|
||||||
scaled_glyph->metrics.y_advance);
|
scaled_glyph->metrics.y_advance);
|
||||||
|
_cairo_scaled_font_thaw_cache (sub_font->scaled_font);
|
||||||
|
|
||||||
if (sub_font_glyph == NULL)
|
if (sub_font_glyph == NULL)
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
|
|
||||||
|
@ -641,7 +661,7 @@ cairo_status_t
|
||||||
_cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
|
_cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
|
||||||
cairo_scaled_font_t *scaled_font,
|
cairo_scaled_font_t *scaled_font,
|
||||||
unsigned long scaled_font_glyph_index,
|
unsigned long scaled_font_glyph_index,
|
||||||
const char * utf8,
|
const char * utf8,
|
||||||
int utf8_len,
|
int utf8_len,
|
||||||
cairo_scaled_font_subsets_glyph_t *subset_glyph)
|
cairo_scaled_font_subsets_glyph_t *subset_glyph)
|
||||||
{
|
{
|
||||||
|
@ -691,13 +711,16 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
|
||||||
* _scaled_glyph_lookup(_GLYPH_INFO_PATH). Type1-fallback creates
|
* _scaled_glyph_lookup(_GLYPH_INFO_PATH). Type1-fallback creates
|
||||||
* empty glyphs in this case so we can put the glyph in a unscaled
|
* empty glyphs in this case so we can put the glyph in a unscaled
|
||||||
* subset. */
|
* subset. */
|
||||||
if (scaled_font_glyph_index == 0) {
|
if (scaled_font_glyph_index == 0 ||
|
||||||
|
_cairo_font_face_is_user (scaled_font->font_face)) {
|
||||||
status = CAIRO_STATUS_SUCCESS;
|
status = CAIRO_STATUS_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
|
_cairo_scaled_font_freeze_cache (scaled_font);
|
||||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||||
scaled_font_glyph_index,
|
scaled_font_glyph_index,
|
||||||
CAIRO_SCALED_GLYPH_INFO_PATH,
|
CAIRO_SCALED_GLYPH_INFO_PATH,
|
||||||
&scaled_glyph);
|
&scaled_glyph);
|
||||||
|
_cairo_scaled_font_thaw_cache (scaled_font);
|
||||||
}
|
}
|
||||||
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
|
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||||
return status;
|
return status;
|
||||||
|
@ -744,6 +767,7 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
|
||||||
subset_glyph->is_scaled,
|
subset_glyph->is_scaled,
|
||||||
subset_glyph->is_composite,
|
subset_glyph->is_composite,
|
||||||
&sub_font);
|
&sub_font);
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
cairo_scaled_font_destroy (unscaled_font);
|
cairo_scaled_font_destroy (unscaled_font);
|
||||||
return status;
|
return status;
|
||||||
|
@ -805,19 +829,32 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
|
||||||
}
|
}
|
||||||
|
|
||||||
return _cairo_sub_font_map_glyph (sub_font,
|
return _cairo_sub_font_map_glyph (sub_font,
|
||||||
scaled_font_glyph_index,
|
scaled_font_glyph_index,
|
||||||
utf8, utf8_len,
|
utf8, utf8_len,
|
||||||
subset_glyph);
|
subset_glyph);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cairo_status_t
|
static cairo_status_t
|
||||||
_cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t *font_subsets,
|
_cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t *font_subsets,
|
||||||
cairo_scaled_font_subset_callback_func_t font_subset_callback,
|
cairo_scaled_font_subset_callback_func_t font_subset_callback,
|
||||||
void *closure,
|
void *closure,
|
||||||
cairo_bool_t is_scaled)
|
cairo_subsets_foreach_type_t type)
|
||||||
{
|
{
|
||||||
cairo_sub_font_collection_t collection;
|
cairo_sub_font_collection_t collection;
|
||||||
cairo_sub_font_t *sub_font;
|
cairo_sub_font_t *sub_font;
|
||||||
|
cairo_bool_t is_scaled, is_user;
|
||||||
|
|
||||||
|
is_scaled = FALSE;
|
||||||
|
is_user = FALSE;
|
||||||
|
|
||||||
|
if (type == CAIRO_SUBSETS_FOREACH_USER)
|
||||||
|
is_user = TRUE;
|
||||||
|
|
||||||
|
if (type == CAIRO_SUBSETS_FOREACH_SCALED ||
|
||||||
|
type == CAIRO_SUBSETS_FOREACH_USER)
|
||||||
|
{
|
||||||
|
is_scaled = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_scaled)
|
if (is_scaled)
|
||||||
collection.glyphs_size = font_subsets->max_glyphs_per_scaled_subset_used;
|
collection.glyphs_size = font_subsets->max_glyphs_per_scaled_subset_used;
|
||||||
|
@ -848,7 +885,9 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t
|
||||||
sub_font = font_subsets->unscaled_sub_fonts_list;
|
sub_font = font_subsets->unscaled_sub_fonts_list;
|
||||||
|
|
||||||
while (sub_font) {
|
while (sub_font) {
|
||||||
_cairo_sub_font_collect (sub_font, &collection);
|
if (sub_font->is_user == is_user)
|
||||||
|
_cairo_sub_font_collect (sub_font, &collection);
|
||||||
|
|
||||||
sub_font = sub_font->next;
|
sub_font = sub_font->next;
|
||||||
}
|
}
|
||||||
free (collection.utf8);
|
free (collection.utf8);
|
||||||
|
@ -865,7 +904,7 @@ _cairo_scaled_font_subsets_foreach_scaled (cairo_scaled_font_subsets_t *fon
|
||||||
return _cairo_scaled_font_subsets_foreach_internal (font_subsets,
|
return _cairo_scaled_font_subsets_foreach_internal (font_subsets,
|
||||||
font_subset_callback,
|
font_subset_callback,
|
||||||
closure,
|
closure,
|
||||||
TRUE);
|
CAIRO_SUBSETS_FOREACH_SCALED);
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_status_t
|
cairo_status_t
|
||||||
|
@ -876,7 +915,18 @@ _cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t *fo
|
||||||
return _cairo_scaled_font_subsets_foreach_internal (font_subsets,
|
return _cairo_scaled_font_subsets_foreach_internal (font_subsets,
|
||||||
font_subset_callback,
|
font_subset_callback,
|
||||||
closure,
|
closure,
|
||||||
FALSE);
|
CAIRO_SUBSETS_FOREACH_UNSCALED);
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_status_t
|
||||||
|
_cairo_scaled_font_subsets_foreach_user (cairo_scaled_font_subsets_t *font_subsets,
|
||||||
|
cairo_scaled_font_subset_callback_func_t font_subset_callback,
|
||||||
|
void *closure)
|
||||||
|
{
|
||||||
|
return _cairo_scaled_font_subsets_foreach_internal (font_subsets,
|
||||||
|
font_subset_callback,
|
||||||
|
closure,
|
||||||
|
CAIRO_SUBSETS_FOREACH_USER);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cairo_bool_t
|
static cairo_bool_t
|
||||||
|
@ -937,23 +987,27 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset
|
||||||
goto CLEANUP_HASH;
|
goto CLEANUP_HASH;
|
||||||
}
|
}
|
||||||
|
|
||||||
subset->glyph_names[0] = strdup (".notdef");
|
i = 0;
|
||||||
if (subset->glyph_names[0] == NULL) {
|
if (! _cairo_font_face_is_user (subset->scaled_font->font_face)) {
|
||||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
subset->glyph_names[0] = strdup (".notdef");
|
||||||
goto CLEANUP_HASH;
|
if (subset->glyph_names[0] == NULL) {
|
||||||
|
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
|
goto CLEANUP_HASH;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = create_string_entry (subset->glyph_names[0], &entry);
|
||||||
|
if (status)
|
||||||
|
goto CLEANUP_HASH;
|
||||||
|
|
||||||
|
status = _cairo_hash_table_insert (names, &entry->base);
|
||||||
|
if (status) {
|
||||||
|
free (entry);
|
||||||
|
goto CLEANUP_HASH;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = create_string_entry (subset->glyph_names[0], &entry);
|
for (; i < subset->num_glyphs; i++) {
|
||||||
if (status)
|
|
||||||
goto CLEANUP_HASH;
|
|
||||||
|
|
||||||
status = _cairo_hash_table_insert (names, &entry->base);
|
|
||||||
if (status) {
|
|
||||||
free (entry);
|
|
||||||
goto CLEANUP_HASH;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 1; i < subset->num_glyphs; i++) {
|
|
||||||
utf8 = subset->utf8[i];
|
utf8 = subset->utf8[i];
|
||||||
utf16 = NULL;
|
utf16 = NULL;
|
||||||
utf16_len = 0;
|
utf16_len = 0;
|
||||||
|
|
|
@ -145,6 +145,9 @@
|
||||||
* and note that glyph origin = device-space origin.
|
* and note that glyph origin = device-space origin.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cairo_scaled_font_fini_internal (cairo_scaled_font_t *scaled_font);
|
||||||
|
|
||||||
static cairo_bool_t
|
static cairo_bool_t
|
||||||
_cairo_scaled_glyph_keys_equal (const void *abstract_key_a, const void *abstract_key_b)
|
_cairo_scaled_glyph_keys_equal (const void *abstract_key_a, const void *abstract_key_b)
|
||||||
{
|
{
|
||||||
|
@ -377,11 +380,11 @@ _cairo_scaled_font_map_destroy (void)
|
||||||
|
|
||||||
font_map->num_holdovers--;
|
font_map->num_holdovers--;
|
||||||
|
|
||||||
/* release the lock to avoid the possibility of a recursive
|
/* This releases the font_map lock to avoid the possibility of a
|
||||||
* deadlock when the scaled font destroy closure gets called */
|
* recursive deadlock when the scaled font destroy closure gets
|
||||||
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
|
* called
|
||||||
|
*/
|
||||||
_cairo_scaled_font_fini (scaled_font);
|
_cairo_scaled_font_fini (scaled_font);
|
||||||
CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
|
|
||||||
|
|
||||||
free (scaled_font);
|
free (scaled_font);
|
||||||
}
|
}
|
||||||
|
@ -407,22 +410,26 @@ _cairo_scaled_font_map_destroy (void)
|
||||||
*
|
*
|
||||||
* The reason we have to create a fake scaled font instead of just using
|
* The reason we have to create a fake scaled font instead of just using
|
||||||
* scaled_font is for lifecycle management: we need to (or rather,
|
* scaled_font is for lifecycle management: we need to (or rather,
|
||||||
* other code needs to) reference the scaked_font in the hash.
|
* other code needs to) reference the scaled_font in the hash table.
|
||||||
* We can't do that on the input scaled_font as it may be freed by
|
* We can't do that on the input scaled_font as it may be freed by
|
||||||
* font backend upon error.
|
* font backend upon error.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
cairo_status_t
|
||||||
_cairo_scaled_font_register_placeholder_and_unlock_font_map (cairo_scaled_font_t *scaled_font)
|
_cairo_scaled_font_register_placeholder_and_unlock_font_map (cairo_scaled_font_t *scaled_font)
|
||||||
{
|
{
|
||||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
cairo_status_t status;
|
||||||
cairo_scaled_font_t *placeholder_scaled_font;
|
cairo_scaled_font_t *placeholder_scaled_font;
|
||||||
|
|
||||||
|
assert (CAIRO_MUTEX_IS_LOCKED (_cairo_scaled_font_map_mutex));
|
||||||
|
|
||||||
|
status = scaled_font->status;
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
placeholder_scaled_font = malloc (sizeof (cairo_scaled_font_t));
|
placeholder_scaled_font = malloc (sizeof (cairo_scaled_font_t));
|
||||||
if (!placeholder_scaled_font) {
|
if (placeholder_scaled_font == NULL)
|
||||||
status = CAIRO_STATUS_NO_MEMORY;
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
goto FREE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* full initialization is wasteful, but who cares... */
|
/* full initialization is wasteful, but who cares... */
|
||||||
status = _cairo_scaled_font_init (placeholder_scaled_font,
|
status = _cairo_scaled_font_init (placeholder_scaled_font,
|
||||||
|
@ -432,32 +439,26 @@ _cairo_scaled_font_register_placeholder_and_unlock_font_map (cairo_scaled_font_t
|
||||||
&scaled_font->options,
|
&scaled_font->options,
|
||||||
NULL);
|
NULL);
|
||||||
if (status)
|
if (status)
|
||||||
goto FINI;
|
goto FREE_PLACEHOLDER;
|
||||||
|
|
||||||
placeholder_scaled_font->placeholder = TRUE;
|
placeholder_scaled_font->placeholder = TRUE;
|
||||||
|
|
||||||
CAIRO_MUTEX_LOCK (placeholder_scaled_font->mutex);
|
|
||||||
|
|
||||||
status = _cairo_hash_table_insert (cairo_scaled_font_map->hash_table,
|
status = _cairo_hash_table_insert (cairo_scaled_font_map->hash_table,
|
||||||
&placeholder_scaled_font->hash_entry);
|
&placeholder_scaled_font->hash_entry);
|
||||||
if (status)
|
if (status)
|
||||||
goto UNLOCK_KEY;
|
goto FINI_PLACEHOLDER;
|
||||||
|
|
||||||
goto UNLOCK;
|
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
|
||||||
|
CAIRO_MUTEX_LOCK (placeholder_scaled_font->mutex);
|
||||||
|
|
||||||
UNLOCK_KEY:
|
return CAIRO_STATUS_SUCCESS;
|
||||||
CAIRO_MUTEX_UNLOCK (placeholder_scaled_font->mutex);
|
|
||||||
|
|
||||||
FINI:
|
FINI_PLACEHOLDER:
|
||||||
_cairo_scaled_font_fini (placeholder_scaled_font);
|
_cairo_scaled_font_fini_internal (placeholder_scaled_font);
|
||||||
|
FREE_PLACEHOLDER:
|
||||||
FREE:
|
|
||||||
free (placeholder_scaled_font);
|
free (placeholder_scaled_font);
|
||||||
|
|
||||||
status = _cairo_scaled_font_set_error (scaled_font, status);
|
return _cairo_scaled_font_set_error (scaled_font, status);
|
||||||
|
|
||||||
UNLOCK:
|
|
||||||
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -473,33 +474,36 @@ _cairo_scaled_font_unregister_placeholder_and_lock_font_map (cairo_scaled_font_t
|
||||||
(cairo_hash_entry_t**) &placeholder_scaled_font);
|
(cairo_hash_entry_t**) &placeholder_scaled_font);
|
||||||
assert (found);
|
assert (found);
|
||||||
assert (placeholder_scaled_font->placeholder);
|
assert (placeholder_scaled_font->placeholder);
|
||||||
|
assert (CAIRO_MUTEX_IS_LOCKED (placeholder_scaled_font->mutex));
|
||||||
|
|
||||||
_cairo_hash_table_remove (cairo_scaled_font_map->hash_table,
|
_cairo_hash_table_remove (cairo_scaled_font_map->hash_table,
|
||||||
&scaled_font->hash_entry);
|
&scaled_font->hash_entry);
|
||||||
|
|
||||||
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
|
|
||||||
|
|
||||||
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
|
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
|
||||||
|
|
||||||
|
CAIRO_MUTEX_UNLOCK (placeholder_scaled_font->mutex);
|
||||||
cairo_scaled_font_destroy (placeholder_scaled_font);
|
cairo_scaled_font_destroy (placeholder_scaled_font);
|
||||||
|
|
||||||
CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
|
CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cairo_scaled_font_placeholder_wait_for_creation_to_finish (cairo_scaled_font_t *scaled_font)
|
_cairo_scaled_font_placeholder_wait_for_creation_to_finish (cairo_scaled_font_t *placeholder_scaled_font)
|
||||||
{
|
{
|
||||||
/* reference the place holder so it doesn't go away */
|
/* reference the place holder so it doesn't go away */
|
||||||
cairo_scaled_font_reference (scaled_font);
|
cairo_scaled_font_reference (placeholder_scaled_font);
|
||||||
|
|
||||||
/* now unlock the fontmap mutex so creation has a chance to finish */
|
/* now unlock the fontmap mutex so creation has a chance to finish */
|
||||||
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
|
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
|
||||||
|
|
||||||
/* wait on placeholder mutex until we are awaken */
|
/* wait on placeholder mutex until we are awaken */
|
||||||
CAIRO_MUTEX_LOCK (scaled_font->mutex);
|
CAIRO_MUTEX_LOCK (placeholder_scaled_font->mutex);
|
||||||
|
|
||||||
/* ok, creation done. just clean up and back out */
|
/* ok, creation done. just clean up and back out */
|
||||||
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
|
CAIRO_MUTEX_UNLOCK (placeholder_scaled_font->mutex);
|
||||||
|
cairo_scaled_font_destroy (placeholder_scaled_font);
|
||||||
|
|
||||||
CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
|
CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
|
||||||
cairo_scaled_font_destroy (scaled_font);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/)
|
/* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/)
|
||||||
|
@ -569,11 +573,11 @@ _cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_
|
||||||
sizeof(cairo_matrix_t)) == 0 &&
|
sizeof(cairo_matrix_t)) == 0 &&
|
||||||
memcmp ((unsigned char *)(&key_a->ctm.xx),
|
memcmp ((unsigned char *)(&key_a->ctm.xx),
|
||||||
(unsigned char *)(&key_b->ctm.xx),
|
(unsigned char *)(&key_b->ctm.xx),
|
||||||
sizeof(double) * 4) == 0 &&
|
sizeof(cairo_matrix_t)) == 0 &&
|
||||||
cairo_font_options_equal (&key_a->options, &key_b->options));
|
cairo_font_options_equal (&key_a->options, &key_b->options));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX: This 256 number is arbitary---we've never done any measurement
|
/* XXX: This 256 number is arbitrary---we've never done any measurement
|
||||||
* of this. In fact, having a per-font glyph caches each managed
|
* of this. In fact, having a per-font glyph caches each managed
|
||||||
* separately is probably not what we want anyway. Would probably be
|
* separately is probably not what we want anyway. Would probably be
|
||||||
* much better to have a single cache for glyphs with random
|
* much better to have a single cache for glyphs with random
|
||||||
|
@ -656,6 +660,10 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
|
||||||
void
|
void
|
||||||
_cairo_scaled_font_freeze_cache (cairo_scaled_font_t *scaled_font)
|
_cairo_scaled_font_freeze_cache (cairo_scaled_font_t *scaled_font)
|
||||||
{
|
{
|
||||||
|
/* ensure we do not modify an error object */
|
||||||
|
assert (scaled_font->status == CAIRO_STATUS_SUCCESS);
|
||||||
|
|
||||||
|
CAIRO_MUTEX_LOCK (scaled_font->mutex);
|
||||||
_cairo_cache_freeze (scaled_font->glyphs);
|
_cairo_cache_freeze (scaled_font->glyphs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,11 +671,14 @@ void
|
||||||
_cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font)
|
_cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font)
|
||||||
{
|
{
|
||||||
_cairo_cache_thaw (scaled_font->glyphs);
|
_cairo_cache_thaw (scaled_font->glyphs);
|
||||||
|
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font)
|
_cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font)
|
||||||
{
|
{
|
||||||
|
assert (CAIRO_MUTEX_IS_LOCKED (scaled_font->mutex));
|
||||||
|
|
||||||
_cairo_cache_destroy (scaled_font->glyphs);
|
_cairo_cache_destroy (scaled_font->glyphs);
|
||||||
scaled_font->glyphs = _cairo_cache_create (_cairo_scaled_glyph_keys_equal,
|
scaled_font->glyphs = _cairo_cache_create (_cairo_scaled_glyph_keys_equal,
|
||||||
_cairo_scaled_glyph_destroy,
|
_cairo_scaled_glyph_destroy,
|
||||||
|
@ -701,8 +712,8 @@ _cairo_scaled_font_set_metrics (cairo_scaled_font_t *scaled_font,
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
|
_cairo_scaled_font_fini_internal (cairo_scaled_font_t *scaled_font)
|
||||||
{
|
{
|
||||||
scaled_font->finished = TRUE;
|
scaled_font->finished = TRUE;
|
||||||
|
|
||||||
|
@ -724,6 +735,16 @@ _cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
|
||||||
_cairo_user_data_array_fini (&scaled_font->user_data);
|
_cairo_user_data_array_fini (&scaled_font->user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
|
||||||
|
{
|
||||||
|
/* Release the lock to avoid the possibility of a recursive
|
||||||
|
* deadlock when the scaled font destroy closure gets called. */
|
||||||
|
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
|
||||||
|
_cairo_scaled_font_fini_internal (scaled_font);
|
||||||
|
CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_scaled_font_create:
|
* cairo_scaled_font_create:
|
||||||
* @font_face: a #cairo_font_face_t
|
* @font_face: a #cairo_font_face_t
|
||||||
|
@ -735,8 +756,7 @@ _cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
|
||||||
* @ctm: user to device transformation matrix with which the font will
|
* @ctm: user to device transformation matrix with which the font will
|
||||||
* be used.
|
* be used.
|
||||||
* @options: options to use when getting metrics for the font and
|
* @options: options to use when getting metrics for the font and
|
||||||
* rendering with it. A %NULL pointer will be interpreted as
|
* rendering with it.
|
||||||
* meaning the default options.
|
|
||||||
*
|
*
|
||||||
* Creates a #cairo_scaled_font_t object from a font face and matrices that
|
* Creates a #cairo_scaled_font_t object from a font face and matrices that
|
||||||
* describe the size of the font and the environment in which it will
|
* describe the size of the font and the environment in which it will
|
||||||
|
@ -752,6 +772,7 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
|
||||||
const cairo_font_options_t *options)
|
const cairo_font_options_t *options)
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
cairo_font_face_t *impl_face;
|
||||||
cairo_scaled_font_map_t *font_map;
|
cairo_scaled_font_map_t *font_map;
|
||||||
cairo_scaled_font_t key, *old = NULL, *scaled_font = NULL;
|
cairo_scaled_font_t key, *old = NULL, *scaled_font = NULL;
|
||||||
|
|
||||||
|
@ -765,11 +786,19 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
|
||||||
/* Note that degenerate ctm or font_matrix *are* allowed.
|
/* Note that degenerate ctm or font_matrix *are* allowed.
|
||||||
* We want to support a font size of 0. */
|
* We want to support a font size of 0. */
|
||||||
|
|
||||||
|
if (font_face->backend->get_implementation != NULL) {
|
||||||
|
/* indirect implementation, lookup the face that is used for the key */
|
||||||
|
status = font_face->backend->get_implementation (font_face, &impl_face);
|
||||||
|
if (status)
|
||||||
|
return _cairo_scaled_font_create_in_error (status);
|
||||||
|
} else
|
||||||
|
impl_face = font_face;
|
||||||
|
|
||||||
font_map = _cairo_scaled_font_map_lock ();
|
font_map = _cairo_scaled_font_map_lock ();
|
||||||
if (font_map == NULL)
|
if (font_map == NULL)
|
||||||
return _cairo_scaled_font_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
return _cairo_scaled_font_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||||
|
|
||||||
_cairo_scaled_font_init_key (&key, font_face,
|
_cairo_scaled_font_init_key (&key, impl_face,
|
||||||
font_matrix, ctm, options);
|
font_matrix, ctm, options);
|
||||||
scaled_font = font_map->mru_scaled_font;
|
scaled_font = font_map->mru_scaled_font;
|
||||||
if (scaled_font != NULL &&
|
if (scaled_font != NULL &&
|
||||||
|
@ -876,7 +905,7 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
|
||||||
/* We can't call _cairo_scaled_font_destroy here since it expects
|
/* We can't call _cairo_scaled_font_destroy here since it expects
|
||||||
* that the font has already been successfully inserted into the
|
* that the font has already been successfully inserted into the
|
||||||
* hash table. */
|
* hash table. */
|
||||||
_cairo_scaled_font_fini (scaled_font);
|
_cairo_scaled_font_fini_internal (scaled_font);
|
||||||
free (scaled_font);
|
free (scaled_font);
|
||||||
return _cairo_scaled_font_create_in_error (status);
|
return _cairo_scaled_font_create_in_error (status);
|
||||||
}
|
}
|
||||||
|
@ -980,6 +1009,8 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
|
||||||
cairo_scaled_font_t *lru = NULL;
|
cairo_scaled_font_t *lru = NULL;
|
||||||
cairo_scaled_font_map_t *font_map;
|
cairo_scaled_font_map_t *font_map;
|
||||||
|
|
||||||
|
assert (CAIRO_MUTEX_IS_UNLOCKED (_cairo_scaled_font_map_mutex));
|
||||||
|
|
||||||
if (scaled_font == NULL ||
|
if (scaled_font == NULL ||
|
||||||
CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count))
|
CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count))
|
||||||
return;
|
return;
|
||||||
|
@ -1020,7 +1051,7 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
|
_cairo_scaled_font_map_unlock ();
|
||||||
|
|
||||||
/* If we pulled an item from the holdovers array, (while the font
|
/* If we pulled an item from the holdovers array, (while the font
|
||||||
* map lock was held, of course), then there is no way that anyone
|
* map lock was held, of course), then there is no way that anyone
|
||||||
|
@ -1029,7 +1060,7 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
|
||||||
* as we never want to call into any backend function with a lock
|
* as we never want to call into any backend function with a lock
|
||||||
* held. */
|
* held. */
|
||||||
if (lru) {
|
if (lru) {
|
||||||
_cairo_scaled_font_fini (lru);
|
_cairo_scaled_font_fini_internal (lru);
|
||||||
free (lru);
|
free (lru);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1103,12 +1134,19 @@ cairo_scaled_font_set_user_data (cairo_scaled_font_t *scaled_font,
|
||||||
cairo_destroy_func_t destroy)
|
cairo_destroy_func_t destroy)
|
||||||
{
|
{
|
||||||
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count))
|
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count))
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
return scaled_font->status;
|
||||||
|
|
||||||
return _cairo_user_data_array_set_data (&scaled_font->user_data,
|
return _cairo_user_data_array_set_data (&scaled_font->user_data,
|
||||||
key, user_data, destroy);
|
key, user_data, destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cairo_bool_t
|
||||||
|
_cairo_scaled_font_is_frozen (cairo_scaled_font_t *scaled_font)
|
||||||
|
{
|
||||||
|
return CAIRO_MUTEX_IS_LOCKED (scaled_font->mutex) &&
|
||||||
|
scaled_font->glyphs->freeze_count > 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Public font API follows. */
|
/* Public font API follows. */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1122,6 +1160,15 @@ void
|
||||||
cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font,
|
cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font,
|
||||||
cairo_font_extents_t *extents)
|
cairo_font_extents_t *extents)
|
||||||
{
|
{
|
||||||
|
if (scaled_font->status) {
|
||||||
|
extents->ascent = 0.0;
|
||||||
|
extents->descent = 0.0;
|
||||||
|
extents->height = 0.0;
|
||||||
|
extents->max_x_advance = 0.0;
|
||||||
|
extents->max_y_advance = 0.0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
*extents = scaled_font->extents;
|
*extents = scaled_font->extents;
|
||||||
}
|
}
|
||||||
slim_hidden_def (cairo_scaled_font_extents);
|
slim_hidden_def (cairo_scaled_font_extents);
|
||||||
|
@ -1169,8 +1216,10 @@ cairo_scaled_font_text_extents (cairo_scaled_font_t *scaled_font,
|
||||||
&glyphs, &num_glyphs,
|
&glyphs, &num_glyphs,
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
NULL);
|
NULL);
|
||||||
if (status)
|
if (status) {
|
||||||
|
status = _cairo_scaled_font_set_error (scaled_font, status);
|
||||||
goto ZERO_EXTENTS;
|
goto ZERO_EXTENTS;
|
||||||
|
}
|
||||||
|
|
||||||
cairo_scaled_font_glyph_extents (scaled_font, glyphs, num_glyphs, extents);
|
cairo_scaled_font_glyph_extents (scaled_font, glyphs, num_glyphs, extents);
|
||||||
free (glyphs);
|
free (glyphs);
|
||||||
|
@ -1241,7 +1290,6 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CAIRO_MUTEX_LOCK (scaled_font->mutex);
|
|
||||||
_cairo_scaled_font_freeze_cache (scaled_font);
|
_cairo_scaled_font_freeze_cache (scaled_font);
|
||||||
|
|
||||||
for (i = 0; i < num_glyphs; i++) {
|
for (i = 0; i < num_glyphs; i++) {
|
||||||
|
@ -1310,7 +1358,6 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
|
||||||
|
|
||||||
UNLOCK:
|
UNLOCK:
|
||||||
_cairo_scaled_font_thaw_cache (scaled_font);
|
_cairo_scaled_font_thaw_cache (scaled_font);
|
||||||
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
|
|
||||||
}
|
}
|
||||||
slim_hidden_def (cairo_scaled_font_glyph_extents);
|
slim_hidden_def (cairo_scaled_font_glyph_extents);
|
||||||
|
|
||||||
|
@ -1325,8 +1372,8 @@ slim_hidden_def (cairo_scaled_font_glyph_extents);
|
||||||
* @num_glyphs: pointer to number of glyphs
|
* @num_glyphs: pointer to number of glyphs
|
||||||
* @clusters: pointer to array of cluster mapping information to fill, or %NULL
|
* @clusters: pointer to array of cluster mapping information to fill, or %NULL
|
||||||
* @num_clusters: pointer to number of clusters, or %NULL
|
* @num_clusters: pointer to number of clusters, or %NULL
|
||||||
* @backward: pointer to whether the text to glyphs mapping goes backward, or
|
* @cluster_flags: pointer to location to store cluster flags corresponding to the
|
||||||
* %NULL
|
* output @clusters, or %NULL
|
||||||
*
|
*
|
||||||
* Converts UTF-8 text to an array of glyphs, optionally with cluster
|
* Converts UTF-8 text to an array of glyphs, optionally with cluster
|
||||||
* mapping, that can be used to render later using @scaled_font.
|
* mapping, that can be used to render later using @scaled_font.
|
||||||
|
@ -1336,11 +1383,12 @@ slim_hidden_def (cairo_scaled_font_glyph_extents);
|
||||||
* entries available there. If the provided glyph array is too short for
|
* entries available there. If the provided glyph array is too short for
|
||||||
* the conversion, a new glyph array is allocated using cairo_glyph_allocate()
|
* the conversion, a new glyph array is allocated using cairo_glyph_allocate()
|
||||||
* and placed in @glyphs. Upon return, @num_glyphs always contains the
|
* and placed in @glyphs. Upon return, @num_glyphs always contains the
|
||||||
* number of generated glyphs. If the value @glyphs points at has changed
|
* number of generated glyphs. If the value @glyphs points to has changed
|
||||||
* after the call, the user is responsible for freeing the allocated glyph
|
* after the call, the user is responsible for freeing the allocated glyph
|
||||||
* array using cairo_glyph_free().
|
* array using cairo_glyph_free(). This may happen even if the provided
|
||||||
|
* array was large enough.
|
||||||
*
|
*
|
||||||
* If @clusters is not %NULL, @num_clusters and @backward should not be %NULL,
|
* If @clusters is not %NULL, @num_clusters and @cluster_flags should not be %NULL,
|
||||||
* and cluster mapping will be computed.
|
* and cluster mapping will be computed.
|
||||||
* The semantics of how cluster array allocation works is similar to the glyph
|
* The semantics of how cluster array allocation works is similar to the glyph
|
||||||
* array. That is,
|
* array. That is,
|
||||||
|
@ -1351,7 +1399,8 @@ slim_hidden_def (cairo_scaled_font_glyph_extents);
|
||||||
* and placed in @clusters. Upon return, @num_clusters always contains the
|
* and placed in @clusters. Upon return, @num_clusters always contains the
|
||||||
* number of generated clusters. If the value @clusters points at has changed
|
* number of generated clusters. If the value @clusters points at has changed
|
||||||
* after the call, the user is responsible for freeing the allocated cluster
|
* after the call, the user is responsible for freeing the allocated cluster
|
||||||
* array using cairo_text_cluster_free().
|
* array using cairo_text_cluster_free(). This may happen even if the provided
|
||||||
|
* array was large enough.
|
||||||
*
|
*
|
||||||
* In the simplest case, @glyphs and @clusters can point to %NULL initially
|
* In the simplest case, @glyphs and @clusters can point to %NULL initially
|
||||||
* and a suitable array will be allocated. In code:
|
* and a suitable array will be allocated. In code:
|
||||||
|
@ -1362,21 +1411,19 @@ slim_hidden_def (cairo_scaled_font_glyph_extents);
|
||||||
* int num_glyphs;
|
* int num_glyphs;
|
||||||
* cairo_text_cluster_t *clusters = NULL;
|
* cairo_text_cluster_t *clusters = NULL;
|
||||||
* int num_clusters;
|
* int num_clusters;
|
||||||
* cairo_bool_t backward;
|
* cairo_text_cluster_flags_t cluster_flags;
|
||||||
*
|
*
|
||||||
* status = cairo_scaled_font_text_to_glyphs (scaled_font,
|
* status = cairo_scaled_font_text_to_glyphs (scaled_font,
|
||||||
* x, y,
|
* x, y,
|
||||||
* utf8, utf8_len,
|
* utf8, utf8_len,
|
||||||
* &glyphs, &num_glyphs,
|
* &glyphs, &num_glyphs,
|
||||||
* &clusters, &num_clusters,
|
* &clusters, &num_clusters, &cluster_flags);
|
||||||
* &backward);
|
|
||||||
*
|
*
|
||||||
* if (status == CAIRO_STATUS_SUCCESS) {
|
* if (status == CAIRO_STATUS_SUCCESS) {
|
||||||
* cairo_show_text_glyphs (cr,
|
* cairo_show_text_glyphs (cr,
|
||||||
* utf8, utf8_len,
|
* utf8, utf8_len,
|
||||||
* *glyphs, *num_glyphs,
|
* *glyphs, *num_glyphs,
|
||||||
* *clusters, *num_clusters,
|
* *clusters, *num_clusters, *cluster_flags);
|
||||||
* *backward);
|
|
||||||
*
|
*
|
||||||
* cairo_glyph_free (*glyphs);
|
* cairo_glyph_free (*glyphs);
|
||||||
* cairo_text_cluster_free (*clusters);
|
* cairo_text_cluster_free (*clusters);
|
||||||
|
@ -1414,21 +1461,19 @@ slim_hidden_def (cairo_scaled_font_glyph_extents);
|
||||||
* cairo_text_cluster_t stack_clusters[40];
|
* cairo_text_cluster_t stack_clusters[40];
|
||||||
* cairo_text_cluster_t *clusters = stack_clusters;
|
* cairo_text_cluster_t *clusters = stack_clusters;
|
||||||
* int num_clusters = sizeof (stack_clusters) / sizeof (stack_clusters[0]);
|
* int num_clusters = sizeof (stack_clusters) / sizeof (stack_clusters[0]);
|
||||||
* cairo_bool_t backward;
|
* cairo_text_cluster_flags_t cluster_flags;
|
||||||
*
|
*
|
||||||
* status = cairo_scaled_font_text_to_glyphs (scaled_font,
|
* status = cairo_scaled_font_text_to_glyphs (scaled_font,
|
||||||
* x, y,
|
* x, y,
|
||||||
* utf8, utf8_len,
|
* utf8, utf8_len,
|
||||||
* &glyphs, &num_glyphs,
|
* &glyphs, &num_glyphs,
|
||||||
* &clusters, &num_clusters,
|
* &clusters, &num_clusters, &cluster_flags);
|
||||||
* &backward);
|
|
||||||
*
|
*
|
||||||
* if (status == CAIRO_STATUS_SUCCESS) {
|
* if (status == CAIRO_STATUS_SUCCESS) {
|
||||||
* cairo_show_text_glyphs (cr,
|
* cairo_show_text_glyphs (cr,
|
||||||
* utf8, utf8_len,
|
* utf8, utf8_len,
|
||||||
* *glyphs, *num_glyphs,
|
* *glyphs, *num_glyphs,
|
||||||
* *clusters, *num_clusters,
|
* *clusters, *num_clusters, *cluster_flags);
|
||||||
* *backward);
|
|
||||||
*
|
*
|
||||||
* if (glyphs != stack_glyphs)
|
* if (glyphs != stack_glyphs)
|
||||||
* cairo_glyph_free (*glyphs);
|
* cairo_glyph_free (*glyphs);
|
||||||
|
@ -1437,7 +1482,7 @@ slim_hidden_def (cairo_scaled_font_glyph_extents);
|
||||||
* }
|
* }
|
||||||
* </programlisting></informalexample>
|
* </programlisting></informalexample>
|
||||||
*
|
*
|
||||||
* For details of how @clusters, @num_clusters, and @backward map input
|
* For details of how @clusters, @num_clusters, and @cluster_flags map input
|
||||||
* UTF-8 text to the output glyphs see cairo_show_text_glyphs().
|
* UTF-8 text to the output glyphs see cairo_show_text_glyphs().
|
||||||
*
|
*
|
||||||
* The output values can be readily passed to cairo_show_text_glyphs()
|
* The output values can be readily passed to cairo_show_text_glyphs()
|
||||||
|
@ -1461,7 +1506,7 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
|
||||||
int *num_glyphs,
|
int *num_glyphs,
|
||||||
cairo_text_cluster_t **clusters,
|
cairo_text_cluster_t **clusters,
|
||||||
int *num_clusters,
|
int *num_clusters,
|
||||||
cairo_bool_t *backward)
|
cairo_text_cluster_flags_t *cluster_flags)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int num_chars = 0;
|
int num_chars = 0;
|
||||||
|
@ -1488,9 +1533,9 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
|
||||||
utf8_len = 0;
|
utf8_len = 0;
|
||||||
|
|
||||||
/* No NULLs for non-NULLs! */
|
/* No NULLs for non-NULLs! */
|
||||||
if ((utf8_len && utf8 == NULL) ||
|
if ((utf8_len && utf8 == NULL) ||
|
||||||
(clusters && num_clusters == NULL) ||
|
(clusters && num_clusters == NULL) ||
|
||||||
(clusters && backward == NULL)) {
|
(clusters && cluster_flags == NULL)) {
|
||||||
status = CAIRO_STATUS_NULL_POINTER;
|
status = CAIRO_STATUS_NULL_POINTER;
|
||||||
goto BAIL;
|
goto BAIL;
|
||||||
}
|
}
|
||||||
|
@ -1511,12 +1556,12 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
|
||||||
num_clusters = NULL;
|
num_clusters = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (backward) {
|
if (cluster_flags) {
|
||||||
*backward = FALSE;
|
*cluster_flags = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!clusters && backward) {
|
if (!clusters && cluster_flags) {
|
||||||
backward = NULL;
|
cluster_flags = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Apart from that, no negatives */
|
/* Apart from that, no negatives */
|
||||||
|
@ -1537,7 +1582,6 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
|
||||||
if (status)
|
if (status)
|
||||||
goto BAIL;
|
goto BAIL;
|
||||||
|
|
||||||
CAIRO_MUTEX_LOCK (scaled_font->mutex);
|
|
||||||
_cairo_scaled_font_freeze_cache (scaled_font);
|
_cairo_scaled_font_freeze_cache (scaled_font);
|
||||||
|
|
||||||
orig_glyphs = *glyphs;
|
orig_glyphs = *glyphs;
|
||||||
|
@ -1549,7 +1593,7 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
|
||||||
utf8, utf8_len,
|
utf8, utf8_len,
|
||||||
glyphs, num_glyphs,
|
glyphs, num_glyphs,
|
||||||
clusters, num_clusters,
|
clusters, num_clusters,
|
||||||
backward);
|
cluster_flags);
|
||||||
|
|
||||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
|
if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||||
|
|
||||||
|
@ -1583,7 +1627,7 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
|
||||||
status = _cairo_validate_text_clusters (utf8, utf8_len,
|
status = _cairo_validate_text_clusters (utf8, utf8_len,
|
||||||
*glyphs, *num_glyphs,
|
*glyphs, *num_glyphs,
|
||||||
*clusters, *num_clusters,
|
*clusters, *num_clusters,
|
||||||
*backward);
|
*cluster_flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1643,7 +1687,6 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
|
||||||
|
|
||||||
DONE: /* error that should be logged on scaled_font happened */
|
DONE: /* error that should be logged on scaled_font happened */
|
||||||
_cairo_scaled_font_thaw_cache (scaled_font);
|
_cairo_scaled_font_thaw_cache (scaled_font);
|
||||||
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
|
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
*num_glyphs = 0;
|
*num_glyphs = 0;
|
||||||
|
@ -1692,6 +1735,8 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
|
||||||
if (scaled_font->status)
|
if (scaled_font->status)
|
||||||
return scaled_font->status;
|
return scaled_font->status;
|
||||||
|
|
||||||
|
_cairo_scaled_font_freeze_cache (scaled_font);
|
||||||
|
|
||||||
for (i = 0; i < num_glyphs; i++) {
|
for (i = 0; i < num_glyphs; i++) {
|
||||||
cairo_scaled_glyph_t *scaled_glyph;
|
cairo_scaled_glyph_t *scaled_glyph;
|
||||||
int left, top;
|
int left, top;
|
||||||
|
@ -1703,7 +1748,7 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
|
||||||
CAIRO_SCALED_GLYPH_INFO_METRICS,
|
CAIRO_SCALED_GLYPH_INFO_METRICS,
|
||||||
&scaled_glyph);
|
&scaled_glyph);
|
||||||
if (status)
|
if (status)
|
||||||
return _cairo_scaled_font_set_error (scaled_font, status);
|
break;
|
||||||
|
|
||||||
/* XXX glyph images are snapped to pixel locations */
|
/* XXX glyph images are snapped to pixel locations */
|
||||||
x = _cairo_lround (glyphs[i].x);
|
x = _cairo_lround (glyphs[i].x);
|
||||||
|
@ -1719,6 +1764,11 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
|
||||||
if (top < min.y) min.y = top;
|
if (top < min.y) min.y = top;
|
||||||
if (bottom > max.y) max.y = bottom;
|
if (bottom > max.y) max.y = bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cairo_scaled_font_thaw_cache (scaled_font);
|
||||||
|
if (status)
|
||||||
|
return _cairo_scaled_font_set_error (scaled_font, status);
|
||||||
|
|
||||||
if (min.x < max.x && min.y < max.y) {
|
if (min.x < max.x && min.y < max.y) {
|
||||||
extents->x = min.x;
|
extents->x = min.x;
|
||||||
extents->width = max.x - min.x;
|
extents->width = max.x - min.x;
|
||||||
|
@ -1728,6 +1778,7 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
|
||||||
extents->x = extents->y = 0;
|
extents->x = extents->y = 0;
|
||||||
extents->width = extents->height = 0;
|
extents->width = extents->height = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1784,7 +1835,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
||||||
|
|
||||||
_cairo_pattern_init_solid (&white_pattern, CAIRO_COLOR_WHITE, CAIRO_CONTENT_COLOR);
|
_cairo_pattern_init_solid (&white_pattern, CAIRO_COLOR_WHITE, CAIRO_CONTENT_COLOR);
|
||||||
|
|
||||||
_cairo_cache_freeze (scaled_font->glyphs);
|
_cairo_scaled_font_freeze_cache (scaled_font);
|
||||||
|
|
||||||
for (i = 0; i < num_glyphs; i++) {
|
for (i = 0; i < num_glyphs; i++) {
|
||||||
int x, y;
|
int x, y;
|
||||||
|
@ -1904,7 +1955,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
||||||
_cairo_pattern_fini (&mask_pattern.base);
|
_cairo_pattern_fini (&mask_pattern.base);
|
||||||
|
|
||||||
CLEANUP_MASK:
|
CLEANUP_MASK:
|
||||||
_cairo_cache_thaw (scaled_font->glyphs);
|
_cairo_scaled_font_thaw_cache (scaled_font);
|
||||||
|
|
||||||
_cairo_pattern_fini (&white_pattern.base);
|
_cairo_pattern_fini (&white_pattern.base);
|
||||||
|
|
||||||
|
@ -2256,9 +2307,19 @@ _cairo_scaled_glyph_set_meta_surface (cairo_scaled_glyph_t *scaled_glyph,
|
||||||
* @index: the glyph to create
|
* @index: the glyph to create
|
||||||
* @info: a #cairo_scaled_glyph_info_t marking which portions of
|
* @info: a #cairo_scaled_glyph_info_t marking which portions of
|
||||||
* the glyph should be filled in.
|
* the glyph should be filled in.
|
||||||
* @scaled_glyph_ret: a #cairo_scaled_glyph_t * where the glyph
|
* @scaled_glyph_ret: a #cairo_scaled_glyph_t where the glyph
|
||||||
* is returned.
|
* is returned.
|
||||||
*
|
*
|
||||||
|
* If the desired info is not available, (for example, when trying to
|
||||||
|
* get INFO_PATH with a bitmapped font), this function will return
|
||||||
|
* %CAIRO_INT_STATUS_UNSUPPORTED.
|
||||||
|
*
|
||||||
|
* Note: This function must be called with the scaled font frozen, and it must
|
||||||
|
* remain frozen for as long as the @scaled_glyph_ret is alive. (If the scaled
|
||||||
|
* font was not frozen, then there is no guarantee that the glyph would not be
|
||||||
|
* evicted before you tried to access it.) See
|
||||||
|
* _cairo_scaled_font_freeze_cache() and _cairo_scaled_font_thaw_cache().
|
||||||
|
*
|
||||||
* Returns: a glyph with the requested portions filled in. Glyph
|
* Returns: a glyph with the requested portions filled in. Glyph
|
||||||
* lookup is cached and glyph will be automatically freed along
|
* lookup is cached and glyph will be automatically freed along
|
||||||
* with the scaled_font so no explicit free is required.
|
* with the scaled_font so no explicit free is required.
|
||||||
|
@ -2266,12 +2327,6 @@ _cairo_scaled_glyph_set_meta_surface (cairo_scaled_glyph_t *scaled_glyph,
|
||||||
* %CAIRO_SCALED_GLYPH_INFO_METRICS - glyph metrics and bounding box
|
* %CAIRO_SCALED_GLYPH_INFO_METRICS - glyph metrics and bounding box
|
||||||
* %CAIRO_SCALED_GLYPH_INFO_SURFACE - surface holding glyph image
|
* %CAIRO_SCALED_GLYPH_INFO_SURFACE - surface holding glyph image
|
||||||
* %CAIRO_SCALED_GLYPH_INFO_PATH - path holding glyph outline in device space
|
* %CAIRO_SCALED_GLYPH_INFO_PATH - path holding glyph outline in device space
|
||||||
*
|
|
||||||
* If the desired info is not available, (for example, when trying to
|
|
||||||
* get INFO_PATH with a bitmapped font), this function will return
|
|
||||||
* %CAIRO_INT_STATUS_UNSUPPORTED.
|
|
||||||
*
|
|
||||||
* Note: This function must be called with scaled_font->mutex held.
|
|
||||||
**/
|
**/
|
||||||
cairo_int_status_t
|
cairo_int_status_t
|
||||||
_cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
|
_cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
|
||||||
|
@ -2287,6 +2342,8 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
|
||||||
if (scaled_font->status)
|
if (scaled_font->status)
|
||||||
return scaled_font->status;
|
return scaled_font->status;
|
||||||
|
|
||||||
|
assert (_cairo_scaled_font_is_frozen (scaled_font));
|
||||||
|
|
||||||
key.hash = index;
|
key.hash = index;
|
||||||
/*
|
/*
|
||||||
* Check cache for glyph
|
* Check cache for glyph
|
||||||
|
|
|
@ -322,16 +322,20 @@ _cairo_skip_list_insert (cairo_skip_list_t *list, void *data, int unique)
|
||||||
/*
|
/*
|
||||||
* Find links along each chain
|
* Find links along each chain
|
||||||
*/
|
*/
|
||||||
|
elt = NULL;
|
||||||
next = list->chains;
|
next = list->chains;
|
||||||
for (i = list->max_level; --i >= 0; )
|
for (i = list->max_level; --i >= 0; )
|
||||||
{
|
{
|
||||||
for (; (elt = next[i]); next = elt->next)
|
if (elt != next[i])
|
||||||
{
|
{
|
||||||
int cmp = list->compare (list, ELT_DATA(elt), data);
|
for (; (elt = next[i]); next = elt->next)
|
||||||
if (unique && 0 == cmp)
|
{
|
||||||
return ELT_DATA(elt);
|
int cmp = list->compare (list, ELT_DATA(elt), data);
|
||||||
if (cmp > 0)
|
if (unique && 0 == cmp)
|
||||||
break;
|
return ELT_DATA(elt);
|
||||||
|
if (cmp > 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
update[i] = next;
|
update[i] = next;
|
||||||
if (next != list->chains)
|
if (next != list->chains)
|
||||||
|
|
|
@ -37,7 +37,9 @@
|
||||||
#include "cairoint.h"
|
#include "cairoint.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
_cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b)
|
_cairo_slope_init (cairo_slope_t *slope,
|
||||||
|
const cairo_point_t *a,
|
||||||
|
const cairo_point_t *b)
|
||||||
{
|
{
|
||||||
slope->dx = b->x - a->x;
|
slope->dx = b->x - a->x;
|
||||||
slope->dy = b->y - a->y;
|
slope->dy = b->y - a->y;
|
||||||
|
@ -62,17 +64,15 @@ _cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b)
|
||||||
> 0 => a more positive than b
|
> 0 => a more positive than b
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
_cairo_slope_compare (cairo_slope_t *a, cairo_slope_t *b)
|
_cairo_slope_compare (const cairo_slope_t *a, const cairo_slope_t *b)
|
||||||
{
|
{
|
||||||
cairo_fixed_48_16_t diff;
|
cairo_int64_t ady_bdx = _cairo_int32x32_64_mul (a->dy, b->dx);
|
||||||
|
cairo_int64_t bdy_adx = _cairo_int32x32_64_mul (b->dy, a->dx);
|
||||||
|
int cmp;
|
||||||
|
|
||||||
diff = ((cairo_fixed_48_16_t) a->dy * (cairo_fixed_48_16_t) b->dx
|
cmp = _cairo_int64_cmp (ady_bdx, bdy_adx);
|
||||||
- (cairo_fixed_48_16_t) b->dy * (cairo_fixed_48_16_t) a->dx);
|
if (cmp)
|
||||||
|
return cmp;
|
||||||
if (diff > 0)
|
|
||||||
return 1;
|
|
||||||
if (diff < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* special-case zero vectors. the intended logic here is:
|
/* special-case zero vectors. the intended logic here is:
|
||||||
* zero vectors all compare equal, and more positive than any
|
* zero vectors all compare equal, and more positive than any
|
||||||
|
|
|
@ -124,6 +124,8 @@ _cairo_surface_fallback_clone_similar (cairo_surface_t *surface,
|
||||||
int src_y,
|
int src_y,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
|
int *clone_offset_x,
|
||||||
|
int *clone_offset_y,
|
||||||
cairo_surface_t **clone_out);
|
cairo_surface_t **clone_out);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -527,16 +527,14 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src,
|
||||||
cairo_rectangle_int_t extents;
|
cairo_rectangle_int_t extents;
|
||||||
cairo_composite_traps_info_t traps_info;
|
cairo_composite_traps_info_t traps_info;
|
||||||
|
|
||||||
if (traps->num_traps == 0)
|
if (_cairo_operator_bounded_by_mask (op) && traps->num_traps == 0)
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
|
||||||
status = _cairo_surface_get_extents (dst, &extents);
|
status = _cairo_surface_get_extents (dst, &extents);
|
||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
status = _cairo_traps_extract_region (traps, &trap_region);
|
status = _cairo_traps_extract_region (traps, &trap_region);
|
||||||
|
|
||||||
if (CAIRO_INT_STATUS_UNSUPPORTED == status) {
|
if (CAIRO_INT_STATUS_UNSUPPORTED == status) {
|
||||||
has_trap_region = FALSE;
|
has_trap_region = FALSE;
|
||||||
} else if (status) {
|
} else if (status) {
|
||||||
|
@ -697,14 +695,9 @@ _cairo_surface_fallback_paint (cairo_surface_t *surface,
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
box.p1.x = _cairo_fixed_from_int (extents.x);
|
_cairo_box_from_rectangle (&box, &extents);
|
||||||
box.p1.y = _cairo_fixed_from_int (extents.y);
|
|
||||||
box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
|
|
||||||
box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);
|
|
||||||
|
|
||||||
status = _cairo_traps_init_box (&traps, &box);
|
_cairo_traps_init_box (&traps, &box);
|
||||||
if (status)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
status = _clip_and_composite_trapezoids (source,
|
status = _clip_and_composite_trapezoids (source,
|
||||||
op,
|
op,
|
||||||
|
@ -821,13 +814,12 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface,
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
box.p1.x = _cairo_fixed_from_int (extents.x);
|
if (extents.width == 0 || extents.height == 0)
|
||||||
box.p1.y = _cairo_fixed_from_int (extents.y);
|
return CAIRO_STATUS_SUCCESS;
|
||||||
box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
|
|
||||||
box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);
|
_cairo_box_from_rectangle (&box, &extents);
|
||||||
|
|
||||||
_cairo_traps_init (&traps);
|
_cairo_traps_init (&traps);
|
||||||
|
|
||||||
_cairo_traps_limit (&traps, &box);
|
_cairo_traps_limit (&traps, &box);
|
||||||
|
|
||||||
status = _cairo_path_fixed_stroke_to_traps (path,
|
status = _cairo_path_fixed_stroke_to_traps (path,
|
||||||
|
@ -835,10 +827,8 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface,
|
||||||
ctm, ctm_inverse,
|
ctm, ctm_inverse,
|
||||||
tolerance,
|
tolerance,
|
||||||
&traps);
|
&traps);
|
||||||
if (status) {
|
if (status)
|
||||||
_cairo_traps_fini (&traps);
|
goto FAIL;
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = _clip_and_composite_trapezoids (source,
|
status = _clip_and_composite_trapezoids (source,
|
||||||
op,
|
op,
|
||||||
|
@ -847,6 +837,7 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface,
|
||||||
surface->clip,
|
surface->clip,
|
||||||
antialias);
|
antialias);
|
||||||
|
|
||||||
|
FAIL:
|
||||||
_cairo_traps_fini (&traps);
|
_cairo_traps_fini (&traps);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
@ -883,13 +874,12 @@ _cairo_surface_fallback_fill (cairo_surface_t *surface,
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
box.p1.x = _cairo_fixed_from_int (extents.x);
|
if (extents.width == 0 || extents.height == 0)
|
||||||
box.p1.y = _cairo_fixed_from_int (extents.y);
|
return CAIRO_STATUS_SUCCESS;
|
||||||
box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
|
|
||||||
box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);
|
_cairo_box_from_rectangle (&box, &extents);
|
||||||
|
|
||||||
_cairo_traps_init (&traps);
|
_cairo_traps_init (&traps);
|
||||||
|
|
||||||
_cairo_traps_limit (&traps, &box);
|
_cairo_traps_limit (&traps, &box);
|
||||||
|
|
||||||
status = _cairo_path_fixed_fill_to_traps (path,
|
status = _cairo_path_fixed_fill_to_traps (path,
|
||||||
|
@ -998,6 +988,7 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
|
||||||
|
|
||||||
if (_cairo_operator_bounded_by_mask (op)) {
|
if (_cairo_operator_bounded_by_mask (op)) {
|
||||||
cairo_rectangle_int_t glyph_extents;
|
cairo_rectangle_int_t glyph_extents;
|
||||||
|
|
||||||
status = _cairo_scaled_font_glyph_device_extents (scaled_font,
|
status = _cairo_scaled_font_glyph_device_extents (scaled_font,
|
||||||
glyphs,
|
glyphs,
|
||||||
num_glyphs,
|
num_glyphs,
|
||||||
|
@ -1259,6 +1250,8 @@ _cairo_surface_fallback_clone_similar (cairo_surface_t *surface,
|
||||||
int src_y,
|
int src_y,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
|
int *clone_offset_x,
|
||||||
|
int *clone_offset_y,
|
||||||
cairo_surface_t **clone_out)
|
cairo_surface_t **clone_out)
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
@ -1288,9 +1281,11 @@ _cairo_surface_fallback_clone_similar (cairo_surface_t *surface,
|
||||||
status = cairo_status (cr);
|
status = cairo_status (cr);
|
||||||
cairo_destroy (cr);
|
cairo_destroy (cr);
|
||||||
|
|
||||||
if (status == CAIRO_STATUS_SUCCESS)
|
if (status == CAIRO_STATUS_SUCCESS) {
|
||||||
|
*clone_offset_x = src_x;
|
||||||
|
*clone_offset_y = src_y;
|
||||||
*clone_out = new_surface;
|
*clone_out = new_surface;
|
||||||
else
|
} else
|
||||||
cairo_surface_destroy (new_surface);
|
cairo_surface_destroy (new_surface);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
|
|
@ -73,7 +73,6 @@ const cairo_surface_t name = { \
|
||||||
FALSE, /* has_font_options */ \
|
FALSE, /* has_font_options */ \
|
||||||
{ CAIRO_ANTIALIAS_DEFAULT, /* antialias */ \
|
{ CAIRO_ANTIALIAS_DEFAULT, /* antialias */ \
|
||||||
CAIRO_SUBPIXEL_ORDER_DEFAULT, /* subpixel_order */ \
|
CAIRO_SUBPIXEL_ORDER_DEFAULT, /* subpixel_order */ \
|
||||||
CAIRO_LCD_FILTER_DEFAULT, /* lcd_filter */ \
|
|
||||||
CAIRO_HINT_STYLE_DEFAULT, /* hint_style */ \
|
CAIRO_HINT_STYLE_DEFAULT, /* hint_style */ \
|
||||||
CAIRO_HINT_METRICS_DEFAULT /* hint_metrics */ \
|
CAIRO_HINT_METRICS_DEFAULT /* hint_metrics */ \
|
||||||
} /* font_options */ \
|
} /* font_options */ \
|
||||||
|
@ -239,12 +238,8 @@ _cairo_surface_create_similar_scratch (cairo_surface_t *other,
|
||||||
|
|
||||||
if (other->backend->create_similar) {
|
if (other->backend->create_similar) {
|
||||||
surface = other->backend->create_similar (other, content, width, height);
|
surface = other->backend->create_similar (other, content, width, height);
|
||||||
/* It's not an error if the backend didn't create a valid
|
if (surface != NULL && surface->status)
|
||||||
* surface---it may just not be supported. */
|
return surface;
|
||||||
if (surface && surface->status) {
|
|
||||||
cairo_surface_destroy (surface);
|
|
||||||
surface = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (surface == NULL)
|
if (surface == NULL)
|
||||||
|
@ -584,7 +579,7 @@ cairo_surface_set_user_data (cairo_surface_t *surface,
|
||||||
cairo_destroy_func_t destroy)
|
cairo_destroy_func_t destroy)
|
||||||
{
|
{
|
||||||
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count))
|
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count))
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
return surface->status;
|
||||||
|
|
||||||
return _cairo_user_data_array_set_data (&surface->user_data,
|
return _cairo_user_data_array_set_data (&surface->user_data,
|
||||||
key, user_data, destroy);
|
key, user_data, destroy);
|
||||||
|
@ -611,11 +606,11 @@ _cairo_surface_set_font_options (cairo_surface_t *surface,
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
|
||||||
assert (! surface->is_snapshot);
|
|
||||||
|
|
||||||
if (surface->status)
|
if (surface->status)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
assert (! surface->is_snapshot);
|
||||||
|
|
||||||
if (surface->finished) {
|
if (surface->finished) {
|
||||||
status = _cairo_surface_set_error (surface,
|
status = _cairo_surface_set_error (surface,
|
||||||
CAIRO_STATUS_SURFACE_FINISHED);
|
CAIRO_STATUS_SURFACE_FINISHED);
|
||||||
|
@ -709,6 +704,9 @@ slim_hidden_def (cairo_surface_flush);
|
||||||
void
|
void
|
||||||
cairo_surface_mark_dirty (cairo_surface_t *surface)
|
cairo_surface_mark_dirty (cairo_surface_t *surface)
|
||||||
{
|
{
|
||||||
|
if (surface->status)
|
||||||
|
return;
|
||||||
|
|
||||||
assert (! surface->is_snapshot);
|
assert (! surface->is_snapshot);
|
||||||
|
|
||||||
cairo_surface_mark_dirty_rectangle (surface, 0, 0, -1, -1);
|
cairo_surface_mark_dirty_rectangle (surface, 0, 0, -1, -1);
|
||||||
|
@ -739,11 +737,11 @@ cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
|
||||||
assert (! surface->is_snapshot);
|
|
||||||
|
|
||||||
if (surface->status)
|
if (surface->status)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
assert (! surface->is_snapshot);
|
||||||
|
|
||||||
if (surface->finished) {
|
if (surface->finished) {
|
||||||
status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
|
status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
|
||||||
return;
|
return;
|
||||||
|
@ -797,11 +795,11 @@ _cairo_surface_set_device_scale (cairo_surface_t *surface,
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
|
||||||
assert (! surface->is_snapshot);
|
|
||||||
|
|
||||||
if (surface->status)
|
if (surface->status)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
assert (! surface->is_snapshot);
|
||||||
|
|
||||||
if (surface->finished) {
|
if (surface->finished) {
|
||||||
status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
|
status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
|
||||||
return;
|
return;
|
||||||
|
@ -812,10 +810,10 @@ _cairo_surface_set_device_scale (cairo_surface_t *surface,
|
||||||
surface->device_transform.xy = 0.0;
|
surface->device_transform.xy = 0.0;
|
||||||
surface->device_transform.yx = 0.0;
|
surface->device_transform.yx = 0.0;
|
||||||
|
|
||||||
surface->device_transform_inverse.xx = 1.0 / sx;
|
surface->device_transform_inverse = surface->device_transform;
|
||||||
surface->device_transform_inverse.yy = 1.0 / sy;
|
status = cairo_matrix_invert (&surface->device_transform_inverse);
|
||||||
surface->device_transform_inverse.xy = 0.0;
|
/* should always be invertible unless given pathological input */
|
||||||
surface->device_transform_inverse.yx = 0.0;
|
assert (status == CAIRO_STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -843,11 +841,11 @@ cairo_surface_set_device_offset (cairo_surface_t *surface,
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
|
||||||
assert (! surface->is_snapshot);
|
|
||||||
|
|
||||||
if (surface->status)
|
if (surface->status)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
assert (! surface->is_snapshot);
|
||||||
|
|
||||||
if (surface->finished) {
|
if (surface->finished) {
|
||||||
status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
|
status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
|
||||||
return;
|
return;
|
||||||
|
@ -856,8 +854,10 @@ cairo_surface_set_device_offset (cairo_surface_t *surface,
|
||||||
surface->device_transform.x0 = x_offset;
|
surface->device_transform.x0 = x_offset;
|
||||||
surface->device_transform.y0 = y_offset;
|
surface->device_transform.y0 = y_offset;
|
||||||
|
|
||||||
surface->device_transform_inverse.x0 = - x_offset;
|
surface->device_transform_inverse = surface->device_transform;
|
||||||
surface->device_transform_inverse.y0 = - y_offset;
|
status = cairo_matrix_invert (&surface->device_transform_inverse);
|
||||||
|
/* should always be invertible unless given pathological input */
|
||||||
|
assert (status == CAIRO_STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
slim_hidden_def (cairo_surface_set_device_offset);
|
slim_hidden_def (cairo_surface_set_device_offset);
|
||||||
|
|
||||||
|
@ -924,11 +924,11 @@ cairo_surface_set_fallback_resolution (cairo_surface_t *surface,
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
|
||||||
assert (! surface->is_snapshot);
|
|
||||||
|
|
||||||
if (surface->status)
|
if (surface->status)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
assert (! surface->is_snapshot);
|
||||||
|
|
||||||
if (surface->finished) {
|
if (surface->finished) {
|
||||||
status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
|
status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
|
||||||
return;
|
return;
|
||||||
|
@ -990,11 +990,11 @@ _cairo_surface_acquire_source_image (cairo_surface_t *surface,
|
||||||
cairo_image_surface_t **image_out,
|
cairo_image_surface_t **image_out,
|
||||||
void **image_extra)
|
void **image_extra)
|
||||||
{
|
{
|
||||||
assert (!surface->finished);
|
|
||||||
|
|
||||||
if (surface->status)
|
if (surface->status)
|
||||||
return surface->status;
|
return surface->status;
|
||||||
|
|
||||||
|
assert (!surface->finished);
|
||||||
|
|
||||||
if (surface->backend->acquire_source_image == NULL)
|
if (surface->backend->acquire_source_image == NULL)
|
||||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
|
@ -1059,11 +1059,11 @@ _cairo_surface_acquire_dest_image (cairo_surface_t *surface,
|
||||||
cairo_rectangle_int_t *image_rect,
|
cairo_rectangle_int_t *image_rect,
|
||||||
void **image_extra)
|
void **image_extra)
|
||||||
{
|
{
|
||||||
assert (!surface->finished);
|
|
||||||
|
|
||||||
if (surface->status)
|
if (surface->status)
|
||||||
return surface->status;
|
return surface->status;
|
||||||
|
|
||||||
|
assert (!surface->finished);
|
||||||
|
|
||||||
if (surface->backend->acquire_dest_image == NULL)
|
if (surface->backend->acquire_dest_image == NULL)
|
||||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
|
@ -1128,6 +1128,8 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
|
||||||
int src_y,
|
int src_y,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
|
int *clone_offset_x,
|
||||||
|
int *clone_offset_y,
|
||||||
cairo_surface_t **clone_out)
|
cairo_surface_t **clone_out)
|
||||||
{
|
{
|
||||||
cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
|
cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
@ -1141,8 +1143,12 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
|
||||||
return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
|
return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
|
||||||
|
|
||||||
if (surface->backend->clone_similar) {
|
if (surface->backend->clone_similar) {
|
||||||
status = surface->backend->clone_similar (surface, src, src_x, src_y,
|
status = surface->backend->clone_similar (surface, src,
|
||||||
width, height, clone_out);
|
src_x, src_y,
|
||||||
|
width, height,
|
||||||
|
clone_offset_x,
|
||||||
|
clone_offset_y,
|
||||||
|
clone_out);
|
||||||
|
|
||||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||||
/* If we failed, try again with an image surface */
|
/* If we failed, try again with an image surface */
|
||||||
|
@ -1152,6 +1158,8 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
|
||||||
surface->backend->clone_similar (surface, &image->base,
|
surface->backend->clone_similar (surface, &image->base,
|
||||||
src_x, src_y,
|
src_x, src_y,
|
||||||
width, height,
|
width, height,
|
||||||
|
clone_offset_x,
|
||||||
|
clone_offset_y,
|
||||||
clone_out);
|
clone_out);
|
||||||
|
|
||||||
_cairo_surface_release_source_image (src, image, image_extra);
|
_cairo_surface_release_source_image (src, image, image_extra);
|
||||||
|
@ -1162,8 +1170,12 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
|
||||||
/* If we're still unsupported, hit our fallback path to get a clone */
|
/* If we're still unsupported, hit our fallback path to get a clone */
|
||||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
|
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
|
||||||
status =
|
status =
|
||||||
_cairo_surface_fallback_clone_similar (surface, src, src_x, src_y,
|
_cairo_surface_fallback_clone_similar (surface, src,
|
||||||
width, height, clone_out);
|
src_x, src_y,
|
||||||
|
width, height,
|
||||||
|
clone_offset_x,
|
||||||
|
clone_offset_y,
|
||||||
|
clone_out);
|
||||||
|
|
||||||
/* We should never get UNSUPPORTED here, so if we have an error, bail. */
|
/* We should never get UNSUPPORTED here, so if we have an error, bail. */
|
||||||
if (status)
|
if (status)
|
||||||
|
@ -1172,8 +1184,8 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
|
||||||
/* Update the clone's device_transform (which the underlying surface
|
/* Update the clone's device_transform (which the underlying surface
|
||||||
* backend knows nothing about) */
|
* backend knows nothing about) */
|
||||||
if (*clone_out != src) {
|
if (*clone_out != src) {
|
||||||
(*clone_out)->device_transform = src->device_transform;
|
(*clone_out)->device_transform = src->device_transform;
|
||||||
(*clone_out)->device_transform_inverse = src->device_transform_inverse;
|
(*clone_out)->device_transform_inverse = src->device_transform_inverse;
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
@ -1256,8 +1268,6 @@ _cairo_surface_composite (cairo_operator_t op,
|
||||||
{
|
{
|
||||||
cairo_int_status_t status;
|
cairo_int_status_t status;
|
||||||
|
|
||||||
assert (! dst->is_snapshot);
|
|
||||||
|
|
||||||
if (mask) {
|
if (mask) {
|
||||||
/* These operators aren't interpreted the same way by the backends;
|
/* These operators aren't interpreted the same way by the backends;
|
||||||
* they are implemented in terms of other operators in cairo-gstate.c
|
* they are implemented in terms of other operators in cairo-gstate.c
|
||||||
|
@ -1268,6 +1278,8 @@ _cairo_surface_composite (cairo_operator_t op,
|
||||||
if (dst->status)
|
if (dst->status)
|
||||||
return dst->status;
|
return dst->status;
|
||||||
|
|
||||||
|
assert (! dst->is_snapshot);
|
||||||
|
|
||||||
if (dst->finished)
|
if (dst->finished)
|
||||||
return _cairo_surface_set_error (dst, CAIRO_STATUS_SURFACE_FINISHED);
|
return _cairo_surface_set_error (dst, CAIRO_STATUS_SURFACE_FINISHED);
|
||||||
|
|
||||||
|
@ -1317,11 +1329,11 @@ _cairo_surface_fill_rectangle (cairo_surface_t *surface,
|
||||||
{
|
{
|
||||||
cairo_rectangle_int_t rect;
|
cairo_rectangle_int_t rect;
|
||||||
|
|
||||||
assert (! surface->is_snapshot);
|
|
||||||
|
|
||||||
if (surface->status)
|
if (surface->status)
|
||||||
return surface->status;
|
return surface->status;
|
||||||
|
|
||||||
|
assert (! surface->is_snapshot);
|
||||||
|
|
||||||
if (surface->finished)
|
if (surface->finished)
|
||||||
return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED);
|
return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED);
|
||||||
|
|
||||||
|
@ -1359,11 +1371,11 @@ _cairo_surface_fill_region (cairo_surface_t *surface,
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
assert (! surface->is_snapshot);
|
|
||||||
|
|
||||||
if (surface->status)
|
if (surface->status)
|
||||||
return surface->status;
|
return surface->status;
|
||||||
|
|
||||||
|
assert (! surface->is_snapshot);
|
||||||
|
|
||||||
num_boxes = _cairo_region_num_boxes (region);
|
num_boxes = _cairo_region_num_boxes (region);
|
||||||
|
|
||||||
if (num_boxes == 0)
|
if (num_boxes == 0)
|
||||||
|
@ -1431,11 +1443,11 @@ _cairo_surface_fill_rectangles (cairo_surface_t *surface,
|
||||||
{
|
{
|
||||||
cairo_int_status_t status;
|
cairo_int_status_t status;
|
||||||
|
|
||||||
assert (! surface->is_snapshot);
|
|
||||||
|
|
||||||
if (surface->status)
|
if (surface->status)
|
||||||
return surface->status;
|
return surface->status;
|
||||||
|
|
||||||
|
assert (! surface->is_snapshot);
|
||||||
|
|
||||||
if (surface->finished)
|
if (surface->finished)
|
||||||
return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED);
|
return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED);
|
||||||
|
|
||||||
|
@ -1462,11 +1474,11 @@ _cairo_surface_paint (cairo_surface_t *surface,
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
cairo_pattern_t *dev_source;
|
cairo_pattern_t *dev_source;
|
||||||
|
|
||||||
assert (! surface->is_snapshot);
|
|
||||||
|
|
||||||
if (surface->status)
|
if (surface->status)
|
||||||
return surface->status;
|
return surface->status;
|
||||||
|
|
||||||
|
assert (! surface->is_snapshot);
|
||||||
|
|
||||||
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
|
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
|
||||||
if (status)
|
if (status)
|
||||||
return _cairo_surface_set_error (surface, status);
|
return _cairo_surface_set_error (surface, status);
|
||||||
|
@ -1495,11 +1507,11 @@ _cairo_surface_mask (cairo_surface_t *surface,
|
||||||
cairo_pattern_t *dev_source;
|
cairo_pattern_t *dev_source;
|
||||||
cairo_pattern_t *dev_mask;
|
cairo_pattern_t *dev_mask;
|
||||||
|
|
||||||
assert (! surface->is_snapshot);
|
|
||||||
|
|
||||||
if (surface->status)
|
if (surface->status)
|
||||||
return surface->status;
|
return surface->status;
|
||||||
|
|
||||||
|
assert (! surface->is_snapshot);
|
||||||
|
|
||||||
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
|
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
|
||||||
if (status)
|
if (status)
|
||||||
goto FINISH;
|
goto FINISH;
|
||||||
|
@ -1607,11 +1619,11 @@ _cairo_surface_stroke (cairo_surface_t *surface,
|
||||||
cairo_matrix_t dev_ctm = *ctm;
|
cairo_matrix_t dev_ctm = *ctm;
|
||||||
cairo_matrix_t dev_ctm_inverse = *ctm_inverse;
|
cairo_matrix_t dev_ctm_inverse = *ctm_inverse;
|
||||||
|
|
||||||
assert (! surface->is_snapshot);
|
|
||||||
|
|
||||||
if (surface->status)
|
if (surface->status)
|
||||||
return surface->status;
|
return surface->status;
|
||||||
|
|
||||||
|
assert (! surface->is_snapshot);
|
||||||
|
|
||||||
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
|
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
|
||||||
if (status)
|
if (status)
|
||||||
return _cairo_surface_set_error (surface, status);
|
return _cairo_surface_set_error (surface, status);
|
||||||
|
@ -1651,11 +1663,11 @@ _cairo_surface_fill (cairo_surface_t *surface,
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
cairo_pattern_t *dev_source;
|
cairo_pattern_t *dev_source;
|
||||||
|
|
||||||
assert (! surface->is_snapshot);
|
|
||||||
|
|
||||||
if (surface->status)
|
if (surface->status)
|
||||||
return surface->status;
|
return surface->status;
|
||||||
|
|
||||||
|
assert (! surface->is_snapshot);
|
||||||
|
|
||||||
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
|
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
|
||||||
if (status)
|
if (status)
|
||||||
return _cairo_surface_set_error (surface, status);
|
return _cairo_surface_set_error (surface, status);
|
||||||
|
@ -1695,8 +1707,6 @@ _cairo_surface_composite_trapezoids (cairo_operator_t op,
|
||||||
{
|
{
|
||||||
cairo_int_status_t status;
|
cairo_int_status_t status;
|
||||||
|
|
||||||
assert (! dst->is_snapshot);
|
|
||||||
|
|
||||||
/* These operators aren't interpreted the same way by the backends;
|
/* These operators aren't interpreted the same way by the backends;
|
||||||
* they are implemented in terms of other operators in cairo-gstate.c
|
* they are implemented in terms of other operators in cairo-gstate.c
|
||||||
*/
|
*/
|
||||||
|
@ -1705,6 +1715,8 @@ _cairo_surface_composite_trapezoids (cairo_operator_t op,
|
||||||
if (dst->status)
|
if (dst->status)
|
||||||
return dst->status;
|
return dst->status;
|
||||||
|
|
||||||
|
assert (! dst->is_snapshot);
|
||||||
|
|
||||||
if (dst->finished)
|
if (dst->finished)
|
||||||
return _cairo_surface_set_error (dst, CAIRO_STATUS_SURFACE_FINISHED);
|
return _cairo_surface_set_error (dst, CAIRO_STATUS_SURFACE_FINISHED);
|
||||||
|
|
||||||
|
@ -1748,11 +1760,11 @@ cairo_surface_copy_page (cairo_surface_t *surface)
|
||||||
{
|
{
|
||||||
cairo_status_t status_ignored;
|
cairo_status_t status_ignored;
|
||||||
|
|
||||||
assert (! surface->is_snapshot);
|
|
||||||
|
|
||||||
if (surface->status)
|
if (surface->status)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
assert (! surface->is_snapshot);
|
||||||
|
|
||||||
if (surface->finished) {
|
if (surface->finished) {
|
||||||
status_ignored = _cairo_surface_set_error (surface,
|
status_ignored = _cairo_surface_set_error (surface,
|
||||||
CAIRO_STATUS_SURFACE_FINISHED);
|
CAIRO_STATUS_SURFACE_FINISHED);
|
||||||
|
@ -1785,11 +1797,11 @@ cairo_surface_show_page (cairo_surface_t *surface)
|
||||||
{
|
{
|
||||||
cairo_status_t status_ignored;
|
cairo_status_t status_ignored;
|
||||||
|
|
||||||
assert (! surface->is_snapshot);
|
|
||||||
|
|
||||||
if (surface->status)
|
if (surface->status)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
assert (! surface->is_snapshot);
|
||||||
|
|
||||||
if (surface->finished) {
|
if (surface->finished) {
|
||||||
status_ignored = _cairo_surface_set_error (surface,
|
status_ignored = _cairo_surface_set_error (surface,
|
||||||
CAIRO_STATUS_SURFACE_FINISHED);
|
CAIRO_STATUS_SURFACE_FINISHED);
|
||||||
|
@ -1809,10 +1821,12 @@ slim_hidden_def (cairo_surface_show_page);
|
||||||
* _cairo_surface_get_current_clip_serial:
|
* _cairo_surface_get_current_clip_serial:
|
||||||
* @surface: the #cairo_surface_t to return the serial number for
|
* @surface: the #cairo_surface_t to return the serial number for
|
||||||
*
|
*
|
||||||
|
* This space left intentionally blank.
|
||||||
|
*
|
||||||
* Returns: the serial number associated with the current
|
* Returns: the serial number associated with the current
|
||||||
* clip in the surface. All gstate functions must
|
* clip in the surface. All gstate functions must
|
||||||
* verify that the correct clip is set in the surface before
|
* verify that the correct clip is set in the surface before
|
||||||
* invoking any surface drawing function
|
* invoking any surface drawing function.
|
||||||
*/
|
*/
|
||||||
unsigned int
|
unsigned int
|
||||||
_cairo_surface_get_current_clip_serial (cairo_surface_t *surface)
|
_cairo_surface_get_current_clip_serial (cairo_surface_t *surface)
|
||||||
|
@ -1904,9 +1918,6 @@ _cairo_surface_set_clip_region (cairo_surface_t *surface,
|
||||||
if (surface->status)
|
if (surface->status)
|
||||||
return surface->status;
|
return surface->status;
|
||||||
|
|
||||||
if (surface->finished)
|
|
||||||
return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED);
|
|
||||||
|
|
||||||
assert (surface->backend->set_clip_region != NULL);
|
assert (surface->backend->set_clip_region != NULL);
|
||||||
|
|
||||||
surface->current_clip_serial = serial;
|
surface->current_clip_serial = serial;
|
||||||
|
@ -2163,9 +2174,6 @@ _cairo_surface_get_extents (cairo_surface_t *surface,
|
||||||
* function to avoid computing UTF-8 text and cluster mapping if the
|
* function to avoid computing UTF-8 text and cluster mapping if the
|
||||||
* target surface does not use it.
|
* target surface does not use it.
|
||||||
*
|
*
|
||||||
* There is a convenience function for this that takes a #cairo_t,
|
|
||||||
* namely cairo_has_show_text_glyphs().
|
|
||||||
*
|
|
||||||
* Return value: %TRUE if @surface supports
|
* Return value: %TRUE if @surface supports
|
||||||
* cairo_show_text_glyphs(), %FALSE otherwise
|
* cairo_show_text_glyphs(), %FALSE otherwise
|
||||||
*
|
*
|
||||||
|
@ -2217,18 +2225,18 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
const cairo_text_cluster_t *clusters,
|
const cairo_text_cluster_t *clusters,
|
||||||
int num_clusters,
|
int num_clusters,
|
||||||
cairo_bool_t backward,
|
cairo_text_cluster_flags_t cluster_flags,
|
||||||
cairo_scaled_font_t *scaled_font)
|
cairo_scaled_font_t *scaled_font)
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
cairo_scaled_font_t *dev_scaled_font = scaled_font;
|
cairo_scaled_font_t *dev_scaled_font = scaled_font;
|
||||||
cairo_pattern_t *dev_source;
|
cairo_pattern_t *dev_source;
|
||||||
|
|
||||||
assert (! surface->is_snapshot);
|
|
||||||
|
|
||||||
if (surface->status)
|
if (surface->status)
|
||||||
return surface->status;
|
return surface->status;
|
||||||
|
|
||||||
|
assert (! surface->is_snapshot);
|
||||||
|
|
||||||
if (!num_glyphs && !utf8_len)
|
if (!num_glyphs && !utf8_len)
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
@ -2259,8 +2267,6 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
|
||||||
return _cairo_surface_set_error (surface, status);
|
return _cairo_surface_set_error (surface, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
CAIRO_MUTEX_LOCK (dev_scaled_font->mutex);
|
|
||||||
|
|
||||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
/* The logic here is duplicated in _cairo_analysis_surface show_glyphs and
|
/* The logic here is duplicated in _cairo_analysis_surface show_glyphs and
|
||||||
|
@ -2272,8 +2278,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
|
||||||
status = surface->backend->show_text_glyphs (surface, op, dev_source,
|
status = surface->backend->show_text_glyphs (surface, op, dev_source,
|
||||||
utf8, utf8_len,
|
utf8, utf8_len,
|
||||||
glyphs, num_glyphs,
|
glyphs, num_glyphs,
|
||||||
clusters, num_clusters,
|
clusters, num_clusters, cluster_flags,
|
||||||
backward,
|
|
||||||
dev_scaled_font);
|
dev_scaled_font);
|
||||||
}
|
}
|
||||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED && surface->backend->show_glyphs) {
|
if (status == CAIRO_INT_STATUS_UNSUPPORTED && surface->backend->show_glyphs) {
|
||||||
|
@ -2311,8 +2316,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
|
||||||
status = surface->backend->show_text_glyphs (surface, op, dev_source,
|
status = surface->backend->show_text_glyphs (surface, op, dev_source,
|
||||||
utf8, utf8_len,
|
utf8, utf8_len,
|
||||||
glyphs, num_glyphs,
|
glyphs, num_glyphs,
|
||||||
clusters, num_clusters,
|
clusters, num_clusters, cluster_flags,
|
||||||
backward,
|
|
||||||
dev_scaled_font);
|
dev_scaled_font);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2322,8 +2326,6 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
|
||||||
glyphs, num_glyphs,
|
glyphs, num_glyphs,
|
||||||
dev_scaled_font);
|
dev_scaled_font);
|
||||||
|
|
||||||
CAIRO_MUTEX_UNLOCK (dev_scaled_font->mutex);
|
|
||||||
|
|
||||||
if (dev_scaled_font != scaled_font)
|
if (dev_scaled_font != scaled_font)
|
||||||
cairo_scaled_font_destroy (dev_scaled_font);
|
cairo_scaled_font_destroy (dev_scaled_font);
|
||||||
|
|
||||||
|
@ -2353,11 +2355,11 @@ _cairo_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
|
||||||
assert (! dst->is_snapshot);
|
|
||||||
|
|
||||||
if (dst->status)
|
if (dst->status)
|
||||||
return dst->status;
|
return dst->status;
|
||||||
|
|
||||||
|
assert (! dst->is_snapshot);
|
||||||
|
|
||||||
if (dst->finished)
|
if (dst->finished)
|
||||||
return _cairo_surface_set_error (dst, CAIRO_STATUS_SURFACE_FINISHED);
|
return _cairo_surface_set_error (dst, CAIRO_STATUS_SURFACE_FINISHED);
|
||||||
|
|
||||||
|
@ -2477,11 +2479,11 @@ _cairo_surface_composite_fixup_unbounded (cairo_surface_t *dst,
|
||||||
cairo_rectangle_int_t *src_rectangle = NULL;
|
cairo_rectangle_int_t *src_rectangle = NULL;
|
||||||
cairo_rectangle_int_t *mask_rectangle = NULL;
|
cairo_rectangle_int_t *mask_rectangle = NULL;
|
||||||
|
|
||||||
assert (! dst->is_snapshot);
|
|
||||||
|
|
||||||
if (dst->status)
|
if (dst->status)
|
||||||
return dst->status;
|
return dst->status;
|
||||||
|
|
||||||
|
assert (! dst->is_snapshot);
|
||||||
|
|
||||||
/* The RENDER/libpixman operators are clipped to the bounds of the untransformed,
|
/* The RENDER/libpixman operators are clipped to the bounds of the untransformed,
|
||||||
* non-repeating sources and masks. Other sources and masks can be ignored.
|
* non-repeating sources and masks. Other sources and masks can be ignored.
|
||||||
*/
|
*/
|
||||||
|
@ -2555,11 +2557,11 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst,
|
||||||
cairo_rectangle_int_t *src_rectangle = NULL;
|
cairo_rectangle_int_t *src_rectangle = NULL;
|
||||||
cairo_rectangle_int_t *mask_rectangle = NULL;
|
cairo_rectangle_int_t *mask_rectangle = NULL;
|
||||||
|
|
||||||
assert (! dst->is_snapshot);
|
|
||||||
|
|
||||||
if (dst->status)
|
if (dst->status)
|
||||||
return dst->status;
|
return dst->status;
|
||||||
|
|
||||||
|
assert (! dst->is_snapshot);
|
||||||
|
|
||||||
/* The RENDER/libpixman operators are clipped to the bounds of the untransformed,
|
/* The RENDER/libpixman operators are clipped to the bounds of the untransformed,
|
||||||
* non-repeating sources and masks. Other sources and masks can be ignored.
|
* non-repeating sources and masks. Other sources and masks can be ignored.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -42,12 +42,13 @@
|
||||||
#define _BSD_SOURCE /* for snprintf() */
|
#define _BSD_SOURCE /* for snprintf() */
|
||||||
#include "cairoint.h"
|
#include "cairoint.h"
|
||||||
#include "cairo-svg.h"
|
#include "cairo-svg.h"
|
||||||
|
#include "cairo-analysis-surface-private.h"
|
||||||
#include "cairo-svg-surface-private.h"
|
#include "cairo-svg-surface-private.h"
|
||||||
#include "cairo-path-fixed-private.h"
|
|
||||||
#include "cairo-meta-surface-private.h"
|
#include "cairo-meta-surface-private.h"
|
||||||
|
#include "cairo-output-stream-private.h"
|
||||||
|
#include "cairo-path-fixed-private.h"
|
||||||
#include "cairo-paginated-private.h"
|
#include "cairo-paginated-private.h"
|
||||||
#include "cairo-scaled-font-subsets-private.h"
|
#include "cairo-scaled-font-subsets-private.h"
|
||||||
#include "cairo-output-stream-private.h"
|
|
||||||
|
|
||||||
typedef struct cairo_svg_page cairo_svg_page_t;
|
typedef struct cairo_svg_page cairo_svg_page_t;
|
||||||
|
|
||||||
|
@ -154,7 +155,10 @@ static const cairo_paginated_surface_backend_t cairo_svg_surface_paginated_backe
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_svg_surface_create_for_stream:
|
* cairo_svg_surface_create_for_stream:
|
||||||
* @write_func: a #cairo_write_func_t to accept the output data
|
* @write_func: a #cairo_write_func_t to accept the output data, may be %NULL
|
||||||
|
* to indicate a no-op @write_func. With a no-op @write_func,
|
||||||
|
* the surface may be queried or used as a source without
|
||||||
|
* generating any temporary files.
|
||||||
* @closure: the closure argument for @write_func
|
* @closure: the closure argument for @write_func
|
||||||
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
|
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
|
||||||
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
|
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
|
||||||
|
@ -189,7 +193,10 @@ cairo_svg_surface_create_for_stream (cairo_write_func_t write_func,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_svg_surface_create:
|
* cairo_svg_surface_create:
|
||||||
* @filename: a filename for the SVG output (must be writable)
|
* @filename: a filename for the SVG output (must be writable), %NULL may be
|
||||||
|
* used to specify no output. This will generate a SVG surface that
|
||||||
|
* may be queried and used as a source, without generating a
|
||||||
|
* temporary file.
|
||||||
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
|
* @width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
|
||||||
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
|
* @height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
|
||||||
*
|
*
|
||||||
|
@ -366,8 +373,8 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document,
|
||||||
if (content == CAIRO_CONTENT_COLOR) {
|
if (content == CAIRO_CONTENT_COLOR) {
|
||||||
_cairo_output_stream_printf (surface->xml_node,
|
_cairo_output_stream_printf (surface->xml_node,
|
||||||
"<rect width=\"%f\" height=\"%f\" "
|
"<rect width=\"%f\" height=\"%f\" "
|
||||||
"style=\"opacity: 1; stroke: none; "
|
"style=\"opacity:1;stroke:none;"
|
||||||
"fill: rgb(0,0,0);\"/>\n",
|
"fill:rgb(0,0,0);\"/>\n",
|
||||||
width, height);
|
width, height);
|
||||||
status = _cairo_output_stream_get_status (surface->xml_node);
|
status = _cairo_output_stream_get_status (surface->xml_node);
|
||||||
if (status)
|
if (status)
|
||||||
|
@ -631,7 +638,7 @@ _cairo_svg_document_emit_outline_glyph_data (cairo_svg_document_t *document,
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
_cairo_output_stream_printf (document->xml_node_glyphs,
|
_cairo_output_stream_printf (document->xml_node_glyphs,
|
||||||
"<path style=\"stroke: none;\" ");
|
"<path style=\"stroke:none;\" ");
|
||||||
|
|
||||||
status = _cairo_svg_surface_emit_path (document->xml_node_glyphs, scaled_glyph->path, NULL);
|
status = _cairo_svg_surface_emit_path (document->xml_node_glyphs, scaled_glyph->path, NULL);
|
||||||
if (status)
|
if (status)
|
||||||
|
@ -706,8 +713,8 @@ _cairo_svg_document_emit_glyph (cairo_svg_document_t *document,
|
||||||
|
|
||||||
_cairo_output_stream_printf (document->xml_node_glyphs,
|
_cairo_output_stream_printf (document->xml_node_glyphs,
|
||||||
"<symbol overflow=\"visible\" id=\"glyph%d-%d\">\n",
|
"<symbol overflow=\"visible\" id=\"glyph%d-%d\">\n",
|
||||||
font_id,
|
font_id,
|
||||||
subset_glyph_index);
|
subset_glyph_index);
|
||||||
|
|
||||||
status = _cairo_svg_document_emit_outline_glyph_data (document,
|
status = _cairo_svg_document_emit_outline_glyph_data (document,
|
||||||
scaled_font,
|
scaled_font,
|
||||||
|
@ -732,6 +739,7 @@ _cairo_svg_document_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
_cairo_scaled_font_freeze_cache (font_subset->scaled_font);
|
||||||
for (i = 0; i < font_subset->num_glyphs; i++) {
|
for (i = 0; i < font_subset->num_glyphs; i++) {
|
||||||
status = _cairo_svg_document_emit_glyph (document,
|
status = _cairo_svg_document_emit_glyph (document,
|
||||||
font_subset->scaled_font,
|
font_subset->scaled_font,
|
||||||
|
@ -740,6 +748,7 @@ _cairo_svg_document_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
|
||||||
if (status)
|
if (status)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
_cairo_scaled_font_thaw_cache (font_subset->scaled_font);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -752,14 +761,48 @@ _cairo_svg_document_emit_font_subsets (cairo_svg_document_t *document)
|
||||||
status = _cairo_scaled_font_subsets_foreach_scaled (document->font_subsets,
|
status = _cairo_scaled_font_subsets_foreach_scaled (document->font_subsets,
|
||||||
_cairo_svg_document_emit_font_subset,
|
_cairo_svg_document_emit_font_subset,
|
||||||
document);
|
document);
|
||||||
|
if (status)
|
||||||
|
goto FAIL;
|
||||||
|
|
||||||
|
status = _cairo_scaled_font_subsets_foreach_user (document->font_subsets,
|
||||||
|
_cairo_svg_document_emit_font_subset,
|
||||||
|
document);
|
||||||
|
|
||||||
|
FAIL:
|
||||||
_cairo_scaled_font_subsets_destroy (document->font_subsets);
|
_cairo_scaled_font_subsets_destroy (document->font_subsets);
|
||||||
document->font_subsets = NULL;
|
document->font_subsets = NULL;
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cairo_bool_t cairo_svg_force_fallbacks = FALSE;
|
static char const *
|
||||||
|
_cairo_svg_surface_operators[] = {
|
||||||
|
"clear",
|
||||||
|
|
||||||
|
"src", "src-over", "src-in",
|
||||||
|
"src-out", "src-atop",
|
||||||
|
|
||||||
|
"dst", "dst-over", "dst-in",
|
||||||
|
"dst-out", "dst-atop",
|
||||||
|
|
||||||
|
"xor", "plus",
|
||||||
|
"color-dodge", /* FIXME: saturate ? */
|
||||||
|
};
|
||||||
|
|
||||||
|
static cairo_bool_t
|
||||||
|
_cairo_svg_surface_analyze_operator (cairo_svg_surface_t *surface,
|
||||||
|
cairo_operator_t op)
|
||||||
|
{
|
||||||
|
/* guard against newly added operators */
|
||||||
|
if (op >= ARRAY_LENGTH (_cairo_svg_surface_operators))
|
||||||
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
|
/* allow operators being NULL if they are unsupported */
|
||||||
|
if (_cairo_svg_surface_operators[op] == NULL)
|
||||||
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static cairo_int_status_t
|
static cairo_int_status_t
|
||||||
_cairo_svg_surface_analyze_operation (cairo_svg_surface_t *surface,
|
_cairo_svg_surface_analyze_operation (cairo_svg_surface_t *surface,
|
||||||
|
@ -768,8 +811,11 @@ _cairo_svg_surface_analyze_operation (cairo_svg_surface_t *surface,
|
||||||
{
|
{
|
||||||
cairo_svg_document_t *document = surface->document;
|
cairo_svg_document_t *document = surface->document;
|
||||||
|
|
||||||
if (cairo_svg_force_fallbacks)
|
if (surface->force_fallbacks &&
|
||||||
return FALSE;
|
surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||||
|
{
|
||||||
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
/* SVG doesn't support extend reflect for image pattern */
|
/* SVG doesn't support extend reflect for image pattern */
|
||||||
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE &&
|
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE &&
|
||||||
|
@ -777,7 +823,7 @@ _cairo_svg_surface_analyze_operation (cairo_svg_surface_t *surface,
|
||||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
if (document->svg_version >= CAIRO_SVG_VERSION_1_2)
|
if (document->svg_version >= CAIRO_SVG_VERSION_1_2)
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return _cairo_svg_surface_analyze_operator (surface, op);
|
||||||
|
|
||||||
if (op == CAIRO_OPERATOR_OVER)
|
if (op == CAIRO_OPERATOR_OVER)
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
@ -960,31 +1006,49 @@ _cairo_surface_base64_encode (cairo_surface_t *surface,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cairo_svg_surface_emit_operator (cairo_output_stream_t *output,
|
||||||
|
cairo_svg_surface_t *surface,
|
||||||
|
cairo_operator_t op)
|
||||||
|
{
|
||||||
|
if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2 &&
|
||||||
|
op != CAIRO_OPERATOR_OVER) {
|
||||||
|
_cairo_output_stream_printf (output, " comp-op=\"%s\"", _cairo_svg_surface_operators[op]);
|
||||||
|
if (!_cairo_operator_bounded_by_source (op))
|
||||||
|
_cairo_output_stream_printf (output, " clip-to-self=\"true\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cairo_svg_surface_emit_operator_for_style (cairo_output_stream_t *output,
|
||||||
|
cairo_svg_surface_t *surface,
|
||||||
|
cairo_operator_t op)
|
||||||
|
{
|
||||||
|
if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2 &&
|
||||||
|
op != CAIRO_OPERATOR_OVER) {
|
||||||
|
_cairo_output_stream_printf (output, "comp-op:%s;", _cairo_svg_surface_operators[op]);
|
||||||
|
if (!_cairo_operator_bounded_by_source (op))
|
||||||
|
_cairo_output_stream_printf (output, "clip-to-self:true;");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static cairo_status_t
|
static cairo_status_t
|
||||||
_cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *output,
|
_cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *output,
|
||||||
cairo_svg_surface_t *svg_surface,
|
cairo_svg_surface_t *svg_surface,
|
||||||
|
cairo_operator_t op,
|
||||||
cairo_surface_pattern_t *pattern,
|
cairo_surface_pattern_t *pattern,
|
||||||
int pattern_id,
|
int pattern_id,
|
||||||
const cairo_matrix_t *parent_matrix,
|
const cairo_matrix_t *parent_matrix,
|
||||||
const char *extra_attributes)
|
const char *extra_attributes)
|
||||||
{
|
{
|
||||||
cairo_surface_t *surface;
|
|
||||||
cairo_surface_attributes_t surface_attr;
|
|
||||||
cairo_rectangle_int_t extents;
|
cairo_rectangle_int_t extents;
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
cairo_matrix_t p2u;
|
cairo_matrix_t p2u;
|
||||||
|
|
||||||
status = _cairo_pattern_acquire_surface ((cairo_pattern_t *)pattern,
|
status = _cairo_surface_get_extents (pattern->surface, &extents);
|
||||||
(cairo_surface_t *)svg_surface,
|
|
||||||
0, 0, (unsigned int)-1, (unsigned int)-1,
|
|
||||||
&surface, &surface_attr);
|
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
status = _cairo_surface_get_extents (surface, &extents);
|
|
||||||
if (status)
|
|
||||||
goto FAIL;
|
|
||||||
|
|
||||||
p2u = pattern->base.matrix;
|
p2u = pattern->base.matrix;
|
||||||
status = cairo_matrix_invert (&p2u);
|
status = cairo_matrix_invert (&p2u);
|
||||||
/* cairo_pattern_set_matrix ensures the matrix is invertible */
|
/* cairo_pattern_set_matrix ensures the matrix is invertible */
|
||||||
|
@ -1005,25 +1069,23 @@ _cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *output
|
||||||
" <image width=\"%d\" height=\"%d\"",
|
" <image width=\"%d\" height=\"%d\"",
|
||||||
extents.width, extents.height);
|
extents.width, extents.height);
|
||||||
|
|
||||||
if (pattern_id == invalid_pattern_id)
|
if (pattern_id == invalid_pattern_id) {
|
||||||
|
_cairo_svg_surface_emit_operator (output, svg_surface, op);
|
||||||
_cairo_svg_surface_emit_transform (output, " transform", &p2u, parent_matrix);
|
_cairo_svg_surface_emit_transform (output, " transform", &p2u, parent_matrix);
|
||||||
|
}
|
||||||
|
|
||||||
if (extra_attributes)
|
if (extra_attributes)
|
||||||
_cairo_output_stream_printf (output, " %s", extra_attributes);
|
_cairo_output_stream_printf (output, " %s", extra_attributes);
|
||||||
|
|
||||||
_cairo_output_stream_printf (output, " xlink:href=\"");
|
_cairo_output_stream_printf (output, " xlink:href=\"");
|
||||||
|
|
||||||
status = _cairo_surface_base64_encode (surface, output);
|
status = _cairo_surface_base64_encode (pattern->surface, output);
|
||||||
|
|
||||||
_cairo_output_stream_printf (output, "\"/>\n");
|
_cairo_output_stream_printf (output, "\"/>\n");
|
||||||
|
|
||||||
if (pattern_id != invalid_pattern_id)
|
if (pattern_id != invalid_pattern_id)
|
||||||
_cairo_output_stream_printf (output, "</pattern>\n");
|
_cairo_output_stream_printf (output, "</pattern>\n");
|
||||||
|
|
||||||
FAIL:
|
|
||||||
_cairo_pattern_release_surface ((cairo_pattern_t *)pattern,
|
|
||||||
surface, &surface_attr);
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1159,6 +1221,7 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
|
||||||
static cairo_status_t
|
static cairo_status_t
|
||||||
_cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output,
|
_cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output,
|
||||||
cairo_svg_surface_t *surface,
|
cairo_svg_surface_t *surface,
|
||||||
|
cairo_operator_t op,
|
||||||
cairo_surface_pattern_t *pattern,
|
cairo_surface_pattern_t *pattern,
|
||||||
int pattern_id,
|
int pattern_id,
|
||||||
const cairo_matrix_t *parent_matrix,
|
const cairo_matrix_t *parent_matrix,
|
||||||
|
@ -1197,8 +1260,10 @@ _cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output,
|
||||||
"<use xlink:href=\"#surface%d\"",
|
"<use xlink:href=\"#surface%d\"",
|
||||||
id);
|
id);
|
||||||
|
|
||||||
if (pattern_id == invalid_pattern_id)
|
if (pattern_id == invalid_pattern_id) {
|
||||||
|
_cairo_svg_surface_emit_operator (output, surface, op);
|
||||||
_cairo_svg_surface_emit_transform (output, " transform", &p2u, parent_matrix);
|
_cairo_svg_surface_emit_transform (output, " transform", &p2u, parent_matrix);
|
||||||
|
}
|
||||||
|
|
||||||
if (extra_attributes)
|
if (extra_attributes)
|
||||||
_cairo_output_stream_printf (output, " %s", extra_attributes);
|
_cairo_output_stream_printf (output, " %s", extra_attributes);
|
||||||
|
@ -1214,6 +1279,7 @@ _cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output,
|
||||||
static cairo_status_t
|
static cairo_status_t
|
||||||
_cairo_svg_surface_emit_composite_pattern (cairo_output_stream_t *output,
|
_cairo_svg_surface_emit_composite_pattern (cairo_output_stream_t *output,
|
||||||
cairo_svg_surface_t *surface,
|
cairo_svg_surface_t *surface,
|
||||||
|
cairo_operator_t op,
|
||||||
cairo_surface_pattern_t *pattern,
|
cairo_surface_pattern_t *pattern,
|
||||||
int pattern_id,
|
int pattern_id,
|
||||||
const cairo_matrix_t *parent_matrix,
|
const cairo_matrix_t *parent_matrix,
|
||||||
|
@ -1221,36 +1287,14 @@ _cairo_svg_surface_emit_composite_pattern (cairo_output_stream_t *output,
|
||||||
{
|
{
|
||||||
|
|
||||||
if (_cairo_surface_is_meta (pattern->surface)) {
|
if (_cairo_surface_is_meta (pattern->surface)) {
|
||||||
return _cairo_svg_surface_emit_composite_meta_pattern (output, surface, pattern,
|
return _cairo_svg_surface_emit_composite_meta_pattern (output, surface, op, pattern,
|
||||||
pattern_id, parent_matrix, extra_attributes);
|
pattern_id, parent_matrix, extra_attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _cairo_svg_surface_emit_composite_image_pattern (output, surface, pattern,
|
return _cairo_svg_surface_emit_composite_image_pattern (output, surface, op, pattern,
|
||||||
pattern_id, parent_matrix, extra_attributes);
|
pattern_id, parent_matrix, extra_attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
_cairo_svg_surface_emit_operator (cairo_output_stream_t *output,
|
|
||||||
cairo_svg_surface_t *surface,
|
|
||||||
cairo_operator_t op)
|
|
||||||
{
|
|
||||||
char const *op_str[] = {
|
|
||||||
"clear",
|
|
||||||
|
|
||||||
"src", "src-over", "src-in",
|
|
||||||
"src-out", "src-atop",
|
|
||||||
|
|
||||||
"dst", "dst-over", "dst-in",
|
|
||||||
"dst-out", "dst-atop",
|
|
||||||
|
|
||||||
"xor", "plus",
|
|
||||||
"color-dodge" /* FIXME: saturate ? */
|
|
||||||
};
|
|
||||||
|
|
||||||
if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2)
|
|
||||||
_cairo_output_stream_printf (output, "comp-op: %s; ", op_str[op]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static cairo_status_t
|
static cairo_status_t
|
||||||
_cairo_svg_surface_emit_solid_pattern (cairo_svg_surface_t *surface,
|
_cairo_svg_surface_emit_solid_pattern (cairo_svg_surface_t *surface,
|
||||||
cairo_solid_pattern_t *pattern,
|
cairo_solid_pattern_t *pattern,
|
||||||
|
@ -1258,8 +1302,8 @@ _cairo_svg_surface_emit_solid_pattern (cairo_svg_surface_t *surface,
|
||||||
cairo_bool_t is_stroke)
|
cairo_bool_t is_stroke)
|
||||||
{
|
{
|
||||||
_cairo_output_stream_printf (style, is_stroke ?
|
_cairo_output_stream_printf (style, is_stroke ?
|
||||||
"stroke: rgb(%f%%,%f%%,%f%%); stroke-opacity: %f;":
|
"stroke:rgb(%f%%,%f%%,%f%%);stroke-opacity:%f;":
|
||||||
"fill: rgb(%f%%,%f%%,%f%%); fill-opacity: %f;",
|
"fill:rgb(%f%%,%f%%,%f%%);fill-opacity:%f;",
|
||||||
pattern->color.red * 100.0,
|
pattern->color.red * 100.0,
|
||||||
pattern->color.green * 100.0,
|
pattern->color.green * 100.0,
|
||||||
pattern->color.blue * 100.0,
|
pattern->color.blue * 100.0,
|
||||||
|
@ -1281,13 +1325,13 @@ _cairo_svg_surface_emit_surface_pattern (cairo_svg_surface_t *surface,
|
||||||
|
|
||||||
pattern_id = document->pattern_id++;
|
pattern_id = document->pattern_id++;
|
||||||
status = _cairo_svg_surface_emit_composite_pattern (document->xml_node_defs,
|
status = _cairo_svg_surface_emit_composite_pattern (document->xml_node_defs,
|
||||||
surface, pattern,
|
surface, CAIRO_OPERATOR_SOURCE, pattern,
|
||||||
pattern_id, parent_matrix, NULL);
|
pattern_id, parent_matrix, NULL);
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
_cairo_output_stream_printf (style,
|
_cairo_output_stream_printf (style,
|
||||||
"%s: url(#pattern%d);",
|
"%s:url(#pattern%d);",
|
||||||
is_stroke ? "stroke" : "fill",
|
is_stroke ? "stroke" : "fill",
|
||||||
pattern_id);
|
pattern_id);
|
||||||
|
|
||||||
|
@ -1312,8 +1356,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
|
||||||
if (pattern->n_stops == 1) {
|
if (pattern->n_stops == 1) {
|
||||||
_cairo_output_stream_printf (output,
|
_cairo_output_stream_printf (output,
|
||||||
"<stop offset=\"%f\" style=\""
|
"<stop offset=\"%f\" style=\""
|
||||||
"stop-color: rgb(%f%%,%f%%,%f%%); "
|
"stop-color:rgb(%f%%,%f%%,%f%%);"
|
||||||
"stop-opacity: %f;\"/>\n",
|
"stop-opacity:%f;\"/>\n",
|
||||||
pattern->stops[0].offset,
|
pattern->stops[0].offset,
|
||||||
pattern->stops[0].color.red * 100.0,
|
pattern->stops[0].color.red * 100.0,
|
||||||
pattern->stops[0].color.green * 100.0,
|
pattern->stops[0].color.green * 100.0,
|
||||||
|
@ -1359,8 +1403,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
|
||||||
offset = start_offset + (1 - start_offset ) * stops[i].offset;
|
offset = start_offset + (1 - start_offset ) * stops[i].offset;
|
||||||
_cairo_output_stream_printf (output,
|
_cairo_output_stream_printf (output,
|
||||||
"<stop offset=\"%f\" style=\""
|
"<stop offset=\"%f\" style=\""
|
||||||
"stop-color: rgb(%f%%,%f%%,%f%%); "
|
"stop-color:rgb(%f%%,%f%%,%f%%);"
|
||||||
"stop-opacity: %f;\"/>\n",
|
"stop-opacity:%f;\"/>\n",
|
||||||
offset,
|
offset,
|
||||||
stops[i].color.red * 100.0,
|
stops[i].color.red * 100.0,
|
||||||
stops[i].color.green * 100.0,
|
stops[i].color.green * 100.0,
|
||||||
|
@ -1411,8 +1455,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
|
||||||
|
|
||||||
_cairo_output_stream_printf (output,
|
_cairo_output_stream_printf (output,
|
||||||
"<stop offset=\"0\" style=\""
|
"<stop offset=\"0\" style=\""
|
||||||
"stop-color: rgb(%f%%,%f%%,%f%%); "
|
"stop-color:rgb(%f%%,%f%%,%f%%);"
|
||||||
"stop-opacity: %f;\"/>\n",
|
"stop-opacity:%f;\"/>\n",
|
||||||
offset_color_start.red * 100.0,
|
offset_color_start.red * 100.0,
|
||||||
offset_color_start.green * 100.0,
|
offset_color_start.green * 100.0,
|
||||||
offset_color_start.blue * 100.0,
|
offset_color_start.blue * 100.0,
|
||||||
|
@ -1420,8 +1464,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
|
||||||
for (i = offset_index; i < n_stops; i++) {
|
for (i = offset_index; i < n_stops; i++) {
|
||||||
_cairo_output_stream_printf (output,
|
_cairo_output_stream_printf (output,
|
||||||
"<stop offset=\"%f\" style=\""
|
"<stop offset=\"%f\" style=\""
|
||||||
"stop-color: rgb(%f%%,%f%%,%f%%); "
|
"stop-color:rgb(%f%%,%f%%,%f%%);"
|
||||||
"stop-opacity: %f;\"/>\n",
|
"stop-opacity:%f;\"/>\n",
|
||||||
stops[i].offset + start_offset,
|
stops[i].offset + start_offset,
|
||||||
stops[i].color.red * 100.0,
|
stops[i].color.red * 100.0,
|
||||||
stops[i].color.green * 100.0,
|
stops[i].color.green * 100.0,
|
||||||
|
@ -1431,8 +1475,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
|
||||||
for (i = 0; i < offset_index; i++) {
|
for (i = 0; i < offset_index; i++) {
|
||||||
_cairo_output_stream_printf (output,
|
_cairo_output_stream_printf (output,
|
||||||
"<stop offset=\"%f\" style=\""
|
"<stop offset=\"%f\" style=\""
|
||||||
"stop-color: rgb(%f%%,%f%%,%f%%); "
|
"stop-color:rgb(%f%%,%f%%,%f%%);"
|
||||||
"stop-opacity: %f;\"/>\n",
|
"stop-opacity:%f;\"/>\n",
|
||||||
1.0 + stops[i].offset + start_offset,
|
1.0 + stops[i].offset + start_offset,
|
||||||
stops[i].color.red * 100.0,
|
stops[i].color.red * 100.0,
|
||||||
stops[i].color.green * 100.0,
|
stops[i].color.green * 100.0,
|
||||||
|
@ -1442,8 +1486,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
|
||||||
|
|
||||||
_cairo_output_stream_printf (output,
|
_cairo_output_stream_printf (output,
|
||||||
"<stop offset=\"1\" style=\""
|
"<stop offset=\"1\" style=\""
|
||||||
"stop-color: rgb(%f%%,%f%%,%f%%); "
|
"stop-color:rgb(%f%%,%f%%,%f%%);"
|
||||||
"stop-opacity: %f;\"/>\n",
|
"stop-opacity:%f;\"/>\n",
|
||||||
offset_color_stop.red * 100.0,
|
offset_color_stop.red * 100.0,
|
||||||
offset_color_stop.green * 100.0,
|
offset_color_stop.green * 100.0,
|
||||||
offset_color_stop.blue * 100.0,
|
offset_color_stop.blue * 100.0,
|
||||||
|
@ -1517,7 +1561,7 @@ _cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface,
|
||||||
"</linearGradient>\n");
|
"</linearGradient>\n");
|
||||||
|
|
||||||
_cairo_output_stream_printf (style,
|
_cairo_output_stream_printf (style,
|
||||||
"%s: url(#linear%d);",
|
"%s:url(#linear%d);",
|
||||||
is_stroke ? "stroke" : "fill",
|
is_stroke ? "stroke" : "fill",
|
||||||
document->linear_pattern_id);
|
document->linear_pattern_id);
|
||||||
|
|
||||||
|
@ -1588,13 +1632,13 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
|
||||||
if (extend == CAIRO_EXTEND_NONE || n_stops < 1)
|
if (extend == CAIRO_EXTEND_NONE || n_stops < 1)
|
||||||
_cairo_output_stream_printf (document->xml_node_defs,
|
_cairo_output_stream_printf (document->xml_node_defs,
|
||||||
"<stop offset=\"0\" style=\""
|
"<stop offset=\"0\" style=\""
|
||||||
"stop-color: rgb(0%%,0%%,0%%); "
|
"stop-color:rgb(0%%,0%%,0%%);"
|
||||||
"stop-opacity: 0;\"/>\n");
|
"stop-opacity:0;\"/>\n");
|
||||||
else {
|
else {
|
||||||
_cairo_output_stream_printf (document->xml_node_defs,
|
_cairo_output_stream_printf (document->xml_node_defs,
|
||||||
"<stop offset=\"0\" style=\""
|
"<stop offset=\"0\" style=\""
|
||||||
"stop-color: rgb(%f%%,%f%%,%f%%); "
|
"stop-color:rgb(%f%%,%f%%,%f%%);"
|
||||||
"stop-opacity: %f;\"/>\n",
|
"stop-opacity %f;\"/>\n",
|
||||||
pattern->base.stops[0].color.red * 100.0,
|
pattern->base.stops[0].color.red * 100.0,
|
||||||
pattern->base.stops[0].color.green * 100.0,
|
pattern->base.stops[0].color.green * 100.0,
|
||||||
pattern->base.stops[0].color.blue * 100.0,
|
pattern->base.stops[0].color.blue * 100.0,
|
||||||
|
@ -1602,8 +1646,8 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
|
||||||
if (n_stops > 1)
|
if (n_stops > 1)
|
||||||
_cairo_output_stream_printf (document->xml_node_defs,
|
_cairo_output_stream_printf (document->xml_node_defs,
|
||||||
"<stop offset=\"0\" style=\""
|
"<stop offset=\"0\" style=\""
|
||||||
"stop-color: rgb(%f%%,%f%%,%f%%); "
|
"stop-color:rgb(%f%%,%f%%,%f%%);"
|
||||||
"stop-opacity: %f;\"/>\n",
|
"stop-opacity:%f;\"/>\n",
|
||||||
pattern->base.stops[n_stops - 1].color.red * 100.0,
|
pattern->base.stops[n_stops - 1].color.red * 100.0,
|
||||||
pattern->base.stops[n_stops - 1].color.green * 100.0,
|
pattern->base.stops[n_stops - 1].color.green * 100.0,
|
||||||
pattern->base.stops[n_stops - 1].color.blue * 100.0,
|
pattern->base.stops[n_stops - 1].color.blue * 100.0,
|
||||||
|
@ -1675,13 +1719,13 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
|
||||||
if (extend == CAIRO_EXTEND_NONE) {
|
if (extend == CAIRO_EXTEND_NONE) {
|
||||||
_cairo_output_stream_printf (document->xml_node_defs,
|
_cairo_output_stream_printf (document->xml_node_defs,
|
||||||
"<stop offset=\"0\" style=\""
|
"<stop offset=\"0\" style=\""
|
||||||
"stop-color: rgb(0%%,0%%,0%%); "
|
"stop-color:rgb(0%%,0%%,0%%);"
|
||||||
"stop-opacity: 0;\"/>\n");
|
"stop-opacity:0;\"/>\n");
|
||||||
if (r0 != 0.0)
|
if (r0 != 0.0)
|
||||||
_cairo_output_stream_printf (document->xml_node_defs,
|
_cairo_output_stream_printf (document->xml_node_defs,
|
||||||
"<stop offset=\"%f\" style=\""
|
"<stop offset=\"%f\" style=\""
|
||||||
"stop-color: rgb(0%%,0%%,0%%); "
|
"stop-color:rgb(0%%,0%%,0%%);"
|
||||||
"stop-opacity: 0;\"/>\n",
|
"stop-opacity:0;\"/>\n",
|
||||||
r0 / r1);
|
r0 / r1);
|
||||||
}
|
}
|
||||||
status = _cairo_svg_surface_emit_pattern_stops (document->xml_node_defs,
|
status = _cairo_svg_surface_emit_pattern_stops (document->xml_node_defs,
|
||||||
|
@ -1694,15 +1738,15 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
|
||||||
if (pattern->base.base.extend == CAIRO_EXTEND_NONE)
|
if (pattern->base.base.extend == CAIRO_EXTEND_NONE)
|
||||||
_cairo_output_stream_printf (document->xml_node_defs,
|
_cairo_output_stream_printf (document->xml_node_defs,
|
||||||
"<stop offset=\"1.0\" style=\""
|
"<stop offset=\"1.0\" style=\""
|
||||||
"stop-color: rgb(0%%,0%%,0%%); "
|
"stop-color:rgb(0%%,0%%,0%%);"
|
||||||
"stop-opacity: 0;\"/>\n");
|
"stop-opacity:0;\"/>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
_cairo_output_stream_printf (document->xml_node_defs,
|
_cairo_output_stream_printf (document->xml_node_defs,
|
||||||
"</radialGradient>\n");
|
"</radialGradient>\n");
|
||||||
|
|
||||||
_cairo_output_stream_printf (style,
|
_cairo_output_stream_printf (style,
|
||||||
"%s: url(#radial%d);",
|
"%s:url(#radial%d);",
|
||||||
is_stroke ? "stroke" : "fill",
|
is_stroke ? "stroke" : "fill",
|
||||||
document->radial_pattern_id);
|
document->radial_pattern_id);
|
||||||
|
|
||||||
|
@ -1747,10 +1791,10 @@ _cairo_svg_surface_emit_fill_style (cairo_output_stream_t *output,
|
||||||
cairo_matrix_t *parent_matrix)
|
cairo_matrix_t *parent_matrix)
|
||||||
{
|
{
|
||||||
_cairo_output_stream_printf (output,
|
_cairo_output_stream_printf (output,
|
||||||
"fill-rule: %s; ",
|
"fill-rule:%s;",
|
||||||
fill_rule == CAIRO_FILL_RULE_EVEN_ODD ?
|
fill_rule == CAIRO_FILL_RULE_EVEN_ODD ?
|
||||||
"evenodd" : "nonzero");
|
"evenodd" : "nonzero");
|
||||||
_cairo_svg_surface_emit_operator (output, surface, op);
|
_cairo_svg_surface_emit_operator_for_style (output, surface, op);
|
||||||
return _cairo_svg_surface_emit_pattern (surface, source, output, FALSE, parent_matrix);
|
return _cairo_svg_surface_emit_pattern (surface, source, output, FALSE, parent_matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1795,9 +1839,9 @@ _cairo_svg_surface_emit_stroke_style (cairo_output_stream_t *output,
|
||||||
}
|
}
|
||||||
|
|
||||||
_cairo_output_stream_printf (output,
|
_cairo_output_stream_printf (output,
|
||||||
"stroke-width: %f; "
|
"stroke-width:%f;"
|
||||||
"stroke-linecap: %s; "
|
"stroke-linecap:%s;"
|
||||||
"stroke-linejoin: %s; ",
|
"stroke-linejoin:%s;",
|
||||||
stroke_style->line_width,
|
stroke_style->line_width,
|
||||||
line_cap,
|
line_cap,
|
||||||
line_join);
|
line_join);
|
||||||
|
@ -1806,27 +1850,27 @@ _cairo_svg_surface_emit_stroke_style (cairo_output_stream_t *output,
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
_cairo_svg_surface_emit_operator (output, surface, op);
|
_cairo_svg_surface_emit_operator_for_style (output, surface, op);
|
||||||
|
|
||||||
if (stroke_style->num_dashes > 0) {
|
if (stroke_style->num_dashes > 0) {
|
||||||
_cairo_output_stream_printf (output, "stroke-dasharray: ");
|
_cairo_output_stream_printf (output, "stroke-dasharray:");
|
||||||
for (i = 0; i < stroke_style->num_dashes; i++) {
|
for (i = 0; i < stroke_style->num_dashes; i++) {
|
||||||
_cairo_output_stream_printf (output, "%f",
|
_cairo_output_stream_printf (output, "%f",
|
||||||
stroke_style->dash[i]);
|
stroke_style->dash[i]);
|
||||||
if (i + 1 < stroke_style->num_dashes)
|
if (i + 1 < stroke_style->num_dashes)
|
||||||
_cairo_output_stream_printf (output, ",");
|
_cairo_output_stream_printf (output, ",");
|
||||||
else
|
else
|
||||||
_cairo_output_stream_printf (output, "; ");
|
_cairo_output_stream_printf (output, ";");
|
||||||
}
|
}
|
||||||
if (stroke_style->dash_offset != 0.0) {
|
if (stroke_style->dash_offset != 0.0) {
|
||||||
_cairo_output_stream_printf (output,
|
_cairo_output_stream_printf (output,
|
||||||
"stroke-dashoffset: %f; ",
|
"stroke-dashoffset:%f;",
|
||||||
stroke_style->dash_offset);
|
stroke_style->dash_offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_cairo_output_stream_printf (output,
|
_cairo_output_stream_printf (output,
|
||||||
"stroke-miterlimit: %f; ",
|
"stroke-miterlimit:%f;",
|
||||||
stroke_style->miter_limit);
|
stroke_style->miter_limit);
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
@ -1931,6 +1975,7 @@ _cairo_svg_surface_emit_paint (cairo_output_stream_t *output,
|
||||||
cairo_svg_surface_t *surface,
|
cairo_svg_surface_t *surface,
|
||||||
cairo_operator_t op,
|
cairo_operator_t op,
|
||||||
cairo_pattern_t *source,
|
cairo_pattern_t *source,
|
||||||
|
cairo_pattern_t *mask_source,
|
||||||
const char *extra_attributes)
|
const char *extra_attributes)
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
@ -1938,23 +1983,24 @@ _cairo_svg_surface_emit_paint (cairo_output_stream_t *output,
|
||||||
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
|
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
|
||||||
source->extend == CAIRO_EXTEND_NONE)
|
source->extend == CAIRO_EXTEND_NONE)
|
||||||
return _cairo_svg_surface_emit_composite_pattern (output,
|
return _cairo_svg_surface_emit_composite_pattern (output,
|
||||||
surface,
|
surface,
|
||||||
(cairo_surface_pattern_t *) source,
|
op,
|
||||||
invalid_pattern_id,
|
(cairo_surface_pattern_t *) source,
|
||||||
NULL,
|
invalid_pattern_id,
|
||||||
extra_attributes);
|
mask_source ? &mask_source->matrix :NULL,
|
||||||
|
extra_attributes);
|
||||||
|
|
||||||
_cairo_output_stream_printf (output,
|
_cairo_output_stream_printf (output,
|
||||||
"<rect x=\"0\" y=\"0\" "
|
"<rect x=\"0\" y=\"0\" "
|
||||||
"width=\"%f\" height=\"%f\" "
|
"width=\"%f\" height=\"%f\" "
|
||||||
"style=\"",
|
"style=\"",
|
||||||
surface->width, surface->height);
|
surface->width, surface->height);
|
||||||
_cairo_svg_surface_emit_operator (output, surface, op);
|
_cairo_svg_surface_emit_operator_for_style (output, surface, op);
|
||||||
status = _cairo_svg_surface_emit_pattern (surface, source, output, FALSE, NULL);
|
status = _cairo_svg_surface_emit_pattern (surface, source, output, FALSE, NULL);
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
_cairo_output_stream_printf (output, " stroke: none;\"");
|
_cairo_output_stream_printf (output, "stroke:none;\"");
|
||||||
|
|
||||||
if (extra_attributes)
|
if (extra_attributes)
|
||||||
_cairo_output_stream_printf (output, " %s", extra_attributes);
|
_cairo_output_stream_printf (output, " %s", extra_attributes);
|
||||||
|
@ -1975,15 +2021,7 @@ _cairo_svg_surface_paint (void *abstract_surface,
|
||||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||||
return _cairo_svg_surface_analyze_operation (surface, op, source);
|
return _cairo_svg_surface_analyze_operation (surface, op, source);
|
||||||
|
|
||||||
/* XXX: It would be nice to be able to assert this condition
|
|
||||||
* here. But, we actually allow one 'cheat' that is used when
|
|
||||||
* painting the final image-based fallbacks. The final fallbacks
|
|
||||||
* do have alpha which we support by blending with white. This is
|
|
||||||
* possible only because there is nothing between the fallback
|
|
||||||
* images and the paper, nor is anything painted above. */
|
|
||||||
/*
|
|
||||||
assert (_cairo_svg_surface_operation_supported (surface, op, source));
|
assert (_cairo_svg_surface_operation_supported (surface, op, source));
|
||||||
*/
|
|
||||||
|
|
||||||
/* Emulation of clear and source operators, when no clipping region
|
/* Emulation of clear and source operators, when no clipping region
|
||||||
* is defined. We just delete existing content of surface root node,
|
* is defined. We just delete existing content of surface root node,
|
||||||
|
@ -1992,11 +2030,8 @@ _cairo_svg_surface_paint (void *abstract_surface,
|
||||||
* above always return FALSE. In order to make it work, we need a way
|
* above always return FALSE. In order to make it work, we need a way
|
||||||
* to know if there's an active clipping path.
|
* to know if there's an active clipping path.
|
||||||
* Optimization of CLEAR works because of a test in paginated surface,
|
* Optimization of CLEAR works because of a test in paginated surface,
|
||||||
* and an optimiszation in meta surface. */
|
* and an optimization in meta surface. */
|
||||||
if (surface->clip_level == 0 &&
|
if (surface->clip_level == 0 && op == CAIRO_OPERATOR_CLEAR) {
|
||||||
(op == CAIRO_OPERATOR_CLEAR ||
|
|
||||||
op == CAIRO_OPERATOR_SOURCE))
|
|
||||||
{
|
|
||||||
status = _cairo_output_stream_destroy (surface->xml_node);
|
status = _cairo_output_stream_destroy (surface->xml_node);
|
||||||
if (status) {
|
if (status) {
|
||||||
surface->xml_node = NULL;
|
surface->xml_node = NULL;
|
||||||
|
@ -2015,16 +2050,17 @@ _cairo_svg_surface_paint (void *abstract_surface,
|
||||||
_cairo_output_stream_printf (surface->xml_node,
|
_cairo_output_stream_printf (surface->xml_node,
|
||||||
"<rect "
|
"<rect "
|
||||||
"width=\"%f\" height=\"%f\" "
|
"width=\"%f\" height=\"%f\" "
|
||||||
"style=\"opacity: 1; "
|
"style=\"opacity:1;"
|
||||||
"stroke: none; "
|
"stroke:none;"
|
||||||
"fill: rgb(0,0,0);\"/>\n",
|
"fill:rgb(0,0,0);\"/>\n",
|
||||||
surface->width, surface->height);
|
surface->width, surface->height);
|
||||||
}
|
}
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return _cairo_svg_surface_emit_paint (surface->xml_node, surface, op, source, NULL);
|
return _cairo_svg_surface_emit_paint (surface->xml_node,
|
||||||
|
surface, op, source, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cairo_int_status_t
|
static cairo_int_status_t
|
||||||
|
@ -2041,10 +2077,23 @@ _cairo_svg_surface_mask (void *abstract_surface,
|
||||||
cairo_bool_t discard_filter = FALSE;
|
cairo_bool_t discard_filter = FALSE;
|
||||||
unsigned int mask_id;
|
unsigned int mask_id;
|
||||||
|
|
||||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
|
||||||
return _cairo_svg_surface_analyze_operation (surface, op, source);
|
cairo_status_t source_status, mask_status;
|
||||||
|
|
||||||
|
source_status = _cairo_svg_surface_analyze_operation (surface, op, source);
|
||||||
|
if (_cairo_status_is_error (source_status))
|
||||||
|
return source_status;
|
||||||
|
|
||||||
|
mask_status = _cairo_svg_surface_analyze_operation (surface, op, mask);
|
||||||
|
if (_cairo_status_is_error (mask_status))
|
||||||
|
return mask_status;
|
||||||
|
|
||||||
|
return _cairo_analysis_surface_merge_status (source_status,
|
||||||
|
mask_status);
|
||||||
|
}
|
||||||
|
|
||||||
assert (_cairo_svg_surface_operation_supported (surface, op, source));
|
assert (_cairo_svg_surface_operation_supported (surface, op, source));
|
||||||
|
assert (_cairo_svg_surface_operation_supported (surface, CAIRO_OPERATOR_OVER, mask));
|
||||||
|
|
||||||
if (cairo_pattern_get_type (mask) == CAIRO_PATTERN_TYPE_SURFACE) {
|
if (cairo_pattern_get_type (mask) == CAIRO_PATTERN_TYPE_SURFACE) {
|
||||||
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t*) mask;
|
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t*) mask;
|
||||||
|
@ -2070,7 +2119,7 @@ _cairo_svg_surface_mask (void *abstract_surface,
|
||||||
"%s",
|
"%s",
|
||||||
mask_id,
|
mask_id,
|
||||||
discard_filter ? "" : " <g filter=\"url(#alpha)\">\n");
|
discard_filter ? "" : " <g filter=\"url(#alpha)\">\n");
|
||||||
status = _cairo_svg_surface_emit_paint (mask_stream, surface, op, mask, NULL);
|
status = _cairo_svg_surface_emit_paint (mask_stream, surface, CAIRO_OPERATOR_OVER, mask, source, NULL);
|
||||||
if (status) {
|
if (status) {
|
||||||
cairo_status_t ignore = _cairo_output_stream_destroy (mask_stream);
|
cairo_status_t ignore = _cairo_output_stream_destroy (mask_stream);
|
||||||
return status;
|
return status;
|
||||||
|
@ -2089,7 +2138,7 @@ _cairo_svg_surface_mask (void *abstract_surface,
|
||||||
|
|
||||||
snprintf (buffer, sizeof buffer, "mask=\"url(#mask%d)\"",
|
snprintf (buffer, sizeof buffer, "mask=\"url(#mask%d)\"",
|
||||||
mask_id);
|
mask_id);
|
||||||
status = _cairo_svg_surface_emit_paint (surface->xml_node, surface, op, source, buffer);
|
status = _cairo_svg_surface_emit_paint (surface->xml_node, surface, op, source, 0, buffer);
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
@ -2115,7 +2164,7 @@ _cairo_svg_surface_stroke (void *abstract_dst,
|
||||||
|
|
||||||
assert (_cairo_svg_surface_operation_supported (surface, op, source));
|
assert (_cairo_svg_surface_operation_supported (surface, op, source));
|
||||||
|
|
||||||
_cairo_output_stream_printf (surface->xml_node, "<path style=\"fill: none; ");
|
_cairo_output_stream_printf (surface->xml_node, "<path style=\"fill:none;");
|
||||||
status = _cairo_svg_surface_emit_stroke_style (surface->xml_node, surface, op,
|
status = _cairo_svg_surface_emit_stroke_style (surface->xml_node, surface, op,
|
||||||
source, stroke_style, ctm_inverse);
|
source, stroke_style, ctm_inverse);
|
||||||
if (status)
|
if (status)
|
||||||
|
@ -2169,6 +2218,8 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
_cairo_svg_surface_emit_operator_for_style (surface->xml_node, surface, op);
|
||||||
|
|
||||||
_cairo_output_stream_printf (surface->xml_node, "\">\n");
|
_cairo_output_stream_printf (surface->xml_node, "\">\n");
|
||||||
|
|
||||||
for (i = 0; i < num_glyphs; i++) {
|
for (i = 0; i < num_glyphs; i++) {
|
||||||
|
@ -2418,6 +2469,28 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
|
||||||
if (document->finished)
|
if (document->finished)
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Should we add DOCTYPE?
|
||||||
|
*
|
||||||
|
* Google says no.
|
||||||
|
*
|
||||||
|
* http://tech.groups.yahoo.com/group/svg-developers/message/48562:
|
||||||
|
* There's a bunch of issues, but just to pick a few:
|
||||||
|
* - they'll give false positives.
|
||||||
|
* - they'll give false negatives.
|
||||||
|
* - they're namespace-unaware.
|
||||||
|
* - they don't wildcard.
|
||||||
|
* So when they say OK they really haven't checked anything, when
|
||||||
|
* they say NOT OK they might be on crack, and like all
|
||||||
|
* namespace-unaware things they're a dead branch of the XML tree.
|
||||||
|
*
|
||||||
|
* http://jwatt.org/svg/authoring/:
|
||||||
|
* Unfortunately the SVG DTDs are a source of so many issues that the
|
||||||
|
* SVG WG has decided not to write one for the upcoming SVG 1.2
|
||||||
|
* standard. In fact SVG WG members are even telling people not to use
|
||||||
|
* a DOCTYPE declaration in SVG 1.0 and 1.1 documents.
|
||||||
|
*/
|
||||||
|
|
||||||
_cairo_output_stream_printf (output,
|
_cairo_output_stream_printf (output,
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
"<svg xmlns=\"http://www.w3.org/2000/svg\" "
|
"<svg xmlns=\"http://www.w3.org/2000/svg\" "
|
||||||
|
@ -2506,15 +2579,33 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cairo_svg_surface_set_paginated_mode (void *abstract_surface,
|
_cairo_svg_surface_set_paginated_mode (void *abstract_surface,
|
||||||
cairo_paginated_mode_t paginated_mode)
|
cairo_paginated_mode_t paginated_mode)
|
||||||
{
|
{
|
||||||
cairo_svg_surface_t *surface = abstract_surface;
|
cairo_svg_surface_t *surface = abstract_surface;
|
||||||
|
|
||||||
surface->paginated_mode = paginated_mode;
|
surface->paginated_mode = paginated_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cairo_bool_t
|
||||||
|
_cairo_svg_surface_supports_fine_grained_fallbacks (void *abstract_surface)
|
||||||
|
{
|
||||||
|
cairo_svg_surface_t *surface = abstract_surface;
|
||||||
|
cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
|
if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2) {
|
||||||
|
status = _cairo_svg_surface_analyze_operator (surface,
|
||||||
|
CAIRO_OPERATOR_SOURCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status == CAIRO_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static const cairo_paginated_surface_backend_t cairo_svg_surface_paginated_backend = {
|
static const cairo_paginated_surface_backend_t cairo_svg_surface_paginated_backend = {
|
||||||
NULL /*_cairo_svg_surface_start_page*/,
|
NULL /*_cairo_svg_surface_start_page*/,
|
||||||
_cairo_svg_surface_set_paginated_mode
|
_cairo_svg_surface_set_paginated_mode,
|
||||||
|
NULL, /* _cairo_svg_surface_set_bounding_box */
|
||||||
|
NULL, /* _cairo_svg_surface_set_fallback_images_required */
|
||||||
|
_cairo_svg_surface_supports_fine_grained_fallbacks,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
|
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
|
||||||
/* Cairo - a vector graphics library with display and print output
|
/* Cairo - a vector graphics library with display and print output
|
||||||
*
|
*
|
||||||
* Copyright © 2007 Adrian Johnson
|
* Copyright © 2005 Red Hat, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it either under the terms of the GNU Lesser General Public
|
* modify it either under the terms of the GNU Lesser General Public
|
||||||
|
@ -28,12 +28,30 @@
|
||||||
*
|
*
|
||||||
* The Original Code is the cairo graphics library.
|
* The Original Code is the cairo graphics library.
|
||||||
*
|
*
|
||||||
* The Initial Developer of the Original Code is Adrian Johnson.
|
* The Initial Developer of the Original Code is Red Hat, Inc.
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* Adrian Johnson <ajohnson@redneon.com>
|
* Owen Taylor <otaylor@redhat.com>
|
||||||
|
* Stuart Parmenter <stuart@mozilla.com>
|
||||||
|
* Vladimir Vukicevic <vladimir@pobox.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* This file should include code that is system-specific, not
|
||||||
|
* feature-specific. For example, the DLL initialization/finalization
|
||||||
|
* code on Win32 or OS/2 must live here (not in cairo-whatever-surface.c).
|
||||||
|
* Same about possible ELF-specific code.
|
||||||
|
*
|
||||||
|
* And no other function should live here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "cairoint.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if CAIRO_MUTEX_IMPL_WIN32
|
||||||
|
#if !CAIRO_WIN32_STATIC_BUILD
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
/* We require Windows 2000 features such as ETO_PDY */
|
/* We require Windows 2000 features such as ETO_PDY */
|
||||||
#if !defined(WINVER) || (WINVER < 0x0500)
|
#if !defined(WINVER) || (WINVER < 0x0500)
|
||||||
|
@ -43,56 +61,37 @@
|
||||||
# define _WIN32_WINNT 0x0500
|
# define _WIN32_WINNT 0x0500
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "cairoint.h"
|
#include "cairo-clip-private.h"
|
||||||
|
#include "cairo-paginated-private.h"
|
||||||
|
#include "cairo-win32-private.h"
|
||||||
|
#include "cairo-scaled-font-subsets-private.h"
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <io.h>
|
|
||||||
|
|
||||||
/* tmpfile() replacment for Windows.
|
/* declare to avoid "no previous prototype for 'DllMain'" warning */
|
||||||
*
|
BOOL WINAPI
|
||||||
* On Windows tmpfile() creates the file in the root directory. This
|
DllMain (HINSTANCE hinstDLL,
|
||||||
* may fail due to unsufficient privileges.
|
DWORD fdwReason,
|
||||||
*/
|
LPVOID lpvReserved);
|
||||||
FILE *
|
|
||||||
_cairo_win32_tmpfile (void)
|
BOOL WINAPI
|
||||||
|
DllMain (HINSTANCE hinstDLL,
|
||||||
|
DWORD fdwReason,
|
||||||
|
LPVOID lpvReserved)
|
||||||
{
|
{
|
||||||
DWORD path_len;
|
switch (fdwReason) {
|
||||||
WCHAR path_name[MAX_PATH + 1];
|
case DLL_PROCESS_ATTACH:
|
||||||
WCHAR file_name[MAX_PATH + 1];
|
CAIRO_MUTEX_INITIALIZE ();
|
||||||
HANDLE handle;
|
break;
|
||||||
int fd;
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
path_len = GetTempPathW (MAX_PATH, path_name);
|
case DLL_PROCESS_DETACH:
|
||||||
if (path_len <= 0 || path_len >= MAX_PATH)
|
CAIRO_MUTEX_FINALIZE ();
|
||||||
return NULL;
|
break;
|
||||||
|
|
||||||
if (GetTempFileNameW (path_name, L"ps_", 0, file_name) == 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
handle = CreateFileW (file_name,
|
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
CREATE_ALWAYS,
|
|
||||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
|
|
||||||
NULL);
|
|
||||||
if (handle == INVALID_HANDLE_VALUE) {
|
|
||||||
DeleteFileW (file_name);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = _open_osfhandle((intptr_t) handle, 0);
|
return TRUE;
|
||||||
if (fd < 0) {
|
|
||||||
CloseHandle (handle);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fp = fdopen(fd, "w+b");
|
|
||||||
if (fp == NULL) {
|
|
||||||
_close(fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
|
@ -41,13 +41,6 @@
|
||||||
|
|
||||||
/* private functions */
|
/* private functions */
|
||||||
|
|
||||||
static cairo_status_t
|
|
||||||
_cairo_traps_grow (cairo_traps_t *traps);
|
|
||||||
|
|
||||||
static void
|
|
||||||
_cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
|
|
||||||
cairo_line_t *left, cairo_line_t *right);
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_compare_point_fixed_by_y (const void *av, const void *bv);
|
_compare_point_fixed_by_y (const void *av, const void *bv);
|
||||||
|
|
||||||
|
@ -83,15 +76,21 @@ _cairo_traps_get_limit (cairo_traps_t *traps,
|
||||||
return traps->has_limits;
|
return traps->has_limits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cairo_traps_clear (cairo_traps_t *traps)
|
||||||
|
{
|
||||||
|
traps->status = CAIRO_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
traps->num_traps = 0;
|
||||||
|
traps->extents.p1.x = traps->extents.p1.y = INT32_MAX;
|
||||||
|
traps->extents.p2.x = traps->extents.p2.y = INT32_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cairo_traps_fini (cairo_traps_t *traps)
|
_cairo_traps_fini (cairo_traps_t *traps)
|
||||||
{
|
{
|
||||||
if (traps->traps && traps->traps != traps->traps_embedded)
|
if (traps->traps != traps->traps_embedded)
|
||||||
free (traps->traps);
|
free (traps->traps);
|
||||||
|
|
||||||
traps->traps = NULL;
|
|
||||||
traps->traps_size = 0;
|
|
||||||
traps->num_traps = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -103,9 +102,9 @@ _cairo_traps_fini (cairo_traps_t *traps)
|
||||||
* Initializes a #cairo_traps_t to contain a single rectangular
|
* Initializes a #cairo_traps_t to contain a single rectangular
|
||||||
* trapezoid.
|
* trapezoid.
|
||||||
**/
|
**/
|
||||||
cairo_status_t
|
void
|
||||||
_cairo_traps_init_box (cairo_traps_t *traps,
|
_cairo_traps_init_box (cairo_traps_t *traps,
|
||||||
cairo_box_t *box)
|
const cairo_box_t *box)
|
||||||
{
|
{
|
||||||
_cairo_traps_init (traps);
|
_cairo_traps_init (traps);
|
||||||
|
|
||||||
|
@ -123,25 +122,41 @@ _cairo_traps_init_box (cairo_traps_t *traps,
|
||||||
traps->traps[0].right.p2 = box->p2;
|
traps->traps[0].right.p2 = box->p2;
|
||||||
|
|
||||||
traps->extents = *box;
|
traps->extents = *box;
|
||||||
|
|
||||||
return traps->status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_status_t
|
/* make room for at least one more trap */
|
||||||
_cairo_traps_status (cairo_traps_t *traps)
|
static cairo_bool_t
|
||||||
|
_cairo_traps_grow (cairo_traps_t *traps)
|
||||||
{
|
{
|
||||||
return traps->status;
|
cairo_trapezoid_t *new_traps;
|
||||||
|
int new_size = 2 * MAX (traps->traps_size, 16);
|
||||||
|
|
||||||
|
if (traps->traps == traps->traps_embedded) {
|
||||||
|
new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t));
|
||||||
|
if (new_traps != NULL)
|
||||||
|
memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded));
|
||||||
|
} else {
|
||||||
|
new_traps = _cairo_realloc_ab (traps->traps,
|
||||||
|
new_size, sizeof (cairo_trapezoid_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_traps == NULL) {
|
||||||
|
traps->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
traps->traps = new_traps;
|
||||||
|
traps->traps_size = new_size;
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
_cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
|
_cairo_traps_add_trap (cairo_traps_t *traps,
|
||||||
|
cairo_fixed_t top, cairo_fixed_t bottom,
|
||||||
cairo_line_t *left, cairo_line_t *right)
|
cairo_line_t *left, cairo_line_t *right)
|
||||||
{
|
{
|
||||||
cairo_trapezoid_t *trap;
|
cairo_trapezoid_t *trap;
|
||||||
|
|
||||||
if (traps->status)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Note: With the goofy trapezoid specification, (where an
|
/* Note: With the goofy trapezoid specification, (where an
|
||||||
* arbitrary two points on the lines can specified for the left
|
* arbitrary two points on the lines can specified for the left
|
||||||
* and right edges), these limit checks would not work in
|
* and right edges), these limit checks would not work in
|
||||||
|
@ -170,6 +185,10 @@ _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bo
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* And reject if the trapezoid is entirely above or below */
|
||||||
|
if (top > traps->limits.p2.y || bottom < traps->limits.p1.y)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Otherwise, clip the trapezoid to the limits. We only clip
|
/* Otherwise, clip the trapezoid to the limits. We only clip
|
||||||
* where an edge is entirely outside the limits. If we wanted
|
* where an edge is entirely outside the limits. If we wanted
|
||||||
* to be more clever, we could handle cases where a trapezoid
|
* to be more clever, we could handle cases where a trapezoid
|
||||||
|
@ -182,28 +201,34 @@ _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bo
|
||||||
if (bottom > traps->limits.p2.y)
|
if (bottom > traps->limits.p2.y)
|
||||||
bottom = traps->limits.p2.y;
|
bottom = traps->limits.p2.y;
|
||||||
|
|
||||||
if (left->p1.x < traps->limits.p1.x &&
|
if (left->p1.x <= traps->limits.p1.x &&
|
||||||
left->p2.x < traps->limits.p1.x)
|
left->p2.x <= traps->limits.p1.x)
|
||||||
{
|
{
|
||||||
left->p1.x = traps->limits.p1.x;
|
left->p1.x = traps->limits.p1.x;
|
||||||
left->p2.x = traps->limits.p1.x;
|
left->p2.x = traps->limits.p1.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (right->p1.x > traps->limits.p2.x &&
|
if (right->p1.x >= traps->limits.p2.x &&
|
||||||
right->p2.x > traps->limits.p2.x)
|
right->p2.x >= traps->limits.p2.x)
|
||||||
{
|
{
|
||||||
right->p1.x = traps->limits.p2.x;
|
right->p1.x = traps->limits.p2.x;
|
||||||
right->p2.x = traps->limits.p2.x;
|
right->p2.x = traps->limits.p2.x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (top >= bottom) {
|
/* Trivial discards for empty trapezoids that are likely to be produced
|
||||||
|
* by our tessellators (most notably convex_quad when given a simple
|
||||||
|
* rectangle).
|
||||||
|
*/
|
||||||
|
if (top >= bottom)
|
||||||
|
return;
|
||||||
|
/* cheap colinearity check */
|
||||||
|
if (right->p1.x <= left->p1.x && right->p1.y == left->p1.y &&
|
||||||
|
right->p2.x <= left->p2.x && right->p2.y == left->p2.y)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (traps->num_traps >= traps->traps_size) {
|
if (traps->num_traps == traps->traps_size) {
|
||||||
traps->status = _cairo_traps_grow (traps);
|
if (! _cairo_traps_grow (traps))
|
||||||
if (traps->status)
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,51 +263,6 @@ _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bo
|
||||||
traps->num_traps++;
|
traps->num_traps++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
_cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
|
|
||||||
cairo_point_t left_p1, cairo_point_t left_p2,
|
|
||||||
cairo_point_t right_p1, cairo_point_t right_p2)
|
|
||||||
{
|
|
||||||
cairo_line_t left;
|
|
||||||
cairo_line_t right;
|
|
||||||
|
|
||||||
if (traps->status)
|
|
||||||
return;
|
|
||||||
|
|
||||||
left.p1 = left_p1;
|
|
||||||
left.p2 = left_p2;
|
|
||||||
|
|
||||||
right.p1 = right_p1;
|
|
||||||
right.p2 = right_p2;
|
|
||||||
|
|
||||||
_cairo_traps_add_trap (traps, top, bottom, &left, &right);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make room for at least one more trap */
|
|
||||||
static cairo_status_t
|
|
||||||
_cairo_traps_grow (cairo_traps_t *traps)
|
|
||||||
{
|
|
||||||
cairo_trapezoid_t *new_traps;
|
|
||||||
int new_size = 2 * MAX (traps->traps_size, 16);
|
|
||||||
|
|
||||||
if (traps->traps == traps->traps_embedded) {
|
|
||||||
new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t));
|
|
||||||
if (new_traps)
|
|
||||||
memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded));
|
|
||||||
} else {
|
|
||||||
new_traps = _cairo_realloc_ab (traps->traps,
|
|
||||||
new_size, sizeof (cairo_trapezoid_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new_traps == NULL)
|
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
||||||
|
|
||||||
traps->traps = new_traps;
|
|
||||||
traps->traps_size = new_size;
|
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_compare_point_fixed_by_y (const void *av, const void *bv)
|
_compare_point_fixed_by_y (const void *av, const void *bv)
|
||||||
{
|
{
|
||||||
|
@ -371,7 +351,8 @@ _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
|
||||||
* quadrilateral. We would not benefit from having any distinct
|
* quadrilateral. We would not benefit from having any distinct
|
||||||
* implementation of triangle vs. quadrilateral tessellation here. */
|
* implementation of triangle vs. quadrilateral tessellation here. */
|
||||||
cairo_status_t
|
cairo_status_t
|
||||||
_cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3])
|
_cairo_traps_tessellate_triangle (cairo_traps_t *traps,
|
||||||
|
const cairo_point_t t[3])
|
||||||
{
|
{
|
||||||
cairo_point_t quad[4];
|
cairo_point_t quad[4];
|
||||||
|
|
||||||
|
@ -384,12 +365,33 @@ _cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3])
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_status_t
|
cairo_status_t
|
||||||
_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
|
_cairo_traps_tessellate_rectangle (cairo_traps_t *traps,
|
||||||
|
const cairo_point_t *top_left,
|
||||||
|
const cairo_point_t *bottom_right)
|
||||||
|
{
|
||||||
|
cairo_line_t left;
|
||||||
|
cairo_line_t right;
|
||||||
|
|
||||||
|
left.p1.x = left.p2.x = top_left->x;
|
||||||
|
left.p1.y = right.p1.y = top_left->y;
|
||||||
|
right.p1.x = right.p2.x = bottom_right->x;
|
||||||
|
left.p2.y = right.p2.y = bottom_right->y;
|
||||||
|
|
||||||
|
_cairo_traps_add_trap (traps, top_left->y, bottom_right->y, &left, &right);
|
||||||
|
|
||||||
|
return traps->status;
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_status_t
|
||||||
|
_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps,
|
||||||
|
const cairo_point_t q[4])
|
||||||
{
|
{
|
||||||
int a, b, c, d;
|
int a, b, c, d;
|
||||||
int i;
|
int i;
|
||||||
cairo_slope_t ab, ad;
|
cairo_slope_t ab, ad;
|
||||||
cairo_bool_t b_left_of_d;
|
cairo_bool_t b_left_of_d;
|
||||||
|
cairo_line_t left;
|
||||||
|
cairo_line_t right;
|
||||||
|
|
||||||
/* Choose a as a point with minimal y */
|
/* Choose a as a point with minimal y */
|
||||||
a = 0;
|
a = 0;
|
||||||
|
@ -454,15 +456,13 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
|
||||||
* | / \| \ \ c.y d.y cd ad
|
* | / \| \ \ c.y d.y cd ad
|
||||||
* d d d
|
* d d d
|
||||||
*/
|
*/
|
||||||
_cairo_traps_add_trap_from_points (traps,
|
left.p1 = q[a]; left.p2 = q[b];
|
||||||
q[a].y, q[b].y,
|
right.p1 = q[a]; right.p2 = q[d];
|
||||||
q[a], q[b], q[a], q[d]);
|
_cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
|
||||||
_cairo_traps_add_trap_from_points (traps,
|
left.p1 = q[b]; left.p2 = q[c];
|
||||||
q[b].y, q[c].y,
|
_cairo_traps_add_trap (traps, q[b].y, q[c].y, &left, &right);
|
||||||
q[b], q[c], q[a], q[d]);
|
left.p1 = q[c]; left.p2 = q[d];
|
||||||
_cairo_traps_add_trap_from_points (traps,
|
_cairo_traps_add_trap (traps, q[c].y, q[d].y, &left, &right);
|
||||||
q[c].y, q[d].y,
|
|
||||||
q[c], q[d], q[a], q[d]);
|
|
||||||
} else {
|
} else {
|
||||||
/* Y-sort is abcd and b is right of d, (slope(ab) <= slope (ad))
|
/* Y-sort is abcd and b is right of d, (slope(ab) <= slope (ad))
|
||||||
*
|
*
|
||||||
|
@ -474,15 +474,13 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
|
||||||
* / / |/ \ | c.y d.y ad cd
|
* / / |/ \ | c.y d.y ad cd
|
||||||
* d d d
|
* d d d
|
||||||
*/
|
*/
|
||||||
_cairo_traps_add_trap_from_points (traps,
|
left.p1 = q[a]; left.p2 = q[d];
|
||||||
q[a].y, q[b].y,
|
right.p1 = q[a]; right.p2 = q[b];
|
||||||
q[a], q[d], q[a], q[b]);
|
_cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
|
||||||
_cairo_traps_add_trap_from_points (traps,
|
right.p1 = q[b]; right.p2 = q[c];
|
||||||
q[b].y, q[c].y,
|
_cairo_traps_add_trap (traps, q[b].y, q[c].y, &left, &right);
|
||||||
q[a], q[d], q[b], q[c]);
|
right.p1 = q[c]; right.p2 = q[d];
|
||||||
_cairo_traps_add_trap_from_points (traps,
|
_cairo_traps_add_trap (traps, q[c].y, q[d].y, &left, &right);
|
||||||
q[c].y, q[d].y,
|
|
||||||
q[a], q[d], q[c], q[d]);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (b_left_of_d) {
|
if (b_left_of_d) {
|
||||||
|
@ -496,15 +494,13 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
|
||||||
* // \ / \| d.y c.y bc dc
|
* // \ / \| d.y c.y bc dc
|
||||||
* c c c
|
* c c c
|
||||||
*/
|
*/
|
||||||
_cairo_traps_add_trap_from_points (traps,
|
left.p1 = q[a]; left.p2 = q[b];
|
||||||
q[a].y, q[b].y,
|
right.p1 = q[a]; right.p2 = q[d];
|
||||||
q[a], q[b], q[a], q[d]);
|
_cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
|
||||||
_cairo_traps_add_trap_from_points (traps,
|
left.p1 = q[b]; left.p2 = q[c];
|
||||||
q[b].y, q[d].y,
|
_cairo_traps_add_trap (traps, q[b].y, q[d].y, &left, &right);
|
||||||
q[b], q[c], q[a], q[d]);
|
right.p1 = q[d]; right.p2 = q[c];
|
||||||
_cairo_traps_add_trap_from_points (traps,
|
_cairo_traps_add_trap (traps, q[d].y, q[c].y, &left, &right);
|
||||||
q[d].y, q[c].y,
|
|
||||||
q[b], q[c], q[d], q[c]);
|
|
||||||
} else {
|
} else {
|
||||||
/* Y-sort is abdc and b is right of d, (slope (ab) <= slope (ad))
|
/* Y-sort is abdc and b is right of d, (slope (ab) <= slope (ad))
|
||||||
*
|
*
|
||||||
|
@ -516,15 +512,13 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
|
||||||
* |/ \ / \\ d.y c.y dc bc
|
* |/ \ / \\ d.y c.y dc bc
|
||||||
* c c c
|
* c c c
|
||||||
*/
|
*/
|
||||||
_cairo_traps_add_trap_from_points (traps,
|
left.p1 = q[a]; left.p2 = q[d];
|
||||||
q[a].y, q[b].y,
|
right.p1 = q[a]; right.p2 = q[b];
|
||||||
q[a], q[d], q[a], q[b]);
|
_cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
|
||||||
_cairo_traps_add_trap_from_points (traps,
|
right.p1 = q[b]; right.p2 = q[c];
|
||||||
q[b].y, q[d].y,
|
_cairo_traps_add_trap (traps, q[b].y, q[d].y, &left, &right);
|
||||||
q[a], q[d], q[b], q[c]);
|
left.p1 = q[d]; left.p2 = q[c];
|
||||||
_cairo_traps_add_trap_from_points (traps,
|
_cairo_traps_add_trap (traps, q[d].y, q[c].y, &left, &right);
|
||||||
q[d].y, q[c].y,
|
|
||||||
q[d], q[c], q[b], q[c]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -581,8 +575,21 @@ _cairo_traps_extents (const cairo_traps_t *traps,
|
||||||
if (traps->num_traps == 0) {
|
if (traps->num_traps == 0) {
|
||||||
extents->p1.x = extents->p1.y = _cairo_fixed_from_int (0);
|
extents->p1.x = extents->p1.y = _cairo_fixed_from_int (0);
|
||||||
extents->p2.x = extents->p2.y = _cairo_fixed_from_int (0);
|
extents->p2.x = extents->p2.y = _cairo_fixed_from_int (0);
|
||||||
} else
|
} else {
|
||||||
*extents = traps->extents;
|
*extents = traps->extents;
|
||||||
|
if (traps->has_limits) {
|
||||||
|
/* clip the traps to the imposed limits */
|
||||||
|
if (extents->p1.x < traps->limits.p1.x)
|
||||||
|
extents->p1.x = traps->limits.p1.x;
|
||||||
|
if (extents->p2.x > traps->limits.p2.x)
|
||||||
|
extents->p2.x = traps->limits.p2.x;
|
||||||
|
|
||||||
|
if (extents->p1.y < traps->limits.p1.y)
|
||||||
|
extents->p1.y = traps->limits.p1.y;
|
||||||
|
if (extents->p2.y > traps->limits.p2.y)
|
||||||
|
extents->p2.y = traps->limits.p2.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1220,6 +1220,12 @@ _cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font,
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
num_segments = be16_to_cpu (map->segCountX2)/2;
|
num_segments = be16_to_cpu (map->segCountX2)/2;
|
||||||
|
|
||||||
|
/* A Format 4 cmap contains 8 uint16_t numbers and 4 arrays of
|
||||||
|
* uint16_t each num_segments long. */
|
||||||
|
if (size < (8 + 4*num_segments)*sizeof(uint16_t))
|
||||||
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
end_code = map->endCount;
|
end_code = map->endCount;
|
||||||
start_code = &(end_code[num_segments + 1]);
|
start_code = &(end_code[num_segments + 1]);
|
||||||
delta = &(start_code[num_segments]);
|
delta = &(start_code[num_segments]);
|
||||||
|
@ -1246,13 +1252,17 @@ _cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font,
|
||||||
uint16_t g_id_be = cpu_to_be16 (index);
|
uint16_t g_id_be = cpu_to_be16 (index);
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
if (range_size > 0)
|
if (range_size > 0) {
|
||||||
|
if ((char*)glyph_ids + 2*range_size > (char*)map + size)
|
||||||
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
for (j = 0; j < range_size; j++) {
|
for (j = 0; j < range_size; j++) {
|
||||||
if (glyph_ids[j] == g_id_be) {
|
if (glyph_ids[j] == g_id_be) {
|
||||||
*ucs4 = be16_to_cpu (start_code[i]) + j;
|
*ucs4 = be16_to_cpu (start_code[i]) + j;
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -444,18 +444,21 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
|
||||||
"2 index /CharStrings %d dict dup begin\n",
|
"2 index /CharStrings %d dict dup begin\n",
|
||||||
font->scaled_font_subset->num_glyphs + 1);
|
font->scaled_font_subset->num_glyphs + 1);
|
||||||
|
|
||||||
|
_cairo_scaled_font_freeze_cache (font->type1_scaled_font);
|
||||||
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
|
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
|
||||||
_cairo_array_truncate (&data, 0);
|
_cairo_array_truncate (&data, 0);
|
||||||
/* four "random" bytes required by encryption algorithm */
|
/* four "random" bytes required by encryption algorithm */
|
||||||
status = _cairo_array_append_multiple (&data, zeros, 4);
|
status = _cairo_array_append_multiple (&data, zeros, 4);
|
||||||
if (status)
|
if (status)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
status = cairo_type1_font_create_charstring (font, i,
|
status = cairo_type1_font_create_charstring (font, i,
|
||||||
font->scaled_font_subset->glyphs[i],
|
font->scaled_font_subset->glyphs[i],
|
||||||
CAIRO_CHARSTRING_TYPE1,
|
CAIRO_CHARSTRING_TYPE1,
|
||||||
&data);
|
&data);
|
||||||
if (status)
|
if (status)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
charstring_encrypt (&data);
|
charstring_encrypt (&data);
|
||||||
length = _cairo_array_num_elements (&data);
|
length = _cairo_array_num_elements (&data);
|
||||||
if (font->scaled_font_subset->glyph_names != NULL) {
|
if (font->scaled_font_subset->glyph_names != NULL) {
|
||||||
|
@ -474,6 +477,7 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
|
||||||
}
|
}
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
_cairo_scaled_font_thaw_cache (font->type1_scaled_font);
|
||||||
_cairo_array_fini (&data);
|
_cairo_array_fini (&data);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -823,6 +827,7 @@ _cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset,
|
||||||
goto fail1;
|
goto fail1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cairo_scaled_font_freeze_cache (font->type1_scaled_font);
|
||||||
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
|
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
|
||||||
_cairo_array_init (&charstring, sizeof (unsigned char));
|
_cairo_array_init (&charstring, sizeof (unsigned char));
|
||||||
status = _cairo_array_grow_by (&charstring, 32);
|
status = _cairo_array_grow_by (&charstring, 32);
|
||||||
|
@ -840,6 +845,7 @@ _cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset,
|
||||||
if (status)
|
if (status)
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
|
_cairo_scaled_font_thaw_cache (font->type1_scaled_font);
|
||||||
|
|
||||||
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
|
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
|
||||||
type2_subset->widths[i] = font->widths[i];
|
type2_subset->widths[i] = font->widths[i];
|
||||||
|
@ -854,6 +860,7 @@ _cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset,
|
||||||
return cairo_type1_font_destroy (font);
|
return cairo_type1_font_destroy (font);
|
||||||
|
|
||||||
fail2:
|
fail2:
|
||||||
|
_cairo_scaled_font_thaw_cache (font->type1_scaled_font);
|
||||||
_cairo_array_fini (&charstring);
|
_cairo_array_fini (&charstring);
|
||||||
_cairo_type2_charstrings_fini (type2_subset);
|
_cairo_type2_charstrings_fini (type2_subset);
|
||||||
fail1:
|
fail1:
|
||||||
|
|
|
@ -61,7 +61,6 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
typedef struct _cairo_type1_font_subset {
|
typedef struct _cairo_type1_font_subset {
|
||||||
|
|
||||||
cairo_scaled_font_subset_t *scaled_font_subset;
|
cairo_scaled_font_subset_t *scaled_font_subset;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -76,7 +75,6 @@ typedef struct _cairo_type1_font_subset {
|
||||||
unsigned long header_size;
|
unsigned long header_size;
|
||||||
unsigned long data_size;
|
unsigned long data_size;
|
||||||
unsigned long trailer_size;
|
unsigned long trailer_size;
|
||||||
|
|
||||||
} base;
|
} base;
|
||||||
|
|
||||||
FT_Face face;
|
FT_Face face;
|
||||||
|
@ -115,15 +113,14 @@ typedef struct _cairo_type1_font_subset {
|
||||||
|
|
||||||
|
|
||||||
static cairo_status_t
|
static cairo_status_t
|
||||||
_cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font,
|
_cairo_type1_font_subset_init (cairo_type1_font_subset_t *font,
|
||||||
cairo_type1_font_subset_t **subset_return,
|
cairo_unscaled_font_t *unscaled_font,
|
||||||
cairo_bool_t hex_encode)
|
cairo_bool_t hex_encode)
|
||||||
{
|
{
|
||||||
cairo_ft_unscaled_font_t *ft_unscaled_font;
|
cairo_ft_unscaled_font_t *ft_unscaled_font;
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
FT_Face face;
|
FT_Face face;
|
||||||
PS_FontInfoRec font_info;
|
PS_FontInfoRec font_info;
|
||||||
cairo_type1_font_subset_t *font;
|
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
ft_unscaled_font = (cairo_ft_unscaled_font_t *) unscaled_font;
|
ft_unscaled_font = (cairo_ft_unscaled_font_t *) unscaled_font;
|
||||||
|
@ -145,12 +142,7 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
font = calloc (sizeof (cairo_type1_font_subset_t), 1);
|
memset (font, 0, sizeof (font));
|
||||||
if (font == NULL) {
|
|
||||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
||||||
goto fail1;
|
|
||||||
}
|
|
||||||
|
|
||||||
font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font);
|
font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font);
|
||||||
font->base.num_glyphs = face->num_glyphs;
|
font->base.num_glyphs = face->num_glyphs;
|
||||||
font->base.x_min = face->bbox.xMin;
|
font->base.x_min = face->bbox.xMin;
|
||||||
|
@ -189,8 +181,6 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font,
|
||||||
|
|
||||||
_cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
|
_cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
|
||||||
|
|
||||||
*subset_return = font;
|
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
|
||||||
fail3:
|
fail3:
|
||||||
|
@ -198,7 +188,6 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font,
|
||||||
free (font->base.base_font);
|
free (font->base.base_font);
|
||||||
fail2:
|
fail2:
|
||||||
_cairo_unscaled_font_destroy (unscaled_font);
|
_cairo_unscaled_font_destroy (unscaled_font);
|
||||||
free (font);
|
|
||||||
fail1:
|
fail1:
|
||||||
_cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
|
_cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
|
||||||
|
|
||||||
|
@ -1225,10 +1214,15 @@ cairo_type1_font_subset_generate (void *abstract_font,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (font->face->stream->read) {
|
if (font->face->stream->read != NULL) {
|
||||||
ret = font->face->stream->read (font->face->stream, 0,
|
/* Note that read() may be implemented as a macro, thanks POSIX!, so we
|
||||||
(unsigned char *) font->type1_data,
|
* need to wrap the following usage in parentheses in order to
|
||||||
font->type1_length);
|
* disambiguate it for the pre-processor - using the verbose function
|
||||||
|
* pointer dereference for clarity.
|
||||||
|
*/
|
||||||
|
ret = (* font->face->stream->read) (font->face->stream, 0,
|
||||||
|
(unsigned char *) font->type1_data,
|
||||||
|
font->type1_length);
|
||||||
if (ret != font->type1_length) {
|
if (ret != font->type1_length) {
|
||||||
status = _cairo_error (CAIRO_STATUS_READ_ERROR);
|
status = _cairo_error (CAIRO_STATUS_READ_ERROR);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -1261,9 +1255,8 @@ cairo_type1_font_subset_generate (void *abstract_font,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cairo_type1_font_subset_destroy (void *abstract_font)
|
_cairo_type1_font_subset_fini (cairo_type1_font_subset_t *font)
|
||||||
{
|
{
|
||||||
cairo_type1_font_subset_t *font = abstract_font;
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
/* If the subset generation failed, some of the pointers below may
|
/* If the subset generation failed, some of the pointers below may
|
||||||
|
@ -1282,17 +1275,15 @@ cairo_type1_font_subset_destroy (void *abstract_font)
|
||||||
if (font->base.base_font)
|
if (font->base.base_font)
|
||||||
free (font->base.base_font);
|
free (font->base.base_font);
|
||||||
free (font->glyphs);
|
free (font->glyphs);
|
||||||
free (font);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cairo_status_t
|
cairo_status_t
|
||||||
_cairo_type1_subset_init (cairo_type1_subset_t *type1_subset,
|
_cairo_type1_subset_init (cairo_type1_subset_t *type1_subset,
|
||||||
const char *name,
|
const char *name,
|
||||||
cairo_scaled_font_subset_t *scaled_font_subset,
|
cairo_scaled_font_subset_t *scaled_font_subset,
|
||||||
cairo_bool_t hex_encode)
|
cairo_bool_t hex_encode)
|
||||||
{
|
{
|
||||||
cairo_type1_font_subset_t *font = NULL; /* hide compiler warning */
|
cairo_type1_font_subset_t font;
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
unsigned long parent_glyph, length;
|
unsigned long parent_glyph, length;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
@ -1308,21 +1299,21 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset,
|
||||||
|
|
||||||
unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font);
|
unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font);
|
||||||
|
|
||||||
status = _cairo_type1_font_subset_create (unscaled_font, &font, hex_encode);
|
status = _cairo_type1_font_subset_init (&font, unscaled_font, hex_encode);
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
for (i = 0; i < scaled_font_subset->num_glyphs; i++) {
|
for (i = 0; i < scaled_font_subset->num_glyphs; i++) {
|
||||||
parent_glyph = scaled_font_subset->glyphs[i];
|
parent_glyph = scaled_font_subset->glyphs[i];
|
||||||
cairo_type1_font_subset_use_glyph (font, parent_glyph);
|
cairo_type1_font_subset_use_glyph (&font, parent_glyph);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = cairo_type1_font_subset_generate (font, name);
|
status = cairo_type1_font_subset_generate (&font, name);
|
||||||
if (status)
|
if (status)
|
||||||
goto fail1;
|
goto fail1;
|
||||||
|
|
||||||
if (font->base.base_font) {
|
if (font.base.base_font) {
|
||||||
type1_subset->base_font = strdup (font->base.base_font);
|
type1_subset->base_font = strdup (font.base.base_font);
|
||||||
} else {
|
} else {
|
||||||
snprintf(buf, sizeof (buf), "CairoFont-%u-%u",
|
snprintf(buf, sizeof (buf), "CairoFont-%u-%u",
|
||||||
scaled_font_subset->font_id, scaled_font_subset->subset_id);
|
scaled_font_subset->font_id, scaled_font_subset->subset_id);
|
||||||
|
@ -1331,37 +1322,38 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset,
|
||||||
if (type1_subset->base_font == NULL)
|
if (type1_subset->base_font == NULL)
|
||||||
goto fail1;
|
goto fail1;
|
||||||
|
|
||||||
type1_subset->widths = calloc (sizeof (int), font->num_glyphs);
|
type1_subset->widths = calloc (sizeof (int), font.num_glyphs);
|
||||||
if (type1_subset->widths == NULL)
|
if (type1_subset->widths == NULL)
|
||||||
goto fail2;
|
goto fail2;
|
||||||
for (i = 0; i < font->base.num_glyphs; i++) {
|
for (i = 0; i < font.base.num_glyphs; i++) {
|
||||||
if (font->glyphs[i].subset_index < 0)
|
if (font.glyphs[i].subset_index < 0)
|
||||||
continue;
|
continue;
|
||||||
type1_subset->widths[font->glyphs[i].subset_index] =
|
type1_subset->widths[font.glyphs[i].subset_index] =
|
||||||
font->glyphs[i].width;
|
font.glyphs[i].width;
|
||||||
}
|
}
|
||||||
|
|
||||||
type1_subset->x_min = font->base.x_min;
|
type1_subset->x_min = font.base.x_min;
|
||||||
type1_subset->y_min = font->base.y_min;
|
type1_subset->y_min = font.base.y_min;
|
||||||
type1_subset->x_max = font->base.x_max;
|
type1_subset->x_max = font.base.x_max;
|
||||||
type1_subset->y_max = font->base.y_max;
|
type1_subset->y_max = font.base.y_max;
|
||||||
type1_subset->ascent = font->base.ascent;
|
type1_subset->ascent = font.base.ascent;
|
||||||
type1_subset->descent = font->base.descent;
|
type1_subset->descent = font.base.descent;
|
||||||
|
|
||||||
length = font->base.header_size + font->base.data_size +
|
length = font.base.header_size +
|
||||||
font->base.trailer_size;
|
font.base.data_size +
|
||||||
|
font.base.trailer_size;
|
||||||
type1_subset->data = malloc (length);
|
type1_subset->data = malloc (length);
|
||||||
if (type1_subset->data == NULL)
|
if (type1_subset->data == NULL)
|
||||||
goto fail3;
|
goto fail3;
|
||||||
|
|
||||||
memcpy (type1_subset->data,
|
memcpy (type1_subset->data,
|
||||||
_cairo_array_index (&font->contents, 0), length);
|
_cairo_array_index (&font.contents, 0), length);
|
||||||
|
|
||||||
type1_subset->header_length = font->base.header_size;
|
type1_subset->header_length = font.base.header_size;
|
||||||
type1_subset->data_length = font->base.data_size;
|
type1_subset->data_length = font.base.data_size;
|
||||||
type1_subset->trailer_length = font->base.trailer_size;
|
type1_subset->trailer_length = font.base.trailer_size;
|
||||||
|
|
||||||
cairo_type1_font_subset_destroy (font);
|
_cairo_type1_font_subset_fini (&font);
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
@ -1370,7 +1362,7 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset,
|
||||||
fail2:
|
fail2:
|
||||||
free (type1_subset->base_font);
|
free (type1_subset->base_font);
|
||||||
fail1:
|
fail1:
|
||||||
cairo_type1_font_subset_destroy (font);
|
_cairo_type1_font_subset_fini (&font);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,13 +60,17 @@ typedef struct cairo_type3_glyph_surface {
|
||||||
cairo_private cairo_surface_t *
|
cairo_private cairo_surface_t *
|
||||||
_cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
|
_cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
|
||||||
cairo_output_stream_t *stream,
|
cairo_output_stream_t *stream,
|
||||||
cairo_type3_glyph_surface_emit_image_t emit_image);
|
cairo_type3_glyph_surface_emit_image_t emit_image,
|
||||||
|
cairo_scaled_font_subsets_t *font_subsets);
|
||||||
|
|
||||||
|
cairo_private void
|
||||||
|
_cairo_type3_glyph_surface_set_font_subsets_callback (void *abstract_surface,
|
||||||
|
cairo_pdf_operators_use_font_subset_t use_font_subset,
|
||||||
|
void *closure);
|
||||||
|
|
||||||
cairo_private cairo_status_t
|
cairo_private cairo_status_t
|
||||||
_cairo_type3_glyph_surface_emit_notdef_glyph (void *abstract_surface,
|
_cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface,
|
||||||
cairo_output_stream_t *stream,
|
unsigned long glyph_index);
|
||||||
cairo_box_t *bbox,
|
|
||||||
double *width);
|
|
||||||
|
|
||||||
cairo_private cairo_status_t
|
cairo_private cairo_status_t
|
||||||
_cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
|
_cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
|
||||||
|
|
|
@ -41,13 +41,15 @@
|
||||||
#include "cairo-type3-glyph-surface-private.h"
|
#include "cairo-type3-glyph-surface-private.h"
|
||||||
#include "cairo-output-stream-private.h"
|
#include "cairo-output-stream-private.h"
|
||||||
#include "cairo-meta-surface-private.h"
|
#include "cairo-meta-surface-private.h"
|
||||||
|
#include "cairo-analysis-surface-private.h"
|
||||||
|
|
||||||
static const cairo_surface_backend_t cairo_type3_glyph_surface_backend;
|
static const cairo_surface_backend_t cairo_type3_glyph_surface_backend;
|
||||||
|
|
||||||
cairo_surface_t *
|
cairo_surface_t *
|
||||||
_cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
|
_cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
|
||||||
cairo_output_stream_t *stream,
|
cairo_output_stream_t *stream,
|
||||||
cairo_type3_glyph_surface_emit_image_t emit_image)
|
cairo_type3_glyph_surface_emit_image_t emit_image,
|
||||||
|
cairo_scaled_font_subsets_t *font_subsets)
|
||||||
{
|
{
|
||||||
cairo_type3_glyph_surface_t *surface;
|
cairo_type3_glyph_surface_t *surface;
|
||||||
cairo_matrix_t invert_y_axis;
|
cairo_matrix_t invert_y_axis;
|
||||||
|
@ -74,7 +76,7 @@ _cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
|
||||||
_cairo_pdf_operators_init (&surface->pdf_operators,
|
_cairo_pdf_operators_init (&surface->pdf_operators,
|
||||||
surface->stream,
|
surface->stream,
|
||||||
&surface->cairo_to_pdf,
|
&surface->cairo_to_pdf,
|
||||||
NULL);
|
font_subsets);
|
||||||
|
|
||||||
return &surface->base;
|
return &surface->base;
|
||||||
}
|
}
|
||||||
|
@ -263,10 +265,37 @@ _cairo_type3_glyph_surface_show_glyphs (void *abstract_surface,
|
||||||
cairo_scaled_font_t *scaled_font,
|
cairo_scaled_font_t *scaled_font,
|
||||||
int *remaining_glyphs)
|
int *remaining_glyphs)
|
||||||
{
|
{
|
||||||
/* XXX: Some refactoring is required before we can add font
|
cairo_type3_glyph_surface_t *surface = abstract_surface;
|
||||||
* subsets in the middle of emitting all the subsets. */
|
cairo_int_status_t status;
|
||||||
|
cairo_scaled_font_t *font;
|
||||||
|
cairo_matrix_t new_ctm, ctm_inverse;
|
||||||
|
int i;
|
||||||
|
|
||||||
return CAIRO_INT_STATUS_IMAGE_FALLBACK;
|
for (i = 0; i < num_glyphs; i++)
|
||||||
|
cairo_matrix_transform_point (&surface->cairo_to_pdf, &glyphs[i].x, &glyphs[i].y);
|
||||||
|
|
||||||
|
/* We require the matrix to be invertable. */
|
||||||
|
ctm_inverse = scaled_font->ctm;
|
||||||
|
status = cairo_matrix_invert (&ctm_inverse);
|
||||||
|
if (status)
|
||||||
|
return CAIRO_INT_STATUS_IMAGE_FALLBACK;
|
||||||
|
|
||||||
|
cairo_matrix_multiply (&new_ctm, &scaled_font->ctm, &ctm_inverse);
|
||||||
|
font = cairo_scaled_font_create (scaled_font->font_face,
|
||||||
|
&scaled_font->font_matrix,
|
||||||
|
&new_ctm,
|
||||||
|
&scaled_font->options);
|
||||||
|
|
||||||
|
status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
|
||||||
|
NULL, 0,
|
||||||
|
glyphs, num_glyphs,
|
||||||
|
NULL, 0,
|
||||||
|
FALSE,
|
||||||
|
font);
|
||||||
|
|
||||||
|
cairo_scaled_font_destroy (font);
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const cairo_surface_backend_t cairo_type3_glyph_surface_backend = {
|
static const cairo_surface_backend_t cairo_type3_glyph_surface_backend = {
|
||||||
|
@ -316,7 +345,7 @@ _cairo_type3_glyph_surface_emit_fallback_image (cairo_type3_glyph_surface_t *sur
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
cairo_image_surface_t *image;
|
cairo_image_surface_t *image;
|
||||||
cairo_matrix_t mat;
|
cairo_matrix_t mat;
|
||||||
double width, height, x, y;
|
double x, y;
|
||||||
|
|
||||||
status = _cairo_scaled_glyph_lookup (surface->scaled_font,
|
status = _cairo_scaled_glyph_lookup (surface->scaled_font,
|
||||||
glyph_index,
|
glyph_index,
|
||||||
|
@ -332,14 +361,10 @@ _cairo_type3_glyph_surface_emit_fallback_image (cairo_type3_glyph_surface_t *sur
|
||||||
|
|
||||||
x = _cairo_fixed_to_double (scaled_glyph->bbox.p1.x);
|
x = _cairo_fixed_to_double (scaled_glyph->bbox.p1.x);
|
||||||
y = _cairo_fixed_to_double (scaled_glyph->bbox.p2.y);
|
y = _cairo_fixed_to_double (scaled_glyph->bbox.p2.y);
|
||||||
width = _cairo_fixed_to_double (scaled_glyph->bbox.p2.x) -
|
mat.xx = image->width;
|
||||||
_cairo_fixed_to_double (scaled_glyph->bbox.p1.x);
|
|
||||||
height = _cairo_fixed_to_double (scaled_glyph->bbox.p2.y) -
|
|
||||||
_cairo_fixed_to_double (scaled_glyph->bbox.p1.y);
|
|
||||||
mat.xx = width;
|
|
||||||
mat.xy = 0;
|
mat.xy = 0;
|
||||||
mat.yx = 0;
|
mat.yx = 0;
|
||||||
mat.yy = height;
|
mat.yy = image->height;
|
||||||
mat.x0 = x;
|
mat.x0 = x;
|
||||||
mat.y0 = y;
|
mat.y0 = y;
|
||||||
cairo_matrix_multiply (&mat, &mat, &surface->scaled_font->scale_inverse);
|
cairo_matrix_multiply (&mat, &mat, &surface->scaled_font->scale_inverse);
|
||||||
|
@ -348,20 +373,65 @@ _cairo_type3_glyph_surface_emit_fallback_image (cairo_type3_glyph_surface_t *sur
|
||||||
return _cairo_type3_glyph_surface_emit_image (surface, image, &mat);
|
return _cairo_type3_glyph_surface_emit_image (surface, image, &mat);
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_status_t
|
void
|
||||||
_cairo_type3_glyph_surface_emit_notdef_glyph (void *abstract_surface,
|
_cairo_type3_glyph_surface_set_font_subsets_callback (void *abstract_surface,
|
||||||
cairo_output_stream_t *stream,
|
cairo_pdf_operators_use_font_subset_t use_font_subset,
|
||||||
cairo_box_t *bbox,
|
void *closure)
|
||||||
double *width)
|
|
||||||
{
|
{
|
||||||
bbox->p1.x = 0;
|
cairo_type3_glyph_surface_t *surface = abstract_surface;
|
||||||
bbox->p1.y = 0;
|
|
||||||
bbox->p2.x = 0;
|
|
||||||
bbox->p2.y = 0;
|
|
||||||
*width = 0.0;
|
|
||||||
_cairo_output_stream_printf (stream, "0 0 0 0 0 0 d1\n");
|
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
_cairo_pdf_operators_set_font_subsets_callback (&surface->pdf_operators,
|
||||||
|
use_font_subset,
|
||||||
|
closure);
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_status_t
|
||||||
|
_cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface,
|
||||||
|
unsigned long glyph_index)
|
||||||
|
{
|
||||||
|
cairo_type3_glyph_surface_t *surface = abstract_surface;
|
||||||
|
cairo_scaled_glyph_t *scaled_glyph;
|
||||||
|
cairo_status_t status, status2;
|
||||||
|
cairo_output_stream_t *null_stream;
|
||||||
|
|
||||||
|
null_stream = _cairo_null_stream_create ();
|
||||||
|
_cairo_type3_glyph_surface_set_stream (surface, null_stream);
|
||||||
|
|
||||||
|
_cairo_scaled_font_freeze_cache (surface->scaled_font);
|
||||||
|
status = _cairo_scaled_glyph_lookup (surface->scaled_font,
|
||||||
|
glyph_index,
|
||||||
|
CAIRO_SCALED_GLYPH_INFO_METRICS |
|
||||||
|
CAIRO_SCALED_GLYPH_INFO_META_SURFACE,
|
||||||
|
&scaled_glyph);
|
||||||
|
|
||||||
|
if (_cairo_status_is_error (status))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||||
|
status = CAIRO_STATUS_SUCCESS;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = _cairo_meta_surface_replay (scaled_glyph->meta_surface,
|
||||||
|
&surface->base);
|
||||||
|
if (status)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
status2 = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||||
|
if (status == CAIRO_STATUS_SUCCESS)
|
||||||
|
status = status2;
|
||||||
|
|
||||||
|
if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK)
|
||||||
|
status = CAIRO_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
_cairo_scaled_font_thaw_cache (surface->scaled_font);
|
||||||
|
|
||||||
|
status2 = _cairo_output_stream_destroy (null_stream);
|
||||||
|
if (status == CAIRO_STATUS_SUCCESS)
|
||||||
|
status = status2;
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_status_t
|
cairo_status_t
|
||||||
|
@ -379,23 +449,24 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
|
||||||
cairo_matrix_t font_matrix_inverse;
|
cairo_matrix_t font_matrix_inverse;
|
||||||
|
|
||||||
_cairo_type3_glyph_surface_set_stream (surface, stream);
|
_cairo_type3_glyph_surface_set_stream (surface, stream);
|
||||||
|
|
||||||
|
_cairo_scaled_font_freeze_cache (surface->scaled_font);
|
||||||
status = _cairo_scaled_glyph_lookup (surface->scaled_font,
|
status = _cairo_scaled_glyph_lookup (surface->scaled_font,
|
||||||
glyph_index,
|
glyph_index,
|
||||||
CAIRO_SCALED_GLYPH_INFO_METRICS |
|
CAIRO_SCALED_GLYPH_INFO_METRICS |
|
||||||
CAIRO_SCALED_GLYPH_INFO_META_SURFACE,
|
CAIRO_SCALED_GLYPH_INFO_META_SURFACE,
|
||||||
&scaled_glyph);
|
&scaled_glyph);
|
||||||
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||||
status = _cairo_scaled_glyph_lookup (surface->scaled_font,
|
status = _cairo_scaled_glyph_lookup (surface->scaled_font,
|
||||||
glyph_index,
|
glyph_index,
|
||||||
CAIRO_SCALED_GLYPH_INFO_METRICS,
|
CAIRO_SCALED_GLYPH_INFO_METRICS,
|
||||||
&scaled_glyph);
|
&scaled_glyph);
|
||||||
if (status)
|
if (status == CAIRO_STATUS_SUCCESS)
|
||||||
return status;
|
status = CAIRO_INT_STATUS_IMAGE_FALLBACK;
|
||||||
|
}
|
||||||
status = CAIRO_INT_STATUS_IMAGE_FALLBACK;
|
if (_cairo_status_is_error (status)) {
|
||||||
|
_cairo_scaled_font_thaw_cache (surface->scaled_font);
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
x_advance = scaled_glyph->metrics.x_advance;
|
x_advance = scaled_glyph->metrics.x_advance;
|
||||||
|
@ -429,7 +500,12 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
|
||||||
|
|
||||||
_cairo_output_stream_printf (surface->stream, "q\n");
|
_cairo_output_stream_printf (surface->stream, "q\n");
|
||||||
status = _cairo_meta_surface_replay (scaled_glyph->meta_surface,
|
status = _cairo_meta_surface_replay (scaled_glyph->meta_surface,
|
||||||
&surface->base);
|
&surface->base);
|
||||||
|
|
||||||
|
status2 = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||||
|
if (status == CAIRO_STATUS_SUCCESS)
|
||||||
|
status = status2;
|
||||||
|
|
||||||
_cairo_output_stream_printf (surface->stream, "Q\n");
|
_cairo_output_stream_printf (surface->stream, "Q\n");
|
||||||
|
|
||||||
_cairo_type3_glyph_surface_set_stream (surface, stream);
|
_cairo_type3_glyph_surface_set_stream (surface, stream);
|
||||||
|
@ -437,13 +513,15 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
|
||||||
_cairo_memory_stream_copy (mem_stream, stream);
|
_cairo_memory_stream_copy (mem_stream, stream);
|
||||||
|
|
||||||
status2 = _cairo_output_stream_destroy (mem_stream);
|
status2 = _cairo_output_stream_destroy (mem_stream);
|
||||||
if (status2)
|
if (status == CAIRO_STATUS_SUCCESS)
|
||||||
return status2;
|
status = status2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK)
|
if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK)
|
||||||
status = _cairo_type3_glyph_surface_emit_fallback_image (surface, glyph_index);
|
status = _cairo_type3_glyph_surface_emit_fallback_image (surface, glyph_index);
|
||||||
|
|
||||||
|
_cairo_scaled_font_thaw_cache (surface->scaled_font);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,6 @@
|
||||||
#ifndef CAIRO_TYPES_PRIVATE_H
|
#ifndef CAIRO_TYPES_PRIVATE_H
|
||||||
#define CAIRO_TYPES_PRIVATE_H
|
#define CAIRO_TYPES_PRIVATE_H
|
||||||
|
|
||||||
/* This is the only header file not including cairoint.h. It only contains
|
|
||||||
* typedefs.*/
|
|
||||||
#include "cairo.h"
|
#include "cairo.h"
|
||||||
#include "cairo-fixed-type-private.h"
|
#include "cairo-fixed-type-private.h"
|
||||||
|
|
||||||
|
@ -118,7 +116,6 @@ struct _cairo_array {
|
||||||
struct _cairo_font_options {
|
struct _cairo_font_options {
|
||||||
cairo_antialias_t antialias;
|
cairo_antialias_t antialias;
|
||||||
cairo_subpixel_order_t subpixel_order;
|
cairo_subpixel_order_t subpixel_order;
|
||||||
cairo_lcd_filter_t lcd_filter;
|
|
||||||
cairo_hint_style_t hint_style;
|
cairo_hint_style_t hint_style;
|
||||||
cairo_hint_metrics_t hint_metrics;
|
cairo_hint_metrics_t hint_metrics;
|
||||||
};
|
};
|
||||||
|
@ -134,6 +131,24 @@ struct _cairo_cache {
|
||||||
int freeze_count;
|
int freeze_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* XXX: Right now, the _cairo_color structure puts unpremultiplied
|
||||||
|
color in the doubles and premultiplied color in the shorts. Yes,
|
||||||
|
this is crazy insane, (but at least we don't export this
|
||||||
|
madness). I'm still working on a cleaner API, but in the meantime,
|
||||||
|
at least this does prevent precision loss in color when changing
|
||||||
|
alpha. */
|
||||||
|
struct _cairo_color {
|
||||||
|
double red;
|
||||||
|
double green;
|
||||||
|
double blue;
|
||||||
|
double alpha;
|
||||||
|
|
||||||
|
unsigned short red_short;
|
||||||
|
unsigned short green_short;
|
||||||
|
unsigned short blue_short;
|
||||||
|
unsigned short alpha_short;
|
||||||
|
};
|
||||||
|
|
||||||
typedef enum _cairo_paginated_mode {
|
typedef enum _cairo_paginated_mode {
|
||||||
CAIRO_PAGINATED_MODE_ANALYZE, /* analyze page regions */
|
CAIRO_PAGINATED_MODE_ANALYZE, /* analyze page regions */
|
||||||
CAIRO_PAGINATED_MODE_RENDER, /* render page contents */
|
CAIRO_PAGINATED_MODE_RENDER, /* render page contents */
|
||||||
|
|
|
@ -230,7 +230,7 @@ _cairo_utf8_get_char_validated (const char *p,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _cairo_utf8_to_utf32:
|
* _cairo_utf8_to_ucs4:
|
||||||
* @str: an UTF-8 string
|
* @str: an UTF-8 string
|
||||||
* @len: length of @str in bytes, or -1 if it is nul-terminated.
|
* @len: length of @str in bytes, or -1 if it is nul-terminated.
|
||||||
* If @len is supplied and the string has an embedded nul
|
* If @len is supplied and the string has an embedded nul
|
||||||
|
@ -247,7 +247,7 @@ _cairo_utf8_get_char_validated (const char *p,
|
||||||
*
|
*
|
||||||
* Return value: %CAIRO_STATUS_SUCCESS if the entire string was
|
* Return value: %CAIRO_STATUS_SUCCESS if the entire string was
|
||||||
* successfully converted. %CAIRO_STATUS_INVALID_STRING if an
|
* successfully converted. %CAIRO_STATUS_INVALID_STRING if an
|
||||||
* an invalid sequence was found.
|
* invalid sequence was found.
|
||||||
**/
|
**/
|
||||||
cairo_status_t
|
cairo_status_t
|
||||||
_cairo_utf8_to_ucs4 (const char *str,
|
_cairo_utf8_to_ucs4 (const char *str,
|
||||||
|
@ -302,6 +302,8 @@ _cairo_utf8_to_ucs4 (const char *str,
|
||||||
* @utf8: buffer to write utf8 string into. Must have at least 4 bytes
|
* @utf8: buffer to write utf8 string into. Must have at least 4 bytes
|
||||||
* space available. Or %NULL.
|
* space available. Or %NULL.
|
||||||
*
|
*
|
||||||
|
* This space left intentionally blank.
|
||||||
|
*
|
||||||
* Return value: Number of bytes in the utf8 string or 0 if an invalid
|
* Return value: Number of bytes in the utf8 string or 0 if an invalid
|
||||||
* unicode character
|
* unicode character
|
||||||
**/
|
**/
|
||||||
|
|
|
@ -96,8 +96,6 @@ _cairo_user_scaled_font_create_meta_context (cairo_user_scaled_font_t *scaled_fo
|
||||||
return cr;
|
return cr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const cairo_scaled_font_backend_t cairo_user_scaled_font_backend;
|
|
||||||
|
|
||||||
static cairo_int_status_t
|
static cairo_int_status_t
|
||||||
_cairo_user_scaled_glyph_init (void *abstract_font,
|
_cairo_user_scaled_glyph_init (void *abstract_font,
|
||||||
cairo_scaled_glyph_t *scaled_glyph,
|
cairo_scaled_glyph_t *scaled_glyph,
|
||||||
|
@ -153,9 +151,14 @@ _cairo_user_scaled_glyph_init (void *abstract_font,
|
||||||
null_surface = _cairo_null_surface_create (cairo_surface_get_content (meta_surface));
|
null_surface = _cairo_null_surface_create (cairo_surface_get_content (meta_surface));
|
||||||
analysis_surface = _cairo_analysis_surface_create (null_surface, -1, -1);
|
analysis_surface = _cairo_analysis_surface_create (null_surface, -1, -1);
|
||||||
cairo_surface_destroy (null_surface);
|
cairo_surface_destroy (null_surface);
|
||||||
|
status = analysis_surface->status;
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
_cairo_analysis_surface_set_ctm (analysis_surface, &scaled_font->extent_scale);
|
_cairo_analysis_surface_set_ctm (analysis_surface,
|
||||||
status = _cairo_meta_surface_replay (meta_surface, analysis_surface);
|
&scaled_font->extent_scale);
|
||||||
|
status = _cairo_meta_surface_replay (meta_surface,
|
||||||
|
analysis_surface);
|
||||||
_cairo_analysis_surface_get_bounding_box (analysis_surface, &bbox);
|
_cairo_analysis_surface_get_bounding_box (analysis_surface, &bbox);
|
||||||
cairo_surface_destroy (analysis_surface);
|
cairo_surface_destroy (analysis_surface);
|
||||||
|
|
||||||
|
@ -271,16 +274,16 @@ _cairo_user_ucs4_to_index (void *abstract_font,
|
||||||
}
|
}
|
||||||
|
|
||||||
static cairo_int_status_t
|
static cairo_int_status_t
|
||||||
_cairo_user_text_to_glyphs (void *abstract_font,
|
_cairo_user_text_to_glyphs (void *abstract_font,
|
||||||
double x,
|
double x,
|
||||||
double y,
|
double y,
|
||||||
const char *utf8,
|
const char *utf8,
|
||||||
int utf8_len,
|
int utf8_len,
|
||||||
cairo_glyph_t **glyphs,
|
cairo_glyph_t **glyphs,
|
||||||
int *num_glyphs,
|
int *num_glyphs,
|
||||||
cairo_text_cluster_t **clusters,
|
cairo_text_cluster_t **clusters,
|
||||||
int *num_clusters,
|
int *num_clusters,
|
||||||
cairo_bool_t *backward)
|
cairo_text_cluster_flags_t *cluster_flags)
|
||||||
{
|
{
|
||||||
cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
|
cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
|
@ -290,18 +293,22 @@ _cairo_user_text_to_glyphs (void *abstract_font,
|
||||||
|
|
||||||
if (face->scaled_font_methods.text_to_glyphs) {
|
if (face->scaled_font_methods.text_to_glyphs) {
|
||||||
int i;
|
int i;
|
||||||
|
cairo_glyph_t *orig_glyphs = *glyphs;
|
||||||
int orig_num_glyphs = *num_glyphs;
|
int orig_num_glyphs = *num_glyphs;
|
||||||
|
|
||||||
status = face->scaled_font_methods.text_to_glyphs (&scaled_font->base,
|
status = face->scaled_font_methods.text_to_glyphs (&scaled_font->base,
|
||||||
utf8, utf8_len,
|
utf8, utf8_len,
|
||||||
glyphs, num_glyphs,
|
glyphs, num_glyphs,
|
||||||
clusters, num_clusters,
|
clusters, num_clusters, cluster_flags);
|
||||||
backward);
|
|
||||||
|
|
||||||
if (status != CAIRO_STATUS_SUCCESS)
|
if (status != CAIRO_STATUS_SUCCESS)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
if (*num_glyphs < 0) {
|
if (*num_glyphs < 0) {
|
||||||
|
if (orig_glyphs != *glyphs) {
|
||||||
|
cairo_glyph_free (*glyphs);
|
||||||
|
*glyphs = orig_glyphs;
|
||||||
|
}
|
||||||
*num_glyphs = orig_num_glyphs;
|
*num_glyphs = orig_num_glyphs;
|
||||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
@ -322,16 +329,79 @@ _cairo_user_text_to_glyphs (void *abstract_font,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const cairo_scaled_font_backend_t cairo_user_scaled_font_backend = {
|
static cairo_status_t
|
||||||
|
_cairo_user_font_face_scaled_font_create (void *abstract_face,
|
||||||
|
const cairo_matrix_t *font_matrix,
|
||||||
|
const cairo_matrix_t *ctm,
|
||||||
|
const cairo_font_options_t *options,
|
||||||
|
cairo_scaled_font_t **scaled_font);
|
||||||
|
|
||||||
|
static cairo_status_t
|
||||||
|
_cairo_user_scaled_font_get_implementation (cairo_toy_font_face_t *toy_face,
|
||||||
|
cairo_font_face_t **font_face_out)
|
||||||
|
{
|
||||||
|
static cairo_user_data_key_t twin_font_face_key;
|
||||||
|
|
||||||
|
cairo_font_face_t *face;
|
||||||
|
cairo_status_t status;
|
||||||
|
|
||||||
|
face = cairo_font_face_get_user_data (&toy_face->base,
|
||||||
|
&twin_font_face_key);
|
||||||
|
if (!face) {
|
||||||
|
face = _cairo_font_face_twin_create (cairo_toy_font_face_get_slant (&toy_face->base),
|
||||||
|
cairo_toy_font_face_get_weight (&toy_face->base));
|
||||||
|
|
||||||
|
status = cairo_font_face_set_user_data (&toy_face->base,
|
||||||
|
&twin_font_face_key,
|
||||||
|
face,
|
||||||
|
(cairo_destroy_func_t) cairo_font_face_destroy);
|
||||||
|
|
||||||
|
if (status) {
|
||||||
|
cairo_font_face_destroy (face);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*font_face_out = face;
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cairo_status_t
|
||||||
|
_cairo_user_scaled_font_create_toy (cairo_toy_font_face_t *toy_face,
|
||||||
|
const cairo_matrix_t *font_matrix,
|
||||||
|
const cairo_matrix_t *ctm,
|
||||||
|
const cairo_font_options_t *font_options,
|
||||||
|
cairo_scaled_font_t **font)
|
||||||
|
{
|
||||||
|
cairo_font_face_t *face;
|
||||||
|
cairo_status_t status;
|
||||||
|
|
||||||
|
status = _cairo_user_scaled_font_get_implementation (toy_face, &face);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = _cairo_user_font_face_scaled_font_create (face,
|
||||||
|
font_matrix,
|
||||||
|
ctm,
|
||||||
|
font_options,
|
||||||
|
font);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cairo_scaled_font_backend_t _cairo_user_scaled_font_backend = {
|
||||||
CAIRO_FONT_TYPE_USER,
|
CAIRO_FONT_TYPE_USER,
|
||||||
NULL, /* create_toy */
|
_cairo_user_scaled_font_get_implementation,
|
||||||
|
_cairo_user_scaled_font_create_toy, /* create_toy */
|
||||||
NULL, /* scaled_font_fini */
|
NULL, /* scaled_font_fini */
|
||||||
_cairo_user_scaled_glyph_init,
|
_cairo_user_scaled_glyph_init,
|
||||||
_cairo_user_text_to_glyphs,
|
_cairo_user_text_to_glyphs,
|
||||||
_cairo_user_ucs4_to_index,
|
_cairo_user_ucs4_to_index,
|
||||||
NULL, /* show_glyphs */
|
NULL, /* show_glyphs */
|
||||||
NULL, /* load_truetype_table */
|
NULL, /* load_truetype_table */
|
||||||
NULL, /* map_glyphs_to_unicode */
|
NULL /* index_to_ucs4 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* #cairo_user_font_face_t */
|
/* #cairo_user_font_face_t */
|
||||||
|
@ -352,12 +422,12 @@ _cairo_user_font_face_scaled_font_create (void *abstract_
|
||||||
|
|
||||||
user_scaled_font = malloc (sizeof (cairo_user_scaled_font_t));
|
user_scaled_font = malloc (sizeof (cairo_user_scaled_font_t));
|
||||||
if (user_scaled_font == NULL)
|
if (user_scaled_font == NULL)
|
||||||
return CAIRO_STATUS_NO_MEMORY;
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
|
|
||||||
status = _cairo_scaled_font_init (&user_scaled_font->base,
|
status = _cairo_scaled_font_init (&user_scaled_font->base,
|
||||||
&font_face->base,
|
&font_face->base,
|
||||||
font_matrix, ctm, options,
|
font_matrix, ctm, options,
|
||||||
&cairo_user_scaled_font_backend);
|
&_cairo_user_scaled_font_backend);
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
free (user_scaled_font);
|
free (user_scaled_font);
|
||||||
|
@ -397,29 +467,31 @@ _cairo_user_font_face_scaled_font_create (void *abstract_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == CAIRO_STATUS_SUCCESS && font_face->scaled_font_methods.init != NULL) {
|
if (status == CAIRO_STATUS_SUCCESS &&
|
||||||
|
font_face->scaled_font_methods.init != NULL)
|
||||||
cairo_t *cr;
|
{
|
||||||
|
|
||||||
/* Lock the scaled_font mutex such that user doesn't accidentally try
|
/* Lock the scaled_font mutex such that user doesn't accidentally try
|
||||||
* to use it just yet. */
|
* to use it just yet. */
|
||||||
CAIRO_MUTEX_LOCK (user_scaled_font->base.mutex);
|
CAIRO_MUTEX_LOCK (user_scaled_font->base.mutex);
|
||||||
|
|
||||||
/* Give away fontmap lock such that user-font can use other fonts */
|
/* Give away fontmap lock such that user-font can use other fonts */
|
||||||
_cairo_scaled_font_register_placeholder_and_unlock_font_map (&user_scaled_font->base);
|
status = _cairo_scaled_font_register_placeholder_and_unlock_font_map (&user_scaled_font->base);
|
||||||
|
if (status == CAIRO_STATUS_SUCCESS) {
|
||||||
|
cairo_t *cr;
|
||||||
|
|
||||||
cr = _cairo_user_scaled_font_create_meta_context (user_scaled_font);
|
cr = _cairo_user_scaled_font_create_meta_context (user_scaled_font);
|
||||||
|
|
||||||
status = font_face->scaled_font_methods.init (&user_scaled_font->base,
|
status = font_face->scaled_font_methods.init (&user_scaled_font->base,
|
||||||
cr,
|
cr,
|
||||||
&font_extents);
|
&font_extents);
|
||||||
|
|
||||||
if (status == CAIRO_STATUS_SUCCESS)
|
if (status == CAIRO_STATUS_SUCCESS)
|
||||||
status = cairo_status (cr);
|
status = cairo_status (cr);
|
||||||
|
|
||||||
cairo_destroy (cr);
|
cairo_destroy (cr);
|
||||||
|
|
||||||
_cairo_scaled_font_unregister_placeholder_and_lock_font_map (&user_scaled_font->base);
|
_cairo_scaled_font_unregister_placeholder_and_lock_font_map (&user_scaled_font->base);
|
||||||
|
}
|
||||||
|
|
||||||
CAIRO_MUTEX_UNLOCK (user_scaled_font->base.mutex);
|
CAIRO_MUTEX_UNLOCK (user_scaled_font->base.mutex);
|
||||||
}
|
}
|
||||||
|
@ -427,7 +499,6 @@ _cairo_user_font_face_scaled_font_create (void *abstract_
|
||||||
if (status == CAIRO_STATUS_SUCCESS)
|
if (status == CAIRO_STATUS_SUCCESS)
|
||||||
status = _cairo_scaled_font_set_metrics (&user_scaled_font->base, &font_extents);
|
status = _cairo_scaled_font_set_metrics (&user_scaled_font->base, &font_extents);
|
||||||
|
|
||||||
|
|
||||||
if (status != CAIRO_STATUS_SUCCESS) {
|
if (status != CAIRO_STATUS_SUCCESS) {
|
||||||
_cairo_scaled_font_fini (&user_scaled_font->base);
|
_cairo_scaled_font_fini (&user_scaled_font->base);
|
||||||
free (user_scaled_font);
|
free (user_scaled_font);
|
||||||
|
@ -448,6 +519,7 @@ _cairo_user_font_face_scaled_font_create (void *abstract_
|
||||||
static const cairo_font_face_backend_t _cairo_user_font_face_backend = {
|
static const cairo_font_face_backend_t _cairo_user_font_face_backend = {
|
||||||
CAIRO_FONT_TYPE_USER,
|
CAIRO_FONT_TYPE_USER,
|
||||||
NULL, /* destroy */
|
NULL, /* destroy */
|
||||||
|
NULL, /* direct implementation */
|
||||||
_cairo_user_font_face_scaled_font_create
|
_cairo_user_font_face_scaled_font_create
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -497,6 +569,7 @@ cairo_user_font_face_create (void)
|
||||||
|
|
||||||
return &font_face->base;
|
return &font_face->base;
|
||||||
}
|
}
|
||||||
|
slim_hidden_def(cairo_user_font_face_create);
|
||||||
|
|
||||||
/* User-font method setters */
|
/* User-font method setters */
|
||||||
|
|
||||||
|
@ -520,17 +593,24 @@ void
|
||||||
cairo_user_font_face_set_init_func (cairo_font_face_t *font_face,
|
cairo_user_font_face_set_init_func (cairo_font_face_t *font_face,
|
||||||
cairo_user_scaled_font_init_func_t init_func)
|
cairo_user_scaled_font_init_func_t init_func)
|
||||||
{
|
{
|
||||||
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
|
cairo_user_font_face_t *user_font_face;
|
||||||
|
|
||||||
|
if (font_face->status)
|
||||||
|
return;
|
||||||
|
|
||||||
if (! _cairo_font_face_is_user (font_face)) {
|
if (! _cairo_font_face_is_user (font_face)) {
|
||||||
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
|
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user_font_face = (cairo_user_font_face_t *) font_face;
|
||||||
if (user_font_face->immutable) {
|
if (user_font_face->immutable) {
|
||||||
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
|
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
user_font_face->scaled_font_methods.init = init_func;
|
user_font_face->scaled_font_methods.init = init_func;
|
||||||
}
|
}
|
||||||
|
slim_hidden_def(cairo_user_font_face_set_init_func);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_user_font_face_set_render_glyph_func:
|
* cairo_user_font_face_set_render_glyph_func:
|
||||||
|
@ -555,17 +635,24 @@ void
|
||||||
cairo_user_font_face_set_render_glyph_func (cairo_font_face_t *font_face,
|
cairo_user_font_face_set_render_glyph_func (cairo_font_face_t *font_face,
|
||||||
cairo_user_scaled_font_render_glyph_func_t render_glyph_func)
|
cairo_user_scaled_font_render_glyph_func_t render_glyph_func)
|
||||||
{
|
{
|
||||||
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
|
cairo_user_font_face_t *user_font_face;
|
||||||
|
|
||||||
|
if (font_face->status)
|
||||||
|
return;
|
||||||
|
|
||||||
if (! _cairo_font_face_is_user (font_face)) {
|
if (! _cairo_font_face_is_user (font_face)) {
|
||||||
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
|
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user_font_face = (cairo_user_font_face_t *) font_face;
|
||||||
if (user_font_face->immutable) {
|
if (user_font_face->immutable) {
|
||||||
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
|
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
user_font_face->scaled_font_methods.render_glyph = render_glyph_func;
|
user_font_face->scaled_font_methods.render_glyph = render_glyph_func;
|
||||||
}
|
}
|
||||||
|
slim_hidden_def(cairo_user_font_face_set_render_glyph_func);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_user_font_face_set_text_to_glyphs_func:
|
* cairo_user_font_face_set_text_to_glyphs_func:
|
||||||
|
@ -586,11 +673,17 @@ void
|
||||||
cairo_user_font_face_set_text_to_glyphs_func (cairo_font_face_t *font_face,
|
cairo_user_font_face_set_text_to_glyphs_func (cairo_font_face_t *font_face,
|
||||||
cairo_user_scaled_font_text_to_glyphs_func_t text_to_glyphs_func)
|
cairo_user_scaled_font_text_to_glyphs_func_t text_to_glyphs_func)
|
||||||
{
|
{
|
||||||
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
|
cairo_user_font_face_t *user_font_face;
|
||||||
|
|
||||||
|
if (font_face->status)
|
||||||
|
return;
|
||||||
|
|
||||||
if (! _cairo_font_face_is_user (font_face)) {
|
if (! _cairo_font_face_is_user (font_face)) {
|
||||||
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
|
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user_font_face = (cairo_user_font_face_t *) font_face;
|
||||||
if (user_font_face->immutable) {
|
if (user_font_face->immutable) {
|
||||||
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
|
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
|
||||||
return;
|
return;
|
||||||
|
@ -617,17 +710,23 @@ void
|
||||||
cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t *font_face,
|
cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t *font_face,
|
||||||
cairo_user_scaled_font_unicode_to_glyph_func_t unicode_to_glyph_func)
|
cairo_user_scaled_font_unicode_to_glyph_func_t unicode_to_glyph_func)
|
||||||
{
|
{
|
||||||
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
|
cairo_user_font_face_t *user_font_face;
|
||||||
|
if (font_face->status)
|
||||||
|
return;
|
||||||
|
|
||||||
if (! _cairo_font_face_is_user (font_face)) {
|
if (! _cairo_font_face_is_user (font_face)) {
|
||||||
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
|
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user_font_face = (cairo_user_font_face_t *) font_face;
|
||||||
if (user_font_face->immutable) {
|
if (user_font_face->immutable) {
|
||||||
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
|
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
user_font_face->scaled_font_methods.unicode_to_glyph = unicode_to_glyph_func;
|
user_font_face->scaled_font_methods.unicode_to_glyph = unicode_to_glyph_func;
|
||||||
}
|
}
|
||||||
|
slim_hidden_def(cairo_user_font_face_set_unicode_to_glyph_func);
|
||||||
|
|
||||||
/* User-font method getters */
|
/* User-font method getters */
|
||||||
|
|
||||||
|
@ -638,18 +737,24 @@ cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t
|
||||||
* Gets the scaled-font initialization function of a user-font.
|
* Gets the scaled-font initialization function of a user-font.
|
||||||
*
|
*
|
||||||
* Return value: The init callback of @font_face
|
* Return value: The init callback of @font_face
|
||||||
* or %NULL if none set.
|
* or %NULL if none set or an error has occurred.
|
||||||
*
|
*
|
||||||
* Since: 1.8
|
* Since: 1.8
|
||||||
**/
|
**/
|
||||||
cairo_user_scaled_font_init_func_t
|
cairo_user_scaled_font_init_func_t
|
||||||
cairo_user_font_face_get_init_func (cairo_font_face_t *font_face)
|
cairo_user_font_face_get_init_func (cairo_font_face_t *font_face)
|
||||||
{
|
{
|
||||||
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
|
cairo_user_font_face_t *user_font_face;
|
||||||
|
|
||||||
|
if (font_face->status)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (! _cairo_font_face_is_user (font_face)) {
|
if (! _cairo_font_face_is_user (font_face)) {
|
||||||
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
|
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user_font_face = (cairo_user_font_face_t *) font_face;
|
||||||
return user_font_face->scaled_font_methods.init;
|
return user_font_face->scaled_font_methods.init;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -660,18 +765,24 @@ cairo_user_font_face_get_init_func (cairo_font_face_t *font_face)
|
||||||
* Gets the glyph rendering function of a user-font.
|
* Gets the glyph rendering function of a user-font.
|
||||||
*
|
*
|
||||||
* Return value: The render_glyph callback of @font_face
|
* Return value: The render_glyph callback of @font_face
|
||||||
* or %NULL if none set.
|
* or %NULL if none set or an error has occurred.
|
||||||
*
|
*
|
||||||
* Since: 1.8
|
* Since: 1.8
|
||||||
**/
|
**/
|
||||||
cairo_user_scaled_font_render_glyph_func_t
|
cairo_user_scaled_font_render_glyph_func_t
|
||||||
cairo_user_font_face_get_render_glyph_func (cairo_font_face_t *font_face)
|
cairo_user_font_face_get_render_glyph_func (cairo_font_face_t *font_face)
|
||||||
{
|
{
|
||||||
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
|
cairo_user_font_face_t *user_font_face;
|
||||||
|
|
||||||
|
if (font_face->status)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (! _cairo_font_face_is_user (font_face)) {
|
if (! _cairo_font_face_is_user (font_face)) {
|
||||||
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
|
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user_font_face = (cairo_user_font_face_t *) font_face;
|
||||||
return user_font_face->scaled_font_methods.render_glyph;
|
return user_font_face->scaled_font_methods.render_glyph;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,18 +793,24 @@ cairo_user_font_face_get_render_glyph_func (cairo_font_face_t *font_face)
|
||||||
* Gets the text-to-glyphs conversion function of a user-font.
|
* Gets the text-to-glyphs conversion function of a user-font.
|
||||||
*
|
*
|
||||||
* Return value: The text_to_glyphs callback of @font_face
|
* Return value: The text_to_glyphs callback of @font_face
|
||||||
* or %NULL if none set.
|
* or %NULL if none set or an error occurred.
|
||||||
*
|
*
|
||||||
* Since: 1.8
|
* Since: 1.8
|
||||||
**/
|
**/
|
||||||
cairo_user_scaled_font_text_to_glyphs_func_t
|
cairo_user_scaled_font_text_to_glyphs_func_t
|
||||||
cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face)
|
cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face)
|
||||||
{
|
{
|
||||||
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
|
cairo_user_font_face_t *user_font_face;
|
||||||
|
|
||||||
|
if (font_face->status)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (! _cairo_font_face_is_user (font_face)) {
|
if (! _cairo_font_face_is_user (font_face)) {
|
||||||
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
|
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user_font_face = (cairo_user_font_face_t *) font_face;
|
||||||
return user_font_face->scaled_font_methods.text_to_glyphs;
|
return user_font_face->scaled_font_methods.text_to_glyphs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -704,17 +821,23 @@ cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face)
|
||||||
* Gets the unicode-to-glyph conversion function of a user-font.
|
* Gets the unicode-to-glyph conversion function of a user-font.
|
||||||
*
|
*
|
||||||
* Return value: The unicode_to_glyph callback of @font_face
|
* Return value: The unicode_to_glyph callback of @font_face
|
||||||
* or %NULL if none set.
|
* or %NULL if none set or an error occurred.
|
||||||
*
|
*
|
||||||
* Since: 1.8
|
* Since: 1.8
|
||||||
**/
|
**/
|
||||||
cairo_user_scaled_font_unicode_to_glyph_func_t
|
cairo_user_scaled_font_unicode_to_glyph_func_t
|
||||||
cairo_user_font_face_get_unicode_to_glyph_func (cairo_font_face_t *font_face)
|
cairo_user_font_face_get_unicode_to_glyph_func (cairo_font_face_t *font_face)
|
||||||
{
|
{
|
||||||
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
|
cairo_user_font_face_t *user_font_face;
|
||||||
|
|
||||||
|
if (font_face->status)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (! _cairo_font_face_is_user (font_face)) {
|
if (! _cairo_font_face_is_user (font_face)) {
|
||||||
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
|
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user_font_face = (cairo_user_font_face_t *) font_face;
|
||||||
return user_font_face->scaled_font_methods.unicode_to_glyph;
|
return user_font_face->scaled_font_methods.unicode_to_glyph;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
* as a pair of 32-bit ints
|
* as a pair of 32-bit ints
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define I cairo_private
|
#define I cairo_private cairo_const
|
||||||
|
|
||||||
#if !HAVE_UINT64_T
|
#if !HAVE_UINT64_T
|
||||||
|
|
||||||
|
@ -61,8 +61,10 @@ cairo_uint64_t I _cairo_uint64_lsl (cairo_uint64_t a, int shift);
|
||||||
cairo_uint64_t I _cairo_uint64_rsl (cairo_uint64_t a, int shift);
|
cairo_uint64_t I _cairo_uint64_rsl (cairo_uint64_t a, int shift);
|
||||||
cairo_uint64_t I _cairo_uint64_rsa (cairo_uint64_t a, int shift);
|
cairo_uint64_t I _cairo_uint64_rsa (cairo_uint64_t a, int shift);
|
||||||
int I _cairo_uint64_lt (cairo_uint64_t a, cairo_uint64_t b);
|
int I _cairo_uint64_lt (cairo_uint64_t a, cairo_uint64_t b);
|
||||||
|
int I _cairo_uint64_cmp (cairo_uint64_t a, cairo_uint64_t b);
|
||||||
int I _cairo_uint64_eq (cairo_uint64_t a, cairo_uint64_t b);
|
int I _cairo_uint64_eq (cairo_uint64_t a, cairo_uint64_t b);
|
||||||
cairo_uint64_t I _cairo_uint64_negate (cairo_uint64_t a);
|
cairo_uint64_t I _cairo_uint64_negate (cairo_uint64_t a);
|
||||||
|
#define _cairo_uint64_is_zero(a) ((a).hi == 0 && (a).lo == 0)
|
||||||
#define _cairo_uint64_negative(a) (((int32_t) ((a).hi)) < 0)
|
#define _cairo_uint64_negative(a) (((int32_t) ((a).hi)) < 0)
|
||||||
cairo_uint64_t I _cairo_uint64_not (cairo_uint64_t a);
|
cairo_uint64_t I _cairo_uint64_not (cairo_uint64_t a);
|
||||||
|
|
||||||
|
@ -75,7 +77,9 @@ cairo_int64_t I _cairo_int32_to_int64(int32_t i);
|
||||||
#define _cairo_int64_sub(a,b) _cairo_uint64_sub (a,b)
|
#define _cairo_int64_sub(a,b) _cairo_uint64_sub (a,b)
|
||||||
#define _cairo_int64_mul(a,b) _cairo_uint64_mul (a,b)
|
#define _cairo_int64_mul(a,b) _cairo_uint64_mul (a,b)
|
||||||
cairo_int64_t I _cairo_int32x32_64_mul (int32_t a, int32_t b);
|
cairo_int64_t I _cairo_int32x32_64_mul (int32_t a, int32_t b);
|
||||||
int I _cairo_int64_lt (cairo_uint64_t a, cairo_uint64_t b);
|
int I _cairo_int64_lt (cairo_int64_t a, cairo_int64_t b);
|
||||||
|
int I _cairo_int64_cmp (cairo_int64_t a, cairo_int64_t b);
|
||||||
|
#define _cairo_int64_is_zero(a) _cairo_uint64_is_zero (a)
|
||||||
#define _cairo_int64_eq(a,b) _cairo_uint64_eq (a,b)
|
#define _cairo_int64_eq(a,b) _cairo_uint64_eq (a,b)
|
||||||
#define _cairo_int64_lsl(a,b) _cairo_uint64_lsl (a,b)
|
#define _cairo_int64_lsl(a,b) _cairo_uint64_lsl (a,b)
|
||||||
#define _cairo_int64_rsl(a,b) _cairo_uint64_rsl (a,b)
|
#define _cairo_int64_rsl(a,b) _cairo_uint64_rsl (a,b)
|
||||||
|
@ -96,6 +100,8 @@ int I _cairo_int64_lt (cairo_uint64_t a, cairo_uint64_t b);
|
||||||
#define _cairo_uint64_rsl(a,b) ((uint64_t) (a) >> (b))
|
#define _cairo_uint64_rsl(a,b) ((uint64_t) (a) >> (b))
|
||||||
#define _cairo_uint64_rsa(a,b) ((uint64_t) ((int64_t) (a) >> (b)))
|
#define _cairo_uint64_rsa(a,b) ((uint64_t) ((int64_t) (a) >> (b)))
|
||||||
#define _cairo_uint64_lt(a,b) ((a) < (b))
|
#define _cairo_uint64_lt(a,b) ((a) < (b))
|
||||||
|
#define _cairo_uint64_cmp(a,b) ((a) == (b) ? 0 : (a) < (b) ? -1 : 1)
|
||||||
|
#define _cairo_uint64_is_zero(a) ((a) == 0)
|
||||||
#define _cairo_uint64_eq(a,b) ((a) == (b))
|
#define _cairo_uint64_eq(a,b) ((a) == (b))
|
||||||
#define _cairo_uint64_negate(a) ((uint64_t) -((int64_t) (a)))
|
#define _cairo_uint64_negate(a) ((uint64_t) -((int64_t) (a)))
|
||||||
#define _cairo_uint64_negative(a) ((int64_t) (a) < 0)
|
#define _cairo_uint64_negative(a) ((int64_t) (a) < 0)
|
||||||
|
@ -111,6 +117,8 @@ int I _cairo_int64_lt (cairo_uint64_t a, cairo_uint64_t b);
|
||||||
#define _cairo_int64_mul(a,b) ((a) * (b))
|
#define _cairo_int64_mul(a,b) ((a) * (b))
|
||||||
#define _cairo_int32x32_64_mul(a,b) ((int64_t) (a) * (b))
|
#define _cairo_int32x32_64_mul(a,b) ((int64_t) (a) * (b))
|
||||||
#define _cairo_int64_lt(a,b) ((a) < (b))
|
#define _cairo_int64_lt(a,b) ((a) < (b))
|
||||||
|
#define _cairo_int64_cmp(a,b) ((a) == (b) ? 0 : (a) < (b) ? -1 : 1)
|
||||||
|
#define _cairo_int64_is_zero(a) ((a) == 0)
|
||||||
#define _cairo_int64_eq(a,b) ((a) == (b))
|
#define _cairo_int64_eq(a,b) ((a) == (b))
|
||||||
#define _cairo_int64_lsl(a,b) ((a) << (b))
|
#define _cairo_int64_lsl(a,b) ((a) << (b))
|
||||||
#define _cairo_int64_rsl(a,b) ((int64_t) ((uint64_t) (a) >> (b)))
|
#define _cairo_int64_rsl(a,b) ((int64_t) ((uint64_t) (a) >> (b)))
|
||||||
|
@ -165,7 +173,9 @@ cairo_uint128_t I _cairo_uint128_lsl (cairo_uint128_t a, int shift);
|
||||||
cairo_uint128_t I _cairo_uint128_rsl (cairo_uint128_t a, int shift);
|
cairo_uint128_t I _cairo_uint128_rsl (cairo_uint128_t a, int shift);
|
||||||
cairo_uint128_t I _cairo_uint128_rsa (cairo_uint128_t a, int shift);
|
cairo_uint128_t I _cairo_uint128_rsa (cairo_uint128_t a, int shift);
|
||||||
int I _cairo_uint128_lt (cairo_uint128_t a, cairo_uint128_t b);
|
int I _cairo_uint128_lt (cairo_uint128_t a, cairo_uint128_t b);
|
||||||
|
int I _cairo_uint128_cmp (cairo_uint128_t a, cairo_uint128_t b);
|
||||||
int I _cairo_uint128_eq (cairo_uint128_t a, cairo_uint128_t b);
|
int I _cairo_uint128_eq (cairo_uint128_t a, cairo_uint128_t b);
|
||||||
|
#define _cairo_uint128_is_zero(a) (_cairo_uint64_is_zero ((a).hi) && _cairo_uint64_is_zero ((a).lo))
|
||||||
cairo_uint128_t I _cairo_uint128_negate (cairo_uint128_t a);
|
cairo_uint128_t I _cairo_uint128_negate (cairo_uint128_t a);
|
||||||
#define _cairo_uint128_negative(a) (_cairo_uint64_negative(a.hi))
|
#define _cairo_uint128_negative(a) (_cairo_uint64_negative(a.hi))
|
||||||
cairo_uint128_t I _cairo_uint128_not (cairo_uint128_t a);
|
cairo_uint128_t I _cairo_uint128_not (cairo_uint128_t a);
|
||||||
|
@ -181,10 +191,13 @@ cairo_int128_t I _cairo_int64_to_int128 (cairo_int64_t i);
|
||||||
#define _cairo_int128_sub(a,b) _cairo_uint128_sub(a,b)
|
#define _cairo_int128_sub(a,b) _cairo_uint128_sub(a,b)
|
||||||
#define _cairo_int128_mul(a,b) _cairo_uint128_mul(a,b)
|
#define _cairo_int128_mul(a,b) _cairo_uint128_mul(a,b)
|
||||||
cairo_int128_t I _cairo_int64x64_128_mul (cairo_int64_t a, cairo_int64_t b);
|
cairo_int128_t I _cairo_int64x64_128_mul (cairo_int64_t a, cairo_int64_t b);
|
||||||
|
#define _cairo_int64x32_128_mul(a, b) _cairo_int64x64_128_mul(a, _cairo_int32_to_int64(b))
|
||||||
#define _cairo_int128_lsl(a,b) _cairo_uint128_lsl(a,b)
|
#define _cairo_int128_lsl(a,b) _cairo_uint128_lsl(a,b)
|
||||||
#define _cairo_int128_rsl(a,b) _cairo_uint128_rsl(a,b)
|
#define _cairo_int128_rsl(a,b) _cairo_uint128_rsl(a,b)
|
||||||
#define _cairo_int128_rsa(a,b) _cairo_uint128_rsa(a,b)
|
#define _cairo_int128_rsa(a,b) _cairo_uint128_rsa(a,b)
|
||||||
int I _cairo_int128_lt (cairo_int128_t a, cairo_int128_t b);
|
int I _cairo_int128_lt (cairo_int128_t a, cairo_int128_t b);
|
||||||
|
int I _cairo_int128_cmp (cairo_int128_t a, cairo_int128_t b);
|
||||||
|
#define _cairo_int128_is_zero(a) _cairo_uint128_is_zero (a)
|
||||||
#define _cairo_int128_eq(a,b) _cairo_uint128_eq (a,b)
|
#define _cairo_int128_eq(a,b) _cairo_uint128_eq (a,b)
|
||||||
#define _cairo_int128_negate(a) _cairo_uint128_negate(a)
|
#define _cairo_int128_negate(a) _cairo_uint128_negate(a)
|
||||||
#define _cairo_int128_negative(a) (_cairo_uint128_negative(a))
|
#define _cairo_int128_negative(a) (_cairo_uint128_negative(a))
|
||||||
|
@ -204,6 +217,8 @@ int I _cairo_int128_lt (cairo_int128_t a, cairo_int128_t b);
|
||||||
#define _cairo_uint128_rsl(a,b) ((uint128_t) (a) >> (b))
|
#define _cairo_uint128_rsl(a,b) ((uint128_t) (a) >> (b))
|
||||||
#define _cairo_uint128_rsa(a,b) ((uint128_t) ((int128_t) (a) >> (b)))
|
#define _cairo_uint128_rsa(a,b) ((uint128_t) ((int128_t) (a) >> (b)))
|
||||||
#define _cairo_uint128_lt(a,b) ((a) < (b))
|
#define _cairo_uint128_lt(a,b) ((a) < (b))
|
||||||
|
#define _cairo_uint128_cmp(a,b) ((a) == (b) ? 0 : (a) < (b) ? -1 : 1)
|
||||||
|
#define _cairo_uint128_is_zero(a) ((a) == 0)
|
||||||
#define _cairo_uint128_eq(a,b) ((a) == (b))
|
#define _cairo_uint128_eq(a,b) ((a) == (b))
|
||||||
#define _cairo_uint128_negate(a) ((uint128_t) -((int128_t) (a)))
|
#define _cairo_uint128_negate(a) ((uint128_t) -((int128_t) (a)))
|
||||||
#define _cairo_uint128_negative(a) ((int128_t) (a) < 0)
|
#define _cairo_uint128_negative(a) ((int128_t) (a) < 0)
|
||||||
|
@ -221,6 +236,8 @@ int I _cairo_int128_lt (cairo_int128_t a, cairo_int128_t b);
|
||||||
#define _cairo_int128_mul(a,b) ((a) * (b))
|
#define _cairo_int128_mul(a,b) ((a) * (b))
|
||||||
#define _cairo_int64x64_128_mul(a,b) ((int128_t) (a) * (b))
|
#define _cairo_int64x64_128_mul(a,b) ((int128_t) (a) * (b))
|
||||||
#define _cairo_int128_lt(a,b) ((a) < (b))
|
#define _cairo_int128_lt(a,b) ((a) < (b))
|
||||||
|
#define _cairo_int128_cmp(a,b) ((a) == (b) ? 0 : (a) < (b) ? -1 : 1)
|
||||||
|
#define _cairo_int128_is_zero(a) ((a) == 0)
|
||||||
#define _cairo_int128_eq(a,b) ((a) == (b))
|
#define _cairo_int128_eq(a,b) ((a) == (b))
|
||||||
#define _cairo_int128_lsl(a,b) ((a) << (b))
|
#define _cairo_int128_lsl(a,b) ((a) << (b))
|
||||||
#define _cairo_int128_rsl(a,b) ((int128_t) ((uint128_t) (a) >> (b)))
|
#define _cairo_int128_rsl(a,b) ((int128_t) ((uint128_t) (a) >> (b)))
|
||||||
|
|
|
@ -37,6 +37,8 @@
|
||||||
#ifndef CAIRO_WIDEINT_TYPE_H
|
#ifndef CAIRO_WIDEINT_TYPE_H
|
||||||
#define CAIRO_WIDEINT_TYPE_H
|
#define CAIRO_WIDEINT_TYPE_H
|
||||||
|
|
||||||
|
#include "cairo.h"
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
#if HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -235,6 +235,32 @@ _cairo_int64_lt (cairo_int64_t a, cairo_int64_t b)
|
||||||
return _cairo_uint64_lt (a, b);
|
return _cairo_uint64_lt (a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_cairo_uint64_cmp (cairo_uint64_t a, cairo_uint64_t b)
|
||||||
|
{
|
||||||
|
if (a.hi < b.hi)
|
||||||
|
return -1;
|
||||||
|
else if (a.hi > b.hi)
|
||||||
|
return 1;
|
||||||
|
else if (a.lo < b.lo)
|
||||||
|
return -1;
|
||||||
|
else if (a.lo > b.lo)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_cairo_int64_cmp (cairo_int64_t a, cairo_int64_t b)
|
||||||
|
{
|
||||||
|
if (_cairo_int64_negative (a) && !_cairo_int64_negative (b))
|
||||||
|
return -1;
|
||||||
|
if (!_cairo_int64_negative (a) && _cairo_int64_negative (b))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return _cairo_uint64_cmp (a, b);
|
||||||
|
}
|
||||||
|
|
||||||
cairo_uint64_t
|
cairo_uint64_t
|
||||||
_cairo_uint64_not (cairo_uint64_t a)
|
_cairo_uint64_not (cairo_uint64_t a)
|
||||||
{
|
{
|
||||||
|
@ -569,6 +595,28 @@ _cairo_int128_lt (cairo_int128_t a, cairo_int128_t b)
|
||||||
return _cairo_uint128_lt (a, b);
|
return _cairo_uint128_lt (a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_cairo_uint128_cmp (cairo_uint128_t a, cairo_uint128_t b)
|
||||||
|
{
|
||||||
|
int cmp;
|
||||||
|
|
||||||
|
cmp = _cairo_uint64_cmp (a.hi, b.hi);
|
||||||
|
if (cmp)
|
||||||
|
return cmp;
|
||||||
|
return _cairo_uint64_cmp (a.lo, b.lo);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_cairo_int128_cmp (cairo_int128_t a, cairo_int128_t b)
|
||||||
|
{
|
||||||
|
if (_cairo_int128_negative (a) && !_cairo_int128_negative (b))
|
||||||
|
return -1;
|
||||||
|
if (!_cairo_int128_negative (a) && _cairo_int128_negative (b))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return _cairo_uint128_cmp (a, b);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_cairo_uint128_eq (cairo_uint128_t a, cairo_uint128_t b)
|
_cairo_uint128_eq (cairo_uint128_t a, cairo_uint128_t b)
|
||||||
{
|
{
|
||||||
|
|
|
@ -640,21 +640,25 @@ _cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled
|
||||||
|
|
||||||
if (GetGlyphIndicesW (hdc, utf16, n16, glyph_indices, 0) == GDI_ERROR) {
|
if (GetGlyphIndicesW (hdc, utf16, n16, glyph_indices, 0) == GDI_ERROR) {
|
||||||
status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_type1_text_to_glyphs:GetGlyphIndicesW");
|
status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_type1_text_to_glyphs:GetGlyphIndicesW");
|
||||||
goto FAIL2;
|
goto FAIL3;
|
||||||
}
|
}
|
||||||
|
|
||||||
*num_glyphs = n16;
|
*num_glyphs = n16;
|
||||||
*glyphs = _cairo_malloc_ab (n16, sizeof (cairo_glyph_t));
|
*glyphs = _cairo_malloc_ab (n16, sizeof (cairo_glyph_t));
|
||||||
if (!*glyphs) {
|
if (!*glyphs) {
|
||||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
goto FAIL2;
|
goto FAIL3;
|
||||||
}
|
}
|
||||||
|
|
||||||
x_pos = x;
|
x_pos = x;
|
||||||
y_pos = y;
|
y_pos = y;
|
||||||
|
|
||||||
mat = scaled_font->base.ctm;
|
mat = scaled_font->base.ctm;
|
||||||
status = cairo_matrix_invert (&mat);
|
status = cairo_matrix_invert (&mat);
|
||||||
assert (status == CAIRO_STATUS_SUCCESS);
|
assert (status == CAIRO_STATUS_SUCCESS);
|
||||||
|
|
||||||
|
_cairo_scaled_font_freeze_cache (&scaled_font->base);
|
||||||
|
|
||||||
for (i = 0; i < n16; i++) {
|
for (i = 0; i < n16; i++) {
|
||||||
cairo_scaled_glyph_t *scaled_glyph;
|
cairo_scaled_glyph_t *scaled_glyph;
|
||||||
|
|
||||||
|
@ -668,7 +672,8 @@ _cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled
|
||||||
&scaled_glyph);
|
&scaled_glyph);
|
||||||
if (status) {
|
if (status) {
|
||||||
free (*glyphs);
|
free (*glyphs);
|
||||||
goto FAIL2;
|
*glyphs = NULL;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
x = scaled_glyph->x_advance;
|
x = scaled_glyph->x_advance;
|
||||||
|
@ -678,8 +683,10 @@ _cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled
|
||||||
y_pos += y;
|
y_pos += y;
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_win32_scaled_font_done_font (&scaled_font->base);
|
_cairo_scaled_font_thaw_cache (&scaled_font->base);
|
||||||
|
|
||||||
|
FAIL3:
|
||||||
|
cairo_win32_scaled_font_done_font (&scaled_font->base);
|
||||||
FAIL2:
|
FAIL2:
|
||||||
free (glyph_indices);
|
free (glyph_indices);
|
||||||
FAIL1:
|
FAIL1:
|
||||||
|
@ -1829,6 +1836,7 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font
|
||||||
|
|
||||||
const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend = {
|
const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend = {
|
||||||
CAIRO_FONT_TYPE_WIN32,
|
CAIRO_FONT_TYPE_WIN32,
|
||||||
|
NULL,
|
||||||
_cairo_win32_scaled_font_create_toy,
|
_cairo_win32_scaled_font_create_toy,
|
||||||
_cairo_win32_scaled_font_fini,
|
_cairo_win32_scaled_font_fini,
|
||||||
_cairo_win32_scaled_font_glyph_init,
|
_cairo_win32_scaled_font_glyph_init,
|
||||||
|
@ -1898,6 +1906,7 @@ _cairo_win32_font_face_scaled_font_create (void *abstract_face,
|
||||||
static const cairo_font_face_backend_t _cairo_win32_font_face_backend = {
|
static const cairo_font_face_backend_t _cairo_win32_font_face_backend = {
|
||||||
CAIRO_FONT_TYPE_WIN32,
|
CAIRO_FONT_TYPE_WIN32,
|
||||||
_cairo_win32_font_face_destroy,
|
_cairo_win32_font_face_destroy,
|
||||||
|
NULL, /* direct implementation */
|
||||||
_cairo_win32_font_face_scaled_font_create
|
_cairo_win32_font_face_scaled_font_create
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -490,7 +490,6 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
cairo_extend_t extend;
|
cairo_extend_t extend;
|
||||||
cairo_surface_t *pat_surface;
|
|
||||||
cairo_surface_attributes_t pat_attr;
|
cairo_surface_attributes_t pat_attr;
|
||||||
cairo_image_surface_t *image;
|
cairo_image_surface_t *image;
|
||||||
void *image_extra;
|
void *image_extra;
|
||||||
|
@ -516,25 +515,20 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
|
||||||
background_color = CAIRO_COLOR_BLACK;
|
background_color = CAIRO_COLOR_BLACK;
|
||||||
|
|
||||||
extend = cairo_pattern_get_extend (&pattern->base);
|
extend = cairo_pattern_get_extend (&pattern->base);
|
||||||
status = _cairo_pattern_acquire_surface ((cairo_pattern_t *)pattern,
|
|
||||||
(cairo_surface_t *)surface,
|
status = _cairo_surface_acquire_source_image (pattern->surface,
|
||||||
0, 0, -1, -1,
|
&image, &image_extra);
|
||||||
&pat_surface, &pat_attr);
|
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
status = _cairo_surface_acquire_source_image (pat_surface, &image, &image_extra);
|
|
||||||
if (status)
|
|
||||||
goto FINISH;
|
|
||||||
|
|
||||||
if (image->base.status) {
|
if (image->base.status) {
|
||||||
status = image->base.status;
|
status = image->base.status;
|
||||||
goto FINISH2;
|
goto CLEANUP_IMAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (image->width == 0 || image->height == 0) {
|
if (image->width == 0 || image->height == 0) {
|
||||||
status = CAIRO_STATUS_SUCCESS;
|
status = CAIRO_STATUS_SUCCESS;
|
||||||
goto FINISH2;
|
goto CLEANUP_IMAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (image->format != CAIRO_FORMAT_RGB24) {
|
if (image->format != CAIRO_FORMAT_RGB24) {
|
||||||
|
@ -545,7 +539,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
|
||||||
image->height);
|
image->height);
|
||||||
if (opaque_surface->status) {
|
if (opaque_surface->status) {
|
||||||
status = opaque_surface->status;
|
status = opaque_surface->status;
|
||||||
goto FINISH3;
|
goto CLEANUP_OPAQUE_IMAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_cairo_pattern_init_for_surface (&opaque_pattern, &image->base);
|
_cairo_pattern_init_for_surface (&opaque_pattern, &image->base);
|
||||||
|
@ -557,7 +551,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
|
||||||
image->width, image->height);
|
image->width, image->height);
|
||||||
if (status) {
|
if (status) {
|
||||||
_cairo_pattern_fini (&opaque_pattern.base);
|
_cairo_pattern_fini (&opaque_pattern.base);
|
||||||
goto FINISH3;
|
goto CLEANUP_OPAQUE_IMAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
|
status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
|
||||||
|
@ -571,7 +565,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
|
||||||
image->height);
|
image->height);
|
||||||
if (status) {
|
if (status) {
|
||||||
_cairo_pattern_fini (&opaque_pattern.base);
|
_cairo_pattern_fini (&opaque_pattern.base);
|
||||||
goto FINISH3;
|
goto CLEANUP_OPAQUE_IMAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_cairo_pattern_fini (&opaque_pattern.base);
|
_cairo_pattern_fini (&opaque_pattern.base);
|
||||||
|
@ -602,8 +596,10 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
|
||||||
SaveDC (surface->dc);
|
SaveDC (surface->dc);
|
||||||
_cairo_matrix_to_win32_xform (&m, &xform);
|
_cairo_matrix_to_win32_xform (&m, &xform);
|
||||||
|
|
||||||
if (!SetWorldTransform (surface->dc, &xform))
|
if (! SetWorldTransform (surface->dc, &xform)) {
|
||||||
return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_world_transform");
|
status = _cairo_win32_print_gdi_error ("_win32_scaled_font_set_world_transform");
|
||||||
|
goto CLEANUP_OPAQUE_IMAGE;
|
||||||
|
}
|
||||||
|
|
||||||
oldmode = SetStretchBltMode(surface->dc, HALFTONE);
|
oldmode = SetStretchBltMode(surface->dc, HALFTONE);
|
||||||
|
|
||||||
|
@ -635,19 +631,20 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
|
||||||
&bi,
|
&bi,
|
||||||
DIB_RGB_COLORS,
|
DIB_RGB_COLORS,
|
||||||
SRCCOPY))
|
SRCCOPY))
|
||||||
return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint(StretchDIBits)");
|
{
|
||||||
|
status = _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint(StretchDIBits)");
|
||||||
|
goto CLEANUP_OPAQUE_IMAGE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SetStretchBltMode(surface->dc, oldmode);
|
SetStretchBltMode(surface->dc, oldmode);
|
||||||
RestoreDC (surface->dc, -1);
|
RestoreDC (surface->dc, -1);
|
||||||
|
|
||||||
FINISH3:
|
CLEANUP_OPAQUE_IMAGE:
|
||||||
if (opaque_image != image)
|
if (opaque_image != image)
|
||||||
cairo_surface_destroy (opaque_surface);
|
cairo_surface_destroy (opaque_surface);
|
||||||
FINISH2:
|
CLEANUP_IMAGE:
|
||||||
_cairo_surface_release_source_image (pat_surface, image, image_extra);
|
_cairo_surface_release_source_image (pattern->surface, image, image_extra);
|
||||||
FINISH:
|
|
||||||
_cairo_pattern_release_surface ((cairo_pattern_t *)pattern, pat_surface, &pat_attr);
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -1525,6 +1522,12 @@ _cairo_win32_printing_surface_set_paginated_mode (void *abstract_surface,
|
||||||
surface->paginated_mode = paginated_mode;
|
surface->paginated_mode = paginated_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cairo_bool_t
|
||||||
|
_cairo_win32_printing_surface_supports_fine_grained_fallbacks (void *abstract_surface)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_win32_printing_surface_create:
|
* cairo_win32_printing_surface_create:
|
||||||
* @hdc: the DC to create a surface for
|
* @hdc: the DC to create a surface for
|
||||||
|
@ -1645,4 +1648,6 @@ static const cairo_paginated_surface_backend_t cairo_win32_surface_paginated_bac
|
||||||
_cairo_win32_printing_surface_start_page,
|
_cairo_win32_printing_surface_start_page,
|
||||||
_cairo_win32_printing_surface_set_paginated_mode,
|
_cairo_win32_printing_surface_set_paginated_mode,
|
||||||
NULL, /* set_bounding_box */
|
NULL, /* set_bounding_box */
|
||||||
|
NULL, /* _cairo_win32_printing_surface_has_fallback_images, */
|
||||||
|
_cairo_win32_printing_surface_supports_fine_grained_fallbacks,
|
||||||
};
|
};
|
||||||
|
|
|
@ -160,6 +160,8 @@ _cairo_win32_surface_clone_similar (void *abstract_surface,
|
||||||
int src_y,
|
int src_y,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
|
int *clone_offset_x,
|
||||||
|
int *clone_offset_y,
|
||||||
cairo_surface_t **clone_out);
|
cairo_surface_t **clone_out);
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
|
|
@ -435,6 +435,8 @@ _cairo_win32_surface_clone_similar (void *abstract_surface,
|
||||||
int src_y,
|
int src_y,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
|
int *clone_offset_x,
|
||||||
|
int *clone_offset_y,
|
||||||
cairo_surface_t **clone_out)
|
cairo_surface_t **clone_out)
|
||||||
{
|
{
|
||||||
cairo_content_t src_content;
|
cairo_content_t src_content;
|
||||||
|
@ -444,10 +446,16 @@ _cairo_win32_surface_clone_similar (void *abstract_surface,
|
||||||
|
|
||||||
src_content = cairo_surface_get_content(src);
|
src_content = cairo_surface_get_content(src);
|
||||||
new_surface =
|
new_surface =
|
||||||
_cairo_win32_surface_create_similar_internal (abstract_surface, src_content, width, height, FALSE);
|
_cairo_win32_surface_create_similar_internal (abstract_surface,
|
||||||
|
src_content,
|
||||||
|
width, height,
|
||||||
|
FALSE);
|
||||||
|
if (new_surface == NULL)
|
||||||
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
if (cairo_surface_status(new_surface))
|
status = new_surface->status;
|
||||||
return cairo_surface_status(new_surface);
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
_cairo_pattern_init_for_surface (&pattern, src);
|
_cairo_pattern_init_for_surface (&pattern, src);
|
||||||
|
|
||||||
|
@ -462,9 +470,11 @@ _cairo_win32_surface_clone_similar (void *abstract_surface,
|
||||||
|
|
||||||
_cairo_pattern_fini (&pattern.base);
|
_cairo_pattern_fini (&pattern.base);
|
||||||
|
|
||||||
if (status == CAIRO_STATUS_SUCCESS)
|
if (status == CAIRO_STATUS_SUCCESS) {
|
||||||
|
*clone_offset_x = src_x;
|
||||||
|
*clone_offset_y = src_y;
|
||||||
*clone_out = new_surface;
|
*clone_out = new_surface;
|
||||||
else
|
} else
|
||||||
cairo_surface_destroy (new_surface);
|
cairo_surface_destroy (new_surface);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
@ -512,8 +522,10 @@ _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface,
|
||||||
local =
|
local =
|
||||||
(cairo_win32_surface_t *) _cairo_win32_surface_create_similar_internal
|
(cairo_win32_surface_t *) _cairo_win32_surface_create_similar_internal
|
||||||
(surface, content, width, height, TRUE);
|
(surface, content, width, height, TRUE);
|
||||||
|
if (local == NULL)
|
||||||
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
if (local->base.status)
|
if (local->base.status)
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
return local->base.status;
|
||||||
|
|
||||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
|
@ -2005,34 +2017,6 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#if !defined(CAIRO_WIN32_STATIC_BUILD)
|
|
||||||
|
|
||||||
/* declare to avoid "no previous prototype for 'DllMain'" warning */
|
|
||||||
BOOL WINAPI
|
|
||||||
DllMain (HINSTANCE hinstDLL,
|
|
||||||
DWORD fdwReason,
|
|
||||||
LPVOID lpvReserved);
|
|
||||||
|
|
||||||
BOOL WINAPI
|
|
||||||
DllMain (HINSTANCE hinstDLL,
|
|
||||||
DWORD fdwReason,
|
|
||||||
LPVOID lpvReserved)
|
|
||||||
{
|
|
||||||
switch (fdwReason) {
|
|
||||||
case DLL_PROCESS_ATTACH:
|
|
||||||
CAIRO_MUTEX_INITIALIZE ();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DLL_PROCESS_DETACH:
|
|
||||||
CAIRO_MUTEX_FINALIZE ();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cairo_int_status_t
|
cairo_int_status_t
|
||||||
_cairo_win32_save_initial_clip (HDC hdc, cairo_win32_surface_t *surface)
|
_cairo_win32_save_initial_clip (HDC hdc, cairo_win32_surface_t *surface)
|
||||||
{
|
{
|
||||||
|
|
|
@ -68,6 +68,12 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface);
|
||||||
cairo_public cairo_surface_t *
|
cairo_public cairo_surface_t *
|
||||||
cairo_win32_surface_get_image (cairo_surface_t *surface);
|
cairo_win32_surface_get_image (cairo_surface_t *surface);
|
||||||
|
|
||||||
|
#if CAIRO_HAS_WIN32_FONT
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Win32 font support
|
||||||
|
*/
|
||||||
|
|
||||||
cairo_public cairo_font_face_t *
|
cairo_public cairo_font_face_t *
|
||||||
cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont);
|
cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont);
|
||||||
|
|
||||||
|
@ -95,6 +101,8 @@ cairo_public void
|
||||||
cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font,
|
cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font,
|
||||||
cairo_matrix_t *device_to_logical);
|
cairo_matrix_t *device_to_logical);
|
||||||
|
|
||||||
|
#endif /* CAIRO_HAS_WIN32_FONT */
|
||||||
|
|
||||||
CAIRO_END_DECLS
|
CAIRO_END_DECLS
|
||||||
|
|
||||||
#else /* CAIRO_HAS_WIN32_SURFACE */
|
#else /* CAIRO_HAS_WIN32_SURFACE */
|
||||||
|
|
|
@ -197,7 +197,7 @@ _cairo_xcb_surface_create_similar (void *abstract_src,
|
||||||
xrender_format,
|
xrender_format,
|
||||||
width, height);
|
width, height);
|
||||||
if (surface->base.status)
|
if (surface->base.status)
|
||||||
return surface;
|
return &surface->base;
|
||||||
|
|
||||||
surface->owns_pixmap = TRUE;
|
surface->owns_pixmap = TRUE;
|
||||||
|
|
||||||
|
@ -695,6 +695,8 @@ _cairo_xcb_surface_clone_similar (void *abstract_surface,
|
||||||
int src_y,
|
int src_y,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
|
int *clone_offset_x,
|
||||||
|
int *clone_offset_y,
|
||||||
cairo_surface_t **clone_out)
|
cairo_surface_t **clone_out)
|
||||||
{
|
{
|
||||||
cairo_xcb_surface_t *surface = abstract_surface;
|
cairo_xcb_surface_t *surface = abstract_surface;
|
||||||
|
@ -704,6 +706,8 @@ _cairo_xcb_surface_clone_similar (void *abstract_surface,
|
||||||
cairo_xcb_surface_t *xcb_src = (cairo_xcb_surface_t *)src;
|
cairo_xcb_surface_t *xcb_src = (cairo_xcb_surface_t *)src;
|
||||||
|
|
||||||
if (_cairo_xcb_surface_same_screen(surface, xcb_src)) {
|
if (_cairo_xcb_surface_same_screen(surface, xcb_src)) {
|
||||||
|
*clone_offset_x = 0;
|
||||||
|
*clone_offset_y = 0;
|
||||||
*clone_out = cairo_surface_reference (src);
|
*clone_out = cairo_surface_reference (src);
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
@ -711,19 +715,29 @@ _cairo_xcb_surface_clone_similar (void *abstract_surface,
|
||||||
} else if (_cairo_surface_is_image (src)) {
|
} else if (_cairo_surface_is_image (src)) {
|
||||||
cairo_image_surface_t *image_src = (cairo_image_surface_t *)src;
|
cairo_image_surface_t *image_src = (cairo_image_surface_t *)src;
|
||||||
cairo_content_t content = _cairo_content_from_format (image_src->format);
|
cairo_content_t content = _cairo_content_from_format (image_src->format);
|
||||||
|
cairo_status_t status;
|
||||||
|
|
||||||
if (surface->base.status)
|
if (surface->base.status)
|
||||||
return surface->base.status;
|
return surface->base.status;
|
||||||
|
|
||||||
clone = (cairo_xcb_surface_t *)
|
clone = (cairo_xcb_surface_t *)
|
||||||
_cairo_xcb_surface_create_similar (surface, content,
|
_cairo_xcb_surface_create_similar (surface, content, width, height);
|
||||||
image_src->width, image_src->height);
|
if (clone == NULL)
|
||||||
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
if (clone->base.status)
|
if (clone->base.status)
|
||||||
return clone->base.status;
|
return clone->base.status;
|
||||||
|
|
||||||
_draw_image_surface (clone, image_src, src_x, src_y,
|
status = _draw_image_surface (clone, image_src,
|
||||||
width, height, src_x, src_y);
|
src_x, src_y,
|
||||||
|
width, height,
|
||||||
|
0, 0);
|
||||||
|
if (status) {
|
||||||
|
cairo_surface_destroy (&clone->base);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
*clone_offset_x = src_x;
|
||||||
|
*clone_offset_y = src_y;
|
||||||
*clone_out = &clone->base;
|
*clone_out = &clone->base;
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
@ -879,7 +893,9 @@ _surfaces_compatible (cairo_xcb_surface_t *dst,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* if Render is supported, match picture formats */
|
/* if Render is supported, match picture formats */
|
||||||
if (src->xrender_format.id != XCB_NONE && src->xrender_format.id == dst->xrender_format.id)
|
if (src->xrender_format.id != dst->xrender_format.id)
|
||||||
|
return FALSE;
|
||||||
|
else if (src->xrender_format.id != XCB_NONE)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* Without Render, match visuals instead */
|
/* Without Render, match visuals instead */
|
||||||
|
@ -1111,6 +1127,7 @@ _cairo_xcb_surface_composite (cairo_operator_t op,
|
||||||
cairo_int_status_t status;
|
cairo_int_status_t status;
|
||||||
composite_operation_t operation;
|
composite_operation_t operation;
|
||||||
int itx, ity;
|
int itx, ity;
|
||||||
|
cairo_bool_t is_integer_translation;
|
||||||
|
|
||||||
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))
|
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))
|
||||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
@ -1200,7 +1217,9 @@ _cairo_xcb_surface_composite (cairo_operator_t op,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
_cairo_xcb_surface_ensure_gc (dst);
|
_cairo_xcb_surface_ensure_gc (dst);
|
||||||
_cairo_matrix_is_integer_translation (&src_attr.matrix, &itx, &ity);
|
is_integer_translation =
|
||||||
|
_cairo_matrix_is_integer_translation (&src_attr.matrix, &itx, &ity);
|
||||||
|
assert (is_integer_translation == TRUE);
|
||||||
{
|
{
|
||||||
uint32_t mask = XCB_GC_FILL_STYLE | XCB_GC_TILE
|
uint32_t mask = XCB_GC_FILL_STYLE | XCB_GC_TILE
|
||||||
| XCB_GC_TILE_STIPPLE_ORIGIN_X
|
| XCB_GC_TILE_STIPPLE_ORIGIN_X
|
||||||
|
@ -1319,7 +1338,7 @@ _create_a8_picture (cairo_xcb_surface_t *surface,
|
||||||
/* Creates a temporary mask for the trapezoids covering the area
|
/* Creates a temporary mask for the trapezoids covering the area
|
||||||
* [@dst_x, @dst_y, @width, @height] of the destination surface.
|
* [@dst_x, @dst_y, @width, @height] of the destination surface.
|
||||||
*/
|
*/
|
||||||
static xcb_render_picture_t
|
static cairo_status_t
|
||||||
_create_trapezoid_mask (cairo_xcb_surface_t *dst,
|
_create_trapezoid_mask (cairo_xcb_surface_t *dst,
|
||||||
cairo_trapezoid_t *traps,
|
cairo_trapezoid_t *traps,
|
||||||
int num_traps,
|
int num_traps,
|
||||||
|
@ -1327,7 +1346,8 @@ _create_trapezoid_mask (cairo_xcb_surface_t *dst,
|
||||||
int dst_y,
|
int dst_y,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
xcb_render_pictforminfo_t *pict_format)
|
xcb_render_pictforminfo_t *pict_format,
|
||||||
|
xcb_render_picture_t *mask_picture_out)
|
||||||
{
|
{
|
||||||
xcb_render_color_t transparent = { 0, 0, 0, 0 };
|
xcb_render_color_t transparent = { 0, 0, 0, 0 };
|
||||||
xcb_render_color_t solid = { 0xffff, 0xffff, 0xffff, 0xffff };
|
xcb_render_color_t solid = { 0xffff, 0xffff, 0xffff, 0xffff };
|
||||||
|
@ -1346,10 +1366,8 @@ _create_trapezoid_mask (cairo_xcb_surface_t *dst,
|
||||||
solid_picture = _create_a8_picture (dst, &solid, width, height, TRUE);
|
solid_picture = _create_a8_picture (dst, &solid, width, height, TRUE);
|
||||||
|
|
||||||
offset_traps = _cairo_malloc_ab (num_traps, sizeof (xcb_render_trapezoid_t));
|
offset_traps = _cairo_malloc_ab (num_traps, sizeof (xcb_render_trapezoid_t));
|
||||||
if (!offset_traps) {
|
if (offset_traps == NULL)
|
||||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
return XCB_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < num_traps; i++) {
|
for (i = 0; i < num_traps; i++) {
|
||||||
offset_traps[i].top = _cairo_fixed_to_16_16(traps[i].top) - 0x10000 * dst_y;
|
offset_traps[i].top = _cairo_fixed_to_16_16(traps[i].top) - 0x10000 * dst_y;
|
||||||
|
@ -1373,7 +1391,8 @@ _create_trapezoid_mask (cairo_xcb_surface_t *dst,
|
||||||
xcb_render_free_picture (dst->dpy, solid_picture);
|
xcb_render_free_picture (dst->dpy, solid_picture);
|
||||||
free (offset_traps);
|
free (offset_traps);
|
||||||
|
|
||||||
return mask_picture;
|
*mask_picture_out = mask_picture;
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cairo_int_status_t
|
static cairo_int_status_t
|
||||||
|
@ -1460,13 +1479,14 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t op,
|
||||||
* bounds and clip. (xcb_render_add_traps() could be used to make creating
|
* bounds and clip. (xcb_render_add_traps() could be used to make creating
|
||||||
* the mask somewhat cheaper.)
|
* the mask somewhat cheaper.)
|
||||||
*/
|
*/
|
||||||
xcb_render_picture_t mask_picture = _create_trapezoid_mask (dst, traps, num_traps,
|
xcb_render_picture_t mask_picture = 0; /* silence compiler */
|
||||||
dst_x, dst_y, width, height,
|
|
||||||
render_format);
|
status = _create_trapezoid_mask (dst, traps, num_traps,
|
||||||
if (!mask_picture) {
|
dst_x, dst_y, width, height,
|
||||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
render_format,
|
||||||
|
&mask_picture);
|
||||||
|
if (status)
|
||||||
goto BAIL;
|
goto BAIL;
|
||||||
}
|
|
||||||
|
|
||||||
xcb_render_composite (dst->dpy,
|
xcb_render_composite (dst->dpy,
|
||||||
_render_operator (op),
|
_render_operator (op),
|
||||||
|
@ -1639,6 +1659,12 @@ _cairo_xcb_surface_is_similar (void *surface_a,
|
||||||
cairo_xcb_surface_t *b = surface_b;
|
cairo_xcb_surface_t *b = surface_b;
|
||||||
xcb_render_pictforminfo_t *xrender_format;
|
xcb_render_pictforminfo_t *xrender_format;
|
||||||
|
|
||||||
|
/* XXX: disable caching by the solid pattern cache until we implement
|
||||||
|
* display notification to avoid issuing xcb calls from the wrong thread
|
||||||
|
* or accessing the surface after the Display has been closed.
|
||||||
|
*/
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (! _cairo_xcb_surface_same_screen (a, b))
|
if (! _cairo_xcb_surface_same_screen (a, b))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -1959,9 +1985,10 @@ cairo_xcb_surface_set_size (cairo_surface_t *abstract_surface,
|
||||||
int height)
|
int height)
|
||||||
{
|
{
|
||||||
cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) abstract_surface;
|
cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) abstract_surface;
|
||||||
|
cairo_status_t status_ignored;
|
||||||
|
|
||||||
if (! _cairo_surface_is_xcb (abstract_surface)) {
|
if (! _cairo_surface_is_xcb (abstract_surface)) {
|
||||||
_cairo_surface_set_error (abstract_surface,
|
status_ignored = _cairo_surface_set_error (abstract_surface,
|
||||||
CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2305,14 +2332,121 @@ typedef cairo_status_t (*cairo_xcb_surface_show_glyphs_func_t)
|
||||||
(cairo_xcb_surface_t *, cairo_operator_t, cairo_xcb_surface_t *, int, int,
|
(cairo_xcb_surface_t *, cairo_operator_t, cairo_xcb_surface_t *, int, int,
|
||||||
const cairo_glyph_t *, int, cairo_scaled_font_t *);
|
const cairo_glyph_t *, int, cairo_scaled_font_t *);
|
||||||
|
|
||||||
|
static cairo_bool_t
|
||||||
|
_cairo_xcb_surface_owns_font (cairo_xcb_surface_t *dst,
|
||||||
|
cairo_scaled_font_t *scaled_font)
|
||||||
|
{
|
||||||
|
cairo_xcb_surface_font_private_t *font_private;
|
||||||
|
|
||||||
|
font_private = scaled_font->surface_private;
|
||||||
|
if ((scaled_font->surface_backend != NULL &&
|
||||||
|
scaled_font->surface_backend != &cairo_xcb_surface_backend) ||
|
||||||
|
(font_private != NULL && font_private->dpy != dst->dpy))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static cairo_status_t
|
||||||
|
_cairo_xcb_surface_emit_glyphs (cairo_xcb_surface_t *dst,
|
||||||
|
cairo_glyph_t *glyphs,
|
||||||
|
int num_glyphs,
|
||||||
|
cairo_scaled_font_t *scaled_font,
|
||||||
|
cairo_operator_t op,
|
||||||
|
cairo_xcb_surface_t *src,
|
||||||
|
cairo_surface_attributes_t *attributes,
|
||||||
|
int *remaining_glyphs)
|
||||||
|
{
|
||||||
|
cairo_scaled_glyph_t *scaled_glyph;
|
||||||
|
int i, o;
|
||||||
|
unsigned long max_index = 0;
|
||||||
|
cairo_status_t status;
|
||||||
|
cairo_glyph_t *output_glyphs;
|
||||||
|
const cairo_glyph_t *glyphs_chunk;
|
||||||
|
int glyphs_remaining, chunk_size, max_chunk_size;
|
||||||
|
cairo_xcb_surface_show_glyphs_func_t show_glyphs_func;
|
||||||
|
|
||||||
|
/* We make a copy of the glyphs so that we can elide any size-zero
|
||||||
|
* glyphs to workaround an X server bug, (present in at least Xorg
|
||||||
|
* 7.1 without EXA). */
|
||||||
|
output_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
|
||||||
|
if (output_glyphs == NULL)
|
||||||
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
|
|
||||||
|
for (i = 0, o = 0; i < num_glyphs; i++) {
|
||||||
|
if (glyphs[i].index > max_index)
|
||||||
|
max_index = glyphs[i].index;
|
||||||
|
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||||
|
glyphs[i].index,
|
||||||
|
CAIRO_SCALED_GLYPH_INFO_SURFACE,
|
||||||
|
&scaled_glyph);
|
||||||
|
if (status) {
|
||||||
|
free (output_glyphs);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't put any size-zero glyphs into output_glyphs to avoid
|
||||||
|
* an X server bug which stops rendering glyphs after the
|
||||||
|
* first size-zero glyph. */
|
||||||
|
if (scaled_glyph->surface->width && scaled_glyph->surface->height) {
|
||||||
|
output_glyphs[o++] = glyphs[i];
|
||||||
|
if (scaled_glyph->surface_private == NULL) {
|
||||||
|
_cairo_xcb_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph);
|
||||||
|
scaled_glyph->surface_private = (void *) 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
num_glyphs = o;
|
||||||
|
|
||||||
|
_cairo_xcb_surface_ensure_dst_picture (dst);
|
||||||
|
|
||||||
|
max_chunk_size = xcb_get_maximum_request_length (dst->dpy);
|
||||||
|
if (max_index < 256) {
|
||||||
|
/* XXX: these are all the same size! (28) */
|
||||||
|
max_chunk_size -= sizeof(xcb_render_composite_glyphs_8_request_t);
|
||||||
|
show_glyphs_func = _cairo_xcb_surface_show_glyphs_8;
|
||||||
|
} else if (max_index < 65536) {
|
||||||
|
max_chunk_size -= sizeof(xcb_render_composite_glyphs_16_request_t);
|
||||||
|
show_glyphs_func = _cairo_xcb_surface_show_glyphs_16;
|
||||||
|
} else {
|
||||||
|
max_chunk_size -= sizeof(xcb_render_composite_glyphs_32_request_t);
|
||||||
|
show_glyphs_func = _cairo_xcb_surface_show_glyphs_32;
|
||||||
|
}
|
||||||
|
/* XXX: I think this is wrong; this is only the header size (2 longs) */
|
||||||
|
/* but should also include the glyph (1 long) */
|
||||||
|
/* max_chunk_size /= sz_xGlyphElt; */
|
||||||
|
max_chunk_size /= 3*sizeof(uint32_t);
|
||||||
|
|
||||||
|
for (glyphs_remaining = num_glyphs, glyphs_chunk = output_glyphs;
|
||||||
|
glyphs_remaining;
|
||||||
|
glyphs_remaining -= chunk_size, glyphs_chunk += chunk_size)
|
||||||
|
{
|
||||||
|
chunk_size = MIN (glyphs_remaining, max_chunk_size);
|
||||||
|
|
||||||
|
status = show_glyphs_func (dst, op, src,
|
||||||
|
attributes->x_offset, attributes->y_offset,
|
||||||
|
glyphs_chunk, chunk_size, scaled_font);
|
||||||
|
if (status) {
|
||||||
|
free (output_glyphs);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static cairo_int_status_t
|
static cairo_int_status_t
|
||||||
_cairo_xcb_surface_show_glyphs (void *abstract_dst,
|
_cairo_xcb_surface_show_glyphs (void *abstract_dst,
|
||||||
cairo_operator_t op,
|
cairo_operator_t op,
|
||||||
cairo_pattern_t *src_pattern,
|
cairo_pattern_t *src_pattern,
|
||||||
cairo_glyph_t *glyphs,
|
cairo_glyph_t *glyphs,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
cairo_scaled_font_t *scaled_font,
|
cairo_scaled_font_t *scaled_font,
|
||||||
int *remaining_glyphs)
|
int *remaining_glyphs)
|
||||||
{
|
{
|
||||||
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
|
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
|
||||||
cairo_xcb_surface_t *dst = abstract_dst;
|
cairo_xcb_surface_t *dst = abstract_dst;
|
||||||
|
@ -2321,17 +2455,6 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
|
||||||
cairo_surface_attributes_t attributes;
|
cairo_surface_attributes_t attributes;
|
||||||
cairo_xcb_surface_t *src = NULL;
|
cairo_xcb_surface_t *src = NULL;
|
||||||
|
|
||||||
cairo_glyph_t *output_glyphs;
|
|
||||||
const cairo_glyph_t *glyphs_chunk;
|
|
||||||
int glyphs_remaining, chunk_size, max_chunk_size;
|
|
||||||
cairo_scaled_glyph_t *scaled_glyph;
|
|
||||||
cairo_xcb_surface_font_private_t *font_private;
|
|
||||||
|
|
||||||
int i, o;
|
|
||||||
unsigned long max_index = 0;
|
|
||||||
|
|
||||||
cairo_xcb_surface_show_glyphs_func_t show_glyphs_func;
|
|
||||||
|
|
||||||
cairo_solid_pattern_t solid_pattern;
|
cairo_solid_pattern_t solid_pattern;
|
||||||
|
|
||||||
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst) || dst->xrender_format.id == XCB_NONE)
|
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst) || dst->xrender_format.id == XCB_NONE)
|
||||||
|
@ -2365,29 +2488,16 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
|
||||||
if (operation == DO_UNSUPPORTED)
|
if (operation == DO_UNSUPPORTED)
|
||||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
font_private = scaled_font->surface_private;
|
if (! _cairo_xcb_surface_owns_font (dst, scaled_font))
|
||||||
if ((scaled_font->surface_backend != NULL &&
|
|
||||||
scaled_font->surface_backend != &cairo_xcb_surface_backend) ||
|
|
||||||
(font_private != NULL && font_private->dpy != dst->dpy))
|
|
||||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
/* We make a copy of the glyphs so that we can elide any size-zero
|
|
||||||
* glyphs to workaround an X server bug, (present in at least Xorg
|
|
||||||
* 7.1 without EXA). */
|
|
||||||
output_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
|
|
||||||
if (output_glyphs == NULL)
|
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
||||||
|
|
||||||
/* After passing all those tests, we're now committed to rendering
|
/* After passing all those tests, we're now committed to rendering
|
||||||
* these glyphs or to fail trying. We first upload any glyphs to
|
* these glyphs or to fail trying. We first upload any glyphs to
|
||||||
* the X server that it doesn't have already, then we draw
|
* the X server that it doesn't have already, then we draw
|
||||||
* them. We tie into the scaled_font's glyph cache and remove
|
* them. We tie into the scaled_font's glyph cache and remove
|
||||||
* glyphs from the X server when they are ejected from the
|
* glyphs from the X server when they are ejected from the
|
||||||
* scaled_font cache. Because of this we first freeze the
|
* scaled_font cache.
|
||||||
* scaled_font's cache so that we don't cause any of our glyphs to
|
*/
|
||||||
* be ejected and removed from the X server before we have a
|
|
||||||
* chance to render them. */
|
|
||||||
_cairo_scaled_font_freeze_cache (scaled_font);
|
|
||||||
|
|
||||||
/* PictOpClear doesn't seem to work with CompositeText; it seems to ignore
|
/* PictOpClear doesn't seem to work with CompositeText; it seems to ignore
|
||||||
* the mask (the glyphs). This code below was executed as a side effect
|
* the mask (the glyphs). This code below was executed as a side effect
|
||||||
|
@ -2437,64 +2547,21 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
|
||||||
goto BAIL;
|
goto BAIL;
|
||||||
|
|
||||||
/* Send all unsent glyphs to the server, and count the max of the glyph indices */
|
/* Send all unsent glyphs to the server, and count the max of the glyph indices */
|
||||||
for (i = 0, o = 0; i < num_glyphs; i++) {
|
_cairo_scaled_font_freeze_cache (scaled_font);
|
||||||
if (glyphs[i].index > max_index)
|
|
||||||
max_index = glyphs[i].index;
|
|
||||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
|
||||||
glyphs[i].index,
|
|
||||||
CAIRO_SCALED_GLYPH_INFO_SURFACE,
|
|
||||||
&scaled_glyph);
|
|
||||||
if (status != CAIRO_STATUS_SUCCESS)
|
|
||||||
goto BAIL;
|
|
||||||
/* Don't put any size-zero glyphs into output_glyphs to avoid
|
|
||||||
* an X server bug which stops rendering glyphs after the
|
|
||||||
* first size-zero glyph. */
|
|
||||||
if (scaled_glyph->surface->width && scaled_glyph->surface->height) {
|
|
||||||
output_glyphs[o++] = glyphs[i];
|
|
||||||
if (scaled_glyph->surface_private == NULL) {
|
|
||||||
_cairo_xcb_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph);
|
|
||||||
scaled_glyph->surface_private = (void *) 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
num_glyphs = o;
|
|
||||||
|
|
||||||
_cairo_xcb_surface_ensure_dst_picture (dst);
|
if (_cairo_xcb_surface_owns_font (dst, scaled_font))
|
||||||
|
status = _cairo_xcb_surface_emit_glyphs (dst,
|
||||||
max_chunk_size = xcb_get_maximum_request_length (dst->dpy);
|
glyphs, num_glyphs,
|
||||||
if (max_index < 256) {
|
scaled_font,
|
||||||
/* XXX: these are all the same size! (28) */
|
op,
|
||||||
max_chunk_size -= sizeof(xcb_render_composite_glyphs_8_request_t);
|
src,
|
||||||
show_glyphs_func = _cairo_xcb_surface_show_glyphs_8;
|
&attributes,
|
||||||
} else if (max_index < 65536) {
|
remaining_glyphs);
|
||||||
max_chunk_size -= sizeof(xcb_render_composite_glyphs_16_request_t);
|
else
|
||||||
show_glyphs_func = _cairo_xcb_surface_show_glyphs_16;
|
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
} else {
|
_cairo_scaled_font_thaw_cache (scaled_font);
|
||||||
max_chunk_size -= sizeof(xcb_render_composite_glyphs_32_request_t);
|
|
||||||
show_glyphs_func = _cairo_xcb_surface_show_glyphs_32;
|
|
||||||
}
|
|
||||||
/* XXX: I think this is wrong; this is only the header size (2 longs) */
|
|
||||||
/* but should also include the glyph (1 long) */
|
|
||||||
/* max_chunk_size /= sz_xGlyphElt; */
|
|
||||||
max_chunk_size /= 3*sizeof(uint32_t);
|
|
||||||
|
|
||||||
for (glyphs_remaining = num_glyphs, glyphs_chunk = output_glyphs;
|
|
||||||
glyphs_remaining;
|
|
||||||
glyphs_remaining -= chunk_size, glyphs_chunk += chunk_size)
|
|
||||||
{
|
|
||||||
chunk_size = MIN (glyphs_remaining, max_chunk_size);
|
|
||||||
|
|
||||||
status = show_glyphs_func (dst, op, src,
|
|
||||||
attributes.x_offset, attributes.y_offset,
|
|
||||||
glyphs_chunk, chunk_size, scaled_font);
|
|
||||||
if (status != CAIRO_STATUS_SUCCESS)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
BAIL:
|
BAIL:
|
||||||
_cairo_scaled_font_thaw_cache (scaled_font);
|
|
||||||
free (output_glyphs);
|
|
||||||
|
|
||||||
if (src)
|
if (src)
|
||||||
_cairo_pattern_release_surface (src_pattern, &src->base, &attributes);
|
_cairo_pattern_release_surface (src_pattern, &src->base, &attributes);
|
||||||
if (src_pattern == &solid_pattern.base)
|
if (src_pattern == &solid_pattern.base)
|
||||||
|
|
|
@ -150,22 +150,13 @@ _cairo_xlib_init_screen_font_options (Display *dpy, cairo_xlib_screen_info_t *in
|
||||||
cairo_bool_t xft_antialias;
|
cairo_bool_t xft_antialias;
|
||||||
int xft_hintstyle;
|
int xft_hintstyle;
|
||||||
int xft_rgba;
|
int xft_rgba;
|
||||||
int xft_lcdfilter;
|
|
||||||
cairo_antialias_t antialias;
|
cairo_antialias_t antialias;
|
||||||
cairo_subpixel_order_t subpixel_order;
|
cairo_subpixel_order_t subpixel_order;
|
||||||
cairo_lcd_filter_t lcd_filter;
|
|
||||||
cairo_hint_style_t hint_style;
|
cairo_hint_style_t hint_style;
|
||||||
|
|
||||||
if (!get_boolean_default (dpy, "antialias", &xft_antialias))
|
if (!get_boolean_default (dpy, "antialias", &xft_antialias))
|
||||||
xft_antialias = TRUE;
|
xft_antialias = TRUE;
|
||||||
|
|
||||||
if (!get_integer_default (dpy, "lcdfilter", &xft_lcdfilter)) {
|
|
||||||
/* -1 is an non-existant Fontconfig constant used to differentiate
|
|
||||||
* the case when no lcdfilter property is available.
|
|
||||||
*/
|
|
||||||
xft_lcdfilter = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!get_boolean_default (dpy, "hinting", &xft_hinting))
|
if (!get_boolean_default (dpy, "hinting", &xft_hinting))
|
||||||
xft_hinting = TRUE;
|
xft_hinting = TRUE;
|
||||||
|
|
||||||
|
@ -248,24 +239,6 @@ _cairo_xlib_init_screen_font_options (Display *dpy, cairo_xlib_screen_info_t *in
|
||||||
subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
|
subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (xft_lcdfilter) {
|
|
||||||
case FC_LCD_NONE:
|
|
||||||
lcd_filter = CAIRO_LCD_FILTER_NONE;
|
|
||||||
break;
|
|
||||||
case FC_LCD_DEFAULT:
|
|
||||||
lcd_filter = CAIRO_LCD_FILTER_FIR5;
|
|
||||||
break;
|
|
||||||
case FC_LCD_LIGHT:
|
|
||||||
lcd_filter = CAIRO_LCD_FILTER_FIR3;
|
|
||||||
break;
|
|
||||||
case FC_LCD_LEGACY:
|
|
||||||
lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
lcd_filter = CAIRO_LCD_FILTER_DEFAULT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xft_antialias) {
|
if (xft_antialias) {
|
||||||
if (subpixel_order == CAIRO_SUBPIXEL_ORDER_DEFAULT)
|
if (subpixel_order == CAIRO_SUBPIXEL_ORDER_DEFAULT)
|
||||||
antialias = CAIRO_ANTIALIAS_GRAY;
|
antialias = CAIRO_ANTIALIAS_GRAY;
|
||||||
|
@ -278,7 +251,6 @@ _cairo_xlib_init_screen_font_options (Display *dpy, cairo_xlib_screen_info_t *in
|
||||||
cairo_font_options_set_hint_style (&info->font_options, hint_style);
|
cairo_font_options_set_hint_style (&info->font_options, hint_style);
|
||||||
cairo_font_options_set_antialias (&info->font_options, antialias);
|
cairo_font_options_set_antialias (&info->font_options, antialias);
|
||||||
cairo_font_options_set_subpixel_order (&info->font_options, subpixel_order);
|
cairo_font_options_set_subpixel_order (&info->font_options, subpixel_order);
|
||||||
cairo_font_options_set_lcd_filter (&info->font_options, lcd_filter);
|
|
||||||
cairo_font_options_set_hint_metrics (&info->font_options, CAIRO_HINT_METRICS_ON);
|
cairo_font_options_set_hint_metrics (&info->font_options, CAIRO_HINT_METRICS_ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -147,7 +147,7 @@ _cairo_xlib_surface_create_similar_with_format (void *abstract_src,
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
xrender_format = _cairo_xlib_display_get_xrender_format (
|
xrender_format = _cairo_xlib_display_get_xrender_format (
|
||||||
src->screen_info->display,
|
src->display,
|
||||||
format);
|
format);
|
||||||
if (xrender_format == NULL)
|
if (xrender_format == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -211,7 +211,7 @@ _cairo_xlib_surface_create_similar (void *abstract_src,
|
||||||
if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
|
if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
|
||||||
return _cairo_surface_create_in_error (_cairo_error(CAIRO_STATUS_NO_MEMORY));
|
return _cairo_surface_create_in_error (_cairo_error(CAIRO_STATUS_NO_MEMORY));
|
||||||
|
|
||||||
_cairo_xlib_display_notify (src->screen_info->display);
|
_cairo_xlib_display_notify (src->display);
|
||||||
|
|
||||||
/* Start by examining the surface's XRenderFormat, or if it
|
/* Start by examining the surface's XRenderFormat, or if it
|
||||||
* doesn't have one, then look one up through its visual (in the
|
* doesn't have one, then look one up through its visual (in the
|
||||||
|
@ -259,9 +259,7 @@ static cairo_status_t
|
||||||
_cairo_xlib_surface_finish (void *abstract_surface)
|
_cairo_xlib_surface_finish (void *abstract_surface)
|
||||||
{
|
{
|
||||||
cairo_xlib_surface_t *surface = abstract_surface;
|
cairo_xlib_surface_t *surface = abstract_surface;
|
||||||
cairo_xlib_display_t *display = surface->screen_info ?
|
cairo_xlib_display_t *display = surface->display;
|
||||||
surface->screen_info->display :
|
|
||||||
NULL;
|
|
||||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||||
|
|
||||||
if (surface->owns_pixmap) {
|
if (surface->owns_pixmap) {
|
||||||
|
@ -345,7 +343,7 @@ _swap_ximage_2bytes (XImage *ximage)
|
||||||
char *line = ximage->data;
|
char *line = ximage->data;
|
||||||
|
|
||||||
for (j = ximage->height; j; j--) {
|
for (j = ximage->height; j; j--) {
|
||||||
uint16_t *p = (uint16_t *)line;
|
uint16_t *p = (uint16_t *) line;
|
||||||
for (i = ximage->width; i; i--) {
|
for (i = ximage->width; i; i--) {
|
||||||
*p = bswap_16 (*p);
|
*p = bswap_16 (*p);
|
||||||
p++;
|
p++;
|
||||||
|
@ -355,6 +353,26 @@ _swap_ximage_2bytes (XImage *ximage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_swap_ximage_3bytes (XImage *ximage)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
char *line = ximage->data;
|
||||||
|
|
||||||
|
for (j = ximage->height; j; j--) {
|
||||||
|
uint8_t *p = (uint8_t *) line;
|
||||||
|
for (i = ximage->width; i; i--) {
|
||||||
|
uint8_t tmp;
|
||||||
|
tmp = p[2];
|
||||||
|
p[2] = p[0];
|
||||||
|
p[0] = tmp;
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
line += ximage->bytes_per_line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_swap_ximage_4bytes (XImage *ximage)
|
_swap_ximage_4bytes (XImage *ximage)
|
||||||
{
|
{
|
||||||
|
@ -362,7 +380,7 @@ _swap_ximage_4bytes (XImage *ximage)
|
||||||
char *line = ximage->data;
|
char *line = ximage->data;
|
||||||
|
|
||||||
for (j = ximage->height; j; j--) {
|
for (j = ximage->height; j; j--) {
|
||||||
uint32_t *p = (uint32_t *)line;
|
uint32_t *p = (uint32_t *) line;
|
||||||
for (i = ximage->width; i; i--) {
|
for (i = ximage->width; i; i--) {
|
||||||
*p = bswap_32 (*p);
|
*p = bswap_32 (*p);
|
||||||
p++;
|
p++;
|
||||||
|
@ -372,6 +390,23 @@ _swap_ximage_4bytes (XImage *ximage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_swap_ximage_nibbles (XImage *ximage)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
char *line = ximage->data;
|
||||||
|
|
||||||
|
for (j = ximage->height; j; j--) {
|
||||||
|
uint8_t *p = (uint8_t *) line;
|
||||||
|
for (i = (ximage->width + 1) / 2; i; i--) {
|
||||||
|
*p = ((*p >> 4) & 0xf) | ((*p << 4) & ~0xf);
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
line += ximage->bytes_per_line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_swap_ximage_bits (XImage *ximage)
|
_swap_ximage_bits (XImage *ximage)
|
||||||
{
|
{
|
||||||
|
@ -404,7 +439,8 @@ _swap_ximage_to_native (XImage *ximage)
|
||||||
int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst;
|
int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst;
|
||||||
|
|
||||||
if (ximage->bits_per_pixel == 1 &&
|
if (ximage->bits_per_pixel == 1 &&
|
||||||
ximage->bitmap_bit_order != native_byte_order) {
|
ximage->bitmap_bit_order != native_byte_order)
|
||||||
|
{
|
||||||
_swap_ximage_bits (ximage);
|
_swap_ximage_bits (ximage);
|
||||||
if (ximage->bitmap_bit_order == ximage->byte_order)
|
if (ximage->bitmap_bit_order == ximage->byte_order)
|
||||||
return;
|
return;
|
||||||
|
@ -417,25 +453,32 @@ _swap_ximage_to_native (XImage *ximage)
|
||||||
case 1:
|
case 1:
|
||||||
unit_bytes = ximage->bitmap_unit / 8;
|
unit_bytes = ximage->bitmap_unit / 8;
|
||||||
break;
|
break;
|
||||||
|
case 4:
|
||||||
|
_swap_ximage_nibbles (ximage);
|
||||||
|
/* fall-through */
|
||||||
case 8:
|
case 8:
|
||||||
case 16:
|
case 16:
|
||||||
|
case 20:
|
||||||
|
case 24:
|
||||||
|
case 28:
|
||||||
|
case 30:
|
||||||
case 32:
|
case 32:
|
||||||
unit_bytes = ximage->bits_per_pixel / 8;
|
unit_bytes = (ximage->bits_per_pixel + 7) / 8;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* This could be hit on some uncommon but possible cases,
|
/* This could be hit on some rare but possible cases. */
|
||||||
* such as bpp=4. These are cases that libpixman can't deal
|
|
||||||
* with in any case.
|
|
||||||
*/
|
|
||||||
ASSERT_NOT_REACHED;
|
ASSERT_NOT_REACHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (unit_bytes) {
|
switch (unit_bytes) {
|
||||||
case 1:
|
case 1:
|
||||||
return;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
_swap_ximage_2bytes (ximage);
|
_swap_ximage_2bytes (ximage);
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
|
_swap_ximage_3bytes (ximage);
|
||||||
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
_swap_ximage_4bytes (ximage);
|
_swap_ximage_4bytes (ximage);
|
||||||
break;
|
break;
|
||||||
|
@ -678,8 +721,11 @@ _get_image_surface (cairo_xlib_surface_t *surface,
|
||||||
xlib_masks.green_mask = surface->g_mask;
|
xlib_masks.green_mask = surface->g_mask;
|
||||||
xlib_masks.blue_mask = surface->b_mask;
|
xlib_masks.blue_mask = surface->b_mask;
|
||||||
|
|
||||||
status = _pixman_format_from_masks (&xlib_masks, &pixman_format);
|
if (_pixman_format_from_masks (&xlib_masks, &pixman_format) &&
|
||||||
if (xlib_masks.bpp >= 24 &&status == CAIRO_STATUS_SUCCESS) {
|
xlib_masks.bpp >= 24 &&
|
||||||
|
ximage->bitmap_unit == 32 &&
|
||||||
|
ximage->bitmap_pad == 32)
|
||||||
|
{
|
||||||
image = (cairo_image_surface_t*)
|
image = (cairo_image_surface_t*)
|
||||||
_cairo_image_surface_create_with_pixman_format ((unsigned char *) ximage->data,
|
_cairo_image_surface_create_with_pixman_format ((unsigned char *) ximage->data,
|
||||||
pixman_format,
|
pixman_format,
|
||||||
|
@ -1009,7 +1055,14 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
|
||||||
else
|
else
|
||||||
in_pixel = row[x];
|
in_pixel = row[x];
|
||||||
|
|
||||||
a = _field_to_8 (in_pixel & image_masks.alpha_mask, i_a_width, i_a_shift);
|
/* If the incoming image has no alpha channel, then the input
|
||||||
|
* is opaque and the output should have the maximum alpha value.
|
||||||
|
* For all other channels, their absence implies 0.
|
||||||
|
*/
|
||||||
|
if (image_masks.alpha_mask == 0x0)
|
||||||
|
a = 0xff;
|
||||||
|
else
|
||||||
|
a = _field_to_8 (in_pixel & image_masks.alpha_mask, i_a_width, i_a_shift);
|
||||||
r = _field_to_8 (in_pixel & image_masks.red_mask , i_r_width, i_r_shift);
|
r = _field_to_8 (in_pixel & image_masks.red_mask , i_r_width, i_r_shift);
|
||||||
g = _field_to_8 (in_pixel & image_masks.green_mask, i_g_width, i_g_shift);
|
g = _field_to_8 (in_pixel & image_masks.green_mask, i_g_width, i_g_shift);
|
||||||
b = _field_to_8 (in_pixel & image_masks.blue_mask , i_b_width, i_b_shift);
|
b = _field_to_8 (in_pixel & image_masks.blue_mask , i_b_width, i_b_shift);
|
||||||
|
@ -1054,7 +1107,7 @@ _cairo_xlib_surface_acquire_source_image (void *abstract_surf
|
||||||
cairo_image_surface_t *image;
|
cairo_image_surface_t *image;
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
|
||||||
_cairo_xlib_display_notify (surface->screen_info->display);
|
_cairo_xlib_display_notify (surface->display);
|
||||||
|
|
||||||
status = _get_image_surface (surface, NULL, &image, NULL);
|
status = _get_image_surface (surface, NULL, &image, NULL);
|
||||||
if (status)
|
if (status)
|
||||||
|
@ -1085,7 +1138,7 @@ _cairo_xlib_surface_acquire_dest_image (void *abstract_surfac
|
||||||
cairo_image_surface_t *image;
|
cairo_image_surface_t *image;
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
|
||||||
_cairo_xlib_display_notify (surface->screen_info->display);
|
_cairo_xlib_display_notify (surface->display);
|
||||||
|
|
||||||
status = _get_image_surface (surface, interest_rect, &image, image_rect_out);
|
status = _get_image_surface (surface, interest_rect, &image, image_rect_out);
|
||||||
if (status)
|
if (status)
|
||||||
|
@ -1134,18 +1187,22 @@ _cairo_xlib_surface_clone_similar (void *abstract_surface,
|
||||||
int src_y,
|
int src_y,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
|
int *clone_offset_x,
|
||||||
|
int *clone_offset_y,
|
||||||
cairo_surface_t **clone_out)
|
cairo_surface_t **clone_out)
|
||||||
{
|
{
|
||||||
cairo_xlib_surface_t *surface = abstract_surface;
|
cairo_xlib_surface_t *surface = abstract_surface;
|
||||||
cairo_xlib_surface_t *clone;
|
cairo_xlib_surface_t *clone;
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
|
||||||
_cairo_xlib_display_notify (surface->screen_info->display);
|
_cairo_xlib_display_notify (surface->display);
|
||||||
|
|
||||||
if (src->backend == surface->base.backend ) {
|
if (src->backend == surface->base.backend ) {
|
||||||
cairo_xlib_surface_t *xlib_src = (cairo_xlib_surface_t *)src;
|
cairo_xlib_surface_t *xlib_src = (cairo_xlib_surface_t *)src;
|
||||||
|
|
||||||
if (_cairo_xlib_surface_same_screen (surface, xlib_src)) {
|
if (_cairo_xlib_surface_same_screen (surface, xlib_src)) {
|
||||||
|
*clone_offset_x = 0;
|
||||||
|
*clone_offset_y = 0;
|
||||||
*clone_out = cairo_surface_reference (src);
|
*clone_out = cairo_surface_reference (src);
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
@ -1156,25 +1213,30 @@ _cairo_xlib_surface_clone_similar (void *abstract_surface,
|
||||||
if (! CAIRO_FORMAT_VALID (image_src->format))
|
if (! CAIRO_FORMAT_VALID (image_src->format))
|
||||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
if (image_src->width > XLIB_COORD_MAX || image_src->height > XLIB_COORD_MAX)
|
if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
|
||||||
return CAIRO_STATUS_NO_MEMORY;
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
|
|
||||||
clone = (cairo_xlib_surface_t *)
|
clone = (cairo_xlib_surface_t *)
|
||||||
_cairo_xlib_surface_create_similar_with_format (surface, image_src->format,
|
_cairo_xlib_surface_create_similar_with_format (surface,
|
||||||
image_src->width, image_src->height);
|
image_src->format,
|
||||||
|
width, height);
|
||||||
if (clone == NULL)
|
if (clone == NULL)
|
||||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
if (clone->base.status)
|
if (clone->base.status)
|
||||||
return clone->base.status;
|
return clone->base.status;
|
||||||
|
|
||||||
status = _draw_image_surface (clone, image_src, src_x, src_y,
|
status = _draw_image_surface (clone, image_src,
|
||||||
width, height, src_x, src_y);
|
src_x, src_y,
|
||||||
|
width, height,
|
||||||
|
0, 0);
|
||||||
if (status) {
|
if (status) {
|
||||||
cairo_surface_destroy (&clone->base);
|
cairo_surface_destroy (&clone->base);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*clone_offset_x = src_x;
|
||||||
|
*clone_offset_y = src_y;
|
||||||
*clone_out = &clone->base;
|
*clone_out = &clone->base;
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
@ -1233,9 +1295,10 @@ _cairo_xlib_surface_create_solid_pattern_surface (void *abstrac
|
||||||
status = surface->base.status;
|
status = surface->base.status;
|
||||||
if (status)
|
if (status)
|
||||||
goto BAIL;
|
goto BAIL;
|
||||||
surface->owns_pixmap = TRUE;
|
|
||||||
|
|
||||||
status = _cairo_surface_paint (&image->base, CAIRO_OPERATOR_SOURCE, &solid_pattern->base);
|
status = _cairo_surface_paint (&image->base,
|
||||||
|
CAIRO_OPERATOR_SOURCE,
|
||||||
|
&solid_pattern->base);
|
||||||
if (status)
|
if (status)
|
||||||
goto BAIL;
|
goto BAIL;
|
||||||
|
|
||||||
|
@ -1246,17 +1309,19 @@ _cairo_xlib_surface_create_solid_pattern_surface (void *abstrac
|
||||||
if (status)
|
if (status)
|
||||||
goto BAIL;
|
goto BAIL;
|
||||||
|
|
||||||
|
|
||||||
BAIL:
|
BAIL:
|
||||||
cairo_surface_destroy (&image->base);
|
cairo_surface_destroy (&image->base);
|
||||||
|
|
||||||
if (status && surface) {
|
if (status) {
|
||||||
XFreePixmap (other->dpy, pixmap);
|
if (pixmap != None)
|
||||||
|
XFreePixmap (other->dpy, pixmap);
|
||||||
cairo_surface_destroy (&surface->base);
|
cairo_surface_destroy (&surface->base);
|
||||||
surface = NULL;
|
|
||||||
|
return _cairo_surface_create_in_error (status);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (cairo_surface_t *) surface;
|
surface->owns_pixmap = TRUE;
|
||||||
|
return &surface->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cairo_status_t
|
static cairo_status_t
|
||||||
|
@ -1267,25 +1332,18 @@ _cairo_xlib_surface_set_matrix (cairo_xlib_surface_t *surface,
|
||||||
|
|
||||||
if (!surface->src_picture)
|
if (!surface->src_picture)
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
|
||||||
xtransform.matrix[0][0] = _cairo_fixed_16_16_from_double (matrix->xx);
|
/* Casting between pixman_transform_t and XTransform is safe because
|
||||||
xtransform.matrix[0][1] = _cairo_fixed_16_16_from_double (matrix->xy);
|
* they happen to be the exact same type.
|
||||||
xtransform.matrix[0][2] = _cairo_fixed_16_16_from_double (matrix->x0);
|
*/
|
||||||
|
_cairo_matrix_to_pixman_matrix (matrix, (pixman_transform_t *)&xtransform);
|
||||||
xtransform.matrix[1][0] = _cairo_fixed_16_16_from_double (matrix->yx);
|
|
||||||
xtransform.matrix[1][1] = _cairo_fixed_16_16_from_double (matrix->yy);
|
|
||||||
xtransform.matrix[1][2] = _cairo_fixed_16_16_from_double (matrix->y0);
|
|
||||||
|
|
||||||
xtransform.matrix[2][0] = 0;
|
|
||||||
xtransform.matrix[2][1] = 0;
|
|
||||||
xtransform.matrix[2][2] = 1 << 16;
|
|
||||||
|
|
||||||
if (memcmp (&xtransform, &surface->xtransform, sizeof (XTransform)) == 0)
|
if (memcmp (&xtransform, &surface->xtransform, sizeof (XTransform)) == 0)
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
|
||||||
if (!CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM (surface))
|
if (!CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM (surface))
|
||||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
XRenderSetPictureTransform (surface->dpy, surface->src_picture, &xtransform);
|
XRenderSetPictureTransform (surface->dpy, surface->src_picture, &xtransform);
|
||||||
surface->xtransform = xtransform;
|
surface->xtransform = xtransform;
|
||||||
|
|
||||||
|
@ -1379,10 +1437,10 @@ _cairo_xlib_surface_set_attributes (cairo_xlib_surface_t *surface,
|
||||||
|
|
||||||
switch (attributes->extend) {
|
switch (attributes->extend) {
|
||||||
case CAIRO_EXTEND_NONE:
|
case CAIRO_EXTEND_NONE:
|
||||||
_cairo_xlib_surface_set_repeat (surface, 0);
|
_cairo_xlib_surface_set_repeat (surface, RepeatNone);
|
||||||
break;
|
break;
|
||||||
case CAIRO_EXTEND_REPEAT:
|
case CAIRO_EXTEND_REPEAT:
|
||||||
_cairo_xlib_surface_set_repeat (surface, 1);
|
_cairo_xlib_surface_set_repeat (surface, RepeatNormal);
|
||||||
break;
|
break;
|
||||||
case CAIRO_EXTEND_REFLECT:
|
case CAIRO_EXTEND_REFLECT:
|
||||||
case CAIRO_EXTEND_PAD:
|
case CAIRO_EXTEND_PAD:
|
||||||
|
@ -1414,7 +1472,9 @@ _surfaces_compatible (cairo_xlib_surface_t *dst,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* if Render is supported, match picture formats */
|
/* if Render is supported, match picture formats */
|
||||||
if (src->xrender_format != NULL && src->xrender_format == dst->xrender_format)
|
if (src->xrender_format != dst->xrender_format)
|
||||||
|
return FALSE;
|
||||||
|
else if (src->xrender_format != NULL)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* Without Render, match visuals instead */
|
/* Without Render, match visuals instead */
|
||||||
|
@ -1557,17 +1617,17 @@ _recategorize_composite_operation (cairo_xlib_surface_t *dst,
|
||||||
_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL);
|
_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL);
|
||||||
cairo_bool_t needs_alpha_composite;
|
cairo_bool_t needs_alpha_composite;
|
||||||
|
|
||||||
if (!_cairo_surface_is_xlib (&src->base))
|
if (! _cairo_surface_is_xlib (&src->base))
|
||||||
return DO_UNSUPPORTED;
|
return DO_UNSUPPORTED;
|
||||||
|
|
||||||
needs_alpha_composite =
|
needs_alpha_composite =
|
||||||
_operator_needs_alpha_composite (op, _surface_has_alpha (src));
|
_operator_needs_alpha_composite (op, _surface_has_alpha (src));
|
||||||
|
|
||||||
if (!have_mask &&
|
if (! have_mask &&
|
||||||
is_integer_translation &&
|
is_integer_translation &&
|
||||||
src_attr->extend == CAIRO_EXTEND_NONE &&
|
src_attr->extend == CAIRO_EXTEND_NONE &&
|
||||||
!needs_alpha_composite &&
|
! needs_alpha_composite &&
|
||||||
_surfaces_compatible(src, dst))
|
_surfaces_compatible (src, dst))
|
||||||
{
|
{
|
||||||
return DO_XCOPYAREA;
|
return DO_XCOPYAREA;
|
||||||
}
|
}
|
||||||
|
@ -1577,8 +1637,8 @@ _recategorize_composite_operation (cairo_xlib_surface_t *dst,
|
||||||
src_attr->extend == CAIRO_EXTEND_REPEAT &&
|
src_attr->extend == CAIRO_EXTEND_REPEAT &&
|
||||||
(src->width != 1 || src->height != 1))
|
(src->width != 1 || src->height != 1))
|
||||||
{
|
{
|
||||||
if (!have_mask &&
|
if (! have_mask &&
|
||||||
!needs_alpha_composite &&
|
! needs_alpha_composite &&
|
||||||
_surfaces_compatible (dst, src))
|
_surfaces_compatible (dst, src))
|
||||||
{
|
{
|
||||||
return DO_XTILE;
|
return DO_XTILE;
|
||||||
|
@ -1587,10 +1647,10 @@ _recategorize_composite_operation (cairo_xlib_surface_t *dst,
|
||||||
return DO_UNSUPPORTED;
|
return DO_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src))
|
if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src))
|
||||||
return DO_UNSUPPORTED;
|
return DO_UNSUPPORTED;
|
||||||
|
|
||||||
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))
|
if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))
|
||||||
return DO_UNSUPPORTED;
|
return DO_UNSUPPORTED;
|
||||||
|
|
||||||
return DO_RENDER;
|
return DO_RENDER;
|
||||||
|
@ -1659,7 +1719,7 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
|
||||||
int itx, ity;
|
int itx, ity;
|
||||||
cairo_bool_t is_integer_translation;
|
cairo_bool_t is_integer_translation;
|
||||||
|
|
||||||
_cairo_xlib_display_notify (dst->screen_info->display);
|
_cairo_xlib_display_notify (dst->display);
|
||||||
|
|
||||||
operation = _categorize_composite_operation (dst, op, src_pattern,
|
operation = _categorize_composite_operation (dst, op, src_pattern,
|
||||||
mask_pattern != NULL);
|
mask_pattern != NULL);
|
||||||
|
@ -1682,7 +1742,10 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
|
||||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
goto BAIL;
|
goto BAIL;
|
||||||
}
|
}
|
||||||
if (mask != NULL && !_cairo_surface_is_xlib (&mask->base)) {
|
if (mask != NULL &&
|
||||||
|
(! _cairo_surface_is_xlib (&mask->base) ||
|
||||||
|
! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst)))
|
||||||
|
{
|
||||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
goto BAIL;
|
goto BAIL;
|
||||||
}
|
}
|
||||||
|
@ -1737,12 +1800,18 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
|
||||||
status = _cairo_xlib_surface_ensure_gc (dst);
|
status = _cairo_xlib_surface_ensure_gc (dst);
|
||||||
if (status)
|
if (status)
|
||||||
goto BAIL;
|
goto BAIL;
|
||||||
|
|
||||||
|
is_integer_translation = _cairo_matrix_is_integer_translation (&src_attr.matrix,
|
||||||
|
&itx, &ity);
|
||||||
|
/* This is a pre-condition for DO_XCOPYAREA. */
|
||||||
|
assert (is_integer_translation);
|
||||||
|
|
||||||
XCopyArea (dst->dpy,
|
XCopyArea (dst->dpy,
|
||||||
src->drawable,
|
src->drawable,
|
||||||
dst->drawable,
|
dst->drawable,
|
||||||
dst->gc,
|
dst->gc,
|
||||||
src_x + src_attr.x_offset,
|
src_x + src_attr.x_offset + itx,
|
||||||
src_y + src_attr.y_offset,
|
src_y + src_attr.y_offset + ity,
|
||||||
width, height,
|
width, height,
|
||||||
dst_x, dst_y);
|
dst_x, dst_y);
|
||||||
break;
|
break;
|
||||||
|
@ -1803,7 +1872,7 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface,
|
||||||
cairo_rectangle_int_t *rects,
|
cairo_rectangle_int_t *rects,
|
||||||
int num_rects)
|
int num_rects)
|
||||||
{
|
{
|
||||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
cairo_status_t status;
|
||||||
cairo_solid_pattern_t solid;
|
cairo_solid_pattern_t solid;
|
||||||
cairo_surface_t *solid_surface = NULL;
|
cairo_surface_t *solid_surface = NULL;
|
||||||
cairo_surface_attributes_t attrs;
|
cairo_surface_attributes_t attrs;
|
||||||
|
@ -1815,7 +1884,7 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface,
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
status = _cairo_pattern_acquire_surface (&solid.base, (cairo_surface_t *) surface,
|
status = _cairo_pattern_acquire_surface (&solid.base, &surface->base,
|
||||||
0, 0,
|
0, 0,
|
||||||
ARRAY_LENGTH (dither_pattern[0]),
|
ARRAY_LENGTH (dither_pattern[0]),
|
||||||
ARRAY_LENGTH (dither_pattern),
|
ARRAY_LENGTH (dither_pattern),
|
||||||
|
@ -1824,7 +1893,7 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface,
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
if (!_cairo_surface_is_xlib (solid_surface)) {
|
if (! _cairo_surface_is_xlib (solid_surface)) {
|
||||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
goto BAIL;
|
goto BAIL;
|
||||||
}
|
}
|
||||||
|
@ -1832,7 +1901,8 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface,
|
||||||
XSetTSOrigin (surface->dpy, surface->gc,
|
XSetTSOrigin (surface->dpy, surface->gc,
|
||||||
- (surface->base.device_transform.x0 + attrs.x_offset),
|
- (surface->base.device_transform.x0 + attrs.x_offset),
|
||||||
- (surface->base.device_transform.y0 + attrs.y_offset));
|
- (surface->base.device_transform.y0 + attrs.y_offset));
|
||||||
XSetTile (surface->dpy, surface->gc, ((cairo_xlib_surface_t *) solid_surface)->drawable);
|
XSetTile (surface->dpy, surface->gc,
|
||||||
|
((cairo_xlib_surface_t *) solid_surface)->drawable);
|
||||||
XSetFillStyle (surface->dpy, surface->gc, FillTiled);
|
XSetFillStyle (surface->dpy, surface->gc, FillTiled);
|
||||||
|
|
||||||
for (i = 0; i < num_rects; i++) {
|
for (i = 0; i < num_rects; i++) {
|
||||||
|
@ -1860,9 +1930,9 @@ _cairo_xlib_surface_fill_rectangles (void *abstract_surface,
|
||||||
XRectangle *xrects = static_xrects;
|
XRectangle *xrects = static_xrects;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
_cairo_xlib_display_notify (surface->screen_info->display);
|
_cairo_xlib_display_notify (surface->display);
|
||||||
|
|
||||||
if (!CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES (surface)) {
|
if (! CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES (surface)) {
|
||||||
if (op == CAIRO_OPERATOR_CLEAR ||
|
if (op == CAIRO_OPERATOR_CLEAR ||
|
||||||
((op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_OVER) &&
|
((op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_OVER) &&
|
||||||
CAIRO_COLOR_IS_OPAQUE (color)))
|
CAIRO_COLOR_IS_OPAQUE (color)))
|
||||||
|
@ -1918,10 +1988,17 @@ _create_a8_picture (cairo_xlib_surface_t *surface,
|
||||||
|
|
||||||
Pixmap pixmap;
|
Pixmap pixmap;
|
||||||
Picture picture;
|
Picture picture;
|
||||||
|
XRenderPictFormat *xrender_format;
|
||||||
|
|
||||||
if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
|
if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
|
||||||
return None;
|
return None;
|
||||||
|
|
||||||
|
xrender_format =
|
||||||
|
_cairo_xlib_display_get_xrender_format (surface->display,
|
||||||
|
CAIRO_FORMAT_A8);
|
||||||
|
if (xrender_format == NULL)
|
||||||
|
return None;
|
||||||
|
|
||||||
pixmap = XCreatePixmap (surface->dpy, surface->drawable,
|
pixmap = XCreatePixmap (surface->dpy, surface->drawable,
|
||||||
width <= 0 ? 1 : width,
|
width <= 0 ? 1 : width,
|
||||||
height <= 0 ? 1 : height,
|
height <= 0 ? 1 : height,
|
||||||
|
@ -1933,8 +2010,7 @@ _create_a8_picture (cairo_xlib_surface_t *surface,
|
||||||
}
|
}
|
||||||
|
|
||||||
picture = XRenderCreatePicture (surface->dpy, pixmap,
|
picture = XRenderCreatePicture (surface->dpy, pixmap,
|
||||||
XRenderFindStandardFormat (surface->dpy, PictStandardA8),
|
xrender_format, mask, &pa);
|
||||||
mask, &pa);
|
|
||||||
XRenderFillRectangle (surface->dpy, PictOpSrc, picture, color,
|
XRenderFillRectangle (surface->dpy, PictOpSrc, picture, color,
|
||||||
0, 0, width, height);
|
0, 0, width, height);
|
||||||
XFreePixmap (surface->dpy, pixmap);
|
XFreePixmap (surface->dpy, pixmap);
|
||||||
|
@ -1993,6 +2069,11 @@ _create_trapezoid_mask (cairo_xlib_surface_t *dst,
|
||||||
}
|
}
|
||||||
|
|
||||||
solid_picture = _create_a8_picture (dst, &solid, width, height, TRUE);
|
solid_picture = _create_a8_picture (dst, &solid, width, height, TRUE);
|
||||||
|
if (solid_picture == None) {
|
||||||
|
XRenderFreePicture (dst->dpy, mask_picture);
|
||||||
|
free (offset_traps);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
XRenderCompositeTrapezoids (dst->dpy, PictOpAdd,
|
XRenderCompositeTrapezoids (dst->dpy, PictOpAdd,
|
||||||
solid_picture, mask_picture,
|
solid_picture, mask_picture,
|
||||||
|
@ -2029,7 +2110,7 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op,
|
||||||
int render_src_x, render_src_y;
|
int render_src_x, render_src_y;
|
||||||
XRenderPictFormat *pict_format;
|
XRenderPictFormat *pict_format;
|
||||||
|
|
||||||
_cairo_xlib_display_notify (dst->screen_info->display);
|
_cairo_xlib_display_notify (dst->display);
|
||||||
|
|
||||||
if (!CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst))
|
if (!CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst))
|
||||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
@ -2045,7 +2126,8 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op,
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
operation = _recategorize_composite_operation (dst, op, src, &attributes, TRUE);
|
operation = _recategorize_composite_operation (dst, op, src,
|
||||||
|
&attributes, TRUE);
|
||||||
if (operation == DO_UNSUPPORTED) {
|
if (operation == DO_UNSUPPORTED) {
|
||||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
goto BAIL;
|
goto BAIL;
|
||||||
|
@ -2053,13 +2135,17 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op,
|
||||||
|
|
||||||
switch (antialias) {
|
switch (antialias) {
|
||||||
case CAIRO_ANTIALIAS_NONE:
|
case CAIRO_ANTIALIAS_NONE:
|
||||||
pict_format = XRenderFindStandardFormat (dst->dpy, PictStandardA1);
|
pict_format =
|
||||||
|
_cairo_xlib_display_get_xrender_format (dst->display,
|
||||||
|
CAIRO_FORMAT_A1);
|
||||||
break;
|
break;
|
||||||
case CAIRO_ANTIALIAS_GRAY:
|
case CAIRO_ANTIALIAS_GRAY:
|
||||||
case CAIRO_ANTIALIAS_SUBPIXEL:
|
case CAIRO_ANTIALIAS_SUBPIXEL:
|
||||||
case CAIRO_ANTIALIAS_DEFAULT:
|
case CAIRO_ANTIALIAS_DEFAULT:
|
||||||
default:
|
default:
|
||||||
pict_format = XRenderFindStandardFormat (dst->dpy, PictStandardA8);
|
pict_format =
|
||||||
|
_cairo_xlib_display_get_xrender_format (dst->display,
|
||||||
|
CAIRO_FORMAT_A8);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2310,7 +2396,7 @@ _cairo_xlib_surface_is_similar (void *surface_a,
|
||||||
_xrender_format_to_content (xrender_format) != content)
|
_xrender_format_to_content (xrender_format) != content)
|
||||||
{
|
{
|
||||||
xrender_format = _cairo_xlib_display_get_xrender_format (
|
xrender_format = _cairo_xlib_display_get_xrender_format (
|
||||||
b->screen_info->display,
|
b->display,
|
||||||
_cairo_format_from_content (content));
|
_cairo_format_from_content (content));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2486,15 +2572,24 @@ _cairo_xlib_surface_create_internal (Display *dpy,
|
||||||
|
|
||||||
if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface)) {
|
if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface)) {
|
||||||
if (!xrender_format) {
|
if (!xrender_format) {
|
||||||
if (visual)
|
if (visual) {
|
||||||
xrender_format = XRenderFindVisualFormat (dpy, visual);
|
xrender_format = XRenderFindVisualFormat (dpy, visual);
|
||||||
else if (depth == 1)
|
} else if (depth == 1) {
|
||||||
xrender_format = XRenderFindStandardFormat (dpy, PictStandardA1);
|
xrender_format =
|
||||||
|
_cairo_xlib_display_get_xrender_format (display,
|
||||||
|
CAIRO_FORMAT_A1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
xrender_format = NULL;
|
xrender_format = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* we cannot use XRender for this surface, so ensure we don't try */
|
||||||
|
if (xrender_format == NULL) {
|
||||||
|
surface->render_major = -1;
|
||||||
|
surface->render_minor = -1;
|
||||||
|
}
|
||||||
|
|
||||||
_cairo_surface_init (&surface->base, &cairo_xlib_surface_backend,
|
_cairo_surface_init (&surface->base, &cairo_xlib_surface_backend,
|
||||||
_xrender_format_to_content (xrender_format));
|
_xrender_format_to_content (xrender_format));
|
||||||
|
|
||||||
|
@ -2787,7 +2882,7 @@ cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface,
|
||||||
if (surface->drawable != drawable) {
|
if (surface->drawable != drawable) {
|
||||||
if (surface->dst_picture != None) {
|
if (surface->dst_picture != None) {
|
||||||
status = _cairo_xlib_display_queue_resource (
|
status = _cairo_xlib_display_queue_resource (
|
||||||
surface->screen_info->display,
|
surface->display,
|
||||||
XRenderFreePicture,
|
XRenderFreePicture,
|
||||||
surface->dst_picture);
|
surface->dst_picture);
|
||||||
if (status) {
|
if (status) {
|
||||||
|
@ -2800,7 +2895,7 @@ cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface,
|
||||||
|
|
||||||
if (surface->src_picture != None) {
|
if (surface->src_picture != None) {
|
||||||
status = _cairo_xlib_display_queue_resource (
|
status = _cairo_xlib_display_queue_resource (
|
||||||
surface->screen_info->display,
|
surface->display,
|
||||||
XRenderFreePicture,
|
XRenderFreePicture,
|
||||||
surface->src_picture);
|
surface->src_picture);
|
||||||
if (status) {
|
if (status) {
|
||||||
|
@ -3019,7 +3114,7 @@ _cairo_xlib_surface_remove_scaled_font (cairo_xlib_display_t *display,
|
||||||
scaled_font = font_private->scaled_font;
|
scaled_font = font_private->scaled_font;
|
||||||
|
|
||||||
CAIRO_MUTEX_LOCK (scaled_font->mutex);
|
CAIRO_MUTEX_LOCK (scaled_font->mutex);
|
||||||
font_private = scaled_font->surface_private;
|
font_private = scaled_font->surface_private;
|
||||||
scaled_font->surface_private = NULL;
|
scaled_font->surface_private = NULL;
|
||||||
|
|
||||||
_cairo_scaled_font_reset_cache (scaled_font);
|
_cairo_scaled_font_reset_cache (scaled_font);
|
||||||
|
@ -3331,7 +3426,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
|
||||||
CAIRO_SCALED_GLYPH_INFO_METRICS |
|
CAIRO_SCALED_GLYPH_INFO_METRICS |
|
||||||
CAIRO_SCALED_GLYPH_INFO_SURFACE,
|
CAIRO_SCALED_GLYPH_INFO_SURFACE,
|
||||||
pscaled_glyph);
|
pscaled_glyph);
|
||||||
if (status != CAIRO_STATUS_SUCCESS)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
scaled_glyph = *pscaled_glyph;
|
scaled_glyph = *pscaled_glyph;
|
||||||
|
@ -3369,7 +3464,8 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
|
||||||
cairo_surface_t *tmp_surface;
|
cairo_surface_t *tmp_surface;
|
||||||
|
|
||||||
tmp_surface = cairo_image_surface_create (glyphset_info->format, 1, 1);
|
tmp_surface = cairo_image_surface_create (glyphset_info->format, 1, 1);
|
||||||
if (tmp_surface->status)
|
status = tmp_surface->status;
|
||||||
|
if (status)
|
||||||
goto BAIL;
|
goto BAIL;
|
||||||
|
|
||||||
cr = cairo_create (tmp_surface);
|
cr = cairo_create (tmp_surface);
|
||||||
|
@ -3398,7 +3494,8 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
|
||||||
tmp_surface = cairo_image_surface_create (glyphset_info->format,
|
tmp_surface = cairo_image_surface_create (glyphset_info->format,
|
||||||
glyph_surface->width,
|
glyph_surface->width,
|
||||||
glyph_surface->height);
|
glyph_surface->height);
|
||||||
if (tmp_surface->status)
|
status = tmp_surface->status;
|
||||||
|
if (status)
|
||||||
goto BAIL;
|
goto BAIL;
|
||||||
|
|
||||||
tmp_surface->device_transform = glyph_surface->base.device_transform;
|
tmp_surface->device_transform = glyph_surface->base.device_transform;
|
||||||
|
@ -3544,18 +3641,29 @@ typedef union {
|
||||||
/* compile-time assert that #cairo_xlib_glyph_t is the same size as #cairo_glyph_t */
|
/* compile-time assert that #cairo_xlib_glyph_t is the same size as #cairo_glyph_t */
|
||||||
COMPILE_TIME_ASSERT (sizeof (cairo_xlib_glyph_t) == sizeof (cairo_glyph_t));
|
COMPILE_TIME_ASSERT (sizeof (cairo_xlib_glyph_t) == sizeof (cairo_glyph_t));
|
||||||
|
|
||||||
|
/* Start a new element for the first glyph,
|
||||||
|
* or for any glyph that has unexpected position,
|
||||||
|
* or if current element has too many glyphs
|
||||||
|
* (Xrender limits each element to 252 glyphs, we limit them to 128)
|
||||||
|
*
|
||||||
|
* These same conditions need to be mirrored between
|
||||||
|
* _cairo_xlib_surface_emit_glyphs and _emit_glyph_chunks
|
||||||
|
*/
|
||||||
|
#define _start_new_glyph_elt(count, glyph) \
|
||||||
|
(((count) & 127) == 0 || (glyph)->i.x || (glyph)->i.y)
|
||||||
|
|
||||||
static cairo_status_t
|
static cairo_status_t
|
||||||
_cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
|
_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
|
||||||
cairo_xlib_glyph_t *glyphs,
|
cairo_xlib_glyph_t *glyphs,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
cairo_scaled_font_t *scaled_font,
|
cairo_scaled_font_t *scaled_font,
|
||||||
cairo_operator_t op,
|
cairo_operator_t op,
|
||||||
cairo_xlib_surface_t *src,
|
cairo_xlib_surface_t *src,
|
||||||
cairo_surface_attributes_t *attributes,
|
cairo_surface_attributes_t *attributes,
|
||||||
/* info for this chunk */
|
/* info for this chunk */
|
||||||
int num_elts,
|
int num_elts,
|
||||||
int width,
|
int width,
|
||||||
cairo_xlib_font_glyphset_info_t *glyphset_info)
|
cairo_xlib_font_glyphset_info_t *glyphset_info)
|
||||||
{
|
{
|
||||||
/* Which XRenderCompositeText function to use */
|
/* Which XRenderCompositeText function to use */
|
||||||
cairo_xrender_composite_text_func_t composite_text_func;
|
cairo_xrender_composite_text_func_t composite_text_func;
|
||||||
|
@ -3606,9 +3714,13 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
|
||||||
j = 0;
|
j = 0;
|
||||||
for (i = 0; i < num_glyphs; i++) {
|
for (i = 0; i < num_glyphs; i++) {
|
||||||
|
|
||||||
/* Start a new element for first output glyph, and for glyphs with
|
/* Start a new element for first output glyph,
|
||||||
* unexpected position */
|
* or for any glyph that has unexpected position,
|
||||||
if (!j || glyphs[i].i.x || glyphs[i].i.y) {
|
* or if current element has too many glyphs.
|
||||||
|
*
|
||||||
|
* These same conditions are mirrored in _cairo_xlib_surface_emit_glyphs()
|
||||||
|
*/
|
||||||
|
if (_start_new_glyph_elt (j, &glyphs[i])) {
|
||||||
if (j) {
|
if (j) {
|
||||||
elts[nelt].nchars = n;
|
elts[nelt].nchars = n;
|
||||||
nelt++;
|
nelt++;
|
||||||
|
@ -3637,6 +3749,10 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
|
||||||
n = 0;
|
n = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check that we agree with _cairo_xlib_surface_emit_glyphs() on the
|
||||||
|
* expected number of xGlyphElts. */
|
||||||
|
assert (nelt == num_elts);
|
||||||
|
|
||||||
composite_text_func (dst->dpy,
|
composite_text_func (dst->dpy,
|
||||||
_render_operator (op),
|
_render_operator (op),
|
||||||
src->src_picture,
|
src->src_picture,
|
||||||
|
@ -3653,6 +3769,11 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* sz_xGlyphtElt required alignment to a 32-bit boundary, so ensure we have
|
||||||
|
* enough room for padding */
|
||||||
|
#define _cairo_sz_xGlyphElt (sz_xGlyphElt + 4)
|
||||||
|
|
||||||
static cairo_status_t
|
static cairo_status_t
|
||||||
_cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
|
_cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
|
||||||
cairo_xlib_glyph_t *glyphs,
|
cairo_xlib_glyph_t *glyphs,
|
||||||
|
@ -3681,7 +3802,7 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
|
||||||
int request_size = 0;
|
int request_size = 0;
|
||||||
|
|
||||||
_cairo_xlib_surface_ensure_dst_picture (dst);
|
_cairo_xlib_surface_ensure_dst_picture (dst);
|
||||||
_cairo_xlib_display_notify (dst->screen_info->display);
|
_cairo_xlib_display_notify (dst->display);
|
||||||
|
|
||||||
for (i = 0; i < num_glyphs; i++) {
|
for (i = 0; i < num_glyphs; i++) {
|
||||||
int this_x, this_y;
|
int this_x, this_y;
|
||||||
|
@ -3738,6 +3859,10 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
|
||||||
if (!glyphset_info)
|
if (!glyphset_info)
|
||||||
glyphset_info = this_glyphset_info;
|
glyphset_info = this_glyphset_info;
|
||||||
|
|
||||||
|
/* The invariant here is that we can always flush the glyphs
|
||||||
|
* accumulated before this one, using old_width, and they
|
||||||
|
* would fit in the request.
|
||||||
|
*/
|
||||||
old_width = width;
|
old_width = width;
|
||||||
|
|
||||||
/* Update max glyph index */
|
/* Update max glyph index */
|
||||||
|
@ -3762,11 +3887,11 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
|
||||||
* to the mask first, and then composes that to final surface,
|
* to the mask first, and then composes that to final surface,
|
||||||
* though it's not a big deal.
|
* though it's not a big deal.
|
||||||
*/
|
*/
|
||||||
if (request_size + width > max_request_size - sz_xGlyphElt ||
|
if (request_size + width > max_request_size - _cairo_sz_xGlyphElt ||
|
||||||
(this_glyphset_info != glyphset_info)) {
|
(this_glyphset_info != glyphset_info)) {
|
||||||
status = _cairo_xlib_surface_emit_glyphs_chunk (dst, glyphs, i,
|
status = _emit_glyphs_chunk (dst, glyphs, i,
|
||||||
scaled_font, op, src, attributes,
|
scaled_font, op, src, attributes,
|
||||||
num_elts, old_width, glyphset_info);
|
num_elts, old_width, glyphset_info);
|
||||||
if (status != CAIRO_STATUS_SUCCESS)
|
if (status != CAIRO_STATUS_SUCCESS)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
@ -3787,11 +3912,15 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
|
||||||
glyphs[i].i.x = this_x - x;
|
glyphs[i].i.x = this_x - x;
|
||||||
glyphs[i].i.y = this_y - y;
|
glyphs[i].i.y = this_y - y;
|
||||||
|
|
||||||
/* Start a new element for the first glyph, or for any glyph that
|
/* Start a new element for the first glyph,
|
||||||
* has unexpected position */
|
* or for any glyph that has unexpected position,
|
||||||
if (!num_out_glyphs || glyphs[i].i.x || glyphs[i].i.y) {
|
* or if current element has too many glyphs.
|
||||||
|
*
|
||||||
|
* These same conditions are mirrored in _emit_glyphs_chunk().
|
||||||
|
*/
|
||||||
|
if (_start_new_glyph_elt (num_out_glyphs, &glyphs[i])) {
|
||||||
num_elts++;
|
num_elts++;
|
||||||
request_size += sz_xGlyphElt;
|
request_size += _cairo_sz_xGlyphElt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* adjust current-position */
|
/* adjust current-position */
|
||||||
|
@ -3803,9 +3932,9 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_elts)
|
if (num_elts)
|
||||||
status = _cairo_xlib_surface_emit_glyphs_chunk (dst, glyphs, i,
|
status = _emit_glyphs_chunk (dst, glyphs, i,
|
||||||
scaled_font, op, src, attributes,
|
scaled_font, op, src, attributes,
|
||||||
num_elts, width, glyphset_info);
|
num_elts, width, glyphset_info);
|
||||||
|
|
||||||
*remaining_glyphs = num_glyphs - i;
|
*remaining_glyphs = num_glyphs - i;
|
||||||
if (*remaining_glyphs && status == CAIRO_STATUS_SUCCESS)
|
if (*remaining_glyphs && status == CAIRO_STATUS_SUCCESS)
|
||||||
|
@ -3814,6 +3943,23 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cairo_bool_t
|
||||||
|
_cairo_xlib_surface_owns_font (cairo_xlib_surface_t *dst,
|
||||||
|
cairo_scaled_font_t *scaled_font)
|
||||||
|
{
|
||||||
|
cairo_xlib_surface_font_private_t *font_private;
|
||||||
|
|
||||||
|
font_private = scaled_font->surface_private;
|
||||||
|
if ((scaled_font->surface_backend != NULL &&
|
||||||
|
scaled_font->surface_backend != &cairo_xlib_surface_backend) ||
|
||||||
|
(font_private != NULL && font_private->display != dst->display))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static cairo_int_status_t
|
static cairo_int_status_t
|
||||||
_cairo_xlib_surface_show_glyphs (void *abstract_dst,
|
_cairo_xlib_surface_show_glyphs (void *abstract_dst,
|
||||||
cairo_operator_t op,
|
cairo_operator_t op,
|
||||||
|
@ -3830,11 +3976,9 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
|
||||||
cairo_surface_attributes_t attributes;
|
cairo_surface_attributes_t attributes;
|
||||||
cairo_xlib_surface_t *src = NULL;
|
cairo_xlib_surface_t *src = NULL;
|
||||||
|
|
||||||
cairo_xlib_surface_font_private_t *font_private;
|
|
||||||
|
|
||||||
cairo_solid_pattern_t solid_pattern;
|
cairo_solid_pattern_t solid_pattern;
|
||||||
|
|
||||||
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst) || !dst->xrender_format)
|
if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst))
|
||||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
/* Just let unbounded operators go through the fallback code
|
/* Just let unbounded operators go through the fallback code
|
||||||
|
@ -3865,22 +4009,14 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
|
||||||
if (operation == DO_UNSUPPORTED)
|
if (operation == DO_UNSUPPORTED)
|
||||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
font_private = scaled_font->surface_private;
|
if (! _cairo_xlib_surface_owns_font (dst, scaled_font))
|
||||||
if ((scaled_font->surface_backend != NULL &&
|
|
||||||
scaled_font->surface_backend != &cairo_xlib_surface_backend) ||
|
|
||||||
(font_private != NULL && font_private->display != dst->screen_info->display))
|
|
||||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
|
||||||
/* After passing all those tests, we're now committed to rendering
|
/* After passing all those tests, we're now committed to rendering
|
||||||
* these glyphs or to fail trying. We first upload any glyphs to
|
* these glyphs or to fail trying. We first upload any glyphs to
|
||||||
* the X server that it doesn't have already, then we draw
|
* the X server that it doesn't have already, then we draw
|
||||||
* them. We tie into the scaled_font's glyph cache and remove
|
* them.
|
||||||
* glyphs from the X server when they are ejected from the
|
*/
|
||||||
* scaled_font cache. Because of this we first freeze the
|
|
||||||
* scaled_font's cache so that we don't cause any of our glyphs to
|
|
||||||
* be ejected and removed from the X server before we have a
|
|
||||||
* chance to render them. */
|
|
||||||
_cairo_scaled_font_freeze_cache (scaled_font);
|
|
||||||
|
|
||||||
/* PictOpClear doesn't seem to work with CompositeText; it seems to ignore
|
/* PictOpClear doesn't seem to work with CompositeText; it seems to ignore
|
||||||
* the mask (the glyphs). This code below was executed as a side effect
|
* the mask (the glyphs). This code below was executed as a side effect
|
||||||
|
@ -3920,7 +4056,8 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
|
||||||
goto BAIL0;
|
goto BAIL0;
|
||||||
}
|
}
|
||||||
|
|
||||||
operation = _recategorize_composite_operation (dst, op, src, &attributes, TRUE);
|
operation = _recategorize_composite_operation (dst, op, src,
|
||||||
|
&attributes, TRUE);
|
||||||
if (operation == DO_UNSUPPORTED) {
|
if (operation == DO_UNSUPPORTED) {
|
||||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
goto BAIL1;
|
goto BAIL1;
|
||||||
|
@ -3930,14 +4067,19 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
|
||||||
if (status)
|
if (status)
|
||||||
goto BAIL1;
|
goto BAIL1;
|
||||||
|
|
||||||
status = _cairo_xlib_surface_emit_glyphs (dst,
|
_cairo_scaled_font_freeze_cache (scaled_font);
|
||||||
(cairo_xlib_glyph_t *) glyphs,
|
if (_cairo_xlib_surface_owns_font (dst, scaled_font)) {
|
||||||
num_glyphs,
|
status = _cairo_xlib_surface_emit_glyphs (dst,
|
||||||
scaled_font,
|
(cairo_xlib_glyph_t *) glyphs,
|
||||||
op,
|
num_glyphs,
|
||||||
src,
|
scaled_font,
|
||||||
&attributes,
|
op,
|
||||||
remaining_glyphs);
|
src,
|
||||||
|
&attributes,
|
||||||
|
remaining_glyphs);
|
||||||
|
} else
|
||||||
|
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
|
_cairo_scaled_font_thaw_cache (scaled_font);
|
||||||
|
|
||||||
BAIL1:
|
BAIL1:
|
||||||
if (src)
|
if (src)
|
||||||
|
@ -3945,8 +4087,7 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
|
||||||
if (src_pattern == &solid_pattern.base)
|
if (src_pattern == &solid_pattern.base)
|
||||||
_cairo_pattern_fini (&solid_pattern.base);
|
_cairo_pattern_fini (&solid_pattern.base);
|
||||||
BAIL0:
|
BAIL0:
|
||||||
_cairo_scaled_font_thaw_cache (scaled_font);
|
_cairo_xlib_display_notify (dst->display);
|
||||||
_cairo_xlib_display_notify (dst->screen_info->display);
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
#include "cairo-arc-private.h"
|
#include "cairo-arc-private.h"
|
||||||
#include "cairo-path-private.h"
|
#include "cairo-path-private.h"
|
||||||
|
|
||||||
#define CAIRO_TOLERANCE_MINIMUM 0.0002 /* We're limited by 16 bits of sub-pixel precision */
|
#define CAIRO_TOLERANCE_MINIMUM _cairo_fixed_to_double(1)
|
||||||
|
|
||||||
static const cairo_t _cairo_nil = {
|
static const cairo_t _cairo_nil = {
|
||||||
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
|
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
|
||||||
|
@ -84,8 +84,7 @@ static const cairo_t _cairo_nil = {
|
||||||
cairo_status_t
|
cairo_status_t
|
||||||
_cairo_error (cairo_status_t status)
|
_cairo_error (cairo_status_t status)
|
||||||
{
|
{
|
||||||
assert (status > CAIRO_STATUS_SUCCESS &&
|
assert (_cairo_status_is_error (status));
|
||||||
status <= CAIRO_STATUS_LAST_STATUS);
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -288,7 +287,7 @@ cairo_set_user_data (cairo_t *cr,
|
||||||
cairo_destroy_func_t destroy)
|
cairo_destroy_func_t destroy)
|
||||||
{
|
{
|
||||||
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&cr->ref_count))
|
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&cr->ref_count))
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
return cr->status;
|
||||||
|
|
||||||
return _cairo_user_data_array_set_data (&cr->user_data,
|
return _cairo_user_data_array_set_data (&cr->user_data,
|
||||||
key, user_data, destroy);
|
key, user_data, destroy);
|
||||||
|
@ -926,6 +925,7 @@ cairo_set_line_width (cairo_t *cr, double width)
|
||||||
if (status)
|
if (status)
|
||||||
_cairo_set_error (cr, status);
|
_cairo_set_error (cr, status);
|
||||||
}
|
}
|
||||||
|
slim_hidden_def (cairo_set_line_width);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_set_line_cap:
|
* cairo_set_line_cap:
|
||||||
|
@ -955,6 +955,7 @@ cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap)
|
||||||
if (status)
|
if (status)
|
||||||
_cairo_set_error (cr, status);
|
_cairo_set_error (cr, status);
|
||||||
}
|
}
|
||||||
|
slim_hidden_def (cairo_set_line_cap);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_set_line_join:
|
* cairo_set_line_join:
|
||||||
|
@ -984,6 +985,7 @@ cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join)
|
||||||
if (status)
|
if (status)
|
||||||
_cairo_set_error (cr, status);
|
_cairo_set_error (cr, status);
|
||||||
}
|
}
|
||||||
|
slim_hidden_def (cairo_set_line_join);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_set_dash:
|
* cairo_set_dash:
|
||||||
|
@ -2087,6 +2089,7 @@ cairo_stroke (cairo_t *cr)
|
||||||
|
|
||||||
cairo_new_path (cr);
|
cairo_new_path (cr);
|
||||||
}
|
}
|
||||||
|
slim_hidden_def(cairo_stroke);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_stroke_preserve:
|
* cairo_stroke_preserve:
|
||||||
|
@ -3077,8 +3080,9 @@ cairo_show_text (cairo_t *cr, const char *utf8)
|
||||||
cairo_glyph_t *glyphs = NULL, *last_glyph;
|
cairo_glyph_t *glyphs = NULL, *last_glyph;
|
||||||
cairo_text_cluster_t *clusters = NULL;
|
cairo_text_cluster_t *clusters = NULL;
|
||||||
int utf8_len, num_glyphs, num_clusters;
|
int utf8_len, num_glyphs, num_clusters;
|
||||||
cairo_bool_t backward;
|
cairo_text_cluster_flags_t cluster_flags;
|
||||||
double x, y;
|
double x, y;
|
||||||
|
cairo_bool_t has_show_text_glyphs;
|
||||||
|
|
||||||
if (cr->status)
|
if (cr->status)
|
||||||
return;
|
return;
|
||||||
|
@ -3090,12 +3094,15 @@ cairo_show_text (cairo_t *cr, const char *utf8)
|
||||||
|
|
||||||
utf8_len = strlen (utf8);
|
utf8_len = strlen (utf8);
|
||||||
|
|
||||||
|
has_show_text_glyphs =
|
||||||
|
cairo_surface_has_show_text_glyphs (cairo_get_target (cr));
|
||||||
|
|
||||||
status = _cairo_gstate_text_to_glyphs (cr->gstate,
|
status = _cairo_gstate_text_to_glyphs (cr->gstate,
|
||||||
x, y,
|
x, y,
|
||||||
utf8, utf8_len,
|
utf8, utf8_len,
|
||||||
&glyphs, &num_glyphs,
|
&glyphs, &num_glyphs,
|
||||||
cairo_has_show_text_glyphs (cr) ? &clusters : NULL, &num_clusters,
|
has_show_text_glyphs ? &clusters : NULL, &num_clusters,
|
||||||
&backward);
|
&cluster_flags);
|
||||||
if (status)
|
if (status)
|
||||||
goto BAIL;
|
goto BAIL;
|
||||||
|
|
||||||
|
@ -3106,7 +3113,7 @@ cairo_show_text (cairo_t *cr, const char *utf8)
|
||||||
utf8, utf8_len,
|
utf8, utf8_len,
|
||||||
glyphs, num_glyphs,
|
glyphs, num_glyphs,
|
||||||
clusters, num_clusters,
|
clusters, num_clusters,
|
||||||
backward);
|
cluster_flags);
|
||||||
if (status)
|
if (status)
|
||||||
goto BAIL;
|
goto BAIL;
|
||||||
|
|
||||||
|
@ -3169,36 +3176,6 @@ cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs)
|
||||||
_cairo_set_error (cr, status);
|
_cairo_set_error (cr, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* cairo_has_show_text_glyphs:
|
|
||||||
* @cr: a cairo context
|
|
||||||
*
|
|
||||||
* Returns whether the target surface of a cairo context supports
|
|
||||||
* sophisticated cairo_show_text_glyphs() operations. That is,
|
|
||||||
* whether it actually uses the provided text and cluster data
|
|
||||||
* to a cairo_show_text_glyphs() call.
|
|
||||||
*
|
|
||||||
* Note: Even if this function returns %FALSE, a
|
|
||||||
* cairo_show_text_glyphs() operation will still succeed. It just will
|
|
||||||
* act like a cairo_show_glyphs() operation. Users can use this
|
|
||||||
* function to avoid computing UTF-8 text and cluster mapping if the
|
|
||||||
* target surface does not use it.
|
|
||||||
*
|
|
||||||
* This is a convenience function that simply calls
|
|
||||||
* cairo_surface_has_show_text_glyphs() on @cr's target.
|
|
||||||
*
|
|
||||||
* Return value: %TRUE if the target surface of @cr supports
|
|
||||||
* cairo_show_text_glyphs(), %FALSE otherwise
|
|
||||||
*
|
|
||||||
* Since: 1.8
|
|
||||||
**/
|
|
||||||
cairo_bool_t
|
|
||||||
cairo_has_show_text_glyphs (cairo_t *cr)
|
|
||||||
{
|
|
||||||
return _cairo_gstate_has_show_text_glyphs (cr->gstate);
|
|
||||||
}
|
|
||||||
slim_hidden_def (cairo_has_show_text_glyphs);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_show_text_glyphs:
|
* cairo_show_text_glyphs:
|
||||||
* @cr: a cairo context
|
* @cr: a cairo context
|
||||||
|
@ -3208,14 +3185,14 @@ slim_hidden_def (cairo_has_show_text_glyphs);
|
||||||
* @num_glyphs: number of glyphs to show
|
* @num_glyphs: number of glyphs to show
|
||||||
* @clusters: array of cluster mapping information
|
* @clusters: array of cluster mapping information
|
||||||
* @num_clusters: number of clusters in the mapping
|
* @num_clusters: number of clusters in the mapping
|
||||||
* @backward: whether the text to glyphs mapping goes backward
|
* @cluster_flags: cluster mapping flags
|
||||||
*
|
*
|
||||||
* This operation has rendering effects similar to cairo_show_glyphs()
|
* This operation has rendering effects similar to cairo_show_glyphs()
|
||||||
* but, if the target surface supports it, uses the provided text and
|
* but, if the target surface supports it, uses the provided text and
|
||||||
* cluster mapping to embed the text for the glyphs shown in the output.
|
* cluster mapping to embed the text for the glyphs shown in the output.
|
||||||
* The cairo_has_show_text_glyphs() function can be used to query that.
|
* If the target does not support the extended attributes, this function
|
||||||
* If the target does not support it, this function acts like
|
* acts like the basic cairo_show_glyphs() as if it had been passed
|
||||||
* cairo_show_glyphs().
|
* @glyphs and @num_glyphs.
|
||||||
*
|
*
|
||||||
* The mapping between @utf8 and @glyphs is provided by an array of
|
* The mapping between @utf8 and @glyphs is provided by an array of
|
||||||
* <firstterm>clusters</firstterm>. Each cluster covers a number of
|
* <firstterm>clusters</firstterm>. Each cluster covers a number of
|
||||||
|
@ -3224,7 +3201,8 @@ slim_hidden_def (cairo_has_show_text_glyphs);
|
||||||
* and @glyphs in entirety.
|
* and @glyphs in entirety.
|
||||||
*
|
*
|
||||||
* The first cluster always covers bytes from the beginning of @utf8.
|
* The first cluster always covers bytes from the beginning of @utf8.
|
||||||
* If @backward is %FALSE, the first cluster also covers the beginning
|
* If @cluster_flags do not have the %CAIRO_TEXT_CLUSTER_FLAG_BACKWARD
|
||||||
|
* set, the first cluster also covers the beginning
|
||||||
* of @glyphs, otherwise it covers the end of the @glyphs array and
|
* of @glyphs, otherwise it covers the end of the @glyphs array and
|
||||||
* following clusters move backward.
|
* following clusters move backward.
|
||||||
*
|
*
|
||||||
|
@ -3240,7 +3218,7 @@ cairo_show_text_glyphs (cairo_t *cr,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
const cairo_text_cluster_t *clusters,
|
const cairo_text_cluster_t *clusters,
|
||||||
int num_clusters,
|
int num_clusters,
|
||||||
cairo_bool_t backward)
|
cairo_text_cluster_flags_t cluster_flags)
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
|
|
||||||
|
@ -3275,8 +3253,7 @@ cairo_show_text_glyphs (cairo_t *cr,
|
||||||
* and that cluster boundaries are UTF-8 boundaries. */
|
* and that cluster boundaries are UTF-8 boundaries. */
|
||||||
status = _cairo_validate_text_clusters (utf8, utf8_len,
|
status = _cairo_validate_text_clusters (utf8, utf8_len,
|
||||||
glyphs, num_glyphs,
|
glyphs, num_glyphs,
|
||||||
clusters, num_clusters,
|
clusters, num_clusters, cluster_flags);
|
||||||
backward);
|
|
||||||
if (status == CAIRO_STATUS_INVALID_CLUSTERS) {
|
if (status == CAIRO_STATUS_INVALID_CLUSTERS) {
|
||||||
/* Either got invalid UTF-8 text, or cluster mapping is bad.
|
/* Either got invalid UTF-8 text, or cluster mapping is bad.
|
||||||
* Differentiate those. */
|
* Differentiate those. */
|
||||||
|
@ -3297,8 +3274,7 @@ cairo_show_text_glyphs (cairo_t *cr,
|
||||||
status = _cairo_gstate_show_text_glyphs (cr->gstate,
|
status = _cairo_gstate_show_text_glyphs (cr->gstate,
|
||||||
utf8, utf8_len,
|
utf8, utf8_len,
|
||||||
glyphs, num_glyphs,
|
glyphs, num_glyphs,
|
||||||
clusters, num_clusters,
|
clusters, num_clusters, cluster_flags);
|
||||||
!!backward);
|
|
||||||
if (status)
|
if (status)
|
||||||
_cairo_set_error (cr, status);
|
_cairo_set_error (cr, status);
|
||||||
}
|
}
|
||||||
|
@ -3585,6 +3561,7 @@ cairo_get_line_width (cairo_t *cr)
|
||||||
|
|
||||||
return _cairo_gstate_get_line_width (cr->gstate);
|
return _cairo_gstate_get_line_width (cr->gstate);
|
||||||
}
|
}
|
||||||
|
slim_hidden_def (cairo_get_line_width);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_get_line_cap:
|
* cairo_get_line_cap:
|
||||||
|
|
|
@ -51,7 +51,11 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef cairo_public
|
#ifndef cairo_public
|
||||||
# define cairo_public
|
# if defined (_MSC_VER) && ! defined (CAIRO_WIN32_STATIC_BUILD)
|
||||||
|
# define cairo_public __declspec(dllimport)
|
||||||
|
# else
|
||||||
|
# define cairo_public
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CAIRO_BEGIN_DECLS
|
CAIRO_BEGIN_DECLS
|
||||||
|
@ -892,6 +896,19 @@ cairo_text_cluster_allocate (int num_clusters);
|
||||||
cairo_public void
|
cairo_public void
|
||||||
cairo_text_cluster_free (cairo_text_cluster_t *clusters);
|
cairo_text_cluster_free (cairo_text_cluster_t *clusters);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cairo_text_cluster_flags_t:
|
||||||
|
* @CAIRO_TEXT_CLUSTER_FLAG_BACKWARD: The clusters in the cluster array
|
||||||
|
* map to glyphs in the glyph array from end to start.
|
||||||
|
*
|
||||||
|
* Specifies properties of a text cluster mapping.
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
**/
|
||||||
|
typedef enum _cairo_text_cluster_flags {
|
||||||
|
CAIRO_TEXT_CLUSTER_FLAG_BACKWARD = 0x00000001
|
||||||
|
} cairo_text_cluster_flags_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_text_extents_t:
|
* cairo_text_extents_t:
|
||||||
* @x_bearing: the horizontal distance from the origin to the
|
* @x_bearing: the horizontal distance from the origin to the
|
||||||
|
@ -1028,28 +1045,6 @@ typedef enum _cairo_subpixel_order {
|
||||||
CAIRO_SUBPIXEL_ORDER_VBGR
|
CAIRO_SUBPIXEL_ORDER_VBGR
|
||||||
} cairo_subpixel_order_t;
|
} cairo_subpixel_order_t;
|
||||||
|
|
||||||
/**
|
|
||||||
* cairo_lcd_filter_t:
|
|
||||||
* @CAIRO_LCD_FILTER_DEFAULT: Use the default LCD filter for
|
|
||||||
* font backend and target device
|
|
||||||
* @CAIRO_LCD_FILTER_NONE: Do not perform LCD filtering
|
|
||||||
* @CAIRO_LCD_FILTER_INTRA_PIXEL: Intra-pixel filter
|
|
||||||
* @CAIRO_LCD_FILTER_FIR3: FIR filter with a 3x3 kernel
|
|
||||||
* @CAIRO_LCD_FILTER_FIR5: FIR filter with a 5x5 kernel
|
|
||||||
*
|
|
||||||
* The LCD filter specifies the low-pass filter applied to LCD-optimized
|
|
||||||
* bitmaps generated with an antialiasing mode of %CAIRO_ANTIALIAS_SUBPIXEL.
|
|
||||||
*
|
|
||||||
* Since: 1.8
|
|
||||||
**/
|
|
||||||
typedef enum _cairo_lcd_filter {
|
|
||||||
CAIRO_LCD_FILTER_DEFAULT,
|
|
||||||
CAIRO_LCD_FILTER_NONE,
|
|
||||||
CAIRO_LCD_FILTER_INTRA_PIXEL,
|
|
||||||
CAIRO_LCD_FILTER_FIR3,
|
|
||||||
CAIRO_LCD_FILTER_FIR5
|
|
||||||
} cairo_lcd_filter_t;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_hint_style_t:
|
* cairo_hint_style_t:
|
||||||
* @CAIRO_HINT_STYLE_DEFAULT: Use the default hint style for
|
* @CAIRO_HINT_STYLE_DEFAULT: Use the default hint style for
|
||||||
|
@ -1155,12 +1150,6 @@ cairo_font_options_set_subpixel_order (cairo_font_options_t *options,
|
||||||
cairo_public cairo_subpixel_order_t
|
cairo_public cairo_subpixel_order_t
|
||||||
cairo_font_options_get_subpixel_order (const cairo_font_options_t *options);
|
cairo_font_options_get_subpixel_order (const cairo_font_options_t *options);
|
||||||
|
|
||||||
cairo_public void
|
|
||||||
cairo_font_options_set_lcd_filter (cairo_font_options_t *options,
|
|
||||||
cairo_lcd_filter_t lcd_filter);
|
|
||||||
cairo_public cairo_lcd_filter_t
|
|
||||||
cairo_font_options_get_lcd_filter (const cairo_font_options_t *options);
|
|
||||||
|
|
||||||
cairo_public void
|
cairo_public void
|
||||||
cairo_font_options_set_hint_style (cairo_font_options_t *options,
|
cairo_font_options_set_hint_style (cairo_font_options_t *options,
|
||||||
cairo_hint_style_t hint_style);
|
cairo_hint_style_t hint_style);
|
||||||
|
@ -1220,9 +1209,6 @@ cairo_show_text (cairo_t *cr, const char *utf8);
|
||||||
cairo_public void
|
cairo_public void
|
||||||
cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs);
|
cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs);
|
||||||
|
|
||||||
cairo_public cairo_bool_t
|
|
||||||
cairo_has_show_text_glyphs (cairo_t *cr);
|
|
||||||
|
|
||||||
cairo_public void
|
cairo_public void
|
||||||
cairo_show_text_glyphs (cairo_t *cr,
|
cairo_show_text_glyphs (cairo_t *cr,
|
||||||
const char *utf8,
|
const char *utf8,
|
||||||
|
@ -1231,7 +1217,7 @@ cairo_show_text_glyphs (cairo_t *cr,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
const cairo_text_cluster_t *clusters,
|
const cairo_text_cluster_t *clusters,
|
||||||
int num_clusters,
|
int num_clusters,
|
||||||
cairo_bool_t backward);
|
cairo_text_cluster_flags_t cluster_flags);
|
||||||
|
|
||||||
cairo_public void
|
cairo_public void
|
||||||
cairo_text_path (cairo_t *cr, const char *utf8);
|
cairo_text_path (cairo_t *cr, const char *utf8);
|
||||||
|
@ -1376,16 +1362,16 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
|
||||||
cairo_text_extents_t *extents);
|
cairo_text_extents_t *extents);
|
||||||
|
|
||||||
cairo_public cairo_status_t
|
cairo_public cairo_status_t
|
||||||
cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
|
cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
|
||||||
double x,
|
double x,
|
||||||
double y,
|
double y,
|
||||||
const char *utf8,
|
const char *utf8,
|
||||||
int utf8_len,
|
int utf8_len,
|
||||||
cairo_glyph_t **glyphs,
|
cairo_glyph_t **glyphs,
|
||||||
int *num_glyphs,
|
int *num_glyphs,
|
||||||
cairo_text_cluster_t **clusters,
|
cairo_text_cluster_t **clusters,
|
||||||
int *num_clusters,
|
int *num_clusters,
|
||||||
cairo_bool_t *backward);
|
cairo_text_cluster_flags_t *cluster_flags);
|
||||||
|
|
||||||
cairo_public cairo_font_face_t *
|
cairo_public cairo_font_face_t *
|
||||||
cairo_scaled_font_get_font_face (cairo_scaled_font_t *scaled_font);
|
cairo_scaled_font_get_font_face (cairo_scaled_font_t *scaled_font);
|
||||||
|
@ -1525,7 +1511,8 @@ typedef cairo_status_t (*cairo_user_scaled_font_render_glyph_func_t) (cairo_scal
|
||||||
* @num_glyphs: pointer to number of glyphs
|
* @num_glyphs: pointer to number of glyphs
|
||||||
* @clusters: pointer to array of cluster mapping information to fill, or %NULL
|
* @clusters: pointer to array of cluster mapping information to fill, or %NULL
|
||||||
* @num_clusters: pointer to number of clusters
|
* @num_clusters: pointer to number of clusters
|
||||||
* @backward: pointer to whether the text to glyphs mapping goes backward
|
* @cluster_flags: pointer to location to store cluster flags corresponding to the
|
||||||
|
* output @clusters
|
||||||
*
|
*
|
||||||
* #cairo_user_scaled_font_text_to_glyphs_func_t is the type of function which
|
* #cairo_user_scaled_font_text_to_glyphs_func_t is the type of function which
|
||||||
* is called to convert input text to an array of glyphs. This is used by the
|
* is called to convert input text to an array of glyphs. This is used by the
|
||||||
|
@ -1536,35 +1523,30 @@ typedef cairo_status_t (*cairo_user_scaled_font_render_glyph_func_t) (cairo_scal
|
||||||
* as well as complex <firstterm>shaping</firstterm> required for scripts like
|
* as well as complex <firstterm>shaping</firstterm> required for scripts like
|
||||||
* Arabic and Indic.
|
* Arabic and Indic.
|
||||||
*
|
*
|
||||||
* The @num_glyphs argument is preset to -1. The callback should allocate an
|
* The @num_glyphs argument is preset to the number of glyph entries available
|
||||||
* array for the resulting glyphs (using malloc()), and populate the glyph indices and
|
* in the @glyphs buffer. If the @glyphs buffer is %NULL, the value of
|
||||||
* positions (in font space) assuming that the text is to be shown at the
|
* @num_glyphs will be zero. If the provided glyph array is too short for
|
||||||
* origin. Cairo will free the glyph array when done with it, no matter what
|
|
||||||
* the return value of the callback is.
|
|
||||||
*
|
|
||||||
* If @glyphs initially points to a non-%NULL value, that array can be used
|
|
||||||
* as a glyph buffer, and @num_glyphs points to the number of glyph
|
|
||||||
* entries available there. If the provided glyph array is too short for
|
|
||||||
* the conversion (or for convenience), a new glyph array may be allocated
|
* the conversion (or for convenience), a new glyph array may be allocated
|
||||||
* using cairo_glyph_allocate() and placed in @glyphs. Upon return,
|
* using cairo_glyph_allocate() and placed in @glyphs. Upon return,
|
||||||
* @num_glyphs should contain the number of generated glyphs.
|
* @num_glyphs should contain the number of generated glyphs. If the value
|
||||||
* If the value @glyphs points at has changed after the call, cairo will
|
* @glyphs points at has changed after the call, the caller will free the
|
||||||
* free the allocated glyph array using cairo_glyph_free().
|
* allocated glyph array using cairo_glyph_free().
|
||||||
|
* The callback should populate the glyph indices and positions (in font space)
|
||||||
|
* assuming that the text is to be shown at the origin.
|
||||||
*
|
*
|
||||||
* If @clusters is not %NULL, @num_clusters and @backward are also non-%NULL,
|
* If @clusters is not %NULL, @num_clusters and @cluster_flags are also
|
||||||
* and cluster mapping should be computed.
|
* non-%NULL, and cluster mapping should be computed. The semantics of how
|
||||||
* The semantics of how cluster array allocation works is similar to the glyph
|
* cluster array allocation works is similar to the glyph array. That is,
|
||||||
* array. That is,
|
|
||||||
* if @clusters initially points to a non-%NULL value, that array may be used
|
* if @clusters initially points to a non-%NULL value, that array may be used
|
||||||
* as a cluster buffer, and @num_clusters points to the number of cluster
|
* as a cluster buffer, and @num_clusters points to the number of cluster
|
||||||
* entries available there. If the provided cluster array is too short for
|
* entries available there. If the provided cluster array is too short for
|
||||||
* the conversion (or for convenience), a new cluster array may be allocated
|
* the conversion (or for convenience), a new cluster array may be allocated
|
||||||
* using cairo_text_cluster_allocate() and placed in @clusters. Upon return,
|
* using cairo_text_cluster_allocate() and placed in @clusters. Upon return,
|
||||||
* @num_clusters should contain the number of generated clusters.
|
* @num_clusters should contain the number of generated clusters.
|
||||||
* If the value @clusters points at has changed after the call, cairo will
|
* If the value @clusters points at has changed after the call, the caller
|
||||||
* free the allocated cluster array using cairo_text_cluster_free().
|
* will free the allocated cluster array using cairo_text_cluster_free().
|
||||||
*
|
*
|
||||||
* The callback is optional. If not set, or if @num_glyphs is negative upon
|
* The callback is optional. If @num_glyphs is negative upon
|
||||||
* the callback returning, the unicode_to_glyph callback
|
* the callback returning, the unicode_to_glyph callback
|
||||||
* is tried. See #cairo_user_scaled_font_unicode_to_glyph_func_t.
|
* is tried. See #cairo_user_scaled_font_unicode_to_glyph_func_t.
|
||||||
*
|
*
|
||||||
|
@ -1581,14 +1563,14 @@ typedef cairo_status_t (*cairo_user_scaled_font_render_glyph_func_t) (cairo_scal
|
||||||
*
|
*
|
||||||
* Since: 1.8
|
* Since: 1.8
|
||||||
**/
|
**/
|
||||||
typedef cairo_status_t (*cairo_user_scaled_font_text_to_glyphs_func_t) (cairo_scaled_font_t *scaled_font,
|
typedef cairo_status_t (*cairo_user_scaled_font_text_to_glyphs_func_t) (cairo_scaled_font_t *scaled_font,
|
||||||
const char *utf8,
|
const char *utf8,
|
||||||
int utf8_len,
|
int utf8_len,
|
||||||
cairo_glyph_t **glyphs,
|
cairo_glyph_t **glyphs,
|
||||||
int *num_glyphs,
|
int *num_glyphs,
|
||||||
cairo_text_cluster_t **clusters,
|
cairo_text_cluster_t **clusters,
|
||||||
int *num_clusters,
|
int *num_clusters,
|
||||||
cairo_bool_t *backward);
|
cairo_text_cluster_flags_t *cluster_flags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cairo_user_scaled_font_unicode_to_glyph_func_t:
|
* cairo_user_scaled_font_unicode_to_glyph_func_t:
|
||||||
|
@ -1931,8 +1913,7 @@ typedef enum _cairo_surface_type {
|
||||||
CAIRO_SURFACE_TYPE_SVG,
|
CAIRO_SURFACE_TYPE_SVG,
|
||||||
CAIRO_SURFACE_TYPE_OS2,
|
CAIRO_SURFACE_TYPE_OS2,
|
||||||
CAIRO_SURFACE_TYPE_WIN32_PRINTING,
|
CAIRO_SURFACE_TYPE_WIN32_PRINTING,
|
||||||
CAIRO_SURFACE_TYPE_QUARTZ_IMAGE,
|
CAIRO_SURFACE_TYPE_QUARTZ_IMAGE
|
||||||
CAIRO_SURFACE_TYPE_QPAINTER
|
|
||||||
} cairo_surface_type_t;
|
} cairo_surface_type_t;
|
||||||
|
|
||||||
cairo_public cairo_surface_type_t
|
cairo_public cairo_surface_type_t
|
||||||
|
|
|
@ -50,12 +50,9 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* We use our own macros */
|
#ifdef _MSC_VER
|
||||||
#undef PACKAGE
|
#define cairo_public __declspec(dllexport)
|
||||||
#undef PACKAGE_NAME
|
#endif
|
||||||
#undef PACKAGE_STRING
|
|
||||||
#undef PACKAGE_TARNAME
|
|
||||||
#undef PACKAGE_VERSION
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -75,11 +72,14 @@
|
||||||
|
|
||||||
#include "cairo-compiler-private.h"
|
#include "cairo-compiler-private.h"
|
||||||
|
|
||||||
#if defined(CAIRO_HAS_PS_SURFACE) || defined(CAIRO_HAS_PDF_SURFACE) || defined(CAIRO_HAS_SVG_SURFACE)
|
#if CAIRO_HAS_PS_SURFACE || \
|
||||||
|
CAIRO_HAS_PDF_SURFACE || \
|
||||||
|
CAIRO_HAS_SVG_SURFACE || \
|
||||||
|
CAIRO_HAS_WIN32_SURFACE
|
||||||
#define CAIRO_HAS_FONT_SUBSET 1
|
#define CAIRO_HAS_FONT_SUBSET 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CAIRO_HAS_PS_SURFACE) || defined(CAIRO_HAS_PDF_SURFACE)
|
#if CAIRO_HAS_PS_SURFACE || CAIRO_HAS_PDF_SURFACE
|
||||||
#define CAIRO_HAS_PDF_OPERATORS 1
|
#define CAIRO_HAS_PDF_OPERATORS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ _cairo_win32_tmpfile (void);
|
||||||
* a bit of a pain, but it should be easy to always catch as long as
|
* a bit of a pain, but it should be easy to always catch as long as
|
||||||
* one adds a new test case to test a trigger of the new status value.
|
* one adds a new test case to test a trigger of the new status value.
|
||||||
*/
|
*/
|
||||||
#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_SLANT
|
#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_WEIGHT
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#define cairo_container_of(ptr, type, member) ({ \
|
#define cairo_container_of(ptr, type, member) ({ \
|
||||||
|
@ -418,6 +418,10 @@ typedef struct _cairo_scaled_font_subset {
|
||||||
struct _cairo_scaled_font_backend {
|
struct _cairo_scaled_font_backend {
|
||||||
cairo_font_type_t type;
|
cairo_font_type_t type;
|
||||||
|
|
||||||
|
cairo_warn cairo_status_t
|
||||||
|
(*get_implementation) (cairo_toy_font_face_t *toy_face,
|
||||||
|
cairo_font_face_t **font_face);
|
||||||
|
|
||||||
cairo_warn cairo_status_t
|
cairo_warn cairo_status_t
|
||||||
(*create_toy) (cairo_toy_font_face_t *toy_face,
|
(*create_toy) (cairo_toy_font_face_t *toy_face,
|
||||||
const cairo_matrix_t *font_matrix,
|
const cairo_matrix_t *font_matrix,
|
||||||
|
@ -438,16 +442,16 @@ struct _cairo_scaled_font_backend {
|
||||||
* then just converting characters one by one.
|
* then just converting characters one by one.
|
||||||
*/
|
*/
|
||||||
cairo_warn cairo_int_status_t
|
cairo_warn cairo_int_status_t
|
||||||
(*text_to_glyphs) (void *scaled_font,
|
(*text_to_glyphs) (void *scaled_font,
|
||||||
double x,
|
double x,
|
||||||
double y,
|
double y,
|
||||||
const char *utf8,
|
const char *utf8,
|
||||||
int utf8_len,
|
int utf8_len,
|
||||||
cairo_glyph_t **glyphs,
|
cairo_glyph_t **glyphs,
|
||||||
int *num_glyphs,
|
int *num_glyphs,
|
||||||
cairo_text_cluster_t **clusters,
|
cairo_text_cluster_t **clusters,
|
||||||
int *num_clusters,
|
int *num_clusters,
|
||||||
cairo_bool_t *backward);
|
cairo_text_cluster_flags_t *cluster_flags);
|
||||||
|
|
||||||
unsigned long
|
unsigned long
|
||||||
(*ucs4_to_index) (void *scaled_font,
|
(*ucs4_to_index) (void *scaled_font,
|
||||||
|
@ -490,6 +494,10 @@ struct _cairo_font_face_backend {
|
||||||
void
|
void
|
||||||
(*destroy) (void *font_face);
|
(*destroy) (void *font_face);
|
||||||
|
|
||||||
|
cairo_warn cairo_status_t
|
||||||
|
(*get_implementation) (void *font_face,
|
||||||
|
cairo_font_face_t **font_face_out);
|
||||||
|
|
||||||
cairo_warn cairo_status_t
|
cairo_warn cairo_status_t
|
||||||
(*scaled_font_create) (void *font_face,
|
(*scaled_font_create) (void *font_face,
|
||||||
const cairo_matrix_t *font_matrix,
|
const cairo_matrix_t *font_matrix,
|
||||||
|
@ -498,6 +506,8 @@ struct _cairo_font_face_backend {
|
||||||
cairo_scaled_font_t **scaled_font);
|
cairo_scaled_font_t **scaled_font);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern const cairo_private struct _cairo_scaled_font_backend _cairo_user_scaled_font_backend;
|
||||||
|
|
||||||
/* concrete font backends */
|
/* concrete font backends */
|
||||||
#if CAIRO_HAS_FT_FONT
|
#if CAIRO_HAS_FT_FONT
|
||||||
|
|
||||||
|
@ -559,9 +569,12 @@ struct _cairo_surface_backend {
|
||||||
* 1. It is as compatible as possible with @surface (in terms of
|
* 1. It is as compatible as possible with @surface (in terms of
|
||||||
* efficiency)
|
* efficiency)
|
||||||
*
|
*
|
||||||
* 2. It has the same size as @src
|
* 2. It has the same contents as @src within the given rectangle.
|
||||||
*
|
*
|
||||||
* 3. It has the same contents as @src within the given rectangle.
|
* 3. The offset of the similar surface with respect to the original
|
||||||
|
* surface is returned in the clone_offset vector.
|
||||||
|
* - if you clone the entire surface, this vector is zero.
|
||||||
|
* - if you clone (src_x, src_y)x(w, h) the vector is (src_x, src_y);
|
||||||
*/
|
*/
|
||||||
cairo_warn cairo_status_t
|
cairo_warn cairo_status_t
|
||||||
(*clone_similar) (void *surface,
|
(*clone_similar) (void *surface,
|
||||||
|
@ -570,6 +583,8 @@ struct _cairo_surface_backend {
|
||||||
int src_y,
|
int src_y,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
|
int *clone_offset_x,
|
||||||
|
int *clone_offset_y,
|
||||||
cairo_surface_t **clone_out);
|
cairo_surface_t **clone_out);
|
||||||
|
|
||||||
/* XXX: dst should be the first argument for consistency */
|
/* XXX: dst should be the first argument for consistency */
|
||||||
|
@ -799,7 +814,7 @@ struct _cairo_surface_backend {
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
const cairo_text_cluster_t *clusters,
|
const cairo_text_cluster_t *clusters,
|
||||||
int num_clusters,
|
int num_clusters,
|
||||||
cairo_bool_t backward,
|
cairo_text_cluster_flags_t cluster_flags,
|
||||||
cairo_scaled_font_t *scaled_font);
|
cairo_scaled_font_t *scaled_font);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -825,24 +840,6 @@ struct _cairo_image_surface {
|
||||||
|
|
||||||
extern const cairo_private cairo_surface_backend_t _cairo_image_surface_backend;
|
extern const cairo_private cairo_surface_backend_t _cairo_image_surface_backend;
|
||||||
|
|
||||||
/* XXX: Right now, the _cairo_color structure puts unpremultiplied
|
|
||||||
color in the doubles and premultiplied color in the shorts. Yes,
|
|
||||||
this is crazy insane, (but at least we don't export this
|
|
||||||
madness). I'm still working on a cleaner API, but in the meantime,
|
|
||||||
at least this does prevent precision loss in color when changing
|
|
||||||
alpha. */
|
|
||||||
struct _cairo_color {
|
|
||||||
double red;
|
|
||||||
double green;
|
|
||||||
double blue;
|
|
||||||
double alpha;
|
|
||||||
|
|
||||||
unsigned short red_short;
|
|
||||||
unsigned short green_short;
|
|
||||||
unsigned short blue_short;
|
|
||||||
unsigned short alpha_short;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define CAIRO_EXTEND_SURFACE_DEFAULT CAIRO_EXTEND_NONE
|
#define CAIRO_EXTEND_SURFACE_DEFAULT CAIRO_EXTEND_NONE
|
||||||
#define CAIRO_EXTEND_GRADIENT_DEFAULT CAIRO_EXTEND_PAD
|
#define CAIRO_EXTEND_GRADIENT_DEFAULT CAIRO_EXTEND_PAD
|
||||||
#define CAIRO_FILTER_DEFAULT CAIRO_FILTER_GOOD
|
#define CAIRO_FILTER_DEFAULT CAIRO_FILTER_GOOD
|
||||||
|
@ -966,8 +963,8 @@ typedef struct _cairo_traps {
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
/* Paranoia: this should have been caught by configure. */
|
#define CAIRO_FONT_FAMILY_DEFAULT CAIRO_FT_FONT_FAMILY_DEFAULT
|
||||||
#error No font backends are available.
|
#define CAIRO_SCALED_FONT_BACKEND_DEFAULT &_cairo_user_scaled_font_backend
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1249,16 +1246,16 @@ _cairo_gstate_set_font_face (cairo_gstate_t *gstate,
|
||||||
cairo_font_face_t *font_face);
|
cairo_font_face_t *font_face);
|
||||||
|
|
||||||
cairo_private cairo_status_t
|
cairo_private cairo_status_t
|
||||||
_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
|
_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
|
||||||
double x,
|
double x,
|
||||||
double y,
|
double y,
|
||||||
const char *utf8,
|
const char *utf8,
|
||||||
int utf8_len,
|
int utf8_len,
|
||||||
cairo_glyph_t **glyphs,
|
cairo_glyph_t **glyphs,
|
||||||
int *num_glyphs,
|
int *num_glyphs,
|
||||||
cairo_text_cluster_t **clusters,
|
cairo_text_cluster_t **clusters,
|
||||||
int *num_clusters,
|
int *num_clusters,
|
||||||
cairo_bool_t *backward);
|
cairo_text_cluster_flags_t *cluster_flags);
|
||||||
|
|
||||||
cairo_private cairo_status_t
|
cairo_private cairo_status_t
|
||||||
_cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
|
_cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
|
||||||
|
@ -1266,9 +1263,6 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
cairo_text_extents_t *extents);
|
cairo_text_extents_t *extents);
|
||||||
|
|
||||||
cairo_private cairo_bool_t
|
|
||||||
_cairo_gstate_has_show_text_glyphs (cairo_gstate_t *gstate);
|
|
||||||
|
|
||||||
cairo_private cairo_status_t
|
cairo_private cairo_status_t
|
||||||
_cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
_cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
||||||
const char *utf8,
|
const char *utf8,
|
||||||
|
@ -1277,7 +1271,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
const cairo_text_cluster_t *clusters,
|
const cairo_text_cluster_t *clusters,
|
||||||
int num_clusters,
|
int num_clusters,
|
||||||
cairo_bool_t backward);
|
cairo_text_cluster_flags_t cluster_flags);
|
||||||
|
|
||||||
cairo_private cairo_status_t
|
cairo_private cairo_status_t
|
||||||
_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
|
_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
|
||||||
|
@ -1358,6 +1352,17 @@ _cairo_unscaled_font_reference (cairo_unscaled_font_t *font);
|
||||||
cairo_private void
|
cairo_private void
|
||||||
_cairo_unscaled_font_destroy (cairo_unscaled_font_t *font);
|
_cairo_unscaled_font_destroy (cairo_unscaled_font_t *font);
|
||||||
|
|
||||||
|
/* cairo-font-face-twin.c */
|
||||||
|
|
||||||
|
cairo_private cairo_font_face_t *
|
||||||
|
_cairo_font_face_twin_create (cairo_font_slant_t slant,
|
||||||
|
cairo_font_weight_t weight);
|
||||||
|
|
||||||
|
/* cairo-font-face-twin-data.c */
|
||||||
|
|
||||||
|
extern const cairo_private int8_t _cairo_twin_outlines[];
|
||||||
|
extern const cairo_private uint16_t _cairo_twin_charmap[128];
|
||||||
|
|
||||||
/* cairo-font-options.c */
|
/* cairo-font-options.c */
|
||||||
|
|
||||||
cairo_private void
|
cairo_private void
|
||||||
|
@ -1383,7 +1388,7 @@ _cairo_validate_text_clusters (const char *utf8,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
const cairo_text_cluster_t *clusters,
|
const cairo_text_cluster_t *clusters,
|
||||||
int num_clusters,
|
int num_clusters,
|
||||||
cairo_bool_t backward);
|
cairo_text_cluster_flags_t cluster_flags);
|
||||||
|
|
||||||
/* cairo-path-fixed.c */
|
/* cairo-path-fixed.c */
|
||||||
cairo_private void
|
cairo_private void
|
||||||
|
@ -1547,7 +1552,7 @@ _cairo_scaled_font_create_in_error (cairo_status_t status);
|
||||||
cairo_private void
|
cairo_private void
|
||||||
_cairo_scaled_font_reset_static_data (void);
|
_cairo_scaled_font_reset_static_data (void);
|
||||||
|
|
||||||
cairo_private void
|
cairo_private cairo_status_t
|
||||||
_cairo_scaled_font_register_placeholder_and_unlock_font_map (cairo_scaled_font_t *scaled_font);
|
_cairo_scaled_font_register_placeholder_and_unlock_font_map (cairo_scaled_font_t *scaled_font);
|
||||||
|
|
||||||
cairo_private void
|
cairo_private void
|
||||||
|
@ -1565,6 +1570,7 @@ cairo_private cairo_status_t
|
||||||
_cairo_scaled_font_set_metrics (cairo_scaled_font_t *scaled_font,
|
_cairo_scaled_font_set_metrics (cairo_scaled_font_t *scaled_font,
|
||||||
cairo_font_extents_t *fs_metrics);
|
cairo_font_extents_t *fs_metrics);
|
||||||
|
|
||||||
|
/* This should only be called on an error path by a scaled_font constructor */
|
||||||
cairo_private void
|
cairo_private void
|
||||||
_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font);
|
_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font);
|
||||||
|
|
||||||
|
@ -1788,7 +1794,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
const cairo_text_cluster_t *clusters,
|
const cairo_text_cluster_t *clusters,
|
||||||
int num_clusters,
|
int num_clusters,
|
||||||
cairo_bool_t backward,
|
cairo_text_cluster_flags_t cluster_flags,
|
||||||
cairo_scaled_font_t *scaled_font);
|
cairo_scaled_font_t *scaled_font);
|
||||||
|
|
||||||
cairo_private cairo_status_t
|
cairo_private cairo_status_t
|
||||||
|
@ -1836,6 +1842,8 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
|
||||||
int src_y,
|
int src_y,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
|
int *clone_offset_x,
|
||||||
|
int *clone_offset_y,
|
||||||
cairo_surface_t **clone_out);
|
cairo_surface_t **clone_out);
|
||||||
|
|
||||||
cairo_private cairo_surface_t *
|
cairo_private cairo_surface_t *
|
||||||
|
@ -1997,7 +2005,7 @@ cairo_private cairo_surface_t *
|
||||||
_cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
|
_cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
|
||||||
pixman_format_code_t pixman_format);
|
pixman_format_code_t pixman_format);
|
||||||
|
|
||||||
cairo_private cairo_int_status_t
|
cairo_private cairo_bool_t
|
||||||
_pixman_format_from_masks (cairo_format_masks_t *masks,
|
_pixman_format_from_masks (cairo_format_masks_t *masks,
|
||||||
pixman_format_code_t *format_ret);
|
pixman_format_code_t *format_ret);
|
||||||
|
|
||||||
|
@ -2109,21 +2117,19 @@ _cairo_polygon_init (cairo_polygon_t *polygon);
|
||||||
cairo_private void
|
cairo_private void
|
||||||
_cairo_polygon_fini (cairo_polygon_t *polygon);
|
_cairo_polygon_fini (cairo_polygon_t *polygon);
|
||||||
|
|
||||||
cairo_private cairo_status_t
|
cairo_private void
|
||||||
_cairo_polygon_status (cairo_polygon_t *polygon);
|
_cairo_polygon_move_to (cairo_polygon_t *polygon,
|
||||||
|
const cairo_point_t *point);
|
||||||
|
|
||||||
cairo_private void
|
cairo_private void
|
||||||
_cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_point_t *p2);
|
_cairo_polygon_line_to (cairo_polygon_t *polygon,
|
||||||
|
const cairo_point_t *point);
|
||||||
cairo_private void
|
|
||||||
_cairo_polygon_move_to (cairo_polygon_t *polygon, cairo_point_t *point);
|
|
||||||
|
|
||||||
cairo_private void
|
|
||||||
_cairo_polygon_line_to (cairo_polygon_t *polygon, cairo_point_t *point);
|
|
||||||
|
|
||||||
cairo_private void
|
cairo_private void
|
||||||
_cairo_polygon_close (cairo_polygon_t *polygon);
|
_cairo_polygon_close (cairo_polygon_t *polygon);
|
||||||
|
|
||||||
|
#define _cairo_polygon_status(P) (P)->status
|
||||||
|
|
||||||
/* cairo-spline.c */
|
/* cairo-spline.c */
|
||||||
cairo_private cairo_int_status_t
|
cairo_private cairo_int_status_t
|
||||||
_cairo_spline_init (cairo_spline_t *spline,
|
_cairo_spline_init (cairo_spline_t *spline,
|
||||||
|
@ -2176,6 +2182,9 @@ cairo_private cairo_bool_t
|
||||||
_cairo_matrix_is_integer_translation(const cairo_matrix_t *matrix,
|
_cairo_matrix_is_integer_translation(const cairo_matrix_t *matrix,
|
||||||
int *itx, int *ity);
|
int *itx, int *ity);
|
||||||
|
|
||||||
|
cairo_private cairo_bool_t
|
||||||
|
_cairo_matrix_is_pixel_exact (const cairo_matrix_t *matrix);
|
||||||
|
|
||||||
cairo_private double
|
cairo_private double
|
||||||
_cairo_matrix_transformed_circle_major_axis(cairo_matrix_t *matrix, double radius);
|
_cairo_matrix_transformed_circle_major_axis(cairo_matrix_t *matrix, double radius);
|
||||||
|
|
||||||
|
@ -2195,29 +2204,38 @@ cairo_private cairo_bool_t
|
||||||
_cairo_traps_get_limit (cairo_traps_t *traps,
|
_cairo_traps_get_limit (cairo_traps_t *traps,
|
||||||
cairo_box_t *limits);
|
cairo_box_t *limits);
|
||||||
|
|
||||||
cairo_private cairo_status_t
|
cairo_private void
|
||||||
_cairo_traps_init_box (cairo_traps_t *traps,
|
_cairo_traps_init_box (cairo_traps_t *traps,
|
||||||
cairo_box_t *box);
|
const cairo_box_t *box);
|
||||||
|
|
||||||
|
cairo_private void
|
||||||
|
_cairo_traps_clear (cairo_traps_t *traps);
|
||||||
|
|
||||||
cairo_private void
|
cairo_private void
|
||||||
_cairo_traps_fini (cairo_traps_t *traps);
|
_cairo_traps_fini (cairo_traps_t *traps);
|
||||||
|
|
||||||
cairo_private cairo_status_t
|
#define _cairo_traps_status(T) (T)->status
|
||||||
_cairo_traps_status (cairo_traps_t *traps);
|
|
||||||
|
|
||||||
cairo_private void
|
cairo_private void
|
||||||
_cairo_traps_translate (cairo_traps_t *traps, int x, int y);
|
_cairo_traps_translate (cairo_traps_t *traps, int x, int y);
|
||||||
|
|
||||||
cairo_private cairo_status_t
|
cairo_private cairo_status_t
|
||||||
_cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3]);
|
_cairo_traps_tessellate_triangle (cairo_traps_t *traps,
|
||||||
|
const cairo_point_t t[3]);
|
||||||
|
|
||||||
cairo_private cairo_status_t
|
cairo_private cairo_status_t
|
||||||
_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]);
|
_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps,
|
||||||
|
const cairo_point_t q[4]);
|
||||||
|
|
||||||
|
cairo_private cairo_status_t
|
||||||
|
_cairo_traps_tessellate_rectangle (cairo_traps_t *traps,
|
||||||
|
const cairo_point_t *top_left,
|
||||||
|
const cairo_point_t *bottom_right);
|
||||||
|
|
||||||
cairo_private void
|
cairo_private void
|
||||||
_cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
|
_cairo_traps_add_trap (cairo_traps_t *traps,
|
||||||
cairo_point_t left_p1, cairo_point_t left_p2,
|
cairo_fixed_t top, cairo_fixed_t bottom,
|
||||||
cairo_point_t right_p1, cairo_point_t right_p2);
|
cairo_line_t *left, cairo_line_t *right);
|
||||||
|
|
||||||
cairo_private cairo_status_t
|
cairo_private cairo_status_t
|
||||||
_cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
|
_cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
|
||||||
|
@ -2249,10 +2267,12 @@ _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
|
||||||
|
|
||||||
/* cairo-slope.c */
|
/* cairo-slope.c */
|
||||||
cairo_private void
|
cairo_private void
|
||||||
_cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b);
|
_cairo_slope_init (cairo_slope_t *slope,
|
||||||
|
const cairo_point_t *a,
|
||||||
|
const cairo_point_t *b);
|
||||||
|
|
||||||
cairo_private int
|
cairo_private int
|
||||||
_cairo_slope_compare (cairo_slope_t *a, cairo_slope_t *b);
|
_cairo_slope_compare (const cairo_slope_t *a, const cairo_slope_t *b);
|
||||||
|
|
||||||
/* cairo-pattern.c */
|
/* cairo-pattern.c */
|
||||||
|
|
||||||
|
@ -2264,6 +2284,10 @@ cairo_private cairo_status_t
|
||||||
_cairo_pattern_init_copy (cairo_pattern_t *pattern,
|
_cairo_pattern_init_copy (cairo_pattern_t *pattern,
|
||||||
const cairo_pattern_t *other);
|
const cairo_pattern_t *other);
|
||||||
|
|
||||||
|
cairo_private cairo_status_t
|
||||||
|
_cairo_pattern_init_snapshot (cairo_pattern_t *pattern,
|
||||||
|
const cairo_pattern_t *other);
|
||||||
|
|
||||||
cairo_private void
|
cairo_private void
|
||||||
_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
|
_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
|
||||||
const cairo_color_t *color,
|
const cairo_color_t *color,
|
||||||
|
@ -2363,7 +2387,7 @@ cairo_private int
|
||||||
_cairo_ucs4_to_utf8 (uint32_t unicode,
|
_cairo_ucs4_to_utf8 (uint32_t unicode,
|
||||||
char *utf8);
|
char *utf8);
|
||||||
|
|
||||||
#if CAIRO_HAS_WIN32_FONT+0 || CAIRO_HAS_QUARTZ_FONT+0 || CAIRO_HAS_PDF_SURFACE+0
|
#if CAIRO_HAS_WIN32_FONT || CAIRO_HAS_QUARTZ_FONT || CAIRO_HAS_PDF_OPERATORS
|
||||||
# define CAIRO_HAS_UTF8_TO_UTF16 1
|
# define CAIRO_HAS_UTF8_TO_UTF16 1
|
||||||
#endif
|
#endif
|
||||||
#if CAIRO_HAS_UTF8_TO_UTF16
|
#if CAIRO_HAS_UTF8_TO_UTF16
|
||||||
|
@ -2374,6 +2398,9 @@ _cairo_utf8_to_utf16 (const char *str,
|
||||||
int *items_written);
|
int *items_written);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define _cairo_status_is_error(status) \
|
||||||
|
(status != CAIRO_STATUS_SUCCESS && status <= CAIRO_STATUS_LAST_STATUS)
|
||||||
|
|
||||||
cairo_private cairo_status_t
|
cairo_private cairo_status_t
|
||||||
_cairo_error (cairo_status_t status);
|
_cairo_error (cairo_status_t status);
|
||||||
|
|
||||||
|
@ -2391,21 +2418,22 @@ slim_hidden_proto (cairo_curve_to);
|
||||||
slim_hidden_proto (cairo_destroy);
|
slim_hidden_proto (cairo_destroy);
|
||||||
slim_hidden_proto (cairo_fill_preserve);
|
slim_hidden_proto (cairo_fill_preserve);
|
||||||
slim_hidden_proto (cairo_font_face_destroy);
|
slim_hidden_proto (cairo_font_face_destroy);
|
||||||
|
slim_hidden_proto (cairo_font_face_get_user_data);
|
||||||
slim_hidden_proto_no_warn (cairo_font_face_reference);
|
slim_hidden_proto_no_warn (cairo_font_face_reference);
|
||||||
|
slim_hidden_proto (cairo_font_face_set_user_data);
|
||||||
slim_hidden_proto (cairo_font_options_equal);
|
slim_hidden_proto (cairo_font_options_equal);
|
||||||
slim_hidden_proto (cairo_font_options_hash);
|
slim_hidden_proto (cairo_font_options_hash);
|
||||||
slim_hidden_proto (cairo_font_options_merge);
|
slim_hidden_proto (cairo_font_options_merge);
|
||||||
slim_hidden_proto (cairo_font_options_set_antialias);
|
slim_hidden_proto (cairo_font_options_set_antialias);
|
||||||
slim_hidden_proto (cairo_font_options_set_hint_metrics);
|
slim_hidden_proto (cairo_font_options_set_hint_metrics);
|
||||||
slim_hidden_proto (cairo_font_options_set_hint_style);
|
slim_hidden_proto (cairo_font_options_set_hint_style);
|
||||||
slim_hidden_proto (cairo_font_options_set_lcd_filter);
|
|
||||||
slim_hidden_proto (cairo_font_options_set_subpixel_order);
|
slim_hidden_proto (cairo_font_options_set_subpixel_order);
|
||||||
slim_hidden_proto (cairo_font_options_status);
|
slim_hidden_proto (cairo_font_options_status);
|
||||||
slim_hidden_proto (cairo_get_current_point);
|
slim_hidden_proto (cairo_get_current_point);
|
||||||
|
slim_hidden_proto (cairo_get_line_width);
|
||||||
slim_hidden_proto (cairo_get_matrix);
|
slim_hidden_proto (cairo_get_matrix);
|
||||||
slim_hidden_proto (cairo_get_target);
|
slim_hidden_proto (cairo_get_target);
|
||||||
slim_hidden_proto (cairo_get_tolerance);
|
slim_hidden_proto (cairo_get_tolerance);
|
||||||
slim_hidden_proto (cairo_has_show_text_glyphs);
|
|
||||||
slim_hidden_proto (cairo_glyph_allocate);
|
slim_hidden_proto (cairo_glyph_allocate);
|
||||||
slim_hidden_proto (cairo_glyph_free);
|
slim_hidden_proto (cairo_glyph_free);
|
||||||
slim_hidden_proto (cairo_image_surface_create);
|
slim_hidden_proto (cairo_image_surface_create);
|
||||||
|
@ -2462,12 +2490,16 @@ slim_hidden_proto_no_warn (cairo_scaled_font_reference);
|
||||||
slim_hidden_proto (cairo_scaled_font_status);
|
slim_hidden_proto (cairo_scaled_font_status);
|
||||||
slim_hidden_proto (cairo_set_font_size);
|
slim_hidden_proto (cairo_set_font_size);
|
||||||
slim_hidden_proto (cairo_set_font_options);
|
slim_hidden_proto (cairo_set_font_options);
|
||||||
|
slim_hidden_proto (cairo_set_line_cap);
|
||||||
|
slim_hidden_proto (cairo_set_line_join);
|
||||||
|
slim_hidden_proto (cairo_set_line_width);
|
||||||
slim_hidden_proto (cairo_set_matrix);
|
slim_hidden_proto (cairo_set_matrix);
|
||||||
slim_hidden_proto (cairo_set_operator);
|
slim_hidden_proto (cairo_set_operator);
|
||||||
slim_hidden_proto (cairo_set_source);
|
slim_hidden_proto (cairo_set_source);
|
||||||
slim_hidden_proto (cairo_set_source);
|
slim_hidden_proto (cairo_set_source);
|
||||||
slim_hidden_proto (cairo_set_source_surface);
|
slim_hidden_proto (cairo_set_source_surface);
|
||||||
slim_hidden_proto (cairo_status);
|
slim_hidden_proto (cairo_status);
|
||||||
|
slim_hidden_proto (cairo_stroke);
|
||||||
slim_hidden_proto (cairo_stroke_preserve);
|
slim_hidden_proto (cairo_stroke_preserve);
|
||||||
slim_hidden_proto (cairo_surface_create_similar);
|
slim_hidden_proto (cairo_surface_create_similar);
|
||||||
slim_hidden_proto (cairo_surface_destroy);
|
slim_hidden_proto (cairo_surface_destroy);
|
||||||
|
@ -2488,6 +2520,12 @@ slim_hidden_proto (cairo_surface_status);
|
||||||
slim_hidden_proto (cairo_text_cluster_allocate);
|
slim_hidden_proto (cairo_text_cluster_allocate);
|
||||||
slim_hidden_proto (cairo_text_cluster_free);
|
slim_hidden_proto (cairo_text_cluster_free);
|
||||||
slim_hidden_proto (cairo_toy_font_face_create);
|
slim_hidden_proto (cairo_toy_font_face_create);
|
||||||
|
slim_hidden_proto (cairo_toy_font_face_get_slant);
|
||||||
|
slim_hidden_proto (cairo_toy_font_face_get_weight);
|
||||||
|
slim_hidden_proto (cairo_user_font_face_create);
|
||||||
|
slim_hidden_proto (cairo_user_font_face_set_init_func);
|
||||||
|
slim_hidden_proto (cairo_user_font_face_set_render_glyph_func);
|
||||||
|
slim_hidden_proto (cairo_user_font_face_set_unicode_to_glyph_func);
|
||||||
slim_hidden_proto (cairo_version_string);
|
slim_hidden_proto (cairo_version_string);
|
||||||
|
|
||||||
#if CAIRO_HAS_PNG_FUNCTIONS
|
#if CAIRO_HAS_PNG_FUNCTIONS
|
||||||
|
|
|
@ -176,11 +176,15 @@ _test_fallback_surface_clone_similar (void *abstract_surface,
|
||||||
int src_y,
|
int src_y,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
|
int *clone_offset_x,
|
||||||
|
int *clone_offset_y,
|
||||||
cairo_surface_t **clone_out)
|
cairo_surface_t **clone_out)
|
||||||
{
|
{
|
||||||
test_fallback_surface_t *surface = abstract_surface;
|
test_fallback_surface_t *surface = abstract_surface;
|
||||||
|
|
||||||
if (src->backend == surface->base.backend) {
|
if (src->backend == surface->base.backend) {
|
||||||
|
*clone_offset_x = 0;
|
||||||
|
*clone_offset_y = 0;
|
||||||
*clone_out = cairo_surface_reference (src);
|
*clone_out = cairo_surface_reference (src);
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
|
|
@ -273,34 +273,18 @@ _test_meta_surface_show_text_glyphs (void *abstract_surface,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
const cairo_text_cluster_t *clusters,
|
const cairo_text_cluster_t *clusters,
|
||||||
int num_clusters,
|
int num_clusters,
|
||||||
cairo_bool_t backward,
|
cairo_text_cluster_flags_t cluster_flags,
|
||||||
cairo_scaled_font_t *scaled_font)
|
cairo_scaled_font_t *scaled_font)
|
||||||
{
|
{
|
||||||
test_meta_surface_t *surface = abstract_surface;
|
test_meta_surface_t *surface = abstract_surface;
|
||||||
cairo_int_status_t status;
|
|
||||||
|
|
||||||
surface->image_reflects_meta = FALSE;
|
surface->image_reflects_meta = FALSE;
|
||||||
|
|
||||||
/* Since this is a "wrapping" surface, we're calling back into
|
return _cairo_surface_show_text_glyphs (surface->meta, op, source,
|
||||||
* _cairo_surface_show_text_glyphs from within a call to the same.
|
utf8, utf8_len,
|
||||||
* Since _cairo_surface_show_text_glyphs acquires a mutex, we release
|
glyphs, num_glyphs,
|
||||||
* and re-acquire the mutex around this nested call.
|
clusters, num_clusters, cluster_flags,
|
||||||
*
|
scaled_font);
|
||||||
* Yes, this is ugly, but we consider it pragmatic as compared to
|
|
||||||
* adding locking code to all 18 surface-backend-specific
|
|
||||||
* show_glyphs functions, (which would get less testing and likely
|
|
||||||
* lead to bugs).
|
|
||||||
*/
|
|
||||||
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
|
|
||||||
status = _cairo_surface_show_text_glyphs (surface->meta, op, source,
|
|
||||||
utf8, utf8_len,
|
|
||||||
glyphs, num_glyphs,
|
|
||||||
clusters, num_clusters,
|
|
||||||
backward,
|
|
||||||
scaled_font);
|
|
||||||
CAIRO_MUTEX_LOCK (scaled_font->mutex);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -308,43 +292,8 @@ static cairo_surface_t *
|
||||||
_test_meta_surface_snapshot (void *abstract_other)
|
_test_meta_surface_snapshot (void *abstract_other)
|
||||||
{
|
{
|
||||||
test_meta_surface_t *other = abstract_other;
|
test_meta_surface_t *other = abstract_other;
|
||||||
cairo_status_t status;
|
|
||||||
|
|
||||||
/* XXX: Just making a snapshot of other->meta is what we really
|
|
||||||
* want. But this currently triggers a bug somewhere (the "mask"
|
|
||||||
* test from the test suite segfaults).
|
|
||||||
*
|
|
||||||
* For now, we'll create a new image surface and replay onto
|
|
||||||
* that. It would be tempting to replay into other->image and then
|
|
||||||
* return a snapshot of that, but that will cause the self-copy
|
|
||||||
* test to fail, (since our replay will be affected by a clip that
|
|
||||||
* should not have any effect on the use of the resulting snapshot
|
|
||||||
* as a source).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
return _cairo_surface_snapshot (other->meta);
|
return _cairo_surface_snapshot (other->meta);
|
||||||
#else
|
|
||||||
cairo_rectangle_int_t extents;
|
|
||||||
cairo_surface_t *surface;
|
|
||||||
|
|
||||||
status = _cairo_surface_get_extents (other->image, &extents);
|
|
||||||
if (status)
|
|
||||||
return _cairo_surface_create_in_error (status);
|
|
||||||
|
|
||||||
surface = cairo_surface_create_similar (other->image,
|
|
||||||
CAIRO_CONTENT_COLOR_ALPHA,
|
|
||||||
extents.width,
|
|
||||||
extents.height);
|
|
||||||
|
|
||||||
status = _cairo_meta_surface_replay (other->meta, surface);
|
|
||||||
if (status) {
|
|
||||||
cairo_surface_destroy (surface);
|
|
||||||
surface = _cairo_surface_create_in_error (status);
|
|
||||||
}
|
|
||||||
|
|
||||||
return surface;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const cairo_surface_backend_t test_meta_surface_backend = {
|
static const cairo_surface_backend_t test_meta_surface_backend = {
|
||||||
|
|
|
@ -93,14 +93,16 @@ _cairo_test_paginated_surface_create_for_data (unsigned char *data,
|
||||||
paginated = _cairo_paginated_surface_create (&surface->base,
|
paginated = _cairo_paginated_surface_create (&surface->base,
|
||||||
content, width, height,
|
content, width, height,
|
||||||
&test_paginated_surface_paginated_backend);
|
&test_paginated_surface_paginated_backend);
|
||||||
|
status = paginated->status;
|
||||||
/* paginated keeps the only reference to surface now, drop ours */
|
if (status == CAIRO_STATUS_SUCCESS) {
|
||||||
cairo_surface_destroy (&surface->base);
|
/* paginated keeps the only reference to surface now, drop ours */
|
||||||
|
cairo_surface_destroy (&surface->base);
|
||||||
if (paginated->status) {
|
return paginated;
|
||||||
cairo_surface_destroy (target);
|
|
||||||
}
|
}
|
||||||
return paginated;
|
|
||||||
|
cairo_surface_destroy (target);
|
||||||
|
free (surface);
|
||||||
|
return _cairo_surface_create_in_error (status);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cairo_status_t
|
static cairo_status_t
|
||||||
|
@ -250,35 +252,19 @@ _test_paginated_surface_show_text_glyphs (void *abstract_surface,
|
||||||
int num_glyphs,
|
int num_glyphs,
|
||||||
const cairo_text_cluster_t *clusters,
|
const cairo_text_cluster_t *clusters,
|
||||||
int num_clusters,
|
int num_clusters,
|
||||||
cairo_bool_t backward,
|
cairo_text_cluster_flags_t cluster_flags,
|
||||||
cairo_scaled_font_t *scaled_font)
|
cairo_scaled_font_t *scaled_font)
|
||||||
{
|
{
|
||||||
test_paginated_surface_t *surface = abstract_surface;
|
test_paginated_surface_t *surface = abstract_surface;
|
||||||
cairo_int_status_t status;
|
|
||||||
|
|
||||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
|
||||||
/* Since this is a "wrapping" surface, we're calling back into
|
return _cairo_surface_show_text_glyphs (surface->target, op, source,
|
||||||
* _cairo_surface_show_text_glyphs from within a call to the same.
|
utf8, utf8_len,
|
||||||
* Since _cairo_surface_show_text_glyphs acquires a mutex, we release
|
glyphs, num_glyphs,
|
||||||
* and re-acquire the mutex around this nested call.
|
clusters, num_clusters, cluster_flags,
|
||||||
*
|
scaled_font);
|
||||||
* Yes, this is ugly, but we consider it pragmatic as compared to
|
|
||||||
* adding locking code to all 18 surface-backend-specific
|
|
||||||
* show_glyphs functions, (which would get less testing and likely
|
|
||||||
* lead to bugs).
|
|
||||||
*/
|
|
||||||
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
|
|
||||||
status = _cairo_surface_show_text_glyphs (surface->target, op, source,
|
|
||||||
utf8, utf8_len,
|
|
||||||
glyphs, num_glyphs,
|
|
||||||
clusters, num_clusters,
|
|
||||||
backward,
|
|
||||||
scaled_font);
|
|
||||||
CAIRO_MUTEX_LOCK (scaled_font->mutex);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
diff -r b79d47dad1ea gfx/cairo/cairo/src/cairoint.h
|
diff -r b79d47dad1ea gfx/cairo/cairo/src/cairoint.h
|
||||||
--- a/cairo/src/cairoint.h Fri Jun 08 18:09:53 2007 -0700
|
--- a/gfx/cairo/cairo/src/cairoint.h Fri Jun 08 18:09:53 2007 -0700
|
||||||
+++ b/cairo/src/cairoint.h Fri Jun 29 09:18:02 2007 +0200
|
+++ b/gfx/cairo/cairo/src/cairoint.h Fri Jun 29 09:18:02 2007 +0200
|
||||||
@@ -159,6 +159,13 @@ CAIRO_BEGIN_DECLS
|
@@ -159,6 +159,13 @@ CAIRO_BEGIN_DECLS
|
||||||
|
|
||||||
#ifndef M_PI
|
#ifndef M_PI
|
||||||
|
|
Загрузка…
Ссылка в новой задаче