Merge branch 'master' of git.cairographics.org:/git/cairo
|
|
@ -48,8 +48,13 @@ endif
|
|||
|
||||
libcairoboilerplate_la_LIBADD += $(CAIROBOILERPLATE_LIBS)
|
||||
|
||||
# we need to workaround the introduction of CC_FOR_BUILD with older builds
|
||||
make-cairo-boilerplate-constructors$(EXEEXT): make-cairo-boilerplate-constructors.c
|
||||
$(CC_FOR_BUILD) $^ -o $@
|
||||
if test -n "$(CC_FOR_BUILD)"; then \
|
||||
$(CC_FOR_BUILD) $^ -o $@; \
|
||||
else \
|
||||
$(CC) $^ -o $@; \
|
||||
fi
|
||||
|
||||
cairo-boilerplate-constructors.c: Makefile $(enabled_cairo_boilerplate_sources) make-cairo-boilerplate-constructors$(EXEEXT)
|
||||
echo '(cd $(srcdir) && $(top_builddir)/boilerplate/make-cairo-boilerplate-constructors$(EXEEXT) $(enabled_cairo_boilerplate_sources)) > $@'
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@
|
|||
#include <cairo-pdf-surface-private.h>
|
||||
#include <cairo-paginated-surface-private.h>
|
||||
|
||||
#if ! CAIRO_HAS_META_SURFACE
|
||||
#define CAIRO_SURFACE_TYPE_META CAIRO_INTERNAL_SURFACE_TYPE_META
|
||||
#endif
|
||||
|
||||
static const cairo_user_data_key_t pdf_closure_key;
|
||||
|
||||
typedef struct _pdf_target_closure
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@
|
|||
#include <cairo-ps-surface-private.h>
|
||||
#include <cairo-paginated-surface-private.h>
|
||||
|
||||
#if ! CAIRO_HAS_META_SURFACE
|
||||
#define CAIRO_SURFACE_TYPE_META CAIRO_INTERNAL_SURFACE_TYPE_META
|
||||
#endif
|
||||
|
||||
static const cairo_user_data_key_t ps_closure_key;
|
||||
|
||||
typedef struct _ps_target_closure {
|
||||
|
|
|
|||
|
|
@ -35,6 +35,10 @@
|
|||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#if ! CAIRO_HAS_META_SURFACE
|
||||
#define CAIRO_SURFACE_TYPE_META CAIRO_INTERNAL_SURFACE_TYPE_META
|
||||
#endif
|
||||
|
||||
static const cairo_user_data_key_t svg_closure_key;
|
||||
|
||||
typedef struct _svg_target_closure {
|
||||
|
|
|
|||
|
|
@ -28,16 +28,20 @@
|
|||
|
||||
#include "cairo-boilerplate-private.h"
|
||||
|
||||
#include <cairo-types-private.h>
|
||||
|
||||
#include <test-fallback-surface.h>
|
||||
#include <test-fallback16-surface.h>
|
||||
#if CAIRO_HAS_TEST_PAGINATED_SURFACE
|
||||
#include <test-paginated-surface.h>
|
||||
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,9,3)
|
||||
#endif
|
||||
#if CAIRO_HAS_TEST_NULL_SURFACE
|
||||
#include <test-null-surface.h>
|
||||
#endif
|
||||
#if CAIRO_HAS_TEST_WRAPPING_SURFACE
|
||||
#include <test-wrapping-surface.h>
|
||||
#endif
|
||||
|
||||
#include <cairo-types-private.h>
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_boilerplate_test_fallback_create_surface (const char *name,
|
||||
cairo_content_t content,
|
||||
|
|
@ -70,6 +74,7 @@ _cairo_boilerplate_test_fallback16_create_surface (const char *name,
|
|||
ceil (width), ceil (height));
|
||||
}
|
||||
|
||||
#if CAIRO_HAS_TEST_NULL_SURFACE
|
||||
static cairo_surface_t *
|
||||
_cairo_boilerplate_test_null_create_surface (const char *name,
|
||||
cairo_content_t content,
|
||||
|
|
@ -82,13 +87,11 @@ _cairo_boilerplate_test_null_create_surface (const char *name,
|
|||
void **closure)
|
||||
{
|
||||
*closure = NULL;
|
||||
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,9,3)
|
||||
return _cairo_test_null_surface_create (content);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CAIRO_HAS_TEST_PAGINATED_SURFACE
|
||||
static const cairo_user_data_key_t test_paginated_closure_key;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -196,7 +199,9 @@ _cairo_boilerplate_test_paginated_cleanup (void *closure)
|
|||
cairo_surface_destroy (tpc->target);
|
||||
free (tpc);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CAIRO_HAS_TEST_WRAPPING_SURFACE
|
||||
static cairo_surface_t *
|
||||
_cairo_boilerplate_test_wrapping_create_surface (const char *name,
|
||||
cairo_content_t content,
|
||||
|
|
@ -208,7 +213,6 @@ _cairo_boilerplate_test_wrapping_create_surface (const char *name,
|
|||
int id,
|
||||
void **closure)
|
||||
{
|
||||
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,9,3)
|
||||
cairo_surface_t *target;
|
||||
cairo_surface_t *surface;
|
||||
cairo_format_t format;
|
||||
|
|
@ -221,11 +225,8 @@ _cairo_boilerplate_test_wrapping_create_surface (const char *name,
|
|||
cairo_surface_destroy (target);
|
||||
|
||||
return surface;
|
||||
#else
|
||||
*closure = NULL;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static const cairo_boilerplate_target_t targets[] = {
|
||||
{
|
||||
|
|
@ -264,6 +265,7 @@ static const cairo_boilerplate_target_t targets[] = {
|
|||
NULL, /* _cairo_boilerplate_get_image_surface, */
|
||||
cairo_surface_write_to_png
|
||||
},
|
||||
#if CAIRO_HAS_TEST_PAGINATED_SURFACE
|
||||
{
|
||||
"test-paginated", "image", NULL, NULL,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
|
||||
|
|
@ -288,6 +290,8 @@ static const cairo_boilerplate_target_t targets[] = {
|
|||
NULL,
|
||||
FALSE, TRUE
|
||||
},
|
||||
#endif
|
||||
#if CAIRO_HAS_TEST_WRAPPING_SURFACE
|
||||
{
|
||||
"test-wrapping", "image", NULL, NULL,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_WRAPPING,
|
||||
|
|
@ -297,6 +301,8 @@ static const cairo_boilerplate_target_t targets[] = {
|
|||
_cairo_boilerplate_get_image_surface,
|
||||
cairo_surface_write_to_png,
|
||||
},
|
||||
#endif
|
||||
#if CAIRO_HAS_TEST_NULL_SURFACE
|
||||
{
|
||||
"null", "image", NULL, NULL,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_NULL,
|
||||
|
|
@ -307,5 +313,6 @@ static const cairo_boilerplate_target_t targets[] = {
|
|||
NULL,
|
||||
TRUE, FALSE
|
||||
},
|
||||
#endif
|
||||
};
|
||||
CAIRO_BOILERPLATE (test, targets)
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ _cairo_boilerplate_image_create_surface (const char *name,
|
|||
return cairo_image_surface_create (format, ceil (width), ceil (height));
|
||||
}
|
||||
|
||||
#if CAIRO_HAS_META_SURFACE
|
||||
static cairo_surface_t *
|
||||
_cairo_boilerplate_meta_create_surface (const char *name,
|
||||
cairo_content_t content,
|
||||
|
|
@ -151,8 +152,6 @@ _cairo_boilerplate_meta_create_surface (const char *name,
|
|||
return cairo_meta_surface_create (content, &extents);
|
||||
}
|
||||
|
||||
const cairo_user_data_key_t cairo_boilerplate_output_basename_key;
|
||||
|
||||
#if CAIRO_HAS_SCRIPT_SURFACE
|
||||
static cairo_status_t
|
||||
stdio_write (void *closure, const unsigned char *data, unsigned int len)
|
||||
|
|
@ -163,6 +162,9 @@ stdio_write (void *closure, const unsigned char *data, unsigned int len)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const cairo_user_data_key_t cairo_boilerplate_output_basename_key;
|
||||
|
||||
cairo_surface_t *
|
||||
_cairo_boilerplate_get_image_surface (cairo_surface_t *src,
|
||||
|
|
@ -186,7 +188,7 @@ _cairo_boilerplate_get_image_surface (cairo_surface_t *src,
|
|||
image = cairo_surface_reference (surface);
|
||||
|
||||
/* open a logging channel (only interesting for meta surfaces) */
|
||||
#if CAIRO_HAS_SCRIPT_SURFACE
|
||||
#if CAIRO_HAS_SCRIPT_SURFACE && CAIRO_HAS_META_SURFACE
|
||||
if (cairo_surface_get_type (src) == CAIRO_SURFACE_TYPE_META) {
|
||||
const char *test_name;
|
||||
|
||||
|
|
@ -307,6 +309,7 @@ static const cairo_boilerplate_target_t builtin_targets[] = {
|
|||
_cairo_boilerplate_get_image_surface,
|
||||
cairo_surface_write_to_png
|
||||
},
|
||||
#if CAIRO_HAS_META_SURFACE
|
||||
{
|
||||
"meta", "image", NULL, NULL,
|
||||
CAIRO_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR_ALPHA, 0,
|
||||
|
|
@ -327,6 +330,7 @@ static const cairo_boilerplate_target_t builtin_targets[] = {
|
|||
NULL, NULL,
|
||||
FALSE, TRUE
|
||||
},
|
||||
#endif
|
||||
};
|
||||
CAIRO_BOILERPLATE (builtin, builtin_targets)
|
||||
|
||||
|
|
|
|||
|
|
@ -144,9 +144,14 @@ perf: cairo-perf$(EXEEXT) cairo-perf-trace$(EXEEXT)
|
|||
|
||||
html-local: index.html
|
||||
|
||||
index.html: cairo-perf$(EXEEXT)
|
||||
$(CAIRO_PERF_ENVIRONMENT) ./cairo-perf-diff -t -h HEAD > $@
|
||||
perf-tag.html : cairo-perf${EXEEXT}
|
||||
$(CAIRO_PERF_ENVIRONMENT) ./cairo-perf-diff -t -h $@ `git describe --abbrev=0` HEAD
|
||||
perf-commit.html : cairo-perf${EXEEXT}
|
||||
$(CAIRO_PERF_ENVIRONMENT) ./cairo-perf-diff -t -h $@ HEAD
|
||||
|
||||
# Summarise changes in index.html, with details in links
|
||||
index.html: perf-tag.html perf-commit.html
|
||||
echo "<html><head><title>Performance Changes</title></head><body>Against <a href=\"perf-tag.html\">"`git describe --abbrev=0`"</a><br><a href=\"perf-commit.html\">Latest commit</a></body>" > $@
|
||||
|
||||
EXTRA_VALGRIND_FLAGS = $(CAIRO_EXTRA_VALGRIND_FLAGS)
|
||||
VALGRIND_MEMCHECK_FLAGS = \
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ benchmarks="cairo-perf"
|
|||
while true; do
|
||||
case $1 in
|
||||
-f|--force) force_cairo_perf="true";;
|
||||
-h|--html) html_output="true";;
|
||||
-h|--html) html_output="$2"; shift ;;
|
||||
-t|--trace) benchmarks="${benchmarks} cairo-perf-trace";;
|
||||
*) break;;
|
||||
esac
|
||||
|
|
@ -243,9 +243,9 @@ if [ ! -e $new ]; then
|
|||
new=`rev2perf $new`
|
||||
fi
|
||||
|
||||
if [ "$html_output" != "true" ]; then
|
||||
if [ -z "$html_output" ]; then
|
||||
$CAIRO_DIR/perf/cairo-perf-diff-files $old $new
|
||||
else
|
||||
$CAIRO_DIR/perf/cairo-perf-diff-files $old $new |
|
||||
$CAIRO_DIR/perf/make-html.py
|
||||
$CAIRO_DIR/perf/make-html.py > $html_output
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ cairo_private = \
|
|||
cairo-private.h \
|
||||
cairo-reference-count-private.h \
|
||||
cairo-region-private.h \
|
||||
cairo-rtree-private.h \
|
||||
cairo-scaled-font-private.h \
|
||||
cairo-skiplist-private.h \
|
||||
cairo-spans-private.h \
|
||||
|
|
@ -133,6 +134,7 @@ cairo_sources = \
|
|||
cairo-polygon.c \
|
||||
cairo-rectangle.c \
|
||||
cairo-region.c \
|
||||
cairo-rtree.c \
|
||||
cairo-scaled-font.c \
|
||||
cairo-skiplist.c \
|
||||
cairo-slope.c \
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
|
|||
surface->height = pixman_image_get_height (pixman_image);
|
||||
surface->stride = pixman_image_get_stride (pixman_image);
|
||||
surface->depth = pixman_image_get_depth (pixman_image);
|
||||
surface->is_clear = FALSE;
|
||||
|
||||
surface->clip_region = NULL;
|
||||
|
||||
|
|
@ -358,6 +359,8 @@ _cairo_image_surface_create_with_pixman_format (unsigned char *data,
|
|||
pixman_format);
|
||||
if (cairo_surface_status (surface))
|
||||
pixman_image_unref (pixman_image);
|
||||
else
|
||||
((cairo_image_surface_t *)surface)->is_clear = TRUE;
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
|
@ -1113,6 +1116,8 @@ _cairo_image_surface_composite (cairo_operator_t op,
|
|||
_cairo_pattern_release_surface (mask_pattern, &mask->base, &mask_attr);
|
||||
|
||||
_cairo_pattern_release_surface (src_pattern, &src->base, &src_attr);
|
||||
if (op != CAIRO_OPERATOR_CLEAR)
|
||||
dst->is_clear = FALSE;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
@ -1171,6 +1176,9 @@ _cairo_image_surface_fill_rectangles (void *abstract_surface,
|
|||
if (pixman_rects != stack_rects)
|
||||
free (pixman_rects);
|
||||
|
||||
if (op != CAIRO_OPERATOR_CLEAR)
|
||||
surface->is_clear = FALSE;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
@ -1300,6 +1308,9 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
|
|||
|
||||
pixman_image_unref (mask);
|
||||
|
||||
if (op != CAIRO_OPERATOR_CLEAR)
|
||||
dst->is_clear = FALSE;
|
||||
|
||||
if (! _cairo_operator_bounded_by_mask (op)) {
|
||||
status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base,
|
||||
&attributes,
|
||||
|
|
@ -1458,6 +1469,9 @@ _cairo_image_surface_span_renderer_finish (void *abstract_renderer)
|
|||
rects->width, rects->height,
|
||||
dst->clip_region);
|
||||
}
|
||||
|
||||
if (renderer->op != CAIRO_OPERATOR_CLEAR)
|
||||
dst->is_clear = FALSE;
|
||||
}
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
return _cairo_span_renderer_set_error (abstract_renderer,
|
||||
|
|
@ -1567,6 +1581,25 @@ _cairo_image_surface_get_font_options (void *abstract_surface,
|
|||
cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_image_surface_paint (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
/* we know that surfaces are calloc, so ignore any redundant clears */
|
||||
if (op == CAIRO_OPERATOR_CLEAR && clip == NULL) {
|
||||
cairo_image_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->is_clear)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
surface->is_clear = TRUE;
|
||||
}
|
||||
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_surface_is_image:
|
||||
* @surface: a #cairo_surface_t
|
||||
|
|
@ -1605,7 +1638,7 @@ const cairo_surface_backend_t _cairo_image_surface_backend = {
|
|||
NULL, /* font_fini */
|
||||
NULL, /* glyph_fini */
|
||||
|
||||
NULL, /* paint */
|
||||
_cairo_image_surface_paint,
|
||||
NULL, /* mask */
|
||||
NULL, /* stroke */
|
||||
NULL, /* fill */
|
||||
|
|
|
|||
|
|
@ -159,6 +159,16 @@ _cairo_paginated_surface_finish (void *abstract_surface)
|
|||
status = cairo_surface_status (abstract_surface);
|
||||
}
|
||||
|
||||
/* XXX We want to propagate any errors from destroy(), but those are not
|
||||
* returned via the api. So we need to explicitly finish the target,
|
||||
* and check the status afterwards. However, we can only call finish()
|
||||
* on the target, if we own it.
|
||||
*/
|
||||
if (CAIRO_REFERENCE_COUNT_GET_VALUE (&surface->target->ref_count) == 1) {
|
||||
cairo_surface_finish (surface->target);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = cairo_surface_status (surface->target);
|
||||
}
|
||||
cairo_surface_destroy (surface->target);
|
||||
|
||||
cairo_surface_finish (surface->meta);
|
||||
|
|
|
|||
|
|
@ -488,6 +488,7 @@ _cairo_path_fixed_curve_to (cairo_path_fixed_t *path,
|
|||
{
|
||||
cairo_status_t status;
|
||||
cairo_point_t point[3];
|
||||
cairo_slope_t slope, tangent;
|
||||
|
||||
/* make sure subpaths are started properly */
|
||||
if (! path->has_current_point) {
|
||||
|
|
@ -502,6 +503,17 @@ _cairo_path_fixed_curve_to (cairo_path_fixed_t *path,
|
|||
point[0].x = x0; point[0].y = y0;
|
||||
point[1].x = x1; point[1].y = y1;
|
||||
point[2].x = x2; point[2].y = y2;
|
||||
|
||||
_cairo_slope_init (&slope, &path->current_point, &point[2]);
|
||||
_cairo_slope_init (&tangent, &path->current_point, &point[0]);
|
||||
if (_cairo_slope_compare (&slope, &tangent) == 0) {
|
||||
_cairo_slope_init (&tangent, &point[1], &point[2]);
|
||||
if (_cairo_slope_compare (&slope, &tangent) == 0) {
|
||||
/* just a straight line... */
|
||||
return _cairo_path_fixed_line_to (path, x2, y2);
|
||||
}
|
||||
}
|
||||
|
||||
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CURVE_TO, point, 3);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
|
|
|||
|
|
@ -244,6 +244,19 @@ _cairo_pdf_surface_set_size_internal (cairo_pdf_surface_t *surface,
|
|||
&surface->cairo_to_pdf);
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_path_covers_bbox (cairo_pdf_surface_t *surface,
|
||||
cairo_path_fixed_t *path)
|
||||
{
|
||||
cairo_box_t box;
|
||||
|
||||
return _cairo_path_fixed_is_rectangle (path, &box) &&
|
||||
box.p1.x <= 0 &&
|
||||
box.p1.y <= 0 &&
|
||||
box.p2.x >= _cairo_fixed_from_double (surface->width) &&
|
||||
box.p2.y >= _cairo_fixed_from_double (surface->height);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_pdf_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
|
||||
cairo_path_fixed_t *path,
|
||||
|
|
@ -269,6 +282,9 @@ _cairo_pdf_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (_path_covers_bbox (surface, path))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
return _cairo_pdf_operators_clip (&surface->pdf_operators, path, fill_rule);
|
||||
}
|
||||
|
||||
|
|
@ -3657,37 +3673,56 @@ _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface,
|
|||
_cairo_output_stream_printf (surface->output,
|
||||
"endcodespacerange\n");
|
||||
|
||||
num_bfchar = font_subset->num_glyphs - 1;
|
||||
|
||||
/* The CMap specification has a limit of 100 characters per beginbfchar operator */
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d beginbfchar\n",
|
||||
num_bfchar > 100 ? 100 : num_bfchar);
|
||||
|
||||
for (i = 0; i < num_bfchar; i++) {
|
||||
if (i != 0 && i % 100 == 0) {
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"endbfchar\n"
|
||||
"%d beginbfchar\n",
|
||||
num_bfchar - i > 100 ? 100 : num_bfchar - i);
|
||||
}
|
||||
if (is_composite) {
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"<%04x> ",
|
||||
i + 1);
|
||||
} else {
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"<%02x> ",
|
||||
i + 1);
|
||||
}
|
||||
status = _cairo_pdf_surface_emit_unicode_for_glyph (surface,
|
||||
font_subset->utf8[i + 1]);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
if (is_composite) {
|
||||
num_bfchar = font_subset->num_glyphs - 1;
|
||||
|
||||
/* The CMap specification has a limit of 100 characters per beginbfchar operator */
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"\n");
|
||||
"%d beginbfchar\n",
|
||||
num_bfchar > 100 ? 100 : num_bfchar);
|
||||
|
||||
for (i = 0; i < num_bfchar; i++) {
|
||||
if (i != 0 && i % 100 == 0) {
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"endbfchar\n"
|
||||
"%d beginbfchar\n",
|
||||
num_bfchar - i > 100 ? 100 : num_bfchar - i);
|
||||
}
|
||||
_cairo_output_stream_printf (surface->output, "<%04x> ", i + 1);
|
||||
status = _cairo_pdf_surface_emit_unicode_for_glyph (surface,
|
||||
font_subset->utf8[i + 1]);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"\n");
|
||||
}
|
||||
} else {
|
||||
num_bfchar = font_subset->num_glyphs;
|
||||
|
||||
/* The CMap specification has a limit of 100 characters per beginbfchar operator */
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d beginbfchar\n",
|
||||
num_bfchar > 100 ? 100 : num_bfchar);
|
||||
|
||||
for (i = 0; i < num_bfchar; i++) {
|
||||
if (i != 0 && i % 100 == 0) {
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"endbfchar\n"
|
||||
"%d beginbfchar\n",
|
||||
num_bfchar - i > 100 ? 100 : num_bfchar - i);
|
||||
}
|
||||
_cairo_output_stream_printf (surface->output, "<%02x> ", i);
|
||||
status = _cairo_pdf_surface_emit_unicode_for_glyph (surface,
|
||||
font_subset->utf8[i]);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"\n");
|
||||
}
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"endbfchar\n");
|
||||
|
||||
|
|
|
|||
125
src/cairo-rtree-private.h
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2009 Chris Wilson
|
||||
*
|
||||
* 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 Chris Wilson.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_RTREE_PRIVATE_H
|
||||
#define CAIRO_RTREE_PRIVATE_H
|
||||
|
||||
#include "cairo-compiler-private.h"
|
||||
#include "cairo-types-private.h"
|
||||
|
||||
#include "cairo-freelist-private.h"
|
||||
#include "cairo-list-private.h"
|
||||
|
||||
enum {
|
||||
CAIRO_RTREE_NODE_AVAILABLE,
|
||||
CAIRO_RTREE_NODE_DIVIDED,
|
||||
CAIRO_RTREE_NODE_OCCUPIED,
|
||||
};
|
||||
|
||||
typedef struct _cairo_rtree_node {
|
||||
struct _cairo_rtree_node *children[4], *parent;
|
||||
void **owner;
|
||||
cairo_list_t link;
|
||||
uint16_t pinned;
|
||||
uint16_t state;
|
||||
uint16_t x, y;
|
||||
uint16_t width, height;
|
||||
} cairo_rtree_node_t;
|
||||
|
||||
typedef struct _cairo_rtree {
|
||||
cairo_rtree_node_t root;
|
||||
int min_size;
|
||||
void (*evict) (void *node);
|
||||
cairo_list_t pinned;
|
||||
cairo_list_t available;
|
||||
cairo_list_t evictable;
|
||||
cairo_freepool_t node_freepool;
|
||||
} cairo_rtree_t;
|
||||
|
||||
cairo_private cairo_rtree_node_t *
|
||||
_cairo_rtree_node_create (cairo_rtree_t *rtree,
|
||||
cairo_rtree_node_t *parent,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_rtree_node_insert (cairo_rtree_t *rtree,
|
||||
cairo_rtree_node_t *node,
|
||||
int width,
|
||||
int height,
|
||||
cairo_rtree_node_t **out);
|
||||
|
||||
cairo_private void
|
||||
_cairo_rtree_node_collapse (cairo_rtree_t *rtree, cairo_rtree_node_t *node);
|
||||
|
||||
cairo_private void
|
||||
_cairo_rtree_node_destroy (cairo_rtree_t *rtree, cairo_rtree_node_t *node);
|
||||
|
||||
cairo_private void
|
||||
_cairo_rtree_init (cairo_rtree_t *rtree,
|
||||
int width,
|
||||
int height,
|
||||
int min_size,
|
||||
int node_size,
|
||||
void (*evict) (void *node));
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_rtree_insert (cairo_rtree_t *rtree,
|
||||
int width,
|
||||
int height,
|
||||
cairo_rtree_node_t **out);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_rtree_evict_random (cairo_rtree_t *rtree,
|
||||
int width,
|
||||
int height,
|
||||
cairo_rtree_node_t **out);
|
||||
|
||||
cairo_private void *
|
||||
_cairo_rtree_pin (cairo_rtree_t *rtree, cairo_rtree_node_t *node);
|
||||
|
||||
cairo_private void
|
||||
_cairo_rtree_unpin (cairo_rtree_t *rtree);
|
||||
|
||||
cairo_private void
|
||||
_cairo_rtree_reset (cairo_rtree_t *rtree);
|
||||
|
||||
cairo_private void
|
||||
_cairo_rtree_fini (cairo_rtree_t *rtree);
|
||||
|
||||
#endif /* CAIRO_RTREE_PRIVATE_H */
|
||||
395
src/cairo-rtree.c
Normal file
|
|
@ -0,0 +1,395 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2009 Chris Wilson
|
||||
*
|
||||
* 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 Chris Wilson.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-rtree-private.h"
|
||||
|
||||
cairo_rtree_node_t *
|
||||
_cairo_rtree_node_create (cairo_rtree_t *rtree,
|
||||
cairo_rtree_node_t *parent,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_rtree_node_t *node;
|
||||
|
||||
node = _cairo_freepool_alloc (&rtree->node_freepool);
|
||||
if (node == NULL) {
|
||||
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node->children[0] = NULL;
|
||||
node->parent = parent;
|
||||
node->owner = NULL;
|
||||
node->state = CAIRO_RTREE_NODE_AVAILABLE;
|
||||
node->pinned = FALSE;
|
||||
node->x = x;
|
||||
node->y = y;
|
||||
node->width = width;
|
||||
node->height = height;
|
||||
|
||||
cairo_list_add (&node->link, &rtree->available);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_rtree_node_destroy (cairo_rtree_t *rtree, cairo_rtree_node_t *node)
|
||||
{
|
||||
int i;
|
||||
|
||||
cairo_list_del (&node->link);
|
||||
|
||||
if (node->state == CAIRO_RTREE_NODE_OCCUPIED) {
|
||||
if (node->owner != NULL)
|
||||
*node->owner = NULL;
|
||||
if (rtree->evict != NULL)
|
||||
rtree->evict (node);
|
||||
} else {
|
||||
for (i = 0; i < 4 && node->children[i] != NULL; i++)
|
||||
_cairo_rtree_node_destroy (rtree, node->children[i]);
|
||||
}
|
||||
|
||||
_cairo_freepool_free (&rtree->node_freepool, node);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_rtree_node_collapse (cairo_rtree_t *rtree, cairo_rtree_node_t *node)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert (node->pinned == FALSE);
|
||||
|
||||
do {
|
||||
assert (node->state == CAIRO_RTREE_NODE_DIVIDED);
|
||||
|
||||
for (i = 0; i < 4 && node->children[i] != NULL; i++)
|
||||
if (node->children[i]->state != CAIRO_RTREE_NODE_AVAILABLE)
|
||||
return;
|
||||
|
||||
for (i = 0; i < 4 && node->children[i] != NULL; i++)
|
||||
_cairo_rtree_node_destroy (rtree, node->children[i]);
|
||||
|
||||
node->children[0] = NULL;
|
||||
node->state = CAIRO_RTREE_NODE_AVAILABLE;
|
||||
cairo_list_move (&node->link, &rtree->available);
|
||||
|
||||
node = node->parent;
|
||||
} while (node != NULL && ! node->pinned);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_rtree_node_insert (cairo_rtree_t *rtree,
|
||||
cairo_rtree_node_t *node,
|
||||
int width,
|
||||
int height,
|
||||
cairo_rtree_node_t **out)
|
||||
{
|
||||
int w, h, i;
|
||||
|
||||
assert (node->state == CAIRO_RTREE_NODE_AVAILABLE);
|
||||
assert (node->pinned == FALSE);
|
||||
|
||||
if (node->width - width > rtree->min_size ||
|
||||
node->height - height > rtree->min_size)
|
||||
{
|
||||
w = node->width - width;
|
||||
h = node->height - height;
|
||||
|
||||
i = 0;
|
||||
node->children[i] = _cairo_rtree_node_create (rtree, node,
|
||||
node->x, node->y,
|
||||
width, height);
|
||||
if (unlikely (node->children[i] == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
i++;
|
||||
|
||||
if (w > rtree->min_size) {
|
||||
node->children[i] = _cairo_rtree_node_create (rtree, node,
|
||||
node->x + width,
|
||||
node->y,
|
||||
w, height);
|
||||
if (unlikely (node->children[i] == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (h > rtree->min_size) {
|
||||
node->children[i] = _cairo_rtree_node_create (rtree, node,
|
||||
node->x,
|
||||
node->y + height,
|
||||
width, h);
|
||||
if (unlikely (node->children[i] == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
i++;
|
||||
|
||||
if (w > rtree->min_size) {
|
||||
node->children[i] = _cairo_rtree_node_create (rtree, node,
|
||||
node->x + width,
|
||||
node->y + height,
|
||||
w, h);
|
||||
if (unlikely (node->children[i] == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < 4)
|
||||
node->children[i] = NULL;
|
||||
|
||||
node->state = CAIRO_RTREE_NODE_DIVIDED;
|
||||
cairo_list_move (&node->link, &rtree->evictable);
|
||||
node = node->children[0];
|
||||
}
|
||||
|
||||
node->state = CAIRO_RTREE_NODE_OCCUPIED;
|
||||
cairo_list_move (&node->link, &rtree->evictable);
|
||||
*out = node;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_rtree_insert (cairo_rtree_t *rtree,
|
||||
int width,
|
||||
int height,
|
||||
cairo_rtree_node_t **out)
|
||||
{
|
||||
cairo_rtree_node_t *node;
|
||||
|
||||
cairo_list_foreach_entry (node, cairo_rtree_node_t,
|
||||
&rtree->available, link)
|
||||
{
|
||||
if (node->width >= width && node->height >= height)
|
||||
return _cairo_rtree_node_insert (rtree, node, width, height, out);
|
||||
}
|
||||
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
hars_petruska_f54_1_random (void)
|
||||
{
|
||||
#define rol(x,k) ((x << k) | (x >> (32-k)))
|
||||
static uint32_t x;
|
||||
return x = (x ^ rol (x, 5) ^ rol (x, 24)) + 0x37798849;
|
||||
#undef rol
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_rtree_evict_random (cairo_rtree_t *rtree,
|
||||
int width,
|
||||
int height,
|
||||
cairo_rtree_node_t **out)
|
||||
{
|
||||
cairo_rtree_node_t *node;
|
||||
int i, cnt;
|
||||
|
||||
cnt = 0;
|
||||
cairo_list_foreach_entry (node, cairo_rtree_node_t,
|
||||
&rtree->evictable, link)
|
||||
{
|
||||
if (node->width >= width && node->height >= height)
|
||||
cnt++;
|
||||
}
|
||||
|
||||
if (cnt == 0)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
cnt = hars_petruska_f54_1_random () % cnt;
|
||||
cairo_list_foreach_entry (node, cairo_rtree_node_t,
|
||||
&rtree->evictable, link)
|
||||
{
|
||||
if (node->width >= width && node->height >= height && cnt-- == 0) {
|
||||
if (node->state == CAIRO_RTREE_NODE_OCCUPIED) {
|
||||
if (node->owner != NULL)
|
||||
*node->owner = NULL;
|
||||
if (rtree->evict != NULL)
|
||||
rtree->evict (node);
|
||||
} else {
|
||||
for (i = 0; i < 4 && node->children[i] != NULL; i++)
|
||||
_cairo_rtree_node_destroy (rtree, node->children[i]);
|
||||
node->children[0] = NULL;
|
||||
}
|
||||
|
||||
node->state = CAIRO_RTREE_NODE_AVAILABLE;
|
||||
cairo_list_move (&node->link, &rtree->available);
|
||||
|
||||
*out = node;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
void *
|
||||
_cairo_rtree_pin (cairo_rtree_t *rtree, cairo_rtree_node_t *node)
|
||||
{
|
||||
void *ptr = node;
|
||||
|
||||
while (node->pinned == FALSE) {
|
||||
cairo_list_move (&node->link, &rtree->pinned);
|
||||
node->pinned = TRUE;
|
||||
node = node->parent;
|
||||
if (node == NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_rtree_unpin (cairo_rtree_t *rtree)
|
||||
{
|
||||
cairo_rtree_node_t *node, *next;
|
||||
cairo_list_t can_collapse;
|
||||
|
||||
if (cairo_list_is_empty (&rtree->pinned))
|
||||
return;
|
||||
|
||||
cairo_list_init (&can_collapse);
|
||||
|
||||
cairo_list_foreach_entry_safe (node, next,
|
||||
cairo_rtree_node_t,
|
||||
&rtree->pinned,
|
||||
link)
|
||||
{
|
||||
node->pinned = FALSE;
|
||||
if (node->state == CAIRO_RTREE_NODE_OCCUPIED && node->owner == NULL) {
|
||||
cairo_bool_t all_available;
|
||||
int i;
|
||||
|
||||
node->state = CAIRO_RTREE_NODE_AVAILABLE;
|
||||
cairo_list_move (&node->link, &rtree->available);
|
||||
|
||||
all_available = TRUE;
|
||||
node = node->parent;
|
||||
for (i = 0; i < 4 && node->children[i] != NULL && all_available; i++)
|
||||
all_available &= node->children[i]->state == CAIRO_RTREE_NODE_AVAILABLE;
|
||||
|
||||
if (all_available) {
|
||||
cairo_list_move (&node->link, &can_collapse);
|
||||
for (i = 0; i < 4 && node->children[i] != NULL; i++)
|
||||
cairo_list_del (&node->children[i]->link);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_list_move (&node->link, &rtree->evictable);
|
||||
}
|
||||
}
|
||||
|
||||
cairo_list_foreach_entry_safe (node, next,
|
||||
cairo_rtree_node_t,
|
||||
&can_collapse,
|
||||
link)
|
||||
{
|
||||
_cairo_rtree_node_collapse (rtree, node);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_rtree_init (cairo_rtree_t *rtree,
|
||||
int width,
|
||||
int height,
|
||||
int min_size,
|
||||
int node_size,
|
||||
void (*evict) (void *node))
|
||||
{
|
||||
rtree->evict = evict;
|
||||
|
||||
assert (node_size >= (int) sizeof (cairo_rtree_node_t));
|
||||
_cairo_freepool_init (&rtree->node_freepool, node_size);
|
||||
|
||||
cairo_list_init (&rtree->available);
|
||||
cairo_list_init (&rtree->pinned);
|
||||
cairo_list_init (&rtree->evictable);
|
||||
|
||||
rtree->min_size = min_size;
|
||||
|
||||
memset (&rtree->root, 0, sizeof (rtree->root));
|
||||
rtree->root.width = width;
|
||||
rtree->root.height = height;
|
||||
rtree->root.state = CAIRO_RTREE_NODE_AVAILABLE;
|
||||
cairo_list_add (&rtree->root.link, &rtree->available);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_rtree_reset (cairo_rtree_t *rtree)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (rtree->root.state == CAIRO_RTREE_NODE_OCCUPIED) {
|
||||
if (rtree->root.owner != NULL)
|
||||
*rtree->root.owner = NULL;
|
||||
if (rtree->evict != NULL)
|
||||
rtree->evict (&rtree->root);
|
||||
} else {
|
||||
for (i = 0; i < 4 && rtree->root.children[i] != NULL; i++)
|
||||
_cairo_rtree_node_destroy (rtree, rtree->root.children[i]);
|
||||
rtree->root.children[0] = NULL;
|
||||
}
|
||||
|
||||
cairo_list_init (&rtree->available);
|
||||
cairo_list_init (&rtree->evictable);
|
||||
cairo_list_init (&rtree->pinned);
|
||||
|
||||
rtree->root.state = CAIRO_RTREE_NODE_AVAILABLE;
|
||||
rtree->root.pinned = FALSE;
|
||||
cairo_list_add (&rtree->root.link, &rtree->available);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_rtree_fini (cairo_rtree_t *rtree)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (rtree->root.state == CAIRO_RTREE_NODE_OCCUPIED) {
|
||||
if (rtree->root.owner != NULL)
|
||||
*rtree->root.owner = NULL;
|
||||
if (rtree->evict != NULL)
|
||||
rtree->evict (&rtree->root);
|
||||
} else {
|
||||
for (i = 0; i < 4 && rtree->root.children[i] != NULL; i++)
|
||||
_cairo_rtree_node_destroy (rtree, rtree->root.children[i]);
|
||||
}
|
||||
|
||||
_cairo_freepool_fini (&rtree->node_freepool);
|
||||
}
|
||||
|
|
@ -1428,22 +1428,22 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
|
|||
extents->x_advance = 0.0;
|
||||
extents->y_advance = 0.0;
|
||||
|
||||
if (scaled_font->status)
|
||||
return;
|
||||
if (unlikely (scaled_font->status))
|
||||
goto ZERO_EXTENTS;
|
||||
|
||||
if (num_glyphs == 0)
|
||||
return;
|
||||
goto ZERO_EXTENTS;
|
||||
|
||||
if (num_glyphs < 0) {
|
||||
if (unlikely (num_glyphs < 0)) {
|
||||
_cairo_error_throw (CAIRO_STATUS_NEGATIVE_COUNT);
|
||||
/* XXX Can't propagate error */
|
||||
return;
|
||||
goto ZERO_EXTENTS;
|
||||
}
|
||||
|
||||
if (glyphs == NULL) {
|
||||
if (unlikely (glyphs == NULL)) {
|
||||
_cairo_error_throw (CAIRO_STATUS_NULL_POINTER);
|
||||
/* XXX Can't propagate error */
|
||||
return;
|
||||
goto ZERO_EXTENTS;
|
||||
}
|
||||
|
||||
_cairo_scaled_font_freeze_cache (scaled_font);
|
||||
|
|
@ -1514,6 +1514,15 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
|
|||
|
||||
UNLOCK:
|
||||
_cairo_scaled_font_thaw_cache (scaled_font);
|
||||
return;
|
||||
|
||||
ZERO_EXTENTS:
|
||||
extents->x_bearing = 0.0;
|
||||
extents->y_bearing = 0.0;
|
||||
extents->width = 0.0;
|
||||
extents->height = 0.0;
|
||||
extents->x_advance = 0.0;
|
||||
extents->y_advance = 0.0;
|
||||
}
|
||||
slim_hidden_def (cairo_scaled_font_glyph_extents);
|
||||
|
||||
|
|
@ -2028,7 +2037,6 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
int x, y;
|
||||
cairo_surface_pattern_t glyph_pattern;
|
||||
cairo_image_surface_t *glyph_surface;
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
|
||||
|
|
@ -2046,8 +2054,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
* glyph. Later we'll deal with different formats. */
|
||||
if (mask == NULL) {
|
||||
mask_format = glyph_surface->format;
|
||||
mask = cairo_image_surface_create (mask_format,
|
||||
width, height);
|
||||
mask = cairo_image_surface_create (mask_format, width, height);
|
||||
status = mask->status;
|
||||
if (unlikely (status))
|
||||
goto CLEANUP_MASK;
|
||||
|
|
@ -2074,10 +2081,9 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
break;
|
||||
}
|
||||
|
||||
new_mask = cairo_image_surface_create (mask_format,
|
||||
width, height);
|
||||
if (new_mask->status) {
|
||||
status = new_mask->status;
|
||||
new_mask = cairo_image_surface_create (mask_format, width, height);
|
||||
status = new_mask->status;
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (new_mask);
|
||||
goto CLEANUP_MASK;
|
||||
}
|
||||
|
|
@ -2105,33 +2111,41 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
mask = new_mask;
|
||||
}
|
||||
|
||||
/* round glyph locations to the nearest pixel */
|
||||
/* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
|
||||
x = _cairo_lround (glyphs[i].x - glyph_surface->base.device_transform.x0);
|
||||
y = _cairo_lround (glyphs[i].y - glyph_surface->base.device_transform.y0);
|
||||
if (glyph_surface->width && glyph_surface->height) {
|
||||
cairo_surface_pattern_t glyph_pattern;
|
||||
|
||||
_cairo_pattern_init_for_surface (&glyph_pattern, &glyph_surface->base);
|
||||
/* round glyph locations to the nearest pixel */
|
||||
/* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
|
||||
x = _cairo_lround (glyphs[i].x -
|
||||
glyph_surface->base.device_transform.x0);
|
||||
y = _cairo_lround (glyphs[i].y -
|
||||
glyph_surface->base.device_transform.y0);
|
||||
|
||||
status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
|
||||
&white_pattern.base,
|
||||
&glyph_pattern.base,
|
||||
mask,
|
||||
0, 0,
|
||||
0, 0,
|
||||
x - dest_x, y - dest_y,
|
||||
glyph_surface->width,
|
||||
glyph_surface->height,
|
||||
NULL);
|
||||
_cairo_pattern_init_for_surface (&glyph_pattern,
|
||||
&glyph_surface->base);
|
||||
|
||||
_cairo_pattern_fini (&glyph_pattern.base);
|
||||
status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
|
||||
&white_pattern.base,
|
||||
&glyph_pattern.base,
|
||||
mask,
|
||||
0, 0,
|
||||
0, 0,
|
||||
x - dest_x, y - dest_y,
|
||||
glyph_surface->width,
|
||||
glyph_surface->height,
|
||||
NULL);
|
||||
|
||||
if (unlikely (status))
|
||||
goto CLEANUP_MASK;
|
||||
_cairo_pattern_fini (&glyph_pattern.base);
|
||||
|
||||
if (unlikely (status))
|
||||
goto CLEANUP_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
if (mask_format == CAIRO_FORMAT_ARGB32)
|
||||
if (mask_format == CAIRO_FORMAT_ARGB32) {
|
||||
pixman_image_set_component_alpha (((cairo_image_surface_t*) mask)->
|
||||
pixman_image, TRUE);
|
||||
}
|
||||
_cairo_pattern_init_for_surface (&mask_pattern, mask);
|
||||
|
||||
status = _cairo_surface_composite (op, pattern, &mask_pattern.base,
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ _cairo_spline_init (cairo_spline_t *spline,
|
|||
const cairo_point_t *a, const cairo_point_t *b,
|
||||
const cairo_point_t *c, const cairo_point_t *d)
|
||||
{
|
||||
cairo_slope_t slope;
|
||||
|
||||
spline->add_point_func = add_point_func;
|
||||
spline->closure = closure;
|
||||
|
||||
|
|
@ -67,6 +69,13 @@ _cairo_spline_init (cairo_spline_t *spline,
|
|||
else
|
||||
_cairo_slope_init (&spline->final_slope, &spline->knots.a, &spline->knots.d);
|
||||
|
||||
_cairo_slope_init (&slope, &spline->knots.a, &spline->knots.d);
|
||||
if (_cairo_slope_compare (&slope, &spline->initial_slope) == 0 &&
|
||||
_cairo_slope_compare (&slope, &spline->final_slope) == 0)
|
||||
{
|
||||
return FALSE; /* just a straight line... */
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -166,7 +166,6 @@ typedef enum _cairo_int_status {
|
|||
typedef enum _cairo_internal_surface_type {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED = 0x1000,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_WRAPPING,
|
||||
|
|
@ -174,6 +173,10 @@ typedef enum _cairo_internal_surface_type {
|
|||
CAIRO_INTERNAL_SURFACE_TYPE_TYPE3_GLYPH
|
||||
} cairo_internal_surface_type_t;
|
||||
|
||||
#define CAIRO_HAS_TEST_PAGINATED_SURFACE 1
|
||||
#define CAIRO_HAS_TEST_NULL_SURFACE 1
|
||||
#define CAIRO_HAS_TEST_WRAPPING_SURFACE 1
|
||||
|
||||
typedef struct _cairo_point {
|
||||
cairo_fixed_t x;
|
||||
cairo_fixed_t y;
|
||||
|
|
|
|||
|
|
@ -457,6 +457,12 @@ _cairo_xlib_display_notify (cairo_xlib_display_t *display)
|
|||
cairo_xlib_job_t *jobs, *job, *freelist;
|
||||
Display *dpy = display->display;
|
||||
|
||||
/* Optimistic atomic pointer read -- don't care if it is wrong due to
|
||||
* contention as we will check again very shortly.
|
||||
*/
|
||||
if (display->workqueue == NULL)
|
||||
return;
|
||||
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
jobs = display->workqueue;
|
||||
while (jobs != NULL) {
|
||||
|
|
@ -508,6 +514,12 @@ _cairo_xlib_display_get_xrender_format (cairo_xlib_display_t *display,
|
|||
{
|
||||
XRenderPictFormat *xrender_format;
|
||||
|
||||
#if ! ATOMIC_OP_NEEDS_MEMORY_BARRIER
|
||||
xrender_format = display->cached_xrender_formats[format];
|
||||
if (likely (xrender_format != NULL))
|
||||
return xrender_format;
|
||||
#endif
|
||||
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
xrender_format = display->cached_xrender_formats[format];
|
||||
if (xrender_format == NULL) {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,12 @@
|
|||
* Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
|
||||
*/
|
||||
|
||||
/* Heed well the words of Owen Taylor:
|
||||
* "Any patch that works around a render bug, or claims to, without a
|
||||
* specific reference to the bug filed in bugzilla.freedesktop.org will
|
||||
* never pass approval."
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-xlib-private.h"
|
||||
|
|
|
|||
|
|
@ -857,6 +857,7 @@ struct _cairo_image_surface {
|
|||
pixman_image_t *pixman_image;
|
||||
cairo_region_t *clip_region;
|
||||
|
||||
unsigned is_clear : 1;
|
||||
unsigned owns_data : 1;
|
||||
unsigned transparency : 2;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -679,6 +679,10 @@ REFERENCE_IMAGES = \
|
|||
over-between-source.svg12.rgb24.xfail.png \
|
||||
over-between-source.xlib.ref.png \
|
||||
over-between-source.xlib.rgb24.ref.png \
|
||||
overlapping-glyphs.argb32.ref.png \
|
||||
overlapping-glyphs.rgb24.ref.png \
|
||||
overlapping-glyphs.pdf.argb32.xfail.png \
|
||||
overlapping-glyphs.pdf.rgb24.xfail.png \
|
||||
paint-repeat.ref.png \
|
||||
paint-source-alpha.ref.png \
|
||||
paint-source-alpha.svg.ref.png \
|
||||
|
|
|
|||
|
|
@ -132,6 +132,7 @@ test_sources = \
|
|||
over-around-source.c \
|
||||
over-below-source.c \
|
||||
over-between-source.c \
|
||||
overlapping-glyphs.c \
|
||||
paint.c \
|
||||
paint-repeat.c \
|
||||
paint-source-alpha.c \
|
||||
|
|
|
|||
|
|
@ -1509,6 +1509,7 @@ _cairo_test_context_run_for_target (cairo_test_context_t *ctx,
|
|||
#if defined(HAVE_SIGNAL_H) && defined(HAVE_SETJMP_H)
|
||||
if (ctx->thread == 0 && ! RUNNING_ON_VALGRIND) {
|
||||
void (* volatile old_segfault_handler)(int);
|
||||
void (* volatile old_segfpe_handler)(int);
|
||||
void (* volatile old_sigpipe_handler)(int);
|
||||
void (* volatile old_sigabrt_handler)(int);
|
||||
void (* volatile old_sigalrm_handler)(int);
|
||||
|
|
@ -1517,6 +1518,9 @@ _cairo_test_context_run_for_target (cairo_test_context_t *ctx,
|
|||
#ifdef SIGSEGV
|
||||
old_segfault_handler = signal (SIGSEGV, segfault_handler);
|
||||
#endif
|
||||
#ifdef SIGFPE
|
||||
old_segfpe_handler = signal (SIGFPE, segfault_handler);
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
old_sigpipe_handler = signal (SIGPIPE, segfault_handler);
|
||||
#endif
|
||||
|
|
@ -1533,6 +1537,9 @@ _cairo_test_context_run_for_target (cairo_test_context_t *ctx,
|
|||
#ifdef SIGSEGV
|
||||
signal (SIGSEGV, old_segfault_handler);
|
||||
#endif
|
||||
#ifdef SIGFPE
|
||||
signal (SIGFPE, old_segfpe_handler);
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
signal (SIGPIPE, old_sigpipe_handler);
|
||||
#endif
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.8 KiB |
BIN
test/overlapping-glyphs.argb32.ref.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
123
test/overlapping-glyphs.c
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright © 2009 Chris Wilson
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software
|
||||
* and its documentation for any purpose is hereby granted without
|
||||
* fee, provided that the above copyright notice appear in all copies
|
||||
* and that both that copyright notice and this permission notice
|
||||
* appear in supporting documentation, and that the name of
|
||||
* Chris Wilson not be used in advertising or publicity pertaining to
|
||||
* distribution of the software without specific, written prior
|
||||
* permission. Chris Wilson makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL,
|
||||
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "cairo-test.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#define TEXT_SIZE 12
|
||||
#define HEIGHT (TEXT_SIZE + 4)
|
||||
#define WIDTH 50
|
||||
|
||||
#define MAX_GLYPHS 80
|
||||
|
||||
static cairo_test_status_t
|
||||
draw (cairo_t *cr, int width, int height)
|
||||
{
|
||||
cairo_glyph_t glyphs_stack[MAX_GLYPHS], *glyphs;
|
||||
const char *cairo = "Cairo";
|
||||
const char *giza = "Giza";
|
||||
cairo_text_extents_t cairo_extents;
|
||||
cairo_text_extents_t giza_extents;
|
||||
int count, num_glyphs;
|
||||
double x0, y0;
|
||||
|
||||
/* We draw in the default black, so paint white first. */
|
||||
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_select_font_face (cr, "Bitstream Vera Sans",
|
||||
CAIRO_FONT_SLANT_NORMAL,
|
||||
CAIRO_FONT_WEIGHT_NORMAL);
|
||||
cairo_set_font_size (cr, TEXT_SIZE);
|
||||
|
||||
/* We want to overlap two strings, so compute overlapping glyphs. */
|
||||
|
||||
cairo_text_extents (cr, cairo, &cairo_extents);
|
||||
cairo_text_extents (cr, giza, &giza_extents);
|
||||
|
||||
x0 = WIDTH/2. - (cairo_extents.width/2. + cairo_extents.x_bearing);
|
||||
y0 = HEIGHT/2. - (cairo_extents.height/2. + cairo_extents.y_bearing);
|
||||
glyphs = glyphs_stack;
|
||||
count = MAX_GLYPHS;
|
||||
cairo_scaled_font_text_to_glyphs (cairo_get_scaled_font (cr),
|
||||
x0, y0,
|
||||
cairo, strlen (cairo),
|
||||
&glyphs, &count,
|
||||
NULL, NULL,
|
||||
NULL);
|
||||
assert (glyphs == glyphs_stack);
|
||||
num_glyphs = count;
|
||||
|
||||
x0 = WIDTH/2. - (giza_extents.width/2. + giza_extents.x_bearing);
|
||||
y0 = HEIGHT/2. - (giza_extents.height/2. + giza_extents.y_bearing);
|
||||
glyphs = glyphs_stack + count;
|
||||
count = MAX_GLYPHS - count;
|
||||
cairo_scaled_font_text_to_glyphs (cairo_get_scaled_font (cr),
|
||||
x0, y0,
|
||||
giza, strlen (giza),
|
||||
&glyphs, &count,
|
||||
NULL, NULL,
|
||||
NULL);
|
||||
assert (glyphs == glyphs_stack + num_glyphs);
|
||||
glyphs = glyphs_stack;
|
||||
num_glyphs += count;
|
||||
|
||||
cairo_set_source_rgba (cr, 0, 0, 0, .5); /* translucent black, gray! */
|
||||
cairo_show_glyphs (cr, glyphs, num_glyphs);
|
||||
|
||||
/* and compare with filling */
|
||||
cairo_translate (cr, 0, HEIGHT);
|
||||
cairo_glyph_path (cr, glyphs, num_glyphs);
|
||||
cairo_fill (cr);
|
||||
|
||||
/* switch to using an unbounded operator for added complexity */
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_IN);
|
||||
|
||||
cairo_translate (cr, WIDTH, -HEIGHT);
|
||||
cairo_save (cr);
|
||||
cairo_rectangle (cr, 0, 0, WIDTH, HEIGHT);
|
||||
cairo_clip (cr);
|
||||
cairo_show_glyphs (cr, glyphs, num_glyphs);
|
||||
cairo_restore (cr);
|
||||
|
||||
cairo_translate (cr, 0, HEIGHT);
|
||||
cairo_save (cr);
|
||||
cairo_rectangle (cr, 0, 0, WIDTH, HEIGHT);
|
||||
cairo_clip (cr);
|
||||
cairo_glyph_path (cr, glyphs, num_glyphs);
|
||||
cairo_fill (cr);
|
||||
cairo_restore (cr);
|
||||
|
||||
return CAIRO_TEST_SUCCESS;
|
||||
}
|
||||
|
||||
CAIRO_TEST (overlapping_glyphs,
|
||||
"Test handing of overlapping glyphs",
|
||||
"text, glyphs", /* keywords */
|
||||
NULL, /* requirements */
|
||||
2 * WIDTH, 2 * HEIGHT,
|
||||
NULL, draw)
|
||||
|
||||
BIN
test/overlapping-glyphs.pdf.argb32.xfail.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
test/overlapping-glyphs.pdf.rgb24.xfail.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
test/overlapping-glyphs.rgb24.ref.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
|
|
@ -29,7 +29,7 @@
|
|||
#define NUM_GRADIENTS 4
|
||||
#define NUM_EXTEND 4
|
||||
#define SIZE 60
|
||||
#define WIDTH (SIZE * NUM_GRADIENTS)
|
||||
#define WIDTH (SIZE * NUM_GRADIENTS * NUM_GRADIENTS)
|
||||
#define HEIGHT (SIZE * NUM_EXTEND)
|
||||
|
||||
static void
|
||||
|
|
@ -37,18 +37,22 @@ draw_gradient (cairo_t *cr,
|
|||
int x,
|
||||
int y,
|
||||
int size,
|
||||
double offset,
|
||||
double inner_radius,
|
||||
double r1_offset,
|
||||
double r1_radius,
|
||||
double r2_offset,
|
||||
double r2_radius,
|
||||
cairo_extend_t extend)
|
||||
{
|
||||
cairo_pattern_t *pattern;
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
pattern = cairo_pattern_create_radial (x + size/2.0 + offset,
|
||||
y + size/2.0 + offset, inner_radius,
|
||||
x + size/2.0,
|
||||
y + size/2.0, size/3.0);
|
||||
pattern = cairo_pattern_create_radial (x + size/2.0 + r1_offset,
|
||||
y + size/2.0 + r1_offset,
|
||||
r1_radius,
|
||||
x + size/2.0 + r2_offset,
|
||||
y + size/2.0 + r2_offset,
|
||||
r2_radius);
|
||||
cairo_pattern_add_color_stop_rgba (pattern, 0.0,
|
||||
1.0, 0.0, 0.0, 1.0);
|
||||
cairo_pattern_add_color_stop_rgba (pattern, sqrt (1.0 / 2.0),
|
||||
|
|
@ -71,8 +75,7 @@ draw_gradient (cairo_t *cr,
|
|||
static cairo_test_status_t
|
||||
draw (cairo_t *cr, int width, int height)
|
||||
{
|
||||
int i, j;
|
||||
double inner_radius, offset;
|
||||
int i, j, k;
|
||||
cairo_extend_t extend[NUM_EXTEND] = {
|
||||
CAIRO_EXTEND_NONE,
|
||||
CAIRO_EXTEND_REPEAT,
|
||||
|
|
@ -84,10 +87,17 @@ draw (cairo_t *cr, int width, int height)
|
|||
|
||||
for (j = 0; j < NUM_EXTEND; j++) {
|
||||
for (i = 0; i < NUM_GRADIENTS; i++) {
|
||||
offset = i % 2 ? SIZE / 12.0 : 0.0;
|
||||
inner_radius = i >= NUM_EXTEND / 2 ? SIZE / 6.0 : 0.0;
|
||||
draw_gradient (cr, i * SIZE, j * SIZE, SIZE,
|
||||
offset, inner_radius, extend[j]);
|
||||
double r1_offset = i % 2 ? SIZE / 12.0 : 0.0;
|
||||
double r1_radius = i >= NUM_GRADIENTS / 2 ? SIZE / 6.0 : 0.0;
|
||||
for (k = 0; k < NUM_GRADIENTS; k++) {
|
||||
double r2_offset = k % 2 ? SIZE / 12.0 : 0.0;
|
||||
double r2_radius = k >= NUM_GRADIENTS / 2 ? SIZE / 3.0 : SIZE / 12.;
|
||||
draw_gradient (cr,
|
||||
i * SIZE * NUM_GRADIENTS + k * SIZE, j * SIZE, SIZE,
|
||||
r1_offset, r1_radius,
|
||||
r2_offset, r2_radius,
|
||||
extend[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 271 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 274 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
|
|
@ -257,11 +257,11 @@ get_user_font_face (cairo_font_face_t *substitute_font,
|
|||
text, -1,
|
||||
&glyphs, &num_glyphs,
|
||||
NULL, NULL, NULL);
|
||||
if (status) {
|
||||
cairo_font_options_destroy (options);
|
||||
cairo_scaled_font_destroy (measure);
|
||||
cairo_font_options_destroy (options);
|
||||
cairo_scaled_font_destroy (measure);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
/* find the glyph range the text covers */
|
||||
max_index = glyphs[0].index;
|
||||
|
|
@ -274,7 +274,7 @@ get_user_font_face (cairo_font_face_t *substitute_font,
|
|||
}
|
||||
|
||||
count = max_index - min_index + 1;
|
||||
widths = xmalloc (sizeof(double) * count);
|
||||
widths = xcalloc (sizeof (double), count);
|
||||
/* measure all of the necessary glyphs individually */
|
||||
for (i=0; i<num_glyphs; i++) {
|
||||
cairo_text_extents_t extents;
|
||||
|
|
@ -284,9 +284,6 @@ get_user_font_face (cairo_font_face_t *substitute_font,
|
|||
|
||||
cairo_glyph_free (glyphs);
|
||||
|
||||
cairo_font_options_destroy (options);
|
||||
cairo_scaled_font_destroy (measure);
|
||||
|
||||
status = create_rescaled_font (substitute_font,
|
||||
min_index, count, widths,
|
||||
out);
|
||||
|
|
|
|||
|
|
@ -1709,6 +1709,12 @@ _ft_create_for_source (csi_t *ctx,
|
|||
if (--source->base.ref == 0)
|
||||
csi_string_free (ctx, source);
|
||||
|
||||
if (source->deflate) {
|
||||
_csi_free (ctx, bytes);
|
||||
bytes = data->blob.bytes + vec[0].num_bytes;
|
||||
} else
|
||||
bytes = data->blob.bytes;
|
||||
|
||||
data->source = NULL;
|
||||
data->bytes = NULL;
|
||||
} else {
|
||||
|
|
@ -5714,6 +5720,7 @@ _integer_constants[] = {
|
|||
{ "XOR", CAIRO_OPERATOR_XOR },
|
||||
{ "ADD", CAIRO_OPERATOR_ADD },
|
||||
{ "SATURATE", CAIRO_OPERATOR_SATURATE },
|
||||
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 9, 4)
|
||||
{ "MULTIPLY", CAIRO_OPERATOR_MULTIPLY },
|
||||
{ "SCREEN", CAIRO_OPERATOR_SCREEN },
|
||||
{ "OVERLAY", CAIRO_OPERATOR_OVERLAY },
|
||||
|
|
@ -5729,6 +5736,7 @@ _integer_constants[] = {
|
|||
{ "HSL_SATURATION", CAIRO_OPERATOR_HSL_SATURATION },
|
||||
{ "HSL_COLOR", CAIRO_OPERATOR_HSL_COLOR },
|
||||
{ "HSL_LUMINOSITY", CAIRO_OPERATOR_HSL_LUMINOSITY },
|
||||
#endif
|
||||
|
||||
{ "WINDING", CAIRO_FILL_RULE_WINDING },
|
||||
{ "EVEN_ODD", CAIRO_FILL_RULE_EVEN_ODD },
|
||||
|
|
|
|||
|
|
@ -665,17 +665,17 @@ base85_end (csi_t *ctx, csi_scanner_t *scan, cairo_bool_t deflate)
|
|||
longjmp (scan->jmpbuf, status);
|
||||
}
|
||||
|
||||
static void
|
||||
static inline void
|
||||
scan_read (csi_scanner_t *scan, csi_file_t *src, void *ptr, int len)
|
||||
{
|
||||
uint8_t *data = ptr;
|
||||
while (len) {
|
||||
do {
|
||||
int ret = csi_file_read (src, data, len);
|
||||
if (_csi_unlikely (ret == 0))
|
||||
longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_READ_ERROR));
|
||||
data += ret;
|
||||
len -= ret;
|
||||
}
|
||||
} while (_csi_unlikely (len));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||