Merge branch 'master' of git.cairographics.org:/git/cairo

This commit is contained in:
Carl Worth 2009-07-27 15:26:19 -07:00
commit 01acad1659
39 changed files with 948 additions and 108 deletions

View file

@ -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)) > $@'

View file

@ -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

View file

@ -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 {

View file

@ -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 {

View file

@ -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)

View file

@ -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)

View file

@ -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 = \

View file

@ -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

View file

@ -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 \

View file

@ -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 */

View file

@ -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);

View file

@ -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;

View file

@ -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
View 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
View 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);
}

View file

@ -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,

View file

@ -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;
}

View file

@ -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;

View file

@ -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) {

View file

@ -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"

View file

@ -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;
};

View file

@ -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 \

View file

@ -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 \

View file

@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

123
test/overlapping-glyphs.c Normal file
View 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)

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -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]);
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 271 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

View file

@ -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);

View file

@ -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 },

View file

@ -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