зеркало из https://github.com/mozilla/gecko-dev.git
Bug 562746. Update cairo to 1.10.
A lot of changes from upstream here that will hopefully be smoothed out a bit soon.
This commit is contained in:
Родитель
f9d994bb5d
Коммит
8eb40c43cb
|
@ -8388,6 +8388,7 @@ if test "$MOZ_TREE_CAIRO"; then
|
|||
AC_DEFINE(HAVE_UINT64_T)
|
||||
|
||||
# Define macros for cairo-features.h
|
||||
TEE_SURFACE_FEATURE="#define CAIRO_HAS_TEE_SURFACE 1"
|
||||
if test "$MOZ_X11"; then
|
||||
XLIB_SURFACE_FEATURE="#define CAIRO_HAS_XLIB_SURFACE 1"
|
||||
XLIB_XRENDER_SURFACE_FEATURE="#define CAIRO_HAS_XLIB_XRENDER_SURFACE 1"
|
||||
|
@ -8470,6 +8471,7 @@ if test "$MOZ_TREE_CAIRO"; then
|
|||
AC_SUBST(QUARTZ_FONT_FEATURE)
|
||||
AC_SUBST(PNG_FUNCTIONS_FEATURE)
|
||||
AC_SUBST(QT_SURFACE_FEATURE)
|
||||
AC_SUBST(TEE_SURFACE_FEATURE)
|
||||
|
||||
MOZ_CAIRO_LIBS='$(call EXPAND_LIBNAME_PATH,mozcairo,$(DEPTH)/gfx/cairo/cairo/src)'" $CAIRO_FT_LIBS"
|
||||
|
||||
|
|
|
@ -70,20 +70,25 @@ CSRCS = \
|
|||
cairo-arc.c \
|
||||
cairo-array.c \
|
||||
cairo-atomic.c \
|
||||
cairo-base64-stream.c \
|
||||
cairo-bentley-ottmann.c \
|
||||
cairo-bentley-ottmann-rectilinear.c \
|
||||
cairo-bentley-ottmann-rectangular.c \
|
||||
cairo-base64-stream.c \
|
||||
cairo-botor-scan-converter.c \
|
||||
cairo-boxes.c \
|
||||
cairo-cache.c \
|
||||
cairo-clip.c \
|
||||
cairo-color.c \
|
||||
cairo-composite-rectangles.c \
|
||||
cairo-debug.c \
|
||||
cairo-deflate-stream.c \
|
||||
cairo-device.c \
|
||||
cairo-fixed.c \
|
||||
cairo-font-face.c \
|
||||
cairo-font-face-twin.c \
|
||||
cairo-font-face-twin-data.c \
|
||||
cairo-font-options.c \
|
||||
cairo-freed-pool.c \
|
||||
cairo-freelist.c \
|
||||
cairo-gstate.c \
|
||||
cairo-hash.c \
|
||||
|
@ -94,6 +99,7 @@ CSRCS = \
|
|||
cairo-matrix.c \
|
||||
cairo-misc.c \
|
||||
cairo-mutex.c \
|
||||
cairo-observer.c \
|
||||
cairo-output-stream.c \
|
||||
cairo-paginated-surface.c \
|
||||
cairo-path.c \
|
||||
|
@ -107,6 +113,7 @@ CSRCS = \
|
|||
cairo-polygon.c \
|
||||
cairo-recording-surface.c \
|
||||
cairo-rectangle.c \
|
||||
cairo-rectangular-scan-converter.c \
|
||||
cairo-region.c \
|
||||
cairo-scaled-font.c \
|
||||
cairo-scaled-font-subsets.c \
|
||||
|
@ -117,6 +124,9 @@ CSRCS = \
|
|||
cairo-surface.c \
|
||||
cairo-surface-clipper.c \
|
||||
cairo-surface-fallback.c \
|
||||
cairo-surface-offset.c \
|
||||
cairo-surface-snapshot.c \
|
||||
cairo-surface-subsurface.c \
|
||||
cairo-surface-wrapper.c \
|
||||
cairo-tee-surface.c \
|
||||
cairo-tor-scan-converter.c \
|
||||
|
@ -130,7 +140,7 @@ CSRCS = \
|
|||
|
||||
EXPORTS_NAMESPACES = cairo
|
||||
|
||||
EXPORTS_cairo = cairo.h cairo-version.h cairo-features.h cairo-platform.h cairo-deprecated.h cairo-rename.h
|
||||
EXPORTS_cairo = cairo.h cairo-version.h cairo-features.h cairo-platform.h cairo-deprecated.h cairo-rename.h cairo-tee.h
|
||||
|
||||
# cairo-type1-subset.c should be here, but it's only supported on freetype platforms
|
||||
|
||||
|
@ -153,6 +163,7 @@ PDF_EXPORTS = cairo-pdf.h
|
|||
PS_EXPORTS = cairo-ps.h
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
|
||||
DEFINES += -DDISABLE_SOME_FLOATING_POINT
|
||||
CSRCS += cairo-win32-surface.c
|
||||
|
||||
ifndef WINCE
|
||||
|
@ -269,3 +280,4 @@ endif
|
|||
|
||||
cairo-features.h: $(srcdir)/cairo-features.h.in $(GLOBAL_DEPS)
|
||||
$(PERL) $(AUTOCONF_TOOLS)/make-makefile -t $(topsrcdir) -d $(DEPTH) ./$@
|
||||
cat cairo-dwrite-font.i | gzip | python -c "import base64,sys; base64.encode(sys.stdin,sys.stdout)"
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -37,6 +37,8 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_analysis_surface_create (cairo_surface_t *target);
|
||||
|
||||
|
@ -71,4 +73,6 @@ _cairo_analysis_surface_merge_status (cairo_int_status_t status_a,
|
|||
cairo_private cairo_surface_t *
|
||||
_cairo_null_surface_create (cairo_content_t content);
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#endif /* CAIRO_ANALYSIS_SURFACE_H */
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -37,8 +37,10 @@
|
|||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-analysis-surface-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-paginated-private.h"
|
||||
#include "cairo-recording-surface-private.h"
|
||||
#include "cairo-surface-subsurface-private.h"
|
||||
#include "cairo-region-private.h"
|
||||
|
||||
typedef struct {
|
||||
|
@ -99,10 +101,11 @@ _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface,
|
|||
cairo_bool_t old_has_ctm;
|
||||
cairo_matrix_t old_ctm, p2d;
|
||||
cairo_status_t status;
|
||||
cairo_surface_t *source;
|
||||
|
||||
assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
|
||||
surface_pattern = (const cairo_surface_pattern_t *) pattern;
|
||||
assert (_cairo_surface_is_recording (surface_pattern->surface));
|
||||
assert (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING);
|
||||
|
||||
old_ctm = surface->ctm;
|
||||
old_has_ctm = surface->has_ctm;
|
||||
|
@ -114,8 +117,13 @@ _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface,
|
|||
cairo_matrix_multiply (&surface->ctm, &p2d, &surface->ctm);
|
||||
surface->has_ctm = ! _cairo_matrix_is_identity (&surface->ctm);
|
||||
|
||||
status = _cairo_recording_surface_replay_and_create_regions (surface_pattern->surface,
|
||||
&surface->base);
|
||||
source = surface_pattern->surface;
|
||||
if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
|
||||
cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
|
||||
source = sub->target;
|
||||
}
|
||||
|
||||
status = _cairo_recording_surface_replay_and_create_regions (source, &surface->base);
|
||||
|
||||
surface->ctm = old_ctm;
|
||||
surface->has_ctm = old_has_ctm;
|
||||
|
@ -396,9 +404,9 @@ _cairo_analysis_surface_stroke (void *abstract_surface,
|
|||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *style,
|
||||
cairo_matrix_t *ctm,
|
||||
cairo_matrix_t *ctm_inverse,
|
||||
const cairo_stroke_style_t *style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_clip_t *clip)
|
||||
|
@ -716,7 +724,9 @@ _cairo_analysis_surface_create (cairo_surface_t *target)
|
|||
|
||||
/* I believe the content type here is truly arbitrary. I'm quite
|
||||
* sure nothing will ever use this value. */
|
||||
_cairo_surface_init (&surface->base, &cairo_analysis_surface_backend,
|
||||
_cairo_surface_init (&surface->base,
|
||||
&cairo_analysis_surface_backend,
|
||||
NULL, /* device */
|
||||
CAIRO_CONTENT_COLOR_ALPHA);
|
||||
|
||||
cairo_matrix_init_identity (&surface->ctm);
|
||||
|
@ -831,9 +841,9 @@ typedef cairo_int_status_t
|
|||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *style,
|
||||
cairo_matrix_t *ctm,
|
||||
cairo_matrix_t *ctm_inverse,
|
||||
const cairo_stroke_style_t *style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_clip_t *clip);
|
||||
|
@ -906,7 +916,10 @@ _cairo_null_surface_create (cairo_content_t content)
|
|||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
}
|
||||
|
||||
_cairo_surface_init (surface, &cairo_null_surface_backend, content);
|
||||
_cairo_surface_init (surface,
|
||||
&cairo_null_surface_backend,
|
||||
NULL, /* device */
|
||||
content);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -36,6 +36,7 @@
|
|||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
/**
|
||||
* _cairo_array_init:
|
||||
|
@ -260,7 +261,7 @@ _cairo_array_append (cairo_array_t *array,
|
|||
}
|
||||
|
||||
/**
|
||||
* _cairo_array_append:
|
||||
* _cairo_array_append_multiple:
|
||||
* @array: a #cairo_array_t
|
||||
*
|
||||
* Append one or more items onto the array by growing the array by
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2007 Chris Wilson
|
||||
* Copyright © 2010 Andrea Canciani
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
|
@ -12,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -32,6 +33,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
* Andrea Canciani <ranma42@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_ATOMIC_PRIVATE_H
|
||||
|
@ -57,12 +59,29 @@ CAIRO_BEGIN_DECLS
|
|||
|
||||
typedef int cairo_atomic_int_t;
|
||||
|
||||
#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
|
||||
static cairo_always_inline cairo_atomic_int_t
|
||||
_cairo_atomic_int_get (cairo_atomic_int_t *x)
|
||||
{
|
||||
__sync_synchronize ();
|
||||
return *x;
|
||||
}
|
||||
|
||||
static cairo_always_inline void *
|
||||
_cairo_atomic_ptr_get (void **x)
|
||||
{
|
||||
__sync_synchronize ();
|
||||
return *x;
|
||||
}
|
||||
#else
|
||||
# define _cairo_atomic_int_get(x) (*x)
|
||||
# define _cairo_atomic_int_set(x, value) ((*x) = value)
|
||||
# define _cairo_atomic_ptr_get(x) (*x)
|
||||
#endif
|
||||
|
||||
# define _cairo_atomic_int_inc(x) ((void) __sync_fetch_and_add(x, 1))
|
||||
# define _cairo_atomic_int_dec_and_test(x) (__sync_fetch_and_add(x, -1) == 1)
|
||||
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) __sync_val_compare_and_swap (x, oldv, newv)
|
||||
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) __sync_bool_compare_and_swap (x, oldv, newv)
|
||||
# define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) __sync_val_compare_and_swap (x, oldv, newv)
|
||||
|
||||
#if SIZEOF_VOID_P==SIZEOF_INT
|
||||
typedef int cairo_atomic_intptr_t;
|
||||
|
@ -75,7 +94,10 @@ typedef long long cairo_atomic_intptr_t;
|
|||
#endif
|
||||
|
||||
# define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
|
||||
(void*)__sync_val_compare_and_swap ((cairo_atomic_intptr_t*)x, (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
|
||||
__sync_bool_compare_and_swap ((cairo_atomic_intptr_t*)x, (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
|
||||
|
||||
# define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) \
|
||||
_cairo_atomic_intptr_to_voidptr (__sync_val_compare_and_swap ((cairo_atomic_intptr_t*)x, (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv))
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -87,11 +109,10 @@ typedef long long cairo_atomic_intptr_t;
|
|||
typedef AO_t cairo_atomic_int_t;
|
||||
|
||||
# define _cairo_atomic_int_get(x) (AO_load_full (x))
|
||||
# define _cairo_atomic_int_set(x, value) (AO_store_full (x))
|
||||
|
||||
# define _cairo_atomic_int_inc(x) ((void) AO_fetch_and_add1_full(x))
|
||||
# define _cairo_atomic_int_dec_and_test(x) (AO_fetch_and_sub1_full(x) == 1)
|
||||
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) ((cairo_atomic_int_t) AO_compare_and_swap_full(x, oldv, newv) ? oldv : *x)
|
||||
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) AO_compare_and_swap_full(x, oldv, newv)
|
||||
|
||||
#if SIZEOF_VOID_P==SIZEOF_INT
|
||||
typedef unsigned int cairo_atomic_intptr_t;
|
||||
|
@ -103,45 +124,129 @@ typedef unsigned long long cairo_atomic_intptr_t;
|
|||
#error No matching integer pointer type
|
||||
#endif
|
||||
|
||||
# define _cairo_atomic_ptr_get(x) _cairo_atomic_intptr_to_voidptr (AO_load_full (x))
|
||||
# define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
|
||||
(void*) (cairo_atomic_intptr_t) _cairo_atomic_int_cmpxchg ((cairo_atomic_intptr_t*)(x), (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
|
||||
_cairo_atomic_int_cmpxchg ((cairo_atomic_intptr_t*)(x), (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
|
||||
|
||||
#endif
|
||||
|
||||
#if HAVE_OS_ATOMIC_OPS
|
||||
#include <libkern/OSAtomic.h>
|
||||
|
||||
#define HAS_ATOMIC_OPS 1
|
||||
|
||||
typedef int32_t cairo_atomic_int_t;
|
||||
|
||||
# define _cairo_atomic_int_get(x) (OSMemoryBarrier(), *(x))
|
||||
|
||||
# define _cairo_atomic_int_inc(x) ((void) OSAtomicIncrement32Barrier (x))
|
||||
# define _cairo_atomic_int_dec_and_test(x) (OSAtomicDecrement32Barrier (x) == 0)
|
||||
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) OSAtomicCompareAndSwap32Barrier(oldv, newv, x)
|
||||
|
||||
#if SIZEOF_VOID_P==4
|
||||
typedef int32_t cairo_atomic_intptr_t;
|
||||
# define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
|
||||
OSAtomicCompareAndSwap32Barrier((cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv, (cairo_atomic_intptr_t *)x)
|
||||
|
||||
#elif SIZEOF_VOID_P==8
|
||||
typedef int64_t cairo_atomic_intptr_t;
|
||||
# define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
|
||||
OSAtomicCompareAndSwap64Barrier((cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv, (cairo_atomic_intptr_t *)x)
|
||||
|
||||
#else
|
||||
#error No matching integer pointer type
|
||||
#endif
|
||||
|
||||
# define _cairo_atomic_ptr_get(x) (OSMemoryBarrier(), *(x))
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAS_ATOMIC_OPS
|
||||
|
||||
typedef int cairo_atomic_int_t;
|
||||
#if SIZEOF_VOID_P==SIZEOF_INT
|
||||
typedef unsigned int cairo_atomic_intptr_t;
|
||||
#elif SIZEOF_VOID_P==SIZEOF_LONG
|
||||
typedef unsigned long cairo_atomic_intptr_t;
|
||||
#elif SIZEOF_VOID_P==SIZEOF_LONG_LONG
|
||||
typedef unsigned long long cairo_atomic_intptr_t;
|
||||
#else
|
||||
#error No matching integer pointer type
|
||||
#endif
|
||||
|
||||
typedef cairo_atomic_intptr_t cairo_atomic_int_t;
|
||||
|
||||
cairo_private void
|
||||
_cairo_atomic_int_inc (int *x);
|
||||
_cairo_atomic_int_inc (cairo_atomic_int_t *x);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_atomic_int_dec_and_test (int *x);
|
||||
_cairo_atomic_int_dec_and_test (cairo_atomic_int_t *x);
|
||||
|
||||
cairo_private int
|
||||
_cairo_atomic_int_cmpxchg (int *x, int oldv, int newv);
|
||||
cairo_private cairo_atomic_int_t
|
||||
_cairo_atomic_int_cmpxchg_return_old_impl (cairo_atomic_int_t *x, cairo_atomic_int_t oldv, cairo_atomic_int_t newv);
|
||||
|
||||
cairo_private void *
|
||||
_cairo_atomic_ptr_cmpxchg (void **x, void *oldv, void *newv);
|
||||
_cairo_atomic_ptr_cmpxchg_return_old_impl (void **x, void *oldv, void *newv);
|
||||
|
||||
#define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_int_cmpxchg_return_old_impl (x, oldv, newv)
|
||||
#define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_ptr_cmpxchg_return_old_impl (x, oldv, newv)
|
||||
|
||||
#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
|
||||
|
||||
# include "cairo-compiler-private.h"
|
||||
|
||||
cairo_private int
|
||||
_cairo_atomic_int_get (int *x);
|
||||
|
||||
cairo_private void
|
||||
_cairo_atomic_int_set (int *x, int value);
|
||||
cairo_private cairo_atomic_int_t
|
||||
_cairo_atomic_int_get (cairo_atomic_int_t *x);
|
||||
# define _cairo_atomic_ptr_get(x) (void *) _cairo_atomic_int_get((cairo_atomic_int_t *) x)
|
||||
#else
|
||||
# define _cairo_atomic_int_get(x) (*x)
|
||||
# define _cairo_atomic_ptr_get(x) (*x)
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
# define _cairo_atomic_int_get(x) (*x)
|
||||
# define _cairo_atomic_int_set(x, value) ((*x) = value)
|
||||
/* Workaround GCC complaining about casts */
|
||||
static cairo_always_inline void *
|
||||
_cairo_atomic_intptr_to_voidptr (cairo_atomic_intptr_t x)
|
||||
{
|
||||
return (void *) x;
|
||||
}
|
||||
|
||||
static cairo_always_inline cairo_atomic_int_t
|
||||
_cairo_atomic_int_cmpxchg_return_old_fallback(cairo_atomic_int_t *x, cairo_atomic_int_t oldv, cairo_atomic_int_t newv)
|
||||
{
|
||||
cairo_atomic_int_t curr;
|
||||
|
||||
do {
|
||||
curr = _cairo_atomic_int_get (x);
|
||||
} while (curr == oldv && !_cairo_atomic_int_cmpxchg (x, oldv, newv));
|
||||
|
||||
return curr;
|
||||
}
|
||||
|
||||
static cairo_always_inline void *
|
||||
_cairo_atomic_ptr_cmpxchg_return_old_fallback(void **x, void *oldv, void *newv)
|
||||
{
|
||||
void *curr;
|
||||
|
||||
do {
|
||||
curr = _cairo_atomic_ptr_get (x);
|
||||
} while (curr == oldv && !_cairo_atomic_ptr_cmpxchg (x, oldv, newv));
|
||||
|
||||
return curr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _cairo_atomic_int_cmpxchg_return_old
|
||||
#define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_int_cmpxchg_return_old_fallback (x, oldv, newv)
|
||||
#endif
|
||||
|
||||
#ifndef _cairo_atomic_ptr_cmpxchg_return_old
|
||||
#define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_ptr_cmpxchg_return_old_fallback (x, oldv, newv)
|
||||
#endif
|
||||
|
||||
#ifndef _cairo_atomic_int_cmpxchg
|
||||
#define _cairo_atomic_int_cmpxchg(x, oldv, newv) (_cairo_atomic_int_cmpxchg_return_old (x, oldv, newv) == oldv)
|
||||
#endif
|
||||
|
||||
#ifndef _cairo_atomic_ptr_cmpxchg
|
||||
#define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) (_cairo_atomic_ptr_cmpxchg_return_old (x, oldv, newv) == oldv)
|
||||
#endif
|
||||
|
||||
#define _cairo_atomic_uint_get(x) _cairo_atomic_int_get(x)
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -42,7 +42,7 @@ COMPILE_TIME_ASSERT(sizeof(void*) == sizeof(int) ||
|
|||
sizeof(void*) == sizeof(long long));
|
||||
#else
|
||||
void
|
||||
_cairo_atomic_int_inc (int *x)
|
||||
_cairo_atomic_int_inc (cairo_atomic_intptr_t *x)
|
||||
{
|
||||
CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
|
||||
*x += 1;
|
||||
|
@ -50,7 +50,7 @@ _cairo_atomic_int_inc (int *x)
|
|||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_atomic_int_dec_and_test (int *x)
|
||||
_cairo_atomic_int_dec_and_test (cairo_atomic_intptr_t *x)
|
||||
{
|
||||
cairo_bool_t ret;
|
||||
|
||||
|
@ -61,10 +61,10 @@ _cairo_atomic_int_dec_and_test (int *x)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
_cairo_atomic_int_cmpxchg (int *x, int oldv, int newv)
|
||||
cairo_atomic_intptr_t
|
||||
_cairo_atomic_int_cmpxchg_return_old_impl (cairo_atomic_intptr_t *x, cairo_atomic_intptr_t oldv, cairo_atomic_intptr_t newv)
|
||||
{
|
||||
int ret;
|
||||
cairo_atomic_intptr_t ret;
|
||||
|
||||
CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
|
||||
ret = *x;
|
||||
|
@ -76,7 +76,7 @@ _cairo_atomic_int_cmpxchg (int *x, int oldv, int newv)
|
|||
}
|
||||
|
||||
void *
|
||||
_cairo_atomic_ptr_cmpxchg (void **x, void *oldv, void *newv)
|
||||
_cairo_atomic_ptr_cmpxchg_return_old_impl (void **x, void *oldv, void *newv)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
|
@ -88,13 +88,12 @@ _cairo_atomic_ptr_cmpxchg (void **x, void *oldv, void *newv)
|
|||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
|
||||
int
|
||||
_cairo_atomic_int_get (int *x)
|
||||
cairo_atomic_intptr_t
|
||||
_cairo_atomic_int_get (cairo_atomic_intptr_t *x)
|
||||
{
|
||||
int ret;
|
||||
cairo_atomic_intptr_t ret;
|
||||
|
||||
CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
|
||||
ret = *x;
|
||||
|
@ -102,12 +101,6 @@ _cairo_atomic_int_get (int *x)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_atomic_int_set (int *x, int value)
|
||||
{
|
||||
CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
|
||||
*x = value;
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -37,6 +37,7 @@
|
|||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-output-stream-private.h"
|
||||
|
||||
typedef struct _cairo_base64_stream {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -35,6 +35,7 @@
|
|||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-output-stream-private.h"
|
||||
|
||||
typedef struct _cairo_base85_stream {
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -38,7 +38,9 @@
|
|||
/* Provide definitions for standalone compilation */
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-boxes-private.h"
|
||||
#include "cairo-combsort-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
typedef struct _cairo_bo_edge cairo_bo_edge_t;
|
||||
typedef struct _cairo_bo_trap cairo_bo_trap_t;
|
||||
|
@ -215,20 +217,33 @@ edges_collinear (const cairo_bo_edge_t *a, const cairo_bo_edge_t *b)
|
|||
static cairo_status_t
|
||||
_cairo_bo_edge_end_trap (cairo_bo_edge_t *left,
|
||||
int32_t bot,
|
||||
cairo_traps_t *traps)
|
||||
cairo_bool_t do_traps,
|
||||
void *container)
|
||||
{
|
||||
cairo_bo_trap_t *trap = &left->deferred_trap;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
/* Only emit (trivial) non-degenerate trapezoids with positive height. */
|
||||
if (likely (trap->top < bot)) {
|
||||
_cairo_traps_add_trap (traps,
|
||||
trap->top, bot,
|
||||
&left->edge.line, &trap->right->edge.line);
|
||||
if (do_traps) {
|
||||
_cairo_traps_add_trap (container,
|
||||
trap->top, bot,
|
||||
&left->edge.line, &trap->right->edge.line);
|
||||
status = _cairo_traps_status ((cairo_traps_t *) container);
|
||||
} else {
|
||||
cairo_box_t box;
|
||||
|
||||
box.p1.x = left->edge.line.p1.x;
|
||||
box.p1.y = trap->top;
|
||||
box.p2.x = trap->right->edge.line.p1.x;
|
||||
box.p2.y = bot;
|
||||
status = _cairo_boxes_add (container, &box);
|
||||
}
|
||||
}
|
||||
|
||||
trap->right = NULL;
|
||||
|
||||
return _cairo_traps_status (traps);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Start a new trapezoid at the given top y coordinate, whose edges
|
||||
|
@ -240,7 +255,8 @@ static inline cairo_status_t
|
|||
_cairo_bo_edge_start_or_continue_trap (cairo_bo_edge_t *left,
|
||||
cairo_bo_edge_t *right,
|
||||
int top,
|
||||
cairo_traps_t *traps)
|
||||
cairo_bool_t do_traps,
|
||||
void *container)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
|
@ -255,7 +271,7 @@ _cairo_bo_edge_start_or_continue_trap (cairo_bo_edge_t *left,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
status = _cairo_bo_edge_end_trap (left, top, traps);
|
||||
status = _cairo_bo_edge_end_trap (left, top, do_traps, container);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
|
@ -272,7 +288,8 @@ static inline cairo_status_t
|
|||
_active_edges_to_traps (cairo_bo_edge_t *left,
|
||||
int32_t top,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
cairo_traps_t *traps)
|
||||
cairo_bool_t do_traps,
|
||||
void *container)
|
||||
{
|
||||
cairo_bo_edge_t *right;
|
||||
cairo_status_t status;
|
||||
|
@ -303,7 +320,7 @@ _active_edges_to_traps (cairo_bo_edge_t *left,
|
|||
right = left->next;
|
||||
while (right != NULL) {
|
||||
if (right->deferred_trap.right != NULL) {
|
||||
status = _cairo_bo_edge_end_trap (right, top, traps);
|
||||
status = _cairo_bo_edge_end_trap (right, top, do_traps, container);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
|
@ -321,8 +338,8 @@ _active_edges_to_traps (cairo_bo_edge_t *left,
|
|||
right = right->next;
|
||||
}
|
||||
|
||||
status = _cairo_bo_edge_start_or_continue_trap (left, right,
|
||||
top, traps);
|
||||
status = _cairo_bo_edge_start_or_continue_trap (left, right, top,
|
||||
do_traps, container);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
|
@ -337,7 +354,7 @@ _active_edges_to_traps (cairo_bo_edge_t *left,
|
|||
right = left->next;
|
||||
while (right != NULL) {
|
||||
if (right->deferred_trap.right != NULL) {
|
||||
status = _cairo_bo_edge_end_trap (right, top, traps);
|
||||
status = _cairo_bo_edge_end_trap (right, top, do_traps, container);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
|
@ -358,8 +375,8 @@ _active_edges_to_traps (cairo_bo_edge_t *left,
|
|||
right = right->next;
|
||||
}
|
||||
|
||||
status = _cairo_bo_edge_start_or_continue_trap (left, right,
|
||||
top, traps);
|
||||
status = _cairo_bo_edge_start_or_continue_trap (left, right, top,
|
||||
do_traps, container);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
|
@ -376,7 +393,8 @@ static cairo_status_t
|
|||
_cairo_bentley_ottmann_tessellate_rectilinear (cairo_bo_event_t **start_events,
|
||||
int num_events,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
cairo_traps_t *traps)
|
||||
cairo_bool_t do_traps,
|
||||
void *container)
|
||||
{
|
||||
cairo_bo_sweep_line_t sweep_line;
|
||||
cairo_bo_event_t *event;
|
||||
|
@ -388,7 +406,7 @@ _cairo_bentley_ottmann_tessellate_rectilinear (cairo_bo_event_t **start_events
|
|||
if (event->point.y != sweep_line.current_y) {
|
||||
status = _active_edges_to_traps (sweep_line.head,
|
||||
sweep_line.current_y,
|
||||
fill_rule, traps);
|
||||
fill_rule, do_traps, container);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
|
@ -406,7 +424,7 @@ _cairo_bentley_ottmann_tessellate_rectilinear (cairo_bo_event_t **start_events
|
|||
if (event->edge->deferred_trap.right != NULL) {
|
||||
status = _cairo_bo_edge_end_trap (event->edge,
|
||||
sweep_line.current_y,
|
||||
traps);
|
||||
do_traps, container);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
|
@ -476,7 +494,8 @@ _cairo_bentley_ottmann_tessellate_rectilinear_polygon (cairo_traps_t *traps,
|
|||
}
|
||||
|
||||
status = _cairo_bentley_ottmann_tessellate_rectilinear (event_ptrs, j,
|
||||
fill_rule, traps);
|
||||
fill_rule,
|
||||
TRUE, traps);
|
||||
if (events != stack_events)
|
||||
free (events);
|
||||
|
||||
|
@ -485,6 +504,72 @@ _cairo_bentley_ottmann_tessellate_rectilinear_polygon (cairo_traps_t *traps,
|
|||
return status;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_bentley_ottmann_tessellate_rectilinear_polygon_to_boxes (const cairo_polygon_t *polygon,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
cairo_boxes_t *boxes)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_bo_event_t stack_events[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_event_t)];
|
||||
cairo_bo_event_t *events;
|
||||
cairo_bo_event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1];
|
||||
cairo_bo_event_t **event_ptrs;
|
||||
cairo_bo_edge_t stack_edges[ARRAY_LENGTH (stack_events)];
|
||||
cairo_bo_edge_t *edges;
|
||||
int num_events;
|
||||
int i, j;
|
||||
|
||||
if (unlikely (polygon->num_edges == 0))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
num_events = 2 * polygon->num_edges;
|
||||
|
||||
events = stack_events;
|
||||
event_ptrs = stack_event_ptrs;
|
||||
edges = stack_edges;
|
||||
if (num_events > ARRAY_LENGTH (stack_events)) {
|
||||
events = _cairo_malloc_ab_plus_c (num_events,
|
||||
sizeof (cairo_bo_event_t) +
|
||||
sizeof (cairo_bo_edge_t) +
|
||||
sizeof (cairo_bo_event_t *),
|
||||
sizeof (cairo_bo_event_t *));
|
||||
if (unlikely (events == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
event_ptrs = (cairo_bo_event_t **) (events + num_events);
|
||||
edges = (cairo_bo_edge_t *) (event_ptrs + num_events + 1);
|
||||
}
|
||||
|
||||
for (i = j = 0; i < polygon->num_edges; i++) {
|
||||
edges[i].edge = polygon->edges[i];
|
||||
edges[i].deferred_trap.right = NULL;
|
||||
edges[i].prev = NULL;
|
||||
edges[i].next = NULL;
|
||||
|
||||
event_ptrs[j] = &events[j];
|
||||
events[j].type = CAIRO_BO_EVENT_TYPE_START;
|
||||
events[j].point.y = polygon->edges[i].top;
|
||||
events[j].point.x = polygon->edges[i].line.p1.x;
|
||||
events[j].edge = &edges[i];
|
||||
j++;
|
||||
|
||||
event_ptrs[j] = &events[j];
|
||||
events[j].type = CAIRO_BO_EVENT_TYPE_STOP;
|
||||
events[j].point.y = polygon->edges[i].bottom;
|
||||
events[j].point.x = polygon->edges[i].line.p1.x;
|
||||
events[j].edge = &edges[i];
|
||||
j++;
|
||||
}
|
||||
|
||||
status = _cairo_bentley_ottmann_tessellate_rectilinear (event_ptrs, j,
|
||||
fill_rule,
|
||||
FALSE, boxes);
|
||||
if (events != stack_events)
|
||||
free (events);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_bentley_ottmann_tessellate_rectilinear_traps (cairo_traps_t *traps,
|
||||
cairo_fill_rule_t fill_rule)
|
||||
|
@ -572,7 +657,7 @@ _cairo_bentley_ottmann_tessellate_rectilinear_traps (cairo_traps_t *traps,
|
|||
_cairo_traps_clear (traps);
|
||||
status = _cairo_bentley_ottmann_tessellate_rectilinear (event_ptrs, j,
|
||||
fill_rule,
|
||||
traps);
|
||||
TRUE, traps);
|
||||
traps->is_rectilinear = TRUE;
|
||||
|
||||
if (events != stack_events)
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -38,6 +38,7 @@
|
|||
/* Provide definitions for standalone compilation */
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-freelist-private.h"
|
||||
#include "cairo-combsort-private.h"
|
||||
|
||||
|
@ -129,21 +130,25 @@ static void
|
|||
dump_traps (cairo_traps_t *traps, const char *filename)
|
||||
{
|
||||
FILE *file;
|
||||
cairo_box_t extents;
|
||||
int n;
|
||||
|
||||
if (getenv ("CAIRO_DEBUG_TRAPS") == NULL)
|
||||
return;
|
||||
|
||||
#if 0
|
||||
if (traps->has_limits) {
|
||||
printf ("%s: limits=(%d, %d, %d, %d)\n",
|
||||
filename,
|
||||
traps->limits.p1.x, traps->limits.p1.y,
|
||||
traps->limits.p2.x, traps->limits.p2.y);
|
||||
}
|
||||
#endif
|
||||
_cairo_traps_extents (traps, &extents);
|
||||
printf ("%s: extents=(%d, %d, %d, %d)\n",
|
||||
filename,
|
||||
traps->extents.p1.x, traps->extents.p1.y,
|
||||
traps->extents.p2.x, traps->extents.p2.y);
|
||||
extents.p1.x, extents.p1.y,
|
||||
extents.p2.x, extents.p2.y);
|
||||
|
||||
file = fopen (filename, "a");
|
||||
if (file != NULL) {
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,84 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2009 Intel Corporation
|
||||
*
|
||||
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_BOXES_H
|
||||
#define CAIRO_BOXES_H
|
||||
|
||||
#include "cairo-types-private.h"
|
||||
#include "cairo-compiler-private.h"
|
||||
|
||||
struct _cairo_boxes_t {
|
||||
cairo_status_t status;
|
||||
cairo_box_t limit;
|
||||
const cairo_box_t *limits;
|
||||
int num_limits;
|
||||
int num_boxes;
|
||||
unsigned int is_pixel_aligned : 1;
|
||||
|
||||
struct _cairo_boxes_chunk {
|
||||
struct _cairo_boxes_chunk *next;
|
||||
cairo_box_t *base;
|
||||
int count;
|
||||
int size;
|
||||
} chunks, *tail;
|
||||
cairo_box_t boxes_embedded[32];
|
||||
};
|
||||
|
||||
cairo_private void
|
||||
_cairo_boxes_init (cairo_boxes_t *boxes);
|
||||
|
||||
cairo_private void
|
||||
_cairo_boxes_init_for_array (cairo_boxes_t *boxes,
|
||||
cairo_box_t *array,
|
||||
int num_boxes);
|
||||
|
||||
cairo_private void
|
||||
_cairo_boxes_limit (cairo_boxes_t *boxes,
|
||||
const cairo_box_t *limits,
|
||||
int num_limits);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_boxes_add (cairo_boxes_t *boxes,
|
||||
const cairo_box_t *box);
|
||||
|
||||
cairo_private void
|
||||
_cairo_boxes_extents (const cairo_boxes_t *boxes,
|
||||
cairo_rectangle_int_t *extents);
|
||||
|
||||
cairo_private void
|
||||
_cairo_boxes_clear (cairo_boxes_t *boxes);
|
||||
|
||||
cairo_private void
|
||||
_cairo_boxes_fini (cairo_boxes_t *boxes);
|
||||
|
||||
#endif /* CAIRO_BOXES_H */
|
|
@ -0,0 +1,300 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2009 Intel Corporation
|
||||
*
|
||||
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-boxes-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
void
|
||||
_cairo_boxes_init (cairo_boxes_t *boxes)
|
||||
{
|
||||
boxes->status = CAIRO_STATUS_SUCCESS;
|
||||
boxes->num_limits = 0;
|
||||
boxes->num_boxes = 0;
|
||||
|
||||
boxes->tail = &boxes->chunks;
|
||||
boxes->chunks.next = NULL;
|
||||
boxes->chunks.base = boxes->boxes_embedded;
|
||||
boxes->chunks.size = ARRAY_LENGTH (boxes->boxes_embedded);
|
||||
boxes->chunks.count = 0;
|
||||
|
||||
boxes->is_pixel_aligned = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_boxes_init_for_array (cairo_boxes_t *boxes,
|
||||
cairo_box_t *array,
|
||||
int num_boxes)
|
||||
{
|
||||
int n;
|
||||
|
||||
boxes->status = CAIRO_STATUS_SUCCESS;
|
||||
boxes->num_limits = 0;
|
||||
boxes->num_boxes = num_boxes;
|
||||
|
||||
boxes->tail = &boxes->chunks;
|
||||
boxes->chunks.next = NULL;
|
||||
boxes->chunks.base = array;
|
||||
boxes->chunks.size = num_boxes;
|
||||
boxes->chunks.count = num_boxes;
|
||||
|
||||
for (n = 0; n < num_boxes; n++) {
|
||||
if (! _cairo_fixed_is_integer (array[n].p1.x) ||
|
||||
! _cairo_fixed_is_integer (array[n].p1.y) ||
|
||||
! _cairo_fixed_is_integer (array[n].p2.x) ||
|
||||
! _cairo_fixed_is_integer (array[n].p2.y))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
boxes->is_pixel_aligned = n == num_boxes;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_boxes_limit (cairo_boxes_t *boxes,
|
||||
const cairo_box_t *limits,
|
||||
int num_limits)
|
||||
{
|
||||
int n;
|
||||
|
||||
boxes->limits = limits;
|
||||
boxes->num_limits = num_limits;
|
||||
|
||||
if (boxes->num_limits) {
|
||||
boxes->limit = limits[0];
|
||||
for (n = 1; n < num_limits; n++) {
|
||||
if (limits[n].p1.x < boxes->limit.p1.x)
|
||||
boxes->limit.p1.x = limits[n].p1.x;
|
||||
|
||||
if (limits[n].p1.y < boxes->limit.p1.y)
|
||||
boxes->limit.p1.y = limits[n].p1.y;
|
||||
|
||||
if (limits[n].p2.x > boxes->limit.p2.x)
|
||||
boxes->limit.p2.x = limits[n].p2.x;
|
||||
|
||||
if (limits[n].p2.y > boxes->limit.p2.y)
|
||||
boxes->limit.p2.y = limits[n].p2.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_boxes_add_internal (cairo_boxes_t *boxes,
|
||||
const cairo_box_t *box)
|
||||
{
|
||||
struct _cairo_boxes_chunk *chunk;
|
||||
|
||||
if (unlikely (boxes->status))
|
||||
return;
|
||||
|
||||
chunk = boxes->tail;
|
||||
if (unlikely (chunk->count == chunk->size)) {
|
||||
int size;
|
||||
|
||||
size = chunk->size * 2;
|
||||
chunk->next = _cairo_malloc_ab_plus_c (size,
|
||||
sizeof (cairo_box_t),
|
||||
sizeof (struct _cairo_boxes_chunk));
|
||||
|
||||
if (unlikely (chunk->next == NULL)) {
|
||||
boxes->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
||||
chunk = chunk->next;
|
||||
boxes->tail = chunk;
|
||||
|
||||
chunk->next = NULL;
|
||||
chunk->count = 0;
|
||||
chunk->size = size;
|
||||
chunk->base = (cairo_box_t *) (chunk + 1);
|
||||
}
|
||||
|
||||
chunk->base[chunk->count++] = *box;
|
||||
boxes->num_boxes++;
|
||||
|
||||
if (boxes->is_pixel_aligned) {
|
||||
boxes->is_pixel_aligned =
|
||||
_cairo_fixed_is_integer (box->p1.x) &&
|
||||
_cairo_fixed_is_integer (box->p1.y) &&
|
||||
_cairo_fixed_is_integer (box->p2.x) &&
|
||||
_cairo_fixed_is_integer (box->p2.y);
|
||||
}
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_boxes_add (cairo_boxes_t *boxes,
|
||||
const cairo_box_t *box)
|
||||
{
|
||||
if (box->p1.y == box->p2.y)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (box->p1.x == box->p2.x)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (boxes->num_limits) {
|
||||
cairo_point_t p1, p2;
|
||||
cairo_bool_t reversed = FALSE;
|
||||
int n;
|
||||
|
||||
/* support counter-clockwise winding for rectangular tessellation */
|
||||
if (box->p1.x < box->p2.x) {
|
||||
p1.x = box->p1.x;
|
||||
p2.x = box->p2.x;
|
||||
} else {
|
||||
p2.x = box->p1.x;
|
||||
p1.x = box->p2.x;
|
||||
reversed = ! reversed;
|
||||
}
|
||||
|
||||
if (p1.x >= boxes->limit.p2.x || p2.x <= boxes->limit.p1.x)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (box->p1.y < box->p2.y) {
|
||||
p1.y = box->p1.y;
|
||||
p2.y = box->p2.y;
|
||||
} else {
|
||||
p2.y = box->p1.y;
|
||||
p1.y = box->p2.y;
|
||||
reversed = ! reversed;
|
||||
}
|
||||
|
||||
if (p1.y >= boxes->limit.p2.y || p2.y <= boxes->limit.p1.y)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
for (n = 0; n < boxes->num_limits; n++) {
|
||||
const cairo_box_t *limits = &boxes->limits[n];
|
||||
cairo_box_t _box;
|
||||
cairo_point_t _p1, _p2;
|
||||
|
||||
if (p1.x >= limits->p2.x || p2.x <= limits->p1.x)
|
||||
continue;
|
||||
if (p1.y >= limits->p2.y || p2.y <= limits->p1.y)
|
||||
continue;
|
||||
|
||||
/* Otherwise, clip the box to the limits. */
|
||||
_p1 = p1;
|
||||
if (_p1.x < limits->p1.x)
|
||||
_p1.x = limits->p1.x;
|
||||
if (_p1.y < limits->p1.y)
|
||||
_p1.y = limits->p1.y;
|
||||
|
||||
_p2 = p2;
|
||||
if (_p2.x > limits->p2.x)
|
||||
_p2.x = limits->p2.x;
|
||||
if (_p2.y > limits->p2.y)
|
||||
_p2.y = limits->p2.y;
|
||||
|
||||
if (_p2.y <= _p1.y || _p2.x <= _p1.x)
|
||||
continue;
|
||||
|
||||
_box.p1.y = _p1.y;
|
||||
_box.p2.y = _p2.y;
|
||||
if (reversed) {
|
||||
_box.p1.x = _p2.x;
|
||||
_box.p2.x = _p1.x;
|
||||
} else {
|
||||
_box.p1.x = _p1.x;
|
||||
_box.p2.x = _p2.x;
|
||||
}
|
||||
|
||||
_cairo_boxes_add_internal (boxes, &_box);
|
||||
}
|
||||
} else {
|
||||
_cairo_boxes_add_internal (boxes, box);
|
||||
}
|
||||
|
||||
return boxes->status;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_boxes_extents (const cairo_boxes_t *boxes,
|
||||
cairo_rectangle_int_t *extents)
|
||||
{
|
||||
const struct _cairo_boxes_chunk *chunk;
|
||||
cairo_box_t box;
|
||||
int i;
|
||||
|
||||
box.p1.y = box.p1.x = INT_MAX;
|
||||
box.p2.y = box.p2.x = INT_MIN;
|
||||
|
||||
for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
|
||||
const cairo_box_t *b = chunk->base;
|
||||
for (i = 0; i < chunk->count; i++) {
|
||||
if (b[i].p1.x < box.p1.x)
|
||||
box.p1.x = b[i].p1.x;
|
||||
|
||||
if (b[i].p1.y < box.p1.y)
|
||||
box.p1.y = b[i].p1.y;
|
||||
|
||||
if (b[i].p2.x > box.p2.x)
|
||||
box.p2.x = b[i].p2.x;
|
||||
|
||||
if (b[i].p2.y > box.p2.y)
|
||||
box.p2.y = b[i].p2.y;
|
||||
}
|
||||
}
|
||||
|
||||
_cairo_box_round_to_rectangle (&box, extents);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_boxes_clear (cairo_boxes_t *boxes)
|
||||
{
|
||||
struct _cairo_boxes_chunk *chunk, *next;
|
||||
|
||||
for (chunk = boxes->chunks.next; chunk != NULL; chunk = next) {
|
||||
next = chunk->next;
|
||||
free (chunk);
|
||||
}
|
||||
|
||||
boxes->tail = &boxes->chunks;
|
||||
boxes->chunks.next = 0;
|
||||
boxes->chunks.count = 0;
|
||||
boxes->num_boxes = 0;
|
||||
|
||||
boxes->is_pixel_aligned = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_boxes_fini (cairo_boxes_t *boxes)
|
||||
{
|
||||
struct _cairo_boxes_chunk *chunk, *next;
|
||||
|
||||
for (chunk = boxes->chunks.next; chunk != NULL; chunk = next) {
|
||||
next = chunk->next;
|
||||
free (chunk);
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -37,6 +37,7 @@
|
|||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
static void
|
||||
_cairo_cache_shrink_to_accommodate (cairo_cache_t *cache,
|
||||
|
@ -174,9 +175,7 @@ _cairo_cache_thaw (cairo_cache_t *cache)
|
|||
{
|
||||
assert (cache->freeze_count > 0);
|
||||
|
||||
cache->freeze_count--;
|
||||
|
||||
if (cache->freeze_count == 0)
|
||||
if (--cache->freeze_count == 0)
|
||||
_cairo_cache_shrink_to_accommodate (cache, 0);
|
||||
}
|
||||
|
||||
|
@ -240,9 +239,6 @@ static void
|
|||
_cairo_cache_shrink_to_accommodate (cairo_cache_t *cache,
|
||||
unsigned long additional)
|
||||
{
|
||||
if (cache->freeze_count)
|
||||
return;
|
||||
|
||||
while (cache->size + additional > cache->max_size) {
|
||||
if (! _cairo_cache_remove_random (cache))
|
||||
return;
|
||||
|
@ -267,7 +263,8 @@ _cairo_cache_insert (cairo_cache_t *cache,
|
|||
{
|
||||
cairo_status_t status;
|
||||
|
||||
_cairo_cache_shrink_to_accommodate (cache, entry->size);
|
||||
if (entry->size && ! cache->freeze_count)
|
||||
_cairo_cache_shrink_to_accommodate (cache, entry->size);
|
||||
|
||||
status = _cairo_hash_table_insert (cache->hash_table,
|
||||
(cairo_hash_entry_t *) entry);
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -41,6 +41,7 @@
|
|||
|
||||
#define _BSD_SOURCE /* for snprintf(), strdup() */
|
||||
#include "cairoint.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
#if CAIRO_HAS_FONT_SUBSET
|
||||
|
||||
|
@ -117,6 +118,7 @@ typedef struct _cairo_cff_font {
|
|||
cairo_array_t local_sub_index;
|
||||
int num_glyphs;
|
||||
cairo_bool_t is_cid;
|
||||
int units_per_em;
|
||||
|
||||
/* CID Font Data */
|
||||
int *fdselect;
|
||||
|
@ -1772,6 +1774,9 @@ _cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
|
|||
font->y_max = (int16_t) be16_to_cpu (head.y_max);
|
||||
font->ascent = (int16_t) be16_to_cpu (hhea.ascender);
|
||||
font->descent = (int16_t) be16_to_cpu (hhea.descender);
|
||||
font->units_per_em = (int16_t) be16_to_cpu (head.units_per_em);
|
||||
if (font->units_per_em == 0)
|
||||
font->units_per_em = 1000;
|
||||
|
||||
font->font_name = NULL;
|
||||
status = _cairo_truetype_read_font_name (scaled_font_subset->scaled_font,
|
||||
|
@ -1955,20 +1960,20 @@ _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
|
|||
cff_subset->font_name = NULL;
|
||||
}
|
||||
|
||||
cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
|
||||
cff_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs);
|
||||
if (unlikely (cff_subset->widths == NULL)) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto fail3;
|
||||
}
|
||||
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
|
||||
cff_subset->widths[i] = font->widths[i];
|
||||
cff_subset->widths[i] = (double)font->widths[i]/font->units_per_em;
|
||||
|
||||
cff_subset->x_min = font->x_min;
|
||||
cff_subset->y_min = font->y_min;
|
||||
cff_subset->x_max = font->x_max;
|
||||
cff_subset->y_max = font->y_max;
|
||||
cff_subset->ascent = font->ascent;
|
||||
cff_subset->descent = font->descent;
|
||||
cff_subset->x_min = (double)font->x_min/font->units_per_em;
|
||||
cff_subset->y_min = (double)font->y_min/font->units_per_em;
|
||||
cff_subset->x_max = (double)font->x_max/font->units_per_em;
|
||||
cff_subset->y_max = (double)font->y_max/font->units_per_em;
|
||||
cff_subset->ascent = (double)font->ascent/font->units_per_em;
|
||||
cff_subset->descent = (double)font->descent/font->units_per_em;
|
||||
|
||||
cff_subset->data = malloc (length);
|
||||
if (unlikely (cff_subset->data == NULL)) {
|
||||
|
@ -2212,21 +2217,21 @@ _cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
|
|||
goto fail2;
|
||||
}
|
||||
|
||||
cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
|
||||
cff_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs);
|
||||
if (unlikely (cff_subset->widths == NULL)) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
|
||||
cff_subset->widths[i] = type2_subset.widths[i];
|
||||
cff_subset->widths[i] = (double)type2_subset.widths[i]/1000;
|
||||
|
||||
cff_subset->x_min = type2_subset.x_min;
|
||||
cff_subset->y_min = type2_subset.y_min;
|
||||
cff_subset->x_max = type2_subset.x_max;
|
||||
cff_subset->y_max = type2_subset.y_max;
|
||||
cff_subset->ascent = type2_subset.y_max;
|
||||
cff_subset->descent = type2_subset.y_min;
|
||||
cff_subset->x_min = (double)type2_subset.x_min/1000;
|
||||
cff_subset->y_min = (double)type2_subset.y_min/1000;
|
||||
cff_subset->x_max = (double)type2_subset.x_max/1000;
|
||||
cff_subset->y_max = (double)type2_subset.y_max/1000;
|
||||
cff_subset->ascent = (double)type2_subset.y_max/1000;
|
||||
cff_subset->descent = (double)type2_subset.y_min/1000;
|
||||
|
||||
cff_subset->data = malloc (length);
|
||||
if (unlikely (cff_subset->data == NULL)) {
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -76,10 +76,6 @@ struct _cairo_clip {
|
|||
cairo_private void
|
||||
_cairo_clip_init (cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_clip_init_rectangle (cairo_clip_t *clip,
|
||||
const cairo_rectangle_int_t *rect);
|
||||
|
||||
cairo_private_no_warn cairo_clip_t *
|
||||
_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other);
|
||||
|
||||
|
@ -91,6 +87,10 @@ _cairo_clip_init_copy_transformed (cairo_clip_t *clip,
|
|||
cairo_private void
|
||||
_cairo_clip_reset (cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_clip_equal (const cairo_clip_t *clip_a,
|
||||
const cairo_clip_t *clip_b);
|
||||
|
||||
#define _cairo_clip_fini(clip) _cairo_clip_reset (clip)
|
||||
|
||||
cairo_private cairo_status_t
|
||||
|
@ -112,12 +112,12 @@ cairo_private const cairo_rectangle_int_t *
|
|||
_cairo_clip_get_extents (const cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *dst);
|
||||
_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *dst, int *tx, int *ty);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_clip_combine_with_surface (cairo_clip_t *clip,
|
||||
cairo_surface_t *dst,
|
||||
const cairo_rectangle_int_t *extents);
|
||||
int dst_x, int dst_y);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_clip_get_region (cairo_clip_t *clip,
|
||||
|
@ -128,6 +128,20 @@ _cairo_clip_get_boxes (cairo_clip_t *clip,
|
|||
cairo_box_t **boxes,
|
||||
int *count);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_clip_to_boxes (cairo_clip_t **clip,
|
||||
cairo_composite_rectangles_t *extents,
|
||||
cairo_box_t **boxes,
|
||||
int *num_boxes);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_clip_contains_rectangle (cairo_clip_t *clip,
|
||||
const cairo_rectangle_int_t *rect);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_clip_contains_extents (cairo_clip_t *clip,
|
||||
const cairo_composite_rectangles_t *extents);
|
||||
|
||||
cairo_private void
|
||||
_cairo_clip_drop_cache (cairo_clip_t *clip);
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -41,95 +41,16 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-clip-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-freed-pool-private.h"
|
||||
#include "cairo-gstate-private.h"
|
||||
#include "cairo-path-fixed-private.h"
|
||||
#include "cairo-composite-rectangles-private.h"
|
||||
#include "cairo-region-private.h"
|
||||
|
||||
/* Keep a stash of recently freed clip_paths, since we need to
|
||||
* reallocate them frequently.
|
||||
*/
|
||||
#define MAX_FREED_POOL_SIZE 4
|
||||
typedef struct {
|
||||
void *pool[MAX_FREED_POOL_SIZE];
|
||||
int top;
|
||||
} freed_pool_t;
|
||||
|
||||
#if HAS_FREED_POOL
|
||||
static freed_pool_t clip_path_pool;
|
||||
|
||||
static void *
|
||||
_atomic_fetch (void **slot)
|
||||
{
|
||||
return _cairo_atomic_ptr_cmpxchg (slot, *slot, NULL);
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_atomic_store (void **slot, void *ptr)
|
||||
{
|
||||
return _cairo_atomic_ptr_cmpxchg (slot, NULL, ptr) == NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
_freed_pool_get (freed_pool_t *pool)
|
||||
{
|
||||
void *ptr;
|
||||
int i;
|
||||
|
||||
i = pool->top - 1;
|
||||
if (i < 0)
|
||||
i = 0;
|
||||
|
||||
ptr = _atomic_fetch (&pool->pool[i]);
|
||||
if (ptr != NULL) {
|
||||
pool->top = i;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* either empty or contended */
|
||||
for (i = ARRAY_LENGTH (pool->pool); i--;) {
|
||||
ptr = _atomic_fetch (&pool->pool[i]);
|
||||
if (ptr != NULL) {
|
||||
pool->top = i;
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* empty */
|
||||
pool->top = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_freed_pool_put (freed_pool_t *pool, void *ptr)
|
||||
{
|
||||
int i = pool->top;
|
||||
|
||||
if (_atomic_store (&pool->pool[i], ptr)) {
|
||||
pool->top = i + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* either full or contended */
|
||||
for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) {
|
||||
if (_atomic_store (&pool->pool[i], ptr)) {
|
||||
pool->top = i + 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* full */
|
||||
pool->top = ARRAY_LENGTH (pool->pool);
|
||||
free (ptr);
|
||||
}
|
||||
|
||||
static void
|
||||
_freed_pool_reset (freed_pool_t *pool)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) {
|
||||
free (pool->pool[i]);
|
||||
pool->pool[i] = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static cairo_clip_path_t *
|
||||
_cairo_clip_path_create (cairo_clip_t *clip)
|
||||
|
@ -158,9 +79,6 @@ _cairo_clip_path_create (cairo_clip_t *clip)
|
|||
static cairo_clip_path_t *
|
||||
_cairo_clip_path_reference (cairo_clip_path_t *clip_path)
|
||||
{
|
||||
if (clip_path == NULL)
|
||||
return NULL;
|
||||
|
||||
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&clip_path->ref_count));
|
||||
|
||||
_cairo_reference_count_inc (&clip_path->ref_count);
|
||||
|
@ -247,47 +165,40 @@ _cairo_clip_intersect_rectangle (cairo_clip_t *clip,
|
|||
status = _cairo_path_fixed_close_path (&clip_path->path);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
clip_path->extents = *rect;
|
||||
clip_path->fill_rule = CAIRO_FILL_RULE_WINDING;
|
||||
clip_path->tolerance = 1;
|
||||
clip_path->antialias = CAIRO_ANTIALIAS_NONE;
|
||||
clip_path->antialias = CAIRO_ANTIALIAS_DEFAULT;
|
||||
clip_path->flags |= CAIRO_CLIP_PATH_IS_BOX;
|
||||
|
||||
clip_path->extents = *rect;
|
||||
if (clip_path->prev != NULL) {
|
||||
if (! _cairo_rectangle_intersect (&clip_path->extents,
|
||||
&clip_path->prev->extents))
|
||||
{
|
||||
_cairo_clip_set_all_clipped (clip);
|
||||
}
|
||||
}
|
||||
|
||||
/* could preallocate the region if it proves worthwhile */
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* XXX consider accepting a matrix, no users yet. */
|
||||
cairo_status_t
|
||||
_cairo_clip_init_rectangle (cairo_clip_t *clip,
|
||||
const cairo_rectangle_int_t *rect)
|
||||
{
|
||||
_cairo_clip_init (clip);
|
||||
|
||||
if (rect == NULL)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (rect->width == 0 || rect->height == 0) {
|
||||
_cairo_clip_set_all_clipped (clip);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return _cairo_clip_intersect_rectangle (clip, rect);
|
||||
}
|
||||
|
||||
cairo_clip_t *
|
||||
_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
|
||||
{
|
||||
if (other != NULL) {
|
||||
clip->all_clipped = other->all_clipped;
|
||||
clip->path = _cairo_clip_path_reference (other->path);
|
||||
|
||||
/* this guy is here because of the weird return semantics of _cairo_clip_init_copy */
|
||||
if (!other->path)
|
||||
return NULL;
|
||||
if (other->path == NULL) {
|
||||
clip->path = NULL;
|
||||
if (! clip->all_clipped)
|
||||
clip = NULL;
|
||||
} else {
|
||||
clip->path = _cairo_clip_path_reference (other->path);
|
||||
}
|
||||
} else {
|
||||
_cairo_clip_init (clip);
|
||||
clip = NULL;
|
||||
}
|
||||
|
||||
return clip;
|
||||
|
@ -318,9 +229,8 @@ _cairo_clip_intersect_path (cairo_clip_t *clip,
|
|||
|
||||
if (clip->path != NULL) {
|
||||
if (clip->path->fill_rule == fill_rule &&
|
||||
(path->is_rectilinear ||
|
||||
(tolerance == clip->path->tolerance &&
|
||||
antialias == clip->path->antialias)) &&
|
||||
(path->is_rectilinear || tolerance == clip->path->tolerance) &&
|
||||
antialias == clip->path->antialias &&
|
||||
_cairo_path_fixed_equal (&clip->path->path, path))
|
||||
{
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
@ -372,6 +282,38 @@ _cairo_clip_intersect_path (cairo_clip_t *clip,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_clip_equal (const cairo_clip_t *clip_a,
|
||||
const cairo_clip_t *clip_b)
|
||||
{
|
||||
const cairo_clip_path_t *clip_path_a, *clip_path_b;
|
||||
|
||||
clip_path_a = clip_a->path;
|
||||
clip_path_b = clip_b->path;
|
||||
|
||||
while (clip_path_a && clip_path_b) {
|
||||
if (clip_path_a == clip_path_b)
|
||||
return TRUE;
|
||||
|
||||
if (clip_path_a->fill_rule != clip_path_b->fill_rule)
|
||||
return FALSE;
|
||||
|
||||
if (clip_path_a->tolerance != clip_path_b->tolerance)
|
||||
return FALSE;
|
||||
|
||||
if (clip_path_a->antialias != clip_path_b->antialias)
|
||||
return FALSE;
|
||||
|
||||
if (! _cairo_path_fixed_equal (&clip_path_a->path, &clip_path_b->path))
|
||||
return FALSE;
|
||||
|
||||
clip_path_a = clip_path_a->prev;
|
||||
clip_path_b = clip_path_b->prev;
|
||||
}
|
||||
|
||||
return clip_path_a == clip_path_b; /* ie both NULL */
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_clip_clip (cairo_clip_t *clip,
|
||||
const cairo_path_fixed_t *path,
|
||||
|
@ -409,7 +351,7 @@ _cairo_clip_rectangle (cairo_clip_t *clip,
|
|||
if (clip->path != NULL) {
|
||||
if (rectangle->x <= clip->path->extents.x &&
|
||||
rectangle->y <= clip->path->extents.y &&
|
||||
rectangle->x + rectangle->width >= clip->path->extents.x + clip->path->extents.width &&
|
||||
rectangle->x + rectangle->width >= clip->path->extents.x + clip->path->extents.width &&
|
||||
rectangle->y + rectangle->height >= clip->path->extents.y + clip->path->extents.height)
|
||||
{
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
@ -443,6 +385,7 @@ _cairo_clip_path_reapply_clip_path_transform (cairo_clip_t *clip,
|
|||
status = _cairo_path_fixed_init_copy (&clip_path->path,
|
||||
&other_path->path);
|
||||
if (unlikely (status)) {
|
||||
clip->path = clip->path->prev;
|
||||
_cairo_clip_path_destroy (clip_path);
|
||||
return status;
|
||||
}
|
||||
|
@ -485,6 +428,7 @@ _cairo_clip_path_reapply_clip_path_translate (cairo_clip_t *clip,
|
|||
status = _cairo_path_fixed_init_copy (&clip_path->path,
|
||||
&other_path->path);
|
||||
if (unlikely (status)) {
|
||||
clip->path = clip->path->prev;
|
||||
_cairo_clip_path_destroy (clip_path);
|
||||
return status;
|
||||
}
|
||||
|
@ -500,6 +444,13 @@ _cairo_clip_path_reapply_clip_path_translate (cairo_clip_t *clip,
|
|||
clip_path->flags = other_path->flags;
|
||||
if (other_path->region != NULL) {
|
||||
clip_path->region = cairo_region_copy (other_path->region);
|
||||
status = clip_path->region->status;
|
||||
if (unlikely (status)) {
|
||||
clip->path = clip->path->prev;
|
||||
_cairo_clip_path_destroy (clip_path);
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_region_translate (clip_path->region, tx, ty);
|
||||
}
|
||||
clip_path->surface = cairo_surface_reference (other_path->surface);
|
||||
|
@ -997,104 +948,73 @@ _cairo_clip_path_to_boxes (cairo_clip_path_t *clip_path,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_combine_region (cairo_surface_t *surface,
|
||||
const cairo_region_t *region,
|
||||
const cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_region_t clear_region;
|
||||
cairo_status_t status;
|
||||
|
||||
_cairo_region_init_rectangle (&clear_region, extents);
|
||||
status = cairo_region_subtract (&clear_region, region);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (! cairo_region_is_empty (&clear_region)) {
|
||||
cairo_region_translate (&clear_region, -extents->x, -extents->y);
|
||||
status = _cairo_surface_fill_region (surface,
|
||||
CAIRO_OPERATOR_CLEAR,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
&clear_region);
|
||||
}
|
||||
_cairo_region_fini (&clear_region);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_clip_path_get_surface (cairo_clip_path_t *clip_path,
|
||||
cairo_surface_t *target)
|
||||
cairo_surface_t *target,
|
||||
int *tx, int *ty)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_pattern_union_t pattern;
|
||||
cairo_status_t status;
|
||||
const cairo_rectangle_int_t *clip_extents = &clip_path->extents;
|
||||
cairo_clip_path_t *prev;
|
||||
cairo_bool_t need_translate;
|
||||
cairo_surface_t *surface;
|
||||
cairo_clip_path_t *prev;
|
||||
cairo_status_t status;
|
||||
|
||||
while (clip_path->prev != NULL &&
|
||||
clip_path->flags & CAIRO_CLIP_PATH_IS_BOX &&
|
||||
clip_path->path.maybe_fill_region)
|
||||
{
|
||||
clip_path = clip_path->prev;
|
||||
}
|
||||
|
||||
clip_extents = &clip_path->extents;
|
||||
if (clip_path->surface != NULL &&
|
||||
clip_path->surface->backend == target->backend)
|
||||
{
|
||||
return cairo_surface_reference (clip_path->surface);
|
||||
*tx = clip_extents->x;
|
||||
*ty = clip_extents->y;
|
||||
return clip_path->surface;
|
||||
}
|
||||
|
||||
surface = _cairo_surface_create_similar_solid (target,
|
||||
CAIRO_CONTENT_ALPHA,
|
||||
clip_extents->width,
|
||||
clip_extents->height,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
FALSE);
|
||||
surface = _cairo_surface_create_similar_scratch (target,
|
||||
CAIRO_CONTENT_ALPHA,
|
||||
clip_extents->width,
|
||||
clip_extents->height);
|
||||
if (surface == NULL) {
|
||||
if (clip_path->surface != NULL &&
|
||||
clip_path->surface->backend == &_cairo_image_surface_backend)
|
||||
{
|
||||
return cairo_surface_reference (clip_path->surface);
|
||||
}
|
||||
|
||||
surface =
|
||||
_cairo_image_surface_create_with_content (CAIRO_CONTENT_ALPHA,
|
||||
clip_extents->width,
|
||||
clip_extents->height);
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_A8,
|
||||
clip_extents->width,
|
||||
clip_extents->height);
|
||||
}
|
||||
if (unlikely (surface->status))
|
||||
return surface;
|
||||
|
||||
_cairo_pattern_init_solid (&pattern.solid,
|
||||
CAIRO_COLOR_WHITE,
|
||||
CAIRO_CONTENT_COLOR);
|
||||
|
||||
status = _cairo_clip_path_to_region (clip_path);
|
||||
if (unlikely (_cairo_status_is_error (status)))
|
||||
goto BAIL;
|
||||
|
||||
need_translate = clip_extents->x | clip_extents->y;
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
if (need_translate) {
|
||||
cairo_region_translate (clip_path->region,
|
||||
-clip_extents->x, -clip_extents->y);
|
||||
}
|
||||
status = _cairo_surface_fill_region (surface,
|
||||
CAIRO_OPERATOR_SOURCE,
|
||||
CAIRO_COLOR_WHITE,
|
||||
clip_path->region);
|
||||
if (need_translate) {
|
||||
cairo_region_translate (clip_path->region,
|
||||
clip_extents->x, clip_extents->y);
|
||||
}
|
||||
if (clip_path->flags & CAIRO_CLIP_PATH_IS_BOX &&
|
||||
clip_path->path.maybe_fill_region)
|
||||
{
|
||||
status = _cairo_surface_paint (surface,
|
||||
CAIRO_OPERATOR_SOURCE,
|
||||
&_cairo_pattern_white.base,
|
||||
NULL);
|
||||
if (unlikely (status))
|
||||
goto BAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = _cairo_surface_paint (surface,
|
||||
CAIRO_OPERATOR_CLEAR,
|
||||
&_cairo_pattern_clear.base,
|
||||
NULL);
|
||||
if (unlikely (status))
|
||||
goto BAIL;
|
||||
|
||||
goto DONE;
|
||||
} else {
|
||||
if (need_translate) {
|
||||
_cairo_path_fixed_translate (&clip_path->path,
|
||||
_cairo_fixed_from_int (-clip_extents->x),
|
||||
_cairo_fixed_from_int (-clip_extents->y));
|
||||
}
|
||||
status = _cairo_surface_fill (surface,
|
||||
CAIRO_OPERATOR_OVER,
|
||||
&pattern.base,
|
||||
CAIRO_OPERATOR_ADD,
|
||||
&_cairo_pattern_white.base,
|
||||
&clip_path->path,
|
||||
clip_path->fill_rule,
|
||||
clip_path->tolerance,
|
||||
|
@ -1111,19 +1031,16 @@ _cairo_clip_path_get_surface (cairo_clip_path_t *clip_path,
|
|||
}
|
||||
|
||||
prev = clip_path->prev;
|
||||
NEXT_PATH:
|
||||
if (prev != NULL) {
|
||||
status = _cairo_clip_path_to_region (prev);
|
||||
if (unlikely (_cairo_status_is_error (status)))
|
||||
goto BAIL;
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
status = _combine_region (surface, prev->region, clip_extents);
|
||||
if (unlikely (status))
|
||||
goto BAIL;
|
||||
} else if (prev->flags & CAIRO_CLIP_PATH_IS_BOX) {
|
||||
while (prev != NULL) {
|
||||
if (prev->flags & CAIRO_CLIP_PATH_IS_BOX &&
|
||||
prev->path.maybe_fill_region)
|
||||
{
|
||||
/* a simple box only affects the extents */
|
||||
} else if (prev->path.is_rectilinear) {
|
||||
}
|
||||
else if (prev->path.is_rectilinear ||
|
||||
prev->surface == NULL ||
|
||||
prev->surface->backend != target->backend)
|
||||
{
|
||||
if (need_translate) {
|
||||
_cairo_path_fixed_translate (&prev->path,
|
||||
_cairo_fixed_from_int (-clip_extents->x),
|
||||
|
@ -1131,7 +1048,7 @@ _cairo_clip_path_get_surface (cairo_clip_path_t *clip_path,
|
|||
}
|
||||
status = _cairo_surface_fill (surface,
|
||||
CAIRO_OPERATOR_IN,
|
||||
&pattern.base,
|
||||
&_cairo_pattern_white.base,
|
||||
&prev->path,
|
||||
prev->fill_rule,
|
||||
prev->tolerance,
|
||||
|
@ -1145,19 +1062,23 @@ _cairo_clip_path_get_surface (cairo_clip_path_t *clip_path,
|
|||
|
||||
if (unlikely (status))
|
||||
goto BAIL;
|
||||
|
||||
prev = prev->prev;
|
||||
goto NEXT_PATH;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_surface_pattern_t pattern;
|
||||
cairo_surface_t *prev_surface;
|
||||
int prev_tx, prev_ty;
|
||||
|
||||
prev_surface = _cairo_clip_path_get_surface (prev, target);
|
||||
_cairo_pattern_init_for_surface (&pattern.surface, prev_surface);
|
||||
cairo_surface_destroy (prev_surface);
|
||||
prev_surface = _cairo_clip_path_get_surface (prev, target, &prev_tx, &prev_ty);
|
||||
status = prev_surface->status;
|
||||
if (unlikely (status))
|
||||
goto BAIL;
|
||||
|
||||
_cairo_pattern_init_for_surface (&pattern, prev_surface);
|
||||
pattern.base.filter = CAIRO_FILTER_NEAREST;
|
||||
cairo_matrix_init_translate (&pattern.base.matrix,
|
||||
-prev->extents.x + clip_extents->x,
|
||||
-prev->extents.y + clip_extents->y);
|
||||
clip_extents->x - prev_tx,
|
||||
clip_extents->y - prev_ty);
|
||||
status = _cairo_surface_paint (surface,
|
||||
CAIRO_OPERATOR_IN,
|
||||
&pattern.base,
|
||||
|
@ -1166,18 +1087,75 @@ _cairo_clip_path_get_surface (cairo_clip_path_t *clip_path,
|
|||
|
||||
if (unlikely (status))
|
||||
goto BAIL;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
prev = prev->prev;
|
||||
}
|
||||
|
||||
DONE:
|
||||
*tx = clip_extents->x;
|
||||
*ty = clip_extents->y;
|
||||
cairo_surface_destroy (clip_path->surface);
|
||||
return clip_path->surface = cairo_surface_reference (surface);
|
||||
return clip_path->surface = surface;
|
||||
|
||||
BAIL:
|
||||
cairo_surface_destroy (surface);
|
||||
return _cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_clip_contains_rectangle (cairo_clip_t *clip,
|
||||
const cairo_rectangle_int_t *rect)
|
||||
{
|
||||
cairo_clip_path_t *clip_path;
|
||||
|
||||
if (clip == NULL)
|
||||
return FALSE;
|
||||
|
||||
clip_path = clip->path;
|
||||
if (clip_path->extents.x > rect->x ||
|
||||
clip_path->extents.y > rect->y ||
|
||||
clip_path->extents.x + clip_path->extents.width < rect->x + rect->width ||
|
||||
clip_path->extents.y + clip_path->extents.height < rect->y + rect->height)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
do {
|
||||
cairo_box_t box;
|
||||
|
||||
if ((clip_path->flags & CAIRO_CLIP_PATH_IS_BOX) == 0)
|
||||
return FALSE;
|
||||
|
||||
if (! _cairo_path_fixed_is_box (&clip_path->path, &box))
|
||||
return FALSE;
|
||||
|
||||
if (box.p1.x > _cairo_fixed_from_int (rect->x) ||
|
||||
box.p1.y > _cairo_fixed_from_int (rect->y) ||
|
||||
box.p2.x < _cairo_fixed_from_int (rect->x + rect->width) ||
|
||||
box.p2.y < _cairo_fixed_from_int (rect->y + rect->height))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
} while ((clip_path = clip_path->prev) != NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_clip_contains_extents (cairo_clip_t *clip,
|
||||
const cairo_composite_rectangles_t *extents)
|
||||
{
|
||||
const cairo_rectangle_int_t *rect;
|
||||
|
||||
if (clip == NULL)
|
||||
return FALSE;
|
||||
|
||||
rect = extents->is_bounded ? &extents->bounded : &extents->unbounded;
|
||||
return _cairo_clip_contains_rectangle (clip, rect);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_debug_print_clip (FILE *stream, cairo_clip_t *clip)
|
||||
{
|
||||
|
@ -1202,72 +1180,48 @@ _cairo_debug_print_clip (FILE *stream, cairo_clip_t *clip)
|
|||
|
||||
clip_path = clip->path;
|
||||
do {
|
||||
fprintf (stream, "path: has region? %s, has surface? %s: ",
|
||||
fprintf (stream, "path: has region? %s, has surface? %s, aa=%d, tolerance=%f, rule=%d: ",
|
||||
clip_path->region == NULL ? "no" : "yes",
|
||||
clip_path->surface == NULL ? "no" : "yes");
|
||||
clip_path->surface == NULL ? "no" : "yes",
|
||||
clip_path->antialias,
|
||||
clip_path->tolerance,
|
||||
clip_path->fill_rule);
|
||||
_cairo_debug_print_path (stream, &clip_path->path);
|
||||
fprintf (stream, "\n");
|
||||
} while ((clip_path = clip_path->prev) != NULL);
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *target)
|
||||
_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *target, int *tx, int *ty)
|
||||
{
|
||||
/* XXX is_clear -> all_clipped */
|
||||
assert (clip->path != NULL);
|
||||
return _cairo_clip_path_get_surface (clip->path, target);
|
||||
return _cairo_clip_path_get_surface (clip->path, target, tx, ty);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_clip_combine_with_surface (cairo_clip_t *clip,
|
||||
cairo_surface_t *dst,
|
||||
const cairo_rectangle_int_t *extents)
|
||||
int dst_x, int dst_y)
|
||||
{
|
||||
cairo_pattern_union_t pattern;
|
||||
cairo_clip_path_t *clip_path = clip->path;
|
||||
cairo_bool_t need_translate;
|
||||
cairo_status_t status;
|
||||
|
||||
assert (clip_path != NULL);
|
||||
|
||||
if (clip_path->surface != NULL &&
|
||||
clip_path->surface->backend == dst->backend)
|
||||
{
|
||||
_cairo_pattern_init_for_surface (&pattern.surface,
|
||||
clip_path->surface);
|
||||
cairo_matrix_init_translate (&pattern.base.matrix,
|
||||
extents->x - clip_path->extents.x,
|
||||
extents->y - clip_path->extents.y);
|
||||
status = _cairo_surface_paint (dst,
|
||||
CAIRO_OPERATOR_IN,
|
||||
&pattern.base,
|
||||
NULL);
|
||||
|
||||
_cairo_pattern_fini (&pattern.base);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
_cairo_pattern_init_solid (&pattern.solid,
|
||||
CAIRO_COLOR_WHITE,
|
||||
CAIRO_CONTENT_COLOR);
|
||||
|
||||
need_translate = extents->x | extents->y;
|
||||
need_translate = dst_x | dst_y;
|
||||
do {
|
||||
status = _cairo_clip_path_to_region (clip_path);
|
||||
if (unlikely (_cairo_status_is_error (status)))
|
||||
return status;
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
return _combine_region (dst, clip_path->region, extents);
|
||||
|
||||
if (clip_path->surface != NULL &&
|
||||
clip_path->surface->backend == dst->backend)
|
||||
{
|
||||
_cairo_pattern_init_for_surface (&pattern.surface,
|
||||
clip_path->surface);
|
||||
cairo_surface_pattern_t pattern;
|
||||
|
||||
_cairo_pattern_init_for_surface (&pattern, clip_path->surface);
|
||||
cairo_matrix_init_translate (&pattern.base.matrix,
|
||||
extents->x - clip_path->extents.x,
|
||||
extents->y - clip_path->extents.y);
|
||||
dst_x - clip_path->extents.x,
|
||||
dst_y - clip_path->extents.y);
|
||||
pattern.base.filter = CAIRO_FILTER_NEAREST;
|
||||
status = _cairo_surface_paint (dst,
|
||||
CAIRO_OPERATOR_IN,
|
||||
&pattern.base,
|
||||
|
@ -1278,30 +1232,29 @@ _cairo_clip_combine_with_surface (cairo_clip_t *clip,
|
|||
return status;
|
||||
}
|
||||
|
||||
if (clip_path->flags & CAIRO_CLIP_PATH_IS_BOX) {
|
||||
cairo_region_t clip_region;
|
||||
if (clip_path->flags & CAIRO_CLIP_PATH_IS_BOX &&
|
||||
clip_path->path.maybe_fill_region)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_cairo_region_init_rectangle (&clip_region, &clip_path->extents);
|
||||
status = _combine_region (dst, &clip_region, extents);
|
||||
} else {
|
||||
if (need_translate) {
|
||||
_cairo_path_fixed_translate (&clip_path->path,
|
||||
_cairo_fixed_from_int (-extents->x),
|
||||
_cairo_fixed_from_int (-extents->y));
|
||||
}
|
||||
status = _cairo_surface_fill (dst,
|
||||
CAIRO_OPERATOR_IN,
|
||||
&pattern.base,
|
||||
&clip_path->path,
|
||||
clip_path->fill_rule,
|
||||
clip_path->tolerance,
|
||||
clip_path->antialias,
|
||||
NULL);
|
||||
if (need_translate) {
|
||||
_cairo_path_fixed_translate (&clip_path->path,
|
||||
_cairo_fixed_from_int (extents->x),
|
||||
_cairo_fixed_from_int (extents->y));
|
||||
}
|
||||
if (need_translate) {
|
||||
_cairo_path_fixed_translate (&clip_path->path,
|
||||
_cairo_fixed_from_int (-dst_x),
|
||||
_cairo_fixed_from_int (-dst_y));
|
||||
}
|
||||
status = _cairo_surface_fill (dst,
|
||||
CAIRO_OPERATOR_IN,
|
||||
&_cairo_pattern_white.base,
|
||||
&clip_path->path,
|
||||
clip_path->fill_rule,
|
||||
clip_path->tolerance,
|
||||
clip_path->antialias,
|
||||
NULL);
|
||||
if (need_translate) {
|
||||
_cairo_path_fixed_translate (&clip_path->path,
|
||||
_cairo_fixed_from_int (dst_x),
|
||||
_cairo_fixed_from_int (dst_y));
|
||||
}
|
||||
|
||||
if (unlikely (status))
|
||||
|
@ -1432,6 +1385,90 @@ _cairo_clip_get_boxes (cairo_clip_t *clip,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
box_is_aligned (const cairo_box_t *box)
|
||||
{
|
||||
return
|
||||
_cairo_fixed_is_integer (box->p1.x) &&
|
||||
_cairo_fixed_is_integer (box->p1.y) &&
|
||||
_cairo_fixed_is_integer (box->p2.x) &&
|
||||
_cairo_fixed_is_integer (box->p2.y);
|
||||
}
|
||||
|
||||
static void
|
||||
intersect_with_boxes (cairo_composite_rectangles_t *extents,
|
||||
cairo_box_t *boxes,
|
||||
int num_boxes)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
cairo_box_t box;
|
||||
cairo_bool_t is_empty;
|
||||
|
||||
box.p1.x = box.p1.y = INT_MIN;
|
||||
box.p2.x = box.p2.y = INT_MAX;
|
||||
while (num_boxes--) {
|
||||
if (boxes->p1.x < box.p1.x)
|
||||
box.p1.x = boxes->p1.x;
|
||||
if (boxes->p1.y < box.p1.y)
|
||||
box.p1.y = boxes->p1.y;
|
||||
|
||||
if (boxes->p2.x > box.p2.x)
|
||||
box.p2.x = boxes->p2.x;
|
||||
if (boxes->p2.y > box.p2.y)
|
||||
box.p2.y = boxes->p2.y;
|
||||
}
|
||||
|
||||
_cairo_box_round_to_rectangle (&box, &rect);
|
||||
is_empty = _cairo_rectangle_intersect (&extents->bounded, &rect);
|
||||
is_empty = _cairo_rectangle_intersect (&extents->unbounded, &rect);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_clip_to_boxes (cairo_clip_t **clip,
|
||||
cairo_composite_rectangles_t *extents,
|
||||
cairo_box_t **boxes,
|
||||
int *num_boxes)
|
||||
{
|
||||
cairo_status_t status;
|
||||
const cairo_rectangle_int_t *rect;
|
||||
|
||||
rect = extents->is_bounded ? &extents->bounded : &extents->unbounded;
|
||||
|
||||
if (*clip == NULL)
|
||||
goto EXTENTS;
|
||||
|
||||
status = _cairo_clip_rectangle (*clip, rect);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = _cairo_clip_get_boxes (*clip, boxes, num_boxes);
|
||||
switch ((int) status) {
|
||||
case CAIRO_STATUS_SUCCESS:
|
||||
intersect_with_boxes (extents, *boxes, *num_boxes);
|
||||
if (rect->width == 0 || rect->height == 0 ||
|
||||
extents->is_bounded ||
|
||||
(*num_boxes == 1 && box_is_aligned (*boxes)))
|
||||
{
|
||||
*clip = NULL;
|
||||
}
|
||||
goto DONE;
|
||||
|
||||
case CAIRO_INT_STATUS_UNSUPPORTED:
|
||||
goto EXTENTS;
|
||||
|
||||
default:
|
||||
return status;
|
||||
}
|
||||
|
||||
EXTENTS:
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
_cairo_box_from_rectangle (&(*boxes)[0], rect);
|
||||
*num_boxes = 1;
|
||||
DONE:
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static cairo_rectangle_list_t *
|
||||
_cairo_rectangle_list_create_in_error (cairo_status_t status)
|
||||
{
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -67,13 +67,14 @@ _cairo_stock_color (cairo_stock_t stock)
|
|||
return &cairo_color_black;
|
||||
case CAIRO_STOCK_TRANSPARENT:
|
||||
return &cairo_color_transparent;
|
||||
|
||||
case CAIRO_STOCK_NUM_COLORS:
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
/* If the user can get here somehow, give a color that indicates a
|
||||
* problem. */
|
||||
return &cairo_color_magenta;
|
||||
}
|
||||
|
||||
ASSERT_NOT_REACHED;
|
||||
|
||||
/* If the user can get here somehow, give a color that indicates a
|
||||
* problem. */
|
||||
return &cairo_color_magenta;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -161,6 +162,7 @@ _cairo_color_get_rgba_premultiplied (cairo_color_t *color,
|
|||
*alpha = color->alpha;
|
||||
}
|
||||
|
||||
/* NB: This function works both for unmultiplied and premultiplied colors */
|
||||
cairo_bool_t
|
||||
_cairo_color_equal (const cairo_color_t *color_a,
|
||||
const cairo_color_t *color_b)
|
||||
|
@ -168,8 +170,42 @@ _cairo_color_equal (const cairo_color_t *color_a,
|
|||
if (color_a == color_b)
|
||||
return TRUE;
|
||||
|
||||
if (color_a->alpha_short != color_b->alpha_short)
|
||||
return FALSE;
|
||||
|
||||
if (color_a->alpha_short == 0)
|
||||
return TRUE;
|
||||
|
||||
return color_a->red_short == color_b->red_short &&
|
||||
color_a->green_short == color_b->green_short &&
|
||||
color_a->blue_short == color_b->blue_short &&
|
||||
color_a->alpha_short == color_b->alpha_short;
|
||||
color_a->blue_short == color_b->blue_short;
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_color_stop_equal (const cairo_color_stop_t *color_a,
|
||||
const cairo_color_stop_t *color_b)
|
||||
{
|
||||
if (color_a == color_b)
|
||||
return TRUE;
|
||||
|
||||
return color_a->alpha_short == color_b->alpha_short &&
|
||||
color_a->red_short == color_b->red_short &&
|
||||
color_a->green_short == color_b->green_short &&
|
||||
color_a->blue_short == color_b->blue_short;
|
||||
}
|
||||
|
||||
cairo_content_t
|
||||
_cairo_color_get_content (const cairo_color_t *color)
|
||||
{
|
||||
if (CAIRO_COLOR_IS_OPAQUE (color))
|
||||
return CAIRO_CONTENT_COLOR;
|
||||
|
||||
if (color->red_short == 0 &&
|
||||
color->green_short == 0 &&
|
||||
color->blue_short == 0)
|
||||
{
|
||||
return CAIRO_CONTENT_ALPHA;
|
||||
}
|
||||
|
||||
return CAIRO_CONTENT_COLOR_ALPHA;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -44,6 +44,45 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* Size in bytes of buffer to use off the stack per functions.
|
||||
* Mostly used by text functions. For larger allocations, they'll
|
||||
* malloc(). */
|
||||
#ifndef CAIRO_STACK_BUFFER_SIZE
|
||||
#define CAIRO_STACK_BUFFER_SIZE (512 * sizeof (int))
|
||||
#endif
|
||||
|
||||
#define CAIRO_STACK_ARRAY_LENGTH(T) (CAIRO_STACK_BUFFER_SIZE / sizeof(T))
|
||||
|
||||
/*
|
||||
* The goal of this block is to define the following macros for
|
||||
* providing faster linkage to functions in the public API for calls
|
||||
* from within cairo.
|
||||
*
|
||||
* slim_hidden_proto(f)
|
||||
* slim_hidden_proto_no_warn(f)
|
||||
*
|
||||
* Declares `f' as a library internal function and hides the
|
||||
* function from the global symbol table. This macro must be
|
||||
* expanded after `f' has been declared with a prototype but before
|
||||
* any calls to the function are seen by the compiler. The no_warn
|
||||
* variant inhibits warnings about the return value being unused at
|
||||
* call sites. The macro works by renaming `f' to an internal name
|
||||
* in the symbol table and hiding that. As far as cairo internal
|
||||
* calls are concerned they're calling a library internal function
|
||||
* and thus don't need to bounce via the PLT.
|
||||
*
|
||||
* slim_hidden_def(f)
|
||||
*
|
||||
* Exports `f' back to the global symbol table. This macro must be
|
||||
* expanded right after the function definition and only for symbols
|
||||
* hidden previously with slim_hidden_proto(). The macro works by
|
||||
* adding a global entry to the symbol table which points at the
|
||||
* internal name of `f' created by slim_hidden_proto().
|
||||
*
|
||||
* Functions in the public API which aren't called by the library
|
||||
* don't need to be hidden and re-exported using the slim hidden
|
||||
* macros.
|
||||
*/
|
||||
#if __GNUC__ >= 3 && defined(__ELF__) && !defined(__sun)
|
||||
# define slim_hidden_proto(name) slim_hidden_proto1(name, slim_hidden_int_name(name)) cairo_private
|
||||
# define slim_hidden_proto_no_warn(name) slim_hidden_proto1(name, slim_hidden_int_name(name)) cairo_private_no_warn
|
||||
|
@ -134,9 +173,11 @@
|
|||
#if __GNUC__ >= 3
|
||||
#define cairo_pure __attribute__((pure))
|
||||
#define cairo_const __attribute__((const))
|
||||
#define cairo_always_inline inline __attribute__((always_inline))
|
||||
#else
|
||||
#define cairo_pure
|
||||
#define cairo_const
|
||||
#define cairo_always_inline inline
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
|
||||
|
@ -171,6 +212,26 @@
|
|||
#ifdef _MSC_VER
|
||||
#undef inline
|
||||
#define inline __inline
|
||||
|
||||
/* there are currently linkage problems that arise when trying to include intrin.h in c++:
|
||||
* D:\sdks\v7.0\include\winnt.h(3674) : error C2733: second C linkage of overloaded function '_interlockedbittestandset' not allowed
|
||||
* so avoid defining ffs in c++ code for now */
|
||||
#ifndef __cplusplus
|
||||
/* Add a definition of ffs */
|
||||
#include <intrin.h>
|
||||
#pragma intrinsic(_BitScanForward)
|
||||
static __forceinline int
|
||||
ffs (int x)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
if (_BitScanForward(&i, x) != 0)
|
||||
return i + 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && defined(_M_IX86)
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2009 Intel Corporation
|
||||
*
|
||||
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 University of Southern
|
||||
* California.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.u>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_COMPOSITE_RECTANGLES_PRIVATE_H
|
||||
#define CAIRO_COMPOSITE_RECTANGLES_PRIVATE_H
|
||||
|
||||
#include "cairo-types-private.h"
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
/* Rectangles that take part in a composite operation.
|
||||
*
|
||||
* The source and mask track the extents of the respective patterns in device
|
||||
* space. The unbounded rectangle is essentially the clip rectangle. And the
|
||||
* intersection of all is the bounded rectangle, which is the minimum extents
|
||||
* the operation may require. Whether or not the operation is actually bounded
|
||||
* is tracked in the is_bounded boolean.
|
||||
*
|
||||
*/
|
||||
struct _cairo_composite_rectangles {
|
||||
cairo_rectangle_int_t source;
|
||||
cairo_rectangle_int_t mask;
|
||||
cairo_rectangle_int_t bounded; /* dst */
|
||||
cairo_rectangle_int_t unbounded; /* clip */
|
||||
uint32_t is_bounded;
|
||||
};
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_paint (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *surface_extents,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_mask (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *surface_extents,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_stroke (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *surface_extents,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_path_fixed_t *path,
|
||||
const cairo_stroke_style_t *style,
|
||||
const cairo_matrix_t *ctm,
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_fill (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *surface_extents,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *surface_extents,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_clip_t *clip,
|
||||
cairo_bool_t *overlap);
|
||||
|
||||
#endif /* CAIRO_COMPOSITE_RECTANGLES_PRIVATE_H */
|
|
@ -0,0 +1,195 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2009 Intel Corporation
|
||||
*
|
||||
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Red Hat, Inc.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-composite-rectangles-private.h"
|
||||
|
||||
/* A collection of routines to facilitate writing compositors. */
|
||||
|
||||
static inline cairo_bool_t
|
||||
_cairo_composite_rectangles_init (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *surface_extents,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
extents->unbounded = *surface_extents;
|
||||
|
||||
if (clip != NULL) {
|
||||
const cairo_rectangle_int_t *clip_extents;
|
||||
|
||||
clip_extents = _cairo_clip_get_extents (clip);
|
||||
if (clip_extents == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (! _cairo_rectangle_intersect (&extents->unbounded, clip_extents))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
extents->bounded = extents->unbounded;
|
||||
extents->is_bounded = _cairo_operator_bounded_by_either (op);
|
||||
|
||||
_cairo_pattern_get_extents (source, &extents->source);
|
||||
if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_SOURCE) {
|
||||
if (! _cairo_rectangle_intersect (&extents->bounded, &extents->source))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_paint (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *surface_extents,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
if (! _cairo_composite_rectangles_init (extents,
|
||||
surface_extents,
|
||||
op, source, clip))
|
||||
{
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
|
||||
extents->mask = extents->bounded;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_composite_rectangles_intersect (cairo_composite_rectangles_t *extents)
|
||||
{
|
||||
cairo_bool_t ret;
|
||||
|
||||
ret = _cairo_rectangle_intersect (&extents->bounded, &extents->mask);
|
||||
if (! ret && extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK)
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_mask (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *surface_extents,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
if (! _cairo_composite_rectangles_init (extents,
|
||||
surface_extents,
|
||||
op, source, clip))
|
||||
{
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
|
||||
_cairo_pattern_get_extents (mask, &extents->mask);
|
||||
|
||||
return _cairo_composite_rectangles_intersect (extents);
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_stroke (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *surface_extents,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_path_fixed_t *path,
|
||||
const cairo_stroke_style_t *style,
|
||||
const cairo_matrix_t *ctm,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
if (! _cairo_composite_rectangles_init (extents,
|
||||
surface_extents,
|
||||
op, source, clip))
|
||||
{
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
|
||||
_cairo_path_fixed_approximate_stroke_extents (path, style, ctm, &extents->mask);
|
||||
|
||||
return _cairo_composite_rectangles_intersect (extents);
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_fill (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *surface_extents,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
if (! _cairo_composite_rectangles_init (extents,
|
||||
surface_extents,
|
||||
op, source, clip))
|
||||
{
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
|
||||
_cairo_path_fixed_approximate_fill_extents (path, &extents->mask);
|
||||
|
||||
return _cairo_composite_rectangles_intersect (extents);
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *surface_extents,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_clip_t *clip,
|
||||
cairo_bool_t *overlap)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (! _cairo_composite_rectangles_init (extents,
|
||||
surface_extents,
|
||||
op, source, clip))
|
||||
{
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
|
||||
status = _cairo_scaled_font_glyph_device_extents (scaled_font,
|
||||
glyphs, num_glyphs,
|
||||
&extents->mask,
|
||||
overlap);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
return _cairo_composite_rectangles_intersect (extents);
|
||||
}
|
|
@ -43,10 +43,8 @@
|
|||
#include <d3d10.h>
|
||||
#include <dxgi.h>
|
||||
|
||||
extern "C" {
|
||||
#include "cairoint.h"
|
||||
#include "cairo-surface-clipper-private.h"
|
||||
}
|
||||
|
||||
#include "cairo-win32-refptr.h"
|
||||
#include "cairo-d2d-private-fx.h"
|
||||
|
|
|
@ -39,10 +39,9 @@
|
|||
#include "cairo-d2d-private.h"
|
||||
#include "cairo-dwrite-private.h"
|
||||
|
||||
extern "C" {
|
||||
#include "cairo-win32.h"
|
||||
#include "cairo-analysis-surface-private.h"
|
||||
}
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
// Required for using placement new.
|
||||
#include <new>
|
||||
|
@ -649,9 +648,9 @@ _cairo_d2d_stroke(void *surface,
|
|||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *style,
|
||||
cairo_matrix_t *ctm,
|
||||
cairo_matrix_t *ctm_inverse,
|
||||
const cairo_stroke_style_t *style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_clip_t *clip);
|
||||
|
@ -763,6 +762,16 @@ _cairo_d2d_compute_surface_mem_size(cairo_d2d_surface_t *surface)
|
|||
return size;
|
||||
}
|
||||
|
||||
static D2D1_COLOR_F
|
||||
_cairo_d2d_color_from_cairo_color_stop(const cairo_color_stop_t &color)
|
||||
{
|
||||
return D2D1::ColorF((FLOAT)color.red,
|
||||
(FLOAT)color.green,
|
||||
(FLOAT)color.blue,
|
||||
(FLOAT)color.alpha);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the surface buffer texture for window surfaces whose backbuffer
|
||||
* is not directly usable as a bitmap.
|
||||
|
@ -1435,7 +1444,7 @@ _cairo_d2d_create_radial_gradient_brush(cairo_d2d_surface_t *d2dsurf,
|
|||
stops[i].position = (FLOAT)((repeat + source_pattern->base.stops[stop].offset) * stop_scale);
|
||||
}
|
||||
stops[i].color =
|
||||
_cairo_d2d_color_from_cairo_color(source_pattern->base.stops[stop].color);
|
||||
_cairo_d2d_color_from_cairo_color_stop(source_pattern->base.stops[stop].color);
|
||||
}
|
||||
} else {
|
||||
// Simple case, we don't need to reflect.
|
||||
|
@ -1445,7 +1454,7 @@ _cairo_d2d_create_radial_gradient_brush(cairo_d2d_surface_t *d2dsurf,
|
|||
// Calculate which stop this would be in the original pattern
|
||||
cairo_gradient_stop_t *stop = &source_pattern->base.stops[i % source_pattern->base.n_stops];
|
||||
stops[i].position = (FLOAT)((repeat + stop->offset) * stop_scale);
|
||||
stops[i].color = _cairo_d2d_color_from_cairo_color(stop->color);
|
||||
stops[i].color = _cairo_d2d_color_from_cairo_color_stop(stop->color);
|
||||
}
|
||||
}
|
||||
} else if (source_pattern->base.base.extend == CAIRO_EXTEND_PAD) {
|
||||
|
@ -1458,7 +1467,7 @@ _cairo_d2d_create_radial_gradient_brush(cairo_d2d_surface_t *d2dsurf,
|
|||
for (unsigned int i = 0; i < source_pattern->base.n_stops; i++) {
|
||||
cairo_gradient_stop_t *stop = &source_pattern->base.stops[i];
|
||||
stops[i].position = (FLOAT)(global_offset + stop->offset * offset_factor);
|
||||
stops[i].color = _cairo_d2d_color_from_cairo_color(stop->color);
|
||||
stops[i].color = _cairo_d2d_color_from_cairo_color_stop(stop->color);
|
||||
}
|
||||
} else if (source_pattern->base.base.extend == CAIRO_EXTEND_NONE) {
|
||||
float offset_factor = (outer_radius - inner_radius) / outer_radius;
|
||||
|
@ -1482,7 +1491,7 @@ _cairo_d2d_create_radial_gradient_brush(cairo_d2d_surface_t *d2dsurf,
|
|||
for (unsigned int j = 0; j < source_pattern->base.n_stops; j++, i++) {
|
||||
cairo_gradient_stop_t *stop = &source_pattern->base.stops[j];
|
||||
stops[i].position = (FLOAT)(global_offset + stop->offset * offset_factor);
|
||||
stops[i].color = _cairo_d2d_color_from_cairo_color(stop->color);
|
||||
stops[i].color = _cairo_d2d_color_from_cairo_color_stop(stop->color);
|
||||
}
|
||||
stops[i].position = 1.0f;
|
||||
stops[i].color = D2D1::ColorF(0, 0);
|
||||
|
@ -1514,7 +1523,7 @@ _cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
|
|||
// Cairo behavior in this situation is to draw a solid color the size of the last stop.
|
||||
RefPtr<ID2D1SolidColorBrush> brush;
|
||||
d2dsurf->rt->CreateSolidColorBrush(
|
||||
_cairo_d2d_color_from_cairo_color(source_pattern->base.stops[source_pattern->base.n_stops - 1].color),
|
||||
_cairo_d2d_color_from_cairo_color_stop(source_pattern->base.stops[source_pattern->base.n_stops - 1].color),
|
||||
&brush);
|
||||
return brush;
|
||||
}
|
||||
|
@ -1619,7 +1628,7 @@ _cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
|
|||
stops[i].position = (FLOAT)((repeat + source_pattern->base.stops[stop].offset) * stop_scale);
|
||||
}
|
||||
stops[i].color =
|
||||
_cairo_d2d_color_from_cairo_color(source_pattern->base.stops[stop].color);
|
||||
_cairo_d2d_color_from_cairo_color_stop(source_pattern->base.stops[stop].color);
|
||||
}
|
||||
} else {
|
||||
// Simple case, we don't need to reflect.
|
||||
|
@ -1629,7 +1638,7 @@ _cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
|
|||
// Calculate which stop this would be in the original pattern
|
||||
cairo_gradient_stop_t *stop = &source_pattern->base.stops[i % source_pattern->base.n_stops];
|
||||
stops[i].position = (FLOAT)((repeat + stop->offset) * stop_scale);
|
||||
stops[i].color = _cairo_d2d_color_from_cairo_color(stop->color);
|
||||
stops[i].color = _cairo_d2d_color_from_cairo_color_stop(stop->color);
|
||||
}
|
||||
}
|
||||
} else if (source_pattern->base.base.extend == CAIRO_EXTEND_PAD) {
|
||||
|
@ -1637,7 +1646,7 @@ _cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
|
|||
for (unsigned int i = 0; i < source_pattern->base.n_stops; i++) {
|
||||
cairo_gradient_stop_t *stop = &source_pattern->base.stops[i];
|
||||
stops[i].position = (FLOAT)stop->offset;
|
||||
stops[i].color = _cairo_d2d_color_from_cairo_color(stop->color);
|
||||
stops[i].color = _cairo_d2d_color_from_cairo_color_stop(stop->color);
|
||||
}
|
||||
} else if (source_pattern->base.base.extend == CAIRO_EXTEND_NONE) {
|
||||
num_stops += 2;
|
||||
|
@ -1647,7 +1656,7 @@ _cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
|
|||
for (unsigned int i = 1; i < source_pattern->base.n_stops + 1; i++) {
|
||||
cairo_gradient_stop_t *stop = &source_pattern->base.stops[i - 1];
|
||||
stops[i].position = (FLOAT)stop->offset;
|
||||
stops[i].color = _cairo_d2d_color_from_cairo_color(stop->color);
|
||||
stops[i].color = _cairo_d2d_color_from_cairo_color_stop(stop->color);
|
||||
}
|
||||
stops[source_pattern->base.n_stops + 1].position = 1.0f;
|
||||
stops[source_pattern->base.n_stops + 1].color = D2D1::ColorF(0, 0);
|
||||
|
@ -2309,6 +2318,16 @@ static cairo_operator_t _cairo_d2d_simplify_operator(cairo_operator_t op,
|
|||
return op;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_d2d_surface_init(cairo_d2d_surface_t *newSurf, cairo_d2d_device_t *d2d_device, cairo_format_t format)
|
||||
{
|
||||
newSurf->format = format;
|
||||
|
||||
newSurf->device = d2d_device;
|
||||
cairo_addref_device(&d2d_device->base);
|
||||
d2d_device->mVRAMUsage += _cairo_d2d_compute_surface_mem_size(newSurf);
|
||||
}
|
||||
|
||||
// Implementation
|
||||
static cairo_surface_t*
|
||||
_cairo_d2d_create_similar(void *surface,
|
||||
|
@ -2320,7 +2339,7 @@ _cairo_d2d_create_similar(void *surface,
|
|||
cairo_d2d_surface_t *newSurf = static_cast<cairo_d2d_surface_t*>(malloc(sizeof(cairo_d2d_surface_t)));
|
||||
|
||||
new (newSurf) cairo_d2d_surface_t();
|
||||
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, content);
|
||||
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, content);
|
||||
|
||||
|
||||
D2D1_SIZE_U sizePixels;
|
||||
|
@ -2425,9 +2444,7 @@ _cairo_d2d_create_similar(void *surface,
|
|||
|
||||
_d2d_clear_surface(newSurf);
|
||||
|
||||
newSurf->device = d2dsurf->device;
|
||||
cairo_addref_device(&newSurf->device->base);
|
||||
newSurf->device->mVRAMUsage += _cairo_d2d_compute_surface_mem_size(newSurf);
|
||||
_cairo_d2d_surface_init(newSurf, d2dsurf->device, _cairo_format_from_content(content));
|
||||
|
||||
return reinterpret_cast<cairo_surface_t*>(newSurf);
|
||||
|
||||
|
@ -2501,8 +2518,8 @@ _cairo_d2d_acquire_source_image(void *abstract_surface,
|
|||
return _cairo_error(CAIRO_STATUS_NO_DEVICE);
|
||||
}
|
||||
*image_out =
|
||||
(cairo_image_surface_t*)_cairo_image_surface_create_for_data_with_content((unsigned char*)data.pData,
|
||||
d2dsurf->base.content,
|
||||
(cairo_image_surface_t*)cairo_image_surface_create_for_data((unsigned char*)data.pData,
|
||||
d2dsurf->format,
|
||||
size.width,
|
||||
size.height,
|
||||
data.RowPitch);
|
||||
|
@ -2573,8 +2590,8 @@ _cairo_d2d_acquire_dest_image(void *abstract_surface,
|
|||
return _cairo_error(CAIRO_STATUS_NO_DEVICE);
|
||||
}
|
||||
*image_out =
|
||||
(cairo_image_surface_t*)_cairo_image_surface_create_for_data_with_content((unsigned char*)data.pData,
|
||||
d2dsurf->base.content,
|
||||
(cairo_image_surface_t*)cairo_image_surface_create_for_data((unsigned char*)data.pData,
|
||||
_cairo_format_from_content(d2dsurf->base.content),
|
||||
size.width,
|
||||
size.height,
|
||||
data.RowPitch);
|
||||
|
@ -3178,7 +3195,7 @@ _cairo_d2d_mask(void *surface,
|
|||
if (mask->type == CAIRO_PATTERN_TYPE_SOLID) {
|
||||
cairo_solid_pattern_t *solidPattern =
|
||||
(cairo_solid_pattern_t*)mask;
|
||||
if (solidPattern->content = CAIRO_CONTENT_ALPHA) {
|
||||
if (_cairo_color_get_content (&solidPattern->color) == CAIRO_CONTENT_ALPHA) {
|
||||
isSolidAlphaMask = true;
|
||||
solidAlphaValue = solidPattern->color.alpha;
|
||||
}
|
||||
|
@ -3321,9 +3338,9 @@ _cairo_d2d_stroke(void *surface,
|
|||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *style,
|
||||
cairo_matrix_t *ctm,
|
||||
cairo_matrix_t *ctm_inverse,
|
||||
const cairo_stroke_style_t *style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_clip_t *clip)
|
||||
|
@ -3526,7 +3543,12 @@ _cairo_d2d_fill(void *surface,
|
|||
|
||||
if (target_rt.get() != d2dsurf->rt.get()) {
|
||||
double x1, y1, x2, y2;
|
||||
_cairo_path_fixed_bounds(path, &x1, &y1, &x2, &y2);
|
||||
cairo_box_t box;
|
||||
_cairo_path_fixed_extents (path, &box);
|
||||
x1 = _cairo_fixed_to_double (box.p1.x);
|
||||
y1 = _cairo_fixed_to_double (box.p1.y);
|
||||
x2 = _cairo_fixed_to_double (box.p2.x);
|
||||
y2 = _cairo_fixed_to_double (box.p2.y);
|
||||
cairo_rectangle_int_t bounds;
|
||||
_cairo_d2d_round_out_to_int_rect(&bounds, x1, y1, x2, y2);
|
||||
return _cairo_d2d_blend_temp_surface(d2dsurf, op, target_rt, clip, &bounds);
|
||||
|
@ -4118,6 +4140,8 @@ _cairo_d2d_getextents(void *surface,
|
|||
|
||||
/** Helper functions. */
|
||||
|
||||
|
||||
|
||||
cairo_surface_t*
|
||||
cairo_d2d_surface_create_for_hwnd(cairo_device_t *cairo_device,
|
||||
HWND wnd,
|
||||
|
@ -4127,7 +4151,7 @@ cairo_d2d_surface_create_for_hwnd(cairo_device_t *cairo_device,
|
|||
cairo_d2d_surface_t *newSurf = static_cast<cairo_d2d_surface_t*>(malloc(sizeof(cairo_d2d_surface_t)));
|
||||
new (newSurf) cairo_d2d_surface_t();
|
||||
|
||||
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, content);
|
||||
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, content);
|
||||
|
||||
RECT rc;
|
||||
HRESULT hr;
|
||||
|
@ -4229,9 +4253,7 @@ cairo_d2d_surface_create_for_hwnd(cairo_device_t *cairo_device,
|
|||
|
||||
_d2d_clear_surface(newSurf);
|
||||
|
||||
newSurf->device = d2d_device;
|
||||
cairo_addref_device(cairo_device);
|
||||
d2d_device->mVRAMUsage += _cairo_d2d_compute_surface_mem_size(newSurf);
|
||||
_cairo_d2d_surface_init(newSurf, d2d_device, _cairo_format_from_content(content));
|
||||
|
||||
return reinterpret_cast<cairo_surface_t*>(newSurf);
|
||||
|
||||
|
@ -4241,6 +4263,8 @@ FAIL_HWND:
|
|||
return _cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY));
|
||||
}
|
||||
|
||||
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_d2d_surface_create(cairo_device_t *device,
|
||||
cairo_format_t format,
|
||||
|
@ -4258,12 +4282,12 @@ cairo_d2d_surface_create(cairo_device_t *device,
|
|||
DXGI_FORMAT dxgiformat = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
D2D1_ALPHA_MODE alpha = D2D1_ALPHA_MODE_PREMULTIPLIED;
|
||||
if (format == CAIRO_FORMAT_ARGB32) {
|
||||
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, CAIRO_CONTENT_COLOR_ALPHA);
|
||||
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, CAIRO_CONTENT_COLOR_ALPHA);
|
||||
} else if (format == CAIRO_FORMAT_RGB24) {
|
||||
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, CAIRO_CONTENT_COLOR);
|
||||
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, CAIRO_CONTENT_COLOR);
|
||||
alpha = D2D1_ALPHA_MODE_IGNORE;
|
||||
} else {
|
||||
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, CAIRO_CONTENT_ALPHA);
|
||||
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, CAIRO_CONTENT_ALPHA);
|
||||
dxgiformat = DXGI_FORMAT_A8_UNORM;
|
||||
}
|
||||
|
||||
|
@ -4343,9 +4367,7 @@ cairo_d2d_surface_create(cairo_device_t *device,
|
|||
|
||||
_d2d_clear_surface(newSurf);
|
||||
|
||||
newSurf->device = d2d_device;
|
||||
cairo_addref_device(device);
|
||||
d2d_device->mVRAMUsage += _cairo_d2d_compute_surface_mem_size(newSurf);
|
||||
_cairo_d2d_surface_init(newSurf, d2d_device, format);
|
||||
|
||||
return reinterpret_cast<cairo_surface_t*>(newSurf);
|
||||
|
||||
|
@ -4398,7 +4420,7 @@ cairo_d2d_surface_create_for_handle(cairo_device_t *device, HANDLE handle, cairo
|
|||
status = CAIRO_STATUS_INVALID_CONTENT;
|
||||
goto FAIL_CREATEHANDLE;
|
||||
}
|
||||
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, content);
|
||||
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, content);
|
||||
if (content == CAIRO_CONTENT_COLOR) {
|
||||
alpha = D2D1_ALPHA_MODE_IGNORE;
|
||||
}
|
||||
|
@ -4407,7 +4429,7 @@ cairo_d2d_surface_create_for_handle(cairo_device_t *device, HANDLE handle, cairo
|
|||
status = CAIRO_STATUS_INVALID_CONTENT;
|
||||
goto FAIL_CREATEHANDLE;
|
||||
}
|
||||
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, CAIRO_CONTENT_ALPHA);
|
||||
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, CAIRO_CONTENT_ALPHA);
|
||||
} else {
|
||||
status = CAIRO_STATUS_INVALID_FORMAT;
|
||||
// We don't know how to support this format!
|
||||
|
@ -4444,9 +4466,7 @@ cairo_d2d_surface_create_for_handle(cairo_device_t *device, HANDLE handle, cairo
|
|||
|
||||
newSurf->rt->CreateSolidColorBrush(D2D1::ColorF(0, 1.0), &newSurf->solidColorBrush);
|
||||
|
||||
newSurf->device = d2d_device;
|
||||
cairo_addref_device(device);
|
||||
d2d_device->mVRAMUsage += _cairo_d2d_compute_surface_mem_size(newSurf);
|
||||
_cairo_d2d_surface_init(newSurf, d2d_device, _cairo_format_from_content(content));
|
||||
|
||||
return &newSurf->base;
|
||||
|
||||
|
@ -4467,10 +4487,10 @@ cairo_d2d_surface_create_for_texture(cairo_device_t *device,
|
|||
|
||||
D2D1_ALPHA_MODE alpha = D2D1_ALPHA_MODE_PREMULTIPLIED;
|
||||
if (content == CAIRO_CONTENT_COLOR) {
|
||||
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, CAIRO_CONTENT_COLOR);
|
||||
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, CAIRO_CONTENT_COLOR);
|
||||
alpha = D2D1_ALPHA_MODE_IGNORE;
|
||||
} else {
|
||||
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, content);
|
||||
_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, NULL, content);
|
||||
}
|
||||
|
||||
D2D1_SIZE_U sizePixels;
|
||||
|
@ -4527,9 +4547,7 @@ cairo_d2d_surface_create_for_texture(cairo_device_t *device,
|
|||
|
||||
newSurf->rt->CreateSolidColorBrush(D2D1::ColorF(0, 1.0), &newSurf->solidColorBrush);
|
||||
|
||||
newSurf->device = d2d_device;
|
||||
cairo_addref_device(device);
|
||||
d2d_device->mVRAMUsage += _cairo_d2d_compute_surface_mem_size(newSurf);
|
||||
_cairo_d2d_surface_init(newSurf, d2d_device, _cairo_format_from_content(content));
|
||||
|
||||
return reinterpret_cast<cairo_surface_t*>(newSurf);
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -77,10 +77,14 @@ cairo_debug_reset_static_data (void)
|
|||
|
||||
_cairo_clip_reset_static_data ();
|
||||
|
||||
_cairo_image_reset_static_data ();
|
||||
|
||||
#if CAIRO_HAS_DRM_SURFACE
|
||||
_cairo_drm_device_reset_static_data ();
|
||||
#endif
|
||||
|
||||
_cairo_reset_static_data ();
|
||||
|
||||
CAIRO_MUTEX_FINALIZE ();
|
||||
}
|
||||
|
||||
|
@ -106,10 +110,14 @@ _cairo_debug_check_image_surface_is_defined (const cairo_surface_t *surface)
|
|||
case CAIRO_FORMAT_A8:
|
||||
width = image->width;
|
||||
break;
|
||||
case CAIRO_FORMAT_RGB16_565:
|
||||
width = image->width*2;
|
||||
break;
|
||||
case CAIRO_FORMAT_RGB24:
|
||||
case CAIRO_FORMAT_ARGB32:
|
||||
width = image->width*4;
|
||||
break;
|
||||
case CAIRO_FORMAT_INVALID:
|
||||
default:
|
||||
/* XXX compute width from pixman bpp */
|
||||
return;
|
||||
|
@ -221,6 +229,12 @@ _cairo_debug_print_path (FILE *stream, cairo_path_fixed_t *path)
|
|||
{
|
||||
cairo_status_t status;
|
||||
|
||||
printf ("path: extents=(%f, %f), (%f, %f)\n",
|
||||
_cairo_fixed_to_double (path->extents.p1.x),
|
||||
_cairo_fixed_to_double (path->extents.p1.y),
|
||||
_cairo_fixed_to_double (path->extents.p2.x),
|
||||
_cairo_fixed_to_double (path->extents.p2.y));
|
||||
|
||||
status = _cairo_path_fixed_interpret (path,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_print_move_to,
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -35,6 +35,7 @@
|
|||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-output-stream-private.h"
|
||||
#include <zlib.h>
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -36,20 +36,6 @@
|
|||
#ifndef CAIRO_DEPRECATED_H
|
||||
#define CAIRO_DEPRECATED_H
|
||||
|
||||
/* The %CAIRO_FORMAT_RGB16_565 value was added in cairo 1.2.0 as part
|
||||
* of fixing cairo's xlib backend to work with X servers advertising a
|
||||
* 16-bit, 565 visual. But as it turned out, adding this format to
|
||||
* #cairo_format_t was not necessary, and was a mistake, (cairo's xlib
|
||||
* backend can work fine with 16-bit visuals in the same way it works
|
||||
* with BGR visuals without any BGR formats in
|
||||
* #cairo_format_t).
|
||||
*
|
||||
* Additionally, the support for the RGB16_565 format was never
|
||||
* completely implemented. So while this format value is currently
|
||||
* deprecated, it may eventually acquire complete support in the future.
|
||||
*/
|
||||
/* #define CAIRO_FORMAT_RGB16_565 4 */
|
||||
|
||||
#define CAIRO_FONT_TYPE_ATSUI CAIRO_FONT_TYPE_QUARTZ
|
||||
|
||||
/* Obsolete functions. These definitions exist to coerce the compiler
|
||||
|
@ -123,7 +109,6 @@
|
|||
#define cairo_matrix_copy cairo_matrix_copy_DEPRECATED_BY_cairo_matrix_t
|
||||
#define cairo_matrix_get_affine cairo_matrix_get_affine_DEPRECATED_BY_cairo_matrix_t
|
||||
#define cairo_set_target_surface cairo_set_target_surface_DEPRECATED_BY_cairo_create
|
||||
#define cairo_set_target_glitz cairo_set_target_glitz_DEPRECATED_BY_cairo_glitz_surface_create
|
||||
#define cairo_set_target_image cairo_set_target_image_DEPRECATED_BY_cairo_image_surface_create_for_data
|
||||
#define cairo_set_target_pdf cairo_set_target_pdf_DEPRECATED_BY_cairo_pdf_surface_create
|
||||
#define cairo_set_target_png cairo_set_target_png_DEPRECATED_BY_cairo_surface_write_to_png
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/* Cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2009 Intel Corporation
|
||||
*
|
||||
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Intel Corporation.
|
||||
*
|
||||
* Contributors(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#ifndef _CAIRO_DEVICE_PRIVATE_H_
|
||||
#define _CAIRO_DEVICE_PRIVATE_H_
|
||||
|
||||
#include "cairo-compiler-private.h"
|
||||
#include "cairo-mutex-private.h"
|
||||
#include "cairo-reference-count-private.h"
|
||||
#include "cairo-types-private.h"
|
||||
|
||||
struct _cairo_device {
|
||||
cairo_reference_count_t ref_count;
|
||||
cairo_status_t status;
|
||||
cairo_user_data_array_t user_data;
|
||||
|
||||
const cairo_device_backend_t *backend;
|
||||
|
||||
cairo_recursive_mutex_t mutex;
|
||||
unsigned mutex_depth;
|
||||
|
||||
cairo_bool_t finished;
|
||||
};
|
||||
|
||||
struct _cairo_device_backend {
|
||||
cairo_device_type_t type;
|
||||
|
||||
void (*lock) (void *device);
|
||||
void (*unlock) (void *device);
|
||||
|
||||
cairo_warn cairo_status_t (*flush) (void *device);
|
||||
void (*finish) (void *device);
|
||||
void (*destroy) (void *device);
|
||||
};
|
||||
|
||||
cairo_private cairo_device_t *
|
||||
_cairo_device_create_in_error (cairo_status_t status);
|
||||
|
||||
cairo_private void
|
||||
_cairo_device_init (cairo_device_t *device,
|
||||
const cairo_device_backend_t *backend);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_device_set_error (cairo_device_t *device,
|
||||
cairo_status_t error);
|
||||
|
||||
slim_hidden_proto_no_warn (cairo_device_reference);
|
||||
slim_hidden_proto (cairo_device_acquire);
|
||||
slim_hidden_proto (cairo_device_release);
|
||||
slim_hidden_proto (cairo_device_flush);
|
||||
slim_hidden_proto (cairo_device_finish);
|
||||
slim_hidden_proto (cairo_device_destroy);
|
||||
|
||||
#endif /* _CAIRO_DEVICE_PRIVATE_H_ */
|
|
@ -0,0 +1,533 @@
|
|||
/* Cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2009 Intel Corporation
|
||||
*
|
||||
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Intel Corporation.
|
||||
*
|
||||
* Contributors(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-device-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
/**
|
||||
* SECTION:cairo-device
|
||||
* @Title: cairo_device_t
|
||||
* @Short_Description: interface to underlying rendering system
|
||||
* @See_Also: #cairo_surface_t
|
||||
*
|
||||
* Devices are the abstraction Cairo employs for the rendering system
|
||||
* used by a #cairo_surface_t. You can get the device of a surface using
|
||||
* cairo_surface_get_device().
|
||||
*
|
||||
* Devices are created using custom functions specific to the rendering
|
||||
* system you want to use. See the documentation for the surface types
|
||||
* for those functions.
|
||||
*
|
||||
* An important function that devices fulfill is sharing access to the
|
||||
* rendering system between Cairo and your application. If you want to
|
||||
* access a device directly that you used to draw to with Cairo, you must
|
||||
* first call cairo_device_flush() to ensure that Cairo finishes all
|
||||
* operations on the device and resets it to a clean state.
|
||||
*
|
||||
* Cairo also provides the functions cairo_device_acquire() and
|
||||
* cairo_device_release() to synchronize access to the rendering system
|
||||
* in a multithreaded environment. This is done internally, but can also
|
||||
* be used by applications.
|
||||
*
|
||||
* Putting this all together, a function that works with devices should
|
||||
* look something like this:
|
||||
* <informalexample><programlisting>
|
||||
* void
|
||||
* my_device_modifying_function (cairo_device_t *device)
|
||||
* {
|
||||
* cairo_status_t status;
|
||||
*
|
||||
* // Ensure the device is properly reset
|
||||
* cairo_device_flush (device);
|
||||
* // Try to acquire the device
|
||||
* status = cairo_device_acquire (device);
|
||||
* if (status != CAIRO_STATUS_SUCCESS) {
|
||||
* printf ("Failed to acquire the device: %s\n", cairo_status_to_string (status));
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
* // Do the custom operations on the device here.
|
||||
* // But do not call any Cairo functions that might acquire devices.
|
||||
*
|
||||
* // Release the device when done.
|
||||
* cairo_device_release (device);
|
||||
* }
|
||||
* </programlisting></informalexample>
|
||||
*
|
||||
* <note><para>Please refer to the documentation of each backend for
|
||||
* additional usage requirements, guarantees provided, and
|
||||
* interactions with existing surface API of the device functions for
|
||||
* surfaces of that type.
|
||||
* </para></note>
|
||||
*/
|
||||
|
||||
static const cairo_device_t _nil_device = {
|
||||
CAIRO_REFERENCE_COUNT_INVALID,
|
||||
CAIRO_STATUS_NO_MEMORY,
|
||||
};
|
||||
|
||||
static const cairo_device_t _mismatch_device = {
|
||||
CAIRO_REFERENCE_COUNT_INVALID,
|
||||
CAIRO_STATUS_DEVICE_TYPE_MISMATCH,
|
||||
};
|
||||
|
||||
static const cairo_device_t _invalid_device = {
|
||||
CAIRO_REFERENCE_COUNT_INVALID,
|
||||
CAIRO_STATUS_DEVICE_ERROR,
|
||||
};
|
||||
|
||||
cairo_device_t *
|
||||
_cairo_device_create_in_error (cairo_status_t status)
|
||||
{
|
||||
switch (status) {
|
||||
case CAIRO_STATUS_NO_MEMORY:
|
||||
return (cairo_device_t *) &_nil_device;
|
||||
case CAIRO_STATUS_DEVICE_ERROR:
|
||||
return (cairo_device_t *) &_invalid_device;
|
||||
case CAIRO_STATUS_DEVICE_TYPE_MISMATCH:
|
||||
return (cairo_device_t *) &_mismatch_device;
|
||||
|
||||
case CAIRO_STATUS_SUCCESS:
|
||||
case CAIRO_STATUS_LAST_STATUS:
|
||||
ASSERT_NOT_REACHED;
|
||||
/* fall-through */
|
||||
case CAIRO_STATUS_SURFACE_TYPE_MISMATCH:
|
||||
case CAIRO_STATUS_INVALID_STATUS:
|
||||
case CAIRO_STATUS_INVALID_FORMAT:
|
||||
case CAIRO_STATUS_INVALID_VISUAL:
|
||||
case CAIRO_STATUS_READ_ERROR:
|
||||
case CAIRO_STATUS_WRITE_ERROR:
|
||||
case CAIRO_STATUS_FILE_NOT_FOUND:
|
||||
case CAIRO_STATUS_TEMP_FILE_ERROR:
|
||||
case CAIRO_STATUS_INVALID_STRIDE:
|
||||
case CAIRO_STATUS_INVALID_SIZE:
|
||||
case CAIRO_STATUS_INVALID_RESTORE:
|
||||
case CAIRO_STATUS_INVALID_POP_GROUP:
|
||||
case CAIRO_STATUS_NO_CURRENT_POINT:
|
||||
case CAIRO_STATUS_INVALID_MATRIX:
|
||||
case CAIRO_STATUS_NULL_POINTER:
|
||||
case CAIRO_STATUS_INVALID_STRING:
|
||||
case CAIRO_STATUS_INVALID_PATH_DATA:
|
||||
case CAIRO_STATUS_SURFACE_FINISHED:
|
||||
case CAIRO_STATUS_PATTERN_TYPE_MISMATCH:
|
||||
case CAIRO_STATUS_INVALID_DASH:
|
||||
case CAIRO_STATUS_INVALID_DSC_COMMENT:
|
||||
case CAIRO_STATUS_INVALID_INDEX:
|
||||
case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE:
|
||||
case CAIRO_STATUS_FONT_TYPE_MISMATCH:
|
||||
case CAIRO_STATUS_USER_FONT_IMMUTABLE:
|
||||
case CAIRO_STATUS_USER_FONT_ERROR:
|
||||
case CAIRO_STATUS_NEGATIVE_COUNT:
|
||||
case CAIRO_STATUS_INVALID_CLUSTERS:
|
||||
case CAIRO_STATUS_INVALID_SLANT:
|
||||
case CAIRO_STATUS_INVALID_WEIGHT:
|
||||
case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED:
|
||||
case CAIRO_STATUS_INVALID_CONTENT:
|
||||
default:
|
||||
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_device_t *) &_nil_device;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_device_init (cairo_device_t *device,
|
||||
const cairo_device_backend_t *backend)
|
||||
{
|
||||
CAIRO_REFERENCE_COUNT_INIT (&device->ref_count, 1);
|
||||
device->status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
device->backend = backend;
|
||||
|
||||
CAIRO_RECURSIVE_MUTEX_INIT (device->mutex);
|
||||
device->mutex_depth = 0;
|
||||
|
||||
device->finished = FALSE;
|
||||
|
||||
_cairo_user_data_array_init (&device->user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_device_reference:
|
||||
* @device: a #cairo_device_t
|
||||
*
|
||||
* Increases the reference count on @device by one. This prevents
|
||||
* @device from being destroyed until a matching call to
|
||||
* cairo_device_destroy() is made.
|
||||
*
|
||||
* The number of references to a #cairo_device_t can be get using
|
||||
* cairo_device_get_reference_count().
|
||||
*
|
||||
* Return value: the referenced #cairo_device_t.
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
cairo_device_t *
|
||||
cairo_device_reference (cairo_device_t *device)
|
||||
{
|
||||
if (device == NULL ||
|
||||
CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
|
||||
{
|
||||
return device;
|
||||
}
|
||||
|
||||
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&device->ref_count));
|
||||
_cairo_reference_count_inc (&device->ref_count);
|
||||
|
||||
return device;
|
||||
}
|
||||
slim_hidden_def (cairo_device_reference);
|
||||
|
||||
/**
|
||||
* cairo_device_status:
|
||||
* @device: a #cairo_device_t
|
||||
*
|
||||
* Checks whether an error has previously occurred for this
|
||||
* device.
|
||||
*
|
||||
* Return value: %CAIRO_STATUS_SUCCESS on success or an error code if
|
||||
* the device is in an error state.
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
cairo_status_t
|
||||
cairo_device_status (cairo_device_t *device)
|
||||
{
|
||||
if (device == NULL)
|
||||
return CAIRO_STATUS_NULL_POINTER;
|
||||
|
||||
return device->status;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_device_flush:
|
||||
* @device: a #cairo_device_t
|
||||
*
|
||||
* Finish any pending operations for the device and also restore any
|
||||
* temporary modifications cairo has made to the device's state.
|
||||
* This function must be called before switching from using the
|
||||
* device with Cairo to operating on it directly with native APIs.
|
||||
* If the device doesn't support direct access, then this function
|
||||
* does nothing.
|
||||
*
|
||||
* This function may acquire devices.
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
void
|
||||
cairo_device_flush (cairo_device_t *device)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (device == NULL || device->status)
|
||||
return;
|
||||
|
||||
if (device->backend->flush != NULL) {
|
||||
status = device->backend->flush (device);
|
||||
if (unlikely (status))
|
||||
status = _cairo_device_set_error (device, status);
|
||||
}
|
||||
}
|
||||
slim_hidden_def (cairo_device_flush);
|
||||
|
||||
/**
|
||||
* cairo_device_finish:
|
||||
* @device: the #cairo_device_t to finish
|
||||
*
|
||||
* This function finishes the device and drops all references to
|
||||
* external resources. All surfaces, fonts and other objects created
|
||||
* for this @device will be finished, too.
|
||||
* Further operations on the @device will not affect the @device but
|
||||
* will instead trigger a %CAIRO_STATUS_DEVICE_FINISHED error.
|
||||
*
|
||||
* When the last call to cairo_device_destroy() decreases the
|
||||
* reference count to zero, cairo will call cairo_device_finish() if
|
||||
* it hasn't been called already, before freeing the resources
|
||||
* associated with the device.
|
||||
*
|
||||
* This function may acquire devices.
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
void
|
||||
cairo_device_finish (cairo_device_t *device)
|
||||
{
|
||||
if (device == NULL ||
|
||||
CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->finished)
|
||||
return;
|
||||
|
||||
cairo_device_flush (device);
|
||||
|
||||
device->finished = TRUE;
|
||||
|
||||
if (device->backend->finish != NULL)
|
||||
device->backend->finish (device);
|
||||
}
|
||||
slim_hidden_def (cairo_device_finish);
|
||||
|
||||
/**
|
||||
* cairo_device_destroy:
|
||||
* @device: a #cairo_device_t
|
||||
*
|
||||
* Decreases the reference count on @device by one. If the result is
|
||||
* zero, then @device and all associated resources are freed. See
|
||||
* cairo_device_reference().
|
||||
*
|
||||
* This function may acquire devices if the last reference was dropped.
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
void
|
||||
cairo_device_destroy (cairo_device_t *device)
|
||||
{
|
||||
cairo_user_data_array_t user_data;
|
||||
|
||||
if (device == NULL ||
|
||||
CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&device->ref_count));
|
||||
if (! _cairo_reference_count_dec_and_test (&device->ref_count))
|
||||
return;
|
||||
|
||||
cairo_device_finish (device);
|
||||
|
||||
assert (device->mutex_depth == 0);
|
||||
CAIRO_MUTEX_FINI (device->mutex);
|
||||
|
||||
user_data = device->user_data;
|
||||
|
||||
device->backend->destroy (device);
|
||||
|
||||
_cairo_user_data_array_fini (&user_data);
|
||||
|
||||
}
|
||||
slim_hidden_def (cairo_device_destroy);
|
||||
|
||||
/**
|
||||
* cairo_device_get_type:
|
||||
* @device: a #cairo_device_t
|
||||
*
|
||||
* This function returns the type of the device. See #cairo_device_type_t
|
||||
* for available types.
|
||||
*
|
||||
* Return value: The type of @device.
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
cairo_device_type_t
|
||||
cairo_device_get_type (cairo_device_t *device)
|
||||
{
|
||||
if (device == NULL ||
|
||||
CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
|
||||
{
|
||||
return (cairo_device_type_t) -1;
|
||||
}
|
||||
|
||||
return device->backend->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_device_acquire:
|
||||
* @device: a #cairo_device_t
|
||||
*
|
||||
* Acquires the @device for the current thread. This function will block
|
||||
* until no other thread has acquired the device.
|
||||
*
|
||||
* If the return value is %CAIRO_STATUS_SUCCESS, you successfully acquired the
|
||||
* device. From now on your thread owns the device and no other thread will be
|
||||
* able to acquire it until a matching call to cairo_device_release(). It is
|
||||
* allowed to recursively acquire the device multiple times from the same
|
||||
* thread.
|
||||
*
|
||||
* <note><para>You must never acquire two different devices at the same time
|
||||
* unless this is explicitly allowed. Otherwise the possibility of deadlocks
|
||||
* exist.
|
||||
*
|
||||
* As various Cairo functions can acquire devices when called, these functions
|
||||
* may also cause deadlocks when you call them with an acquired device. So you
|
||||
* must not have a device acquired when calling them. These functions are
|
||||
* marked in the documentation.
|
||||
* </para></note>
|
||||
*
|
||||
* Return value: %CAIRO_STATUS_SUCCESS on success or an error code if
|
||||
* the device is in an error state and could not be
|
||||
* acquired. After a successful call to cairo_device_acquire(),
|
||||
* a matching call to cairo_device_release() is required.
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
cairo_status_t
|
||||
cairo_device_acquire (cairo_device_t *device)
|
||||
{
|
||||
if (device == NULL)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (unlikely (device->status))
|
||||
return device->status;
|
||||
|
||||
if (unlikely (device->finished))
|
||||
return _cairo_device_set_error (device, CAIRO_STATUS_SURFACE_FINISHED); /* XXX */
|
||||
|
||||
CAIRO_MUTEX_LOCK (device->mutex);
|
||||
if (device->mutex_depth++ == 0) {
|
||||
if (device->backend->lock != NULL)
|
||||
device->backend->lock (device);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
slim_hidden_def (cairo_device_acquire);
|
||||
|
||||
/**
|
||||
* cairo_device_release:
|
||||
* @device: a #cairo_device_t
|
||||
*
|
||||
* Releases a @device previously acquired using cairo_device_acquire(). See
|
||||
* that function for details.
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
void
|
||||
cairo_device_release (cairo_device_t *device)
|
||||
{
|
||||
if (device == NULL)
|
||||
return;
|
||||
|
||||
assert (device->mutex_depth > 0);
|
||||
|
||||
if (--device->mutex_depth == 0) {
|
||||
if (device->backend->unlock != NULL)
|
||||
device->backend->unlock (device);
|
||||
}
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (device->mutex);
|
||||
}
|
||||
slim_hidden_def (cairo_device_release);
|
||||
|
||||
cairo_status_t
|
||||
_cairo_device_set_error (cairo_device_t *device,
|
||||
cairo_status_t status)
|
||||
{
|
||||
if (status == CAIRO_STATUS_SUCCESS || status >= CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return status;
|
||||
|
||||
/* Don't overwrite an existing error. This preserves the first
|
||||
* error, which is the most significant. */
|
||||
_cairo_status_set_error (&device->status, status);
|
||||
|
||||
return _cairo_error (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_device_get_reference_count:
|
||||
* @device: a #cairo_device_t
|
||||
*
|
||||
* Returns the current reference count of @device.
|
||||
*
|
||||
* Return value: the current reference count of @device. If the
|
||||
* object is a nil object, 0 will be returned.
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
unsigned int
|
||||
cairo_device_get_reference_count (cairo_device_t *device)
|
||||
{
|
||||
if (device == NULL ||
|
||||
CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
|
||||
return 0;
|
||||
|
||||
return CAIRO_REFERENCE_COUNT_GET_VALUE (&device->ref_count);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_device_get_user_data:
|
||||
* @device: a #cairo_device_t
|
||||
* @key: the address of the #cairo_user_data_key_t the user data was
|
||||
* attached to
|
||||
*
|
||||
* Return user data previously attached to @device using the
|
||||
* specified key. If no user data has been attached with the given
|
||||
* key this function returns %NULL.
|
||||
*
|
||||
* Return value: the user data previously attached or %NULL.
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
void *
|
||||
cairo_device_get_user_data (cairo_device_t *device,
|
||||
const cairo_user_data_key_t *key)
|
||||
{
|
||||
return _cairo_user_data_array_get_data (&device->user_data,
|
||||
key);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_device_set_user_data:
|
||||
* @device: a #cairo_device_t
|
||||
* @key: the address of a #cairo_user_data_key_t to attach the user data to
|
||||
* @user_data: the user data to attach to the #cairo_device_t
|
||||
* @destroy: a #cairo_destroy_func_t which will be called when the
|
||||
* #cairo_t is destroyed or when new user data is attached using the
|
||||
* same key.
|
||||
*
|
||||
* Attach user data to @device. To remove user data from a surface,
|
||||
* call this function with the key that was used to set it and %NULL
|
||||
* for @data.
|
||||
*
|
||||
* Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
|
||||
* slot could not be allocated for the user data.
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
cairo_status_t
|
||||
cairo_device_set_user_data (cairo_device_t *device,
|
||||
const cairo_user_data_key_t *key,
|
||||
void *user_data,
|
||||
cairo_destroy_func_t destroy)
|
||||
{
|
||||
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
|
||||
return device->status;
|
||||
|
||||
return _cairo_user_data_array_set_data (&device->user_data,
|
||||
key, user_data, destroy);
|
||||
}
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -39,6 +39,7 @@
|
|||
#include "cairo-directfb.h"
|
||||
|
||||
#include "cairo-clip-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
#include <pixman.h>
|
||||
|
||||
|
@ -564,6 +565,7 @@ _cairo_directfb_surface_create_internal (IDirectFB *dfb,
|
|||
|
||||
_cairo_surface_init (&surface->base,
|
||||
&_cairo_directfb_surface_backend,
|
||||
NULL, /* device */
|
||||
content);
|
||||
surface->pixman_format = _directfb_to_pixman_format (format);
|
||||
surface->supported_destination = pixman_format_supported_destination (surface->pixman_format);
|
||||
|
@ -762,14 +764,14 @@ _cairo_directfb_surface_clone_similar (void *abstract_surface,
|
|||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
pixman_image_composite (PIXMAN_OP_SRC,
|
||||
image_src->pixman_image,
|
||||
NULL,
|
||||
pixman_image,
|
||||
src_x, src_y,
|
||||
0, 0,
|
||||
0, 0,
|
||||
width, height);
|
||||
pixman_image_composite32 (PIXMAN_OP_SRC,
|
||||
image_src->pixman_image,
|
||||
NULL,
|
||||
pixman_image,
|
||||
src_x, src_y,
|
||||
0, 0,
|
||||
0, 0,
|
||||
width, height);
|
||||
|
||||
pixman_image_unref (pixman_image);
|
||||
|
||||
|
@ -1814,7 +1816,7 @@ _cairo_directfb_surface_show_glyphs (void *abstract_dst,
|
|||
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_directfb_surface_is_similar (void *surface_a, void *surface_b, cairo_content_t content)
|
||||
_cairo_directfb_surface_is_similar (void *surface_a, void *surface_b)
|
||||
{
|
||||
cairo_directfb_surface_t *a = (cairo_directfb_surface_t *) surface_a;
|
||||
cairo_directfb_surface_t *b = (cairo_directfb_surface_t *) surface_b;
|
||||
|
@ -1955,6 +1957,7 @@ cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *dfbsurface)
|
|||
|
||||
_cairo_surface_init (&surface->base,
|
||||
&_cairo_directfb_surface_backend,
|
||||
NULL, /* device */
|
||||
_directfb_format_to_content (format));
|
||||
|
||||
return &surface->base;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -39,56 +39,41 @@
|
|||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
typedef struct _cairo_drm_device cairo_drm_device_t;
|
||||
|
||||
struct udev_device;
|
||||
|
||||
cairo_public cairo_drm_device_t *
|
||||
cairo_public cairo_device_t *
|
||||
cairo_drm_device_get (struct udev_device *device);
|
||||
|
||||
cairo_public cairo_drm_device_t *
|
||||
cairo_public cairo_device_t *
|
||||
cairo_drm_device_get_for_fd (int fd);
|
||||
|
||||
cairo_public cairo_drm_device_t *
|
||||
cairo_public cairo_device_t *
|
||||
cairo_drm_device_default (void);
|
||||
|
||||
cairo_public cairo_drm_device_t *
|
||||
cairo_drm_device_reference (cairo_drm_device_t *device);
|
||||
|
||||
cairo_public cairo_status_t
|
||||
cairo_drm_device_status (cairo_drm_device_t *device);
|
||||
|
||||
cairo_public int
|
||||
cairo_drm_device_get_fd (cairo_drm_device_t *device);
|
||||
cairo_drm_device_get_fd (cairo_device_t *device);
|
||||
|
||||
cairo_public void
|
||||
cairo_drm_device_throttle (cairo_drm_device_t *device);
|
||||
|
||||
cairo_public void
|
||||
cairo_drm_device_destroy (cairo_drm_device_t *device);
|
||||
|
||||
cairo_drm_device_throttle (cairo_device_t *device);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_drm_surface_create (cairo_drm_device_t *device,
|
||||
cairo_content_t content,
|
||||
cairo_drm_surface_create (cairo_device_t *device,
|
||||
cairo_format_t format,
|
||||
int width, int height);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_drm_surface_create_for_name (cairo_drm_device_t *device,
|
||||
cairo_drm_surface_create_for_name (cairo_device_t *device,
|
||||
unsigned int name,
|
||||
cairo_format_t format,
|
||||
int width, int height, int stride);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_drm_surface_create_from_cacheable_image (cairo_drm_device_t *device,
|
||||
cairo_drm_surface_create_from_cacheable_image (cairo_device_t *device,
|
||||
cairo_surface_t *surface);
|
||||
|
||||
cairo_public cairo_status_t
|
||||
cairo_drm_surface_enable_scan_out (cairo_surface_t *surface);
|
||||
|
||||
cairo_public cairo_drm_device_t *
|
||||
cairo_drm_surface_get_device (cairo_surface_t *abstract_surface);
|
||||
|
||||
cairo_public unsigned int
|
||||
cairo_drm_surface_get_handle (cairo_surface_t *surface);
|
||||
|
||||
|
@ -120,7 +105,7 @@ cairo_drm_surface_get_stride (cairo_surface_t *surface);
|
|||
* will also disassociate the mapping.)
|
||||
*/
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_drm_surface_map (cairo_surface_t *surface);
|
||||
cairo_drm_surface_map_to_image (cairo_surface_t *surface);
|
||||
|
||||
cairo_public void
|
||||
cairo_drm_surface_unmap (cairo_surface_t *drm_surface,
|
||||
|
|
|
@ -34,13 +34,12 @@
|
|||
* Bas Schouten <bschouten@mozilla.com>
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-win32-private.h"
|
||||
#include "cairo-surface-private.h"
|
||||
#include "cairo-clip-private.h"
|
||||
}
|
||||
|
||||
#include "cairo-d2d-private.h"
|
||||
#include "cairo-dwrite-private.h"
|
||||
#include <float.h>
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2002 University of Southern California
|
||||
* Copyright © 2005 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 University of Southern
|
||||
* California.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#ifndef _CAIRO_ERROR_PRIVATE_H_
|
||||
#define _CAIRO_ERROR_PRIVATE_H_
|
||||
|
||||
#include "cairo.h"
|
||||
#include "cairo-compiler-private.h"
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
#define _cairo_status_is_error(status) \
|
||||
(status != CAIRO_STATUS_SUCCESS && status <= CAIRO_STATUS_LAST_STATUS)
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_error (cairo_status_t status);
|
||||
|
||||
/* hide compiler warnings when discarding the return value */
|
||||
#define _cairo_error_throw(status) do { \
|
||||
cairo_status_t status__ = _cairo_error (status); \
|
||||
(void) status__; \
|
||||
} while (0)
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#endif /* _CAIRO_ERROR_PRIVATE_H_ */
|
|
@ -89,6 +89,8 @@
|
|||
|
||||
@QUARTZ_FONT_FEATURE@
|
||||
|
||||
@TEE_SURFACE_FEATURE@
|
||||
|
||||
@PNG_FUNCTIONS_FEATURE@
|
||||
|
||||
@FC_FONT_FEATURE@
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -53,7 +53,7 @@
|
|||
#define CAIRO_FIXED_ONE_FLOAT ((float)(1 << CAIRO_FIXED_FRAC_BITS))
|
||||
#define CAIRO_FIXED_EPSILON ((cairo_fixed_t)(1))
|
||||
|
||||
#define CAIRO_FIXED_FRAC_MASK (((cairo_fixed_unsigned_t)(-1)) >> (CAIRO_FIXED_BITS - CAIRO_FIXED_FRAC_BITS))
|
||||
#define CAIRO_FIXED_FRAC_MASK ((cairo_fixed_t)(((cairo_fixed_unsigned_t)(-1)) >> (CAIRO_FIXED_BITS - CAIRO_FIXED_FRAC_BITS)))
|
||||
#define CAIRO_FIXED_WHOLE_MASK (~CAIRO_FIXED_FRAC_MASK)
|
||||
|
||||
static inline cairo_fixed_t
|
||||
|
@ -136,6 +136,16 @@ _cairo_fixed_from_26_6 (uint32_t i)
|
|||
#endif
|
||||
}
|
||||
|
||||
static inline cairo_fixed_t
|
||||
_cairo_fixed_from_16_16 (uint32_t i)
|
||||
{
|
||||
#if CAIRO_FIXED_FRAC_BITS > 16
|
||||
return i << (CAIRO_FIXED_FRAC_BITS - 16);
|
||||
#else
|
||||
return i >> (16 - CAIRO_FIXED_FRAC_BITS);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline double
|
||||
_cairo_fixed_to_double (cairo_fixed_t f)
|
||||
{
|
||||
|
@ -154,12 +164,48 @@ _cairo_fixed_is_integer (cairo_fixed_t f)
|
|||
return (f & CAIRO_FIXED_FRAC_MASK) == 0;
|
||||
}
|
||||
|
||||
static inline cairo_fixed_t
|
||||
_cairo_fixed_floor (cairo_fixed_t f)
|
||||
{
|
||||
return f & ~CAIRO_FIXED_FRAC_MASK;
|
||||
}
|
||||
|
||||
static inline cairo_fixed_t
|
||||
_cairo_fixed_round (cairo_fixed_t f)
|
||||
{
|
||||
return _cairo_fixed_floor (f + (CAIRO_FIXED_FRAC_MASK+1)/2);
|
||||
}
|
||||
|
||||
static inline cairo_fixed_t
|
||||
_cairo_fixed_round_down (cairo_fixed_t f)
|
||||
{
|
||||
return _cairo_fixed_floor (f + CAIRO_FIXED_FRAC_MASK/2);
|
||||
}
|
||||
|
||||
static inline int
|
||||
_cairo_fixed_integer_part (cairo_fixed_t f)
|
||||
{
|
||||
return f >> CAIRO_FIXED_FRAC_BITS;
|
||||
}
|
||||
|
||||
static inline int
|
||||
_cairo_fixed_integer_round (cairo_fixed_t f)
|
||||
{
|
||||
return _cairo_fixed_integer_part (f + (CAIRO_FIXED_FRAC_MASK+1)/2);
|
||||
}
|
||||
|
||||
static inline int
|
||||
_cairo_fixed_integer_round_down (cairo_fixed_t f)
|
||||
{
|
||||
return _cairo_fixed_integer_part (f + CAIRO_FIXED_FRAC_MASK/2);
|
||||
}
|
||||
|
||||
static inline int
|
||||
_cairo_fixed_fractional_part (cairo_fixed_t f)
|
||||
{
|
||||
return f & CAIRO_FIXED_FRAC_MASK;
|
||||
}
|
||||
|
||||
static inline int
|
||||
_cairo_fixed_integer_floor (cairo_fixed_t f)
|
||||
{
|
||||
|
@ -225,12 +271,18 @@ _cairo_fixed_16_16_from_double (double d)
|
|||
}
|
||||
|
||||
static inline int
|
||||
_cairo_fixed_16_16_floor (cairo_fixed_t f)
|
||||
_cairo_fixed_16_16_floor (cairo_fixed_16_16_t f)
|
||||
{
|
||||
if (f >= 0)
|
||||
return f >> 16;
|
||||
return f >> 16;
|
||||
else
|
||||
return -((-f - 1) >> 16) - 1;
|
||||
return -((-f - 1) >> 16) - 1;
|
||||
}
|
||||
|
||||
static inline double
|
||||
_cairo_fixed_16_16_to_double (cairo_fixed_16_16_t f)
|
||||
{
|
||||
return ((double) f) / (double) (1 << 16);
|
||||
}
|
||||
|
||||
#if CAIRO_FIXED_BITS == 32
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -35,6 +35,7 @@
|
|||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -39,6 +39,24 @@
|
|||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
/**
|
||||
* SECTION:cairo-font-face
|
||||
* @Title: cairo_font_face_t
|
||||
* @Short_Description: Base class for font faces
|
||||
* @See_Also: #cairo_scaled_font_t
|
||||
*
|
||||
* #cairo_font_face_t represents a particular font at a particular weight,
|
||||
* slant, and other characteristic but no size, transformation, or size.
|
||||
*
|
||||
* Font faces are created using <firstterm>font-backend</firstterm>-specific
|
||||
* constructors, typically of the form
|
||||
* cairo_<emphasis>backend</emphasis>_font_face_create(), or implicitly
|
||||
* using the <firstterm>toy</firstterm> text API by way of
|
||||
* cairo_select_font_face(). The resulting face can be accessed using
|
||||
* cairo_get_font_face().
|
||||
*/
|
||||
|
||||
/* #cairo_font_face_t */
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -35,12 +35,27 @@
|
|||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
/**
|
||||
* SECTION:cairo-font-options
|
||||
* @Title: cairo_font_options_t
|
||||
* @Short_Description: How a font should be rendered
|
||||
* @See_Also: #cairo_scaled_font_t
|
||||
*
|
||||
* The font options specify how fonts should be rendered. Most of the
|
||||
* time the font options implied by a surface are just right and do not
|
||||
* need any changes, but for pixel-based targets tweaking font options
|
||||
* may result in superior output on a particular display.
|
||||
*/
|
||||
|
||||
static const cairo_font_options_t _cairo_font_options_nil = {
|
||||
CAIRO_ANTIALIAS_DEFAULT,
|
||||
CAIRO_SUBPIXEL_ORDER_DEFAULT,
|
||||
CAIRO_LCD_FILTER_DEFAULT,
|
||||
CAIRO_HINT_STYLE_DEFAULT,
|
||||
CAIRO_HINT_METRICS_DEFAULT
|
||||
CAIRO_HINT_METRICS_DEFAULT,
|
||||
CAIRO_ROUND_GLYPH_POS_DEFAULT
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -54,8 +69,10 @@ _cairo_font_options_init_default (cairo_font_options_t *options)
|
|||
{
|
||||
options->antialias = CAIRO_ANTIALIAS_DEFAULT;
|
||||
options->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
|
||||
options->lcd_filter = CAIRO_LCD_FILTER_DEFAULT;
|
||||
options->hint_style = CAIRO_HINT_STYLE_DEFAULT;
|
||||
options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT;
|
||||
options->round_glyph_positions = CAIRO_ROUND_GLYPH_POS_DEFAULT;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -64,8 +81,10 @@ _cairo_font_options_init_copy (cairo_font_options_t *options,
|
|||
{
|
||||
options->antialias = other->antialias;
|
||||
options->subpixel_order = other->subpixel_order;
|
||||
options->lcd_filter = other->lcd_filter;
|
||||
options->hint_style = other->hint_style;
|
||||
options->hint_metrics = other->hint_metrics;
|
||||
options->round_glyph_positions = other->round_glyph_positions;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -189,10 +208,14 @@ cairo_font_options_merge (cairo_font_options_t *options,
|
|||
options->antialias = other->antialias;
|
||||
if (other->subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT)
|
||||
options->subpixel_order = other->subpixel_order;
|
||||
if (other->lcd_filter != CAIRO_LCD_FILTER_DEFAULT)
|
||||
options->lcd_filter = other->lcd_filter;
|
||||
if (other->hint_style != CAIRO_HINT_STYLE_DEFAULT)
|
||||
options->hint_style = other->hint_style;
|
||||
if (other->hint_metrics != CAIRO_HINT_METRICS_DEFAULT)
|
||||
options->hint_metrics = other->hint_metrics;
|
||||
if (other->round_glyph_positions != CAIRO_ROUND_GLYPH_POS_DEFAULT)
|
||||
options->round_glyph_positions = other->round_glyph_positions;
|
||||
}
|
||||
slim_hidden_def (cairo_font_options_merge);
|
||||
|
||||
|
@ -221,8 +244,10 @@ cairo_font_options_equal (const cairo_font_options_t *options,
|
|||
|
||||
return (options->antialias == other->antialias &&
|
||||
options->subpixel_order == other->subpixel_order &&
|
||||
options->lcd_filter == other->lcd_filter &&
|
||||
options->hint_style == other->hint_style &&
|
||||
options->hint_metrics == other->hint_metrics);
|
||||
options->hint_metrics == other->hint_metrics &&
|
||||
options->round_glyph_positions == other->round_glyph_positions);
|
||||
}
|
||||
slim_hidden_def (cairo_font_options_equal);
|
||||
|
||||
|
@ -246,7 +271,8 @@ cairo_font_options_hash (const cairo_font_options_t *options)
|
|||
|
||||
return ((options->antialias) |
|
||||
(options->subpixel_order << 4) |
|
||||
(options->hint_style << 8) |
|
||||
(options->lcd_filter << 8) |
|
||||
(options->hint_style << 12) |
|
||||
(options->hint_metrics << 16));
|
||||
}
|
||||
slim_hidden_def (cairo_font_options_hash);
|
||||
|
@ -327,6 +353,87 @@ cairo_font_options_get_subpixel_order (const cairo_font_options_t *options)
|
|||
return options->subpixel_order;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_font_options_set_lcd_filter:
|
||||
* @options: a #cairo_font_options_t
|
||||
* @lcd_filter: the new LCD filter
|
||||
*
|
||||
* Sets the LCD filter for the font options object. The LCD filter
|
||||
* specifies how pixels are filtered when rendered with an antialiasing
|
||||
* mode of %CAIRO_ANTIALIAS_SUBPIXEL. See the documentation for
|
||||
* #cairo_lcd_filter_t for full details.
|
||||
*
|
||||
* Since: 1.8
|
||||
**/
|
||||
void
|
||||
_cairo_font_options_set_lcd_filter (cairo_font_options_t *options,
|
||||
cairo_lcd_filter_t lcd_filter)
|
||||
{
|
||||
if (cairo_font_options_status (options))
|
||||
return;
|
||||
|
||||
options->lcd_filter = lcd_filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_font_options_get_lcd_filter:
|
||||
* @options: a #cairo_font_options_t
|
||||
*
|
||||
* Gets the LCD filter for the font options object.
|
||||
* See the documentation for #cairo_lcd_filter_t for full details.
|
||||
*
|
||||
* Return value: the LCD filter for the font options object
|
||||
*
|
||||
* Since: 1.8
|
||||
**/
|
||||
cairo_lcd_filter_t
|
||||
_cairo_font_options_get_lcd_filter (const cairo_font_options_t *options)
|
||||
{
|
||||
if (cairo_font_options_status ((cairo_font_options_t *) options))
|
||||
return CAIRO_LCD_FILTER_DEFAULT;
|
||||
|
||||
return options->lcd_filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_font_options_set_round_glyph_positions:
|
||||
* @options: a #cairo_font_options_t
|
||||
* @round: the new rounding value
|
||||
*
|
||||
* Sets the rounding options for the font options object. If rounding is set, a
|
||||
* glyph's position will be rounded to integer values.
|
||||
*
|
||||
* Since: 1.12
|
||||
**/
|
||||
void
|
||||
_cairo_font_options_set_round_glyph_positions (cairo_font_options_t *options,
|
||||
cairo_round_glyph_positions_t round)
|
||||
{
|
||||
if (cairo_font_options_status (options))
|
||||
return;
|
||||
|
||||
options->round_glyph_positions = round;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_font_options_get_round_glyph_positions:
|
||||
* @options: a #cairo_font_options_t
|
||||
*
|
||||
* Gets the glyph position rounding option for the font options object.
|
||||
*
|
||||
* Return value: The round glyph posistions flag for the font options object.
|
||||
*
|
||||
* Since: 1.12
|
||||
**/
|
||||
cairo_round_glyph_positions_t
|
||||
_cairo_font_options_get_round_glyph_positions (const cairo_font_options_t *options)
|
||||
{
|
||||
if (cairo_font_options_status ((cairo_font_options_t *) options))
|
||||
return CAIRO_ROUND_GLYPH_POS_DEFAULT;
|
||||
|
||||
return options->round_glyph_positions;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_font_options_set_hint_style:
|
||||
* @options: a #cairo_font_options_t
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2000 Keith Packard
|
||||
* Copyright © 2005 Red Hat, Inc
|
||||
* Copyright © 2010 Intel Corporation
|
||||
*
|
||||
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Red Hat, Inc.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Graydon Hoare <graydon@redhat.com>
|
||||
* Owen Taylor <otaylor@redhat.com>
|
||||
* Keith Packard <keithp@keithp.com>
|
||||
* Carl Worth <cworth@cworth.org>
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#ifndef _CAIRO_FONTCONFIG_PRIVATE_H
|
||||
#define _CAIRO_FONTCONFIG_PRIVATE_H
|
||||
|
||||
#include "cairo.h"
|
||||
|
||||
#if CAIRO_HAS_FC_FONT
|
||||
#include <fontconfig/fontconfig.h>
|
||||
#include <fontconfig/fcfreetype.h>
|
||||
#endif
|
||||
|
||||
/* sub-pixel order */
|
||||
#ifndef FC_RGBA_UNKNOWN
|
||||
#define FC_RGBA_UNKNOWN 0
|
||||
#define FC_RGBA_RGB 1
|
||||
#define FC_RGBA_BGR 2
|
||||
#define FC_RGBA_VRGB 3
|
||||
#define FC_RGBA_VBGR 4
|
||||
#define FC_RGBA_NONE 5
|
||||
#endif
|
||||
|
||||
/* hinting style */
|
||||
#ifndef FC_HINT_NONE
|
||||
#define FC_HINT_NONE 0
|
||||
#define FC_HINT_SLIGHT 1
|
||||
#define FC_HINT_MEDIUM 2
|
||||
#define FC_HINT_FULL 3
|
||||
#endif
|
||||
|
||||
/* LCD filter */
|
||||
#ifndef FC_LCD_NONE
|
||||
#define FC_LCD_NONE 0
|
||||
#define FC_LCD_DEFAULT 1
|
||||
#define FC_LCD_LIGHT 2
|
||||
#define FC_LCD_LEGACY 3
|
||||
#endif
|
||||
|
||||
#endif /* _CAIRO_FONTCONFIG_PRIVATE_H */
|
|
@ -0,0 +1,129 @@
|
|||
/* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 University of Southern
|
||||
* California.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_FREED_POOL_H
|
||||
#define CAIRO_FREED_POOL_H
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-atomic-private.h"
|
||||
|
||||
#if HAS_ATOMIC_OPS
|
||||
/* Keep a stash of recently freed clip_paths, since we need to
|
||||
* reallocate them frequently.
|
||||
*/
|
||||
#define MAX_FREED_POOL_SIZE 4
|
||||
typedef struct {
|
||||
void *pool[MAX_FREED_POOL_SIZE];
|
||||
int top;
|
||||
} freed_pool_t;
|
||||
|
||||
static cairo_always_inline void *
|
||||
_atomic_fetch (void **slot)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
do {
|
||||
ptr = _cairo_atomic_ptr_get (slot);
|
||||
} while (! _cairo_atomic_ptr_cmpxchg (slot, ptr, NULL));
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static cairo_always_inline cairo_bool_t
|
||||
_atomic_store (void **slot, void *ptr)
|
||||
{
|
||||
return _cairo_atomic_ptr_cmpxchg (slot, NULL, ptr);
|
||||
}
|
||||
|
||||
cairo_private void *
|
||||
_freed_pool_get_search (freed_pool_t *pool);
|
||||
|
||||
static inline void *
|
||||
_freed_pool_get (freed_pool_t *pool)
|
||||
{
|
||||
void *ptr;
|
||||
int i;
|
||||
|
||||
i = pool->top - 1;
|
||||
if (i < 0)
|
||||
i = 0;
|
||||
|
||||
ptr = _atomic_fetch (&pool->pool[i]);
|
||||
if (likely (ptr != NULL)) {
|
||||
pool->top = i;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* either empty or contended */
|
||||
return _freed_pool_get_search (pool);
|
||||
}
|
||||
|
||||
cairo_private void
|
||||
_freed_pool_put_search (freed_pool_t *pool, void *ptr);
|
||||
|
||||
static inline void
|
||||
_freed_pool_put (freed_pool_t *pool, void *ptr)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = pool->top;
|
||||
if (likely (i < ARRAY_LENGTH (pool->pool) &&
|
||||
_atomic_store (&pool->pool[i], ptr)))
|
||||
{
|
||||
pool->top = i + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* either full or contended */
|
||||
_freed_pool_put_search (pool, ptr);
|
||||
}
|
||||
|
||||
cairo_private void
|
||||
_freed_pool_reset (freed_pool_t *pool);
|
||||
|
||||
#define HAS_FREED_POOL 1
|
||||
|
||||
#else
|
||||
|
||||
typedef int freed_pool_t;
|
||||
|
||||
#define _freed_pool_get(pool) NULL
|
||||
#define _freed_pool_put(pool, ptr) free(ptr)
|
||||
#define _freed_pool_reset(ptr)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* CAIRO_FREED_POOL_PRIVATE_H */
|
|
@ -0,0 +1,93 @@
|
|||
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
|
||||
/* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 University of Southern
|
||||
* California.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-freed-pool-private.h"
|
||||
|
||||
#if HAS_FREED_POOL
|
||||
|
||||
void *
|
||||
_freed_pool_get_search (freed_pool_t *pool)
|
||||
{
|
||||
void *ptr;
|
||||
int i;
|
||||
|
||||
for (i = ARRAY_LENGTH (pool->pool); i--;) {
|
||||
ptr = _atomic_fetch (&pool->pool[i]);
|
||||
if (ptr != NULL) {
|
||||
pool->top = i;
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* empty */
|
||||
pool->top = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
_freed_pool_put_search (freed_pool_t *pool, void *ptr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) {
|
||||
if (_atomic_store (&pool->pool[i], ptr)) {
|
||||
pool->top = i + 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* full */
|
||||
pool->top = i;
|
||||
free (ptr);
|
||||
}
|
||||
|
||||
void
|
||||
_freed_pool_reset (freed_pool_t *pool)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) {
|
||||
free (pool->pool[i]);
|
||||
pool->pool[i] = NULL;
|
||||
}
|
||||
|
||||
pool->top = 0;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "cairo-types-private.h"
|
||||
#include "cairo-compiler-private.h"
|
||||
#include "cairo-freelist-type-private.h"
|
||||
|
||||
/* for stand-alone compilation*/
|
||||
#ifndef VG
|
||||
|
@ -34,32 +35,6 @@
|
|||
#define NULL (void *) 0
|
||||
#endif
|
||||
|
||||
typedef struct _cairo_freelist_node cairo_freelist_node_t;
|
||||
struct _cairo_freelist_node {
|
||||
cairo_freelist_node_t *next;
|
||||
};
|
||||
|
||||
typedef struct _cairo_freelist {
|
||||
cairo_freelist_node_t *first_free_node;
|
||||
unsigned nodesize;
|
||||
} cairo_freelist_t;
|
||||
|
||||
typedef struct _cairo_freelist_pool cairo_freelist_pool_t;
|
||||
struct _cairo_freelist_pool {
|
||||
cairo_freelist_pool_t *next;
|
||||
unsigned size, rem;
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
typedef struct _cairo_freepool {
|
||||
cairo_freelist_node_t *first_free_node;
|
||||
cairo_freelist_pool_t *pools;
|
||||
unsigned nodesize;
|
||||
cairo_freelist_pool_t embedded_pool;
|
||||
uint8_t embedded_data[1000];
|
||||
} cairo_freepool_t;
|
||||
|
||||
|
||||
/* Initialise a freelist that will be responsible for allocating
|
||||
* nodes of size nodesize. */
|
||||
cairo_private void
|
||||
|
@ -96,6 +71,20 @@ _cairo_freepool_init (cairo_freepool_t *freepool, unsigned nodesize);
|
|||
cairo_private void
|
||||
_cairo_freepool_fini (cairo_freepool_t *freepool);
|
||||
|
||||
static inline void
|
||||
_cairo_freepool_reset (cairo_freepool_t *freepool)
|
||||
{
|
||||
while (freepool->pools != &freepool->embedded_pool) {
|
||||
cairo_freelist_pool_t *pool = freepool->pools;
|
||||
freepool->pools = pool->next;
|
||||
pool->next = freepool->freepools;
|
||||
freepool->freepools = pool;
|
||||
}
|
||||
|
||||
freepool->embedded_pool.rem = sizeof (freepool->embedded_data);
|
||||
freepool->embedded_pool.data = freepool->embedded_data;
|
||||
}
|
||||
|
||||
cairo_private void *
|
||||
_cairo_freepool_alloc_from_new_pool (cairo_freepool_t *freepool);
|
||||
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright © 2010 Joonas Pihlaja
|
||||
*
|
||||
* 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 the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
#ifndef CAIRO_FREELIST_TYPE_H
|
||||
#define CAIRO_FREELIST_TYPE_H
|
||||
|
||||
#include "cairo-types-private.h"
|
||||
#include "cairo-compiler-private.h"
|
||||
|
||||
typedef struct _cairo_freelist_node cairo_freelist_node_t;
|
||||
struct _cairo_freelist_node {
|
||||
cairo_freelist_node_t *next;
|
||||
};
|
||||
|
||||
typedef struct _cairo_freelist {
|
||||
cairo_freelist_node_t *first_free_node;
|
||||
unsigned nodesize;
|
||||
} cairo_freelist_t;
|
||||
|
||||
typedef struct _cairo_freelist_pool cairo_freelist_pool_t;
|
||||
struct _cairo_freelist_pool {
|
||||
cairo_freelist_pool_t *next;
|
||||
unsigned size, rem;
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
typedef struct _cairo_freepool {
|
||||
cairo_freelist_node_t *first_free_node;
|
||||
cairo_freelist_pool_t *pools;
|
||||
cairo_freelist_pool_t *freepools;
|
||||
unsigned nodesize;
|
||||
cairo_freelist_pool_t embedded_pool;
|
||||
uint8_t embedded_data[1000];
|
||||
} cairo_freepool_t;
|
||||
|
||||
#endif /* CAIRO_FREELIST_TYPE_H */
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-freelist-private.h"
|
||||
|
||||
void
|
||||
|
@ -83,12 +84,12 @@ _cairo_freelist_free (cairo_freelist_t *freelist, void *voidnode)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_cairo_freepool_init (cairo_freepool_t *freepool, unsigned nodesize)
|
||||
{
|
||||
freepool->first_free_node = NULL;
|
||||
freepool->pools = &freepool->embedded_pool;
|
||||
freepool->freepools = NULL;
|
||||
freepool->nodesize = nodesize;
|
||||
|
||||
freepool->embedded_pool.next = NULL;
|
||||
|
@ -96,19 +97,28 @@ _cairo_freepool_init (cairo_freepool_t *freepool, unsigned nodesize)
|
|||
freepool->embedded_pool.rem = sizeof (freepool->embedded_data);
|
||||
freepool->embedded_pool.data = freepool->embedded_data;
|
||||
|
||||
VG (VALGRIND_MAKE_MEM_NOACCESS (freepool->embedded_data,
|
||||
sizeof (freepool->embedded_data)));
|
||||
VG (VALGRIND_MAKE_MEM_NOACCESS (freepool->embedded_data, sizeof (freepool->embedded_data)));
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_freepool_fini (cairo_freepool_t *freepool)
|
||||
{
|
||||
cairo_freelist_pool_t *pool = freepool->pools;
|
||||
cairo_freelist_pool_t *pool;
|
||||
|
||||
pool = freepool->pools;
|
||||
while (pool != &freepool->embedded_pool) {
|
||||
cairo_freelist_pool_t *next = pool->next;
|
||||
free (pool);
|
||||
pool = next;
|
||||
}
|
||||
|
||||
pool = freepool->freepools;
|
||||
while (pool != NULL) {
|
||||
cairo_freelist_pool_t *next = pool->next;
|
||||
free (pool);
|
||||
pool = next;
|
||||
}
|
||||
|
||||
VG (VALGRIND_MAKE_MEM_NOACCESS (freepool, sizeof (freepool)));
|
||||
}
|
||||
|
||||
|
@ -118,23 +128,31 @@ _cairo_freepool_alloc_from_new_pool (cairo_freepool_t *freepool)
|
|||
cairo_freelist_pool_t *pool;
|
||||
int poolsize;
|
||||
|
||||
if (freepool->pools != &freepool->embedded_pool)
|
||||
poolsize = 2 * freepool->pools->size;
|
||||
else
|
||||
poolsize = (128 * freepool->nodesize + 8191) & -8192;
|
||||
pool = malloc (sizeof (cairo_freelist_pool_t) + poolsize);
|
||||
if (unlikely (pool == NULL))
|
||||
return pool;
|
||||
if (freepool->freepools != NULL) {
|
||||
pool = freepool->freepools;
|
||||
freepool->freepools = pool->next;
|
||||
|
||||
poolsize = pool->size;
|
||||
} else {
|
||||
if (freepool->pools != &freepool->embedded_pool)
|
||||
poolsize = 2 * freepool->pools->size;
|
||||
else
|
||||
poolsize = (128 * freepool->nodesize + 8191) & -8192;
|
||||
|
||||
pool = malloc (sizeof (cairo_freelist_pool_t) + poolsize);
|
||||
if (unlikely (pool == NULL))
|
||||
return pool;
|
||||
|
||||
pool->size = poolsize;
|
||||
}
|
||||
|
||||
pool->next = freepool->pools;
|
||||
freepool->pools = pool;
|
||||
|
||||
pool->size = poolsize;
|
||||
pool->rem = poolsize - freepool->nodesize;
|
||||
pool->data = (uint8_t *) (pool + 1) + freepool->nodesize;
|
||||
|
||||
VG (VALGRIND_MAKE_MEM_NOACCESS (pool->data, poolsize));
|
||||
VG (VALGRIND_MAKE_MEM_UNDEFINED (pool->data, freepool->nodesize));
|
||||
VG (VALGRIND_MAKE_MEM_NOACCESS (pool->data, pool->rem));
|
||||
|
||||
return pool + 1;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -41,14 +41,12 @@
|
|||
#define _BSD_SOURCE /* for strdup() */
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-ft-private.h"
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#if CAIRO_HAS_FC_FONT
|
||||
#include <fontconfig/fontconfig.h>
|
||||
#include <fontconfig/fcfreetype.h>
|
||||
#endif
|
||||
#include "cairo-fontconfig-private.h"
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
@ -59,6 +57,30 @@
|
|||
#include FT_SYNTHESIS_H
|
||||
#endif
|
||||
|
||||
#if HAVE_FT_LIBRARY_SETLCDFILTER
|
||||
#include FT_LCD_FILTER_H
|
||||
#endif
|
||||
|
||||
/* Fontconfig version older than 2.6 didn't have these options */
|
||||
#ifndef FC_LCD_FILTER
|
||||
#define FC_LCD_FILTER "lcdfilter"
|
||||
#endif
|
||||
/* Some Ubuntu versions defined FC_LCD_FILTER without defining the following */
|
||||
#ifndef FC_LCD_NONE
|
||||
#define FC_LCD_NONE 0
|
||||
#define FC_LCD_DEFAULT 1
|
||||
#define FC_LCD_LIGHT 2
|
||||
#define FC_LCD_LEGACY 3
|
||||
#endif
|
||||
|
||||
/* FreeType version older than 2.3.5(?) didn't have these options */
|
||||
#ifndef FT_LCD_FILTER_NONE
|
||||
#define FT_LCD_FILTER_NONE 0
|
||||
#define FT_LCD_FILTER_DEFAULT 1
|
||||
#define FT_LCD_FILTER_LIGHT 2
|
||||
#define FT_LCD_FILTER_LEGACY 16
|
||||
#endif
|
||||
|
||||
#define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0))
|
||||
#define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
|
||||
#define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
|
||||
|
@ -67,11 +89,35 @@
|
|||
/* This is the max number of FT_face objects we keep open at once
|
||||
*/
|
||||
#define MAX_OPEN_FACES 10
|
||||
|
||||
/* This is the maximum font size we allow to be passed to FT_Set_Char_Size
|
||||
*/
|
||||
#define MAX_FONT_SIZE 1000
|
||||
|
||||
/**
|
||||
* SECTION:cairo-ft
|
||||
* @Title: FreeType Fonts
|
||||
* @Short_Description: Font support for FreeType
|
||||
* @See_Also: #cairo_font_face_t
|
||||
*
|
||||
* The FreeType font backend is primarily used to render text on GNU/Linux
|
||||
* systems, but can be used on other platforms too.
|
||||
*/
|
||||
|
||||
/**
|
||||
* CAIRO_HAS_FT_FONT:
|
||||
*
|
||||
* Defined if the FreeType font backend is available.
|
||||
* This macro can be used to conditionally compile backend-specific code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* CAIRO_HAS_FC_FONT:
|
||||
*
|
||||
* Defined if the Fontconfig-specific functions of the FreeType font backend
|
||||
* are available.
|
||||
* This macro can be used to conditionally compile backend-specific code.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The simple 2x2 matrix is converted into separate scale and shape
|
||||
* factors so that hinting works right
|
||||
|
@ -180,6 +226,7 @@ typedef struct _cairo_ft_unscaled_font_map {
|
|||
|
||||
static cairo_ft_unscaled_font_map_t *cairo_ft_unscaled_font_map = NULL;
|
||||
|
||||
|
||||
static void
|
||||
_font_map_release_face_lock_held (cairo_ft_unscaled_font_map_t *font_map,
|
||||
cairo_ft_unscaled_font_t *unscaled)
|
||||
|
@ -779,23 +826,279 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Empirically-derived subpixel filtering values thanks to Keith
|
||||
* Packard and libXft. */
|
||||
static const int filters[3][3] = {
|
||||
/* red */
|
||||
#if 0
|
||||
{ 65538*4/7,65538*2/7,65538*1/7 },
|
||||
/* green */
|
||||
{ 65536*1/4, 65536*2/4, 65537*1/4 },
|
||||
/* blue */
|
||||
{ 65538*1/7,65538*2/7,65538*4/7 },
|
||||
#endif
|
||||
{ 65538*9/13,65538*3/13,65538*1/13 },
|
||||
/* green */
|
||||
{ 65538*1/6, 65538*4/6, 65538*1/6 },
|
||||
/* blue */
|
||||
{ 65538*1/13,65538*3/13,65538*9/13 },
|
||||
};
|
||||
/* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot
|
||||
* into a different format. For example, we want to convert a
|
||||
* FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit
|
||||
* ARGB or ABGR bitmap.
|
||||
*
|
||||
* this function prepares a target descriptor for this operation.
|
||||
*
|
||||
* input :: target bitmap descriptor. The function will set its
|
||||
* 'width', 'rows' and 'pitch' fields, and only these
|
||||
*
|
||||
* slot :: the glyph slot containing the source bitmap. this
|
||||
* function assumes that slot->format == FT_GLYPH_FORMAT_BITMAP
|
||||
*
|
||||
* mode :: the requested final rendering mode. supported values are
|
||||
* MONO, NORMAL (i.e. gray), LCD and LCD_V
|
||||
*
|
||||
* the function returns the size in bytes of the corresponding buffer,
|
||||
* it's up to the caller to allocate the corresponding memory block
|
||||
* before calling _fill_xrender_bitmap
|
||||
*
|
||||
* it also returns -1 in case of error (e.g. incompatible arguments,
|
||||
* like trying to convert a gray bitmap into a monochrome one)
|
||||
*/
|
||||
static int
|
||||
_compute_xrender_bitmap_size(FT_Bitmap *target,
|
||||
FT_GlyphSlot slot,
|
||||
FT_Render_Mode mode)
|
||||
{
|
||||
FT_Bitmap *ftbit;
|
||||
int width, height, pitch;
|
||||
|
||||
if (slot->format != FT_GLYPH_FORMAT_BITMAP)
|
||||
return -1;
|
||||
|
||||
/* compute the size of the final bitmap */
|
||||
ftbit = &slot->bitmap;
|
||||
|
||||
width = ftbit->width;
|
||||
height = ftbit->rows;
|
||||
pitch = (width + 3) & ~3;
|
||||
|
||||
switch (ftbit->pixel_mode) {
|
||||
case FT_PIXEL_MODE_MONO:
|
||||
if (mode == FT_RENDER_MODE_MONO) {
|
||||
pitch = (((width + 31) & ~31) >> 3);
|
||||
break;
|
||||
}
|
||||
/* fall-through */
|
||||
|
||||
case FT_PIXEL_MODE_GRAY:
|
||||
if (mode == FT_RENDER_MODE_LCD ||
|
||||
mode == FT_RENDER_MODE_LCD_V)
|
||||
{
|
||||
/* each pixel is replicated into a 32-bit ARGB value */
|
||||
pitch = width * 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case FT_PIXEL_MODE_LCD:
|
||||
if (mode != FT_RENDER_MODE_LCD)
|
||||
return -1;
|
||||
|
||||
/* horz pixel triplets are packed into 32-bit ARGB values */
|
||||
width /= 3;
|
||||
pitch = width * 4;
|
||||
break;
|
||||
|
||||
case FT_PIXEL_MODE_LCD_V:
|
||||
if (mode != FT_RENDER_MODE_LCD_V)
|
||||
return -1;
|
||||
|
||||
/* vert pixel triplets are packed into 32-bit ARGB values */
|
||||
height /= 3;
|
||||
pitch = width * 4;
|
||||
break;
|
||||
|
||||
default: /* unsupported source format */
|
||||
return -1;
|
||||
}
|
||||
|
||||
target->width = width;
|
||||
target->rows = height;
|
||||
target->pitch = pitch;
|
||||
target->buffer = NULL;
|
||||
|
||||
return pitch * height;
|
||||
}
|
||||
|
||||
/* this functions converts the glyph bitmap found in a FT_GlyphSlot
|
||||
* into a different format (see _compute_xrender_bitmap_size)
|
||||
*
|
||||
* you should call this function after _compute_xrender_bitmap_size
|
||||
*
|
||||
* target :: target bitmap descriptor. Note that its 'buffer' pointer
|
||||
* must point to memory allocated by the caller
|
||||
*
|
||||
* slot :: the glyph slot containing the source bitmap
|
||||
*
|
||||
* mode :: the requested final rendering mode
|
||||
*
|
||||
* bgr :: boolean, set if BGR or VBGR pixel ordering is needed
|
||||
*/
|
||||
static void
|
||||
_fill_xrender_bitmap(FT_Bitmap *target,
|
||||
FT_GlyphSlot slot,
|
||||
FT_Render_Mode mode,
|
||||
int bgr)
|
||||
{
|
||||
FT_Bitmap *ftbit = &slot->bitmap;
|
||||
unsigned char *srcLine = ftbit->buffer;
|
||||
unsigned char *dstLine = target->buffer;
|
||||
int src_pitch = ftbit->pitch;
|
||||
int width = target->width;
|
||||
int height = target->rows;
|
||||
int pitch = target->pitch;
|
||||
int subpixel;
|
||||
int h;
|
||||
|
||||
subpixel = (mode == FT_RENDER_MODE_LCD ||
|
||||
mode == FT_RENDER_MODE_LCD_V);
|
||||
|
||||
if (src_pitch < 0)
|
||||
srcLine -= src_pitch * (ftbit->rows - 1);
|
||||
|
||||
target->pixel_mode = ftbit->pixel_mode;
|
||||
|
||||
switch (ftbit->pixel_mode) {
|
||||
case FT_PIXEL_MODE_MONO:
|
||||
if (subpixel) {
|
||||
/* convert mono to ARGB32 values */
|
||||
|
||||
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
|
||||
int x;
|
||||
|
||||
for (x = 0; x < width; x++) {
|
||||
if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
|
||||
((unsigned int *) dstLine)[x] = 0xffffffffU;
|
||||
}
|
||||
}
|
||||
target->pixel_mode = FT_PIXEL_MODE_LCD;
|
||||
|
||||
} else if (mode == FT_RENDER_MODE_NORMAL) {
|
||||
/* convert mono to 8-bit gray */
|
||||
|
||||
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
|
||||
int x;
|
||||
|
||||
for (x = 0; x < width; x++) {
|
||||
if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
|
||||
dstLine[x] = 0xff;
|
||||
}
|
||||
}
|
||||
target->pixel_mode = FT_PIXEL_MODE_GRAY;
|
||||
|
||||
} else {
|
||||
/* copy mono to mono */
|
||||
|
||||
int bytes = (width + 7) >> 3;
|
||||
|
||||
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
|
||||
memcpy (dstLine, srcLine, bytes);
|
||||
}
|
||||
break;
|
||||
|
||||
case FT_PIXEL_MODE_GRAY:
|
||||
if (subpixel) {
|
||||
/* convert gray to ARGB32 values */
|
||||
|
||||
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
|
||||
int x;
|
||||
unsigned int *dst = (unsigned int *) dstLine;
|
||||
|
||||
for (x = 0; x < width; x++) {
|
||||
unsigned int pix = srcLine[x];
|
||||
|
||||
pix |= (pix << 8);
|
||||
pix |= (pix << 16);
|
||||
|
||||
dst[x] = pix;
|
||||
}
|
||||
}
|
||||
target->pixel_mode = FT_PIXEL_MODE_LCD;
|
||||
} else {
|
||||
/* copy gray into gray */
|
||||
|
||||
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
|
||||
memcpy (dstLine, srcLine, width);
|
||||
}
|
||||
break;
|
||||
|
||||
case FT_PIXEL_MODE_LCD:
|
||||
if (!bgr) {
|
||||
/* convert horizontal RGB into ARGB32 */
|
||||
|
||||
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
|
||||
int x;
|
||||
unsigned char *src = srcLine;
|
||||
unsigned int *dst = (unsigned int *) dstLine;
|
||||
|
||||
for (x = 0; x < width; x++, src += 3) {
|
||||
unsigned int pix;
|
||||
|
||||
pix = ((unsigned int)src[0] << 16) |
|
||||
((unsigned int)src[1] << 8) |
|
||||
((unsigned int)src[2] ) |
|
||||
((unsigned int)src[1] << 24) ;
|
||||
|
||||
dst[x] = pix;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* convert horizontal BGR into ARGB32 */
|
||||
|
||||
for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
|
||||
|
||||
int x;
|
||||
unsigned char *src = srcLine;
|
||||
unsigned int *dst = (unsigned int *) dstLine;
|
||||
|
||||
for (x = 0; x < width; x++, src += 3) {
|
||||
unsigned int pix;
|
||||
|
||||
pix = ((unsigned int)src[2] << 16) |
|
||||
((unsigned int)src[1] << 8) |
|
||||
((unsigned int)src[0] ) |
|
||||
((unsigned int)src[1] << 24) ;
|
||||
|
||||
dst[x] = pix;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: /* FT_PIXEL_MODE_LCD_V */
|
||||
/* convert vertical RGB into ARGB32 */
|
||||
if (!bgr) {
|
||||
|
||||
for (h = height; h > 0; h--, srcLine += 3 * src_pitch, dstLine += pitch) {
|
||||
int x;
|
||||
unsigned char* src = srcLine;
|
||||
unsigned int* dst = (unsigned int *) dstLine;
|
||||
|
||||
for (x = 0; x < width; x++, src += 1) {
|
||||
unsigned int pix;
|
||||
pix = ((unsigned int)src[0] << 16) |
|
||||
((unsigned int)src[src_pitch] << 8) |
|
||||
((unsigned int)src[src_pitch*2] ) |
|
||||
((unsigned int)src[src_pitch] << 24) ;
|
||||
dst[x] = pix;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
for (h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch) {
|
||||
int x;
|
||||
unsigned char *src = srcLine;
|
||||
unsigned int *dst = (unsigned int *) dstLine;
|
||||
|
||||
for (x = 0; x < width; x++, src += 1) {
|
||||
unsigned int pix;
|
||||
|
||||
pix = ((unsigned int)src[src_pitch * 2] << 16) |
|
||||
((unsigned int)src[src_pitch] << 8) |
|
||||
((unsigned int)src[0] ) |
|
||||
((unsigned int)src[src_pitch] << 24) ;
|
||||
|
||||
dst[x] = pix;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Fills in val->image with an image surface created from @bitmap
|
||||
*/
|
||||
|
@ -808,6 +1111,7 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
|
|||
int width, height, stride;
|
||||
unsigned char *data;
|
||||
int format = CAIRO_FORMAT_A8;
|
||||
cairo_image_surface_t *image;
|
||||
|
||||
width = bitmap->width;
|
||||
height = bitmap->rows;
|
||||
|
@ -864,11 +1168,7 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
|
|||
case FT_PIXEL_MODE_LCD:
|
||||
case FT_PIXEL_MODE_LCD_V:
|
||||
case FT_PIXEL_MODE_GRAY:
|
||||
switch (font_options->antialias) {
|
||||
case CAIRO_ANTIALIAS_DEFAULT:
|
||||
case CAIRO_ANTIALIAS_GRAY:
|
||||
case CAIRO_ANTIALIAS_NONE:
|
||||
default:
|
||||
if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) {
|
||||
stride = bitmap->pitch;
|
||||
if (own_buffer) {
|
||||
data = bitmap->buffer;
|
||||
|
@ -879,104 +1179,18 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
|
|||
|
||||
memcpy (data, bitmap->buffer, stride * height);
|
||||
}
|
||||
format = CAIRO_FORMAT_A8;
|
||||
break;
|
||||
case CAIRO_ANTIALIAS_SUBPIXEL: {
|
||||
int x, y;
|
||||
unsigned char *in_line, *out_line, *in;
|
||||
unsigned int *out;
|
||||
unsigned int red, green, blue;
|
||||
int rf, gf, bf;
|
||||
int s;
|
||||
int o, os;
|
||||
unsigned char *data_rgba;
|
||||
unsigned int width_rgba, stride_rgba;
|
||||
int vmul = 1;
|
||||
int hmul = 1;
|
||||
|
||||
switch (font_options->subpixel_order) {
|
||||
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
|
||||
case CAIRO_SUBPIXEL_ORDER_RGB:
|
||||
case CAIRO_SUBPIXEL_ORDER_BGR:
|
||||
default:
|
||||
width /= 3;
|
||||
hmul = 3;
|
||||
break;
|
||||
case CAIRO_SUBPIXEL_ORDER_VRGB:
|
||||
case CAIRO_SUBPIXEL_ORDER_VBGR:
|
||||
vmul = 3;
|
||||
height /= 3;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Filter the glyph to soften the color fringes
|
||||
*/
|
||||
width_rgba = width;
|
||||
stride = bitmap->pitch;
|
||||
stride_rgba = (width_rgba * 4 + 3) & ~3;
|
||||
data_rgba = calloc (stride_rgba, height);
|
||||
if (unlikely (data_rgba == NULL)) {
|
||||
if (own_buffer)
|
||||
free (bitmap->buffer);
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
format = CAIRO_FORMAT_A8;
|
||||
} else {
|
||||
/* if we get there, the data from the source bitmap
|
||||
* really comes from _fill_xrender_bitmap, and is
|
||||
* made of 32-bit ARGB or ABGR values */
|
||||
assert (own_buffer != 0);
|
||||
assert (bitmap->pixel_mode != FT_PIXEL_MODE_GRAY);
|
||||
|
||||
os = 1;
|
||||
switch (font_options->subpixel_order) {
|
||||
case CAIRO_SUBPIXEL_ORDER_VRGB:
|
||||
os = stride;
|
||||
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
|
||||
case CAIRO_SUBPIXEL_ORDER_RGB:
|
||||
default:
|
||||
rf = 0;
|
||||
gf = 1;
|
||||
bf = 2;
|
||||
break;
|
||||
case CAIRO_SUBPIXEL_ORDER_VBGR:
|
||||
os = stride;
|
||||
case CAIRO_SUBPIXEL_ORDER_BGR:
|
||||
bf = 0;
|
||||
gf = 1;
|
||||
rf = 2;
|
||||
break;
|
||||
}
|
||||
in_line = bitmap->buffer;
|
||||
out_line = data_rgba;
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
in = in_line;
|
||||
out = (unsigned int *) out_line;
|
||||
in_line += stride * vmul;
|
||||
out_line += stride_rgba;
|
||||
for (x = 0; x < width * hmul; x += hmul)
|
||||
{
|
||||
red = green = blue = 0;
|
||||
o = 0;
|
||||
for (s = 0; s < 3; s++)
|
||||
{
|
||||
red += filters[rf][s]*in[x+o];
|
||||
green += filters[gf][s]*in[x+o];
|
||||
blue += filters[bf][s]*in[x+o];
|
||||
o += os;
|
||||
}
|
||||
red = red / 65536;
|
||||
green = green / 65536;
|
||||
blue = blue / 65536;
|
||||
*out++ = (green << 24) | (red << 16) | (green << 8) | blue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Images here are stored in native format. The
|
||||
* backend must convert to its own format as needed
|
||||
*/
|
||||
|
||||
if (own_buffer)
|
||||
free (bitmap->buffer);
|
||||
data = data_rgba;
|
||||
stride = stride_rgba;
|
||||
format = CAIRO_FORMAT_ARGB32;
|
||||
break;
|
||||
}
|
||||
data = bitmap->buffer;
|
||||
stride = bitmap->pitch;
|
||||
format = CAIRO_FORMAT_ARGB32;
|
||||
}
|
||||
break;
|
||||
case FT_PIXEL_MODE_GRAY2:
|
||||
|
@ -988,18 +1202,22 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
|
|||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
*surface = (cairo_image_surface_t *)
|
||||
/* XXX */
|
||||
*surface = image = (cairo_image_surface_t *)
|
||||
cairo_image_surface_create_for_data (data,
|
||||
format,
|
||||
width, height, stride);
|
||||
if ((*surface)->base.status) {
|
||||
if (image->base.status) {
|
||||
free (data);
|
||||
return (*surface)->base.status;
|
||||
}
|
||||
|
||||
_cairo_image_surface_assume_ownership_of_data ((*surface));
|
||||
if (format == CAIRO_FORMAT_ARGB32)
|
||||
pixman_image_set_component_alpha (image->pixman_image, TRUE);
|
||||
|
||||
_cairo_debug_check_image_surface_is_defined (&(*surface)->base);
|
||||
_cairo_image_surface_assume_ownership_of_data (image);
|
||||
|
||||
_cairo_debug_check_image_surface_is_defined (&image->base);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -1024,16 +1242,59 @@ _render_glyph_outline (FT_Face face,
|
|||
cairo_font_options_t *font_options,
|
||||
cairo_image_surface_t **surface)
|
||||
{
|
||||
int rgba = FC_RGBA_UNKNOWN;
|
||||
int lcd_filter = FT_LCD_FILTER_LEGACY;
|
||||
FT_GlyphSlot glyphslot = face->glyph;
|
||||
FT_Outline *outline = &glyphslot->outline;
|
||||
FT_Bitmap bitmap;
|
||||
FT_BBox cbox;
|
||||
FT_Matrix matrix;
|
||||
int hmul = 1;
|
||||
int vmul = 1;
|
||||
unsigned int width, height, stride;
|
||||
cairo_bool_t subpixel = FALSE;
|
||||
unsigned int width, height;
|
||||
cairo_status_t status;
|
||||
FT_Error fterror;
|
||||
FT_Library library = glyphslot->library;
|
||||
FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL;
|
||||
|
||||
switch (font_options->antialias) {
|
||||
case CAIRO_ANTIALIAS_NONE:
|
||||
render_mode = FT_RENDER_MODE_MONO;
|
||||
break;
|
||||
|
||||
case CAIRO_ANTIALIAS_SUBPIXEL:
|
||||
switch (font_options->subpixel_order) {
|
||||
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
|
||||
case CAIRO_SUBPIXEL_ORDER_RGB:
|
||||
case CAIRO_SUBPIXEL_ORDER_BGR:
|
||||
render_mode = FT_RENDER_MODE_LCD;
|
||||
break;
|
||||
|
||||
case CAIRO_SUBPIXEL_ORDER_VRGB:
|
||||
case CAIRO_SUBPIXEL_ORDER_VBGR:
|
||||
render_mode = FT_RENDER_MODE_LCD_V;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (font_options->lcd_filter) {
|
||||
case CAIRO_LCD_FILTER_NONE:
|
||||
lcd_filter = FT_LCD_FILTER_NONE;
|
||||
break;
|
||||
case CAIRO_LCD_FILTER_DEFAULT:
|
||||
case CAIRO_LCD_FILTER_INTRA_PIXEL:
|
||||
lcd_filter = FT_LCD_FILTER_LEGACY;
|
||||
break;
|
||||
case CAIRO_LCD_FILTER_FIR3:
|
||||
lcd_filter = FT_LCD_FILTER_LIGHT;
|
||||
break;
|
||||
case CAIRO_LCD_FILTER_FIR5:
|
||||
lcd_filter = FT_LCD_FILTER_DEFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CAIRO_ANTIALIAS_DEFAULT:
|
||||
case CAIRO_ANTIALIAS_GRAY:
|
||||
render_mode = FT_RENDER_MODE_NORMAL;
|
||||
}
|
||||
|
||||
FT_Outline_Get_CBox (outline, &cbox);
|
||||
|
||||
|
@ -1044,20 +1305,21 @@ _render_glyph_outline (FT_Face face,
|
|||
|
||||
width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
|
||||
height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
|
||||
stride = (width * hmul + 3) & ~3;
|
||||
|
||||
if (width * height == 0) {
|
||||
cairo_format_t format;
|
||||
/* Looks like fb handles zero-sized images just fine */
|
||||
switch (font_options->antialias) {
|
||||
case CAIRO_ANTIALIAS_NONE:
|
||||
switch (render_mode) {
|
||||
case FT_RENDER_MODE_MONO:
|
||||
format = CAIRO_FORMAT_A1;
|
||||
break;
|
||||
case CAIRO_ANTIALIAS_SUBPIXEL:
|
||||
case FT_RENDER_MODE_LCD:
|
||||
case FT_RENDER_MODE_LCD_V:
|
||||
format= CAIRO_FORMAT_ARGB32;
|
||||
break;
|
||||
case CAIRO_ANTIALIAS_DEFAULT:
|
||||
case CAIRO_ANTIALIAS_GRAY:
|
||||
case FT_RENDER_MODE_LIGHT:
|
||||
case FT_RENDER_MODE_NORMAL:
|
||||
case FT_RENDER_MODE_MAX:
|
||||
default:
|
||||
format = CAIRO_FORMAT_A8;
|
||||
break;
|
||||
|
@ -1067,75 +1329,74 @@ _render_glyph_outline (FT_Face face,
|
|||
cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
|
||||
if ((*surface)->base.status)
|
||||
return (*surface)->base.status;
|
||||
} else {
|
||||
} else {
|
||||
|
||||
matrix.xx = matrix.yy = 0x10000L;
|
||||
matrix.xy = matrix.yx = 0;
|
||||
int bitmap_size;
|
||||
|
||||
switch (font_options->antialias) {
|
||||
case CAIRO_ANTIALIAS_NONE:
|
||||
bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
|
||||
bitmap.num_grays = 1;
|
||||
stride = ((width + 31) & -32) >> 3;
|
||||
break;
|
||||
case CAIRO_ANTIALIAS_DEFAULT:
|
||||
case CAIRO_ANTIALIAS_GRAY:
|
||||
bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
|
||||
bitmap.num_grays = 256;
|
||||
stride = (width + 3) & -4;
|
||||
break;
|
||||
case CAIRO_ANTIALIAS_SUBPIXEL:
|
||||
switch (font_options->subpixel_order) {
|
||||
case CAIRO_SUBPIXEL_ORDER_RGB:
|
||||
case CAIRO_SUBPIXEL_ORDER_BGR:
|
||||
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
|
||||
default:
|
||||
matrix.xx *= 3;
|
||||
hmul = 3;
|
||||
subpixel = TRUE;
|
||||
break;
|
||||
case CAIRO_SUBPIXEL_ORDER_VRGB:
|
||||
case CAIRO_SUBPIXEL_ORDER_VBGR:
|
||||
matrix.yy *= 3;
|
||||
vmul = 3;
|
||||
subpixel = TRUE;
|
||||
break;
|
||||
switch (render_mode) {
|
||||
case FT_RENDER_MODE_LCD:
|
||||
if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_BGR) {
|
||||
rgba = FC_RGBA_BGR;
|
||||
} else {
|
||||
rgba = FC_RGBA_RGB;
|
||||
}
|
||||
case FT_RENDER_MODE_LCD_V:
|
||||
if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_VBGR) {
|
||||
rgba = FC_RGBA_VBGR;
|
||||
} else {
|
||||
rgba = FC_RGBA_VRGB;
|
||||
}
|
||||
break;
|
||||
case FT_RENDER_MODE_MONO:
|
||||
case FT_RENDER_MODE_LIGHT:
|
||||
case FT_RENDER_MODE_NORMAL:
|
||||
case FT_RENDER_MODE_MAX:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
FT_Outline_Transform (outline, &matrix);
|
||||
|
||||
bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
|
||||
bitmap.num_grays = 256;
|
||||
stride = (width * hmul + 3) & -4;
|
||||
}
|
||||
#if HAVE_FT_LIBRARY_SETLCDFILTER
|
||||
FT_Library_SetLcdFilter (library, lcd_filter);
|
||||
#endif
|
||||
|
||||
bitmap.pitch = stride;
|
||||
bitmap.width = width * hmul;
|
||||
bitmap.rows = height * vmul;
|
||||
bitmap.buffer = calloc (stride, bitmap.rows);
|
||||
if (unlikely (bitmap.buffer == NULL))
|
||||
fterror = FT_Render_Glyph (face->glyph, render_mode);
|
||||
|
||||
#if HAVE_FT_LIBRARY_SETLCDFILTER
|
||||
FT_Library_SetLcdFilter (library, FT_LCD_FILTER_NONE);
|
||||
#endif
|
||||
|
||||
if (fterror != 0)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
bitmap_size = _compute_xrender_bitmap_size (&bitmap,
|
||||
face->glyph,
|
||||
render_mode);
|
||||
if (bitmap_size < 0)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul);
|
||||
bitmap.buffer = calloc (1, bitmap_size);
|
||||
if (bitmap.buffer == NULL)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
|
||||
free (bitmap.buffer);
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
_fill_xrender_bitmap (&bitmap, face->glyph, render_mode,
|
||||
(rgba == FC_RGBA_BGR || rgba == FC_RGBA_VBGR));
|
||||
|
||||
/* Note:
|
||||
* _get_bitmap_surface will free bitmap.buffer if there is an error
|
||||
*/
|
||||
status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: the font's coordinate system is upside down from ours, so the
|
||||
* Y coordinate of the control box needs to be negated. Moreover, device
|
||||
* offsets are position of glyph origin relative to top left while xMin
|
||||
* and yMax are offsets of top left relative to origin. Another negation.
|
||||
*/
|
||||
cairo_surface_set_device_offset (&(*surface)->base,
|
||||
floor (-(double) cbox.xMin / 64.0),
|
||||
floor (+(double) cbox.yMax / 64.0));
|
||||
/* Note: the font's coordinate system is upside down from ours, so the
|
||||
* Y coordinate of the control box needs to be negated. Moreover, device
|
||||
* offsets are position of glyph origin relative to top left while xMin
|
||||
* and yMax are offsets of top left relative to origin. Another negation.
|
||||
*/
|
||||
cairo_surface_set_device_offset (&(*surface)->base,
|
||||
(double)-glyphslot->bitmap_left,
|
||||
(double)+glyphslot->bitmap_top);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -1207,8 +1468,8 @@ _transform_glyph_bitmap (cairo_matrix_t * shape,
|
|||
original_to_transformed = *shape;
|
||||
|
||||
cairo_surface_get_device_offset (&(*surface)->base, &origin_x, &origin_y);
|
||||
orig_width = cairo_image_surface_get_width (&(*surface)->base);
|
||||
orig_height = cairo_image_surface_get_height (&(*surface)->base);
|
||||
orig_width = (*surface)->width;
|
||||
orig_height = (*surface)->height;
|
||||
|
||||
cairo_matrix_translate (&original_to_transformed,
|
||||
-origin_x, -origin_y);
|
||||
|
@ -1246,9 +1507,8 @@ _transform_glyph_bitmap (cairo_matrix_t * shape,
|
|||
original_to_transformed.x0 -= x_min;
|
||||
original_to_transformed.y0 -= y_min;
|
||||
|
||||
/* Create the transformed bitmap
|
||||
*/
|
||||
width = x_max - x_min;
|
||||
/* Create the transformed bitmap */
|
||||
width = x_max - x_min;
|
||||
height = y_max - y_min;
|
||||
|
||||
transformed_to_original = original_to_transformed;
|
||||
|
@ -1256,30 +1516,19 @@ _transform_glyph_bitmap (cairo_matrix_t * shape,
|
|||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
/* We need to pad out the width to 32-bit intervals for cairo-xlib-surface.c */
|
||||
width = (width + 3) & ~3;
|
||||
image = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
|
||||
if (unlikely (image->status))
|
||||
return image->status;
|
||||
|
||||
/* Initialize it to empty
|
||||
*/
|
||||
status = _cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_CLEAR,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
0, 0,
|
||||
width, height);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (image);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Draw the original bitmap transformed into the new bitmap
|
||||
*/
|
||||
_cairo_pattern_init_for_surface (&pattern, &(*surface)->base);
|
||||
cairo_pattern_set_matrix (&pattern.base, &transformed_to_original);
|
||||
|
||||
status = _cairo_surface_paint (image, CAIRO_OPERATOR_OVER,
|
||||
&pattern.base, NULL);
|
||||
status = _cairo_surface_paint (image,
|
||||
CAIRO_OPERATOR_SOURCE,
|
||||
&pattern.base,
|
||||
NULL);
|
||||
|
||||
_cairo_pattern_fini (&pattern.base);
|
||||
|
||||
|
@ -1355,6 +1604,7 @@ _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
|
|||
|
||||
if (antialias) {
|
||||
cairo_subpixel_order_t subpixel_order;
|
||||
int lcd_filter;
|
||||
|
||||
/* disable hinting if requested */
|
||||
if (FcPatternGetBool (pattern,
|
||||
|
@ -1390,6 +1640,25 @@ _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
|
|||
ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
|
||||
}
|
||||
|
||||
if (FcPatternGetInteger (pattern,
|
||||
FC_LCD_FILTER, 0, &lcd_filter) == FcResultMatch)
|
||||
{
|
||||
switch (lcd_filter) {
|
||||
case FC_LCD_NONE:
|
||||
ft_options.base.lcd_filter = CAIRO_LCD_FILTER_NONE;
|
||||
break;
|
||||
case FC_LCD_DEFAULT:
|
||||
ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR5;
|
||||
break;
|
||||
case FC_LCD_LIGHT:
|
||||
ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR3;
|
||||
break;
|
||||
case FC_LCD_LEGACY:
|
||||
ft_options.base.lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FC_HINT_STYLE
|
||||
if (FcPatternGetInteger (pattern,
|
||||
FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch)
|
||||
|
@ -1491,6 +1760,12 @@ _cairo_ft_options_merge (cairo_ft_options_t *options,
|
|||
if (other->base.hint_style == CAIRO_HINT_STYLE_NONE)
|
||||
options->base.hint_style = CAIRO_HINT_STYLE_NONE;
|
||||
|
||||
if (options->base.lcd_filter == CAIRO_LCD_FILTER_DEFAULT)
|
||||
options->base.lcd_filter = other->base.lcd_filter;
|
||||
|
||||
if (other->base.lcd_filter == CAIRO_LCD_FILTER_NONE)
|
||||
options->base.lcd_filter = CAIRO_LCD_FILTER_NONE;
|
||||
|
||||
if (options->base.antialias == CAIRO_ANTIALIAS_NONE) {
|
||||
if (options->base.hint_style == CAIRO_HINT_STYLE_NONE)
|
||||
load_flags |= FT_LOAD_NO_HINTING;
|
||||
|
@ -1514,11 +1789,11 @@ _cairo_ft_options_merge (cairo_ft_options_t *options,
|
|||
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
|
||||
case CAIRO_SUBPIXEL_ORDER_RGB:
|
||||
case CAIRO_SUBPIXEL_ORDER_BGR:
|
||||
load_target |= FT_LOAD_TARGET_LCD;
|
||||
load_target = FT_LOAD_TARGET_LCD;
|
||||
break;
|
||||
case CAIRO_SUBPIXEL_ORDER_VRGB:
|
||||
case CAIRO_SUBPIXEL_ORDER_VBGR:
|
||||
load_target |= FT_LOAD_TARGET_LCD_V;
|
||||
load_target = FT_LOAD_TARGET_LCD_V;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2517,6 +2792,34 @@ _cairo_ft_font_options_substitute (const cairo_font_options_t *options,
|
|||
}
|
||||
}
|
||||
|
||||
if (options->lcd_filter != CAIRO_LCD_FILTER_DEFAULT)
|
||||
{
|
||||
if (FcPatternGet (pattern, FC_LCD_FILTER, 0, &v) == FcResultNoMatch)
|
||||
{
|
||||
int lcd_filter;
|
||||
|
||||
switch (options->lcd_filter) {
|
||||
case CAIRO_LCD_FILTER_NONE:
|
||||
lcd_filter = FT_LCD_FILTER_NONE;
|
||||
break;
|
||||
case CAIRO_LCD_FILTER_DEFAULT:
|
||||
case CAIRO_LCD_FILTER_INTRA_PIXEL:
|
||||
lcd_filter = FT_LCD_FILTER_LEGACY;
|
||||
break;
|
||||
case CAIRO_LCD_FILTER_FIR3:
|
||||
lcd_filter = FT_LCD_FILTER_LIGHT;
|
||||
break;
|
||||
default:
|
||||
case CAIRO_LCD_FILTER_FIR5:
|
||||
lcd_filter = FT_LCD_FILTER_DEFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (! FcPatternAddInteger (pattern, FC_LCD_FILTER, lcd_filter))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
}
|
||||
|
||||
if (options->hint_style != CAIRO_HINT_STYLE_DEFAULT)
|
||||
{
|
||||
if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch)
|
||||
|
@ -2638,13 +2941,11 @@ _cairo_ft_resolve_pattern (FcPattern *pattern,
|
|||
}
|
||||
|
||||
status = _cairo_ft_unscaled_font_create_for_pattern (resolved, &unscaled);
|
||||
if (unlikely (status)) {
|
||||
if (unlikely (status || unscaled == NULL)) {
|
||||
font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
|
||||
goto FREE_RESOLVED;
|
||||
}
|
||||
|
||||
assert (unscaled != NULL);
|
||||
|
||||
_get_pattern_ft_options (resolved, &ft_options);
|
||||
font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
|
||||
_cairo_unscaled_font_destroy (&unscaled->base);
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/* Cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2009 Chris Wilson
|
||||
* Copyright © 2010 Intel Corporation
|
||||
* Copyright © 2010 Red Hat, Inc
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
|
@ -12,7 +14,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -28,11 +30,17 @@
|
|||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Chris Wilson.
|
||||
*
|
||||
* Contributors:
|
||||
* Benjamin Otte <otte@gnome.org>
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-gl-private.h"
|
||||
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-rtree-private.h"
|
||||
|
||||
#define GLYPH_CACHE_WIDTH 1024
|
||||
|
@ -47,40 +55,16 @@ typedef struct _cairo_gl_glyph_private {
|
|||
} cairo_gl_glyph_private_t;
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_gl_glyph_cache_add_glyph (cairo_gl_glyph_cache_t *cache,
|
||||
_cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx,
|
||||
cairo_gl_glyph_cache_t *cache,
|
||||
cairo_scaled_glyph_t *scaled_glyph)
|
||||
{
|
||||
cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
|
||||
cairo_gl_surface_t *cache_surface;
|
||||
cairo_gl_glyph_private_t *glyph_private;
|
||||
cairo_rtree_node_t *node = NULL;
|
||||
cairo_image_surface_t *clone = NULL;
|
||||
cairo_status_t status;
|
||||
int width, height;
|
||||
GLenum internal_format, format, type;
|
||||
cairo_bool_t has_alpha;
|
||||
|
||||
if (! _cairo_gl_get_image_format_and_type (glyph_surface->pixman_format,
|
||||
&internal_format,
|
||||
&format,
|
||||
&type,
|
||||
&has_alpha))
|
||||
{
|
||||
cairo_bool_t is_supported;
|
||||
|
||||
clone = _cairo_image_surface_coerce (glyph_surface,
|
||||
_cairo_format_from_content (glyph_surface->base.content));
|
||||
if (unlikely (clone->base.status))
|
||||
return clone->base.status;
|
||||
|
||||
is_supported =
|
||||
_cairo_gl_get_image_format_and_type (clone->pixman_format,
|
||||
&internal_format,
|
||||
&format,
|
||||
&type,
|
||||
&has_alpha);
|
||||
assert (is_supported);
|
||||
glyph_surface = clone;
|
||||
}
|
||||
|
||||
width = glyph_surface->width;
|
||||
if (width < GLYPH_CACHE_MIN_SIZE)
|
||||
|
@ -103,16 +87,17 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_glyph_cache_t *cache,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH,
|
||||
glyph_surface->stride /
|
||||
(PIXMAN_FORMAT_BPP (glyph_surface->pixman_format) / 8));
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||
node->x, node->y,
|
||||
glyph_surface->width, glyph_surface->height,
|
||||
format, type,
|
||||
glyph_surface->data);
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
|
||||
cache_surface = (cairo_gl_surface_t *) cache->pattern.surface;
|
||||
|
||||
/* XXX: Make sure we use the mask texture. This should work automagically somehow */
|
||||
glActiveTexture (GL_TEXTURE1);
|
||||
status = _cairo_gl_surface_draw_image (cache_surface,
|
||||
glyph_surface,
|
||||
0, 0,
|
||||
glyph_surface->width, glyph_surface->height,
|
||||
node->x, node->y);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
scaled_glyph->surface_private = node;
|
||||
node->owner = &scaled_glyph->surface_private;
|
||||
|
@ -121,14 +106,16 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_glyph_cache_t *cache,
|
|||
glyph_private->cache = cache;
|
||||
|
||||
/* compute tex coords */
|
||||
glyph_private->p1.x = node->x / (double) cache->width;
|
||||
glyph_private->p1.y = node->y / (double) cache->height;
|
||||
glyph_private->p2.x =
|
||||
(node->x + glyph_surface->width) / (double) cache->width;
|
||||
glyph_private->p2.y =
|
||||
(node->y + glyph_surface->height) / (double) cache->height;
|
||||
|
||||
cairo_surface_destroy (&clone->base);
|
||||
glyph_private->p1.x = node->x;
|
||||
glyph_private->p1.y = node->y;
|
||||
glyph_private->p2.x = node->x + glyph_surface->width;
|
||||
glyph_private->p2.y = node->y + glyph_surface->height;
|
||||
if (! _cairo_gl_device_requires_power_of_two_textures (&ctx->base)) {
|
||||
glyph_private->p1.x /= cache_surface->width;
|
||||
glyph_private->p1.y /= cache_surface->height;
|
||||
glyph_private->p2.x /= cache_surface->width;
|
||||
glyph_private->p2.y /= cache_surface->height;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -140,53 +127,50 @@ _cairo_gl_glyph_cache_lock (cairo_gl_glyph_cache_t *cache,
|
|||
return _cairo_rtree_pin (&cache->rtree, scaled_glyph->surface_private);
|
||||
}
|
||||
|
||||
static cairo_gl_glyph_cache_t *
|
||||
static cairo_status_t
|
||||
cairo_gl_context_get_glyph_cache (cairo_gl_context_t *ctx,
|
||||
cairo_format_t format)
|
||||
cairo_format_t format,
|
||||
cairo_gl_glyph_cache_t **cache_out)
|
||||
{
|
||||
cairo_gl_glyph_cache_t *cache;
|
||||
cairo_content_t content;
|
||||
|
||||
switch (format) {
|
||||
case CAIRO_FORMAT_RGB16_565:
|
||||
case CAIRO_FORMAT_ARGB32:
|
||||
case CAIRO_FORMAT_RGB24:
|
||||
cache = &ctx->glyph_cache[0];
|
||||
format = CAIRO_FORMAT_ARGB32;
|
||||
content = CAIRO_CONTENT_COLOR_ALPHA;
|
||||
break;
|
||||
case CAIRO_FORMAT_A8:
|
||||
case CAIRO_FORMAT_A1:
|
||||
cache = &ctx->glyph_cache[1];
|
||||
format = CAIRO_FORMAT_A8;
|
||||
content = CAIRO_CONTENT_ALPHA;
|
||||
break;
|
||||
case CAIRO_FORMAT_INVALID:
|
||||
ASSERT_NOT_REACHED;
|
||||
return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
|
||||
}
|
||||
|
||||
if (unlikely (cache->tex == 0)) {
|
||||
GLenum internal_format;
|
||||
|
||||
cache->width = GLYPH_CACHE_WIDTH;
|
||||
cache->height = GLYPH_CACHE_HEIGHT;
|
||||
|
||||
switch (format) {
|
||||
case CAIRO_FORMAT_A1:
|
||||
case CAIRO_FORMAT_RGB24:
|
||||
ASSERT_NOT_REACHED;
|
||||
case CAIRO_FORMAT_ARGB32:
|
||||
internal_format = GL_RGBA;
|
||||
break;
|
||||
case CAIRO_FORMAT_A8:
|
||||
internal_format = GL_ALPHA;
|
||||
break;
|
||||
}
|
||||
|
||||
glGenTextures (1, &cache->tex);
|
||||
glBindTexture (GL_TEXTURE_2D, cache->tex);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, internal_format,
|
||||
GLYPH_CACHE_WIDTH, GLYPH_CACHE_HEIGHT, 0,
|
||||
internal_format, GL_FLOAT, NULL);
|
||||
if (unlikely (cache->pattern.surface == NULL)) {
|
||||
cairo_surface_t *surface;
|
||||
surface = cairo_gl_surface_create (&ctx->base,
|
||||
content,
|
||||
GLYPH_CACHE_WIDTH,
|
||||
GLYPH_CACHE_HEIGHT);
|
||||
if (unlikely (surface->status)) {
|
||||
cairo_status_t status = surface->status;
|
||||
cairo_surface_destroy (surface);
|
||||
return status;
|
||||
}
|
||||
_cairo_surface_release_device_reference (surface);
|
||||
_cairo_pattern_init_for_surface (&cache->pattern, surface);
|
||||
cairo_surface_destroy (surface);
|
||||
cache->pattern.base.has_component_alpha = (content == CAIRO_CONTENT_COLOR_ALPHA);
|
||||
}
|
||||
|
||||
return cache;
|
||||
*cache_out = cache;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -199,12 +183,12 @@ static cairo_bool_t
|
|||
_cairo_gl_surface_owns_font (cairo_gl_surface_t *surface,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_gl_context_t *font_private;
|
||||
cairo_device_t *font_private;
|
||||
|
||||
font_private = scaled_font->surface_private;
|
||||
if ((scaled_font->surface_backend != NULL &&
|
||||
scaled_font->surface_backend != &_cairo_gl_surface_backend) ||
|
||||
(font_private != NULL && font_private != surface->ctx))
|
||||
(font_private != NULL && font_private != surface->base.device))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -212,6 +196,12 @@ _cairo_gl_surface_owns_font (cairo_gl_surface_t *surface,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_gl_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_list_del (&scaled_font->link);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_gl_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
|
@ -229,109 +219,6 @@ _cairo_gl_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
|
|||
}
|
||||
}
|
||||
|
||||
typedef struct _cairo_gl_glyphs_setup
|
||||
{
|
||||
unsigned int vbo_size; /* units of floats */
|
||||
unsigned int vb_offset; /* units of floats */
|
||||
unsigned int vertex_size; /* units of floats */
|
||||
unsigned int num_prims;
|
||||
float *vb;
|
||||
cairo_gl_composite_setup_t *composite;
|
||||
cairo_region_t *clip;
|
||||
cairo_gl_surface_t *dst;
|
||||
} cairo_gl_glyphs_setup_t;
|
||||
|
||||
static void
|
||||
_cairo_gl_flush_glyphs (cairo_gl_context_t *ctx,
|
||||
cairo_gl_glyphs_setup_t *setup)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (setup->vb != NULL) {
|
||||
glUnmapBufferARB (GL_ARRAY_BUFFER_ARB);
|
||||
setup->vb = NULL;
|
||||
|
||||
if (setup->num_prims != 0) {
|
||||
if (setup->clip) {
|
||||
int num_rectangles = cairo_region_num_rectangles (setup->clip);
|
||||
|
||||
glEnable (GL_SCISSOR_TEST);
|
||||
for (i = 0; i < num_rectangles; i++) {
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
cairo_region_get_rectangle (setup->clip, i, &rect);
|
||||
|
||||
glScissor (rect.x,
|
||||
_cairo_gl_y_flip (setup->dst, rect.y),
|
||||
rect.x + rect.width,
|
||||
_cairo_gl_y_flip (setup->dst,
|
||||
rect.y + rect.height));
|
||||
glDrawArrays (GL_QUADS, 0, 4 * setup->num_prims);
|
||||
}
|
||||
glDisable (GL_SCISSOR_TEST);
|
||||
} else {
|
||||
glDrawArrays (GL_QUADS, 0, 4 * setup->num_prims);
|
||||
}
|
||||
setup->num_prims = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_gl_glyphs_emit_vertex (cairo_gl_glyphs_setup_t *setup,
|
||||
int x, int y, float glyph_x, float glyph_y)
|
||||
{
|
||||
int i = 0;
|
||||
float *vb = &setup->vb[setup->vb_offset];
|
||||
cairo_surface_attributes_t *src_attributes;
|
||||
|
||||
src_attributes = &setup->composite->src.operand.texture.attributes;
|
||||
|
||||
vb[i++] = x;
|
||||
vb[i++] = y;
|
||||
|
||||
vb[i++] = glyph_x;
|
||||
vb[i++] = glyph_y;
|
||||
|
||||
if (setup->composite->src.type == OPERAND_TEXTURE) {
|
||||
double s = x;
|
||||
double t = y;
|
||||
cairo_matrix_transform_point (&src_attributes->matrix, &s, &t);
|
||||
vb[i++] = s;
|
||||
vb[i++] = t;
|
||||
}
|
||||
|
||||
setup->vb_offset += setup->vertex_size;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_cairo_gl_emit_glyph_rectangle (cairo_gl_context_t *ctx,
|
||||
cairo_gl_glyphs_setup_t *setup,
|
||||
int x1, int y1,
|
||||
int x2, int y2,
|
||||
cairo_gl_glyph_private_t *glyph)
|
||||
{
|
||||
if (setup->vb != NULL &&
|
||||
setup->vb_offset + 4 * setup->vertex_size > setup->vbo_size) {
|
||||
_cairo_gl_flush_glyphs (ctx, setup);
|
||||
}
|
||||
|
||||
if (setup->vb == NULL) {
|
||||
glBufferDataARB (GL_ARRAY_BUFFER_ARB,
|
||||
setup->vbo_size * sizeof (GLfloat),
|
||||
NULL, GL_STREAM_DRAW_ARB);
|
||||
setup->vb = glMapBufferARB (GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
|
||||
setup->vb_offset = 0;
|
||||
}
|
||||
|
||||
_cairo_gl_glyphs_emit_vertex (setup, x1, y1, glyph->p1.x, glyph->p1.y);
|
||||
_cairo_gl_glyphs_emit_vertex (setup, x2, y1, glyph->p2.x, glyph->p1.y);
|
||||
_cairo_gl_glyphs_emit_vertex (setup, x2, y2, glyph->p2.x, glyph->p2.y);
|
||||
_cairo_gl_glyphs_emit_vertex (setup, x1, y2, glyph->p1.x, glyph->p2.y);
|
||||
setup->num_prims++;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_render_glyphs (cairo_gl_surface_t *dst,
|
||||
int dst_x, int dst_y,
|
||||
|
@ -345,106 +232,51 @@ _render_glyphs (cairo_gl_surface_t *dst,
|
|||
cairo_region_t *clip_region,
|
||||
int *remaining_glyphs)
|
||||
{
|
||||
cairo_format_t last_format = (cairo_format_t) -1;
|
||||
cairo_format_t last_format = CAIRO_FORMAT_INVALID;
|
||||
cairo_gl_glyph_cache_t *cache = NULL;
|
||||
cairo_gl_context_t *ctx;
|
||||
cairo_gl_glyphs_setup_t setup;
|
||||
cairo_gl_composite_setup_t composite_setup;
|
||||
cairo_gl_composite_t setup;
|
||||
cairo_status_t status;
|
||||
int i = 0;
|
||||
GLuint vbo = 0;
|
||||
|
||||
*has_component_alpha = FALSE;
|
||||
|
||||
status = _cairo_gl_operand_init (&composite_setup.src, source, dst,
|
||||
glyph_extents->x, glyph_extents->y,
|
||||
dst_x, dst_y,
|
||||
glyph_extents->width,
|
||||
glyph_extents->height);
|
||||
status = _cairo_gl_context_acquire (dst->base.device, &ctx);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
ctx = _cairo_gl_context_acquire (dst->ctx);
|
||||
|
||||
/* Set up the IN operator for source IN mask.
|
||||
*
|
||||
* IN (normal, any op): dst.argb = src.argb * mask.aaaa
|
||||
* IN (component, ADD): dst.argb = src.argb * mask.argb
|
||||
*
|
||||
* The mask channel selection for component alpha ADD will be updated in
|
||||
* the loop over glyphs below.
|
||||
*/
|
||||
glActiveTexture (GL_TEXTURE1);
|
||||
glEnable (GL_TEXTURE_2D);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
|
||||
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE1);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE1);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
|
||||
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PREVIOUS);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
|
||||
|
||||
_cairo_gl_set_destination (dst);
|
||||
/* If we're doing some CA glyphs, we're only doing it for ADD,
|
||||
* which doesn't require the source alpha value in blending.
|
||||
*/
|
||||
_cairo_gl_set_operator (dst, op, FALSE);
|
||||
_cairo_gl_set_src_operand (ctx, &composite_setup);
|
||||
|
||||
_cairo_scaled_font_freeze_cache (scaled_font);
|
||||
|
||||
status = _cairo_gl_composite_init (&setup, op, dst,
|
||||
TRUE, glyph_extents);
|
||||
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
if (! _cairo_gl_surface_owns_font (dst, scaled_font)) {
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
goto CLEANUP_FONT;
|
||||
goto FINISH;
|
||||
}
|
||||
|
||||
status = _cairo_gl_composite_set_source (&setup, source,
|
||||
glyph_extents->x, glyph_extents->y,
|
||||
dst_x, dst_y,
|
||||
glyph_extents->width,
|
||||
glyph_extents->height);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
if (scaled_font->surface_private == NULL) {
|
||||
/* XXX couple into list to remove on context destruction */
|
||||
scaled_font->surface_private = ctx;
|
||||
scaled_font->surface_backend = &_cairo_gl_surface_backend;
|
||||
cairo_list_add (&scaled_font->link, &ctx->fonts);
|
||||
}
|
||||
|
||||
/* Create our VBO so that we can accumulate a bunch of glyph primitives
|
||||
* into one giant DrawArrays.
|
||||
*/
|
||||
memset(&setup, 0, sizeof(setup));
|
||||
setup.composite = &composite_setup;
|
||||
setup.clip = clip_region;
|
||||
setup.dst = dst;
|
||||
setup.vertex_size = 4;
|
||||
if (composite_setup.src.type == OPERAND_TEXTURE)
|
||||
setup.vertex_size += 2;
|
||||
setup.vbo_size = num_glyphs * 4 * setup.vertex_size;
|
||||
if (setup.vbo_size > 4096)
|
||||
setup.vbo_size = 4096;
|
||||
|
||||
glGenBuffersARB (1, &vbo);
|
||||
glBindBufferARB (GL_ARRAY_BUFFER_ARB, vbo);
|
||||
|
||||
glVertexPointer (2, GL_FLOAT, setup.vertex_size * sizeof (GLfloat),
|
||||
(void *)(uintptr_t)(0));
|
||||
glEnableClientState (GL_VERTEX_ARRAY);
|
||||
if (composite_setup.src.type == OPERAND_TEXTURE) {
|
||||
/* Note that we're packing texcoord 0 after texcoord 1, for
|
||||
* convenience.
|
||||
*/
|
||||
glClientActiveTexture (GL_TEXTURE0);
|
||||
glTexCoordPointer (2, GL_FLOAT, setup.vertex_size * sizeof (GLfloat),
|
||||
(void *)(uintptr_t)(4 * sizeof (GLfloat)));
|
||||
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
glClientActiveTexture (GL_TEXTURE1);
|
||||
glTexCoordPointer (2, GL_FLOAT, setup.vertex_size * sizeof (GLfloat),
|
||||
(void *)(uintptr_t)(2 * sizeof (GLfloat)));
|
||||
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||
_cairo_gl_composite_set_clip_region (&setup, clip_region);
|
||||
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
cairo_gl_glyph_private_t *glyph;
|
||||
double x_offset, y_offset;
|
||||
double x1, x2, y1, y2;
|
||||
|
||||
|
@ -468,39 +300,40 @@ _render_glyphs (cairo_gl_surface_t *dst,
|
|||
}
|
||||
|
||||
if (scaled_glyph->surface->format != last_format) {
|
||||
/* Switching textures, so flush any queued prims. */
|
||||
_cairo_gl_flush_glyphs (ctx, &setup);
|
||||
|
||||
glActiveTexture (GL_TEXTURE1);
|
||||
cache = cairo_gl_context_get_glyph_cache (ctx,
|
||||
scaled_glyph->surface->format);
|
||||
|
||||
glBindTexture (GL_TEXTURE_2D, cache->tex);
|
||||
status = cairo_gl_context_get_glyph_cache (ctx,
|
||||
scaled_glyph->surface->format,
|
||||
&cache);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
last_format = scaled_glyph->surface->format;
|
||||
/* If we're doing component alpha in this function, it should
|
||||
* only be in the case of CAIRO_OPERATOR_ADD. In that case, we just
|
||||
* need to make sure we send the rgb bits down to the destination.
|
||||
*/
|
||||
if (last_format == CAIRO_FORMAT_ARGB32) {
|
||||
assert (op == CAIRO_OPERATOR_ADD);
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
||||
*has_component_alpha = TRUE;
|
||||
} else {
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA);
|
||||
}
|
||||
|
||||
/* XXX component alpha */
|
||||
status = _cairo_gl_composite_set_mask (&setup,
|
||||
&cache->pattern.base,
|
||||
0, 0, 0, 0, 0, 0);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
*has_component_alpha |= cache->pattern.base.has_component_alpha;
|
||||
|
||||
/* XXX: _cairo_gl_composite_begin() acquires the context a
|
||||
* second time. Need to refactor this loop so this doesn't happen.
|
||||
*/
|
||||
status = _cairo_gl_composite_begin (&setup, &ctx);
|
||||
|
||||
status = _cairo_gl_context_release (ctx, status);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
}
|
||||
|
||||
if (scaled_glyph->surface_private == NULL) {
|
||||
status = _cairo_gl_glyph_cache_add_glyph (cache, scaled_glyph);
|
||||
status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph);
|
||||
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
/* Cache is full, so flush existing prims and try again. */
|
||||
_cairo_gl_flush_glyphs (ctx, &setup);
|
||||
_cairo_gl_composite_flush (ctx);
|
||||
_cairo_gl_glyph_cache_unlock (cache);
|
||||
status = _cairo_gl_glyph_cache_add_glyph (cache, scaled_glyph);
|
||||
status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph);
|
||||
}
|
||||
|
||||
if (unlikely (_cairo_status_is_error (status)))
|
||||
|
@ -515,40 +348,20 @@ _render_glyphs (cairo_gl_surface_t *dst,
|
|||
x2 = x1 + scaled_glyph->surface->width;
|
||||
y2 = y1 + scaled_glyph->surface->height;
|
||||
|
||||
_cairo_gl_emit_glyph_rectangle (ctx, &setup,
|
||||
glyph = _cairo_gl_glyph_cache_lock (cache, scaled_glyph);
|
||||
_cairo_gl_composite_emit_glyph (ctx,
|
||||
x1, y1, x2, y2,
|
||||
_cairo_gl_glyph_cache_lock (cache, scaled_glyph));
|
||||
glyph->p1.x, glyph->p1.y,
|
||||
glyph->p2.x, glyph->p2.y);
|
||||
}
|
||||
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
FINISH:
|
||||
_cairo_gl_flush_glyphs (ctx, &setup);
|
||||
CLEANUP_FONT:
|
||||
_cairo_scaled_font_thaw_cache (scaled_font);
|
||||
|
||||
glDisable (GL_BLEND);
|
||||
glDisable (GL_SCISSOR_TEST);
|
||||
status = _cairo_gl_context_release (ctx, status);
|
||||
|
||||
glDisableClientState (GL_VERTEX_ARRAY);
|
||||
|
||||
glClientActiveTexture (GL_TEXTURE0);
|
||||
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||
glActiveTexture (GL_TEXTURE0);
|
||||
glDisable (GL_TEXTURE_2D);
|
||||
|
||||
glClientActiveTexture (GL_TEXTURE1);
|
||||
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||
glActiveTexture (GL_TEXTURE1);
|
||||
glDisable (GL_TEXTURE_2D);
|
||||
|
||||
if (vbo != 0) {
|
||||
glBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
|
||||
glDeleteBuffersARB (1, &vbo);
|
||||
}
|
||||
|
||||
_cairo_gl_context_release (ctx);
|
||||
|
||||
_cairo_gl_operand_destroy (&composite_setup.src);
|
||||
_cairo_gl_composite_fini (&setup);
|
||||
|
||||
*remaining_glyphs = num_glyphs - i;
|
||||
return status;
|
||||
|
@ -567,26 +380,25 @@ _cairo_gl_surface_show_glyphs_via_mask (cairo_gl_surface_t *dst,
|
|||
{
|
||||
cairo_surface_t *mask;
|
||||
cairo_status_t status;
|
||||
cairo_solid_pattern_t solid;
|
||||
cairo_bool_t has_component_alpha;
|
||||
int i;
|
||||
|
||||
/* XXX: For non-CA, this should be CAIRO_CONTENT_ALPHA to save memory */
|
||||
mask = cairo_gl_surface_create (dst->ctx,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
glyph_extents->width,
|
||||
glyph_extents->height);
|
||||
mask = cairo_gl_surface_create (dst->base.device,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
glyph_extents->width,
|
||||
glyph_extents->height);
|
||||
if (unlikely (mask->status))
|
||||
return mask->status;
|
||||
return mask->status;
|
||||
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
glyphs[i].x -= glyph_extents->x;
|
||||
glyphs[i].y -= glyph_extents->y;
|
||||
}
|
||||
|
||||
_cairo_pattern_init_solid (&solid, CAIRO_COLOR_WHITE, CAIRO_CONTENT_COLOR_ALPHA);
|
||||
status = _render_glyphs ((cairo_gl_surface_t *) mask, 0, 0,
|
||||
CAIRO_OPERATOR_ADD, &solid.base,
|
||||
CAIRO_OPERATOR_ADD,
|
||||
&_cairo_pattern_white.base,
|
||||
glyphs, num_glyphs, glyph_extents,
|
||||
scaled_font, &has_component_alpha,
|
||||
NULL, remaining_glyphs);
|
||||
|
@ -610,6 +422,7 @@ _cairo_gl_surface_show_glyphs_via_mask (cairo_gl_surface_t *dst,
|
|||
}
|
||||
|
||||
cairo_surface_destroy (mask);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -627,15 +440,11 @@ _cairo_gl_surface_show_glyphs (void *abstract_dst,
|
|||
cairo_rectangle_int_t surface_extents;
|
||||
cairo_rectangle_int_t extents;
|
||||
cairo_region_t *clip_region = NULL;
|
||||
cairo_solid_pattern_t solid_pattern;
|
||||
cairo_bool_t overlap, use_mask = FALSE;
|
||||
cairo_bool_t has_component_alpha;
|
||||
cairo_status_t status;
|
||||
int i;
|
||||
|
||||
if (! GLEW_ARB_vertex_buffer_object)
|
||||
return UNSUPPORTED ("requires ARB_vertex_buffer_object");
|
||||
|
||||
if (! _cairo_gl_operator_is_supported (op))
|
||||
return UNSUPPORTED ("unsupported operator");
|
||||
|
||||
|
@ -646,18 +455,20 @@ _cairo_gl_surface_show_glyphs (void *abstract_dst,
|
|||
* since only _cairo_gl_surface_composite() currently supports component
|
||||
* alpha.
|
||||
*/
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
if (!use_mask && op != CAIRO_OPERATOR_OVER) {
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
glyphs[i].index,
|
||||
CAIRO_SCALED_GLYPH_INFO_SURFACE,
|
||||
&scaled_glyph);
|
||||
if (!_cairo_status_is_error (status) &&
|
||||
scaled_glyph->surface->format == CAIRO_FORMAT_ARGB32)
|
||||
{
|
||||
use_mask = TRUE;
|
||||
break;
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
glyphs[i].index,
|
||||
CAIRO_SCALED_GLYPH_INFO_SURFACE,
|
||||
&scaled_glyph);
|
||||
if (!_cairo_status_is_error (status) &&
|
||||
scaled_glyph->surface->format == CAIRO_FORMAT_ARGB32)
|
||||
{
|
||||
use_mask = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -682,9 +493,7 @@ _cairo_gl_surface_show_glyphs (void *abstract_dst,
|
|||
* mask IN clip ? 0 : dest
|
||||
*/
|
||||
if (op == CAIRO_OPERATOR_CLEAR) {
|
||||
_cairo_pattern_init_solid (&solid_pattern, CAIRO_COLOR_WHITE,
|
||||
CAIRO_CONTENT_COLOR);
|
||||
source = &solid_pattern.base;
|
||||
source = &_cairo_pattern_white.base;
|
||||
op = CAIRO_OPERATOR_DEST_OUT;
|
||||
}
|
||||
|
||||
|
@ -772,26 +581,25 @@ EMPTY:
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_gl_glyph_cache_fini (cairo_gl_glyph_cache_t *cache)
|
||||
{
|
||||
if (cache->tex == 0)
|
||||
return;
|
||||
|
||||
glDeleteTextures (1, &cache->tex);
|
||||
|
||||
_cairo_rtree_fini (&cache->rtree);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_gl_glyph_cache_init (cairo_gl_glyph_cache_t *cache)
|
||||
{
|
||||
cache->tex = 0;
|
||||
|
||||
_cairo_rtree_init (&cache->rtree,
|
||||
GLYPH_CACHE_WIDTH,
|
||||
GLYPH_CACHE_HEIGHT,
|
||||
GLYPH_CACHE_MIN_SIZE,
|
||||
sizeof (cairo_gl_glyph_private_t),
|
||||
NULL);
|
||||
sizeof (cairo_gl_glyph_private_t));
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_gl_glyph_cache_fini (cairo_gl_context_t *ctx,
|
||||
cairo_gl_glyph_cache_t *cache)
|
||||
{
|
||||
_cairo_rtree_fini (&cache->rtree);
|
||||
|
||||
if (cache->pattern.surface) {
|
||||
_cairo_pattern_fini (&cache->pattern.base);
|
||||
cache->pattern.surface = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* Copyright © 2009 Eric Anholt
|
||||
* Copyright © 2009 Chris Wilson
|
||||
* Copyright © 2005 Red Hat, Inc
|
||||
* Copyright © 2005,2010 Red Hat, Inc
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
|
@ -14,7 +14,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -32,16 +32,26 @@
|
|||
* The Initial Developer of the Original Code is Red Hat, Inc.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Benjamin Otte <otte@gnome.org>
|
||||
* Carl Worth <cworth@cworth.org>
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
* T. Zachary Laine <whatwasthataddress@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_GL_PRIVATE_H
|
||||
#define CAIRO_GL_PRIVATE_H
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-gl-gradient-private.h"
|
||||
|
||||
#include "cairo-device-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-rtree-private.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include "cairo-gl.h"
|
||||
|
@ -63,51 +73,75 @@
|
|||
#define UNSUPPORTED(reason) CAIRO_INT_STATUS_UNSUPPORTED
|
||||
#endif
|
||||
|
||||
/* maximal number of shaders we keep in the cache.
|
||||
* Random number that is hopefully big enough to not cause many cache evictions. */
|
||||
#define CAIRO_GL_MAX_SHADERS_PER_CONTEXT 64
|
||||
|
||||
/* VBO size that we allocate, smaller size means we gotta flush more often */
|
||||
#define CAIRO_GL_VBO_SIZE 16384
|
||||
|
||||
typedef struct _cairo_gl_surface {
|
||||
cairo_surface_t base;
|
||||
|
||||
cairo_gl_context_t *ctx;
|
||||
int width, height;
|
||||
|
||||
GLuint tex; /* GL texture object containing our data. */
|
||||
GLuint fb; /* GL framebuffer object wrapping our data. */
|
||||
GLuint depth; /* GL framebuffer object holding depth */
|
||||
int owns_tex;
|
||||
} cairo_gl_surface_t;
|
||||
|
||||
typedef struct cairo_gl_glyph_cache {
|
||||
cairo_rtree_t rtree;
|
||||
GLuint tex;
|
||||
unsigned int width, height;
|
||||
cairo_surface_pattern_t pattern;
|
||||
} cairo_gl_glyph_cache_t;
|
||||
|
||||
struct _cairo_gl_context {
|
||||
cairo_reference_count_t ref_count;
|
||||
cairo_status_t status;
|
||||
typedef enum cairo_gl_tex {
|
||||
CAIRO_GL_TEX_SOURCE = 0,
|
||||
CAIRO_GL_TEX_MASK = 1,
|
||||
CAIRO_GL_TEX_TEMP = 2
|
||||
} cairo_gl_tex_t;
|
||||
|
||||
cairo_mutex_t mutex; /* needed? */
|
||||
GLuint dummy_tex;
|
||||
GLint fill_rectangles_shader;
|
||||
GLint fill_rectangles_color_uniform;
|
||||
GLint max_framebuffer_size;
|
||||
GLint max_texture_size;
|
||||
typedef enum cairo_gl_operand_type {
|
||||
CAIRO_GL_OPERAND_NONE,
|
||||
CAIRO_GL_OPERAND_CONSTANT,
|
||||
CAIRO_GL_OPERAND_TEXTURE,
|
||||
CAIRO_GL_OPERAND_LINEAR_GRADIENT,
|
||||
CAIRO_GL_OPERAND_RADIAL_GRADIENT,
|
||||
CAIRO_GL_OPERAND_SPANS,
|
||||
|
||||
cairo_gl_surface_t *current_target;
|
||||
cairo_gl_glyph_cache_t glyph_cache[2];
|
||||
CAIRO_GL_OPERAND_COUNT
|
||||
} cairo_gl_operand_type_t;
|
||||
|
||||
void (*make_current)(void *ctx, cairo_gl_surface_t *surface);
|
||||
void (*swap_buffers)(void *ctx, cairo_gl_surface_t *surface);
|
||||
void (*destroy) (void *ctx);
|
||||
};
|
||||
typedef struct cairo_gl_shader_impl cairo_gl_shader_impl_t;
|
||||
|
||||
enum cairo_gl_composite_operand_type {
|
||||
OPERAND_CONSTANT,
|
||||
OPERAND_TEXTURE,
|
||||
};
|
||||
typedef struct cairo_gl_shader {
|
||||
GLuint fragment_shader;
|
||||
GLuint program;
|
||||
} cairo_gl_shader_t;
|
||||
|
||||
typedef enum cairo_gl_shader_in {
|
||||
CAIRO_GL_SHADER_IN_NORMAL,
|
||||
CAIRO_GL_SHADER_IN_CA_SOURCE,
|
||||
CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA,
|
||||
|
||||
CAIRO_GL_SHADER_IN_COUNT
|
||||
} cairo_gl_shader_in_t;
|
||||
|
||||
typedef enum cairo_gl_var_type {
|
||||
CAIRO_GL_VAR_NONE,
|
||||
CAIRO_GL_VAR_TEXCOORDS,
|
||||
CAIRO_GL_VAR_COVERAGE
|
||||
} cairo_gl_var_type_t;
|
||||
|
||||
#define cairo_gl_var_type_hash(src,mask,dest) ((mask) << 2 | (src << 1) | (dest))
|
||||
#define CAIRO_GL_VAR_TYPE_MAX ((CAIRO_GL_VAR_COVERAGE << 2) | (CAIRO_GL_VAR_TEXCOORDS << 1) | CAIRO_GL_VAR_TEXCOORDS)
|
||||
|
||||
/* This union structure describes a potential source or mask operand to the
|
||||
* compositing equation.
|
||||
*/
|
||||
typedef struct cairo_gl_composite_operand {
|
||||
enum cairo_gl_composite_operand_type type;
|
||||
typedef struct cairo_gl_operand {
|
||||
cairo_gl_operand_type_t type;
|
||||
union {
|
||||
struct {
|
||||
GLuint tex;
|
||||
|
@ -117,30 +151,111 @@ typedef struct cairo_gl_composite_operand {
|
|||
struct {
|
||||
GLfloat color[4];
|
||||
} constant;
|
||||
} operand;
|
||||
struct {
|
||||
cairo_gl_gradient_t *gradient;
|
||||
cairo_matrix_t m;
|
||||
float segment_x;
|
||||
float segment_y;
|
||||
cairo_extend_t extend;
|
||||
} linear;
|
||||
struct {
|
||||
cairo_gl_gradient_t *gradient;
|
||||
cairo_matrix_t m;
|
||||
float circle_1_x;
|
||||
float circle_1_y;
|
||||
float radius_0;
|
||||
float radius_1;
|
||||
cairo_extend_t extend;
|
||||
} radial;
|
||||
};
|
||||
unsigned int vertex_offset;
|
||||
} cairo_gl_operand_t;
|
||||
|
||||
const cairo_pattern_t *pattern;
|
||||
} cairo_gl_composite_operand_t;
|
||||
struct _cairo_gl_context {
|
||||
cairo_device_t base;
|
||||
|
||||
typedef struct _cairo_gl_composite_setup {
|
||||
cairo_gl_composite_operand_t src;
|
||||
cairo_gl_composite_operand_t mask;
|
||||
} cairo_gl_composite_setup_t;
|
||||
GLuint dummy_tex;
|
||||
GLuint texture_load_pbo;
|
||||
GLuint vbo;
|
||||
GLint max_framebuffer_size;
|
||||
GLint max_texture_size;
|
||||
GLint max_textures;
|
||||
GLenum tex_target;
|
||||
|
||||
const cairo_gl_shader_impl_t *shader_impl;
|
||||
|
||||
GLuint vertex_shaders[CAIRO_GL_VAR_TYPE_MAX + 1];
|
||||
cairo_gl_shader_t fill_rectangles_shader;
|
||||
cairo_cache_t shaders;
|
||||
|
||||
cairo_cache_t gradients;
|
||||
|
||||
cairo_gl_glyph_cache_t glyph_cache[2];
|
||||
cairo_list_t fonts;
|
||||
|
||||
cairo_gl_surface_t *current_target;
|
||||
cairo_operator_t current_operator;
|
||||
cairo_gl_shader_t *pre_shader; /* for component alpha */
|
||||
cairo_gl_shader_t *current_shader;
|
||||
|
||||
cairo_gl_operand_t operands[2];
|
||||
|
||||
char *vb;
|
||||
unsigned int vb_offset;
|
||||
unsigned int vertex_size;
|
||||
cairo_region_t *clip_region;
|
||||
|
||||
void (*acquire) (void *ctx);
|
||||
void (*release) (void *ctx);
|
||||
|
||||
void (*make_current) (void *ctx, cairo_gl_surface_t *surface);
|
||||
void (*swap_buffers)(void *ctx, cairo_gl_surface_t *surface);
|
||||
void (*destroy) (void *ctx);
|
||||
};
|
||||
|
||||
typedef struct _cairo_gl_composite {
|
||||
cairo_gl_surface_t *dst;
|
||||
cairo_operator_t op;
|
||||
cairo_region_t *clip_region;
|
||||
|
||||
cairo_gl_operand_t src;
|
||||
cairo_gl_operand_t mask;
|
||||
} cairo_gl_composite_t;
|
||||
|
||||
cairo_private extern const cairo_surface_backend_t _cairo_gl_surface_backend;
|
||||
|
||||
cairo_private cairo_gl_context_t *
|
||||
_cairo_gl_context_create_in_error (cairo_status_t status);
|
||||
static cairo_always_inline GLenum
|
||||
_cairo_gl_get_error (void)
|
||||
{
|
||||
GLenum err = glGetError();
|
||||
|
||||
if (unlikely (err))
|
||||
while (glGetError ());
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline cairo_device_t *
|
||||
_cairo_gl_context_create_in_error (cairo_status_t status)
|
||||
{
|
||||
return (cairo_device_t *) _cairo_device_create_in_error (status);
|
||||
}
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gl_context_init (cairo_gl_context_t *ctx);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_surface_init (cairo_gl_context_t *ctx,
|
||||
_cairo_gl_surface_init (cairo_device_t *device,
|
||||
cairo_gl_surface_t *surface,
|
||||
cairo_content_t content,
|
||||
int width, int height);
|
||||
|
||||
static cairo_always_inline cairo_bool_t cairo_warn
|
||||
_cairo_gl_surface_is_texture (cairo_gl_surface_t *surface)
|
||||
{
|
||||
return surface->tex != 0;
|
||||
}
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
|
||||
cairo_image_surface_t *src,
|
||||
|
@ -148,42 +263,133 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
|
|||
int width, int height,
|
||||
int dst_x, int dst_y);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_gl_operand_init (cairo_gl_composite_operand_t *operand,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_gl_surface_t *dst,
|
||||
int src_x, int src_y,
|
||||
int dst_x, int dst_y,
|
||||
int width, int height);
|
||||
static cairo_always_inline cairo_bool_t
|
||||
_cairo_gl_device_has_glsl (cairo_device_t *device)
|
||||
{
|
||||
return ((cairo_gl_context_t *) device)->shader_impl != NULL;
|
||||
}
|
||||
|
||||
cairo_private cairo_gl_context_t *
|
||||
_cairo_gl_context_acquire (cairo_gl_context_t *ctx);
|
||||
static cairo_always_inline cairo_bool_t
|
||||
_cairo_gl_device_requires_power_of_two_textures (cairo_device_t *device)
|
||||
{
|
||||
return ((cairo_gl_context_t *) device)->tex_target == GL_TEXTURE_RECTANGLE_EXT;
|
||||
}
|
||||
|
||||
static cairo_always_inline cairo_status_t cairo_warn
|
||||
_cairo_gl_context_acquire (cairo_device_t *device,
|
||||
cairo_gl_context_t **ctx)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
status = cairo_device_acquire (device);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
/* clear potential previous GL errors */
|
||||
_cairo_gl_get_error ();
|
||||
|
||||
*ctx = (cairo_gl_context_t *) device;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_always_inline cairo_warn cairo_status_t
|
||||
_cairo_gl_context_release (cairo_gl_context_t *ctx, cairo_status_t status)
|
||||
{
|
||||
GLenum err;
|
||||
|
||||
err = _cairo_gl_get_error ();
|
||||
|
||||
if (unlikely (err)) {
|
||||
cairo_status_t new_status;
|
||||
new_status = _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = new_status;
|
||||
}
|
||||
|
||||
cairo_device_release (&(ctx)->base);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_context_release (cairo_gl_context_t *ctx);
|
||||
_cairo_gl_context_set_destination (cairo_gl_context_t *ctx, cairo_gl_surface_t *surface);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_set_destination (cairo_gl_surface_t *surface);
|
||||
_cairo_gl_context_activate (cairo_gl_context_t *ctx,
|
||||
cairo_gl_tex_t tex_unit);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_gl_operator_is_supported (cairo_operator_t op);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_set_operator (cairo_gl_surface_t *dst, cairo_operator_t op,
|
||||
cairo_bool_t component_alpha);
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gl_composite_init (cairo_gl_composite_t *setup,
|
||||
cairo_operator_t op,
|
||||
cairo_gl_surface_t *dst,
|
||||
cairo_bool_t has_component_alpha,
|
||||
const cairo_rectangle_int_t *rect);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
|
||||
cairo_gl_composite_setup_t *setup);
|
||||
_cairo_gl_composite_fini (cairo_gl_composite_t *setup);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_operand_destroy (cairo_gl_composite_operand_t *operand);
|
||||
_cairo_gl_composite_set_clip_region (cairo_gl_composite_t *setup,
|
||||
cairo_region_t *clip_region);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_gl_composite_set_source (cairo_gl_composite_t *setup,
|
||||
const cairo_pattern_t *pattern,
|
||||
int src_x, int src_y,
|
||||
int dst_x, int dst_y,
|
||||
int width, int height);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_gl_composite_set_mask (cairo_gl_composite_t *setup,
|
||||
const cairo_pattern_t *pattern,
|
||||
int src_x, int src_y,
|
||||
int dst_x, int dst_y,
|
||||
int width, int height);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_composite_set_mask_spans (cairo_gl_composite_t *setup);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gl_composite_begin (cairo_gl_composite_t *setup,
|
||||
cairo_gl_context_t **ctx);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_composite_emit_rect (cairo_gl_context_t *ctx,
|
||||
GLfloat x1,
|
||||
GLfloat y1,
|
||||
GLfloat x2,
|
||||
GLfloat y2,
|
||||
uint8_t alpha);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_composite_emit_glyph (cairo_gl_context_t *ctx,
|
||||
GLfloat x1,
|
||||
GLfloat y1,
|
||||
GLfloat x2,
|
||||
GLfloat y2,
|
||||
GLfloat glyph_x1,
|
||||
GLfloat glyph_y1,
|
||||
GLfloat glyph_x2,
|
||||
GLfloat glyph_y2);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_composite_flush (cairo_gl_context_t *ctx);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_context_destroy_operand (cairo_gl_context_t *ctx,
|
||||
cairo_gl_tex_t tex_unit);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_gl_get_image_format_and_type (pixman_format_code_t pixman_format,
|
||||
GLenum *internal_format, GLenum *format,
|
||||
GLenum *type, cairo_bool_t *has_alpha);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_surface_scaled_font_fini ( cairo_scaled_font_t *scaled_font);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
|
||||
cairo_scaled_font_t *scaled_font);
|
||||
|
@ -191,6 +397,10 @@ _cairo_gl_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
|
|||
cairo_private void
|
||||
_cairo_gl_glyph_cache_init (cairo_gl_glyph_cache_t *cache);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_glyph_cache_fini (cairo_gl_context_t *ctx,
|
||||
cairo_gl_glyph_cache_t *cache);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_gl_surface_show_glyphs (void *abstract_dst,
|
||||
cairo_operator_t op,
|
||||
|
@ -201,13 +411,6 @@ _cairo_gl_surface_show_glyphs (void *abstract_dst,
|
|||
cairo_clip_t *clip,
|
||||
int *remaining_glyphs);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_glyph_cache_fini (cairo_gl_glyph_cache_t *cache);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gl_load_glsl (GLint *shader,
|
||||
const char *vs_source, const char *fs_source);
|
||||
|
||||
static inline int
|
||||
_cairo_gl_y_flip (cairo_gl_surface_t *surface, int y)
|
||||
{
|
||||
|
@ -217,6 +420,66 @@ _cairo_gl_y_flip (cairo_gl_surface_t *surface, int y)
|
|||
return (surface->height - 1) - y;
|
||||
}
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gl_context_init_shaders (cairo_gl_context_t *ctx);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_context_fini_shaders (cairo_gl_context_t *ctx);
|
||||
|
||||
static cairo_always_inline cairo_bool_t
|
||||
_cairo_gl_context_is_flushed (cairo_gl_context_t *ctx)
|
||||
{
|
||||
return ctx->vb == NULL;
|
||||
}
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx,
|
||||
cairo_gl_operand_type_t source,
|
||||
cairo_gl_operand_type_t mask,
|
||||
cairo_gl_shader_in_t in,
|
||||
cairo_gl_shader_t **shader);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_shader_bind_float (cairo_gl_context_t *ctx,
|
||||
const char *name,
|
||||
float value);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_shader_bind_vec2 (cairo_gl_context_t *ctx,
|
||||
const char *name,
|
||||
float value0, float value1);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_shader_bind_vec3 (cairo_gl_context_t *ctx,
|
||||
const char *name,
|
||||
float value0,
|
||||
float value1,
|
||||
float value2);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_shader_bind_vec4 (cairo_gl_context_t *ctx,
|
||||
const char *name,
|
||||
float value0, float value1,
|
||||
float value2, float value3);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx,
|
||||
const char *name,
|
||||
cairo_matrix_t* m);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_shader_bind_texture (cairo_gl_context_t *ctx,
|
||||
const char *name,
|
||||
GLuint tex_unit);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_set_shader (cairo_gl_context_t *ctx,
|
||||
cairo_gl_shader_t *shader);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_shader_fini (cairo_gl_context_t *ctx, cairo_gl_shader_t *shader);
|
||||
|
||||
slim_hidden_proto (cairo_gl_surface_create);
|
||||
slim_hidden_proto (cairo_gl_surface_create_for_texture);
|
||||
|
||||
#endif /* CAIRO_GL_PRIVATE_H */
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -40,19 +40,16 @@
|
|||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
typedef struct _cairo_gl_context cairo_gl_context_t;
|
||||
|
||||
cairo_public cairo_gl_context_t *
|
||||
cairo_gl_context_reference (cairo_gl_context_t *context);
|
||||
|
||||
cairo_public void
|
||||
cairo_gl_context_destroy (cairo_gl_context_t *context);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_gl_surface_create (cairo_gl_context_t *ctx,
|
||||
cairo_gl_surface_create (cairo_device_t *device,
|
||||
cairo_content_t content,
|
||||
int width, int height);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_gl_surface_create_for_texture (cairo_device_t *abstract_device,
|
||||
cairo_content_t content,
|
||||
unsigned int tex,
|
||||
int width, int height);
|
||||
cairo_public void
|
||||
cairo_gl_surface_set_size (cairo_surface_t *surface, int width, int height);
|
||||
|
||||
|
@ -65,31 +62,52 @@ cairo_gl_surface_get_height (cairo_surface_t *abstract_surface);
|
|||
cairo_public void
|
||||
cairo_gl_surface_swapbuffers (cairo_surface_t *surface);
|
||||
|
||||
cairo_public cairo_status_t
|
||||
cairo_gl_surface_glfinish (cairo_surface_t *surface);
|
||||
|
||||
#if CAIRO_HAS_GLX_FUNCTIONS
|
||||
#include <GL/glx.h>
|
||||
|
||||
cairo_public cairo_gl_context_t *
|
||||
cairo_glx_context_create (Display *dpy, GLXContext gl_ctx);
|
||||
cairo_public cairo_device_t *
|
||||
cairo_glx_device_create (Display *dpy, GLXContext gl_ctx);
|
||||
|
||||
cairo_public Display *
|
||||
cairo_glx_device_get_display (cairo_device_t *device);
|
||||
|
||||
cairo_public GLXContext
|
||||
cairo_glx_device_get_context (cairo_device_t *device);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_gl_surface_create_for_window (cairo_gl_context_t *ctx,
|
||||
cairo_gl_surface_create_for_window (cairo_device_t *device,
|
||||
Window win,
|
||||
int width, int height);
|
||||
#endif
|
||||
|
||||
#if CAIRO_HAS_EAGLE_FUNCTIONS
|
||||
#include <eagle.h>
|
||||
#if CAIRO_HAS_WGL_FUNCTIONS
|
||||
#include <windows.h>
|
||||
|
||||
cairo_public cairo_gl_context_t *
|
||||
cairo_eagle_context_create (EGLDisplay display, EGLContext context);
|
||||
cairo_public cairo_device_t *
|
||||
cairo_wgl_device_create (HGLRC rc);
|
||||
|
||||
cairo_public HGLRC
|
||||
cairo_wgl_device_get_context (cairo_device_t *device);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_gl_surface_create_for_eagle (cairo_gl_context_t *ctx,
|
||||
EGLSurface surface,
|
||||
int width, int height);
|
||||
cairo_gl_surface_create_for_dc (cairo_device_t *device,
|
||||
HDC dc,
|
||||
int width,
|
||||
int height);
|
||||
#endif
|
||||
|
||||
#if CAIRO_HAS_EGL_FUNCTIONS
|
||||
#include <EGL/egl.h>
|
||||
|
||||
cairo_public cairo_device_t *
|
||||
cairo_egl_device_create (EGLDisplay dpy, EGLContext egl);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_gl_surface_create_for_egl (cairo_device_t *device,
|
||||
EGLSurface egl,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
#endif
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -40,6 +40,8 @@
|
|||
|
||||
#include "cairo-gl-private.h"
|
||||
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
/* XXX needs hooking into XCloseDisplay() */
|
||||
|
@ -59,8 +61,24 @@ typedef struct _cairo_glx_surface {
|
|||
} cairo_glx_surface_t;
|
||||
|
||||
static void
|
||||
_glx_make_current (void *abstract_ctx,
|
||||
cairo_gl_surface_t *abstract_surface)
|
||||
_glx_acquire (void *abstract_ctx)
|
||||
{
|
||||
cairo_glx_context_t *ctx = abstract_ctx;
|
||||
GLXDrawable current_drawable;
|
||||
|
||||
if (ctx->base.current_target == NULL ||
|
||||
_cairo_gl_surface_is_texture (ctx->base.current_target)) {
|
||||
current_drawable = ctx->dummy_window;
|
||||
} else {
|
||||
cairo_glx_surface_t *surface = (cairo_glx_surface_t *) ctx->base.current_target;
|
||||
current_drawable = surface->win;
|
||||
}
|
||||
|
||||
glXMakeCurrent (ctx->display, current_drawable, ctx->context);
|
||||
}
|
||||
|
||||
static void
|
||||
_glx_make_current (void *abstract_ctx, cairo_gl_surface_t *abstract_surface)
|
||||
{
|
||||
cairo_glx_context_t *ctx = abstract_ctx;
|
||||
cairo_glx_surface_t *surface = (cairo_glx_surface_t *) abstract_surface;
|
||||
|
@ -69,6 +87,14 @@ _glx_make_current (void *abstract_ctx,
|
|||
glXMakeCurrent (ctx->display, surface->win, ctx->context);
|
||||
}
|
||||
|
||||
static void
|
||||
_glx_release (void *abstract_ctx)
|
||||
{
|
||||
cairo_glx_context_t *ctx = abstract_ctx;
|
||||
|
||||
glXMakeCurrent (ctx->display, None, None);
|
||||
}
|
||||
|
||||
static void
|
||||
_glx_swap_buffers (void *abstract_ctx,
|
||||
cairo_gl_surface_t *abstract_surface)
|
||||
|
@ -86,6 +112,8 @@ _glx_destroy (void *abstract_ctx)
|
|||
|
||||
if (ctx->dummy_window != None)
|
||||
XDestroyWindow (ctx->display, ctx->dummy_window);
|
||||
|
||||
glXMakeCurrent (ctx->display, 0, 0);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
@ -140,8 +168,8 @@ _glx_dummy_ctx (Display *dpy, GLXContext gl_ctx, Window *dummy)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_gl_context_t *
|
||||
cairo_glx_context_create (Display *dpy, GLXContext gl_ctx)
|
||||
cairo_device_t *
|
||||
cairo_glx_device_create (Display *dpy, GLXContext gl_ctx)
|
||||
{
|
||||
cairo_glx_context_t *ctx;
|
||||
cairo_status_t status;
|
||||
|
@ -159,6 +187,8 @@ cairo_glx_context_create (Display *dpy, GLXContext gl_ctx)
|
|||
ctx->dummy_window = dummy;
|
||||
ctx->context = gl_ctx;
|
||||
|
||||
ctx->base.acquire = _glx_acquire;
|
||||
ctx->base.release = _glx_release;
|
||||
ctx->base.make_current = _glx_make_current;
|
||||
ctx->base.swap_buffers = _glx_swap_buffers;
|
||||
ctx->base.destroy = _glx_destroy;
|
||||
|
@ -169,25 +199,60 @@ cairo_glx_context_create (Display *dpy, GLXContext gl_ctx)
|
|||
return _cairo_gl_context_create_in_error (status);
|
||||
}
|
||||
|
||||
return &ctx->base;
|
||||
ctx->base.release (ctx);
|
||||
|
||||
return &ctx->base.base;
|
||||
}
|
||||
|
||||
Display *
|
||||
cairo_glx_device_get_display (cairo_device_t *device)
|
||||
{
|
||||
cairo_glx_context_t *ctx;
|
||||
|
||||
if (device->backend->type != CAIRO_DEVICE_TYPE_GL) {
|
||||
_cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx = (cairo_glx_context_t *) device;
|
||||
|
||||
return ctx->display;
|
||||
}
|
||||
|
||||
GLXContext
|
||||
cairo_glx_device_get_context (cairo_device_t *device)
|
||||
{
|
||||
cairo_glx_context_t *ctx;
|
||||
|
||||
if (device->backend->type != CAIRO_DEVICE_TYPE_GL) {
|
||||
_cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx = (cairo_glx_context_t *) device;
|
||||
|
||||
return ctx->context;
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_gl_surface_create_for_window (cairo_gl_context_t *ctx,
|
||||
Window win,
|
||||
int width,
|
||||
int height)
|
||||
cairo_gl_surface_create_for_window (cairo_device_t *device,
|
||||
Window win,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_glx_surface_t *surface;
|
||||
|
||||
if (unlikely (ctx->status))
|
||||
return _cairo_surface_create_in_error (ctx->status);
|
||||
if (unlikely (device->status))
|
||||
return _cairo_surface_create_in_error (device->status);
|
||||
|
||||
if (device->backend->type != CAIRO_DEVICE_TYPE_GL)
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
|
||||
|
||||
surface = calloc (1, sizeof (cairo_glx_surface_t));
|
||||
if (unlikely (surface == NULL))
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
|
||||
_cairo_gl_surface_init (ctx, &surface->base,
|
||||
_cairo_gl_surface_init (device, &surface->base,
|
||||
CAIRO_CONTENT_COLOR_ALPHA, width, height);
|
||||
surface->win = win;
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -60,13 +60,326 @@ struct _cairo_gstate {
|
|||
cairo_surface_t *parent_target; /* The previous target which was receiving rendering */
|
||||
cairo_surface_t *original_target; /* The original target the initial gstate was created with */
|
||||
|
||||
/* the user is allowed to update the device after we have cached the matrices... */
|
||||
cairo_observer_t device_transform_observer;
|
||||
|
||||
cairo_matrix_t ctm;
|
||||
cairo_matrix_t ctm_inverse;
|
||||
cairo_matrix_t source_ctm_inverse; /* At the time ->source was set */
|
||||
cairo_bool_t is_identity;
|
||||
|
||||
cairo_pattern_t *source;
|
||||
|
||||
struct _cairo_gstate *next;
|
||||
};
|
||||
|
||||
/* cairo-gstate.c */
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_init (cairo_gstate_t *gstate,
|
||||
cairo_surface_t *target);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gstate_fini (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_save (cairo_gstate_t **gstate, cairo_gstate_t **freelist);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_restore (cairo_gstate_t **gstate, cairo_gstate_t **freelist);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_gstate_is_redirected (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_gstate_get_target (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_gstate_get_parent_target (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_gstate_get_original_target (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_clip_t *
|
||||
_cairo_gstate_get_clip (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_set_source (cairo_gstate_t *gstate, cairo_pattern_t *source);
|
||||
|
||||
cairo_private cairo_pattern_t *
|
||||
_cairo_gstate_get_source (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_set_operator (cairo_gstate_t *gstate, cairo_operator_t op);
|
||||
|
||||
cairo_private cairo_operator_t
|
||||
_cairo_gstate_get_operator (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_set_tolerance (cairo_gstate_t *gstate, double tolerance);
|
||||
|
||||
cairo_private double
|
||||
_cairo_gstate_get_tolerance (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_set_fill_rule (cairo_gstate_t *gstate, cairo_fill_rule_t fill_rule);
|
||||
|
||||
cairo_private cairo_fill_rule_t
|
||||
_cairo_gstate_get_fill_rule (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_set_line_width (cairo_gstate_t *gstate, double width);
|
||||
|
||||
cairo_private double
|
||||
_cairo_gstate_get_line_width (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_set_line_cap (cairo_gstate_t *gstate, cairo_line_cap_t line_cap);
|
||||
|
||||
cairo_private cairo_line_cap_t
|
||||
_cairo_gstate_get_line_cap (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_set_line_join (cairo_gstate_t *gstate, cairo_line_join_t line_join);
|
||||
|
||||
cairo_private cairo_line_join_t
|
||||
_cairo_gstate_get_line_join (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_set_dash (cairo_gstate_t *gstate, const double *dash, int num_dashes, double offset);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gstate_get_dash (cairo_gstate_t *gstate, double *dash, int *num_dashes, double *offset);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_set_miter_limit (cairo_gstate_t *gstate, double limit);
|
||||
|
||||
cairo_private double
|
||||
_cairo_gstate_get_miter_limit (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gstate_get_matrix (cairo_gstate_t *gstate, cairo_matrix_t *matrix);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_scale (cairo_gstate_t *gstate, double sx, double sy);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_rotate (cairo_gstate_t *gstate, double angle);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_transform (cairo_gstate_t *gstate,
|
||||
const cairo_matrix_t *matrix);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_set_matrix (cairo_gstate_t *gstate,
|
||||
const cairo_matrix_t *matrix);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gstate_identity_matrix (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gstate_user_to_device (cairo_gstate_t *gstate, double *x, double *y);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gstate_user_to_device_distance (cairo_gstate_t *gstate, double *dx, double *dy);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gstate_device_to_user (cairo_gstate_t *gstate, double *x, double *y);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gstate_device_to_user_distance (cairo_gstate_t *gstate, double *dx, double *dy);
|
||||
|
||||
cairo_private void
|
||||
_do_cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y);
|
||||
|
||||
static inline void
|
||||
_cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y)
|
||||
{
|
||||
if (! gstate->is_identity)
|
||||
_do_cairo_gstate_user_to_backend (gstate, x, y);
|
||||
}
|
||||
|
||||
cairo_private void
|
||||
_do_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y);
|
||||
|
||||
static inline void
|
||||
_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y)
|
||||
{
|
||||
if (! gstate->is_identity)
|
||||
_do_cairo_gstate_backend_to_user (gstate, x, y);
|
||||
}
|
||||
|
||||
cairo_private void
|
||||
_cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate,
|
||||
double *x1, double *y1,
|
||||
double *x2, double *y2,
|
||||
cairo_bool_t *is_tight);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gstate_path_extents (cairo_gstate_t *gstate,
|
||||
cairo_path_fixed_t *path,
|
||||
double *x1, double *y1,
|
||||
double *x2, double *y2);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_paint (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_mask (cairo_gstate_t *gstate,
|
||||
cairo_pattern_t *mask);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_copy_page (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_show_page (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
|
||||
cairo_path_fixed_t *path,
|
||||
double *x1, double *y1,
|
||||
double *x2, double *y2);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_fill_extents (cairo_gstate_t *gstate,
|
||||
cairo_path_fixed_t *path,
|
||||
double *x1, double *y1,
|
||||
double *x2, double *y2);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_in_stroke (cairo_gstate_t *gstate,
|
||||
cairo_path_fixed_t *path,
|
||||
double x,
|
||||
double y,
|
||||
cairo_bool_t *inside_ret);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_gstate_in_fill (cairo_gstate_t *gstate,
|
||||
cairo_path_fixed_t *path,
|
||||
double x,
|
||||
double y);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_gstate_in_clip (cairo_gstate_t *gstate,
|
||||
double x,
|
||||
double y);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_reset_clip (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_gstate_clip_extents (cairo_gstate_t *gstate,
|
||||
double *x1,
|
||||
double *y1,
|
||||
double *x2,
|
||||
double *y2);
|
||||
|
||||
cairo_private cairo_rectangle_list_t*
|
||||
_cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_show_surface (cairo_gstate_t *gstate,
|
||||
cairo_surface_t *surface,
|
||||
double x,
|
||||
double y,
|
||||
double width,
|
||||
double height);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_select_font_face (cairo_gstate_t *gstate,
|
||||
const char *family,
|
||||
cairo_font_slant_t slant,
|
||||
cairo_font_weight_t weight);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_set_font_size (cairo_gstate_t *gstate,
|
||||
double size);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gstate_get_font_matrix (cairo_gstate_t *gstate,
|
||||
cairo_matrix_t *matrix);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_set_font_matrix (cairo_gstate_t *gstate,
|
||||
const cairo_matrix_t *matrix);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gstate_get_font_options (cairo_gstate_t *gstate,
|
||||
cairo_font_options_t *options);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gstate_set_font_options (cairo_gstate_t *gstate,
|
||||
const cairo_font_options_t *options);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_get_font_face (cairo_gstate_t *gstate,
|
||||
cairo_font_face_t **font_face);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_get_scaled_font (cairo_gstate_t *gstate,
|
||||
cairo_scaled_font_t **scaled_font);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_get_font_extents (cairo_gstate_t *gstate,
|
||||
cairo_font_extents_t *extents);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_set_font_face (cairo_gstate_t *gstate,
|
||||
cairo_font_face_t *font_face);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
|
||||
double x,
|
||||
double y,
|
||||
const char *utf8,
|
||||
int utf8_len,
|
||||
cairo_glyph_t **glyphs,
|
||||
int *num_glyphs,
|
||||
cairo_text_cluster_t **clusters,
|
||||
int *num_clusters,
|
||||
cairo_text_cluster_flags_t *cluster_flags);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_text_extents_t *extents);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
||||
const char *utf8,
|
||||
int utf8_len,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
const cairo_text_cluster_t *clusters,
|
||||
int num_clusters,
|
||||
cairo_text_cluster_flags_t cluster_flags);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_path_fixed_t *path);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_set_antialias (cairo_gstate_t *gstate,
|
||||
cairo_antialias_t antialias);
|
||||
|
||||
cairo_private cairo_antialias_t
|
||||
_cairo_gstate_get_antialias (cairo_gstate_t *gstate);
|
||||
|
||||
#endif /* CAIRO_GSTATE_PRIVATE_H */
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -35,11 +35,10 @@
|
|||
* Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-clip-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-gstate-private.h"
|
||||
|
||||
#if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE)
|
||||
|
@ -71,6 +70,18 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
|
|||
int *num_transformed_glyphs,
|
||||
cairo_text_cluster_t *transformed_clusters);
|
||||
|
||||
static void
|
||||
_cairo_gstate_update_device_transform (cairo_observer_t *observer,
|
||||
void *arg)
|
||||
{
|
||||
cairo_gstate_t *gstate = cairo_container_of (observer,
|
||||
cairo_gstate_t,
|
||||
device_transform_observer);
|
||||
|
||||
gstate->is_identity = (_cairo_matrix_is_identity (&gstate->ctm) &&
|
||||
_cairo_matrix_is_identity (&gstate->target->device_transform));
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_gstate_init (cairo_gstate_t *gstate,
|
||||
cairo_surface_t *target)
|
||||
|
@ -106,6 +117,11 @@ _cairo_gstate_init (cairo_gstate_t *gstate,
|
|||
gstate->parent_target = NULL;
|
||||
gstate->original_target = cairo_surface_reference (target);
|
||||
|
||||
gstate->device_transform_observer.callback = _cairo_gstate_update_device_transform;
|
||||
cairo_list_add (&gstate->device_transform_observer.link,
|
||||
&gstate->target->device_transform_observers);
|
||||
|
||||
gstate->is_identity = _cairo_matrix_is_identity (&gstate->target->device_transform);
|
||||
cairo_matrix_init_identity (&gstate->ctm);
|
||||
gstate->ctm_inverse = gstate->ctm;
|
||||
gstate->source_ctm_inverse = gstate->ctm;
|
||||
|
@ -115,10 +131,6 @@ _cairo_gstate_init (cairo_gstate_t *gstate,
|
|||
/* Now that the gstate is fully initialized and ready for the eventual
|
||||
* _cairo_gstate_fini(), we can check for errors (and not worry about
|
||||
* the resource deallocation). */
|
||||
|
||||
if (target == NULL)
|
||||
return _cairo_error (CAIRO_STATUS_NULL_POINTER);
|
||||
|
||||
status = target->status;
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
@ -171,6 +183,11 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
|
|||
gstate->parent_target = NULL;
|
||||
gstate->original_target = cairo_surface_reference (other->original_target);
|
||||
|
||||
gstate->device_transform_observer.callback = _cairo_gstate_update_device_transform;
|
||||
cairo_list_add (&gstate->device_transform_observer.link,
|
||||
&gstate->target->device_transform_observers);
|
||||
|
||||
gstate->is_identity = other->is_identity;
|
||||
gstate->ctm = other->ctm;
|
||||
gstate->ctm_inverse = other->ctm_inverse;
|
||||
gstate->source_ctm_inverse = other->source_ctm_inverse;
|
||||
|
@ -198,6 +215,8 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
|
|||
|
||||
_cairo_clip_reset (&gstate->clip);
|
||||
|
||||
cairo_list_del (&gstate->device_transform_observer.link);
|
||||
|
||||
cairo_surface_destroy (gstate->target);
|
||||
gstate->target = NULL;
|
||||
|
||||
|
@ -307,6 +326,9 @@ _cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child)
|
|||
/* Now set up our new target; we overwrite gstate->target directly,
|
||||
* since its ref is now owned by gstate->parent_target */
|
||||
gstate->target = cairo_surface_reference (child);
|
||||
gstate->is_identity &= _cairo_matrix_is_identity (&child->device_transform);
|
||||
cairo_list_move (&gstate->device_transform_observer.link,
|
||||
&gstate->target->device_transform_observers);
|
||||
|
||||
/* The clip is in surface backend coordinates for the previous target;
|
||||
* translate it into the child's backend coordinates. */
|
||||
|
@ -413,8 +435,7 @@ _cairo_gstate_get_source (cairo_gstate_t *gstate)
|
|||
{
|
||||
if (gstate->source == &_cairo_pattern_black.base) {
|
||||
/* do not expose the static object to the user */
|
||||
gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK,
|
||||
CAIRO_CONTENT_COLOR);
|
||||
gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
|
||||
}
|
||||
|
||||
return gstate->source;
|
||||
|
@ -533,6 +554,7 @@ _cairo_gstate_set_dash (cairo_gstate_t *gstate, const double *dash, int num_dash
|
|||
for (i = 0; i < gstate->stroke_style.num_dashes; i++) {
|
||||
if (gstate->stroke_style.dash[i] < 0)
|
||||
return _cairo_error (CAIRO_STATUS_INVALID_DASH);
|
||||
|
||||
dash_total += gstate->stroke_style.dash[i];
|
||||
}
|
||||
|
||||
|
@ -563,10 +585,11 @@ _cairo_gstate_get_dash (cairo_gstate_t *gstate,
|
|||
int *num_dashes,
|
||||
double *offset)
|
||||
{
|
||||
if (dashes)
|
||||
if (dashes) {
|
||||
memcpy (dashes,
|
||||
gstate->stroke_style.dash,
|
||||
sizeof (double) * gstate->stroke_style.num_dashes);
|
||||
}
|
||||
|
||||
if (num_dashes)
|
||||
*num_dashes = gstate->stroke_style.num_dashes;
|
||||
|
@ -607,6 +630,7 @@ _cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty)
|
|||
|
||||
cairo_matrix_init_translate (&tmp, tx, ty);
|
||||
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
|
||||
gstate->is_identity = FALSE;
|
||||
|
||||
/* paranoid check against gradual numerical instability */
|
||||
if (! _cairo_matrix_is_invertible (&gstate->ctm))
|
||||
|
@ -632,6 +656,7 @@ _cairo_gstate_scale (cairo_gstate_t *gstate, double sx, double sy)
|
|||
|
||||
cairo_matrix_init_scale (&tmp, sx, sy);
|
||||
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
|
||||
gstate->is_identity = FALSE;
|
||||
|
||||
/* paranoid check against gradual numerical instability */
|
||||
if (! _cairo_matrix_is_invertible (&gstate->ctm))
|
||||
|
@ -658,6 +683,7 @@ _cairo_gstate_rotate (cairo_gstate_t *gstate, double angle)
|
|||
|
||||
cairo_matrix_init_rotate (&tmp, angle);
|
||||
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
|
||||
gstate->is_identity = FALSE;
|
||||
|
||||
/* paranoid check against gradual numerical instability */
|
||||
if (! _cairo_matrix_is_invertible (&gstate->ctm))
|
||||
|
@ -676,6 +702,9 @@ _cairo_gstate_transform (cairo_gstate_t *gstate,
|
|||
cairo_matrix_t tmp;
|
||||
cairo_status_t status;
|
||||
|
||||
if (! _cairo_matrix_is_invertible (matrix))
|
||||
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
|
||||
|
||||
if (_cairo_matrix_is_identity (matrix))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
@ -688,6 +717,7 @@ _cairo_gstate_transform (cairo_gstate_t *gstate,
|
|||
|
||||
cairo_matrix_multiply (&gstate->ctm, matrix, &gstate->ctm);
|
||||
cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
|
||||
gstate->is_identity = FALSE;
|
||||
|
||||
/* paranoid check against gradual numerical instability */
|
||||
if (! _cairo_matrix_is_invertible (&gstate->ctm))
|
||||
|
@ -708,12 +738,18 @@ _cairo_gstate_set_matrix (cairo_gstate_t *gstate,
|
|||
if (! _cairo_matrix_is_invertible (matrix))
|
||||
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
|
||||
|
||||
if (_cairo_matrix_is_identity (matrix)) {
|
||||
_cairo_gstate_identity_matrix (gstate);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_cairo_gstate_unset_scaled_font (gstate);
|
||||
|
||||
gstate->ctm = *matrix;
|
||||
gstate->ctm_inverse = *matrix;
|
||||
status = cairo_matrix_invert (&gstate->ctm_inverse);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
gstate->is_identity = FALSE;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -728,6 +764,7 @@ _cairo_gstate_identity_matrix (cairo_gstate_t *gstate)
|
|||
|
||||
cairo_matrix_init_identity (&gstate->ctm);
|
||||
cairo_matrix_init_identity (&gstate->ctm_inverse);
|
||||
gstate->is_identity = _cairo_matrix_is_identity (&gstate->target->device_transform);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -757,14 +794,14 @@ _cairo_gstate_device_to_user_distance (cairo_gstate_t *gstate,
|
|||
}
|
||||
|
||||
void
|
||||
_cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y)
|
||||
_do_cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y)
|
||||
{
|
||||
cairo_matrix_transform_point (&gstate->ctm, x, y);
|
||||
cairo_matrix_transform_point (&gstate->target->device_transform, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y)
|
||||
_do_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y)
|
||||
{
|
||||
cairo_matrix_transform_point (&gstate->target->device_transform_inverse, x, y);
|
||||
cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);
|
||||
|
@ -802,14 +839,25 @@ _cairo_gstate_path_extents (cairo_gstate_t *gstate,
|
|||
double *x1, double *y1,
|
||||
double *x2, double *y2)
|
||||
{
|
||||
cairo_box_t box;
|
||||
double px1, py1, px2, py2;
|
||||
|
||||
_cairo_path_fixed_bounds (path,
|
||||
&px1, &py1, &px2, &py2);
|
||||
if (_cairo_path_fixed_extents (path, &box)) {
|
||||
px1 = _cairo_fixed_to_double (box.p1.x);
|
||||
py1 = _cairo_fixed_to_double (box.p1.y);
|
||||
px2 = _cairo_fixed_to_double (box.p2.x);
|
||||
py2 = _cairo_fixed_to_double (box.p2.y);
|
||||
|
||||
_cairo_gstate_backend_to_user_rectangle (gstate,
|
||||
&px1, &py1, &px2, &py2,
|
||||
NULL);
|
||||
} else {
|
||||
px1 = 0.0;
|
||||
py1 = 0.0;
|
||||
px2 = 0.0;
|
||||
py2 = 0.0;
|
||||
}
|
||||
|
||||
_cairo_gstate_backend_to_user_rectangle (gstate,
|
||||
&px1, &py1, &px2, &py2,
|
||||
NULL);
|
||||
if (x1)
|
||||
*x1 = px1;
|
||||
if (y1)
|
||||
|
@ -820,70 +868,32 @@ _cairo_gstate_path_extents (cairo_gstate_t *gstate,
|
|||
*y2 = py2;
|
||||
}
|
||||
|
||||
static void
|
||||
_init_solid_for_color_stop (cairo_solid_pattern_t *solid,
|
||||
const cairo_color_t *color)
|
||||
{
|
||||
cairo_color_t premult;
|
||||
|
||||
/* Color stops aren't premultiplied, so fix that here */
|
||||
_cairo_color_init_rgba (&premult,
|
||||
color->red,
|
||||
color->green,
|
||||
color->blue,
|
||||
color->alpha);
|
||||
_cairo_pattern_init_solid (solid, &premult, CAIRO_CONTENT_COLOR_ALPHA);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_gstate_copy_pattern (cairo_pattern_t *pattern,
|
||||
const cairo_pattern_t *original)
|
||||
{
|
||||
/* First check if the we can replace the original with a much simpler
|
||||
* pattern. For example, gradients that are uniform or just have a single
|
||||
* stop can be replace with a solid.
|
||||
* stop can sometimes be replaced with a solid.
|
||||
*/
|
||||
switch (original->type) {
|
||||
case CAIRO_PATTERN_TYPE_SOLID:
|
||||
case CAIRO_PATTERN_TYPE_SURFACE:
|
||||
break;
|
||||
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
case CAIRO_PATTERN_TYPE_RADIAL:
|
||||
if (_cairo_pattern_is_clear (original)) {
|
||||
_cairo_pattern_init_solid ((cairo_solid_pattern_t *) pattern,
|
||||
CAIRO_COLOR_TRANSPARENT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (original->type == CAIRO_PATTERN_TYPE_LINEAR ||
|
||||
original->type == CAIRO_PATTERN_TYPE_RADIAL)
|
||||
{
|
||||
cairo_color_t color;
|
||||
if (_cairo_gradient_pattern_is_solid ((cairo_gradient_pattern_t *) original,
|
||||
NULL,
|
||||
&color))
|
||||
{
|
||||
cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) original;
|
||||
|
||||
/* fast path for gradients with less than 2 color stops */
|
||||
if (src->n_stops < 2) {
|
||||
if (src->n_stops) {
|
||||
_init_solid_for_color_stop ((cairo_solid_pattern_t *) pattern,
|
||||
&src->stops->color);
|
||||
} else {
|
||||
_cairo_pattern_init_solid ((cairo_solid_pattern_t *) pattern,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
CAIRO_CONTENT_ALPHA);
|
||||
}
|
||||
|
||||
return;
|
||||
} else {
|
||||
unsigned int i;
|
||||
|
||||
/* Is the gradient a uniform colour?
|
||||
* Happens more often than you would believe.
|
||||
*/
|
||||
for (i = 1; i < src->n_stops; i++) {
|
||||
if (! _cairo_color_equal (&src->stops[0].color,
|
||||
&src->stops[i].color))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == src->n_stops) {
|
||||
_init_solid_for_color_stop ((cairo_solid_pattern_t *) pattern,
|
||||
&src->stops->color);
|
||||
return;
|
||||
}
|
||||
}
|
||||
_cairo_pattern_init_solid ((cairo_solid_pattern_t *) pattern,
|
||||
&color);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -913,9 +923,10 @@ _cairo_gstate_copy_transformed_pattern (cairo_gstate_t *gstate,
|
|||
if (! _cairo_matrix_is_identity (ctm_inverse))
|
||||
_cairo_pattern_transform (pattern, ctm_inverse);
|
||||
|
||||
if (_cairo_surface_has_device_transform (gstate->target))
|
||||
if (_cairo_surface_has_device_transform (gstate->target)) {
|
||||
_cairo_pattern_transform (pattern,
|
||||
&gstate->target->device_transform_inverse);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -970,24 +981,73 @@ _clipped (cairo_gstate_t *gstate)
|
|||
return _cairo_clip_get_region (&gstate->clip, NULL) == CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
|
||||
static cairo_operator_t
|
||||
_reduce_op (cairo_gstate_t *gstate)
|
||||
{
|
||||
cairo_operator_t op;
|
||||
const cairo_pattern_t *pattern;
|
||||
|
||||
op = gstate->op;
|
||||
if (op != CAIRO_OPERATOR_SOURCE)
|
||||
return op;
|
||||
|
||||
pattern = gstate->source;
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
|
||||
const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
|
||||
if (solid->color.alpha_short <= 0x00ff) {
|
||||
op = CAIRO_OPERATOR_CLEAR;
|
||||
} else if ((gstate->target->content & CAIRO_CONTENT_ALPHA) == 0) {
|
||||
if ((solid->color.red_short |
|
||||
solid->color.green_short |
|
||||
solid->color.blue_short) <= 0x00ff)
|
||||
{
|
||||
op = CAIRO_OPERATOR_CLEAR;
|
||||
}
|
||||
}
|
||||
} else if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
||||
const cairo_surface_pattern_t *surface = (cairo_surface_pattern_t *) pattern;
|
||||
if (surface->surface->is_clear &&
|
||||
surface->surface->content & CAIRO_CONTENT_ALPHA)
|
||||
{
|
||||
op = CAIRO_OPERATOR_CLEAR;
|
||||
}
|
||||
} else {
|
||||
const cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
|
||||
if (gradient->n_stops == 0)
|
||||
op = CAIRO_OPERATOR_CLEAR;
|
||||
}
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_gstate_paint (cairo_gstate_t *gstate)
|
||||
{
|
||||
cairo_pattern_union_t pattern;
|
||||
cairo_pattern_union_t source_pattern;
|
||||
const cairo_pattern_t *pattern;
|
||||
cairo_clip_t clip;
|
||||
cairo_status_t status;
|
||||
cairo_operator_t op;
|
||||
|
||||
if (unlikely (gstate->source->status))
|
||||
return gstate->source->status;
|
||||
|
||||
if (gstate->op == CAIRO_OPERATOR_DEST)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (_clipped (gstate))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_gstate_copy_transformed_source (gstate, &pattern.base);
|
||||
op = _reduce_op (gstate);
|
||||
if (op == CAIRO_OPERATOR_CLEAR) {
|
||||
pattern = &_cairo_pattern_clear.base;
|
||||
} else {
|
||||
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
|
||||
pattern = &source_pattern.base;
|
||||
}
|
||||
|
||||
status = _cairo_surface_paint (gstate->target,
|
||||
gstate->op,
|
||||
&pattern.base,
|
||||
op, pattern,
|
||||
_gstate_get_clip (gstate, &clip));
|
||||
_cairo_clip_fini (&clip);
|
||||
|
||||
|
@ -999,6 +1059,8 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
|
|||
cairo_pattern_t *mask)
|
||||
{
|
||||
cairo_pattern_union_t source_pattern, mask_pattern;
|
||||
const cairo_pattern_t *source;
|
||||
cairo_operator_t op;
|
||||
cairo_clip_t clip;
|
||||
cairo_status_t status;
|
||||
|
||||
|
@ -1008,46 +1070,59 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
|
|||
if (unlikely (gstate->source->status))
|
||||
return gstate->source->status;
|
||||
|
||||
if (gstate->op == CAIRO_OPERATOR_DEST)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (_clipped (gstate))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (_cairo_pattern_is_opaque (mask))
|
||||
if (_cairo_pattern_is_opaque (mask, NULL))
|
||||
return _cairo_gstate_paint (gstate);
|
||||
|
||||
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
|
||||
if (_cairo_pattern_is_clear (mask) &&
|
||||
_cairo_operator_bounded_by_mask (gstate->op))
|
||||
{
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
op = _reduce_op (gstate);
|
||||
if (op == CAIRO_OPERATOR_CLEAR) {
|
||||
source = &_cairo_pattern_clear.base;
|
||||
} else {
|
||||
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
|
||||
source = &source_pattern.base;
|
||||
}
|
||||
_cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
|
||||
|
||||
if (source_pattern.type == CAIRO_PATTERN_TYPE_SOLID &&
|
||||
mask_pattern.type == CAIRO_PATTERN_TYPE_SOLID)
|
||||
if (source->type == CAIRO_PATTERN_TYPE_SOLID &&
|
||||
mask_pattern.type == CAIRO_PATTERN_TYPE_SOLID &&
|
||||
_cairo_operator_bounded_by_source (op))
|
||||
{
|
||||
const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source;
|
||||
cairo_color_t combined;
|
||||
|
||||
if (mask_pattern.base.has_component_alpha) {
|
||||
#define M(R, A, B, c) R.c = A.c * B.c
|
||||
M(combined, source_pattern.solid.color, mask_pattern.solid.color, red);
|
||||
M(combined, source_pattern.solid.color, mask_pattern.solid.color, green);
|
||||
M(combined, source_pattern.solid.color, mask_pattern.solid.color, blue);
|
||||
M(combined, source_pattern.solid.color, mask_pattern.solid.color, alpha);
|
||||
M(combined, solid->color, mask_pattern.solid.color, red);
|
||||
M(combined, solid->color, mask_pattern.solid.color, green);
|
||||
M(combined, solid->color, mask_pattern.solid.color, blue);
|
||||
M(combined, solid->color, mask_pattern.solid.color, alpha);
|
||||
#undef M
|
||||
} else {
|
||||
combined = source_pattern.solid.color;
|
||||
combined = solid->color;
|
||||
_cairo_color_multiply_alpha (&combined, mask_pattern.solid.color.alpha);
|
||||
}
|
||||
|
||||
_cairo_pattern_init_solid (&source_pattern.solid, &combined,
|
||||
source_pattern.solid.content |
|
||||
mask_pattern.solid.content);
|
||||
_cairo_pattern_init_solid (&source_pattern.solid, &combined);
|
||||
|
||||
status = _cairo_surface_paint (gstate->target,
|
||||
gstate->op,
|
||||
status = _cairo_surface_paint (gstate->target, op,
|
||||
&source_pattern.base,
|
||||
_gstate_get_clip (gstate, &clip));
|
||||
}
|
||||
else
|
||||
{
|
||||
status = _cairo_surface_mask (gstate->target,
|
||||
gstate->op,
|
||||
&source_pattern.base,
|
||||
status = _cairo_surface_mask (gstate->target, op,
|
||||
source,
|
||||
&mask_pattern.base,
|
||||
_gstate_get_clip (gstate, &clip));
|
||||
}
|
||||
|
@ -1060,25 +1135,39 @@ cairo_status_t
|
|||
_cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
|
||||
{
|
||||
cairo_pattern_union_t source_pattern;
|
||||
cairo_stroke_style_t style;
|
||||
double dash[2];
|
||||
cairo_clip_t clip;
|
||||
cairo_status_t status;
|
||||
|
||||
if (unlikely (gstate->source->status))
|
||||
return gstate->source->status;
|
||||
|
||||
if (gstate->op == CAIRO_OPERATOR_DEST)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (gstate->stroke_style.line_width <= 0.0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (_clipped (gstate))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
memcpy (&style, &gstate->stroke_style, sizeof (gstate->stroke_style));
|
||||
if (_cairo_stroke_style_dash_can_approximate (&gstate->stroke_style, &gstate->ctm, gstate->tolerance)) {
|
||||
style.dash = dash;
|
||||
_cairo_stroke_style_dash_approximate (&gstate->stroke_style, &gstate->ctm, gstate->tolerance,
|
||||
&style.dash_offset,
|
||||
style.dash,
|
||||
&style.num_dashes);
|
||||
}
|
||||
|
||||
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
|
||||
|
||||
status = _cairo_surface_stroke (gstate->target,
|
||||
gstate->op,
|
||||
&source_pattern.base,
|
||||
path,
|
||||
&gstate->stroke_style,
|
||||
&style,
|
||||
&gstate->ctm,
|
||||
&gstate->ctm_inverse,
|
||||
gstate->tolerance,
|
||||
|
@ -1150,13 +1239,15 @@ BAIL:
|
|||
cairo_status_t
|
||||
_cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
|
||||
{
|
||||
cairo_pattern_union_t pattern;
|
||||
cairo_clip_t clip;
|
||||
cairo_status_t status;
|
||||
|
||||
if (unlikely (gstate->source->status))
|
||||
return gstate->source->status;
|
||||
|
||||
if (gstate->op == CAIRO_OPERATOR_DEST)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (_clipped (gstate))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
@ -1164,24 +1255,45 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
|
|||
if (_cairo_operator_bounded_by_mask (gstate->op))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_pattern_init_solid (&pattern.solid,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
CAIRO_CONTENT_COLOR_ALPHA);
|
||||
status = _cairo_surface_paint (gstate->target,
|
||||
CAIRO_OPERATOR_CLEAR,
|
||||
&pattern.base,
|
||||
&_cairo_pattern_clear.base,
|
||||
_gstate_get_clip (gstate, &clip));
|
||||
} else {
|
||||
_cairo_gstate_copy_transformed_source (gstate, &pattern.base);
|
||||
cairo_pattern_union_t source_pattern;
|
||||
const cairo_pattern_t *pattern;
|
||||
cairo_operator_t op;
|
||||
cairo_rectangle_int_t extents;
|
||||
cairo_box_t box;
|
||||
|
||||
status = _cairo_surface_fill (gstate->target,
|
||||
gstate->op,
|
||||
&pattern.base,
|
||||
path,
|
||||
gstate->fill_rule,
|
||||
gstate->tolerance,
|
||||
gstate->antialias,
|
||||
_gstate_get_clip (gstate, &clip));
|
||||
op = _reduce_op (gstate);
|
||||
if (op == CAIRO_OPERATOR_CLEAR) {
|
||||
pattern = &_cairo_pattern_clear.base;
|
||||
} else {
|
||||
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
|
||||
pattern = &source_pattern.base;
|
||||
}
|
||||
|
||||
/* Toolkits often paint the entire background with a fill */
|
||||
if (_cairo_surface_get_extents (gstate->target, &extents) &&
|
||||
_cairo_path_fixed_is_box (path, &box) &&
|
||||
box.p1.x <= _cairo_fixed_from_int (extents.x) &&
|
||||
box.p1.y <= _cairo_fixed_from_int (extents.y) &&
|
||||
box.p2.x >= _cairo_fixed_from_int (extents.x + extents.width) &&
|
||||
box.p2.y >= _cairo_fixed_from_int (extents.y + extents.height))
|
||||
{
|
||||
status = _cairo_surface_paint (gstate->target, op, pattern,
|
||||
_gstate_get_clip (gstate, &clip));
|
||||
}
|
||||
else
|
||||
{
|
||||
status = _cairo_surface_fill (gstate->target, op, pattern,
|
||||
path,
|
||||
gstate->fill_rule,
|
||||
gstate->tolerance,
|
||||
gstate->antialias,
|
||||
_gstate_get_clip (gstate, &clip));
|
||||
}
|
||||
}
|
||||
|
||||
_cairo_clip_fini (&clip);
|
||||
|
@ -1793,16 +1905,21 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
|||
cairo_text_cluster_flags_t cluster_flags)
|
||||
{
|
||||
cairo_pattern_union_t source_pattern;
|
||||
const cairo_pattern_t *pattern;
|
||||
cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
|
||||
cairo_glyph_t *transformed_glyphs;
|
||||
cairo_text_cluster_t stack_transformed_clusters[CAIRO_STACK_ARRAY_LENGTH (cairo_text_cluster_t)];
|
||||
cairo_text_cluster_t *transformed_clusters;
|
||||
cairo_operator_t op;
|
||||
cairo_status_t status;
|
||||
cairo_clip_t clip;
|
||||
|
||||
if (unlikely (gstate->source->status))
|
||||
return gstate->source->status;
|
||||
|
||||
if (gstate->op == CAIRO_OPERATOR_DEST)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (_clipped (gstate))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
@ -1845,7 +1962,13 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
|||
if (status || num_glyphs == 0)
|
||||
goto CLEANUP_GLYPHS;
|
||||
|
||||
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
|
||||
op = _reduce_op (gstate);
|
||||
if (op == CAIRO_OPERATOR_CLEAR) {
|
||||
pattern = &_cairo_pattern_clear.base;
|
||||
} else {
|
||||
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
|
||||
pattern = &source_pattern.base;
|
||||
}
|
||||
_cairo_clip_init(&clip);
|
||||
|
||||
/* For really huge font sizes, we can just do path;fill instead of
|
||||
|
@ -1864,10 +1987,9 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
|||
* Needless to say, do this only if show_text_glyphs is not available. */
|
||||
if (cairo_surface_has_show_text_glyphs (gstate->target) ||
|
||||
_cairo_scaled_font_get_max_scale (gstate->scaled_font) <=
|
||||
_cairo_surface_get_text_path_fill_threshold (gstate->target)) {
|
||||
status = _cairo_surface_show_text_glyphs (gstate->target,
|
||||
gstate->op,
|
||||
&source_pattern.base,
|
||||
_cairo_surface_get_text_path_fill_threshold (gstate->target))
|
||||
{
|
||||
status = _cairo_surface_show_text_glyphs (gstate->target, op, pattern,
|
||||
utf8, utf8_len,
|
||||
transformed_glyphs, num_glyphs,
|
||||
transformed_clusters, num_clusters,
|
||||
|
@ -1886,9 +2008,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
|||
&path);
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
status = _cairo_surface_fill (gstate->target,
|
||||
gstate->op,
|
||||
&source_pattern.base,
|
||||
status = _cairo_surface_fill (gstate->target, op, pattern,
|
||||
&path,
|
||||
CAIRO_FILL_RULE_WINDING,
|
||||
gstate->tolerance,
|
||||
|
@ -2044,6 +2164,7 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
|
|||
if (! drop) {
|
||||
memcpy (transformed_glyphs, glyphs,
|
||||
num_glyphs * sizeof (cairo_glyph_t));
|
||||
j = num_glyphs;
|
||||
} else if (num_clusters == 0) {
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
transformed_glyphs[j].index = glyphs[i].index;
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -37,6 +37,7 @@
|
|||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
/*
|
||||
* An entry can be in one of three states:
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -36,6 +36,7 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-slope-private.h"
|
||||
|
||||
typedef struct cairo_hull {
|
||||
|
@ -94,6 +95,13 @@ _cairo_hull_vertex_compare (const void *av, const void *bv)
|
|||
cairo_hull_t *b = (cairo_hull_t *) bv;
|
||||
int ret;
|
||||
|
||||
/* Some libraries are reported to actually compare identical
|
||||
* pointers and require the result to be 0. This is the crazy world we
|
||||
* have to live in.
|
||||
*/
|
||||
if (a == b)
|
||||
return 0;
|
||||
|
||||
ret = _cairo_slope_compare (&a->slope, &b->slope);
|
||||
|
||||
/*
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -53,11 +53,11 @@ _cairo_image_info_get_jpeg_info (cairo_image_info_t *info,
|
|||
cairo_private cairo_int_status_t
|
||||
_cairo_image_info_get_jpx_info (cairo_image_info_t *info,
|
||||
const unsigned char *data,
|
||||
long length);
|
||||
unsigned long length);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_image_info_get_png_info (cairo_image_info_t *info,
|
||||
_cairo_image_info_get_png_info (cairo_image_info_t *info,
|
||||
const unsigned char *data,
|
||||
long length);
|
||||
unsigned long length);
|
||||
|
||||
#endif /* CAIRO_IMAGE_INFO_PRIVATE_H */
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -214,7 +214,7 @@ _jpx_extract_info (const unsigned char *p, cairo_image_info_t *info)
|
|||
cairo_int_status_t
|
||||
_cairo_image_info_get_jpx_info (cairo_image_info_t *info,
|
||||
const unsigned char *data,
|
||||
long length)
|
||||
unsigned long length)
|
||||
{
|
||||
const unsigned char *p = data;
|
||||
const unsigned char *end = data + length;
|
||||
|
@ -262,7 +262,7 @@ static const unsigned char _png_magic[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
|
|||
cairo_int_status_t
|
||||
_cairo_image_info_get_png_info (cairo_image_info_t *info,
|
||||
const unsigned char *data,
|
||||
long length)
|
||||
unsigned long length)
|
||||
{
|
||||
const unsigned char *p = data;
|
||||
const unsigned char *end = data + length;
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -73,19 +73,38 @@ typedef struct _cairo_list {
|
|||
&pos->member != (head); \
|
||||
pos = cairo_list_entry(pos->member.prev, type, member))
|
||||
|
||||
#define cairo_list_foreach_entry_reverse_safe(pos, n, type, head, member) \
|
||||
for (pos = cairo_list_entry((head)->prev, type, member),\
|
||||
n = cairo_list_entry (pos->member.prev, type, member);\
|
||||
&pos->member != (head); \
|
||||
pos = n, n = cairo_list_entry (n->member.prev, type, member))
|
||||
|
||||
#ifdef CAIRO_LIST_DEBUG
|
||||
static inline void
|
||||
_cairo_list_validate (const cairo_list_t *link)
|
||||
{
|
||||
assert (link->next->prev == link);
|
||||
assert (link->prev->next == link);
|
||||
}
|
||||
static inline void
|
||||
cairo_list_validate (const cairo_list_t *head)
|
||||
{
|
||||
cairo_list_t *link;
|
||||
|
||||
cairo_list_foreach (link, head) {
|
||||
assert (link->next->prev == link);
|
||||
assert (link->prev->next == link);
|
||||
}
|
||||
cairo_list_foreach (link, head)
|
||||
_cairo_list_validate (link);
|
||||
}
|
||||
static inline cairo_bool_t
|
||||
cairo_list_is_empty (const cairo_list_t *head);
|
||||
static inline void
|
||||
cairo_list_validate_is_empty (const cairo_list_t *head)
|
||||
{
|
||||
assert (head->next == NULL || (cairo_list_is_empty (head) && head->next == head->prev));
|
||||
}
|
||||
#else
|
||||
#define _cairo_list_validate(link)
|
||||
#define cairo_list_validate(head)
|
||||
#define cairo_list_validate_is_empty(head)
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
|
@ -110,6 +129,7 @@ static inline void
|
|||
cairo_list_add (cairo_list_t *entry, cairo_list_t *head)
|
||||
{
|
||||
cairo_list_validate (head);
|
||||
cairo_list_validate_is_empty (entry);
|
||||
__cairo_list_add (entry, head, head->next);
|
||||
cairo_list_validate (head);
|
||||
}
|
||||
|
@ -118,6 +138,7 @@ static inline void
|
|||
cairo_list_add_tail (cairo_list_t *entry, cairo_list_t *head)
|
||||
{
|
||||
cairo_list_validate (head);
|
||||
cairo_list_validate_is_empty (entry);
|
||||
__cairo_list_add (entry, head->prev, head);
|
||||
cairo_list_validate (head);
|
||||
}
|
||||
|
@ -157,10 +178,8 @@ cairo_list_move_tail (cairo_list_t *entry, cairo_list_t *head)
|
|||
static inline void
|
||||
cairo_list_swap (cairo_list_t *entry, cairo_list_t *other)
|
||||
{
|
||||
cairo_list_validate (head);
|
||||
__cairo_list_add (entry, other->prev, other->next);
|
||||
cairo_list_init (other);
|
||||
cairo_list_validate (head);
|
||||
}
|
||||
|
||||
static inline cairo_bool_t
|
||||
|
@ -186,4 +205,11 @@ cairo_list_is_empty (const cairo_list_t *head)
|
|||
return head->next == head;
|
||||
}
|
||||
|
||||
static inline cairo_bool_t
|
||||
cairo_list_is_singular (const cairo_list_t *head)
|
||||
{
|
||||
cairo_list_validate (head);
|
||||
return head->next == head || head->next == head->prev;
|
||||
}
|
||||
|
||||
#endif /* CAIRO_LIST_PRIVATE_H */
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -35,6 +35,7 @@
|
|||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
typedef struct _lzw_buf {
|
||||
cairo_status_t status;
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -34,9 +34,8 @@
|
|||
* Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
#if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE)
|
||||
#define ISFINITE(x) isfinite (x)
|
||||
|
@ -44,6 +43,29 @@
|
|||
#define ISFINITE(x) ((x) * (x) >= 0.) /* check for NaNs */
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SECTION:cairo-matrix
|
||||
* @Title: cairo_matrix_t
|
||||
* @Short_Description: Generic matrix operations
|
||||
* @See_Also: #cairo_t
|
||||
*
|
||||
* #cairo_matrix_t is used throughout cairo to convert between different
|
||||
* coordinate spaces. A #cairo_matrix_t holds an affine transformation,
|
||||
* such as a scale, rotation, shear, or a combination of these.
|
||||
* The transformation of a point (<literal>x</literal>,<literal>y</literal>)
|
||||
* is given by:
|
||||
*
|
||||
* <programlisting>
|
||||
* x_new = xx * x + xy * y + x0;
|
||||
* y_new = yx * x + yy * y + y0;
|
||||
* </programlisting>
|
||||
*
|
||||
* The current transformation matrix of a #cairo_t, represented as a
|
||||
* #cairo_matrix_t, defines the transformation from user-space
|
||||
* coordinates to device-space coordinates. See cairo_get_matrix() and
|
||||
* cairo_set_matrix().
|
||||
*/
|
||||
|
||||
static void
|
||||
_cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar);
|
||||
|
||||
|
@ -579,6 +601,15 @@ _cairo_matrix_is_invertible (const cairo_matrix_t *matrix)
|
|||
return ISFINITE (det) && det != 0.;
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_matrix_is_scale_0 (const cairo_matrix_t *matrix)
|
||||
{
|
||||
return matrix->xx == 0. &&
|
||||
matrix->xy == 0. &&
|
||||
matrix->yx == 0. &&
|
||||
matrix->yy == 0.;
|
||||
}
|
||||
|
||||
double
|
||||
_cairo_matrix_compute_determinant (const cairo_matrix_t *matrix)
|
||||
{
|
||||
|
@ -916,7 +947,7 @@ _cairo_matrix_to_pixman_matrix (const cairo_matrix_t *matrix,
|
|||
* that point.
|
||||
*/
|
||||
|
||||
if (_cairo_matrix_is_translation (matrix))
|
||||
if (_cairo_matrix_has_unity_scale (matrix))
|
||||
return;
|
||||
|
||||
/* Note: If we can't invert the transformation, skip the adjustment. */
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -39,10 +39,31 @@
|
|||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
COMPILE_TIME_ASSERT (CAIRO_STATUS_LAST_STATUS < CAIRO_INT_STATUS_UNSUPPORTED);
|
||||
COMPILE_TIME_ASSERT (CAIRO_INT_STATUS_LAST_STATUS <= 127);
|
||||
|
||||
/**
|
||||
* SECTION:cairo-status
|
||||
* @Title: Error handling
|
||||
* @Short_Description: Decoding cairo's status
|
||||
* @See_Also: cairo_status(), cairo_surface_status(), cairo_pattern_status(),
|
||||
* cairo_font_face_status(), cairo_scaled_font_status(),
|
||||
* cairo_region_status()
|
||||
*
|
||||
* Cairo uses a single status type to represent all kinds of errors. A status
|
||||
* value of %CAIRO_STATUS_SUCCESS represents no error and has an integer value
|
||||
* of zero. All other status values represent an error.
|
||||
*
|
||||
* Cairo's error handling is designed to be easy to use and safe. All major
|
||||
* cairo objects <firstterm>retain</firstterm> an error status internally which
|
||||
* can be queried anytime by the users using cairo*_status() calls. In
|
||||
* the mean time, it is safe to call all cairo functions normally even if the
|
||||
* underlying object is in an error status. This means that no error handling
|
||||
* code is required before or after each individual cairo function call.
|
||||
*/
|
||||
|
||||
/* Public stuff */
|
||||
|
||||
/**
|
||||
|
@ -125,6 +146,10 @@ cairo_status_to_string (cairo_status_t status)
|
|||
return "invalid value (typically too big) for the size of the input (surface, pattern, etc.)";
|
||||
case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED:
|
||||
return "user-font method not implemented";
|
||||
case CAIRO_STATUS_DEVICE_TYPE_MISMATCH:
|
||||
return "the device type is not appropriate for the operation";
|
||||
case CAIRO_STATUS_DEVICE_ERROR:
|
||||
return "an operation to the device caused an unspecified error";
|
||||
default:
|
||||
case CAIRO_STATUS_LAST_STATUS:
|
||||
return "<unknown error status>";
|
||||
|
@ -416,7 +441,49 @@ _cairo_operator_bounded_by_source (cairo_operator_t op)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
_cairo_operator_bounded_by_either (cairo_operator_t op)
|
||||
{
|
||||
switch (op) {
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
case CAIRO_OPERATOR_OVER:
|
||||
case CAIRO_OPERATOR_ATOP:
|
||||
case CAIRO_OPERATOR_DEST:
|
||||
case CAIRO_OPERATOR_DEST_OVER:
|
||||
case CAIRO_OPERATOR_DEST_OUT:
|
||||
case CAIRO_OPERATOR_XOR:
|
||||
case CAIRO_OPERATOR_ADD:
|
||||
case CAIRO_OPERATOR_SATURATE:
|
||||
case CAIRO_OPERATOR_MULTIPLY:
|
||||
case CAIRO_OPERATOR_SCREEN:
|
||||
case CAIRO_OPERATOR_OVERLAY:
|
||||
case CAIRO_OPERATOR_DARKEN:
|
||||
case CAIRO_OPERATOR_LIGHTEN:
|
||||
case CAIRO_OPERATOR_COLOR_DODGE:
|
||||
case CAIRO_OPERATOR_COLOR_BURN:
|
||||
case CAIRO_OPERATOR_HARD_LIGHT:
|
||||
case CAIRO_OPERATOR_SOFT_LIGHT:
|
||||
case CAIRO_OPERATOR_DIFFERENCE:
|
||||
case CAIRO_OPERATOR_EXCLUSION:
|
||||
case CAIRO_OPERATOR_HSL_HUE:
|
||||
case CAIRO_OPERATOR_HSL_SATURATION:
|
||||
case CAIRO_OPERATOR_HSL_COLOR:
|
||||
case CAIRO_OPERATOR_HSL_LUMINOSITY:
|
||||
return CAIRO_OPERATOR_BOUND_BY_MASK | CAIRO_OPERATOR_BOUND_BY_SOURCE;
|
||||
case CAIRO_OPERATOR_CLEAR:
|
||||
case CAIRO_OPERATOR_SOURCE:
|
||||
return CAIRO_OPERATOR_BOUND_BY_MASK;
|
||||
case CAIRO_OPERATOR_OUT:
|
||||
case CAIRO_OPERATOR_IN:
|
||||
case CAIRO_OPERATOR_DEST_IN:
|
||||
case CAIRO_OPERATOR_DEST_ATOP:
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if DISABLE_SOME_FLOATING_POINT
|
||||
/* This function is identical to the C99 function lround(), except that it
|
||||
* performs arithmetic rounding (floor(d + .5) instead of away-from-zero rounding) and
|
||||
* has a valid input range of (INT_MIN, INT_MAX] instead of
|
||||
|
@ -627,6 +694,64 @@ _cairo_lround (double d)
|
|||
#undef MSW
|
||||
#undef LSW
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Convert a 32-bit IEEE single precision floating point number to a
|
||||
* 'half' representation (s10.5)
|
||||
*/
|
||||
uint16_t
|
||||
_cairo_half_from_float (float f)
|
||||
{
|
||||
union {
|
||||
uint32_t ui;
|
||||
float f;
|
||||
} u;
|
||||
int s, e, m;
|
||||
|
||||
u.f = f;
|
||||
s = (u.ui >> 16) & 0x00008000;
|
||||
e = ((u.ui >> 23) & 0x000000ff) - (127 - 15);
|
||||
m = u.ui & 0x007fffff;
|
||||
if (e <= 0) {
|
||||
if (e < -10) {
|
||||
/* underflow */
|
||||
return 0;
|
||||
}
|
||||
|
||||
m = (m | 0x00800000) >> (1 - e);
|
||||
|
||||
/* round to nearest, round 0.5 up. */
|
||||
if (m & 0x00001000)
|
||||
m += 0x00002000;
|
||||
return s | (m >> 13);
|
||||
} else if (e == 0xff - (127 - 15)) {
|
||||
if (m == 0) {
|
||||
/* infinity */
|
||||
return s | 0x7c00;
|
||||
} else {
|
||||
/* nan */
|
||||
m >>= 13;
|
||||
return s | 0x7c00 | m | (m == 0);
|
||||
}
|
||||
} else {
|
||||
/* round to nearest, round 0.5 up. */
|
||||
if (m & 0x00001000) {
|
||||
m += 0x00002000;
|
||||
|
||||
if (m & 0x00800000) {
|
||||
m = 0;
|
||||
e += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (e > 30) {
|
||||
/* overflow -> infinity */
|
||||
return s | 0x7c00;
|
||||
}
|
||||
|
||||
return s | (e << 10) | (m >> 13);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -168,6 +168,13 @@
|
|||
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex)
|
||||
# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER 0
|
||||
|
||||
# define CAIRO_MUTEX_HAS_RECURSIVE_IMPL 1
|
||||
|
||||
typedef int cairo_recursive_mutex_impl_t;
|
||||
|
||||
# define CAIRO_RECURSIVE_MUTEX_IMPL_INIT(mutex)
|
||||
# define CAIRO_RECURSIVE_MUTEX_IMPL_NIL_INITIALIZER 0
|
||||
|
||||
#elif defined(_WIN32) /******************************************************/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
@ -221,6 +228,7 @@
|
|||
# include <pthread.h>
|
||||
|
||||
typedef pthread_mutex_t cairo_mutex_impl_t;
|
||||
typedef pthread_mutex_t cairo_recursive_mutex_impl_t;
|
||||
|
||||
# define CAIRO_MUTEX_IMPL_PTHREAD 1
|
||||
#if HAVE_LOCKDEP
|
||||
|
@ -239,11 +247,31 @@
|
|||
#endif
|
||||
# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER PTHREAD_MUTEX_INITIALIZER
|
||||
|
||||
# define CAIRO_MUTEX_HAS_RECURSIVE_IMPL 1
|
||||
# define CAIRO_RECURSIVE_MUTEX_IMPL_INIT(mutex) do { \
|
||||
pthread_mutexattr_t attr; \
|
||||
pthread_mutexattr_init (&attr); \
|
||||
pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); \
|
||||
pthread_mutex_init (&(mutex), &attr); \
|
||||
pthread_mutexattr_destroy (&attr); \
|
||||
} while (0)
|
||||
# define CAIRO_RECURSIVE_MUTEX_IMPL_NIL_INITIALIZER PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
|
||||
|
||||
#else /**********************************************************************/
|
||||
|
||||
# error "XXX: No mutex implementation found. Cairo will not work with multiple threads. Define CAIRO_NO_MUTEX to 1 to acknowledge and accept this limitation and compile cairo without thread-safety support."
|
||||
|
||||
#endif
|
||||
|
||||
/* By default mutex implementations are assumed to be recursive */
|
||||
#if ! CAIRO_MUTEX_HAS_RECURSIVE_IMPL
|
||||
|
||||
# define CAIRO_MUTEX_HAS_RECURSIVE_IMPL 1
|
||||
|
||||
typedef cairo_mutex_impl_t cairo_recursive_mutex_impl_t;
|
||||
|
||||
# define CAIRO_RECURSIVE_MUTEX_IMPL_INIT(mutex) CAIRO_MUTEX_IMPL_INIT(mutex)
|
||||
# define CAIRO_RECURSIVE_MUTEX_IMPL_NIL_INITIALIZER CAIRO_MUTEX_IMPL_NIL_INITIALIZER
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -38,6 +38,9 @@
|
|||
|
||||
CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_surface_cache_lock)
|
||||
|
||||
CAIRO_MUTEX_DECLARE (_cairo_image_solid_cache_mutex)
|
||||
|
||||
CAIRO_MUTEX_DECLARE (_cairo_error_mutex)
|
||||
CAIRO_MUTEX_DECLARE (_cairo_toy_font_face_mutex)
|
||||
CAIRO_MUTEX_DECLARE (_cairo_intern_string_mutex)
|
||||
CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex)
|
||||
|
@ -52,6 +55,10 @@ CAIRO_MUTEX_DECLARE (_cairo_ft_unscaled_font_map_mutex)
|
|||
CAIRO_MUTEX_DECLARE (_cairo_xlib_display_mutex)
|
||||
#endif
|
||||
|
||||
#if CAIRO_HAS_XCB_SURFACE
|
||||
CAIRO_MUTEX_DECLARE (_cairo_xcb_connections_mutex)
|
||||
#endif
|
||||
|
||||
#if CAIRO_HAS_GL_SURFACE
|
||||
CAIRO_MUTEX_DECLARE (_cairo_gl_context_mutex)
|
||||
#endif
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -44,7 +44,7 @@
|
|||
#include "cairo-compiler-private.h"
|
||||
#include "cairo-mutex-impl-private.h"
|
||||
|
||||
/* Only the following three are mandatory at this point */
|
||||
/* Only the following four are mandatory at this point */
|
||||
#ifndef CAIRO_MUTEX_IMPL_LOCK
|
||||
# error "CAIRO_MUTEX_IMPL_LOCK not defined. Check cairo-mutex-impl-private.h."
|
||||
#endif
|
||||
|
@ -54,6 +54,9 @@
|
|||
#ifndef CAIRO_MUTEX_IMPL_NIL_INITIALIZER
|
||||
# error "CAIRO_MUTEX_IMPL_NIL_INITIALIZER not defined. Check cairo-mutex-impl-private.h."
|
||||
#endif
|
||||
#ifndef CAIRO_RECURSIVE_MUTEX_IMPL_INIT
|
||||
# error "CAIRO_RECURSIVE_MUTEX_IMPL_INIT not defined. Check cairo-mutex-impl-private.h."
|
||||
#endif
|
||||
|
||||
|
||||
/* make sure implementations don't fool us: we decide these ourself */
|
||||
|
@ -156,6 +159,7 @@
|
|||
|
||||
#ifndef CAIRO_MUTEX_DEBUG
|
||||
typedef cairo_mutex_impl_t cairo_mutex_t;
|
||||
typedef cairo_recursive_mutex_impl_t cairo_recursive_mutex_t;
|
||||
#else
|
||||
# define cairo_mutex_t cairo_mutex_impl_t
|
||||
#endif
|
||||
|
@ -168,6 +172,9 @@ typedef cairo_mutex_impl_t cairo_mutex_t;
|
|||
#define CAIRO_MUTEX_FINI CAIRO_MUTEX_IMPL_FINI
|
||||
#define CAIRO_MUTEX_NIL_INITIALIZER CAIRO_MUTEX_IMPL_NIL_INITIALIZER
|
||||
|
||||
#define CAIRO_RECURSIVE_MUTEX_INIT CAIRO_RECURSIVE_MUTEX_IMPL_INIT
|
||||
#define CAIRO_RECURSIVE_MUTEX_NIL_INITIALIZER CAIRO_RECURSIVE_MUTEX_IMPL_NIL_INITIALIZER
|
||||
|
||||
#ifndef CAIRO_MUTEX_IS_LOCKED
|
||||
# define CAIRO_MUTEX_IS_LOCKED(name) 1
|
||||
#endif
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
|
||||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2010 Intel Corporation
|
||||
*
|
||||
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Intel Corporation
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
void
|
||||
_cairo_observers_notify (cairo_list_t *observers, void *arg)
|
||||
{
|
||||
cairo_observer_t *obs, *next;
|
||||
|
||||
cairo_list_foreach_entry_safe (obs, next,
|
||||
cairo_observer_t,
|
||||
observers, link)
|
||||
{
|
||||
obs->callback (obs, arg);
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -39,6 +39,7 @@
|
|||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-os2-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
#if CAIRO_HAS_FC_FONT
|
||||
#include <fontconfig/fontconfig.h>
|
||||
|
@ -782,7 +783,7 @@ cairo_os2_surface_create (HPS hps_client_window,
|
|||
0,
|
||||
FALSE))
|
||||
{
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
status = _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
|
@ -791,7 +792,7 @@ cairo_os2_surface_create (HPS hps_client_window,
|
|||
0,
|
||||
FALSE))
|
||||
{
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
status = _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
|
@ -829,6 +830,7 @@ cairo_os2_surface_create (HPS hps_client_window,
|
|||
/* Initialize base surface */
|
||||
_cairo_surface_init (&local_os2_surface->base,
|
||||
&cairo_os2_surface_backend,
|
||||
NULL, /* device */
|
||||
_cairo_content_from_format (CAIRO_FORMAT_ARGB32));
|
||||
|
||||
/* Successful exit */
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -175,7 +175,7 @@ _cairo_memory_stream_length (cairo_output_stream_t *stream);
|
|||
cairo_private cairo_status_t
|
||||
_cairo_memory_stream_destroy (cairo_output_stream_t *abstract_stream,
|
||||
unsigned char **data_out,
|
||||
unsigned int *length_out);
|
||||
unsigned long *length_out);
|
||||
|
||||
cairo_private cairo_output_stream_t *
|
||||
_cairo_null_stream_create (void);
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -37,6 +37,7 @@
|
|||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-output-stream-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-compiler-private.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -694,7 +695,7 @@ _cairo_memory_stream_create (void)
|
|||
cairo_status_t
|
||||
_cairo_memory_stream_destroy (cairo_output_stream_t *abstract_stream,
|
||||
unsigned char **data_out,
|
||||
unsigned int *length_out)
|
||||
unsigned long *length_out)
|
||||
{
|
||||
memory_stream_t *stream;
|
||||
cairo_status_t status;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -57,7 +57,6 @@ typedef struct _cairo_paginated_surface {
|
|||
cairo_surface_t *recording_surface;
|
||||
|
||||
int page_num;
|
||||
cairo_bool_t page_is_blank;
|
||||
} cairo_paginated_surface_t;
|
||||
|
||||
#endif /* CAIRO_PAGINATED_SURFACE_H */
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -48,6 +48,7 @@
|
|||
#include "cairo-paginated-surface-private.h"
|
||||
#include "cairo-recording-surface-private.h"
|
||||
#include "cairo-analysis-surface-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
static const cairo_surface_backend_t cairo_paginated_surface_backend;
|
||||
|
||||
|
@ -101,7 +102,9 @@ _cairo_paginated_surface_create (cairo_surface_t *target,
|
|||
goto FAIL;
|
||||
}
|
||||
|
||||
_cairo_surface_init (&surface->base, &cairo_paginated_surface_backend,
|
||||
_cairo_surface_init (&surface->base,
|
||||
&cairo_paginated_surface_backend,
|
||||
NULL, /* device */
|
||||
content);
|
||||
|
||||
/* Override surface->base.type with target's type so we don't leak
|
||||
|
@ -119,7 +122,7 @@ _cairo_paginated_surface_create (cairo_surface_t *target,
|
|||
goto FAIL_CLEANUP_SURFACE;
|
||||
|
||||
surface->page_num = 1;
|
||||
surface->page_is_blank = TRUE;
|
||||
surface->base.is_clear = TRUE;
|
||||
|
||||
return &surface->base;
|
||||
|
||||
|
@ -154,9 +157,11 @@ _cairo_paginated_surface_finish (void *abstract_surface)
|
|||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (surface->page_is_blank == FALSE || surface->page_num == 1) {
|
||||
cairo_surface_show_page (abstract_surface);
|
||||
status = cairo_surface_status (abstract_surface);
|
||||
if (! surface->base.is_clear || surface->page_num == 1) {
|
||||
/* Bypass some of the sanity checking in cairo-surface.c, as we
|
||||
* know that the surface is finished...
|
||||
*/
|
||||
status = _cairo_paginated_surface_show_page (surface);
|
||||
}
|
||||
|
||||
/* XXX We want to propagate any errors from destroy(), but those are not
|
||||
|
@ -164,11 +169,10 @@ _cairo_paginated_surface_finish (void *abstract_surface)
|
|||
* 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) {
|
||||
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);
|
||||
}
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = cairo_surface_status (surface->target);
|
||||
cairo_surface_destroy (surface->target);
|
||||
|
||||
cairo_surface_finish (surface->recording_surface);
|
||||
|
@ -272,17 +276,17 @@ _paint_fallback_image (cairo_paginated_surface_t *surface,
|
|||
* filtering (if possible) to avoid introducing potential artifacts. */
|
||||
pattern.base.filter = CAIRO_FILTER_NEAREST;
|
||||
|
||||
status = _cairo_clip_init_rectangle (&clip, rect);
|
||||
if (unlikely (status))
|
||||
goto CLEANUP_IMAGE;
|
||||
|
||||
status = _cairo_surface_paint (surface->target,
|
||||
CAIRO_OPERATOR_SOURCE,
|
||||
&pattern.base, &clip);
|
||||
|
||||
_cairo_clip_reset (&clip);
|
||||
_cairo_clip_init (&clip);
|
||||
status = _cairo_clip_rectangle (&clip, rect);
|
||||
if (likely (status == CAIRO_STATUS_SUCCESS)) {
|
||||
status = _cairo_surface_paint (surface->target,
|
||||
CAIRO_OPERATOR_SOURCE,
|
||||
&pattern.base, &clip);
|
||||
}
|
||||
|
||||
_cairo_clip_fini (&clip);
|
||||
_cairo_pattern_fini (&pattern.base);
|
||||
|
||||
CLEANUP_IMAGE:
|
||||
cairo_surface_destroy (image);
|
||||
|
||||
|
@ -357,6 +361,7 @@ _paint_page (cairo_paginated_surface_t *surface)
|
|||
CAIRO_PAGINATED_MODE_RENDER);
|
||||
|
||||
status = _cairo_recording_surface_replay_region (surface->recording_surface,
|
||||
NULL,
|
||||
surface->target,
|
||||
CAIRO_RECORDING_REGION_NATIVE);
|
||||
assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
|
||||
|
@ -471,16 +476,18 @@ _cairo_paginated_surface_show_page (void *abstract_surface)
|
|||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
cairo_surface_destroy (surface->recording_surface);
|
||||
if (! surface->base.finished) {
|
||||
cairo_surface_destroy (surface->recording_surface);
|
||||
|
||||
surface->recording_surface = _create_recording_surface_for_target (surface->target,
|
||||
surface->content);
|
||||
status = surface->recording_surface->status;
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
surface->recording_surface = _create_recording_surface_for_target (surface->target,
|
||||
surface->content);
|
||||
status = surface->recording_surface->status;
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
surface->page_num++;
|
||||
surface->page_is_blank = TRUE;
|
||||
surface->page_num++;
|
||||
surface->base.is_clear = TRUE;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -511,12 +518,6 @@ _cairo_paginated_surface_paint (void *abstract_surface,
|
|||
{
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
/* Optimize away erasing of nothing. */
|
||||
if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
surface->page_is_blank = FALSE;
|
||||
|
||||
return _cairo_surface_paint (surface->recording_surface, op, source, clip);
|
||||
}
|
||||
|
||||
|
@ -529,12 +530,6 @@ _cairo_paginated_surface_mask (void *abstract_surface,
|
|||
{
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
/* Optimize away erasing of nothing. */
|
||||
if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
surface->page_is_blank = FALSE;
|
||||
|
||||
return _cairo_surface_mask (surface->recording_surface, op, source, mask, clip);
|
||||
}
|
||||
|
||||
|
@ -543,21 +538,15 @@ _cairo_paginated_surface_stroke (void *abstract_surface,
|
|||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *style,
|
||||
cairo_matrix_t *ctm,
|
||||
cairo_matrix_t *ctm_inverse,
|
||||
const cairo_stroke_style_t *style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
/* Optimize away erasing of nothing. */
|
||||
if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
surface->page_is_blank = FALSE;
|
||||
|
||||
return _cairo_surface_stroke (surface->recording_surface, op, source,
|
||||
path, style,
|
||||
ctm, ctm_inverse,
|
||||
|
@ -577,12 +566,6 @@ _cairo_paginated_surface_fill (void *abstract_surface,
|
|||
{
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
/* Optimize away erasing of nothing. */
|
||||
if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
surface->page_is_blank = FALSE;
|
||||
|
||||
return _cairo_surface_fill (surface->recording_surface, op, source,
|
||||
path, fill_rule,
|
||||
tolerance, antialias,
|
||||
|
@ -613,12 +596,6 @@ _cairo_paginated_surface_show_text_glyphs (void *abstract_surface,
|
|||
{
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
/* Optimize away erasing of nothing. */
|
||||
if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
surface->page_is_blank = FALSE;
|
||||
|
||||
return _cairo_surface_show_text_glyphs (surface->recording_surface, op, source,
|
||||
utf8, utf8_len,
|
||||
glyphs, num_glyphs,
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -35,6 +35,7 @@
|
|||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-path-fixed-private.h"
|
||||
|
||||
typedef struct cairo_path_bounder {
|
||||
cairo_point_t current_point;
|
||||
|
@ -134,26 +135,6 @@ _cairo_path_bounder_curve_to (void *closure,
|
|||
}
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_path_bounder_curve_to_cp (void *closure,
|
||||
const cairo_point_t *b,
|
||||
const cairo_point_t *c,
|
||||
const cairo_point_t *d)
|
||||
{
|
||||
cairo_path_bounder_t *bounder = closure;
|
||||
|
||||
if (bounder->has_initial_point) {
|
||||
_cairo_path_bounder_add_point (bounder, &bounder->current_point);
|
||||
bounder->has_initial_point = FALSE;
|
||||
}
|
||||
|
||||
_cairo_path_bounder_add_point (bounder, b);
|
||||
_cairo_path_bounder_add_point (bounder, c);
|
||||
_cairo_path_bounder_add_point (bounder, d);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_path_bounder_close_path (void *closure)
|
||||
{
|
||||
|
@ -168,21 +149,8 @@ void
|
|||
_cairo_path_fixed_approximate_clip_extents (const cairo_path_fixed_t *path,
|
||||
cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_path_bounder_t bounder;
|
||||
cairo_status_t status;
|
||||
|
||||
_cairo_path_bounder_init (&bounder);
|
||||
|
||||
status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD,
|
||||
_cairo_path_bounder_move_to,
|
||||
_cairo_path_bounder_line_to,
|
||||
_cairo_path_bounder_curve_to_cp,
|
||||
_cairo_path_bounder_close_path,
|
||||
&bounder);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
if (bounder.has_point) {
|
||||
_cairo_box_round_to_rectangle (&bounder.extents, extents);
|
||||
if (path->extents.p1.x < path->extents.p2.x) {
|
||||
_cairo_box_round_to_rectangle (&path->extents, extents);
|
||||
} else {
|
||||
extents->x = extents->y = 0;
|
||||
extents->width = extents->height = 0;
|
||||
|
@ -199,15 +167,20 @@ _cairo_path_fixed_approximate_fill_extents (const cairo_path_fixed_t *path,
|
|||
cairo_path_bounder_t bounder;
|
||||
cairo_status_t status;
|
||||
|
||||
_cairo_path_bounder_init (&bounder);
|
||||
if (! path->has_curve_to) {
|
||||
bounder.extents = path->extents;
|
||||
bounder.has_point = path->extents.p1.x < path->extents.p2.x;
|
||||
} else {
|
||||
_cairo_path_bounder_init (&bounder);
|
||||
|
||||
status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD,
|
||||
_cairo_path_bounder_move_to,
|
||||
_cairo_path_bounder_line_to,
|
||||
_cairo_path_bounder_curve_to,
|
||||
_cairo_path_bounder_close_path,
|
||||
&bounder);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD,
|
||||
_cairo_path_bounder_move_to,
|
||||
_cairo_path_bounder_line_to,
|
||||
_cairo_path_bounder_curve_to,
|
||||
_cairo_path_bounder_close_path,
|
||||
&bounder);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
if (bounder.has_point) {
|
||||
_cairo_box_round_to_rectangle (&bounder.extents, extents);
|
||||
|
@ -226,14 +199,19 @@ _cairo_path_fixed_fill_extents (const cairo_path_fixed_t *path,
|
|||
cairo_path_bounder_t bounder;
|
||||
cairo_status_t status;
|
||||
|
||||
_cairo_path_bounder_init (&bounder);
|
||||
if (! path->has_curve_to) {
|
||||
bounder.extents = path->extents;
|
||||
bounder.has_point = path->extents.p1.x < path->extents.p2.x;
|
||||
} else {
|
||||
_cairo_path_bounder_init (&bounder);
|
||||
|
||||
status = _cairo_path_fixed_interpret_flat (path, CAIRO_DIRECTION_FORWARD,
|
||||
_cairo_path_bounder_move_to,
|
||||
_cairo_path_bounder_line_to,
|
||||
_cairo_path_bounder_close_path,
|
||||
&bounder, tolerance);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
status = _cairo_path_fixed_interpret_flat (path, CAIRO_DIRECTION_FORWARD,
|
||||
_cairo_path_bounder_move_to,
|
||||
_cairo_path_bounder_line_to,
|
||||
_cairo_path_bounder_close_path,
|
||||
&bounder, tolerance);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
if (bounder.has_point) {
|
||||
_cairo_box_round_to_rectangle (&bounder.extents, extents);
|
||||
|
@ -246,22 +224,44 @@ _cairo_path_fixed_fill_extents (const cairo_path_fixed_t *path,
|
|||
/* Adjusts the fill extents (above) by the device-space pen. */
|
||||
void
|
||||
_cairo_path_fixed_approximate_stroke_extents (const cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *style,
|
||||
const cairo_stroke_style_t *style,
|
||||
const cairo_matrix_t *ctm,
|
||||
cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_path_bounder_t bounder;
|
||||
cairo_status_t status;
|
||||
|
||||
_cairo_path_bounder_init (&bounder);
|
||||
if (! path->has_curve_to) {
|
||||
bounder.extents = path->extents;
|
||||
|
||||
status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD,
|
||||
_cairo_path_bounder_move_to,
|
||||
_cairo_path_bounder_line_to,
|
||||
_cairo_path_bounder_curve_to,
|
||||
_cairo_path_bounder_close_path,
|
||||
&bounder);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
/* include trailing move-to for degenerate segments */
|
||||
if (path->has_last_move_point) {
|
||||
const cairo_point_t *point = &path->last_move_point;
|
||||
|
||||
if (point->x < bounder.extents.p1.x)
|
||||
bounder.extents.p1.x = point->x;
|
||||
if (point->y < bounder.extents.p1.y)
|
||||
bounder.extents.p1.y = point->y;
|
||||
|
||||
if (point->x > bounder.extents.p2.x)
|
||||
bounder.extents.p2.x = point->x;
|
||||
if (point->y > bounder.extents.p2.y)
|
||||
bounder.extents.p2.y = point->y;
|
||||
}
|
||||
|
||||
bounder.has_point = bounder.extents.p1.x <= bounder.extents.p2.x;
|
||||
bounder.has_initial_point = FALSE;
|
||||
} else {
|
||||
_cairo_path_bounder_init (&bounder);
|
||||
|
||||
status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD,
|
||||
_cairo_path_bounder_move_to,
|
||||
_cairo_path_bounder_line_to,
|
||||
_cairo_path_bounder_curve_to,
|
||||
_cairo_path_bounder_close_path,
|
||||
&bounder);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
if (bounder.has_point) {
|
||||
double dx, dy;
|
||||
|
@ -294,12 +294,12 @@ _cairo_path_fixed_approximate_stroke_extents (const cairo_path_fixed_t *path,
|
|||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_stroke_extents (const cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *stroke_style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_rectangle_int_t *extents)
|
||||
_cairo_path_fixed_stroke_extents (const cairo_path_fixed_t *path,
|
||||
const cairo_stroke_style_t *stroke_style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_traps_t traps;
|
||||
cairo_box_t bbox;
|
||||
|
@ -322,14 +322,18 @@ _cairo_path_fixed_stroke_extents (const cairo_path_fixed_t *path,
|
|||
return status;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_path_fixed_bounds (const cairo_path_fixed_t *path,
|
||||
double *x1, double *y1,
|
||||
double *x2, double *y2)
|
||||
cairo_bool_t
|
||||
_cairo_path_fixed_extents (const cairo_path_fixed_t *path,
|
||||
cairo_box_t *box)
|
||||
{
|
||||
cairo_path_bounder_t bounder;
|
||||
cairo_status_t status;
|
||||
|
||||
if (! path->has_curve_to) {
|
||||
*box = path->extents;
|
||||
return path->extents.p1.x <= path->extents.p2.x;
|
||||
}
|
||||
|
||||
_cairo_path_bounder_init (&bounder);
|
||||
|
||||
status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD,
|
||||
|
@ -340,15 +344,6 @@ _cairo_path_fixed_bounds (const cairo_path_fixed_t *path,
|
|||
&bounder);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
if (bounder.has_point) {
|
||||
*x1 = _cairo_fixed_to_double (bounder.extents.p1.x);
|
||||
*y1 = _cairo_fixed_to_double (bounder.extents.p1.y);
|
||||
*x2 = _cairo_fixed_to_double (bounder.extents.p2.x);
|
||||
*y2 = _cairo_fixed_to_double (bounder.extents.p2.y);
|
||||
} else {
|
||||
*x1 = 0.0;
|
||||
*y1 = 0.0;
|
||||
*x2 = 0.0;
|
||||
*y2 = 0.0;
|
||||
}
|
||||
*box = bounder.extents;
|
||||
return bounder.has_point;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -35,6 +35,8 @@
|
|||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-boxes-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-path-fixed-private.h"
|
||||
#include "cairo-region-private.h"
|
||||
|
||||
|
@ -141,7 +143,8 @@ _cairo_path_fixed_fill_to_traps (const cairo_path_fixed_t *path,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_polygon_init (&polygon);
|
||||
_cairo_polygon_limit (&polygon, traps->limits, traps->num_limits);
|
||||
if (traps->num_limits)
|
||||
_cairo_polygon_limit (&polygon, traps->limits, traps->num_limits);
|
||||
|
||||
status = _cairo_path_fixed_fill_to_polygon (path,
|
||||
tolerance,
|
||||
|
@ -217,11 +220,8 @@ _cairo_path_fixed_fill_rectilinear_tessellate_to_region (const cairo_path_fixed_
|
|||
CLEANUP_TRAPS:
|
||||
_cairo_traps_fini (&traps);
|
||||
|
||||
if (unlikely (status)) { /* XXX _cairo_region_create_in_error() */
|
||||
region = cairo_region_create ();
|
||||
if (likely (region->status) == CAIRO_STATUS_SUCCESS)
|
||||
region->status = status;
|
||||
}
|
||||
if (unlikely (status))
|
||||
region = _cairo_region_create_in_error (status);
|
||||
|
||||
return region;
|
||||
}
|
||||
|
@ -391,3 +391,75 @@ _cairo_path_fixed_fill_rectilinear_to_traps (const cairo_path_fixed_t *path,
|
|||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_path_fixed_fill_rectilinear_tessellate_to_boxes (const cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
cairo_boxes_t *boxes)
|
||||
{
|
||||
cairo_polygon_t polygon;
|
||||
cairo_status_t status;
|
||||
|
||||
_cairo_polygon_init (&polygon);
|
||||
if (boxes->num_limits) {
|
||||
_cairo_polygon_limit (&polygon, boxes->limits, boxes->num_limits);
|
||||
boxes->num_limits = 0;
|
||||
}
|
||||
|
||||
/* tolerance will be ignored as the path is rectilinear */
|
||||
status = _cairo_path_fixed_fill_to_polygon (path, 0., &polygon);
|
||||
if (likely (status == CAIRO_STATUS_SUCCESS)) {
|
||||
status =
|
||||
_cairo_bentley_ottmann_tessellate_rectilinear_polygon_to_boxes (&polygon,
|
||||
fill_rule,
|
||||
boxes);
|
||||
}
|
||||
|
||||
_cairo_polygon_fini (&polygon);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_fill_rectilinear_to_boxes (const cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
cairo_boxes_t *boxes)
|
||||
{
|
||||
cairo_path_fixed_iter_t iter;
|
||||
cairo_status_t status;
|
||||
cairo_box_t box;
|
||||
|
||||
if (_cairo_path_fixed_is_box (path, &box))
|
||||
return _cairo_boxes_add (boxes, &box);
|
||||
|
||||
_cairo_path_fixed_iter_init (&iter, path);
|
||||
while (_cairo_path_fixed_iter_is_fill_box (&iter, &box)) {
|
||||
if (box.p1.y == box.p2.y || box.p1.x == box.p2.x)
|
||||
continue;
|
||||
|
||||
if (box.p1.y > box.p2.y) {
|
||||
cairo_fixed_t t;
|
||||
|
||||
t = box.p1.y;
|
||||
box.p1.y = box.p2.y;
|
||||
box.p2.y = t;
|
||||
|
||||
t = box.p1.x;
|
||||
box.p1.x = box.p2.x;
|
||||
box.p2.x = t;
|
||||
}
|
||||
|
||||
status = _cairo_boxes_add (boxes, &box);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
|
||||
if (_cairo_path_fixed_iter_at_end (&iter))
|
||||
return _cairo_bentley_ottmann_tessellate_boxes (boxes, fill_rule, boxes);
|
||||
|
||||
/* path is not rectangular, try extracting clipped rectilinear edges */
|
||||
_cairo_boxes_clear (boxes);
|
||||
return _cairo_path_fixed_fill_rectilinear_tessellate_to_boxes (path,
|
||||
fill_rule,
|
||||
boxes);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -61,9 +61,10 @@ typedef char cairo_path_op_t;
|
|||
|
||||
typedef struct _cairo_path_buf {
|
||||
cairo_list_t link;
|
||||
unsigned int buf_size;
|
||||
unsigned int num_ops;
|
||||
unsigned int size_ops;
|
||||
unsigned int num_points;
|
||||
unsigned int size_points;
|
||||
|
||||
cairo_path_op_t *op;
|
||||
cairo_point_t *points;
|
||||
|
@ -80,15 +81,17 @@ struct _cairo_path_fixed {
|
|||
cairo_point_t last_move_point;
|
||||
cairo_point_t current_point;
|
||||
unsigned int has_current_point : 1;
|
||||
unsigned int has_last_move_point : 1;
|
||||
unsigned int has_curve_to : 1;
|
||||
unsigned int is_rectilinear : 1;
|
||||
unsigned int maybe_fill_region : 1;
|
||||
unsigned int is_empty_fill : 1;
|
||||
|
||||
cairo_box_t extents;
|
||||
|
||||
cairo_path_buf_fixed_t buf;
|
||||
};
|
||||
|
||||
|
||||
cairo_private void
|
||||
_cairo_path_fixed_translate (cairo_path_fixed_t *path,
|
||||
cairo_fixed_t offx,
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -38,6 +38,7 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-path-fixed-private.h"
|
||||
#include "cairo-slope-private.h"
|
||||
|
||||
|
@ -52,7 +53,7 @@ _cairo_path_fixed_add_buf (cairo_path_fixed_t *path,
|
|||
cairo_path_buf_t *buf);
|
||||
|
||||
static cairo_path_buf_t *
|
||||
_cairo_path_buf_create (int buf_size);
|
||||
_cairo_path_buf_create (int size_ops, int size_points);
|
||||
|
||||
static void
|
||||
_cairo_path_buf_destroy (cairo_path_buf_t *buf);
|
||||
|
@ -88,18 +89,23 @@ _cairo_path_fixed_init (cairo_path_fixed_t *path)
|
|||
|
||||
path->buf.base.num_ops = 0;
|
||||
path->buf.base.num_points = 0;
|
||||
path->buf.base.buf_size = CAIRO_PATH_BUF_SIZE;
|
||||
path->buf.base.size_ops = ARRAY_LENGTH (path->buf.op);
|
||||
path->buf.base.size_points = ARRAY_LENGTH (path->buf.points);
|
||||
path->buf.base.op = path->buf.op;
|
||||
path->buf.base.points = path->buf.points;
|
||||
|
||||
path->current_point.x = 0;
|
||||
path->current_point.y = 0;
|
||||
path->last_move_point = path->current_point;
|
||||
path->has_last_move_point = FALSE;
|
||||
path->has_current_point = FALSE;
|
||||
path->has_curve_to = FALSE;
|
||||
path->is_rectilinear = TRUE;
|
||||
path->maybe_fill_region = TRUE;
|
||||
path->is_empty_fill = TRUE;
|
||||
|
||||
path->extents.p1.x = path->extents.p1.y = INT_MAX;
|
||||
path->extents.p2.x = path->extents.p2.y = INT_MIN;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
|
@ -107,7 +113,7 @@ _cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
|
|||
const cairo_path_fixed_t *other)
|
||||
{
|
||||
cairo_path_buf_t *buf, *other_buf;
|
||||
unsigned int num_points, num_ops, buf_size;
|
||||
unsigned int num_points, num_ops;
|
||||
|
||||
VG (VALGRIND_MAKE_MEM_UNDEFINED (path, sizeof (cairo_path_fixed_t)));
|
||||
|
||||
|
@ -115,18 +121,22 @@ _cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
|
|||
|
||||
path->buf.base.op = path->buf.op;
|
||||
path->buf.base.points = path->buf.points;
|
||||
path->buf.base.size_ops = ARRAY_LENGTH (path->buf.op);
|
||||
path->buf.base.size_points = ARRAY_LENGTH (path->buf.points);
|
||||
|
||||
path->current_point = other->current_point;
|
||||
path->last_move_point = other->last_move_point;
|
||||
path->has_last_move_point = other->has_last_move_point;
|
||||
path->has_current_point = other->has_current_point;
|
||||
path->has_curve_to = other->has_curve_to;
|
||||
path->is_rectilinear = other->is_rectilinear;
|
||||
path->maybe_fill_region = other->maybe_fill_region;
|
||||
path->is_empty_fill = other->is_empty_fill;
|
||||
|
||||
path->extents = other->extents;
|
||||
|
||||
path->buf.base.num_ops = other->buf.base.num_ops;
|
||||
path->buf.base.num_points = other->buf.base.num_points;
|
||||
path->buf.base.buf_size = other->buf.base.buf_size;
|
||||
memcpy (path->buf.op, other->buf.base.op,
|
||||
other->buf.base.num_ops * sizeof (other->buf.op[0]));
|
||||
memcpy (path->buf.points, other->buf.points,
|
||||
|
@ -141,9 +151,8 @@ _cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
|
|||
num_points += other_buf->num_points;
|
||||
}
|
||||
|
||||
buf_size = MAX (num_ops, (num_points + 1) / 2);
|
||||
if (buf_size) {
|
||||
buf = _cairo_path_buf_create (buf_size);
|
||||
if (num_ops) {
|
||||
buf = _cairo_path_buf_create (num_ops, num_points);
|
||||
if (unlikely (buf == NULL)) {
|
||||
_cairo_path_fixed_fini (path);
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
@ -175,6 +184,8 @@ _cairo_path_fixed_hash (const cairo_path_fixed_t *path)
|
|||
const cairo_path_buf_t *buf;
|
||||
int num_points, num_ops;
|
||||
|
||||
hash = _cairo_hash_bytes (hash, &path->extents, sizeof (path->extents));
|
||||
|
||||
num_ops = num_points = 0;
|
||||
cairo_path_foreach_buf_start (buf, path) {
|
||||
hash = _cairo_hash_bytes (hash, buf->op,
|
||||
|
@ -230,21 +241,25 @@ _cairo_path_fixed_equal (const cairo_path_fixed_t *a,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
num_ops_a = num_points_a = 0;
|
||||
if (a != NULL) {
|
||||
cairo_path_foreach_buf_start (buf_a, a) {
|
||||
num_ops_a += buf_a->num_ops;
|
||||
num_points_a += buf_a->num_points;
|
||||
} cairo_path_foreach_buf_end (buf_a, a);
|
||||
if (a->extents.p1.x != b->extents.p1.x ||
|
||||
a->extents.p1.y != b->extents.p1.y ||
|
||||
a->extents.p2.x != b->extents.p2.x ||
|
||||
a->extents.p2.y != b->extents.p2.y)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
num_ops_a = num_points_a = 0;
|
||||
cairo_path_foreach_buf_start (buf_a, a) {
|
||||
num_ops_a += buf_a->num_ops;
|
||||
num_points_a += buf_a->num_points;
|
||||
} cairo_path_foreach_buf_end (buf_a, a);
|
||||
|
||||
num_ops_b = num_points_b = 0;
|
||||
if (b != NULL) {
|
||||
cairo_path_foreach_buf_start (buf_b, b) {
|
||||
num_ops_b += buf_b->num_ops;
|
||||
num_points_b += buf_b->num_points;
|
||||
} cairo_path_foreach_buf_end (buf_b, b);
|
||||
}
|
||||
cairo_path_foreach_buf_start (buf_b, b) {
|
||||
num_ops_b += buf_b->num_ops;
|
||||
num_points_b += buf_b->num_points;
|
||||
} cairo_path_foreach_buf_end (buf_b, b);
|
||||
|
||||
if (num_ops_a == 0 && num_ops_b == 0)
|
||||
return TRUE;
|
||||
|
@ -252,8 +267,6 @@ _cairo_path_fixed_equal (const cairo_path_fixed_t *a,
|
|||
if (num_ops_a != num_ops_b || num_points_a != num_points_b)
|
||||
return FALSE;
|
||||
|
||||
assert (a != NULL && b != NULL);
|
||||
|
||||
buf_a = cairo_path_head (a);
|
||||
num_points_a = buf_a->num_points;
|
||||
num_ops_a = buf_a->num_ops;
|
||||
|
@ -364,6 +377,21 @@ _cairo_path_last_op (cairo_path_fixed_t *path)
|
|||
return buf->op[buf->num_ops - 1];
|
||||
}
|
||||
|
||||
static inline void
|
||||
_cairo_path_fixed_extents_add (cairo_path_fixed_t *path,
|
||||
const cairo_point_t *point)
|
||||
{
|
||||
if (point->x < path->extents.p1.x)
|
||||
path->extents.p1.x = point->x;
|
||||
if (point->y < path->extents.p1.y)
|
||||
path->extents.p1.y = point->y;
|
||||
|
||||
if (point->x > path->extents.p2.x)
|
||||
path->extents.p2.x = point->x;
|
||||
if (point->y > path->extents.p2.y)
|
||||
path->extents.p2.y = point->y;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_move_to (cairo_path_fixed_t *path,
|
||||
cairo_fixed_t x,
|
||||
|
@ -402,6 +430,7 @@ _cairo_path_fixed_move_to (cairo_path_fixed_t *path,
|
|||
|
||||
path->current_point = point;
|
||||
path->last_move_point = point;
|
||||
path->has_last_move_point = TRUE;
|
||||
path->has_current_point = TRUE;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
@ -510,6 +539,11 @@ _cairo_path_fixed_line_to (cairo_path_fixed_t *path,
|
|||
}
|
||||
|
||||
path->current_point = point;
|
||||
if (path->has_last_move_point) {
|
||||
_cairo_path_fixed_extents_add (path, &path->last_move_point);
|
||||
path->has_last_move_point = FALSE;
|
||||
}
|
||||
_cairo_path_fixed_extents_add (path, &point);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -556,6 +590,15 @@ _cairo_path_fixed_curve_to (cairo_path_fixed_t *path,
|
|||
path->is_rectilinear = FALSE;
|
||||
path->maybe_fill_region = FALSE;
|
||||
|
||||
/* coarse bounds */
|
||||
if (path->has_last_move_point) {
|
||||
_cairo_path_fixed_extents_add (path, &path->last_move_point);
|
||||
path->has_last_move_point = FALSE;
|
||||
}
|
||||
_cairo_path_fixed_extents_add (path, &point[0]);
|
||||
_cairo_path_fixed_extents_add (path, &point[1]);
|
||||
_cairo_path_fixed_extents_add (path, &point[2]);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -640,10 +683,10 @@ _cairo_path_fixed_add (cairo_path_fixed_t *path,
|
|||
{
|
||||
cairo_path_buf_t *buf = cairo_path_tail (path);
|
||||
|
||||
if (buf->num_ops + 1 > buf->buf_size ||
|
||||
buf->num_points + num_points > 2 * buf->buf_size)
|
||||
if (buf->num_ops + 1 > buf->size_ops ||
|
||||
buf->num_points + num_points > buf->size_points)
|
||||
{
|
||||
buf = _cairo_path_buf_create (buf->buf_size * 2);
|
||||
buf = _cairo_path_buf_create (buf->num_ops * 2, buf->num_points * 2);
|
||||
if (unlikely (buf == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
|
@ -689,25 +732,23 @@ _cairo_path_fixed_add_buf (cairo_path_fixed_t *path,
|
|||
cairo_list_add_tail (&buf->link, &cairo_path_head (path)->link);
|
||||
}
|
||||
|
||||
COMPILE_TIME_ASSERT (sizeof (cairo_path_op_t) == 1);
|
||||
static cairo_path_buf_t *
|
||||
_cairo_path_buf_create (int buf_size)
|
||||
_cairo_path_buf_create (int size_ops, int size_points)
|
||||
{
|
||||
cairo_path_buf_t *buf;
|
||||
|
||||
/* adjust buf_size to ensure that buf->points is naturally aligned */
|
||||
buf_size += sizeof (double)
|
||||
- ((buf_size + sizeof (cairo_path_buf_t)) & (sizeof (double)-1));
|
||||
buf = _cairo_malloc_ab_plus_c (buf_size,
|
||||
sizeof (cairo_path_op_t) +
|
||||
2 * sizeof (cairo_point_t),
|
||||
sizeof (cairo_path_buf_t));
|
||||
/* adjust size_ops to ensure that buf->points is naturally aligned */
|
||||
size_ops += sizeof (double) - ((sizeof (cairo_path_buf_t) + size_ops) % sizeof (double));
|
||||
buf = _cairo_malloc_ab_plus_c (size_points, sizeof (cairo_point_t), size_ops + sizeof (cairo_path_buf_t));
|
||||
if (buf) {
|
||||
buf->num_ops = 0;
|
||||
buf->num_points = 0;
|
||||
buf->buf_size = buf_size;
|
||||
buf->size_ops = size_ops;
|
||||
buf->size_points = size_points;
|
||||
|
||||
buf->op = (cairo_path_op_t *) (buf + 1);
|
||||
buf->points = (cairo_point_t *) (buf->op + buf_size);
|
||||
buf->points = (cairo_point_t *) (buf->op + size_ops);
|
||||
}
|
||||
|
||||
return buf;
|
||||
|
@ -906,6 +947,12 @@ _cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path,
|
|||
buf->points[i].y += offy;
|
||||
}
|
||||
} cairo_path_foreach_buf_end (buf, path);
|
||||
|
||||
path->extents.p1.x = _cairo_fixed_mul (scalex, path->extents.p1.x) + offx;
|
||||
path->extents.p2.x = _cairo_fixed_mul (scalex, path->extents.p2.x) + offx;
|
||||
|
||||
path->extents.p1.y = _cairo_fixed_mul (scaley, path->extents.p1.y) + offy;
|
||||
path->extents.p2.y = _cairo_fixed_mul (scaley, path->extents.p2.y) + offy;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -926,9 +973,9 @@ _cairo_path_fixed_translate (cairo_path_fixed_t *path,
|
|||
}
|
||||
|
||||
path->last_move_point.x += offx;
|
||||
path->last_move_point.y += offx;
|
||||
path->last_move_point.y += offy;
|
||||
path->current_point.x += offx;
|
||||
path->current_point.y += offx;
|
||||
path->current_point.y += offy;
|
||||
|
||||
cairo_path_foreach_buf_start (buf, path) {
|
||||
for (i = 0; i < buf->num_points; i++) {
|
||||
|
@ -936,6 +983,11 @@ _cairo_path_fixed_translate (cairo_path_fixed_t *path,
|
|||
buf->points[i].y += offy;
|
||||
}
|
||||
} cairo_path_foreach_buf_end (buf, path);
|
||||
|
||||
path->extents.p1.x += offx;
|
||||
path->extents.p1.y += offy;
|
||||
path->extents.p2.x += offx;
|
||||
path->extents.p2.y += offy;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -959,14 +1011,22 @@ _cairo_path_fixed_transform (cairo_path_fixed_t *path,
|
|||
|
||||
if (matrix->yx == 0.0 && matrix->xy == 0.0) {
|
||||
/* Fast path for the common case of scale+transform */
|
||||
_cairo_path_fixed_offset_and_scale (path,
|
||||
_cairo_fixed_from_double (matrix->x0),
|
||||
_cairo_fixed_from_double (matrix->y0),
|
||||
_cairo_fixed_from_double (matrix->xx),
|
||||
_cairo_fixed_from_double (matrix->yy));
|
||||
if (matrix->xx == 1. && matrix->yy == 1.) {
|
||||
_cairo_path_fixed_translate (path,
|
||||
_cairo_fixed_from_double (matrix->x0),
|
||||
_cairo_fixed_from_double (matrix->y0));
|
||||
} else {
|
||||
_cairo_path_fixed_offset_and_scale (path,
|
||||
_cairo_fixed_from_double (matrix->x0),
|
||||
_cairo_fixed_from_double (matrix->y0),
|
||||
_cairo_fixed_from_double (matrix->xx),
|
||||
_cairo_fixed_from_double (matrix->yy));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
path->extents.p1.x = path->extents.p1.y = INT_MAX;
|
||||
path->extents.p2.x = path->extents.p2.y = INT_MIN;
|
||||
path->maybe_fill_region = FALSE;
|
||||
cairo_path_foreach_buf_start (buf, path) {
|
||||
for (i = 0; i < buf->num_points; i++) {
|
||||
|
@ -977,6 +1037,9 @@ _cairo_path_fixed_transform (cairo_path_fixed_t *path,
|
|||
|
||||
buf->points[i].x = _cairo_fixed_from_double (dx);
|
||||
buf->points[i].y = _cairo_fixed_from_double (dy);
|
||||
|
||||
/* XXX need to eliminate surplus move-to's? */
|
||||
_cairo_path_fixed_extents_add (path, &buf->points[i]);
|
||||
}
|
||||
} cairo_path_foreach_buf_end (buf, path);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -39,6 +39,8 @@
|
|||
#define _BSD_SOURCE /* for hypot() */
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-boxes-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-path-fixed-private.h"
|
||||
#include "cairo-slope-private.h"
|
||||
|
||||
|
@ -51,12 +53,11 @@ typedef struct _cairo_stroker_dash {
|
|||
|
||||
double dash_offset;
|
||||
const double *dashes;
|
||||
double approximate_dashes[2];
|
||||
unsigned int num_dashes;
|
||||
} cairo_stroker_dash_t;
|
||||
|
||||
typedef struct cairo_stroker {
|
||||
cairo_stroke_style_t *style;
|
||||
cairo_stroke_style_t style;
|
||||
|
||||
const cairo_matrix_t *ctm;
|
||||
const cairo_matrix_t *ctm_inverse;
|
||||
|
@ -138,39 +139,29 @@ _cairo_stroker_dash_step (cairo_stroker_dash_t *dash, double step)
|
|||
|
||||
static void
|
||||
_cairo_stroker_dash_init (cairo_stroker_dash_t *dash,
|
||||
const cairo_stroke_style_t *style,
|
||||
const cairo_matrix_t *ctm,
|
||||
double tolerance)
|
||||
const cairo_stroke_style_t *style)
|
||||
{
|
||||
dash->dashed = style->dash != NULL;
|
||||
if (! dash->dashed)
|
||||
return;
|
||||
|
||||
if (_cairo_stroke_style_dash_can_approximate (style, ctm, tolerance)) {
|
||||
_cairo_stroke_style_dash_approximate (style, ctm, tolerance,
|
||||
&dash->dash_offset,
|
||||
dash->approximate_dashes,
|
||||
&dash->num_dashes);
|
||||
dash->dashes = dash->approximate_dashes;
|
||||
} else {
|
||||
dash->dashes = style->dash;
|
||||
dash->num_dashes = style->num_dashes;
|
||||
dash->dash_offset = style->dash_offset;
|
||||
}
|
||||
dash->dashes = style->dash;
|
||||
dash->num_dashes = style->num_dashes;
|
||||
dash->dash_offset = style->dash_offset;
|
||||
|
||||
_cairo_stroker_dash_start (dash);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_stroker_init (cairo_stroker_t *stroker,
|
||||
cairo_stroke_style_t *stroke_style,
|
||||
const cairo_stroke_style_t *stroke_style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse,
|
||||
double tolerance)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
stroker->style = stroke_style;
|
||||
stroker->style = *stroke_style;
|
||||
stroker->ctm = ctm;
|
||||
stroker->ctm_inverse = ctm_inverse;
|
||||
stroker->tolerance = tolerance;
|
||||
|
@ -190,7 +181,7 @@ _cairo_stroker_init (cairo_stroker_t *stroker,
|
|||
stroker->has_first_face = FALSE;
|
||||
stroker->has_initial_sub_path = FALSE;
|
||||
|
||||
_cairo_stroker_dash_init (&stroker->dash, stroke_style, ctm, tolerance);
|
||||
_cairo_stroker_dash_init (&stroker->dash, stroke_style);
|
||||
|
||||
stroker->add_external_edge = NULL;
|
||||
|
||||
|
@ -213,7 +204,7 @@ _cairo_stroker_limit (cairo_stroker_t *stroker,
|
|||
* of the bounds but which might generate rendering that's within bounds.
|
||||
*/
|
||||
|
||||
_cairo_stroke_style_max_distance_from_path (stroker->style, stroker->ctm,
|
||||
_cairo_stroke_style_max_distance_from_path (&stroker->style, stroker->ctm,
|
||||
&dx, &dy);
|
||||
|
||||
fdx = _cairo_fixed_from_double (dx);
|
||||
|
@ -456,7 +447,7 @@ _cairo_stroker_join (cairo_stroker_t *stroker,
|
|||
outpt = &out->cw;
|
||||
}
|
||||
|
||||
switch (stroker->style->line_join) {
|
||||
switch (stroker->style.line_join) {
|
||||
case CAIRO_LINE_JOIN_ROUND:
|
||||
/* construct a fan around the common midpoint */
|
||||
return _tessellate_fan (stroker,
|
||||
|
@ -470,7 +461,7 @@ _cairo_stroker_join (cairo_stroker_t *stroker,
|
|||
/* dot product of incoming slope vector with outgoing slope vector */
|
||||
double in_dot_out = -in->usr_vector.x * out->usr_vector.x +
|
||||
-in->usr_vector.y * out->usr_vector.y;
|
||||
double ml = stroker->style->miter_limit;
|
||||
double ml = stroker->style.miter_limit;
|
||||
|
||||
/* Check the miter limit -- lines meeting at an acute angle
|
||||
* can generate long miters, the limit converts them to bevel
|
||||
|
@ -665,7 +656,7 @@ static cairo_status_t
|
|||
_cairo_stroker_add_cap (cairo_stroker_t *stroker,
|
||||
const cairo_stroke_face_t *f)
|
||||
{
|
||||
switch (stroker->style->line_cap) {
|
||||
switch (stroker->style.line_cap) {
|
||||
case CAIRO_LINE_CAP_ROUND: {
|
||||
cairo_slope_t slope;
|
||||
|
||||
|
@ -687,8 +678,8 @@ _cairo_stroker_add_cap (cairo_stroker_t *stroker,
|
|||
|
||||
dx = f->usr_vector.x;
|
||||
dy = f->usr_vector.y;
|
||||
dx *= stroker->style->line_width / 2.0;
|
||||
dy *= stroker->style->line_width / 2.0;
|
||||
dx *= stroker->style.line_width / 2.0;
|
||||
dy *= stroker->style.line_width / 2.0;
|
||||
cairo_matrix_transform_distance (stroker->ctm, &dx, &dy);
|
||||
fvector.dx = _cairo_fixed_from_double (dx);
|
||||
fvector.dy = _cairo_fixed_from_double (dy);
|
||||
|
@ -826,13 +817,13 @@ _compute_face (const cairo_point_t *point, cairo_slope_t *dev_slope,
|
|||
*/
|
||||
if (stroker->ctm_det_positive)
|
||||
{
|
||||
face_dx = - slope_dy * (stroker->style->line_width / 2.0);
|
||||
face_dy = slope_dx * (stroker->style->line_width / 2.0);
|
||||
face_dx = - slope_dy * (stroker->style.line_width / 2.0);
|
||||
face_dy = slope_dx * (stroker->style.line_width / 2.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
face_dx = slope_dy * (stroker->style->line_width / 2.0);
|
||||
face_dy = - slope_dx * (stroker->style->line_width / 2.0);
|
||||
face_dx = slope_dy * (stroker->style.line_width / 2.0);
|
||||
face_dy = - slope_dx * (stroker->style.line_width / 2.0);
|
||||
}
|
||||
|
||||
/* back to device space */
|
||||
|
@ -866,7 +857,7 @@ _cairo_stroker_add_caps (cairo_stroker_t *stroker)
|
|||
if (stroker->has_initial_sub_path
|
||||
&& ! stroker->has_first_face
|
||||
&& ! stroker->has_current_face
|
||||
&& stroker->style->line_cap == CAIRO_LINE_JOIN_ROUND)
|
||||
&& stroker->style.line_cap == CAIRO_LINE_JOIN_ROUND)
|
||||
{
|
||||
/* pick an arbitrary slope to use */
|
||||
double dx = 1.0, dy = 0.0;
|
||||
|
@ -1231,8 +1222,8 @@ _cairo_stroker_curve_to (void *closure,
|
|||
|
||||
/* Temporarily modify the stroker to use round joins to guarantee
|
||||
* smooth stroked curves. */
|
||||
line_join_save = stroker->style->line_join;
|
||||
stroker->style->line_join = CAIRO_LINE_JOIN_ROUND;
|
||||
line_join_save = stroker->style.line_join;
|
||||
stroker->style.line_join = CAIRO_LINE_JOIN_ROUND;
|
||||
|
||||
status = _cairo_spline_decompose (&spline, stroker->tolerance);
|
||||
if (unlikely (status))
|
||||
|
@ -1258,7 +1249,7 @@ _cairo_stroker_curve_to (void *closure,
|
|||
stroker->current_face = face;
|
||||
}
|
||||
|
||||
stroker->style->line_join = line_join_save;
|
||||
stroker->style.line_join = line_join_save;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -1299,9 +1290,9 @@ _cairo_stroker_close_path (void *closure)
|
|||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_stroke_to_shaper (cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *stroke_style,
|
||||
cairo_matrix_t *ctm,
|
||||
cairo_matrix_t *ctm_inverse,
|
||||
const cairo_stroke_style_t *stroke_style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_status_t (*add_triangle) (void *closure,
|
||||
const cairo_point_t triangle[3]),
|
||||
|
@ -1350,7 +1341,7 @@ BAIL:
|
|||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_stroke_to_polygon (const cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *stroke_style,
|
||||
const cairo_stroke_style_t *stroke_style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
|
@ -1394,7 +1385,7 @@ BAIL:
|
|||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_stroke_to_traps (const cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *stroke_style,
|
||||
const cairo_stroke_style_t *stroke_style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
|
@ -1418,14 +1409,15 @@ _cairo_path_fixed_stroke_to_traps (const cairo_path_fixed_t *path,
|
|||
}
|
||||
|
||||
_cairo_polygon_init (&polygon);
|
||||
_cairo_polygon_limit (&polygon, traps->limits, traps->num_limits);
|
||||
if (traps->num_limits)
|
||||
_cairo_polygon_limit (&polygon, traps->limits, traps->num_limits);
|
||||
|
||||
status = _cairo_path_fixed_stroke_to_polygon (path,
|
||||
stroke_style,
|
||||
ctm,
|
||||
ctm_inverse,
|
||||
tolerance,
|
||||
&polygon);
|
||||
stroke_style,
|
||||
ctm,
|
||||
ctm_inverse,
|
||||
tolerance,
|
||||
&polygon);
|
||||
if (unlikely (status))
|
||||
goto BAIL;
|
||||
|
||||
|
@ -1449,11 +1441,12 @@ typedef struct _segment_t {
|
|||
} segment_t;
|
||||
|
||||
typedef struct _cairo_rectilinear_stroker {
|
||||
cairo_stroke_style_t *stroke_style;
|
||||
const cairo_stroke_style_t *stroke_style;
|
||||
const cairo_matrix_t *ctm;
|
||||
|
||||
cairo_fixed_t half_line_width;
|
||||
cairo_traps_t *traps;
|
||||
cairo_bool_t do_traps;
|
||||
void *container;
|
||||
cairo_point_t current_point;
|
||||
cairo_point_t first_point;
|
||||
cairo_bool_t open_sub_path;
|
||||
|
@ -1484,27 +1477,60 @@ _cairo_rectilinear_stroker_limit (cairo_rectilinear_stroker_t *stroker,
|
|||
stroker->bounds.p2.y += stroker->half_line_width;
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_bool_t
|
||||
_cairo_rectilinear_stroker_init (cairo_rectilinear_stroker_t *stroker,
|
||||
cairo_stroke_style_t *stroke_style,
|
||||
const cairo_stroke_style_t *stroke_style,
|
||||
const cairo_matrix_t *ctm,
|
||||
cairo_traps_t *traps)
|
||||
cairo_bool_t do_traps,
|
||||
void *container)
|
||||
{
|
||||
/* This special-case rectilinear stroker only supports
|
||||
* miter-joined lines (not curves) and a translation-only matrix
|
||||
* (though it could probably be extended to support a matrix with
|
||||
* uniform, integer scaling).
|
||||
*
|
||||
* It also only supports horizontal and vertical line_to
|
||||
* elements. But we don't catch that here, but instead return
|
||||
* UNSUPPORTED from _cairo_rectilinear_stroker_line_to if any
|
||||
* non-rectilinear line_to is encountered.
|
||||
*/
|
||||
if (stroke_style->line_join != CAIRO_LINE_JOIN_MITER)
|
||||
return FALSE;
|
||||
|
||||
/* If the miter limit turns right angles into bevels, then we
|
||||
* can't use this optimization. Remember, the ratio is
|
||||
* 1/sin(ɸ/2). So the cutoff is 1/sin(π/4.0) or ⎷2,
|
||||
* which we round for safety. */
|
||||
if (stroke_style->miter_limit < M_SQRT2)
|
||||
return FALSE;
|
||||
|
||||
if (! (stroke_style->line_cap == CAIRO_LINE_CAP_BUTT ||
|
||||
stroke_style->line_cap == CAIRO_LINE_CAP_SQUARE))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (! _cairo_matrix_has_unity_scale (ctm))
|
||||
return FALSE;
|
||||
|
||||
stroker->stroke_style = stroke_style;
|
||||
stroker->ctm = ctm;
|
||||
|
||||
stroker->half_line_width =
|
||||
_cairo_fixed_from_double (stroke_style->line_width / 2.0);
|
||||
stroker->traps = traps;
|
||||
stroker->open_sub_path = FALSE;
|
||||
stroker->segments = stroker->segments_embedded;
|
||||
stroker->segments_size = ARRAY_LENGTH (stroker->segments_embedded);
|
||||
stroker->num_segments = 0;
|
||||
|
||||
/* Assume 2*EPSILON tolerance */
|
||||
_cairo_stroker_dash_init (&stroker->dash, stroke_style, ctm, _cairo_fixed_to_double (2 * CAIRO_FIXED_EPSILON));
|
||||
_cairo_stroker_dash_init (&stroker->dash, stroke_style);
|
||||
|
||||
stroker->has_bounds = FALSE;
|
||||
|
||||
stroker->do_traps = do_traps;
|
||||
stroker->container = container;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1663,7 +1689,16 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
|
|||
b->x += half_line_width;
|
||||
}
|
||||
|
||||
status = _cairo_traps_tessellate_rectangle (stroker->traps, a, b);
|
||||
if (stroker->do_traps) {
|
||||
status = _cairo_traps_tessellate_rectangle (stroker->container, a, b);
|
||||
} else {
|
||||
cairo_box_t box;
|
||||
|
||||
box.p1 = *a;
|
||||
box.p2 = *b;
|
||||
|
||||
status = _cairo_boxes_add (stroker->container, &box);
|
||||
}
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
|
@ -1729,8 +1764,16 @@ _cairo_rectilinear_stroker_emit_segments_dashed (cairo_rectilinear_stroker_t *st
|
|||
p2.x += half_line_width;
|
||||
}
|
||||
|
||||
status = _cairo_traps_tessellate_rectangle (stroker->traps,
|
||||
&p1, &p2);
|
||||
if (stroker->do_traps) {
|
||||
status = _cairo_traps_tessellate_rectangle (stroker->container, &p1, &p2);
|
||||
} else {
|
||||
cairo_box_t box;
|
||||
|
||||
box.p1 = p1;
|
||||
box.p2 = p2;
|
||||
|
||||
status = _cairo_boxes_add (stroker->container, &box);
|
||||
}
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
|
@ -1783,7 +1826,16 @@ _cairo_rectilinear_stroker_emit_segments_dashed (cairo_rectilinear_stroker_t *st
|
|||
if (a->x == b->x && a->y == b->y)
|
||||
continue;
|
||||
|
||||
status = _cairo_traps_tessellate_rectangle (stroker->traps, a, b);
|
||||
if (stroker->do_traps) {
|
||||
status = _cairo_traps_tessellate_rectangle (stroker->container, a, b);
|
||||
} else {
|
||||
cairo_box_t box;
|
||||
|
||||
box.p1 = *a;
|
||||
box.p2 = *b;
|
||||
|
||||
status = _cairo_boxes_add (stroker->container, &box);
|
||||
}
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
|
@ -1978,45 +2030,22 @@ _cairo_rectilinear_stroker_close_path (void *closure)
|
|||
|
||||
cairo_int_status_t
|
||||
_cairo_path_fixed_stroke_rectilinear_to_traps (const cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *stroke_style,
|
||||
const cairo_stroke_style_t *stroke_style,
|
||||
const cairo_matrix_t *ctm,
|
||||
cairo_traps_t *traps)
|
||||
{
|
||||
cairo_rectilinear_stroker_t rectilinear_stroker;
|
||||
cairo_int_status_t status;
|
||||
|
||||
/* This special-case rectilinear stroker only supports
|
||||
* miter-joined lines (not curves) and a translation-only matrix
|
||||
* (though it could probably be extended to support a matrix with
|
||||
* uniform, integer scaling).
|
||||
*
|
||||
* It also only supports horizontal and vertical line_to
|
||||
* elements. But we don't catch that here, but instead return
|
||||
* UNSUPPORTED from _cairo_rectilinear_stroker_line_to if any
|
||||
* non-rectilinear line_to is encountered.
|
||||
*/
|
||||
assert (path->is_rectilinear);
|
||||
|
||||
if (stroke_style->line_join != CAIRO_LINE_JOIN_MITER)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
/* If the miter limit turns right angles into bevels, then we
|
||||
* can't use this optimization. Remember, the ratio is
|
||||
* 1/sin(ɸ/2). So the cutoff is 1/sin(π/4.0) or ⎷2,
|
||||
* which we round for safety. */
|
||||
if (stroke_style->miter_limit < M_SQRT2)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (! (stroke_style->line_cap == CAIRO_LINE_CAP_BUTT ||
|
||||
stroke_style->line_cap == CAIRO_LINE_CAP_SQUARE))
|
||||
if (! _cairo_rectilinear_stroker_init (&rectilinear_stroker,
|
||||
stroke_style, ctm,
|
||||
TRUE, traps))
|
||||
{
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
if (! _cairo_matrix_has_unity_scale (ctm))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
_cairo_rectilinear_stroker_init (&rectilinear_stroker,
|
||||
stroke_style,
|
||||
ctm,
|
||||
traps);
|
||||
if (traps->num_limits) {
|
||||
_cairo_rectilinear_stroker_limit (&rectilinear_stroker,
|
||||
traps->limits,
|
||||
|
@ -2052,3 +2081,63 @@ BAIL:
|
|||
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_path_fixed_stroke_rectilinear_to_boxes (const cairo_path_fixed_t *path,
|
||||
const cairo_stroke_style_t *stroke_style,
|
||||
const cairo_matrix_t *ctm,
|
||||
cairo_boxes_t *boxes)
|
||||
{
|
||||
cairo_rectilinear_stroker_t rectilinear_stroker;
|
||||
cairo_int_status_t status;
|
||||
|
||||
assert (path->is_rectilinear);
|
||||
|
||||
if (! _cairo_rectilinear_stroker_init (&rectilinear_stroker,
|
||||
stroke_style, ctm,
|
||||
FALSE, boxes))
|
||||
{
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (boxes->num_limits) {
|
||||
_cairo_rectilinear_stroker_limit (&rectilinear_stroker,
|
||||
boxes->limits,
|
||||
boxes->num_limits);
|
||||
}
|
||||
|
||||
status = _cairo_path_fixed_interpret (path,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_cairo_rectilinear_stroker_move_to,
|
||||
rectilinear_stroker.dash.dashed ?
|
||||
_cairo_rectilinear_stroker_line_to_dashed :
|
||||
_cairo_rectilinear_stroker_line_to,
|
||||
NULL,
|
||||
_cairo_rectilinear_stroker_close_path,
|
||||
&rectilinear_stroker);
|
||||
if (unlikely (status))
|
||||
goto BAIL;
|
||||
|
||||
if (rectilinear_stroker.dash.dashed)
|
||||
status = _cairo_rectilinear_stroker_emit_segments_dashed (&rectilinear_stroker);
|
||||
else
|
||||
status = _cairo_rectilinear_stroker_emit_segments (&rectilinear_stroker);
|
||||
if (unlikely (status))
|
||||
goto BAIL;
|
||||
|
||||
/* As we incrementally tessellate, we do not eliminate self-intersections */
|
||||
status = _cairo_bentley_ottmann_tessellate_boxes (boxes,
|
||||
CAIRO_FILL_RULE_WINDING,
|
||||
boxes);
|
||||
if (unlikely (status))
|
||||
goto BAIL;
|
||||
|
||||
_cairo_rectilinear_stroker_fini (&rectilinear_stroker);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
BAIL:
|
||||
_cairo_rectilinear_stroker_fini (&rectilinear_stroker);
|
||||
_cairo_boxes_clear (boxes);
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -37,9 +37,19 @@
|
|||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-path-private.h"
|
||||
#include "cairo-path-fixed-private.h"
|
||||
|
||||
/**
|
||||
* SECTION:cairo-paths
|
||||
* @Title: Paths
|
||||
* @Short_Description: Creating paths and manipulating path data
|
||||
*
|
||||
* Paths are the most basic drawing tools and are primarily used to implicitly
|
||||
* generate simple masks.
|
||||
*/
|
||||
|
||||
static const cairo_path_t _cairo_path_nil = { CAIRO_STATUS_NO_MEMORY, NULL, 0 };
|
||||
|
||||
/* Closure for path interpretation. */
|
||||
|
|
|
@ -29,6 +29,29 @@
|
|||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-freed-pool-private.h"
|
||||
|
||||
/**
|
||||
* SECTION:cairo-pattern
|
||||
* @Title: cairo_pattern_t
|
||||
* @Short_Description: Sources for drawing
|
||||
* @See_Also: #cairo_t, #cairo_surface_t
|
||||
*
|
||||
* #cairo_pattern_t is the paint with which cairo draws.
|
||||
* The primary use of patterns is as the source for all cairo drawing
|
||||
* operations, although they can also be used as masks, that is, as the
|
||||
* brush too.
|
||||
*
|
||||
* A cairo pattern is created by using one of the many constructors,
|
||||
* of the form cairo_pattern_create_<emphasis>type</emphasis>()
|
||||
* or implicitly through
|
||||
* cairo_set_source_<emphasis>type</emphasis>() functions.
|
||||
*/
|
||||
|
||||
#if HAS_FREED_POOL
|
||||
static freed_pool_t freed_pattern_pool[4];
|
||||
#endif
|
||||
|
||||
static const cairo_solid_pattern_t _cairo_pattern_nil = {
|
||||
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
|
||||
|
@ -59,7 +82,28 @@ const cairo_solid_pattern_t _cairo_pattern_black = {
|
|||
CAIRO_FILTER_DEFAULT, /* filter */
|
||||
CAIRO_EXTEND_GRADIENT_DEFAULT}, /* extend */
|
||||
{ 0., 0., 0., 1., 0, 0, 0, 0xffff },/* color (double rgba, short rgba) */
|
||||
CAIRO_CONTENT_COLOR, /* content */
|
||||
};
|
||||
|
||||
const cairo_solid_pattern_t _cairo_pattern_clear = {
|
||||
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
|
||||
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
|
||||
CAIRO_STATUS_SUCCESS, /* status */
|
||||
{ 0, 0, 0, NULL }, /* user_data */
|
||||
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
|
||||
CAIRO_FILTER_DEFAULT, /* filter */
|
||||
CAIRO_EXTEND_GRADIENT_DEFAULT}, /* extend */
|
||||
{ 0., 0., 0., 0., 0, 0, 0, 0 },/* color (double rgba, short rgba) */
|
||||
};
|
||||
|
||||
const cairo_solid_pattern_t _cairo_pattern_white = {
|
||||
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
|
||||
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
|
||||
CAIRO_STATUS_SUCCESS, /* status */
|
||||
{ 0, 0, 0, NULL }, /* user_data */
|
||||
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
|
||||
CAIRO_FILTER_DEFAULT, /* filter */
|
||||
CAIRO_EXTEND_GRADIENT_DEFAULT}, /* extend */
|
||||
{ 1., 1., 1., 1., 0xffff, 0xffff, 0xffff, 0xffff },/* color (double rgba, short rgba) */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -329,23 +373,6 @@ _cairo_pattern_fini (cairo_pattern_t *pattern)
|
|||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_pattern_fini_snapshot (cairo_pattern_t *pattern)
|
||||
{
|
||||
/* XXX this is quite ugly, but currently necessary to break the circular
|
||||
* references with snapshot-cow and the recording-surface.
|
||||
* This operation remains safe only whilst _cairo_surface_snapshot() is
|
||||
* not public...
|
||||
*/
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
||||
cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) pattern;
|
||||
|
||||
cairo_surface_finish (spat->surface);
|
||||
}
|
||||
|
||||
_cairo_pattern_fini (pattern);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_pattern_create_copy (cairo_pattern_t **pattern_out,
|
||||
const cairo_pattern_t *other)
|
||||
|
@ -390,15 +417,10 @@ _cairo_pattern_create_copy (cairo_pattern_t **pattern_out,
|
|||
|
||||
void
|
||||
_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
|
||||
const cairo_color_t *color,
|
||||
cairo_content_t content)
|
||||
const cairo_color_t *color)
|
||||
{
|
||||
if (content == CAIRO_CONTENT_COLOR_ALPHA && CAIRO_COLOR_IS_OPAQUE (color))
|
||||
content = CAIRO_CONTENT_COLOR;
|
||||
|
||||
_cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
|
||||
pattern->color = *color;
|
||||
pattern->content = content;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -455,106 +477,13 @@ _cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
|
|||
pattern->r2 = _cairo_fixed_from_double (fabs (radius1));
|
||||
}
|
||||
|
||||
/* We use a small freed pattern cache here, because we don't want to
|
||||
* constantly reallocate simple colors. */
|
||||
#define MAX_PATTERN_CACHE_SIZE 4
|
||||
typedef struct {
|
||||
void *pool[MAX_PATTERN_CACHE_SIZE];
|
||||
int top;
|
||||
} freed_pool_t;
|
||||
|
||||
static freed_pool_t freed_pattern_pool[4];
|
||||
|
||||
static void *
|
||||
_atomic_fetch (void **slot)
|
||||
{
|
||||
return _cairo_atomic_ptr_cmpxchg (slot, *slot, NULL);
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_atomic_store (void **slot, void *pattern)
|
||||
{
|
||||
return _cairo_atomic_ptr_cmpxchg (slot, NULL, pattern) == NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
_freed_pattern_get (freed_pool_t *pool)
|
||||
{
|
||||
cairo_pattern_t *pattern;
|
||||
int i;
|
||||
|
||||
i = pool->top - 1;
|
||||
if (i < 0)
|
||||
i = 0;
|
||||
|
||||
pattern = _atomic_fetch (&pool->pool[i]);
|
||||
if (likely (pattern != NULL)) {
|
||||
pool->top = i;
|
||||
return pattern;
|
||||
}
|
||||
|
||||
/* either empty or contended */
|
||||
for (i = ARRAY_LENGTH (pool->pool); i--;) {
|
||||
pattern = _atomic_fetch (&pool->pool[i]);
|
||||
if (pattern != NULL) {
|
||||
pool->top = i;
|
||||
return pattern;
|
||||
}
|
||||
}
|
||||
|
||||
/* empty */
|
||||
pool->top = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_freed_pattern_put (freed_pool_t *pool,
|
||||
cairo_pattern_t *pattern)
|
||||
{
|
||||
int i = pool->top;
|
||||
|
||||
if (likely (i < ARRAY_LENGTH (pool->pool) &&
|
||||
_atomic_store (&pool->pool[i], pattern)))
|
||||
{
|
||||
pool->top = i + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* either full or contended */
|
||||
for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) {
|
||||
if (_atomic_store (&pool->pool[i], pattern)) {
|
||||
pool->top = i + 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* full */
|
||||
pool->top = ARRAY_LENGTH (pool->pool);
|
||||
free (pattern);
|
||||
}
|
||||
|
||||
static void
|
||||
_freed_patterns_reset (void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH (freed_pattern_pool); i++) {
|
||||
freed_pool_t *pool = &freed_pattern_pool[i];
|
||||
for (j = 0; j < ARRAY_LENGTH (pool->pool); j++) {
|
||||
free (pool->pool[j]);
|
||||
pool->pool[j] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cairo_pattern_t *
|
||||
_cairo_pattern_create_solid (const cairo_color_t *color,
|
||||
cairo_content_t content)
|
||||
_cairo_pattern_create_solid (const cairo_color_t *color)
|
||||
{
|
||||
cairo_solid_pattern_t *pattern;
|
||||
|
||||
pattern =
|
||||
_freed_pattern_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SOLID]);
|
||||
_freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SOLID]);
|
||||
if (unlikely (pattern == NULL)) {
|
||||
/* None cached, need to create a new pattern. */
|
||||
pattern = malloc (sizeof (cairo_solid_pattern_t));
|
||||
|
@ -564,7 +493,7 @@ _cairo_pattern_create_solid (const cairo_color_t *color,
|
|||
}
|
||||
}
|
||||
|
||||
_cairo_pattern_init_solid (pattern, color, content);
|
||||
_cairo_pattern_init_solid (pattern, color);
|
||||
CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
|
||||
|
||||
return &pattern->base;
|
||||
|
@ -580,7 +509,7 @@ _cairo_pattern_create_in_error (cairo_status_t status)
|
|||
|
||||
CAIRO_MUTEX_INITIALIZE ();
|
||||
|
||||
pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK, CAIRO_CONTENT_COLOR);
|
||||
pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
|
||||
if (pattern->status == CAIRO_STATUS_SUCCESS)
|
||||
status = _cairo_pattern_set_error (pattern, status);
|
||||
|
||||
|
@ -620,7 +549,7 @@ cairo_pattern_create_rgb (double red, double green, double blue)
|
|||
|
||||
CAIRO_MUTEX_INITIALIZE ();
|
||||
|
||||
return _cairo_pattern_create_solid (&color, CAIRO_CONTENT_COLOR);
|
||||
return _cairo_pattern_create_solid (&color);
|
||||
}
|
||||
slim_hidden_def (cairo_pattern_create_rgb);
|
||||
|
||||
|
@ -660,7 +589,7 @@ cairo_pattern_create_rgba (double red, double green, double blue,
|
|||
|
||||
CAIRO_MUTEX_INITIALIZE ();
|
||||
|
||||
return _cairo_pattern_create_solid (&color, CAIRO_CONTENT_COLOR_ALPHA);
|
||||
return _cairo_pattern_create_solid (&color);
|
||||
}
|
||||
slim_hidden_def (cairo_pattern_create_rgba);
|
||||
|
||||
|
@ -693,7 +622,7 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface)
|
|||
return _cairo_pattern_create_in_error (surface->status);
|
||||
|
||||
pattern =
|
||||
_freed_pattern_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SURFACE]);
|
||||
_freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SURFACE]);
|
||||
if (unlikely (pattern == NULL)) {
|
||||
pattern = malloc (sizeof (cairo_surface_pattern_t));
|
||||
if (unlikely (pattern == NULL)) {
|
||||
|
@ -743,7 +672,7 @@ cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
|
|||
cairo_linear_pattern_t *pattern;
|
||||
|
||||
pattern =
|
||||
_freed_pattern_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_LINEAR]);
|
||||
_freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_LINEAR]);
|
||||
if (unlikely (pattern == NULL)) {
|
||||
pattern = malloc (sizeof (cairo_linear_pattern_t));
|
||||
if (unlikely (pattern == NULL)) {
|
||||
|
@ -795,7 +724,7 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0,
|
|||
cairo_radial_pattern_t *pattern;
|
||||
|
||||
pattern =
|
||||
_freed_pattern_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_RADIAL]);
|
||||
_freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_RADIAL]);
|
||||
if (unlikely (pattern == NULL)) {
|
||||
pattern = malloc (sizeof (cairo_radial_pattern_t));
|
||||
if (unlikely (pattern == NULL)) {
|
||||
|
@ -899,7 +828,7 @@ cairo_pattern_destroy (cairo_pattern_t *pattern)
|
|||
_cairo_pattern_fini (pattern);
|
||||
|
||||
/* maintain a small cache of freed patterns */
|
||||
_freed_pattern_put (&freed_pattern_pool[type], pattern);
|
||||
_freed_pool_put (&freed_pattern_pool[type], pattern);
|
||||
}
|
||||
slim_hidden_def (cairo_pattern_destroy);
|
||||
|
||||
|
@ -1592,14 +1521,14 @@ _cairo_pattern_acquire_surface_for_gradient (const cairo_gradient_pattern_t *pat
|
|||
break;
|
||||
}
|
||||
|
||||
pixman_image_composite (PIXMAN_OP_SRC,
|
||||
pixman_image,
|
||||
NULL,
|
||||
image->pixman_image,
|
||||
x, y,
|
||||
0, 0,
|
||||
0, 0,
|
||||
width, height);
|
||||
pixman_image_composite32 (PIXMAN_OP_SRC,
|
||||
pixman_image,
|
||||
NULL,
|
||||
image->pixman_image,
|
||||
x, y,
|
||||
0, 0,
|
||||
0, 0,
|
||||
width, height);
|
||||
|
||||
pixman_image_unref (pixman_image);
|
||||
|
||||
|
@ -1628,7 +1557,6 @@ _cairo_pattern_acquire_surface_for_gradient (const cairo_gradient_pattern_t *pat
|
|||
#define MAX_SURFACE_CACHE_SIZE 16
|
||||
static struct {
|
||||
struct _cairo_pattern_solid_surface_cache{
|
||||
cairo_content_t content;
|
||||
cairo_color_t color;
|
||||
cairo_surface_t *surface;
|
||||
} cache[MAX_SURFACE_CACHE_SIZE];
|
||||
|
@ -1641,13 +1569,13 @@ _cairo_pattern_solid_surface_matches (
|
|||
const cairo_solid_pattern_t *pattern,
|
||||
cairo_surface_t *dst)
|
||||
{
|
||||
if (cache->content != pattern->content)
|
||||
if (cairo_surface_get_content (cache->surface) != _cairo_color_get_content (&pattern->color))
|
||||
return FALSE;
|
||||
|
||||
if (CAIRO_REFERENCE_COUNT_GET_VALUE (&cache->surface->ref_count) != 1)
|
||||
return FALSE;
|
||||
|
||||
if (! _cairo_surface_is_similar (cache->surface, dst, pattern->content))
|
||||
if (! _cairo_surface_is_similar (cache->surface, dst))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
|
@ -1736,8 +1664,7 @@ _cairo_pattern_acquire_surface_for_solid (const cairo_solid_pattern_t *patt
|
|||
goto UNLOCK;
|
||||
}
|
||||
|
||||
if (unlikely (! _cairo_surface_is_similar (surface,
|
||||
dst, pattern->content)))
|
||||
if (unlikely (! _cairo_surface_is_similar (surface, dst)))
|
||||
{
|
||||
/* In the rare event of a substitute surface being returned,
|
||||
* don't cache the fallback.
|
||||
|
@ -1753,7 +1680,6 @@ _cairo_pattern_acquire_surface_for_solid (const cairo_solid_pattern_t *patt
|
|||
to_destroy = solid_surface_cache.cache[i].surface;
|
||||
solid_surface_cache.cache[i].surface = surface;
|
||||
solid_surface_cache.cache[i].color = pattern->color;
|
||||
solid_surface_cache.cache[i].content = pattern->content;
|
||||
|
||||
DONE:
|
||||
*out = cairo_surface_reference (solid_surface_cache.cache[i].surface);
|
||||
|
@ -1800,6 +1726,151 @@ _cairo_pattern_reset_solid_surface_cache (void)
|
|||
CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
_extents_to_linear_parameter (const cairo_linear_pattern_t *linear,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
double t[2])
|
||||
{
|
||||
double t0, tdx, tdy;
|
||||
double p1x, p1y, pdx, pdy, invsqnorm;
|
||||
|
||||
p1x = _cairo_fixed_to_double (linear->p1.x);
|
||||
p1y = _cairo_fixed_to_double (linear->p1.y);
|
||||
pdx = _cairo_fixed_to_double (linear->p2.x) - p1x;
|
||||
pdy = _cairo_fixed_to_double (linear->p2.y) - p1y;
|
||||
invsqnorm = 1.0 / (pdx * pdx + pdy * pdy);
|
||||
pdx *= invsqnorm;
|
||||
pdy *= invsqnorm;
|
||||
|
||||
t0 = (extents->x - p1x) * pdx + (extents->y - p1y) * pdy;
|
||||
tdx = extents->width * pdx;
|
||||
tdy = extents->height * pdy;
|
||||
|
||||
t[0] = t[1] = t0;
|
||||
if (tdx < 0)
|
||||
t[0] += tdx;
|
||||
else
|
||||
t[1] += tdx;
|
||||
|
||||
if (tdy < 0)
|
||||
t[0] += tdy;
|
||||
else
|
||||
t[1] += tdy;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_linear_pattern_is_degenerate (const cairo_linear_pattern_t *linear)
|
||||
{
|
||||
return linear->p1.x == linear->p2.x && linear->p1.y == linear->p2.y;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_radial_pattern_is_degenerate (const cairo_radial_pattern_t *radial)
|
||||
{
|
||||
return radial->r1 == radial->r2 &&
|
||||
(radial->r1 == 0 /* && radial->r2 == 0 */ ||
|
||||
(radial->c1.x == radial->c2.x && radial->c1.y == radial->c2.y));
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_gradient_is_clear (const cairo_gradient_pattern_t *gradient,
|
||||
const cairo_rectangle_int_t *extents)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
|
||||
gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
|
||||
|
||||
if (gradient->n_stops == 0 ||
|
||||
(gradient->base.extend == CAIRO_EXTEND_NONE &&
|
||||
gradient->stops[0].offset == gradient->stops[gradient->n_stops - 1].offset))
|
||||
return TRUE;
|
||||
|
||||
/* Check if the extents intersect the drawn part of the pattern. */
|
||||
if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
|
||||
if (gradient->base.extend == CAIRO_EXTEND_NONE) {
|
||||
cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
|
||||
/* EXTEND_NONE degenerate linear gradients are clear */
|
||||
if (_linear_pattern_is_degenerate (linear))
|
||||
return TRUE;
|
||||
|
||||
if (extents != NULL) {
|
||||
double t[2];
|
||||
_extents_to_linear_parameter (linear, extents, t);
|
||||
if ((t[0] <= 0.0 && t[1] <= 0.0) || (t[0] >= 1.0 && t[1] >= 1.0))
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) gradient;
|
||||
/* degenerate radial gradients are clear */
|
||||
if (_radial_pattern_is_degenerate (radial) && FALSE)
|
||||
return TRUE;
|
||||
/* TODO: check actual intersection */
|
||||
}
|
||||
|
||||
for (i = 0; i < gradient->n_stops; i++)
|
||||
if (! CAIRO_COLOR_IS_CLEAR (&gradient->stops[i].color))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_gradient_pattern_is_solid
|
||||
*
|
||||
* Convenience function to determine whether a gradient pattern is
|
||||
* a solid color within the given extents. In this case the color
|
||||
* argument is initialized to the color the pattern represents.
|
||||
* This functions doesn't handle completely transparent gradients,
|
||||
* thus it should be called only after _cairo_pattern_is_clear has
|
||||
* returned FALSE.
|
||||
*
|
||||
* Return value: %TRUE if the pattern is a solid color.
|
||||
**/
|
||||
cairo_bool_t
|
||||
_cairo_gradient_pattern_is_solid (const cairo_gradient_pattern_t *gradient,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
cairo_color_t *color)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
|
||||
gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
|
||||
|
||||
/* TODO: radial, degenerate linear */
|
||||
if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
|
||||
if (gradient->base.extend == CAIRO_EXTEND_NONE) {
|
||||
cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
|
||||
double t[2];
|
||||
|
||||
/* We already know that the pattern is not clear, thus if some
|
||||
* part of it is clear, the whole is not solid.
|
||||
*/
|
||||
|
||||
if (extents == NULL)
|
||||
return FALSE;
|
||||
|
||||
_extents_to_linear_parameter (linear, extents, t);
|
||||
if (t[0] < 0.0 || t[1] > 1.0)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 1; i < gradient->n_stops; i++)
|
||||
if (! _cairo_color_stop_equal (&gradient->stops[0].color,
|
||||
&gradient->stops[i].color))
|
||||
return FALSE;
|
||||
|
||||
_cairo_color_init_rgba (color,
|
||||
gradient->stops[0].color.red,
|
||||
gradient->stops[0].color.green,
|
||||
gradient->stops[0].color.blue,
|
||||
gradient->stops[0].color.alpha);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_pattern_is_opaque_solid
|
||||
*
|
||||
|
@ -1825,10 +1896,78 @@ _cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern)
|
|||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_gradient_is_opaque (const cairo_gradient_pattern_t *gradient)
|
||||
_surface_is_opaque (const cairo_surface_pattern_t *pattern,
|
||||
const cairo_rectangle_int_t *r)
|
||||
{
|
||||
if (pattern->surface->content & CAIRO_CONTENT_ALPHA)
|
||||
return FALSE;
|
||||
|
||||
if (pattern->base.extend != CAIRO_EXTEND_NONE)
|
||||
return TRUE;
|
||||
|
||||
if (r != NULL) {
|
||||
cairo_rectangle_int_t extents;
|
||||
|
||||
if (! _cairo_surface_get_extents (pattern->surface, &extents))
|
||||
return TRUE;
|
||||
|
||||
if (r->x >= extents.x &&
|
||||
r->y >= extents.y &&
|
||||
r->x + r->width <= extents.x + extents.width &&
|
||||
r->y + r->height <= extents.y + extents.height)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_surface_is_clear (const cairo_surface_pattern_t *pattern)
|
||||
{
|
||||
cairo_rectangle_int_t extents;
|
||||
|
||||
if (_cairo_surface_get_extents (pattern->surface, &extents) &&
|
||||
(extents.width == 0 || extents.height == 0))
|
||||
return TRUE;
|
||||
|
||||
return pattern->surface->is_clear &&
|
||||
pattern->surface->content & CAIRO_CONTENT_ALPHA;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_gradient_is_opaque (const cairo_gradient_pattern_t *gradient,
|
||||
const cairo_rectangle_int_t *extents)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
|
||||
gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
|
||||
|
||||
if (gradient->n_stops == 0 ||
|
||||
(gradient->base.extend == CAIRO_EXTEND_NONE &&
|
||||
gradient->stops[0].offset == gradient->stops[gradient->n_stops - 1].offset))
|
||||
return FALSE;
|
||||
|
||||
if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
|
||||
if (gradient->base.extend == CAIRO_EXTEND_NONE) {
|
||||
double t[2];
|
||||
cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
|
||||
|
||||
/* EXTEND_NONE degenerate radial gradients are clear */
|
||||
if (_linear_pattern_is_degenerate (linear))
|
||||
return FALSE;
|
||||
|
||||
if (extents == NULL)
|
||||
return FALSE;
|
||||
|
||||
_extents_to_linear_parameter (linear, extents, t);
|
||||
if (t[0] < 0.0 || t[1] > 1.0)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < gradient->n_stops; i++)
|
||||
if (! CAIRO_COLOR_IS_OPAQUE (&gradient->stops[i].color))
|
||||
return FALSE;
|
||||
|
@ -1846,7 +1985,8 @@ _gradient_is_opaque (const cairo_gradient_pattern_t *gradient)
|
|||
* Return value: %TRUE if the pattern is a opaque.
|
||||
**/
|
||||
cairo_bool_t
|
||||
_cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern)
|
||||
_cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern,
|
||||
const cairo_rectangle_int_t *extents)
|
||||
{
|
||||
const cairo_pattern_union_t *pattern;
|
||||
|
||||
|
@ -1858,10 +1998,33 @@ _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern)
|
|||
case CAIRO_PATTERN_TYPE_SOLID:
|
||||
return _cairo_pattern_is_opaque_solid (abstract_pattern);
|
||||
case CAIRO_PATTERN_TYPE_SURFACE:
|
||||
return cairo_surface_get_content (pattern->surface.surface) == CAIRO_CONTENT_COLOR;
|
||||
return _surface_is_opaque (&pattern->surface, extents);
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
case CAIRO_PATTERN_TYPE_RADIAL:
|
||||
return _gradient_is_opaque (&pattern->gradient.base);
|
||||
return _gradient_is_opaque (&pattern->gradient.base, extents);
|
||||
}
|
||||
|
||||
ASSERT_NOT_REACHED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_pattern_is_clear (const cairo_pattern_t *abstract_pattern)
|
||||
{
|
||||
const cairo_pattern_union_t *pattern;
|
||||
|
||||
if (abstract_pattern->has_component_alpha)
|
||||
return FALSE;
|
||||
|
||||
pattern = (cairo_pattern_union_t *) abstract_pattern;
|
||||
switch (pattern->type) {
|
||||
case CAIRO_PATTERN_TYPE_SOLID:
|
||||
return CAIRO_COLOR_IS_CLEAR (&pattern->solid.color);
|
||||
case CAIRO_PATTERN_TYPE_SURFACE:
|
||||
return _surface_is_clear (&pattern->surface);
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
case CAIRO_PATTERN_TYPE_RADIAL:
|
||||
return _gradient_is_clear (&pattern->gradient.base, NULL);
|
||||
}
|
||||
|
||||
ASSERT_NOT_REACHED;
|
||||
|
@ -1882,7 +2045,7 @@ _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern)
|
|||
* the filter radius, so we just guess base on what we know that
|
||||
* backends do currently (see bug #10508)
|
||||
*/
|
||||
static cairo_filter_t
|
||||
cairo_filter_t
|
||||
_cairo_pattern_analyze_filter (const cairo_pattern_t *pattern,
|
||||
double *pad_out)
|
||||
{
|
||||
|
@ -2206,21 +2369,6 @@ _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t *pat
|
|||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
_init_solid_for_color_stop (cairo_solid_pattern_t *solid,
|
||||
const cairo_color_t *color)
|
||||
{
|
||||
cairo_color_t premult;
|
||||
|
||||
/* Color stops aren't premultiplied, so fix that here */
|
||||
_cairo_color_init_rgba (&premult,
|
||||
color->red,
|
||||
color->green,
|
||||
color->blue,
|
||||
color->alpha);
|
||||
_cairo_pattern_init_solid (solid, &premult, CAIRO_CONTENT_COLOR_ALPHA);
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_pattern_acquire_surface:
|
||||
* @pattern: a #cairo_pattern_t
|
||||
|
@ -2252,98 +2400,36 @@ _cairo_pattern_acquire_surface (const cairo_pattern_t *pattern,
|
|||
cairo_surface_t **surface_out,
|
||||
cairo_surface_attributes_t *attributes)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (unlikely (pattern->status)) {
|
||||
*surface_out = NULL;
|
||||
return pattern->status;
|
||||
}
|
||||
|
||||
switch (pattern->type) {
|
||||
case CAIRO_PATTERN_TYPE_SOLID: {
|
||||
cairo_solid_pattern_t *src = (cairo_solid_pattern_t *) pattern;
|
||||
case CAIRO_PATTERN_TYPE_SOLID:
|
||||
return _cairo_pattern_acquire_surface_for_solid ((cairo_solid_pattern_t *) pattern,
|
||||
dst, x, y, width, height,
|
||||
surface_out,
|
||||
attributes);
|
||||
|
||||
status = _cairo_pattern_acquire_surface_for_solid (src, dst,
|
||||
x, y, width, height,
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
case CAIRO_PATTERN_TYPE_RADIAL:
|
||||
return _cairo_pattern_acquire_surface_for_gradient ((cairo_gradient_pattern_t *) pattern,
|
||||
dst, x, y, width, height,
|
||||
surface_out,
|
||||
attributes);
|
||||
|
||||
case CAIRO_PATTERN_TYPE_SURFACE:
|
||||
return _cairo_pattern_acquire_surface_for_surface ((cairo_surface_pattern_t *) pattern,
|
||||
dst, x, y, width, height,
|
||||
flags,
|
||||
surface_out,
|
||||
attributes);
|
||||
} break;
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
case CAIRO_PATTERN_TYPE_RADIAL: {
|
||||
cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) pattern;
|
||||
|
||||
/* XXX The gradient->solid conversion code should now be redundant. */
|
||||
|
||||
/* fast path for gradients with less than 2 color stops */
|
||||
if (src->n_stops < 2)
|
||||
{
|
||||
cairo_solid_pattern_t solid;
|
||||
|
||||
if (src->n_stops) {
|
||||
_init_solid_for_color_stop (&solid, &src->stops->color);
|
||||
} else {
|
||||
_cairo_pattern_init_solid (&solid,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
CAIRO_CONTENT_ALPHA);
|
||||
}
|
||||
|
||||
status = _cairo_pattern_acquire_surface_for_solid (&solid, dst,
|
||||
x, y,
|
||||
width, height,
|
||||
surface_out,
|
||||
attributes);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* Is the gradient a uniform colour?
|
||||
* Happens more often than you would believe.
|
||||
*/
|
||||
for (i = 1; i < src->n_stops; i++) {
|
||||
if (! _cairo_color_equal (&src->stops[0].color,
|
||||
&src->stops[i].color))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == src->n_stops) {
|
||||
cairo_solid_pattern_t solid;
|
||||
|
||||
_init_solid_for_color_stop (&solid, &src->stops->color);
|
||||
|
||||
status =
|
||||
_cairo_pattern_acquire_surface_for_solid (&solid, dst,
|
||||
x, y,
|
||||
width, height,
|
||||
surface_out,
|
||||
attributes);
|
||||
} else {
|
||||
status =
|
||||
_cairo_pattern_acquire_surface_for_gradient (src, dst,
|
||||
x, y,
|
||||
width, height,
|
||||
surface_out,
|
||||
attributes);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case CAIRO_PATTERN_TYPE_SURFACE: {
|
||||
cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) pattern;
|
||||
|
||||
status = _cairo_pattern_acquire_surface_for_surface (src, dst,
|
||||
x, y,
|
||||
width, height,
|
||||
flags,
|
||||
surface_out,
|
||||
attributes);
|
||||
} break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
|
||||
return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2401,8 +2487,7 @@ _cairo_pattern_acquire_surfaces (const cairo_pattern_t *src,
|
|||
combined = src_solid->color;
|
||||
_cairo_color_multiply_alpha (&combined, mask_solid->color.alpha);
|
||||
|
||||
_cairo_pattern_init_solid (&src_tmp.solid, &combined,
|
||||
src_solid->content | mask_solid->content);
|
||||
_cairo_pattern_init_solid (&src_tmp.solid, &combined);
|
||||
|
||||
src = &src_tmp.base;
|
||||
mask = NULL;
|
||||
|
@ -2452,7 +2537,6 @@ void
|
|||
_cairo_pattern_get_extents (const cairo_pattern_t *pattern,
|
||||
cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_matrix_t imatrix;
|
||||
double x1, y1, x2, y2;
|
||||
cairo_status_t status;
|
||||
|
||||
|
@ -2539,6 +2623,9 @@ _cairo_pattern_get_extents (const cairo_pattern_t *pattern,
|
|||
if (pattern->extend != CAIRO_EXTEND_NONE)
|
||||
goto UNBOUNDED;
|
||||
|
||||
if (linear->p1.x == linear->p2.x && linear->p1.y == linear->p2.y)
|
||||
goto EMPTY;
|
||||
|
||||
if (pattern->matrix.xy != 0. || pattern->matrix.yx != 0.)
|
||||
goto UNBOUNDED;
|
||||
|
||||
|
@ -2562,14 +2649,21 @@ _cairo_pattern_get_extents (const cairo_pattern_t *pattern,
|
|||
ASSERT_NOT_REACHED;
|
||||
}
|
||||
|
||||
imatrix = pattern->matrix;
|
||||
status = cairo_matrix_invert (&imatrix);
|
||||
/* cairo_pattern_set_matrix ensures the matrix is invertible */
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
if (_cairo_matrix_is_translation (&pattern->matrix)) {
|
||||
x1 -= pattern->matrix.x0; x2 -= pattern->matrix.x0;
|
||||
y1 -= pattern->matrix.y0; y2 -= pattern->matrix.y0;
|
||||
} else {
|
||||
cairo_matrix_t imatrix;
|
||||
|
||||
_cairo_matrix_transform_bounding_box (&imatrix,
|
||||
&x1, &y1, &x2, &y2,
|
||||
NULL);
|
||||
imatrix = pattern->matrix;
|
||||
status = cairo_matrix_invert (&imatrix);
|
||||
/* cairo_pattern_set_matrix ensures the matrix is invertible */
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
_cairo_matrix_transform_bounding_box (&imatrix,
|
||||
&x1, &y1, &x2, &y2,
|
||||
NULL);
|
||||
}
|
||||
|
||||
x1 = floor (x1);
|
||||
if (x1 < CAIRO_RECT_INT_MIN)
|
||||
|
@ -2607,7 +2701,6 @@ _cairo_solid_pattern_hash (unsigned long hash,
|
|||
{
|
||||
const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
|
||||
|
||||
hash = _cairo_hash_bytes (hash, &solid->content, sizeof (solid->content));
|
||||
hash = _cairo_hash_bytes (hash, &solid->color, sizeof (solid->color));
|
||||
|
||||
return hash;
|
||||
|
@ -2635,23 +2728,20 @@ _cairo_gradient_color_stops_hash (unsigned long hash,
|
|||
return hash;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
unsigned long
|
||||
_cairo_linear_pattern_hash (unsigned long hash,
|
||||
const cairo_pattern_t *pattern)
|
||||
const cairo_linear_pattern_t *linear)
|
||||
{
|
||||
const cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern;
|
||||
|
||||
hash = _cairo_hash_bytes (hash, &linear->p1, sizeof (linear->p1));
|
||||
hash = _cairo_hash_bytes (hash, &linear->p2, sizeof (linear->p2));
|
||||
|
||||
return _cairo_gradient_color_stops_hash (hash, &linear->base);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
_cairo_radial_pattern_hash (unsigned long hash, const cairo_pattern_t *pattern)
|
||||
unsigned long
|
||||
_cairo_radial_pattern_hash (unsigned long hash,
|
||||
const cairo_radial_pattern_t *radial)
|
||||
{
|
||||
const cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern;
|
||||
|
||||
hash = _cairo_hash_bytes (hash, &radial->c1, sizeof (radial->c1));
|
||||
hash = _cairo_hash_bytes (hash, &radial->r1, sizeof (radial->r1));
|
||||
hash = _cairo_hash_bytes (hash, &radial->c2, sizeof (radial->c2));
|
||||
|
@ -2696,9 +2786,9 @@ _cairo_pattern_hash (const cairo_pattern_t *pattern)
|
|||
case CAIRO_PATTERN_TYPE_SOLID:
|
||||
return _cairo_solid_pattern_hash (hash, pattern);
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
return _cairo_linear_pattern_hash (hash, pattern);
|
||||
return _cairo_linear_pattern_hash (hash, (cairo_linear_pattern_t *) pattern);
|
||||
case CAIRO_PATTERN_TYPE_RADIAL:
|
||||
return _cairo_radial_pattern_hash (hash, pattern);
|
||||
return _cairo_radial_pattern_hash (hash, (cairo_radial_pattern_t *) pattern);
|
||||
case CAIRO_PATTERN_TYPE_SURFACE:
|
||||
return _cairo_surface_pattern_hash (hash, pattern);
|
||||
default:
|
||||
|
@ -2750,9 +2840,6 @@ _cairo_solid_pattern_equal (const cairo_pattern_t *A,
|
|||
const cairo_solid_pattern_t *a = (cairo_solid_pattern_t *) A;
|
||||
const cairo_solid_pattern_t *b = (cairo_solid_pattern_t *) B;
|
||||
|
||||
if (a->content != b->content)
|
||||
return FALSE;
|
||||
|
||||
return _cairo_color_equal (&a->color, &b->color);
|
||||
}
|
||||
|
||||
|
@ -2768,20 +2855,17 @@ _cairo_gradient_color_stops_equal (const cairo_gradient_pattern_t *a,
|
|||
for (n = 0; n < a->n_stops; n++) {
|
||||
if (a->stops[n].offset != b->stops[n].offset)
|
||||
return FALSE;
|
||||
if (! _cairo_color_equal (&a->stops[n].color, &b->stops[n].color))
|
||||
if (! _cairo_color_stop_equal (&a->stops[n].color, &b->stops[n].color))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_linear_pattern_equal (const cairo_pattern_t *A,
|
||||
const cairo_pattern_t *B)
|
||||
cairo_bool_t
|
||||
_cairo_linear_pattern_equal (const cairo_linear_pattern_t *a,
|
||||
const cairo_linear_pattern_t *b)
|
||||
{
|
||||
const cairo_linear_pattern_t *a = (cairo_linear_pattern_t *) A;
|
||||
const cairo_linear_pattern_t *b = (cairo_linear_pattern_t *) B;
|
||||
|
||||
if (a->p1.x != b->p1.x)
|
||||
return FALSE;
|
||||
|
||||
|
@ -2797,13 +2881,10 @@ _cairo_linear_pattern_equal (const cairo_pattern_t *A,
|
|||
return _cairo_gradient_color_stops_equal (&a->base, &b->base);
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_radial_pattern_equal (const cairo_pattern_t *A,
|
||||
const cairo_pattern_t *B)
|
||||
cairo_bool_t
|
||||
_cairo_radial_pattern_equal (const cairo_radial_pattern_t *a,
|
||||
const cairo_radial_pattern_t *b)
|
||||
{
|
||||
const cairo_radial_pattern_t *a = (cairo_radial_pattern_t *) A;
|
||||
const cairo_radial_pattern_t *b = (cairo_radial_pattern_t *) B;
|
||||
|
||||
if (a->c1.x != b->c1.x)
|
||||
return FALSE;
|
||||
|
||||
|
@ -2865,9 +2946,11 @@ _cairo_pattern_equal (const cairo_pattern_t *a, const cairo_pattern_t *b)
|
|||
case CAIRO_PATTERN_TYPE_SOLID:
|
||||
return _cairo_solid_pattern_equal (a, b);
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
return _cairo_linear_pattern_equal (a, b);
|
||||
return _cairo_linear_pattern_equal ((cairo_linear_pattern_t *) a,
|
||||
(cairo_linear_pattern_t *) b);
|
||||
case CAIRO_PATTERN_TYPE_RADIAL:
|
||||
return _cairo_radial_pattern_equal (a, b);
|
||||
return _cairo_radial_pattern_equal ((cairo_radial_pattern_t *) a,
|
||||
(cairo_radial_pattern_t *) b);
|
||||
case CAIRO_PATTERN_TYPE_SURFACE:
|
||||
return _cairo_surface_pattern_equal (a, b);
|
||||
default:
|
||||
|
@ -3131,6 +3214,12 @@ cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
|
|||
void
|
||||
_cairo_pattern_reset_static_data (void)
|
||||
{
|
||||
_freed_patterns_reset ();
|
||||
#if HAS_FREED_POOL
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH (freed_pattern_pool); i++)
|
||||
_freed_pool_reset (&freed_pattern_pool[i]);
|
||||
#endif
|
||||
|
||||
_cairo_pattern_reset_solid_surface_cache ();
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -82,6 +82,7 @@ typedef struct _cairo_pdf_operators {
|
|||
double cur_y;
|
||||
int hex_width;
|
||||
int num_glyphs;
|
||||
double glyph_buf_x_pos;
|
||||
cairo_pdf_glyph_t glyphs[PDF_GLYPH_BUFFER_SIZE];
|
||||
|
||||
/* PDF line style */
|
||||
|
@ -132,16 +133,16 @@ _cairo_pdf_operators_clip (cairo_pdf_operators_t *pdf_operators,
|
|||
cairo_fill_rule_t fill_rule);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_stroke_style_t *style,
|
||||
double scale);
|
||||
_cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
|
||||
const cairo_stroke_style_t *style,
|
||||
double scale);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_pdf_operators_stroke (cairo_pdf_operators_t *pdf_operators,
|
||||
_cairo_pdf_operators_stroke (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *style,
|
||||
cairo_matrix_t *ctm,
|
||||
cairo_matrix_t *ctm_inverse);
|
||||
const cairo_stroke_style_t *style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators,
|
||||
|
@ -149,12 +150,12 @@ _cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators,
|
|||
cairo_fill_rule_t fill_rule);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t *pdf_operators,
|
||||
_cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
cairo_stroke_style_t *style,
|
||||
cairo_matrix_t *ctm,
|
||||
cairo_matrix_t *ctm_inverse);
|
||||
cairo_fill_rule_t fill_rule,
|
||||
const cairo_stroke_style_t *style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators,
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*
|
||||
* 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
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
|
@ -43,6 +43,7 @@
|
|||
|
||||
#if CAIRO_HAS_PDF_OPERATORS
|
||||
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-pdf-operators-private.h"
|
||||
#include "cairo-path-fixed-private.h"
|
||||
#include "cairo-output-stream-private.h"
|
||||
|
@ -499,14 +500,14 @@ _cairo_pdf_operators_clip (cairo_pdf_operators_t *pdf_operators,
|
|||
}
|
||||
|
||||
switch (fill_rule) {
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
case CAIRO_FILL_RULE_WINDING:
|
||||
pdf_operator = "W";
|
||||
break;
|
||||
case CAIRO_FILL_RULE_EVEN_ODD:
|
||||
pdf_operator = "W*";
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
|
@ -549,9 +550,9 @@ _cairo_pdf_line_join (cairo_line_join_t join)
|
|||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_stroke_style_t *style,
|
||||
double scale)
|
||||
_cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
|
||||
const cairo_stroke_style_t *style,
|
||||
double scale)
|
||||
{
|
||||
double *dash = style->dash;
|
||||
int num_dashes = style->num_dashes;
|
||||
|
@ -706,12 +707,12 @@ _cairo_matrix_factor_out_scale (cairo_matrix_t *m, double *scale)
|
|||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_pdf_operators_emit_stroke (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *style,
|
||||
cairo_matrix_t *ctm,
|
||||
cairo_matrix_t *ctm_inverse,
|
||||
const char *pdf_operator)
|
||||
_cairo_pdf_operators_emit_stroke (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_path_fixed_t *path,
|
||||
const cairo_stroke_style_t *style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse,
|
||||
const char *pdf_operator)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_matrix_t m, path_transform;
|
||||
|
@ -797,11 +798,11 @@ _cairo_pdf_operators_emit_stroke (cairo_pdf_operators_t *pdf_operators,
|
|||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_pdf_operators_stroke (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *style,
|
||||
cairo_matrix_t *ctm,
|
||||
cairo_matrix_t *ctm_inverse)
|
||||
_cairo_pdf_operators_stroke (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_path_fixed_t *path,
|
||||
const cairo_stroke_style_t *style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse)
|
||||
{
|
||||
return _cairo_pdf_operators_emit_stroke (pdf_operators,
|
||||
path,
|
||||
|
@ -833,14 +834,14 @@ _cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators,
|
|||
return status;
|
||||
|
||||
switch (fill_rule) {
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
case CAIRO_FILL_RULE_WINDING:
|
||||
pdf_operator = "f";
|
||||
break;
|
||||
case CAIRO_FILL_RULE_EVEN_ODD:
|
||||
pdf_operator = "f*";
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
|
@ -851,24 +852,24 @@ _cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators,
|
|||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t *pdf_operators,
|
||||
_cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
cairo_stroke_style_t *style,
|
||||
cairo_matrix_t *ctm,
|
||||
cairo_matrix_t *ctm_inverse)
|
||||
cairo_fill_rule_t fill_rule,
|
||||
const cairo_stroke_style_t *style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse)
|
||||
{
|
||||
const char *operator;
|
||||
|
||||
switch (fill_rule) {
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
case CAIRO_FILL_RULE_WINDING:
|
||||
operator = "B";
|
||||
break;
|
||||
case CAIRO_FILL_RULE_EVEN_ODD:
|
||||
operator = "B*";
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
}
|
||||
|
||||
return _cairo_pdf_operators_emit_stroke (pdf_operators,
|
||||
|
@ -989,6 +990,7 @@ _cairo_pdf_operators_flush_glyphs (cairo_pdf_operators_t *pdf_operators)
|
|||
}
|
||||
|
||||
pdf_operators->num_glyphs = 0;
|
||||
pdf_operators->glyph_buf_x_pos = pdf_operators->cur_x;
|
||||
status2 = _cairo_output_stream_destroy (word_wrap_stream);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = status2;
|
||||
|
@ -1011,6 +1013,7 @@ _cairo_pdf_operators_add_glyph (cairo_pdf_operators_t *pdf_operators
|
|||
pdf_operators->glyphs[pdf_operators->num_glyphs].x_position = x_position;
|
||||
pdf_operators->glyphs[pdf_operators->num_glyphs].glyph_index = glyph->subset_glyph_index;
|
||||
pdf_operators->glyphs[pdf_operators->num_glyphs].x_advance = x;
|
||||
pdf_operators->glyph_buf_x_pos += x;
|
||||
pdf_operators->num_glyphs++;
|
||||
if (pdf_operators->num_glyphs == PDF_GLYPH_BUFFER_SIZE)
|
||||
return _cairo_pdf_operators_flush_glyphs (pdf_operators);
|
||||
|
@ -1035,6 +1038,7 @@ _cairo_pdf_operators_set_text_matrix (cairo_pdf_operators_t *pdf_operators,
|
|||
pdf_operators->text_matrix = *matrix;
|
||||
pdf_operators->cur_x = 0;
|
||||
pdf_operators->cur_y = 0;
|
||||
pdf_operators->glyph_buf_x_pos = 0;
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
"%f %f %f %f %f %f Tm\n",
|
||||
pdf_operators->text_matrix.xx,
|
||||
|
@ -1090,6 +1094,7 @@ _cairo_pdf_operators_set_text_position (cairo_pdf_operators_t *pdf_operators,
|
|||
translate.y0);
|
||||
pdf_operators->cur_x = 0;
|
||||
pdf_operators->cur_y = 0;
|
||||
pdf_operators->glyph_buf_x_pos = 0;
|
||||
|
||||
pdf_operators->cairo_to_pdftext = pdf_operators->text_matrix;
|
||||
status = cairo_matrix_invert (&pdf_operators->cairo_to_pdftext);
|
||||
|
@ -1139,6 +1144,7 @@ _cairo_pdf_operators_begin_text (cairo_pdf_operators_t *pdf_operators)
|
|||
|
||||
pdf_operators->in_text_object = TRUE;
|
||||
pdf_operators->num_glyphs = 0;
|
||||
pdf_operators->glyph_buf_x_pos = 0;
|
||||
|
||||
return _cairo_output_stream_get_status (pdf_operators->stream);
|
||||
}
|
||||
|
@ -1243,7 +1249,7 @@ _cairo_pdf_operators_emit_glyph (cairo_pdf_operators_t *pdf_operator
|
|||
* PDF consumers that do not handle very large position
|
||||
* adjustments in TJ.
|
||||
*/
|
||||
if (fabs(x - pdf_operators->cur_x) > 10 ||
|
||||
if (fabs(x - pdf_operators->glyph_buf_x_pos) > 10 ||
|
||||
fabs(y - pdf_operators->cur_y) > GLYPH_POSITION_TOLERANCE)
|
||||
{
|
||||
status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
|
||||
|
@ -1380,8 +1386,7 @@ _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators,
|
|||
status = cairo_matrix_invert (&pdf_operators->font_matrix_inverse);
|
||||
if (status == CAIRO_STATUS_INVALID_MATRIX)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
pdf_operators->is_new_text_object = FALSE;
|
||||
if (pdf_operators->in_text_object == FALSE) {
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче