summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CODING_STYLE212
-rw-r--r--ChangeLog749
-rw-r--r--Makefile.am2
-rw-r--r--NEWS102
-rw-r--r--ROADMAP6
-rw-r--r--TODO186
-rw-r--r--configure.in2
-rw-r--r--doc/public/.cvsignore3
-rw-r--r--doc/public/Makefile.am3
-rw-r--r--doc/public/cairo-sections.txt113
-rw-r--r--doc/public/tmpl/cairo-atsui.sgml9
-rw-r--r--doc/public/tmpl/cairo-font.sgml8
-rw-r--r--doc/public/tmpl/cairo-matrix.sgml28
-rw-r--r--doc/public/tmpl/cairo-pattern.sgml15
-rw-r--r--doc/public/tmpl/cairo-pdf.sgml32
-rw-r--r--doc/public/tmpl/cairo-ps.sgml30
-rw-r--r--doc/public/tmpl/cairo-surface.sgml70
-rw-r--r--doc/public/tmpl/cairo-win32.sgml64
-rw-r--r--doc/public/tmpl/cairo-xcb-xrender.sgml32
-rw-r--r--doc/public/tmpl/cairo-xcb.sgml27
-rw-r--r--doc/public/tmpl/cairo-xlib-xrender.sgml32
-rw-r--r--doc/public/tmpl/cairo-xlib.sgml14
-rw-r--r--doc/public/tmpl/cairo.sgml108
-rw-r--r--gtk-doc.make26
-rw-r--r--src/cairo-array.c6
-rw-r--r--src/cairo-atsui-font.c7
-rw-r--r--src/cairo-cache.c34
-rw-r--r--src/cairo-font.c45
-rw-r--r--src/cairo-ft-font.c20
-rw-r--r--src/cairo-glitz-surface.c57
-rw-r--r--src/cairo-gstate-private.h59
-rw-r--r--src/cairo-gstate.c680
-rw-r--r--src/cairo-hash.c34
-rw-r--r--src/cairo-image-surface.c14
-rw-r--r--src/cairo-matrix.c44
-rw-r--r--src/cairo-path-data-private.h11
-rw-r--r--src/cairo-path-data.c111
-rw-r--r--src/cairo-pattern.c273
-rw-r--r--src/cairo-pdf-surface.c140
-rw-r--r--src/cairo-png.c10
-rw-r--r--src/cairo-private.h5
-rw-r--r--src/cairo-ps-surface.c2
-rw-r--r--src/cairo-quartz-surface.c2
-rw-r--r--src/cairo-spline.c16
-rw-r--r--src/cairo-surface.c360
-rw-r--r--src/cairo-traps.c2
-rw-r--r--src/cairo-wideint.c6
-rw-r--r--src/cairo-win32-font.c42
-rw-r--r--src/cairo-win32-surface.c37
-rw-r--r--src/cairo-xcb-surface.c41
-rw-r--r--src/cairo-xcb.h2
-rw-r--r--src/cairo-xlib-surface.c433
-rw-r--r--src/cairo.c778
-rw-r--r--src/cairo.h43
-rw-r--r--src/cairoint.h178
-rw-r--r--test/.cvsignore3
-rw-r--r--test/Makefile.am23
-rw-r--r--test/cairo-test.c3
-rw-r--r--test/clip-twice-ref.pngbin751 -> 1191 bytes
-rw-r--r--test/clip-twice.c6
-rw-r--r--test/pdf-clip.c134
-rw-r--r--test/self-copy.c3
-rw-r--r--test/self-intersecting-ref.pngbin0 -> 242 bytes
-rw-r--r--test/self-intersecting.c89
64 files changed, 3955 insertions, 1671 deletions
diff --git a/CODING_STYLE b/CODING_STYLE
new file mode 100644
index 000000000..04fc53c44
--- /dev/null
+++ b/CODING_STYLE
@@ -0,0 +1,212 @@
+Cairo coding style.
+
+This document is intended to be a short description of the preferred
+coding style for the cairo source code. Good style requires good
+taste, which means this can't all be reduced to automated rules, and
+there are exceptions.
+
+We want the code to be easy to understand and maintain, and consistent
+style plays an important part in that, even if some of the specific
+details seem trivial. If nothing else, this document gives a place to
+put consistent answers for issues that would otherwise be arbitrary.
+
+Most of the guidelines here are demonstrated by examples, (which means
+this document is quicker to read than it might appear given its
+length). Most of the examples are positive examples that you should
+imitate. The few negative examples are clearly marked with a comment
+of /* Yuck! */. Please don't submit code to cairo that looks like any
+of these.
+
+Indentation
+-----------
+Each new level is indented 4 more spaces than the previous level:
+
+ if (condition)
+ do_something ();
+
+Spaces or tabs (or a combination) can be used in indentation, but tabs
+must always be interpreted as 8 spaces. Code using single tabs for all
+indentation (expecting people to interpret tabs as 4 spaces) will not
+be accepted in cairo.
+
+The rationale here is that tabs are used in the code for lining things
+up other than indentation, (see the Whitespace section below), and
+changing the interpretation of tab from 8 characters will break this.
+
+Braces
+------
+Most of the code in cairo uses bracing in the style of K&R:
+
+ if (condition) {
+ do_this ();
+ do_that ();
+ } else {
+ do_the_other ();
+ }
+
+but some of the code uses an alternate style:
+
+ if (condition)
+ {
+ do_this ();
+ do_that ();
+ }
+ else
+ {
+ do_the_other ();
+ }
+
+and that seems just fine. We won't lay down any strict rule on this
+point, (though there should be some local). If you came here hoping to
+find some guidance, then use the first form above.
+
+If all of the substatements of an if statement are single statements,
+the optional braces should not usually appear:
+
+ if (condition)
+ do_this ();
+ else
+ do_that ();
+
+But the braces are mandatory when mixing single statement and compound
+statements in the various clauses. For example, do not do this:
+
+ if (condition) {
+ do_this ();
+ do_that ();
+ } else /* Yuck! */
+ do_the_other ();
+
+And of course, there are exceptions for when the code just looks
+better with the braces:
+
+ if (condition) {
+ /* Note that we have to be careful here. */
+ do_something_dangerous (with_care);
+ }
+
+ if (condition &&
+ other_condition &&
+ yet_another)
+ {
+ do_something ();
+ }
+
+And note that this last example also shows a situation in which the
+opening brace really needs to be on its own line. The following looks awful:
+
+ if (condition &&
+ other_condition &&
+ yet_another) { /* Yuck! */
+ do_something ();
+ }
+
+As we said above, legible code that is easy to understand and maintain
+is the goal, not adherence to strict rules.
+
+Whitespace
+----------
+Separate logically distinct chunks with a single newline. This
+obviously applies between functions, but also applies within a
+function or block and can even be used to good effect within a
+structure definition:
+
+ struct _cairo_gstate {
+ cairo_operator_t operator;
+
+ double tolerance;
+
+ /* stroke style */
+ double line_width;
+ cairo_line_cap_t line_cap;
+ cairo_line_join_t line_join;
+ double miter_limit;
+
+ cairo_fill_rule_t fill_rule;
+
+ double *dash;
+ int num_dashes;
+ double dash_offset;
+
+ ...
+ }
+
+Use a single space before a left parenthesis, except where the
+standard will not allow it, (eg. when defining a parameterized macro).
+
+Don't eliminate whitespace just because things would still fit on one
+line. This breaks the expected visual structure of the code making it
+much harder to read and understand:
+
+ if (condition) foo (); else bar (); /* Yuck! */
+
+As a special case of the bracing and whitespace guidelines, function
+definitions should always take the following form:
+
+ void
+ my_function (argument)
+ {
+ do_my_things ();
+ }
+
+And function prototypes should similarly have the return type (and
+associated specifiers and qualifiers) on a line above the function, so
+that the function name is flush left.
+
+Break up long lines (> ~80 characters) and use whitespace to align
+things nicely. For example the arguments in a long list to a function
+call should all be aligned with each other:
+
+ align_function_arguments (argument_the_first,
+ argument_the_second,
+ argument_the_third);
+
+And as a special rule, in a function prototype, (as well as in the
+definition), whitespace should be inserted between the parameter types
+and names so that the names are aligned:
+
+ void
+ align_parameter_names_in_prototypes (const char *char_star_arg,
+ int int_arg,
+ double *double_star_arg,
+ double double_arg);
+
+Note that parameters with a * prefix are aligned one character to the
+left so that the actual names are aligned.
+
+Managing nested blocks
+----------------------
+Long blocks that are deeply nested make the code very hard to
+read. Fortunately such blocks often indicate logically distinct chunks
+of functionality that are begging to be split into their own
+functions. Please listen to the blocks when they beg.
+
+In other cases, gratuitous nesting comes about because the primary
+functionality gets buried in a nested block rather than living at the
+primary level where it belongs. Consider the following:
+
+ foo = malloc (sizeof (foo_t));
+ if (foo) { /* Yuck! */
+ ...
+ /* lots of code to initialize foo */
+ ...
+ return SUCCESS;
+ }
+ return FAILURE;
+
+This kind of gratuitous nesting can be avoided by following a pattern
+of handling exceptional cases early and returning:
+
+ foo = malloc (sizeof (foo_t));
+ if (foo == NULL)
+ return FAILURE;
+
+ ...
+ /* lots of code to initialize foo */
+ ...
+ return SUCCESS;
+
+The return statement is often the best thing to use in a pattern like
+this. If it's not available due to additional nesting above which
+require some cleanup after the current block, then consider splitting
+the current block into a new function before using goto.
diff --git a/ChangeLog b/ChangeLog
index 55cb2b9e9..90daddbfb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,752 @@
+2005-06-20 Carl Worth <cworth@cworth.org>
+
+ * Makefile.am: Force distcheck to enable gtk-doc.
+
+2005-06-20 Carl Worth <cworth@cworth.org>
+
+ * NEWS: Added notes for snapshot 0.5.1
+
+ * configure.in: Increment CAIRO_VERSION to 0.5.1
+
+2005-06-20 Owen Taylor <otaylor@redhat.com>
+
+ Workaround for https://bugs.freedesktop.org/show_bug.cgi?id=3566
+
+ * src/cairo-xlib-surface.c: Detect servers with a bug in
+ repeating surfaces by checking vendor string and version.
+
+ * src/cairo-xlib-surface.c: For such surfaces either fall back to
+ an implementation with the core protocol or fall back to the image
+ backend.
+
+ * src/cairo-xlib-surface.c: Save clip rects when setting a
+ clip region on a surface so that we set the right clip for the
+ surface's GC if we create it later.
+
+2005-06-20 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-matrix.c: (_cairo_matrix_is_integer_translation):
+ Make out parameters optional. Style cleanup.
+
+2005-06-20 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h:
+ * src/cairo-pattern.c: (_cairo_pattern_is_opaque_solid): Abstract
+ CAIRO_ALPHA_IS_OPAQUE out for general internal use.
+
+ * src/cairo.c: (cairo_paint_with_alpha): Optimize to defer to
+ cairo_paint if the alpha value is actually opaque.
+
+2005-06-20 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.h:
+ * src/cairo-private.h:
+ * src/cairo.c: (_cairo_error), (cairo_create): Rip out
+ cairo_set_error_notfiy function as it is clear that it is not the
+ right approach.
+
+ * test/.cvsignore:
+ * test/Makefile.am:
+ * test/error-notify.c: Remove error-notify test.
+
+2005-06-17 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-xcb-surface.c (_get_image_surface): Remove references
+ to repeat and matrix fields that no longer exist.
+
+2005-06-17 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-xcb-surface.c (_get_image_surface)
+ * src/cairo-xlib-surface.c (_get_image_surface): Fix
+ width/height typo.
+
+2005-06-17 Kristian Høgsberg <krh@redhat.com>
+
+ * src/cairo-glitz-surface.c: (_cairo_glitz_surface_get_image):
+ * src/cairo-pattern.c: (cairo_pattern_create_for_surface):
+ * src/cairo-pdf-surface.c: (_cairo_pdf_surface_composite_pdf):
+ * src/cairo-surface.c: (_cairo_surface_init):
+ * src/cairo-xlib-surface.c: (_get_image_surface):
+ * src/cairoint.h: Remove matrix, filter and repeat from the
+ cairo_surface_t struct.
+
+2005-06-17 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.c: (cairo_reference), (cairo_destroy): cairo_reference
+ and cairo_destroy shouldn't behave differently when cr->status
+ indicates an error. Fix this bug that just slipped back in.
+
+ * src/cairo.c: (cairo_restore): Remove useless conditional return
+ at the end of a void function.
+
+ * src/cairo.c: (cairo_get_source), (cairo_get_font_face),
+ (cairo_text_extents), (cairo_show_text), (cairo_text_path):
+ Fix so that after calling _cairo_error the most that any cairo
+ entry function ever does is return a previously computed value.
+
+2005-06-17 Kristian Høgsberg <krh@redhat.com>
+
+ * TODO: Remove the path clipping entry from the list.
+
+2005-06-16 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-private.h: Reorder fields of cairo_private_t to match
+ initialization order.
+
+ * src/cairo.c: (_cairo_error): Call error_notify callback if set.
+ (cairo_create): Initialize error_notify callback to NULL.
+ (cairo_set_error_notify): New function to allow the user to set
+ an error notify callback.
+
+ * src/cairo.h: New cairo_set_error_notify prototye.
+
+ * test/.cvsignore:
+ * test/Makefile.am:
+ * test/error-notify.c: (toggle_status), (do_test), (main): New
+ test for cairo_set_error_notify.
+
+2005-06-15 Carl Worth <cworth@cworth.org>
+
+ * TODO: Add CAIRO_STATUS_DESTROYED to TODO list.
+
+ * ROADMAP: Note progress on consistent error handling.
+
+ * src/cairo-surface.c: Fix typo in documentation comment for
+ _cairo_surface_get_current_clip_serial.
+
+2005-06-15 Owen Taylor <otaylor@redhat.com>
+
+ * doc/public/Makefile.am (MKTMPL_OPTIONS): Remove --only-section-tmpl;
+ it doesn't really work currently :-(.
+
+2005-06-15 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-gstate.c (_cairo_gstate_clip_and_composite_trapezoids):
+ Use a clip region when rendering a non-solid pattern through
+ a rectangular path ... trapezoid rasterization is just too slow
+ to use that path when we aren't forced to do so.
+
+2005-06-15 Carl Worth <cworth@cworth.org>
+
+ * test/cairo-test.c: Track removal of cairo_status_string.
+ (cairo_test_for_target): And add missing parenthesis.
+
+2005-06-15 Carl Worth <cworth@cworth.org>
+
+ * TODO: Add cairo_finish to TODO list. Note that
+ cairo_satus_string has now been removed.
+
+2005-06-15 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.h:
+ * src/cairo.c: Remove cairo_status_string function which can now
+ be replaced by:
+
+ cairo_status_to_string (cairo_status (cr));
+
+ This allows consistent handling of status values for things like
+ cairo_pattern_status where there is now
+ cairo_pattern_status_string function.
+
+2005-06-13 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.c: (_cairo_error): Add _cairo_error so we have a
+ single function which all errors can pass through. This allows the
+ user to set a breakpoint on error and will allow us to augment
+ error handling later as necessary.
+
+ * src/cairo.c: (cairo_create), (cairo_reference),
+ (cairo_destroy), (cairo_save), (cairo_restore),
+ (cairo_set_operator), (cairo_set_source_rgb),
+ (cairo_set_source_rgba), (cairo_set_source_surface),
+ (cairo_set_source), (cairo_get_source), (cairo_set_tolerance),
+ (cairo_set_fill_rule), (cairo_set_line_width),
+ (cairo_set_line_cap), (cairo_set_line_join), (cairo_set_dash),
+ (cairo_set_miter_limit), (cairo_translate), (cairo_scale),
+ (cairo_rotate), (cairo_transform), (cairo_set_matrix),
+ (cairo_identity_matrix), (cairo_user_to_device),
+ (cairo_user_to_device_distance), (cairo_device_to_user),
+ (cairo_device_to_user_distance), (cairo_new_path), (cairo_move_to),
+ (cairo_line_to), (cairo_curve_to), (cairo_arc),
+ (cairo_arc_negative), (cairo_rel_move_to), (cairo_rel_line_to),
+ (cairo_rel_curve_to), (cairo_rectangle), (cairo_close_path),
+ (cairo_paint), (cairo_paint_with_alpha), (cairo_mask),
+ (cairo_mask_surface), (cairo_stroke_preserve),
+ (cairo_fill_preserve), (cairo_copy_page), (cairo_show_page),
+ (cairo_in_stroke), (cairo_in_fill), (cairo_stroke_extents),
+ (cairo_fill_extents), (cairo_clip_preserve), (cairo_reset_clip),
+ (cairo_select_font_face), (cairo_get_font_face),
+ (cairo_font_extents), (cairo_set_font_face), (cairo_set_font_size),
+ (cairo_set_font_matrix), (cairo_get_font_matrix),
+ (cairo_text_extents), (cairo_glyph_extents), (cairo_show_text),
+ (cairo_show_glyphs), (cairo_text_path), (cairo_glyph_path),
+ (cairo_get_operator), (cairo_get_tolerance),
+ (cairo_get_current_point), (cairo_get_fill_rule),
+ (cairo_get_line_width), (cairo_get_line_cap),
+ (cairo_get_line_join), (cairo_get_miter_limit), (cairo_get_matrix),
+ (cairo_get_target), (cairo_copy_path), (cairo_copy_path_flat),
+ (cairo_append_path), (cairo_status): Make all assignements to
+ cr->status go through the new _cairo_error function. Remove
+ CAIRO_CHECK_SANITY macro.
+
+2005-06-15 Carl Worth <cworth@cworth.org>
+
+ * doc/public/cairo-sections.txt: Remove cairo-atsui section since
+ cairo-atsui.h is currently empty.
+ Add cairo_path_data_type_t and cairo_path_data_t.
+
+ * test/.cvsignore: Add pdf-clip and pdf-clip.pdf.
+
+2005-06-14 Kristian Høgsberg <krh@redhat.com>
+
+ * src/cairo-gstate-private.h:
+ * src/cairo-gstate.c: (_cairo_gstate_init),
+ (_cairo_gstate_init_copy), (_cairo_gstate_fini),
+ (_cairo_gstate_set_clip), (_composite_trap_region),
+ (_cairo_gstate_fill), (_cairo_gstate_reset_clip),
+ (_cairo_gstate_intersect_clip_path), (_cairo_clip_path_reference),
+ (_cairo_clip_path_destroy), (_cairo_gstate_intersect_clip_region),
+ (_cairo_gstate_intersect_clip_mask), (_cairo_gstate_clip):
+ * src/cairo-pdf-surface.c:
+ (_cairo_pdf_surface_create_for_document),
+ (_cairo_pdf_path_move_to), (_cairo_pdf_path_line_to),
+ (_cairo_pdf_path_close_path), (_cairo_pdf_surface_fill_path),
+ (_cairo_pdf_surface_intersect_clip_path),
+ (_cairo_pdf_document_add_page):
+ * src/cairo-surface.c: (_cairo_surface_get_clip_mode),
+ (_cairo_surface_fill_path), (_cairo_surface_reset_clip),
+ (_cairo_surface_set_clip_path_recursive),
+ (_cairo_surface_set_clip_path):
+ * src/cairoint.h: Implement path clipping and refactor
+ _cairo_gstate_clip() out in three different functions
+ corresponding to the three different clipping modes.
+
+ * src/cairo-glitz-surface.c:
+ * src/cairo-ps-surface.c:
+ * src/cairo-win32-surface.c:
+ * src/cairo-xcb-surface.c:
+ * src/cairo-xlib-surface.c:
+ * src/cairo-image-surface.c:
+ * src/cairo-quartz-surface.c: Add NULL pointers for
+ intersect_clip_path.
+
+ * test/Makefile.am:
+ * test/pdf-clip.c: New test case to exercise PDF clipping code.
+
+2005-06-14 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-glitz-surface.c: (_cairo_glitz_surface_create_similar),
+ (_cairo_glitz_surface_clone_similar),
+ (_cairo_glitz_pattern_acquire_surface),
+ (_cairo_glitz_surface_composite_trapezoids):
+ * src/cairo-image-surface.c: (_cairo_image_surface_create_similar):
+ * src/cairo-pdf-surface.c: (_cairo_pdf_surface_create_similar):
+ * src/cairo-ps-surface.c: (_cairo_ps_surface_create_similar):
+ * src/cairo-quartz-surface.c:
+ (_cairo_quartz_surface_create_similar):
+ * src/cairo-surface.c: (_cairo_surface_create_similar_scratch),
+ (_cairo_surface_create_similar_solid):
+ * src/cairo-win32-surface.c: (_cairo_win32_surface_create_similar),
+ (_cairo_win32_surface_get_subimage):
+ * src/cairo-xcb-surface.c: (_cairo_xcb_surface_create_similar),
+ (_cairo_xcb_surface_clone_similar):
+ * src/cairo-xlib-surface.c: (_cairo_xlib_surface_create_similar),
+ (_cairo_xlib_surface_clone_similar):
+ * src/cairoint.h: Remove Boolean 'drawable' parameter from the
+ create_similar surface backend function since nothing anywhere is
+ actually using this parameter.
+
+2005-06-14 T Rowley <tim.rowley@gmail.com>
+
+ * src/cairo-win32-font.c: Correct extents for text with a general
+ tranform.
+
+2005-06-14 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.h: Remove comment suggesting ambiguity of whether
+ cairo_get_target references the surface, (we decided as part of
+ the API shakeup that cairo functions returning pointers to
+ internal objects do not automatically take a reference).
+
+2005-06-13 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h:
+ * src/cairo-pattern.c: (_cairo_pattern_create_in_error): Add new
+ _cairo_pattern_create_in_error.
+
+ * src/cairo.c: (cairo_get_source): Propagate error values from
+ cr->status to pattern->status.
+
+2005-06-13 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.c (_cairo_set_source_solid),
+ (cairo_set_source_surface), (cairo_mask_surface): No longer need
+ to check for NULL after creating a pattern.
+
+ * src/cairo.c (cairo_set_source), (cairo_mask): Propagate status
+ errors from pattern->status to cr->status.
+
+ Originally 2005-05-08 Owen Taylor <otaylor@redhat.com>:
+
+ * src/cairo-pattern.c src/cairoint.h: If allocation of pattern
+ objects fails, return special static nil pattern objects.
+
+ * src/cairo-pattern.c: If adding a color stop fails to allocate
+ memory, set pattern->status. (And fix a memory leak.) Make public
+ functions return when pattern->status is set, (and no longer
+ return a cairo_status_t).
+
+ * src/cairo-pattern.c src/cairo.h doc/public/cairo-sections.txt:
+ Add cairo_pattern_status()
+
+ * src/cairo-gstate.c: Check the status of gstate->source and
+ of mask patterns passed in.
+
+2005-06-13 Carl Worth <cworth@cworth.org>
+
+ Originally 2005-05-08 Owen Taylor <otaylor@redhat.com>:
+
+ * src/cairo.c (cairo_create): If cairo_create() fails, return
+ a special static object, cairo_nil.
+
+ * src/cairo.c (cairo_reference): Don't return early if
+ cr->status is set. cr->status should not affect reference
+ counting.
+
+ * src/cairo.c: (cairo_reference), (cairo_destroy): Ignore any
+ magic object with a reference count of -1.
+
+2005-06-13 Carl Worth <cworth@cworth.org>
+
+ Originally 2005-06-02 Carl Worth <cworth@cworth.org>:
+
+ * src/cairo.h: Add a status field to cairo_path_t.
+
+ * src/cairo.c:
+ (cairo_copy_path), (cairo_copy_path_flat): Add documentation for
+ the new approach for handling errors in these functions---always
+ returning a valid pointer with at least a status.
+ (cairo_append_path): Propagate path status errors to the
+ context. Add note to documentation on initializing path->status.
+
+ * src/cairo-path-data-private.h: Add missing cairo_private
+ qualifier to a couple functions.
+
+ * src/cairo-path-data.c: (_cairo_path_data_create_real): Track new
+ status field in cairo_path_t.
+ (cairo_path_destroy): Don't destroy cairo_path_nil. Add
+ documentation.
+ (_cairo_path_data_create):
+ (_cairo_path_data_create_flat):
+ (_cairo_path_data_append_to_context): Add documentation.
+ (_cairo_path_data_create_in_error): New function to create a
+ placeholder cairo_path_t just to propagate a cairo_status_t error.
+
+2005-06-11 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h:
+ * src/cairo-gstate.c: (_cairo_gstate_init,
+ _cairo_gstate_init_copy, _cairo_gstate_fini): Make these functions
+ static, which allows slightly less awkward error handling within
+ them.
+
+2005-06-10 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h: Provide font-backend-specific macros for
+ FONT_FAMILY_DEFAULT. Change CAIRO_FT_FONT_FAMILY_DEFAULT from
+ "serif" to "" to allow the actual default to come from the
+ system/user configuration.
+
+2005-06-10 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.h: Pull the enum out from inside cairo_path_data_t and
+ give it a name of cairo_path_data_type_t. This allows C++ programs
+ to see the enum values. It also allows variables to be declared of
+ this type for manually constructing a cairo_path_t.
+
+2005-06-10 Carl Worth <cworth@cworth.org>
+
+ * ROADMAP: Add 'consistent error handling' to 1.0 roadmap. (This
+ isn't new, we just forgot to list it here before).
+
+ * TODO: Big cleanup to remove finished items. Also, split the file
+ up to separate TODO items that affect the API from items that do
+ not.
+
+2005-06-10 Carl Worth <cworth@cworth.org>
+
+ Originally: 2005-06-09 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-pdf-surface.c: (_cairo_pdf_surface_show_page):
+ * src/cairo-xcb-surface.c:
+ (_cairo_xcb_surface_acquire_source_image),
+ (_cairo_xcb_surface_acquire_dest_image):
+ * src/cairo-xlib-surface.c:
+ (_cairo_xlib_surface_acquire_source_image),
+ (_cairo_xlib_surface_acquire_dest_image): Rework occurrences
+ of 'if (status == CAIRO_STATUS_SUCCESS)' to use 'if (status)'
+ instead where trivial.
+
+2005-06-10 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h:
+ * src/cairo-font.c:
+ * src/cairo-ft-font.c:
+ * src/cairo-glitz-surface.c:
+ * src/cairo-gstate.c:
+ * src/cairo-image-surface.c:
+ * src/cairo-pattern.c:
+ * src/cairo-pdf-surface.c:
+ * src/cairo-png.c:
+ * src/cairo-surface.c:
+ * src/cairo-win32-font.c:
+ * src/cairo-win32-surface.c:
+ * src/cairo-xcb-surface.c:
+ * src/cairo-xlib-surface.c: Remove STATUS_OK macro which was not
+ being used universally.
+
+2005-06-09 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.h: Remove trailing comma from enum values which gcc
+ 4.0 does not want to see (Luis Villa). Closes bug #3502.
+
+2005-06-09 Owen Taylor <otaylor@redhat.com>
+
+ * test/Makefile.am (INCLUDES): Add
+ -I$(top_builddir)/src for cairo-features.h (Tomasz Cholewo)
+
+2005-06-07 Keith Packard <keithp@keithp.com>
+
+ * src/cairo-pdf-surface.c: (_cairo_pdf_surface_show_glyphs):
+ Font matrix was output incorrectly; the implicit mirror-in-y
+ transformation was not computed correctly, missing a negation
+ of the 'xy' component.
+
+2005-06-02 Kristian Høgsberg <krh@redhat.com>
+
+ * src/cairo-gstate.c (_cairo_gstate_clip): When clipping, update
+ the clip surface to a new surface the size of the intersection of
+ the old clip surface and the extents of the new clip path.
+
+2005-06-03 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-font.c: (cairo_font_face_reference),
+ (cairo_font_face_destroy), (_cairo_simple_font_face_destroy),
+ (_cairo_unscaled_font_reference), (_cairo_unscaled_font_destroy),
+ (cairo_scaled_font_reference), (cairo_scaled_font_destroy):
+ * src/cairo-ft-font.c: (_ft_font_cache_destroy_cache),
+ (_cairo_ft_unscaled_font_destroy), (_ft_font_face_destroy):
+ * src/cairo-glitz-surface.c: (_cairo_glitz_area_destroy):
+ * src/cairo-path-data.c: (cairo_path_destroy):
+ * src/cairo-pdf-surface.c: (cairo_pdf_font_destroy),
+ (cairo_pdf_ft_font_destroy):
+ * src/cairo-win32-font.c: (_cairo_win32_scaled_font_destroy):
+ Allow NULL as a valid value for several objects. That is, calling
+ reference or destroy on these objects will simply do nothing,
+ successfully.
+
+ * src/cairo-atsui-font.c: (_cairo_atsui_font_destroy_font): Remove
+ extra whitespace.
+
+2005-06-03 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h:
+ * src/cairo-cache.c: (_cairo_cache_init), (_cairo_cache_destroy):
+ Remove unused cache->refcount and _cairo_cache_reference().
+
+ * src/cairo-cache.c: (_cairo_cache_destroy): Remove gratuitous
+ nesting as recommended in CODING_STYLE.
+
+2005-06-03 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h:
+ * src/cairo-array.c: (_cairo_user_data_array_fini):
+ * src/cairo-font.c: (cairo_font_face_destroy):
+ * src/cairo-surface.c: (cairo_surface_destroy): Fix name of
+ _cairo_user_data_array_destroy to be _cairo_user_data_array_fini.
+
+2005-06-03 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-glitz-surface.c:
+ (_cairo_glitz_glyph_cache_create_entry),
+ (_cairo_glitz_glyph_cache_destroy_entry),
+ (_cairo_glitz_glyph_cache_destroy_cache),
+ (_cairo_glitz_surface_show_glyphs): Rename functions to match the
+ naming scheme used by cairo-cache.c and all other users of
+ it. Though it's quite likely that glitz had this right and now
+ everything could be changed to match it instead. I'll save that
+ for some day when we're cleaning up the cache code.
+
+2005-06-03 Carl Worth <cworth@cworth.org>
+
+ * CODING_STYLE: Fix spelling errors.
+
+2005-06-03 Carl Worth <cworth@cworth.org>
+
+ * CODING_STYLE: Fix Freudian unwrapped line in paragraph
+ describing why long lines should be wrapped.
+
+2005-06-03 Carl Worth <cworth@cworth.org>
+
+ * CODING_STYLE: Add CODING_STYLE document to standardize on some
+ style issues.
+
+ * src/cairo-atsui-font.c:
+ * src/cairo-cache.c:
+ * src/cairo-ft-font.c:
+ * src/cairo-glitz-surface.c:
+ * src/cairo-gstate.c:
+ * src/cairo-matrix.c:
+ * src/cairo-pattern.c:
+ * src/cairo-pdf-surface.c:
+ * src/cairo-spline.c:
+ * src/cairo-wideint.c:
+ * src/cairo-win32-font.c:
+ * src/cairo-xlib-surface.c: Standardize brace handling around all
+ else clauses according to new CODING_STYLE guidelines.
+
+2005-06-03 Kristian Høgsberg <krh@redhat.com>
+
+ Patch from Tomasz Cholewo <cholewo@ieee-cis.org>:
+
+ * src/cairo-pdf-surface.c: (cairo_pdf_ft_font_write_head_table),
+ (cairo_pdf_ft_font_generate): Store the index of the checksum
+ instead of a pointer to the location.
+
+2005-06-03 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h:
+ * src/cairo-gstate.c:
+ * src/cairo.c: (_cairo_set_source_solid), (cairo_set_source_rgb),
+ (cairo_set_source_rgba): Move internal convenience up from
+ _cairo_gstate_set_source_solid to _cairo_set_source_solid so that
+ all set_source functions flow through cairo_set_source.
+
+2005-06-01 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-gstate.c: (_cairo_gstate_init): Remove obsolete
+ _cairo_gstate_set_target_surface, folding its contents into
+ _cairo_gstate_init, most of which disappears due to constant
+ folding. Ensure that gstate->next is initialized even if
+ _cairo_pattern_create_solid fails.
+
+ * src/cairo-xcb-surface.c: Remove unused
+ _cairo_xcb_surface_set_clip_region.
+
+2005-06-01 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h:
+ * src/cairo-font.c:
+ * src/cairo-ft-font.c:
+ * src/cairo-glitz-surface.c:
+ * src/cairo-gstate.c:
+ * src/cairo-image-surface.c:
+ * src/cairo-pattern.c:
+ * src/cairo-pdf-surface.c:
+ * src/cairo-png.c:
+ * src/cairo-surface.c:
+ * src/cairo-win32-font.c:
+ * src/cairo-win32-surface.c:
+ * src/cairo-xcb-surface.c:
+ * src/cairo-xlib-surface.c: Rename CAIRO_OK to STATUS_OK. No
+ intended changes in functionality.
+
+2005-06-01 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-gstate-private.h:
+ * src/cairo-gstate.c: Rename gstate->surface to gstate->target. No
+ intended changes in functionality.
+
+2005-06-01 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-gstate-private.h:
+ * src/cairo-gstate.c: (_cairo_gstate_init): Remove unused fields
+ from cairo_gstate_t, (font_family, font_slant,
+ font_weight). Reorder fields to match between declaration and
+ initialization and to put the most problematic fields (surface and
+ source) at the end. No intended changes in functionality.
+
+2005-06-01 Carl Worth <cworth@cworth.org>
+
+ * test/Makefile.am (XFAIL_TESTS): Add self-intersecting to the
+ list of expected failures.
+
+2005-06-01 Carl Worth <cworth@cworth.org>
+
+ * test/.cvsignore:
+ * test/Makefile.am:
+ * test/self-intersecting-ref.png:
+ * test/self-intersecting.c: (draw), (main): Add self-intersecting
+ test which demonstrates the long-standing bug with stroking
+ self-intersecting paths.
+
+2005-06-01 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-gstate.c (_cairo_gstate_get_clip_extents): Fix bug in
+ converting box to rectangle that left clip_rect.height
+ uninitialized, (leading to unpredictable, intermittent test
+ failures).
+
+2005-05-31 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.h:
+ * src/cairo.c: (cairo_status_to_string), (cairo_status_string):
+ Add new function cairo_status_to_string an reimplement
+ cairo_status_string in terms of the new function.
+
+2005-05-27 Olivier Andrieu <oliv__a@users.sourceforge.net>
+
+ * src/cairo-path-data.c (_cpdc_curve_to_flatten),
+ (_cpdp_curve_to_flatten) : Fix memory leak
+
+2005-05-26 Keith Packard <keithp@keithp.com>
+
+ reviewed by: krh, otaylor, cworth
+
+ Replace nesting-only surface clipping with gstate contained
+ serial-number tracked clipping sets that are loaded into the surface
+ on demand just before each rendering operation. This permits
+ multiple cairo_t contexts to reference a surface without
+ regard to ordering of operations among the contexts.
+
+ Also in this patch is a change to the xlib surface that
+ creates two separate Pictures, one for source and one for
+ destination operands which separates the source clipping
+ from destination clipping. Cairo now specifies that sources
+ are never clipped by any clipping applied to them as destinations.
+
+ * src/cairoint.h:
+ * src/cairo-gstate-private.h:
+ Move cairo_clip_t (renamed from cairo_clip_rec_t) from cairoint.h
+ to cairo-gstate-private.h. Eliminate stack of clip state
+ from surfaces. Add new surface clipping API.
+
+ * src/cairo-gstate.c: (_cairo_gstate_init),
+ (_cairo_gstate_init_copy), (_cairo_gstate_fini),
+ (_cairo_gstate_has_surface_clip), (_cairo_gstate_set_clip),
+ (_cairo_gstate_get_clip_extents),
+ (_cairo_gstate_set_target_surface), (_cairo_gstate_paint),
+ (_cairo_gstate_combine_clip_surface),
+ (_cairo_gstate_intersect_clip), (_get_mask_extents),
+ (_cairo_gstate_mask), (_cairo_gstate_stroke),
+ (_clip_and_compute_extents_arbitrary), (_composite_trap_region),
+ (_cairo_gstate_fill), (_cairo_gstate_reset_clip),
+ (_cairo_gstate_clip), (_cairo_gstate_show_glyphs):
+ Manage clip objects entirely within the gstate, loading
+ the whole thing into the surface just before drawing.
+
+ * src/cairo-pattern.c:
+ (_cairo_pattern_acquire_surface_for_gradient),
+ (_cairo_pattern_acquire_surface_for_solid),
+ (_cairo_pattern_acquire_surface_for_surface),
+ (_cairo_pattern_acquire_surface), (_cairo_pattern_release_surface):
+ Source surfaces need not have clipping modified as the
+ surface interface now specifies that source surfaces are always
+ unclipped.
+
+ * src/cairo-surface.c: (_cairo_surface_init),
+ (cairo_surface_finish), (_cairo_surface_clone_similar),
+ (_cairo_surface_get_current_clip_serial),
+ (_cairo_surface_allocate_clip_serial), (_cairo_surface_reset_clip),
+ (_cairo_surface_can_clip_region), (_cairo_surface_set_clip_region),
+ (_cairo_surface_can_clip_path), (_cairo_surface_clip_path),
+ (_cairo_surface_get_extents):
+ Eliminate nested clipping contexts, leaving clip management
+ entirely to the gstate. Create new clip API for the gstate
+ which uses per-surface serial numbers to match gstate clipping
+ against current surface clipping values.
+
+ Surfaces no longer track clipping regions at all, so the
+ old _cairo_surface_get_clip_extents has been replaced with
+ _cairo_surface_get_extents. For PDF/PS surfaces, this
+ function is expected to return a rectangle covering the
+ entire fixed point coordinate space to leave rendering
+ unclipped by the surface.
+
+ * src/cairo-xcb-surface.c:
+ Region clipping capability is now signalled by a non-NULL
+ function pointer in set_clip_region.
+
+ * src/cairo-xlib-surface.c: (_cairo_xlib_surface_finish),
+ (_cairo_xlib_surface_ensure_src_picture),
+ (_cairo_xlib_surface_ensure_dst_picture),
+ (_cairo_xlib_surface_set_matrix), (_cairo_xlib_surface_set_filter),
+ (_cairo_xlib_surface_set_repeat),
+ (_cairo_xlib_surface_set_attributes),
+ (_cairo_xlib_surface_composite),
+ (_cairo_xlib_surface_fill_rectangles),
+ (_cairo_xlib_surface_composite_trapezoids),
+ (_cairo_xlib_surface_set_clip_region),
+ (_cairo_xlib_surface_create_internal),
+ (_cairo_xlib_surface_show_glyphs32),
+ (_cairo_xlib_surface_show_glyphs16),
+ (_cairo_xlib_surface_show_glyphs8),
+ (_cairo_xlib_surface_show_glyphs):
+ Each surface now contains two Pictures, one for source
+ and one for destination operands so that source operands
+ are never clipped by destination clipping.
+
+ * src/cairo.h:
+ * src/cairo.c: (cairo_status_string):
+ CAIRO_STATUS_BAD_NESTING removed
+
+ * test/Makefile.am:
+ * test/self-copy.c: (main):
+ self-copy now passes (Xlib only, until libpixman changes land)
+
+2005-05-26 Olivier Andrieu <oliv__a@users.sourceforge.net>
+
+ * src/cairo.c: trivial doc fixes.
+
+2005-05-24 Carl Worth <cworth@cworth.org>
+
+ * gtk-doc.make: Re-synch with latest from gtk-doc CVS tree.
+
+ * doc/public/Makefile.am (MKTMPL_OPTIONS): Add --only-section-tmpl
+ option so that changes to inline documentation does not lead to
+ churn in the .sgml template files.
+
+ * doc/public/tmpl/cairo-font.sgml:
+ * doc/public/tmpl/cairo-ft.sgml:
+ * doc/public/tmpl/cairo-glitz.sgml:
+ * doc/public/tmpl/cairo-matrix.sgml:
+ * doc/public/tmpl/cairo-pattern.sgml:
+ * doc/public/tmpl/cairo-pdf.sgml:
+ * doc/public/tmpl/cairo-png.sgml:
+ * doc/public/tmpl/cairo-ps.sgml:
+ * doc/public/tmpl/cairo-quartz.sgml:
+ * doc/public/tmpl/cairo-surface.sgml:
+ * doc/public/tmpl/cairo-xcb.sgml:
+ * doc/public/tmpl/cairo-xlib.sgml:
+ * doc/public/tmpl/cairo.sgml: Commit new templates now that
+ gtk-doc has ripped all the inline portions out.
+
+ * doc/public/tmpl/cairo-win32.sgml:
+ * doc/public/tmpl/cairo-xcb-xrender.sgml:
+ * doc/public/tmpl/cairo-xlib-xrender.sgml: New template files
+ added for new sections.
+
+ * doc/public/cairo-sections.txt: Update to match current API.
+
+ * src/cairo-xcb.h: Make parameter names match those in the .c file
+ and its documentation.
+
+2005-05-22 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.c (cairo_create): Protect less-than and greater-than
+ symbols in documentation string.
+
+ * TODO: Not that a patch has been submitted for consistent error
+ handling.
+
+ * src/cairo.c: Fix documentation string for cairo_create so that
+ it might actualyl appear in the manual.
+
+2005-05-18 Carl Worth <cworth@cworth.org>
+
+ * configure.in: Add -head to CAIRO_VERSION after tagging with
+ SNAPSHOT_0_5_0.
+
2005-05-17 Carl Worth <cworth@cworth.org>
* PORTING_GUIDE: Added porting guide to help with transition to
diff --git a/Makefile.am b/Makefile.am
index 60ae80514..31aea9118 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,6 +9,8 @@ EXTRA_DIST = \
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = cairo.pc
+DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc
+
# Some custom targets to make it easier to release things.
# Use either:
# make release-check
diff --git a/NEWS b/NEWS
index 447583c45..f69bbd066 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,105 @@
+Snapshot 0.5.1 (2005-06-20 Carl Worth <cworth@cworth.org>)
+==========================================================
+API changes
+-----------
+* Removed cairo_status_string(cairo_t*) and add
+ cairo_status_to_string(cairo_status_t) in its place. Code using
+ cairo_status_string can be ported forward as follows:
+
+ cairo_status (cr);
+ ->
+ cairo_status_to_string (cairo_status (cr));
+
+* Removed the BAD_NESTING restriction which means that two different
+ cairo_t objects can now interleave drawing to the same
+ cairo_surface_t without causing an error.
+
+* The following functions which previously had a return type of
+ cairo_status_t now have a return type of void:
+
+ cairo_pattern_add_color_stop_rgba
+ cairo_pattern_set_matrix
+ cairo_pattern_get_matrix
+ cairo_pattern_set_extend
+ cairo_pattern_set_filter
+
+ See discussion of cairo_pattern_status below for more details.
+
+API additions
+-------------
+* Improved error handling:
+
+ cairo_status_t
+ cairo_pattern_status (cairo_pattern_t *pattern);
+
+ This snapshot expands the status-based error handling scheme from
+ cairo_t to cairo_path_t and cairo_pattern_t. It also expands the
+ scheme so that object-creating functions, (cairo_create,
+ cairo_pattern_create_*, cairo_copy_path_*), are now guaranteed to
+ not return NULL. Instead, in the case of out-of-memory these
+ functions will return a static object with
+ status==CAIRO_STATUS_NO_MEMORY. The status can be checked with the
+ functions cairo_status and cairo_pattern_status, or by direct
+ inspection of the new status field in cairo_path_t.
+
+ Please note that some objects, including cairo_surface_t and all of
+ the font-related objects have not been converted to this
+ error-handling scheme.
+
+* In addition to the above changes, a new private function has been added:
+
+ _cairo_error
+
+ This function can be used to set a breakpoint in a debugger to make
+ it easier to find programming error in cairo-using code. (Currently,
+ _cairo_error is called when any error is detected within a cairo_t
+ context, but is not called for non-cairo_t errors such as for
+ cairo_path_t and cairo_pattern_t).
+
+* Fixed cairo_path_data_t so that its enum is visible to C++ code, (as
+ cairo_path_data_type_t).
+
+Performance improvements
+------------------------
+* Made a minor performance improvement for clipping, (restrict clip
+ surface to the new intersected bounds).
+
+* Optimize rendering of a solid source pattern with a pixel-aligned
+ rectangular path to use backend clipping rather than rasterization
+ and backend compositing.
+
+* Optimize cairo_paint_with_alpha to defer to cairo_paint when alpha
+ is 1.0.
+
+Bug fixes
+---------
+* Fixed memory leak in cairo_copy_path.
+
+* A build fix for non-srcdir builds.
+
+PDF backend fixes
+-----------------
+* New support for path-based clipping.
+
+* Fix for text rotated to angles other than multiples of π/2.
+
+Win32 backend fixes
+-------------------
+* Fix for text extents.
+
+Xlib backend
+------------
+* Implemented a complex workaround for X server bug[*] related to
+ Render-based compositing with untransformed, repeating source
+ pictures. The workaround uses core Xlib when possible for
+ performance, (ie. with CAIRO_OPERATOR_SOURCE or CAIRO_OPERATOR_OVER
+ with an opaque source surface), and falls back to the pixman
+ image-based compositing otherwise.
+
+ [*] https://bugs.freedesktop.org/show_bug.cgi?id=3566
+
+* Various bug fixes, particularly in the fallback paths.
+
Snapshot 0.5.0 (2005-05-17 Carl Worth <cworth@cworth.org>)
==========================================================
This is a pretty big, and fairly significant snapshot. It represents
diff --git a/ROADMAP b/ROADMAP
index 4a47c4964..3dfdd3335 100644
--- a/ROADMAP
+++ b/ROADMAP
@@ -69,6 +69,12 @@ API Issues (more detail in TODO file)
of them.
Status: not started, there is a rough plan in TODO
+ A9. consistent error handling for all objects
+ Difficulty: Easy to implement to get the API right. Hard to test.
+ Status: Done for cairo_t, cairo_path_t, and cairo_pattern_t.
+ Still need to do cairo_font_face_t,
+ cairo_scaled_font_t, and cairo_surface_t.
+
Performance work
----------------
✓P1. Make pixel-aligned rectangle compositing fast
diff --git a/TODO b/TODO
index ea44263ed..41f896055 100644
--- a/TODO
+++ b/TODO
@@ -1,56 +1,84 @@
-API Shakeup planning
---------------------
+Changes that are expected to impact the public API
+==================================================
+
Patch submitted to mailing list?
/ Documentation included in patch?
|/ Review of patch completed?
||/ Test case included?
|||/ Committed.
||||/
-New functionality (more-or-less)
---------------------------------
+Backwards compatible (API additions only)
+-----------------------------------------
cairo_begin_group, cairo_end_group, cairo_get_group
- cairo_<device>_surface_mark_dirty
- Consistent error handling for all objects
-
-Somewhat backwards-compatible changes
------------------------------------
-PDRTC user data (was Re: [cairo] Patch improving fallbacks)
-PDRTC setters and getters
-PDRTC cairo_output_stream_t and cairo_surface_finish()
-PDRTC cairo_current_path -> cairo_copy_path_data
+ cairo_surface_mark_dirty (see below for details)
+ Add support for non-antialiased rendering. API ?
+ Add CAIRO_FILL_RULE_INVERSE_WINDING and CAIRO_FILL_RULE_INVERSE_EVEN_ODD
+ Add cairo_text_glyphs (see below for details)
+ Add support for programmatic patterns, (ie. arbitrary gradients)
+ Add cairo_arc_to.
+ Add support for custom caps (see below for details)
+ Add support for getting at image data from image surface
+ Add CAIRO_STATUS_DESTROYED
+ Add cairo_finish
+
+Backwards incompatible (API deletions or changes)
+-------------------------------------------------
PDR C cairo_surface_finish, cairo_surface_flush
-PDRTC Abbreviation hunt: cairo_init_clip and cairo_concat_matrix
-PDRTC Renaming the terms of the rendering equation
-PDRTC default matrix
-PDRTC cairo_paint
-PDRTC Making set_source consistent
-PDRTC cairo_stroke_path -> cairo_stroke_to_path
-PDRTC cairo_current_matrix
-PDRTC cairo_mask
-PDRTC cairo_fill_preserve, cairo_stroke_preserve, cairo_clip_preserve
PDR C A hidden offset for the xlib backend
+P Consistent error handling for all objects
+ Split cairo_format_t (see below for details)
+P---C Remove cairo_status_string in favor of cairo_status_to_string
-Backwards incompatible
-----------------------
-PDRTC Simplifying the operator set
-PDRTC cairo_create and eliminating cairo_set_target_surface
-PDRTC Eliminating cairo_copy
-PDRTC Eliminating cairo_surface_set_repeat/matrix/filter
-PDRTC Eliminating cairo_show_surface
+Details on some of the above changes
+------------------------------------
+* cairo_surface_mark_dirty
-* Add support for non-antialiased rendering. API ?
+ One question is what the function should accept. A single
+ device-space rectangle seems like a consistent approach. That would
+ allow us to avoid needing backend-specific functions with
+ backend-specific region datatypes, (cf. clipping support)
-* Clean up the cache code a bit, (there is at least one redundant
- level of cacheing, and there are some minor style issues).
+ In order to get the intended efficiency benefits, we'll need to make
+ two changes:
-* Add CAIRO_FILL_RULE_INVERSE_WINDING and CAIRO_FILL_RULE_INVERSE_EVEN_ODD
+ 1) In the fallback code, never fetch any data from the clean
+ region.
-* Fix clipping to work for all operators. The equation we have come up
- with is:
+ 2) Mark clean any region drawn with device-pixel aligned
+ rectangles, (cairo_paint with no clip is the most iportant
+ one here).
- ((src Op dest) In clip) Add (dest Out clip)
+* cairo_text_glyphs:
+
+ It would function as a sort of bridge between the toy and the
+ real text APIs:
+
+ > void
+ > cairo_text_glyphs (cairo_t *cr, const unsigned char *utf8,
+ > cairo_glyph_t *glyphs, int *num_glyphs);
+ >
+ > with num_glyphs as an input-output parameter. The behavior of this
+ > function would be such that calling:
+ >
+ > cairo_text_glyphs (cr, string, glyphs, &num_glyphs);
+ > cairo_show_glyphs (cr, glyphs, num_glyphs);
+ >
+ > would be equivalent too:
+ >
+ > cairo_show_text (cr, string);
+ >
+ > as long as the original size of glyphs/num_glyphs was large
+ > enough.
+
+* support for custom caps:
+
+ It would be nice if the user had a mechanism to reliably draw custom
+ caps. One approach here would be to provide the coordinates of the
+ butt cap faces so that the user can append seamless caps to the
+ current path. We may also need to provide the coordinates of the
+ faces of every dash as well.
-* Split cairo_format_t into two things:
+* split cairo_format_t into two things:
- An enumeration that determines the "capabilities" of a surface -
A vs. ARGB. vs. RGB
@@ -82,92 +110,32 @@ PDRTC Eliminating cairo_show_surface
people are going to screw up and pass CAIRO_FORMAT_RGB into that, and if it
"just worked" that would save people trouble....)
-* Clean up the API in preparation for freezing and release.
+Changes that do not affect the public API
+=========================================
+* Clean up the cache code a bit, (there is at least one redundant
+ level of cacheing, and there are some minor style issues).
-* Make a more interesting PS backend, (other than the current
-"giant-image for every page" approach).
+* Fix clipping to work for all operators. The equation we have come up
+ with is:
+
+ ((src Op dest) In clip) Add (dest Out clip)
-* Figure out what to do with DPI for image/png backends.
+* Make a more interesting PS backend, (other than the current
+ "giant-image for every page" approach).
* Change stroke code to go through one giant polygon. This will fix
-problems with stroking self-intersecting paths.
-
-* Re-work the backend clipping interface to use geometry rather than
-images.
+ problems with stroking self-intersecting paths.
* Fix the intersection problem, (see reference to Hobby's paper
-mentioned in cairo_traps.c).
-
-* Add a new cairo_text_glyphs function (a sort of bridge between the
-toy and the real text API):
-
- > void
- > cairo_text_glyphs (cairo_t *cr, const unsigned char *utf8,
- > cairo_glyph_t *glyphs, int *num_glyphs);
- >
- > with num_glyphs as an input-output parameter. The behavior of this
- > function would be such that calling:
- >
- > cairo_text_glyphs (cr, string, glyphs, &num_glyphs);
- > cairo_show_glyphs (cr, glyphs, num_glyphs);
- >
- > would be equivalent too:
- >
- > cairo_show_text (cr, string);
- >
- > as long as the original size of glyphs/num_glyphs was large
- > enough.
+ mentioned in cairo_traps.c).
* Implement dashing for cairo_curve_to.
-* Implement support for programmatic patterns, (ie. figure out how to
-do gradients the Right Way).
-
-* Implement cairo_arc_to.
-
* Stroking closed, degenerate paths should still draw caps. Round
caps are easy; square should probably draw an axis-aligned square.
-* It would be nice if the user had a mechanism to reliably draw custom
- caps. One approach here would be to provide the coordinates of the
- butt cap faces so that the user can append seamless caps to the
- current path. We may also need to provide the coordinates of the
- faces of every dash as well.
-
* Should add geometry pruning as appropriate.
-* We need a way to get at the image data after something
- like cairo_surface_create_similar with the image backend.
-
-* Three suggestions from Owen that will help GTK+ performance:
-
- - The ability have an additional rectangle-list clip in the
- Xlib surface. Frequently during an expose event, GTK+ is
- drawing L shaped areas
-
- XXXXXX
- X.....
- X.....
-
- And passing the real clip to the server is going to save
- a lot of pixel operations that will be thrown away.
-
- - The ability to pass in a width/height to cairo_xlib_surface_create()
- to avoid a round-trip. (Round-trips are bad to the point where
- querying the the server is something you don't want to do in
- production software)
-
- - More of a future thing, the ability to hint to to cairo that
- the contents of the Xlib surface passed to
- cairo_xlib_surface_create() are a solid fill ... this is
- very much the normal case for GTK+ usage and allows for
- big optimization in the no-RENDER case.
- (see http://mail.gnome.org/archives/gtk-devel-list/2003-March/msg00045.html
-
* Verification, profiling, optimization.
centi_unfinished.svg may provide a good test case.
-
-* Implement copy-on-write regions in pixman as a more complete
- solution than the BAD_NESTING stuff to Owen's "Clip region problems"
- thread.
diff --git a/configure.in b/configure.in
index 070b0ef64..c2305de50 100644
--- a/configure.in
+++ b/configure.in
@@ -5,7 +5,7 @@ AC_INIT(src/cairo.h)
dnl ===========================================================================
# Package version number, (as distinct from shared library version)
-CAIRO_VERSION=0.5.0
+CAIRO_VERSION=0.5.1
# libtool shared library version
diff --git a/doc/public/.cvsignore b/doc/public/.cvsignore
index 35479d5e3..ff4418d10 100644
--- a/doc/public/.cvsignore
+++ b/doc/public/.cvsignore
@@ -3,6 +3,7 @@ Makefile
Makefile.in
cairo-decl-list.txt
cairo-decl.txt
+cairo-docs.sgml
cairo-undocumented.txt
cairo-unused.txt
cairo.hierarchy
@@ -13,3 +14,5 @@ cairo.signals
html
xml
+
+
diff --git a/doc/public/Makefile.am b/doc/public/Makefile.am
index f058d36aa..9e4c10365 100644
--- a/doc/public/Makefile.am
+++ b/doc/public/Makefile.am
@@ -38,6 +38,9 @@ GTKDOC_LIBS =
# Extra options to supply to gtkdoc-mkdb
MKDB_OPTIONS=--sgml-mode --output-format=xml
+# Extra options to supply to gtkdoc-mktmpl
+MKTMPL_OPTIONS=
+
# Non-autogenerated SGML files to be included in $(DOC_MAIN_SGML_FILE)
content_files = \
language-bindings.xml
diff --git a/doc/public/cairo-sections.txt b/doc/public/cairo-sections.txt
index b462436b8..4db600b2a 100644
--- a/doc/public/cairo-sections.txt
+++ b/doc/public/cairo-sections.txt
@@ -1,10 +1,4 @@
<SECTION>
-<FILE>cairo-atsui</FILE>
-<TITLE>ATSUI Fonts</TITLE>
-cairo_atsui_font_create
-</SECTION>
-
-<SECTION>
<FILE>cairo-ft</FILE>
<TITLE>FreeType Fonts</TITLE>
cairo_ft_font_face_create_for_pattern
@@ -23,7 +17,8 @@ cairo_glitz_surface_create
<FILE>cairo-pdf</FILE>
<TITLE>PDF Backend</TITLE>
cairo_pdf_surface_create
-cairo_pdf_surface_create_for_callback
+cairo_pdf_surface_create_for_stream
+cairo_pdf_surface_set_dpi
</SECTION>
<SECTION>
@@ -39,6 +34,8 @@ cairo_surface_write_to_png_stream
<FILE>cairo-ps</FILE>
<TITLE>PS Backend</TITLE>
cairo_ps_surface_create
+cairo_ps_surface_create_for_stream
+cairo_ps_surface_set_dpi
</SECTION>
<SECTION>
@@ -61,30 +58,38 @@ cairo_win32_scaled_font_get_metrics_factor
<FILE>cairo-xcb</FILE>
<TITLE>XCB Backend</TITLE>
cairo_xcb_surface_create
+cairo_xcb_surface_create_for_bitmap
+cairo_xcb_surface_set_size
+</SECTION>
+
+<SECTION>
+<FILE>cairo-xcb-xrender</FILE>
+<TITLE>XCB Backend</TITLE>
+cairo_xcb_surface_create_with_xrender_format
</SECTION>
<SECTION>
<FILE>cairo-xlib</FILE>
<TITLE>XLib Backend</TITLE>
cairo_xlib_surface_create
-cairo_xlib_surface_create_with_visual
+cairo_xlib_surface_create_for_bitmap
cairo_xlib_surface_set_size
</SECTION>
<SECTION>
+<FILE>cairo-xlib-xrender</FILE>
+<TITLE>XLib/Xrender Backend</TITLE>
+cairo_xlib_surface_create_with_xrender_format
+</SECTION>
+
+<SECTION>
<FILE>cairo-surface</FILE>
<TITLE>cairo_surface_t</TITLE>
cairo_surface_t
-cairo_surface_create_for_image
cairo_surface_create_similar
cairo_surface_reference
cairo_surface_destroy
cairo_surface_finish
-cairo_surface_set_repeat
-cairo_surface_set_matrix
-cairo_surface_get_matrix
-cairo_surface_set_filter
-cairo_surface_get_filter
cairo_surface_set_user_data
cairo_surface_get_user_data
cairo_surface_set_device_offset
@@ -99,6 +104,7 @@ cairo_pattern_create_linear
cairo_pattern_create_radial
cairo_pattern_reference
cairo_pattern_destroy
+cairo_pattern_status
cairo_pattern_add_color_stop_rgb
cairo_pattern_add_color_stop_rgba
cairo_pattern_set_matrix
@@ -108,8 +114,6 @@ cairo_pattern_set_extend
cairo_pattern_get_extend
cairo_pattern_set_filter
cairo_pattern_get_filter
-<SUBSECTION Private>
-cairo_pattern_add_color_stop
</SECTION>
<SECTION>
@@ -128,13 +132,6 @@ cairo_matrix_invert
cairo_matrix_multiply
cairo_matrix_transform_distance
cairo_matrix_transform_point
-<SUBSECTION Private>
-cairo_matrix_create
-cairo_matrix_destroy
-cairo_matrix_copy
-cairo_matrix_set_identity
-cairo_matrix_set_affine
-cairo_matrix_get_affine
</SECTION>
<SECTION>
@@ -164,7 +161,6 @@ cairo_reference
cairo_destroy
cairo_save
cairo_restore
-cairo_copy
cairo_format_t
cairo_operator_t
cairo_set_operator
@@ -172,7 +168,6 @@ cairo_set_source_rgb
cairo_set_source_rgba
cairo_set_source
cairo_set_source_surface
-cairo_set_alpha
cairo_set_tolerance
cairo_fill_rule_t
cairo_set_fill_rule
@@ -188,7 +183,6 @@ cairo_scale
cairo_rotate
cairo_transform
cairo_set_matrix
-cairo_default_matrix
cairo_identity_matrix
cairo_user_to_device
cairo_user_to_device_distance
@@ -239,7 +233,6 @@ cairo_text_extents
cairo_glyph_extents
cairo_text_path
cairo_glyph_path
-cairo_show_surface
cairo_get_operator
cairo_get_source
cairo_get_tolerance
@@ -251,16 +244,19 @@ cairo_get_line_join
cairo_get_miter_limit
cairo_get_matrix
cairo_get_target
-cairo_get_path
-cairo_get_path_flat
cairo_copy_path
cairo_copy_path_flat
cairo_append_path
+cairo_path_data_type_t
+cairo_path_data_t
cairo_path_t
cairo_path_destroy
cairo_status_t
cairo_status
cairo_status_string
+cairo_status_to_string
+cairo_error_notify_func_t
+cairo_set_error_notify
cairo_filter_t
cairo_image_surface_create
cairo_image_surface_create_for_data
@@ -273,7 +269,8 @@ cairo_write_func_t
<SUBSECTION Private>
CAIRO_BEGIN_DECLS
CAIRO_END_DECLS
-cairo_concat_matrix
+cairo_current_font_extents
+cairo_get_font_extents
cairo_current_operator
cairo_current_tolerance
cairo_current_point
@@ -284,20 +281,54 @@ cairo_current_line_join
cairo_current_miter_limit
cairo_current_matrix
cairo_current_target_surface
-cairo_current_path
-cairo_current_path_flat
-cairo_current_font_extents
-cairo_init_clip
-cairo_inverse_transform_point
-cairo_inverse_transform_distance
+cairo_get_status
+cairo_get_status_string
+cairo_concat_matrix
cairo_scale_font
cairo_select_font
-cairo_set_pattern
-cairo_set_rgb_color
cairo_transform_font
-cairo_get_font_extents
-cairo_get_status
-cairo_get_status_string
cairo_transform_point
cairo_transform_distance
+cairo_inverse_transform_point
+cairo_inverse_transform_distance
+cairo_init_clip
+cairo_surface_create_for_image
+cairo_default_matrix
+cairo_matrix_set_affine
+cairo_matrix_set_identity
+cairo_pattern_add_color_stop
+cairo_set_rgb_color
+cairo_set_pattern
+cairo_xlib_surface_create_for_pixmap_with_visual
+cairo_xlib_surface_create_for_window_with_visual
+cairo_xcb_surface_create_for_pixmap_with_visual
+cairo_xcb_surface_create_for_window_with_visual
+cairo_current_path
+cairo_current_path_flat
+cairo_get_path
+cairo_get_path_flat
+cairo_set_alpha
+cairo_show_surface
+cairo_copy
+cairo_surface_set_repeat
+cairo_surface_set_matrix
+cairo_surface_get_matrix
+cairo_surface_set_filter
+cairo_surface_get_filter
+cairo_matrix_create
+cairo_matrix_destroy
+cairo_matrix_copy
+cairo_matrix_set_identity
+cairo_matrix_set_affine
+cairo_matrix_get_affine
+cairo_set_target_surface
+cairo_set_target_glitz
+cairo_set_target_image
+cairo_set_target_pdf
+cairo_set_target_png
+cairo_set_target_ps
+cairo_set_target_quartz
+cairo_set_target_win32
+cairo_set_target_xcb
+cairo_set_target_drawable
</SECTION>
diff --git a/doc/public/tmpl/cairo-atsui.sgml b/doc/public/tmpl/cairo-atsui.sgml
index a47ee8c68..4a8b35aaf 100644
--- a/doc/public/tmpl/cairo-atsui.sgml
+++ b/doc/public/tmpl/cairo-atsui.sgml
@@ -17,12 +17,3 @@ ATSUI Fonts
<!-- ##### SECTION Stability_Level ##### -->
-<!-- ##### FUNCTION cairo_atsui_font_create ##### -->
-<para>
-
-</para>
-
-@style:
-@Returns:
-
-
diff --git a/doc/public/tmpl/cairo-font.sgml b/doc/public/tmpl/cairo-font.sgml
index 66502930e..d6c7043d2 100644
--- a/doc/public/tmpl/cairo-font.sgml
+++ b/doc/public/tmpl/cairo-font.sgml
@@ -84,8 +84,6 @@ Font Handling
</para>
@scaled_font:
-<!-- # Unused Parameters # -->
-@font:
<!-- ##### FUNCTION cairo_scaled_font_destroy ##### -->
@@ -94,8 +92,6 @@ Font Handling
</para>
@scaled_font:
-<!-- # Unused Parameters # -->
-@font:
<!-- ##### STRUCT cairo_font_extents_t ##### -->
@@ -117,8 +113,6 @@ Font Handling
@scaled_font:
@extents:
@Returns:
-<!-- # Unused Parameters # -->
-@font:
<!-- ##### STRUCT cairo_text_extents_t ##### -->
@@ -142,7 +136,5 @@ Font Handling
@glyphs:
@num_glyphs:
@extents:
-<!-- # Unused Parameters # -->
-@font:
diff --git a/doc/public/tmpl/cairo-matrix.sgml b/doc/public/tmpl/cairo-matrix.sgml
index c58abe488..d9549b4a6 100644
--- a/doc/public/tmpl/cairo-matrix.sgml
+++ b/doc/public/tmpl/cairo-matrix.sgml
@@ -65,14 +65,6 @@ cairo_matrix_t
@yy:
@x0:
@y0:
-<!-- # Unused Parameters # -->
-@Param7:
-@a:
-@b:
-@c:
-@d:
-@tx:
-@ty:
<!-- ##### FUNCTION cairo_matrix_init_identity ##### -->
@@ -120,8 +112,6 @@ cairo_matrix_t
@matrix:
@tx:
@ty:
-<!-- # Unused Parameters # -->
-@Returns:
<!-- ##### FUNCTION cairo_matrix_scale ##### -->
@@ -132,8 +122,6 @@ cairo_matrix_t
@matrix:
@sx:
@sy:
-<!-- # Unused Parameters # -->
-@Returns:
<!-- ##### FUNCTION cairo_matrix_rotate ##### -->
@@ -143,8 +131,6 @@ cairo_matrix_t
@matrix:
@radians:
-<!-- # Unused Parameters # -->
-@Returns:
<!-- ##### FUNCTION cairo_matrix_invert ##### -->
@@ -164,8 +150,6 @@ cairo_matrix_t
@result:
@a:
@b:
-<!-- # Unused Parameters # -->
-@Returns:
<!-- ##### FUNCTION cairo_matrix_transform_distance ##### -->
@@ -176,25 +160,15 @@ cairo_matrix_t
@matrix:
@dx:
@dy:
-<!-- # Unused Parameters # -->
-@Returns:
<!-- ##### FUNCTION cairo_matrix_transform_point ##### -->
<para>
+
</para>
@matrix:
@x:
@y:
-<!-- # Unused Parameters # -->
-@Returns:
-
-<!--
-Local variables:
-mode: sgml
-sgml-parent-document: ("../cairo-docs.xml" "book" "refsect2" "")
-End:
--->
diff --git a/doc/public/tmpl/cairo-pattern.sgml b/doc/public/tmpl/cairo-pattern.sgml
index 30deec9b8..dadd7870c 100644
--- a/doc/public/tmpl/cairo-pattern.sgml
+++ b/doc/public/tmpl/cairo-pattern.sgml
@@ -74,6 +74,15 @@ cairo_pattern_t
@pattern:
+<!-- ##### FUNCTION cairo_pattern_status ##### -->
+<para>
+
+</para>
+
+@pattern:
+@Returns:
+
+
<!-- ##### FUNCTION cairo_pattern_add_color_stop_rgb ##### -->
<para>
@@ -84,7 +93,6 @@ cairo_pattern_t
@red:
@green:
@blue:
-@Returns:
<!-- ##### FUNCTION cairo_pattern_add_color_stop_rgba ##### -->
@@ -98,7 +106,6 @@ cairo_pattern_t
@green:
@blue:
@alpha:
-@Returns:
<!-- ##### FUNCTION cairo_pattern_set_matrix ##### -->
@@ -108,7 +115,6 @@ cairo_pattern_t
@pattern:
@matrix:
-@Returns:
<!-- ##### FUNCTION cairo_pattern_get_matrix ##### -->
@@ -118,6 +124,7 @@ cairo_pattern_t
@pattern:
@matrix:
+<!-- # Unused Parameters # -->
@Returns:
@@ -137,7 +144,6 @@ cairo_pattern_t
@pattern:
@extend:
-@Returns:
<!-- ##### FUNCTION cairo_pattern_get_extend ##### -->
@@ -156,7 +162,6 @@ cairo_pattern_t
@pattern:
@filter:
-@Returns:
<!-- ##### FUNCTION cairo_pattern_get_filter ##### -->
diff --git a/doc/public/tmpl/cairo-pdf.sgml b/doc/public/tmpl/cairo-pdf.sgml
index 8ff0ea17e..d29ed0e26 100644
--- a/doc/public/tmpl/cairo-pdf.sgml
+++ b/doc/public/tmpl/cairo-pdf.sgml
@@ -22,31 +22,31 @@ PDF Backend
</para>
-@fp:
-@width_inches:
-@height_inches:
-@x_pixels_per_inch:
-@y_pixels_per_inch:
+@filename:
+@width_in_points:
+@height_in_points:
@Returns:
-<!-- # Unused Parameters # -->
-@write_func:
-@destroy_closure_func:
-@closure:
-@file:
-<!-- ##### FUNCTION cairo_pdf_surface_create_for_callback ##### -->
+<!-- ##### FUNCTION cairo_pdf_surface_create_for_stream ##### -->
<para>
</para>
@write_func:
-@destroy_closure_func:
@closure:
-@width_inches:
-@height_inches:
-@x_pixels_per_inch:
-@y_pixels_per_inch:
+@width_in_points:
+@height_in_points:
@Returns:
+<!-- ##### FUNCTION cairo_pdf_surface_set_dpi ##### -->
+<para>
+
+</para>
+
+@surface:
+@x_dpi:
+@y_dpi:
+
+
diff --git a/doc/public/tmpl/cairo-ps.sgml b/doc/public/tmpl/cairo-ps.sgml
index 4cb4a0268..4c5e8b37b 100644
--- a/doc/public/tmpl/cairo-ps.sgml
+++ b/doc/public/tmpl/cairo-ps.sgml
@@ -22,11 +22,31 @@ PS Backend
</para>
-@file:
-@width_inches:
-@height_inches:
-@x_pixels_per_inch:
-@y_pixels_per_inch:
+@filename:
+@width_in_points:
+@height_in_points:
@Returns:
+<!-- ##### FUNCTION cairo_ps_surface_create_for_stream ##### -->
+<para>
+
+</para>
+
+@write_func:
+@closure:
+@width_in_points:
+@height_in_points:
+@Returns:
+
+
+<!-- ##### FUNCTION cairo_ps_surface_set_dpi ##### -->
+<para>
+
+</para>
+
+@surface:
+@x_dpi:
+@y_dpi:
+
+
diff --git a/doc/public/tmpl/cairo-surface.sgml b/doc/public/tmpl/cairo-surface.sgml
index e92935a6c..fab1306f6 100644
--- a/doc/public/tmpl/cairo-surface.sgml
+++ b/doc/public/tmpl/cairo-surface.sgml
@@ -23,20 +23,6 @@ cairo_surface_t
</para>
-<!-- ##### MACRO cairo_surface_create_for_image ##### -->
-<para>
-
-</para>
-
-@Returns:
-<!-- # Unused Parameters # -->
-@data:
-@format:
-@width:
-@height:
-@stride:
-
-
<!-- ##### FUNCTION cairo_surface_create_similar ##### -->
<para>
@@ -74,60 +60,6 @@ cairo_surface_t
@Returns:
-<!-- ##### MACRO cairo_surface_set_repeat ##### -->
-<para>
-
-</para>
-
-@Returns:
-<!-- # Unused Parameters # -->
-@surface:
-@repeat:
-
-
-<!-- ##### MACRO cairo_surface_set_matrix ##### -->
-<para>
-
-</para>
-
-@Returns:
-<!-- # Unused Parameters # -->
-@surface:
-@matrix:
-
-
-<!-- ##### MACRO cairo_surface_get_matrix ##### -->
-<para>
-
-</para>
-
-@Returns:
-<!-- # Unused Parameters # -->
-@surface:
-@matrix:
-
-
-<!-- ##### MACRO cairo_surface_set_filter ##### -->
-<para>
-
-</para>
-
-@Returns:
-<!-- # Unused Parameters # -->
-@surface:
-@filter:
-
-
-<!-- ##### MACRO cairo_surface_get_filter ##### -->
-<para>
-
-</para>
-
-@Returns:
-<!-- # Unused Parameters # -->
-@surface:
-
-
<!-- ##### FUNCTION cairo_surface_set_user_data ##### -->
<para>
@@ -138,8 +70,6 @@ cairo_surface_t
@user_data:
@destroy:
@Returns:
-<!-- # Unused Parameters # -->
-@data:
<!-- ##### FUNCTION cairo_surface_get_user_data ##### -->
diff --git a/doc/public/tmpl/cairo-win32.sgml b/doc/public/tmpl/cairo-win32.sgml
new file mode 100644
index 000000000..4976ea064
--- /dev/null
+++ b/doc/public/tmpl/cairo-win32.sgml
@@ -0,0 +1,64 @@
+<!-- ##### SECTION Title ##### -->
+Microsoft Windows Backend
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### FUNCTION cairo_win32_surface_create ##### -->
+<para>
+
+</para>
+
+@hdc:
+@Returns:
+
+
+<!-- ##### FUNCTION cairo_win32_font_face_create_for_logfontw ##### -->
+<para>
+
+</para>
+
+@logfont:
+@Returns:
+
+
+<!-- ##### FUNCTION cairo_win32_scaled_font_select_font ##### -->
+<para>
+
+</para>
+
+@scaled_font:
+@hdc:
+@Returns:
+
+
+<!-- ##### FUNCTION cairo_win32_scaled_font_done_font ##### -->
+<para>
+
+</para>
+
+@scaled_font:
+
+
+<!-- ##### FUNCTION cairo_win32_scaled_font_get_metrics_factor ##### -->
+<para>
+
+</para>
+
+@scaled_font:
+@Returns:
+
+
diff --git a/doc/public/tmpl/cairo-xcb-xrender.sgml b/doc/public/tmpl/cairo-xcb-xrender.sgml
new file mode 100644
index 000000000..892967ec0
--- /dev/null
+++ b/doc/public/tmpl/cairo-xcb-xrender.sgml
@@ -0,0 +1,32 @@
+<!-- ##### SECTION Title ##### -->
+XCB Backend
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### FUNCTION cairo_xcb_surface_create_with_xrender_format ##### -->
+<para>
+
+</para>
+
+@c:
+@drawable:
+@format:
+@width:
+@height:
+@Returns:
+
+
diff --git a/doc/public/tmpl/cairo-xcb.sgml b/doc/public/tmpl/cairo-xcb.sgml
index 416d71638..a58912c75 100644
--- a/doc/public/tmpl/cairo-xcb.sgml
+++ b/doc/public/tmpl/cairo-xcb.sgml
@@ -22,10 +22,33 @@ XCB Backend
</para>
-@dpy:
+@c:
@drawable:
@visual:
-@format:
+@width:
+@height:
@Returns:
+<!-- ##### FUNCTION cairo_xcb_surface_create_for_bitmap ##### -->
+<para>
+
+</para>
+
+@c:
+@bitmap:
+@width:
+@height:
+@Returns:
+
+
+<!-- ##### FUNCTION cairo_xcb_surface_set_size ##### -->
+<para>
+
+</para>
+
+@surface:
+@width:
+@height:
+
+
diff --git a/doc/public/tmpl/cairo-xlib-xrender.sgml b/doc/public/tmpl/cairo-xlib-xrender.sgml
new file mode 100644
index 000000000..4ceab1968
--- /dev/null
+++ b/doc/public/tmpl/cairo-xlib-xrender.sgml
@@ -0,0 +1,32 @@
+<!-- ##### SECTION Title ##### -->
+XLib/Xrender Backend
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### FUNCTION cairo_xlib_surface_create_with_xrender_format ##### -->
+<para>
+
+</para>
+
+@dpy:
+@drawable:
+@format:
+@width:
+@height:
+@Returns:
+
+
diff --git a/doc/public/tmpl/cairo-xlib.sgml b/doc/public/tmpl/cairo-xlib.sgml
index 30282b226..ae8bb785c 100644
--- a/doc/public/tmpl/cairo-xlib.sgml
+++ b/doc/public/tmpl/cairo-xlib.sgml
@@ -24,21 +24,21 @@ XLib Backend
@dpy:
@drawable:
-@format:
-@Returns:
-<!-- # Unused Parameters # -->
@visual:
-@colormap:
+@width:
+@height:
+@Returns:
-<!-- ##### FUNCTION cairo_xlib_surface_create_with_visual ##### -->
+<!-- ##### FUNCTION cairo_xlib_surface_create_for_bitmap ##### -->
<para>
</para>
@dpy:
-@drawable:
-@visual:
+@bitmap:
+@width:
+@height:
@Returns:
diff --git a/doc/public/tmpl/cairo.sgml b/doc/public/tmpl/cairo.sgml
index 06a5fba6d..992ace500 100644
--- a/doc/public/tmpl/cairo.sgml
+++ b/doc/public/tmpl/cairo.sgml
@@ -74,16 +74,6 @@ Drawing contexts.
@cr:
-<!-- ##### MACRO cairo_copy ##### -->
-<para>
-
-</para>
-
-<!-- # Unused Parameters # -->
-@dest:
-@src:
-
-
<!-- ##### ENUM cairo_format_t ##### -->
<para>
@@ -153,8 +143,6 @@ Drawing contexts.
@cr:
@source:
-<!-- # Unused Parameters # -->
-@pattern:
<!-- ##### FUNCTION cairo_set_source_surface ##### -->
@@ -168,16 +156,6 @@ Drawing contexts.
@y:
-<!-- ##### MACRO cairo_set_alpha ##### -->
-<para>
-
-</para>
-
-<!-- # Unused Parameters # -->
-@cr:
-@alpha:
-
-
<!-- ##### FUNCTION cairo_set_tolerance ##### -->
<para>
@@ -316,15 +294,6 @@ Drawing contexts.
@matrix:
-<!-- ##### MACRO cairo_default_matrix ##### -->
-<para>
-
-</para>
-
-<!-- # Unused Parameters # -->
-@cr:
-
-
<!-- ##### FUNCTION cairo_identity_matrix ##### -->
<para>
@@ -718,7 +687,6 @@ Drawing contexts.
@cr:
@matrix:
-@Returns:
<!-- ##### FUNCTION cairo_show_text ##### -->
@@ -756,10 +724,6 @@ Drawing contexts.
@cr:
@extents:
-<!-- # Unused Parameters # -->
-@font:
-@Returns:
-@font_matrix:
<!-- ##### FUNCTION cairo_set_font_face ##### -->
@@ -811,18 +775,6 @@ Drawing contexts.
@num_glyphs:
-<!-- ##### MACRO cairo_show_surface ##### -->
-<para>
-
-</para>
-
-<!-- # Unused Parameters # -->
-@cr:
-@surface:
-@width:
-@height:
-
-
<!-- ##### FUNCTION cairo_get_operator ##### -->
<para>
@@ -925,33 +877,6 @@ Drawing contexts.
@Returns:
-<!-- ##### MACRO cairo_get_path ##### -->
-<para>
-
-</para>
-
-<!-- # Unused Parameters # -->
-@cr:
-@move_to:
-@line_to:
-@curve_to:
-@close_path:
-@closure:
-
-
-<!-- ##### MACRO cairo_get_path_flat ##### -->
-<para>
-
-</para>
-
-<!-- # Unused Parameters # -->
-@cr:
-@move_to:
-@line_to:
-@close_path:
-@closure:
-
-
<!-- ##### FUNCTION cairo_copy_path ##### -->
<para>
@@ -979,11 +904,22 @@ Drawing contexts.
@path:
+<!-- ##### ENUM cairo_path_data_type_t ##### -->
+<para>
+
+</para>
+
+@CAIRO_PATH_MOVE_TO:
+@CAIRO_PATH_LINE_TO:
+@CAIRO_PATH_CURVE_TO:
+@CAIRO_PATH_CLOSE_PATH:
+
<!-- ##### STRUCT cairo_path_t ##### -->
<para>
</para>
+@status:
@data:
@num_data:
@@ -1014,7 +950,7 @@ Drawing contexts.
@CAIRO_STATUS_WRITE_ERROR:
@CAIRO_STATUS_SURFACE_FINISHED:
@CAIRO_STATUS_SURFACE_TYPE_MISMATCH:
-@CAIRO_STATUS_BAD_NESTING:
+@CAIRO_STATUS_PATTERN_TYPE_MISMATCH:
<!-- ##### FUNCTION cairo_status ##### -->
<para>
@@ -1025,12 +961,19 @@ Drawing contexts.
@Returns:
-<!-- ##### FUNCTION cairo_status_string ##### -->
+<!-- ##### MACRO cairo_status_string ##### -->
<para>
</para>
-@cr:
+
+
+<!-- ##### FUNCTION cairo_status_to_string ##### -->
+<para>
+
+</para>
+
+@status:
@Returns:
@@ -1070,15 +1013,6 @@ Drawing contexts.
@Returns:
-
-<!--
-Local variables:
-mode: sgml
-sgml-parent-document: ("../cairo-docs.xml" "book" "refsect2" "")
-End:
--->
-
-
<!-- ##### FUNCTION cairo_image_surface_get_width ##### -->
<para>
diff --git a/gtk-doc.make b/gtk-doc.make
index 18c60c2d7..91cdd34d2 100644
--- a/gtk-doc.make
+++ b/gtk-doc.make
@@ -1,9 +1,3 @@
-#
-# *** NOTE *** this file is checked into CVS for convenience only.
-# DO NOT EDIT. Rather get changes into upstream gtk-doc and then
-# update this version from the gtk-doc version.
-#
-
# -*- mode: makefile -*-
####################################
@@ -31,7 +25,6 @@ EXTRA_DIST = \
$(content_files) \
$(HTML_IMAGES) \
$(DOC_MAIN_SGML_FILE) \
- $(DOC_MODULE).types \
$(DOC_MODULE)-sections.txt \
$(DOC_MODULE)-overrides.txt
@@ -55,7 +48,7 @@ all-local: html-build.stamp
scan-build.stamp: $(HFILE_GLOB) $(CFILE_GLOB)
@echo '*** Scanning header files ***'
@-chmod -R u+w $(srcdir)
- if grep -l '^..*$$' $(srcdir)/$(DOC_MODULE).types > /dev/null ; then \
+ if grep -l '^..*$$' $(srcdir)/$(DOC_MODULE).types > /dev/null 2>&1 ; then \
CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" CFLAGS="$(GTKDOC_CFLAGS)" LDFLAGS="$(GTKDOC_LIBS)" gtkdoc-scangobj $(SCANGOBJ_OPTIONS) --module=$(DOC_MODULE) --output-dir=$(srcdir) ; \
else \
cd $(srcdir) ; \
@@ -75,7 +68,7 @@ $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES): scan-build.stamp
tmpl-build.stamp: $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt
@echo '*** Rebuilding template files ***'
@-chmod -R u+w $(srcdir)
- cd $(srcdir) && gtkdoc-mktmpl --module=$(DOC_MODULE)
+ cd $(srcdir) && gtkdoc-mktmpl --module=$(DOC_MODULE) $(MKTMPL_OPTIONS)
touch tmpl-build.stamp
tmpl.stamp: tmpl-build.stamp
@@ -83,11 +76,11 @@ tmpl.stamp: tmpl-build.stamp
#### xml ####
-sgml-build.stamp: tmpl.stamp $(CFILE_GLOB) $(srcdir)/tmpl/*.sgml
+sgml-build.stamp: tmpl.stamp $(CFILE_GLOB) $(srcdir)/tmpl/*.sgml $(expand_content_files)
@echo '*** Building XML ***'
@-chmod -R u+w $(srcdir)
cd $(srcdir) && \
- gtkdoc-mkdb --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --output-format=xml $(MKDB_OPTIONS)
+ gtkdoc-mkdb --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --output-format=xml --expand-content-files="$(expand_content_files)" $(MKDB_OPTIONS)
touch sgml-build.stamp
sgml.stamp: sgml-build.stamp
@@ -146,18 +139,15 @@ dist-check-gtkdoc:
@false
endif
-# XXX: Before this was:
-# dist-hook: dist-check-gtkdoc dist-hook-local
-# which seems reasonable, but for some reason the dist-check-gtkdoc
-# was always failing on me, even though I do have gtk-doc installed
-# and it is successfully building the documentation.
-
-dist-hook: dist-hook-local
+dist-hook: dist-check-gtkdoc dist-hook-local
mkdir $(distdir)/tmpl
mkdir $(distdir)/xml
mkdir $(distdir)/html
-cp $(srcdir)/tmpl/*.sgml $(distdir)/tmpl
-cp $(srcdir)/xml/*.xml $(distdir)/xml
-cp $(srcdir)/html/* $(distdir)/html
+ if test -f $(srcdir)/$(DOC_MODULE).types; then \
+ cp $(srcdir)/$(DOC_MODULE).types $(distdir)/$(DOC_MODULE).types; \
+ fi
.PHONY : dist-hook-local
diff --git a/src/cairo-array.c b/src/cairo-array.c
index a37ea9af5..a9f148a07 100644
--- a/src/cairo-array.c
+++ b/src/cairo-array.c
@@ -147,7 +147,7 @@ typedef struct {
*
* Initializes a #cairo_user_data_array_t structure for future
* use. After initialization, the array has no keys. Call
- * _cairo_user_data_array_destroy() to free any allocated memory
+ * _cairo_user_data_array_fini() to free any allocated memory
* when done using the array.
**/
void
@@ -157,14 +157,14 @@ _cairo_user_data_array_init (cairo_user_data_array_t *array)
}
/**
- * _cairo_user_data_array_destroy:
+ * _cairo_user_data_array_fini:
* @array: a #cairo_user_data_array_t
*
* Destroys all current keys in the user data array and deallocates
* any memory allocated for the array itself.
**/
void
-_cairo_user_data_array_destroy (cairo_user_data_array_t *array)
+_cairo_user_data_array_fini (cairo_user_data_array_t *array)
{
int i, num_slots;
cairo_user_data_slot_t *slots;
diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index a279956df..5c7ddf54a 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -209,7 +209,6 @@ _cairo_atsui_font_destroy_font(void *abstract_font)
{
cairo_atsui_font_t *font = abstract_font;
-
if (font == NULL)
return;
@@ -486,14 +485,16 @@ _cairo_atsui_font_show_glyphs(void *abstract_font,
CGContextSetTextMatrix(myBitmapContext, textTransform);
if (pattern->type == CAIRO_PATTERN_SOLID &&
- _cairo_pattern_is_opaque_solid(pattern)) {
+ _cairo_pattern_is_opaque_solid(pattern))
+ {
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *)pattern;
CGContextSetRGBFillColor(myBitmapContext,
solid->color.red,
solid->color.green,
solid->color.blue, 1.0f);
- } else
+ } else {
CGContextSetRGBFillColor(myBitmapContext, 0.0f, 0.0f, 0.0f, 0.0f);
+ }
// TODO - bold and italic text
//
diff --git a/src/cairo-cache.c b/src/cairo-cache.c
index e95894960..e7547bc29 100644
--- a/src/cairo-cache.c
+++ b/src/cairo-cache.c
@@ -182,19 +182,25 @@ _cache_lookup (cairo_cache_t *cache,
{
/* We are looking up an exact entry. */
if (*probe == NULL)
+ {
/* Found an empty spot, there can't be a match */
break;
+ }
else if (*probe != DEAD_ENTRY
&& (*probe)->hashcode == hash
&& predicate (cache, key, *probe))
+ {
return probe;
+ }
}
else
{
/* We are just looking for a free slot. */
if (*probe == NULL
|| *probe == DEAD_ENTRY)
+ {
return probe;
+ }
}
if (step == 0) {
@@ -339,7 +345,6 @@ _cairo_cache_init (cairo_cache_t *cache,
if (cache != NULL){
cache->arrangement = &cache_arrangements[0];
- cache->refcount = 1;
cache->max_memory = max_memory;
cache->used_memory = 0;
cache->live_entries = 0;
@@ -362,31 +367,20 @@ _cairo_cache_init (cairo_cache_t *cache,
}
void
-_cairo_cache_reference (cairo_cache_t *cache)
-{
- _cache_sane_state (cache);
- cache->refcount++;
-}
-
-void
_cairo_cache_destroy (cairo_cache_t *cache)
{
unsigned long i;
- if (cache != NULL) {
+ if (cache == NULL)
+ return;
- _cache_sane_state (cache);
+ _cache_sane_state (cache);
- if (--cache->refcount > 0)
- return;
-
- for (i = 0; i < cache->arrangement->size; ++i) {
- _entry_destroy (cache, i);
- }
+ for (i = 0; i < cache->arrangement->size; ++i)
+ _entry_destroy (cache, i);
- free (cache->entries);
- cache->entries = NULL;
- cache->backend->destroy_cache (cache);
- }
+ free (cache->entries);
+ cache->entries = NULL;
+ cache->backend->destroy_cache (cache);
}
cairo_status_t
diff --git a/src/cairo-font.c b/src/cairo-font.c
index 3bd1e0318..0aeb00b61 100644
--- a/src/cairo-font.c
+++ b/src/cairo-font.c
@@ -53,15 +53,19 @@ _cairo_font_face_init (cairo_font_face_t *font_face,
/**
* cairo_font_face_reference:
- * @font_face: a #cairo_font_face_t
+ * @font_face: a #cairo_font_face_t, (may be NULL in which case this
+ * function does nothing).
*
* Increases the reference count on @font_face by one. This prevents
- * @font_face from being destroyed until a matching call to cairo_font_face_destroy()
- * is made.
+ * @font_face from being destroyed until a matching call to
+ * cairo_font_face_destroy() is made.
**/
void
cairo_font_face_reference (cairo_font_face_t *font_face)
{
+ if (font_face == NULL)
+ return;
+
font_face->refcount++;
}
@@ -76,6 +80,9 @@ cairo_font_face_reference (cairo_font_face_t *font_face)
void
cairo_font_face_destroy (cairo_font_face_t *font_face)
{
+ if (font_face == NULL)
+ return;
+
if (--(font_face->refcount) > 0)
return;
@@ -88,7 +95,7 @@ cairo_font_face_destroy (cairo_font_face_t *font_face)
if (font_face->refcount > 0)
return;
- _cairo_user_data_array_destroy (&font_face->user_data);
+ _cairo_user_data_array_fini (&font_face->user_data);
free (font_face);
}
@@ -327,6 +334,9 @@ _cairo_simple_font_face_destroy (void *abstract_face)
cairo_cache_t *cache;
cairo_simple_cache_key_t key;
+ if (simple_face == NULL)
+ return;
+
_lock_global_simple_cache ();
cache = _get_global_simple_cache ();
assert (cache);
@@ -395,7 +405,7 @@ _cairo_simple_font_face_create (const char *family,
return NULL;
}
status = _cairo_cache_lookup (cache, &key, (void **) &entry, &created_entry);
- if (CAIRO_OK (status) && !created_entry)
+ if (status == CAIRO_STATUS_SUCCESS && !created_entry)
cairo_font_face_reference (&entry->font_face->base);
_unlock_global_simple_cache ();
@@ -586,7 +596,7 @@ _cairo_outer_font_cache_create_entry (void *cache,
}
status = _cairo_cache_lookup (cache, key, (void **) &inner_entry, &created_entry);
- if (!CAIRO_OK (status)) {
+ if (status) {
free (entry);
return status;
}
@@ -636,7 +646,7 @@ _cairo_inner_font_cache_create_entry (void *cache,
k->font_matrix,
k->ctm,
&entry->scaled_font);
- if (!CAIRO_OK (status)) {
+ if (status) {
free (entry);
return status;
}
@@ -727,11 +737,11 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
}
status = _cairo_cache_lookup (cache, &key, (void **) &entry, NULL);
- if (CAIRO_OK (status))
+ if (status == CAIRO_STATUS_SUCCESS)
cairo_scaled_font_reference (entry->scaled_font);
_unlock_global_font_cache ();
- if (!CAIRO_OK (status))
+ if (status)
return NULL;
return entry->scaled_font;
@@ -847,12 +857,18 @@ _cairo_unscaled_font_init (cairo_unscaled_font_t *unscaled_font,
void
_cairo_unscaled_font_reference (cairo_unscaled_font_t *unscaled_font)
{
+ if (unscaled_font == NULL)
+ return;
+
unscaled_font->refcount++;
}
void
_cairo_unscaled_font_destroy (cairo_unscaled_font_t *unscaled_font)
{
+ if (unscaled_font == NULL)
+ return;
+
if (--(unscaled_font->refcount) > 0)
return;
@@ -867,7 +883,8 @@ _cairo_unscaled_font_destroy (cairo_unscaled_font_t *unscaled_font)
/**
* cairo_scaled_font_reference:
- * @scaled_font: a #cairo_scaled_font_t
+ * @scaled_font: a #cairo_scaled_font_t, (may be NULL in which case
+ * this function does nothing)
*
* Increases the reference count on @scaled_font by one. This prevents
* @scaled_font from being destroyed until a matching call to
@@ -876,6 +893,9 @@ _cairo_unscaled_font_destroy (cairo_unscaled_font_t *unscaled_font)
void
cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font)
{
+ if (scaled_font == NULL)
+ return;
+
scaled_font->refcount++;
}
@@ -893,6 +913,9 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
cairo_font_cache_key_t key;
cairo_cache_t *cache;
+ if (scaled_font == NULL)
+ return;
+
if (--(scaled_font->refcount) > 0)
return;
@@ -935,7 +958,7 @@ cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font,
status = _cairo_scaled_font_font_extents (scaled_font, extents);
- if (!CAIRO_OK (status))
+ if (status)
return status;
_cairo_matrix_compute_scale_factors (&scaled_font->font_matrix,
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index c02cd61e5..63f51a51c 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -256,6 +256,7 @@ static void
_ft_font_cache_destroy_cache (void *cache)
{
ft_cache_t *fc = (ft_cache_t *) cache;
+
FT_Done_FreeType (fc->lib);
free (fc);
}
@@ -337,11 +338,11 @@ _ft_unscaled_font_get_for_pattern (FcPattern *pattern)
}
status = _cairo_cache_lookup (cache, &key, (void **) &entry, &created_entry);
- if (CAIRO_OK (status) && !created_entry)
+ if (status == CAIRO_STATUS_SUCCESS && !created_entry)
_cairo_unscaled_font_reference (&entry->unscaled->base);
_unlock_global_ft_cache ();
- if (!CAIRO_OK (status))
+ if (status)
return NULL;
return entry->unscaled;
@@ -482,6 +483,9 @@ _cairo_ft_unscaled_font_destroy (void *abstract_font)
{
ft_unscaled_font_t *unscaled = abstract_font;
+ if (unscaled == NULL)
+ return;
+
if (unscaled->from_face) {
/* See comments in _ft_font_face_destroy about the "zombie" state
* for a _ft_font_face.
@@ -575,10 +579,9 @@ _cairo_ft_unscaled_font_create_glyph (void *abstract_
height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
stride = (width + 3) & -4;
- if (width * height == 0)
+ if (width * height == 0) {
val->image = NULL;
- else
- {
+ } else {
bitmap.pixel_mode = ft_pixel_mode_grays;
bitmap.num_grays = 256;
@@ -863,7 +866,7 @@ _cairo_ft_scaled_font_text_to_glyphs (void *abstract_font,
_cairo_ft_scaled_font_get_glyph_cache_key (scaled_font, &key);
status = _cairo_utf8_to_ucs4 ((unsigned char*)utf8, -1, &ucs4, num_glyphs);
- if (!CAIRO_OK (status))
+ if (status)
return status;
face = cairo_ft_scaled_font_lock_face (&scaled_font->base);
@@ -1341,6 +1344,9 @@ _ft_font_face_destroy (void *abstract_face)
ft_font_face_t *tmp_face = NULL;
ft_font_face_t *last_face = NULL;
+ if (font_face == NULL)
+ return;
+
/* When destroying the face created by cairo_ft_font_face_create_for_ft_face,
* we have a special "zombie" state for the face when the unscaled font
* is still alive but there are no public references to the font face.
@@ -1476,7 +1482,7 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
}
/**
- * cairo_ft_font_create_for_ft_face:
+ * cairo_ft_font_face_create_for_ft_face:
* @face: A FreeType face object, already opened. This must
* be kept around until the face's refcount drops to
* zero and it is freed. Since the face may be referenced
diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c
index 673b972c3..ce9da259b 100644
--- a/src/cairo-glitz-surface.c
+++ b/src/cairo-glitz-surface.c
@@ -70,7 +70,6 @@ _glitz_format (cairo_format_t format)
static cairo_surface_t *
_cairo_glitz_surface_create_similar (void *abstract_src,
cairo_format_t format,
- int draw,
int width,
int height)
{
@@ -215,9 +214,6 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
_cairo_image_surface_assume_ownership_of_data (image);
- _cairo_image_surface_set_repeat (image, surface->base.repeat);
- _cairo_image_surface_set_matrix (image, &(surface->base.matrix));
-
*image_out = image;
return CAIRO_STATUS_SUCCESS;
@@ -356,7 +352,7 @@ _cairo_glitz_surface_clone_similar (void *abstract_surface,
cairo_image_surface_t *image_src = (cairo_image_surface_t *) src;
clone = (cairo_glitz_surface_t *)
- _cairo_glitz_surface_create_similar (surface, image_src->format, 0,
+ _cairo_glitz_surface_create_similar (surface, image_src->format,
image_src->width,
image_src->height);
if (!clone)
@@ -602,7 +598,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
src = (cairo_glitz_surface_t *)
_cairo_surface_create_similar_scratch (&dst->base,
- CAIRO_FORMAT_ARGB32, 0,
+ CAIRO_FORMAT_ARGB32,
gradient->n_stops, 1);
if (!src)
{
@@ -1035,7 +1031,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
mask = (cairo_glitz_surface_t *)
_cairo_glitz_surface_create_similar (&dst->base,
- CAIRO_FORMAT_A8, 0,
+ CAIRO_FORMAT_A8,
2, 1);
if (!mask)
{
@@ -1135,7 +1131,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
mask = (cairo_glitz_surface_t *)
_cairo_surface_create_similar_scratch (&dst->base,
- CAIRO_FORMAT_A8, 0,
+ CAIRO_FORMAT_A8,
width, height);
if (!mask)
{
@@ -1328,7 +1324,7 @@ _cairo_glitz_area_create (cairo_glitz_root_area_t *root,
static void
_cairo_glitz_area_destroy (cairo_glitz_area_t *area)
{
- if (!area)
+ if (area == NULL)
return;
if (area->state == CAIRO_GLITZ_AREA_OCCUPIED)
@@ -1390,6 +1386,8 @@ _cairo_glitz_area_find (cairo_glitz_area_t *area,
cairo_bool_t kick_out,
void *closure)
{
+ cairo_status_t status;
+
if (area->width < width || area->height < height)
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -1403,8 +1401,9 @@ _cairo_glitz_area_find (cairo_glitz_area_t *area,
return CAIRO_INT_STATUS_UNSUPPORTED;
_cairo_glitz_area_move_out (area);
- } else
+ } else {
return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
/* fall-through */
case CAIRO_GLITZ_AREA_AVAILABLE: {
@@ -1449,9 +1448,10 @@ _cairo_glitz_area_find (cairo_glitz_area_t *area,
area->state = CAIRO_GLITZ_AREA_DIVIDED;
- if (CAIRO_OK (_cairo_glitz_area_find (area->area[0],
- width, height,
- kick_out, closure)))
+ status = _cairo_glitz_area_find (area->area[0],
+ width, height,
+ kick_out, closure);
+ if (status == CAIRO_STATUS_SUCCESS)
return CAIRO_STATUS_SUCCESS;
}
} break;
@@ -1466,9 +1466,10 @@ _cairo_glitz_area_find (cairo_glitz_area_t *area,
if (area->area[i]->width >= width &&
area->area[i]->height >= height)
{
- if (CAIRO_OK (_cairo_glitz_area_find (area->area[i],
- width, height,
- kick_out, closure)))
+ status = _cairo_glitz_area_find (area->area[i],
+ width, height,
+ kick_out, closure);
+ if (status == CAIRO_STATUS_SUCCESS)
return CAIRO_STATUS_SUCCESS;
rejected = TRUE;
@@ -1488,8 +1489,9 @@ _cairo_glitz_area_find (cairo_glitz_area_t *area,
to_area->closure,
closure) >= 0)
return CAIRO_INT_STATUS_UNSUPPORTED;
- } else
+ } else {
return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
}
for (i = 0; i < 4; i++)
@@ -1500,8 +1502,10 @@ _cairo_glitz_area_find (cairo_glitz_area_t *area,
area->closure = NULL;
area->state = CAIRO_GLITZ_AREA_AVAILABLE;
- if (CAIRO_OK (_cairo_glitz_area_find (area, width, height,
- TRUE, closure)))
+
+ status = _cairo_glitz_area_find (area, width, height,
+ TRUE, closure);
+ if (status == CAIRO_STATUS_SUCCESS)
return CAIRO_STATUS_SUCCESS;
} break;
@@ -1607,7 +1611,7 @@ static const cairo_glitz_area_funcs_t _cairo_glitz_area_funcs = {
};
static cairo_status_t
-_cairo_glitz_glyph_cache_entry_create (void *abstract_cache,
+_cairo_glitz_glyph_cache_create_entry (void *abstract_cache,
void *abstract_key,
void **return_entry)
{
@@ -1631,7 +1635,7 @@ _cairo_glitz_glyph_cache_entry_create (void *abstract_cache,
}
static void
-_cairo_glitz_glyph_cache_entry_destroy (void *abstract_cache,
+_cairo_glitz_glyph_cache_destroy_entry (void *abstract_cache,
void *abstract_entry)
{
cairo_glitz_glyph_cache_entry_t *entry = abstract_entry;
@@ -1657,7 +1661,7 @@ _cairo_glitz_glyph_cache_entry_reference (void *abstract_entry)
}
static void
-_cairo_glitz_glyph_cache_destroy (void *abstract_cache)
+_cairo_glitz_glyph_cache_destroy_cache (void *abstract_cache)
{
cairo_glitz_glyph_cache_t *cache = abstract_cache;
@@ -1669,9 +1673,9 @@ _cairo_glitz_glyph_cache_destroy (void *abstract_cache)
static const cairo_cache_backend_t _cairo_glitz_glyph_cache_backend = {
_cairo_glyph_cache_hash,
_cairo_glyph_cache_keys_equal,
- _cairo_glitz_glyph_cache_entry_create,
- _cairo_glitz_glyph_cache_entry_destroy,
- _cairo_glitz_glyph_cache_destroy
+ _cairo_glitz_glyph_cache_create_entry,
+ _cairo_glitz_glyph_cache_destroy_entry,
+ _cairo_glitz_glyph_cache_destroy_cache
};
static cairo_glitz_glyph_cache_t *_cairo_glitz_glyph_caches = NULL;
@@ -2088,7 +2092,7 @@ UNLOCK:
}
for (i = 0; i < num_glyphs; i++)
- _cairo_glitz_glyph_cache_entry_destroy (cache, entries[i]);
+ _cairo_glitz_glyph_cache_destroy_entry (cache, entries[i]);
glitz_buffer_destroy (buffer);
@@ -2125,6 +2129,7 @@ static const cairo_surface_backend_t cairo_glitz_surface_backend = {
NULL, /* copy_page */
NULL, /* show_page */
_cairo_glitz_surface_set_clip_region,
+ NULL, /* intersect_clip_path */
_cairo_glitz_surface_get_extents,
_cairo_glitz_surface_show_glyphs
};
diff --git a/src/cairo-gstate-private.h b/src/cairo-gstate-private.h
index eeb35b83e..7e2c8597c 100644
--- a/src/cairo-gstate-private.h
+++ b/src/cairo-gstate-private.h
@@ -36,6 +36,47 @@
#ifndef CAIRO_GSTATE_PRIVATE_H
#define CAIRO_GSTATE_PRIVATE_H
+#include "cairo-path-fixed-private.h"
+
+struct _cairo_clip_path {
+ unsigned int ref_count;
+ cairo_path_fixed_t path;
+ cairo_fill_rule_t fill_rule;
+ double tolerance;
+ cairo_clip_path_t *prev;
+};
+
+typedef struct _cairo_clip {
+ cairo_clip_mode_t mode;
+
+ /*
+ * Mask-based clipping for cases where the backend
+ * clipping isn't sufficiently able.
+ *
+ * The rectangle here represents the
+ * portion of the destination surface that this
+ * clip surface maps to, it does not
+ * represent the extents of the clip region or
+ * clip paths
+ */
+ cairo_surface_t *surface;
+ cairo_rectangle_t surface_rect;
+ /*
+ * Surface clip serial number to store
+ * in the surface when this clip is set
+ */
+ unsigned int serial;
+ /*
+ * A clip region that can be placed in the surface
+ */
+ pixman_region16_t *region;
+ /*
+ * If the surface supports path clipping, we store the list of
+ * clipping paths that has been set here as a linked list.
+ */
+ cairo_clip_path_t *path;
+} cairo_clip_t;
+
struct _cairo_gstate {
cairo_operator_t operator;
@@ -53,27 +94,21 @@ struct _cairo_gstate {
int num_dashes;
double dash_offset;
- char *font_family; /* NULL means CAIRO_FONT_FAMILY_DEFAULT; */
- cairo_font_slant_t font_slant;
- cairo_font_weight_t font_weight;
-
cairo_font_face_t *font_face;
cairo_scaled_font_t *scaled_font; /* Specific to the current CTM */
-
- cairo_surface_t *surface;
- int surface_level; /* Used to detect bad nested use */
-
- cairo_pattern_t *source;
-
- cairo_clip_rec_t clip;
-
cairo_matrix_t font_matrix;
+ cairo_clip_t clip;
+
cairo_matrix_t ctm;
cairo_matrix_t ctm_inverse;
cairo_pen_t pen_regular;
+ cairo_surface_t *target;
+
+ cairo_pattern_t *source;
+
struct _cairo_gstate *next;
};
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 45c729fc9..94770f329 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -42,8 +42,14 @@
#include "cairo-gstate-private.h"
static cairo_status_t
-_cairo_gstate_set_target_surface (cairo_gstate_t *gstate,
- cairo_surface_t *surface);
+_cairo_gstate_init (cairo_gstate_t *gstate,
+ cairo_surface_t *target);
+
+static cairo_status_t
+_cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other);
+
+static void
+_cairo_gstate_fini (cairo_gstate_t *gstate);
static cairo_status_t
_cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
@@ -61,6 +67,15 @@ _cairo_gstate_ensure_font_face (cairo_gstate_t *gstate);
static void
_cairo_gstate_unset_font (cairo_gstate_t *gstate);
+static void
+_cairo_rectangle_intersect (cairo_rectangle_t *dest, cairo_rectangle_t *src);
+
+static void
+_cairo_clip_path_reference (cairo_clip_path_t *clip_path);
+
+static void
+_cairo_clip_path_destroy (cairo_clip_path_t *clip_path);
+
cairo_gstate_t *
_cairo_gstate_create (cairo_surface_t *target)
{
@@ -81,12 +96,10 @@ _cairo_gstate_create (cairo_surface_t *target)
return gstate;
}
-cairo_status_t
+static cairo_status_t
_cairo_gstate_init (cairo_gstate_t *gstate,
cairo_surface_t *target)
{
- cairo_status_t status;
-
gstate->operator = CAIRO_GSTATE_OPERATOR_DEFAULT;
gstate->tolerance = CAIRO_GSTATE_TOLERANCE_DEFAULT;
@@ -102,37 +115,36 @@ _cairo_gstate_init (cairo_gstate_t *gstate,
gstate->num_dashes = 0;
gstate->dash_offset = 0.0;
- gstate->scaled_font = NULL;
gstate->font_face = NULL;
+ gstate->scaled_font = NULL;
cairo_matrix_init_scale (&gstate->font_matrix,
CAIRO_GSTATE_DEFAULT_FONT_SIZE,
CAIRO_GSTATE_DEFAULT_FONT_SIZE);
- gstate->surface = NULL;
- gstate->surface_level = 0;
-
+ gstate->clip.mode = _cairo_surface_get_clip_mode (target);
gstate->clip.region = NULL;
gstate->clip.surface = NULL;
-
- gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
- if (!gstate->source)
- return CAIRO_STATUS_NO_MEMORY;
+ gstate->clip.serial = 0;
+ gstate->clip.path = NULL;
_cairo_gstate_identity_matrix (gstate);
_cairo_pen_init_empty (&gstate->pen_regular);
- gstate->next = NULL;
+ gstate->target = target;
+ cairo_surface_reference (gstate->target);
- status = _cairo_gstate_set_target_surface (gstate, target);
- if (status)
- return status;
+ gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
+ if (gstate->source->status)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ gstate->next = NULL;
return CAIRO_STATUS_SUCCESS;
}
-cairo_status_t
+static cairo_status_t
_cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
{
cairo_status_t status;
@@ -151,8 +163,7 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
memcpy (gstate->dash, other->dash, other->num_dashes * sizeof (double));
}
- if (other->clip.region)
- {
+ if (other->clip.region) {
gstate->clip.region = pixman_region_create ();
pixman_region_copy (gstate->clip.region, other->clip.region);
}
@@ -163,8 +174,9 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
if (gstate->scaled_font)
cairo_scaled_font_reference (gstate->scaled_font);
- cairo_surface_reference (gstate->surface);
+ cairo_surface_reference (gstate->target);
cairo_surface_reference (gstate->clip.surface);
+ _cairo_clip_path_reference (gstate->clip.path);
cairo_pattern_reference (gstate->source);
@@ -172,16 +184,8 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
if (status)
goto CLEANUP_FONT;
- status = _cairo_surface_begin (gstate->surface);
- if (status)
- goto CLEANUP_PEN;
- gstate->surface_level = gstate->surface->level;
-
return status;
- CLEANUP_PEN:
- _cairo_pen_fini (&gstate->pen_regular);
-
CLEANUP_FONT:
cairo_scaled_font_destroy (gstate->scaled_font);
gstate->scaled_font = NULL;
@@ -201,19 +205,23 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
if (gstate->scaled_font)
cairo_scaled_font_destroy (gstate->scaled_font);
- if (gstate->surface) {
- _cairo_surface_end (gstate->surface);
- cairo_surface_destroy (gstate->surface);
- gstate->surface = NULL;
+ if (gstate->target) {
+ cairo_surface_destroy (gstate->target);
+ gstate->target = NULL;
}
if (gstate->clip.surface)
cairo_surface_destroy (gstate->clip.surface);
gstate->clip.surface = NULL;
+ if (gstate->clip.path)
+ _cairo_clip_path_destroy (gstate->clip.path);
+ gstate->clip.path = NULL;
+
if (gstate->clip.region)
pixman_region_destroy (gstate->clip.region);
gstate->clip.region = NULL;
+ gstate->clip.serial = 0;
cairo_pattern_destroy (gstate->source);
@@ -259,30 +267,30 @@ _cairo_gstate_begin_group (cairo_gstate_t *gstate)
Pixmap pix;
unsigned int width, height;
- gstate->parent_surface = gstate->surface;
+ gstate->parent_surface = gstate->target;
- width = _cairo_surface_get_width (gstate->surface);
- height = _cairo_surface_get_height (gstate->surface);
+ width = _cairo_surface_get_width (gstate->target);
+ height = _cairo_surface_get_height (gstate->target);
pix = XCreatePixmap (gstate->dpy,
- _cairo_surface_get_drawable (gstate->surface),
+ _cairo_surface_get_drawable (gstate->target),
width, height,
- _cairo_surface_get_depth (gstate->surface));
+ _cairo_surface_get_depth (gstate->target));
if (pix == 0)
return CAIRO_STATUS_NO_MEMORY;
- gstate->surface = cairo_surface_create (gstate->dpy);
- if (gstate->surface == NULL)
+ gstate->target = cairo_surface_create (gstate->dpy);
+ if (gstate->target == NULL)
return CAIRO_STATUS_NO_MEMORY;
- _cairo_surface_set_drawableWH (gstate->surface, pix, width, height);
+ _cairo_surface_set_drawableWH (gstate->target, pix, width, height);
- status = _cairo_surface_fill_rectangle (gstate->surface,
+ status = _cairo_surface_fill_rectangle (gstate->target,
CAIRO_OPERATOR_SOURCE,
&CAIRO_COLOR_TRANSPARENT,
0, 0,
- _cairo_surface_get_width (gstate->surface),
- _cairo_surface_get_height (gstate->surface));
+ _cairo_surface_get_width (gstate->target),
+ _cairo_surface_get_height (gstate->target));
if (status)
return status;
@@ -311,22 +319,22 @@ _cairo_gstate_end_group (cairo_gstate_t *gstate)
_cairo_surface_get_damaged_width/Height if cairo_surface_t actually kept
track of such informaton. *
_cairo_surface_composite (gstate->operator,
- gstate->surface,
+ gstate->target,
mask,
gstate->parent_surface,
0, 0,
0, 0,
0, 0,
- _cairo_surface_get_width (gstate->surface),
- _cairo_surface_get_height (gstate->surface));
+ _cairo_surface_get_width (gstate->target),
+ _cairo_surface_get_height (gstate->target));
_cairo_surface_fini (&mask);
- pix = _cairo_surface_get_drawable (gstate->surface);
+ pix = _cairo_surface_get_drawable (gstate->target);
XFreePixmap (gstate->dpy, pix);
- cairo_surface_destroy (gstate->surface);
- gstate->surface = gstate->parent_surface;
+ cairo_surface_destroy (gstate->target);
+ gstate->target = gstate->parent_surface;
gstate->parent_surface = NULL;
return CAIRO_STATUS_SUCCESS;
@@ -334,41 +342,57 @@ _cairo_gstate_end_group (cairo_gstate_t *gstate)
*/
static cairo_status_t
-_cairo_gstate_set_target_surface (cairo_gstate_t *gstate, cairo_surface_t *surface)
+_cairo_gstate_set_clip (cairo_gstate_t *gstate)
{
- cairo_status_t status;
+ cairo_surface_t *surface = gstate->target;
- if (gstate->surface == surface)
+ if (!surface)
+ return CAIRO_STATUS_NULL_POINTER;
+ if (gstate->clip.serial == _cairo_surface_get_current_clip_serial (surface))
return CAIRO_STATUS_SUCCESS;
- if (surface) {
- status = _cairo_surface_begin_reset_clip (surface);
- if (!CAIRO_OK (status))
- return status;
- }
-
- _cairo_gstate_unset_font (gstate);
-
- if (gstate->surface) {
- _cairo_surface_end (gstate->surface);
- cairo_surface_destroy (gstate->surface);
- }
-
- gstate->surface = surface;
+ if (gstate->clip.path)
+ return _cairo_surface_set_clip_path (surface,
+ gstate->clip.path,
+ gstate->clip.serial);
+
+ if (gstate->clip.region)
+ return _cairo_surface_set_clip_region (surface,
+ gstate->clip.region,
+ gstate->clip.serial);
+
+ return _cairo_surface_reset_clip (surface);
+}
- /* Sometimes the user wants to return to having no target surface,
- * (just like after cairo_create). This can be useful for forcing
- * the old surface to be destroyed. */
- if (surface == NULL) {
- gstate->surface_level = 0;
- return CAIRO_STATUS_SUCCESS;
+static cairo_status_t
+_cairo_gstate_get_clip_extents (cairo_gstate_t *gstate,
+ cairo_rectangle_t *rectangle)
+{
+ cairo_status_t status;
+
+ status = _cairo_surface_get_extents (gstate->target, rectangle);
+ if (status)
+ return status;
+ /* check path extents here */
+
+ if (gstate->clip.region) {
+ pixman_box16_t *clip_box;
+ cairo_rectangle_t clip_rect;
+
+ /* get region extents as a box */
+ clip_box = pixman_region_extents (gstate->clip.region);
+ /* convert to a rectangle */
+ clip_rect.x = clip_box->x1;
+ clip_rect.width = clip_box->x2 - clip_box->x1;
+ clip_rect.y = clip_box->y1;
+ clip_rect.height = clip_box->y2 - clip_box->y1;
+ /* intersect with surface extents */
+ _cairo_rectangle_intersect (rectangle, &clip_rect);
}
- cairo_surface_reference (gstate->surface);
- gstate->surface_level = surface->level;
-
- _cairo_gstate_identity_matrix (gstate);
-
+ if (gstate->clip.surface)
+ _cairo_rectangle_intersect (rectangle, &gstate->clip.surface_rect);
+
return CAIRO_STATUS_SUCCESS;
}
@@ -378,15 +402,15 @@ _cairo_gstate_get_target (cairo_gstate_t *gstate)
if (gstate == NULL)
return NULL;
- return gstate->surface;
+ return gstate->target;
}
cairo_status_t
_cairo_gstate_set_source (cairo_gstate_t *gstate,
cairo_pattern_t *source)
{
- if (source == NULL)
- return CAIRO_STATUS_NULL_POINTER;
+ if (source->status)
+ return source->status;
cairo_pattern_reference (source);
cairo_pattern_destroy (gstate->source);
@@ -395,24 +419,6 @@ _cairo_gstate_set_source (cairo_gstate_t *gstate,
return CAIRO_STATUS_SUCCESS;
}
-cairo_status_t
-_cairo_gstate_set_source_solid (cairo_gstate_t *gstate,
- const cairo_color_t *color)
-{
- cairo_status_t status;
- cairo_pattern_t *source;
-
- source = _cairo_pattern_create_solid (color);
- if (!source)
- return CAIRO_STATUS_NO_MEMORY;
-
- status = _cairo_gstate_set_source (gstate, source);
-
- cairo_pattern_destroy (source);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
cairo_pattern_t *
_cairo_gstate_get_source (cairo_gstate_t *gstate)
{
@@ -684,18 +690,18 @@ void
_cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y)
{
cairo_matrix_transform_point (&gstate->ctm, x, y);
- if (gstate->surface) {
- *x += gstate->surface->device_x_offset;
- *y += gstate->surface->device_y_offset;
+ if (gstate->target) {
+ *x += gstate->target->device_x_offset;
+ *y += gstate->target->device_y_offset;
}
}
void
_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y)
{
- if (gstate->surface) {
- *x -= gstate->surface->device_x_offset;
- *y -= gstate->surface->device_y_offset;
+ if (gstate->target) {
+ *x -= gstate->target->device_x_offset;
+ *y -= gstate->target->device_y_offset;
}
cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);
}
@@ -717,10 +723,10 @@ _cairo_gstate_pattern_transform (cairo_gstate_t *gstate,
{
cairo_matrix_t tmp_matrix = gstate->ctm_inverse;
- if (gstate->surface)
+ if (gstate->target)
cairo_matrix_translate (&tmp_matrix,
- - gstate->surface->device_x_offset,
- - gstate->surface->device_y_offset);
+ - gstate->target->device_x_offset,
+ - gstate->target->device_y_offset);
_cairo_pattern_transform (pattern, &tmp_matrix);
}
@@ -733,11 +739,15 @@ _cairo_gstate_paint (cairo_gstate_t *gstate)
cairo_box_t box;
cairo_traps_t traps;
- if (gstate->surface->level != gstate->surface_level)
- return CAIRO_STATUS_BAD_NESTING;
-
- status = _cairo_surface_get_clip_extents (gstate->surface, &rectangle);
- if (!CAIRO_OK (status))
+ if (gstate->source->status)
+ return gstate->source->status;
+
+ status = _cairo_gstate_set_clip (gstate);
+ if (status)
+ return status;
+
+ status = _cairo_gstate_get_clip_extents (gstate, &rectangle);
+ if (status)
return status;
box.p1.x = _cairo_fixed_from_int (rectangle.x);
@@ -745,13 +755,13 @@ _cairo_gstate_paint (cairo_gstate_t *gstate)
box.p2.x = _cairo_fixed_from_int (rectangle.x + rectangle.width);
box.p2.y = _cairo_fixed_from_int (rectangle.y + rectangle.height);
status = _cairo_traps_init_box (&traps, &box);
- if (!CAIRO_OK (status))
+ if (status)
return status;
_cairo_gstate_clip_and_composite_trapezoids (gstate,
gstate->source,
gstate->operator,
- gstate->surface,
+ gstate->target,
&traps);
_cairo_traps_fini (&traps);
@@ -778,8 +788,8 @@ _cairo_gstate_combine_clip_surface (cairo_gstate_t *gstate,
&pattern.base,
NULL,
intermediate,
- extents->x - gstate->clip.rect.x,
- extents->y - gstate->clip.rect.y,
+ extents->x - gstate->clip.surface_rect.x,
+ extents->y - gstate->clip.surface_rect.y,
0, 0,
0, 0,
extents->width, extents->height);
@@ -832,8 +842,8 @@ _cairo_gstate_intersect_clip (cairo_gstate_t *gstate,
pixman_region16_t *clip_rect;
cairo_status_t status;
- status = _region_new_from_rect (&gstate->clip.rect, &clip_rect);
- if (!CAIRO_OK (status))
+ status = _region_new_from_rect (&gstate->clip.surface_rect, &clip_rect);
+ if (status)
return status;
if (pixman_region_intersect (region,
@@ -843,7 +853,7 @@ _cairo_gstate_intersect_clip (cairo_gstate_t *gstate,
pixman_region_destroy (clip_rect);
- if (!CAIRO_OK (status))
+ if (status)
return status;
}
@@ -855,27 +865,12 @@ _get_mask_extents (cairo_gstate_t *gstate,
cairo_pattern_t *mask,
cairo_rectangle_t *extents)
{
- cairo_rectangle_t clip_rect;
- pixman_region16_t *clip_region;
- cairo_status_t status;
-
- status = _cairo_surface_get_clip_extents (gstate->surface, &clip_rect);
- if (!CAIRO_OK (status))
- return status;
-
- status = _region_new_from_rect (&clip_rect, &clip_region);
- if (!CAIRO_OK (status))
- return status;
-
- status = _cairo_gstate_intersect_clip (gstate, clip_region);
- if (!CAIRO_OK (status))
- return status;
-
- _region_rect_extents (clip_region, extents);
-
- pixman_region_destroy (clip_region);
-
- return CAIRO_STATUS_SUCCESS;
+ /*
+ * XXX should take mask extents into account, but
+ * that involves checking the transform... For now,
+ * be lazy and just use the destination extents
+ */
+ return _cairo_gstate_get_clip_extents (gstate, extents);
}
cairo_status_t
@@ -889,9 +884,16 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
cairo_status_t status;
int mask_x, mask_y;
- if (gstate->surface->level != gstate->surface_level)
- return CAIRO_STATUS_BAD_NESTING;
-
+ if (mask->status)
+ return mask->status;
+
+ if (gstate->source->status)
+ return gstate->source->status;
+
+ status = _cairo_gstate_set_clip (gstate);
+ if (status)
+ return status;
+
_get_mask_extents (gstate, mask, &extents);
if (gstate->clip.surface) {
@@ -913,13 +915,13 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
0, 0,
0, 0,
extents.width, extents.height);
- if (!CAIRO_OK (status)) {
+ if (status) {
cairo_surface_destroy (intermediate);
return status;
}
status = _cairo_gstate_combine_clip_surface (gstate, intermediate, &extents);
- if (!CAIRO_OK (status)) {
+ if (status) {
cairo_surface_destroy (intermediate);
return status;
}
@@ -942,7 +944,7 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
status = _cairo_surface_composite (gstate->operator,
&pattern.base,
effective_mask,
- gstate->surface,
+ gstate->target,
extents.x, extents.y,
extents.x - mask_x, extents.y - mask_y,
extents.x, extents.y,
@@ -960,12 +962,16 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
cairo_status_t status;
cairo_traps_t traps;
- if (gstate->surface->level != gstate->surface_level)
- return CAIRO_STATUS_BAD_NESTING;
-
+ if (gstate->source->status)
+ return gstate->source->status;
+
if (gstate->line_width <= 0.0)
return CAIRO_STATUS_SUCCESS;
+ status = _cairo_gstate_set_clip (gstate);
+ if (status)
+ return status;
+
_cairo_pen_init (&gstate->pen_regular, gstate->line_width / 2.0, gstate);
_cairo_traps_init (&traps);
@@ -979,7 +985,7 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
_cairo_gstate_clip_and_composite_trapezoids (gstate,
gstate->source,
gstate->operator,
- gstate->surface,
+ gstate->target,
&traps);
_cairo_traps_fini (&traps);
@@ -1079,7 +1085,7 @@ _clip_and_compute_extents_region (cairo_gstate_t *gstate,
cairo_status_t status;
status = _cairo_gstate_intersect_clip (gstate, trap_region);
- if (!CAIRO_OK (status))
+ if (status)
return status;
_region_rect_extents (trap_region, extents);
@@ -1105,24 +1111,28 @@ _clip_and_compute_extents_arbitrary (cairo_gstate_t *gstate,
cairo_status_t status;
status = _region_new_from_rect (extents, &intersection);
- if (!CAIRO_OK (status))
+ if (status)
return status;
if (pixman_region_intersect (intersection,
gstate->clip.region,
intersection) == PIXMAN_REGION_STATUS_SUCCESS)
+ {
_region_rect_extents (intersection, extents);
+ }
else
+ {
status = CAIRO_STATUS_NO_MEMORY;
+ }
pixman_region_destroy (intersection);
- if (!CAIRO_OK (status))
+ if (status)
return status;
}
if (gstate->clip.surface)
- _cairo_rectangle_intersect (extents, &gstate->clip.rect);
+ _cairo_rectangle_intersect (extents, &gstate->clip.surface_rect);
return CAIRO_STATUS_SUCCESS;
}
@@ -1137,17 +1147,25 @@ _composite_trap_region (cairo_gstate_t *gstate,
pixman_region16_t *trap_region,
cairo_rectangle_t *extents)
{
- cairo_status_t status, tmp_status;
+ cairo_status_t status;
cairo_pattern_union_t pattern;
cairo_pattern_union_t mask;
int num_rects = pixman_region_num_rects (trap_region);
+ unsigned int clip_serial;
if (num_rects == 0)
return CAIRO_STATUS_SUCCESS;
if (num_rects > 1) {
- status = _cairo_surface_set_clip_region (dst, trap_region);
- if (!CAIRO_OK (status))
+
+ if (gstate->clip.mode != CAIRO_CLIP_MODE_REGION)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ clip_serial = _cairo_surface_allocate_clip_serial (gstate->target);
+ status = _cairo_surface_set_clip_region (gstate->target,
+ trap_region,
+ clip_serial);
+ if (status)
return status;
}
@@ -1162,8 +1180,8 @@ _composite_trap_region (cairo_gstate_t *gstate,
gstate->clip.surface ? &mask.base : NULL,
dst,
extents->x, extents->y,
- extents->x - (gstate->clip.surface ? gstate->clip.rect.x : 0),
- extents->y - (gstate->clip.surface ? gstate->clip.rect.y : 0),
+ extents->x - (gstate->clip.surface ? gstate->clip.surface_rect.x : 0),
+ extents->y - (gstate->clip.surface ? gstate->clip.surface_rect.y : 0),
extents->x, extents->y,
extents->width, extents->height);
@@ -1171,12 +1189,6 @@ _composite_trap_region (cairo_gstate_t *gstate,
if (gstate->clip.surface)
_cairo_pattern_fini (&mask.base);
- if (num_rects > 1) {
- tmp_status = _cairo_surface_set_clip_region (dst, gstate->clip.region);
- if (!CAIRO_OK (tmp_status))
- status = tmp_status;
- }
-
return status;
}
@@ -1250,11 +1262,11 @@ _composite_traps_intermediate_surface (cairo_gstate_t *gstate,
traps->num_traps);
_cairo_pattern_fini (&pattern.base);
- if (!CAIRO_OK (status))
+ if (status)
goto out;
status = _cairo_gstate_combine_clip_surface (gstate, intermediate, extents);
- if (!CAIRO_OK (status))
+ if (status)
goto out;
_cairo_pattern_init_for_surface (&intermediate_pattern, intermediate);
@@ -1364,11 +1376,11 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
if (traps->num_traps == 0)
return CAIRO_STATUS_SUCCESS;
- if (gstate->surface == NULL)
+ if (gstate->target == NULL)
return CAIRO_STATUS_NO_TARGET_SURFACE;
status = _cairo_traps_extract_region (traps, &trap_region);
- if (!CAIRO_OK (status))
+ if (status)
return status;
if (trap_region)
@@ -1376,7 +1388,7 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
else
status = _clip_and_compute_extents_arbitrary (gstate, traps, &extents);
- if (!CAIRO_OK (status))
+ if (status)
goto out;
if (_cairo_rectangle_empty (&extents))
@@ -1405,16 +1417,23 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
/* Solid rectangles are handled specially */
status = _composite_trap_region_solid (gstate, (cairo_solid_pattern_t *)src,
operator, dst, trap_region);
- } else if (trap_region && pixman_region_num_rects (trap_region) <= 1) {
- /* For a simple rectangle, we can just use composite(), for more
- * rectangles, we'd have to set a clip region. That might still
- * be a win, but it's less obvious. (Depends on the backend)
- */
- status = _composite_trap_region (gstate, src, operator, dst,
- trap_region, &extents);
} else {
- status = _composite_traps (gstate, src, operator,
- dst, traps, &extents);
+ if (trap_region) {
+ /* For a simple rectangle, we can just use composite(), for more
+ * rectangles, we have to set a clip region. The cost of rasterizing
+ * trapezoids is pretty high for most backends currently, so it's
+ * worthwhile even if a region is needed.
+ */
+ status = _composite_trap_region (gstate, src, operator, dst,
+ trap_region, &extents);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ goto out;
+
+ /* If a clip regions aren't supported, fall through */
+ }
+
+ status = _composite_traps (gstate, src, operator,
+ dst, traps, &extents);
}
}
@@ -1431,13 +1450,19 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
cairo_status_t status;
cairo_traps_t traps;
- if (gstate->surface->level != gstate->surface_level)
- return CAIRO_STATUS_BAD_NESTING;
+ if (gstate->source->status)
+ return gstate->source->status;
+
+ status = _cairo_gstate_set_clip (gstate);
+ if (status)
+ return status;
status = _cairo_surface_fill_path (gstate->operator,
gstate->source,
- gstate->surface,
- path);
+ gstate->target,
+ path,
+ gstate->fill_rule,
+ gstate->tolerance);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
@@ -1453,7 +1478,7 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
_cairo_gstate_clip_and_composite_trapezoids (gstate,
gstate->source,
gstate->operator,
- gstate->surface,
+ gstate->target,
&traps);
_cairo_traps_fini (&traps);
@@ -1490,19 +1515,19 @@ BAIL:
cairo_status_t
_cairo_gstate_copy_page (cairo_gstate_t *gstate)
{
- if (gstate->surface == NULL)
+ if (gstate->target == NULL)
return CAIRO_STATUS_NO_TARGET_SURFACE;
- return _cairo_surface_copy_page (gstate->surface);
+ return _cairo_surface_copy_page (gstate->target);
}
cairo_status_t
_cairo_gstate_show_page (cairo_gstate_t *gstate)
{
- if (gstate->surface == NULL)
+ if (gstate->target == NULL)
return CAIRO_STATUS_NO_TARGET_SURFACE;
- return _cairo_surface_show_page (gstate->surface);
+ return _cairo_surface_show_page (gstate->target);
}
cairo_status_t
@@ -1574,9 +1599,6 @@ BAIL:
cairo_status_t
_cairo_gstate_reset_clip (cairo_gstate_t *gstate)
{
- if (gstate->surface->level != gstate->surface_level)
- return CAIRO_STATUS_BAD_NESTING;
-
/* destroy any existing clip-region artifacts */
if (gstate->clip.surface)
cairo_surface_destroy (gstate->clip.surface);
@@ -1586,109 +1608,213 @@ _cairo_gstate_reset_clip (cairo_gstate_t *gstate)
pixman_region_destroy (gstate->clip.region);
gstate->clip.region = NULL;
- /* reset the surface's clip to the whole surface */
- if (gstate->surface)
- _cairo_surface_set_clip_region (gstate->surface,
- gstate->clip.region);
+ if (gstate->clip.path)
+ _cairo_clip_path_destroy (gstate->clip.path);
+ gstate->clip.path = NULL;
+ gstate->clip.serial = 0;
+
return CAIRO_STATUS_SUCCESS;
}
-cairo_status_t
-_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
+static cairo_status_t
+_cairo_gstate_intersect_clip_path (cairo_gstate_t *gstate,
+ cairo_path_fixed_t *path)
{
+ cairo_clip_path_t *clip_path;
cairo_status_t status;
- cairo_pattern_union_t pattern;
- cairo_traps_t traps;
- cairo_box_t extents;
- pixman_region16_t *region;
- if (gstate->surface->level != gstate->surface_level)
- return CAIRO_STATUS_BAD_NESTING;
-
- /* Fill the clip region as traps. */
+ if (gstate->clip.mode != CAIRO_CLIP_MODE_PATH)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
- _cairo_traps_init (&traps);
- status = _cairo_path_fixed_fill_to_traps (path, gstate, &traps);
- if (!CAIRO_OK (status)) {
- _cairo_traps_fini (&traps);
+ clip_path = malloc (sizeof (cairo_clip_path_t));
+ if (clip_path == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ status = _cairo_path_fixed_init_copy (&clip_path->path, path);
+ if (status)
return status;
- }
- /* Check to see if we can represent these traps as a PixRegion. */
+ clip_path->ref_count = 1;
+ clip_path->fill_rule = gstate->fill_rule;
+ clip_path->tolerance = gstate->tolerance;
+ clip_path->prev = gstate->clip.path;
+ gstate->clip.path = clip_path;
+ gstate->clip.serial = _cairo_surface_allocate_clip_serial (gstate->target);
- status = _cairo_traps_extract_region (&traps, &region);
- if (!CAIRO_OK (status)) {
- _cairo_traps_fini (&traps);
- return status;
- }
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_clip_path_reference (cairo_clip_path_t *clip_path)
+{
+ if (clip_path == NULL)
+ return;
+
+ clip_path->ref_count++;
+}
+
+static void
+_cairo_clip_path_destroy (cairo_clip_path_t *clip_path)
+{
+ if (clip_path == NULL)
+ return;
+
+ clip_path->ref_count--;
+ if (clip_path->ref_count)
+ return;
+
+ _cairo_path_fixed_fini (&clip_path->path);
+ _cairo_clip_path_destroy (clip_path->prev);
+ free (clip_path);
+}
+
+static cairo_status_t
+_cairo_gstate_intersect_clip_region (cairo_gstate_t *gstate,
+ cairo_traps_t *traps)
+{
+ pixman_region16_t *region;
+ cairo_status_t status;
+
+ if (gstate->clip.mode != CAIRO_CLIP_MODE_REGION)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
- if (region) {
- status = CAIRO_STATUS_SUCCESS;
-
- if (gstate->clip.region == NULL) {
- gstate->clip.region = region;
- } else {
- pixman_region16_t *intersection = pixman_region_create();
-
- if (pixman_region_intersect (intersection,
- gstate->clip.region, region)
- == PIXMAN_REGION_STATUS_SUCCESS) {
- pixman_region_destroy (gstate->clip.region);
- gstate->clip.region = intersection;
- } else {
- status = CAIRO_STATUS_NO_MEMORY;
- }
- pixman_region_destroy (region);
- }
-
- if (CAIRO_OK (status))
- status = _cairo_surface_set_clip_region (gstate->surface,
- gstate->clip.region);
+ status = _cairo_traps_extract_region (traps, &region);
+ if (status)
+ return status;
- if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
- _cairo_traps_fini (&traps);
- return status;
- }
+ if (region == NULL)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
- /* Fall through as status == CAIRO_INT_STATUS_UNSUPPORTED
- means that backend doesn't support clipping regions and
- mask surface clipping should be used instead. */
+ status = CAIRO_STATUS_SUCCESS;
+ if (gstate->clip.region == NULL) {
+ gstate->clip.region = region;
+ } else {
+ pixman_region16_t *intersection = pixman_region_create();
+
+ if (pixman_region_intersect (intersection,
+ gstate->clip.region, region)
+ == PIXMAN_REGION_STATUS_SUCCESS) {
+ pixman_region_destroy (gstate->clip.region);
+ gstate->clip.region = intersection;
+ } else {
+ status = CAIRO_STATUS_NO_MEMORY;
+ }
+ pixman_region_destroy (region);
}
+ gstate->clip.serial = _cairo_surface_allocate_clip_serial (gstate->target);
+ return status;
+}
- /* Otherwise represent the clip as a mask surface. */
-
- if (gstate->clip.surface == NULL) {
- _cairo_traps_extents (&traps, &extents);
- _cairo_box_round_to_rectangle (&extents, &gstate->clip.rect);
- gstate->clip.surface =
- _cairo_surface_create_similar_solid (gstate->surface,
- CAIRO_FORMAT_A8,
- gstate->clip.rect.width,
- gstate->clip.rect.height,
- CAIRO_COLOR_WHITE);
- if (gstate->clip.surface == NULL)
- return CAIRO_STATUS_NO_MEMORY;
- }
+static cairo_status_t
+_cairo_gstate_intersect_clip_mask (cairo_gstate_t *gstate,
+ cairo_traps_t *traps)
+{
+ cairo_pattern_union_t pattern;
+ cairo_box_t extents;
+ cairo_rectangle_t surface_rect;
+ cairo_surface_t *surface;
+ cairo_status_t status;
+
+ /* Represent the clip as a mask surface. We create a new surface
+ * the size of the intersection of the old mask surface and the
+ * extents of the new clip path. */
+
+ _cairo_traps_extents (traps, &extents);
+ _cairo_box_round_to_rectangle (&extents, &surface_rect);
+
+ if (gstate->clip.surface != NULL)
+ _cairo_rectangle_intersect (&surface_rect, &gstate->clip.surface_rect);
- translate_traps (&traps, -gstate->clip.rect.x, -gstate->clip.rect.y);
+ surface = _cairo_surface_create_similar_solid (gstate->target,
+ CAIRO_FORMAT_A8,
+ surface_rect.width,
+ surface_rect.height,
+ CAIRO_COLOR_WHITE);
+ if (surface == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ /* Render the new clipping path into the new mask surface. */
+
+ translate_traps (traps, -surface_rect.x, -surface_rect.y);
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_IN,
&pattern.base,
- gstate->clip.surface,
+ surface,
0, 0,
0, 0,
- gstate->clip.rect.width,
- gstate->clip.rect.height,
- traps.traps,
- traps.num_traps);
+ surface_rect.width,
+ surface_rect.height,
+ traps->traps,
+ traps->num_traps);
_cairo_pattern_fini (&pattern.base);
+
+ if (status) {
+ cairo_surface_destroy (surface);
+ return status;
+ }
+
+ /* If there was a clip surface already, combine it with the new
+ * mask surface using the IN operator, so we get the intersection
+ * of the old and new clipping paths. */
+
+ if (gstate->clip.surface != NULL) {
+ _cairo_pattern_init_for_surface (&pattern.surface, gstate->clip.surface);
+
+ status = _cairo_surface_composite (CAIRO_OPERATOR_IN,
+ &pattern.base,
+ NULL,
+ surface,
+ surface_rect.x - gstate->clip.surface_rect.x,
+ surface_rect.y - gstate->clip.surface_rect.y,
+ 0, 0,
+ 0, 0,
+ surface_rect.width,
+ surface_rect.height);
+
+ _cairo_pattern_fini (&pattern.base);
+
+ if (status) {
+ cairo_surface_destroy (surface);
+ return status;
+ }
+
+ cairo_surface_destroy (gstate->clip.surface);
+ }
+
+ gstate->clip.surface = surface;
+ gstate->clip.surface_rect = surface_rect;
+
+ return status;
+}
+
+cairo_status_t
+_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
+{
+ cairo_status_t status;
+ cairo_traps_t traps;
+ status = _cairo_gstate_intersect_clip_path (gstate, path);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
+
+ _cairo_traps_init (&traps);
+ status = _cairo_path_fixed_fill_to_traps (path, gstate, &traps);
+ if (status)
+ goto bail;
+
+ status = _cairo_gstate_intersect_clip_region (gstate, &traps);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ goto bail;
+
+ status = _cairo_gstate_intersect_clip_mask (gstate, &traps);
+
+ bail:
_cairo_traps_fini (&traps);
- return CAIRO_STATUS_SUCCESS;
+ return status;
}
static void
@@ -1969,9 +2095,13 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
cairo_box_t bbox;
cairo_rectangle_t extents;
- if (gstate->surface->level != gstate->surface_level)
- return CAIRO_STATUS_BAD_NESTING;
-
+ if (gstate->source->status)
+ return gstate->source->status;
+
+ status = _cairo_gstate_set_clip (gstate);
+ if (status)
+ return status;
+
status = _cairo_gstate_ensure_font (gstate);
if (status)
return status;
@@ -2001,7 +2131,7 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
cairo_surface_t *intermediate;
cairo_surface_pattern_t intermediate_pattern;
- _cairo_rectangle_intersect (&extents, &gstate->clip.rect);
+ _cairo_rectangle_intersect (&extents, &gstate->clip.surface_rect);
/* Shortcut if empty */
if (_cairo_rectangle_empty (&extents)) {
@@ -2048,8 +2178,8 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
&pattern.base,
NULL,
intermediate,
- extents.x - gstate->clip.rect.x,
- extents.y - gstate->clip.rect.y,
+ extents.x - gstate->clip.surface_rect.x,
+ extents.y - gstate->clip.surface_rect.y,
0, 0,
0, 0,
extents.width, extents.height);
@@ -2066,7 +2196,7 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
status = _cairo_surface_composite (gstate->operator,
&pattern.base,
&intermediate_pattern.base,
- gstate->surface,
+ gstate->target,
extents.x, extents.y,
0, 0,
extents.x, extents.y,
@@ -2086,7 +2216,7 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
status = _cairo_scaled_font_show_glyphs (gstate->scaled_font,
gstate->operator, &pattern.base,
- gstate->surface,
+ gstate->target,
extents.x, extents.y,
extents.x, extents.y,
extents.width, extents.height,
diff --git a/src/cairo-hash.c b/src/cairo-hash.c
index e95894960..e7547bc29 100644
--- a/src/cairo-hash.c
+++ b/src/cairo-hash.c
@@ -182,19 +182,25 @@ _cache_lookup (cairo_cache_t *cache,
{
/* We are looking up an exact entry. */
if (*probe == NULL)
+ {
/* Found an empty spot, there can't be a match */
break;
+ }
else if (*probe != DEAD_ENTRY
&& (*probe)->hashcode == hash
&& predicate (cache, key, *probe))
+ {
return probe;
+ }
}
else
{
/* We are just looking for a free slot. */
if (*probe == NULL
|| *probe == DEAD_ENTRY)
+ {
return probe;
+ }
}
if (step == 0) {
@@ -339,7 +345,6 @@ _cairo_cache_init (cairo_cache_t *cache,
if (cache != NULL){
cache->arrangement = &cache_arrangements[0];
- cache->refcount = 1;
cache->max_memory = max_memory;
cache->used_memory = 0;
cache->live_entries = 0;
@@ -362,31 +367,20 @@ _cairo_cache_init (cairo_cache_t *cache,
}
void
-_cairo_cache_reference (cairo_cache_t *cache)
-{
- _cache_sane_state (cache);
- cache->refcount++;
-}
-
-void
_cairo_cache_destroy (cairo_cache_t *cache)
{
unsigned long i;
- if (cache != NULL) {
+ if (cache == NULL)
+ return;
- _cache_sane_state (cache);
+ _cache_sane_state (cache);
- if (--cache->refcount > 0)
- return;
-
- for (i = 0; i < cache->arrangement->size; ++i) {
- _entry_destroy (cache, i);
- }
+ for (i = 0; i < cache->arrangement->size; ++i)
+ _entry_destroy (cache, i);
- free (cache->entries);
- cache->entries = NULL;
- cache->backend->destroy_cache (cache);
- }
+ free (cache->entries);
+ cache->entries = NULL;
+ cache->backend->destroy_cache (cache);
}
cairo_status_t
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 19dc7b611..255cd0c43 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -259,7 +259,6 @@ cairo_image_surface_get_height (cairo_surface_t *surface)
static cairo_surface_t *
_cairo_image_surface_create_similar (void *abstract_src,
cairo_format_t format,
- int drawable,
int width,
int height)
{
@@ -352,7 +351,7 @@ _cairo_image_surface_clone_similar (void *abstract_surface,
return CAIRO_INT_STATUS_UNSUPPORTED;
}
-cairo_status_t
+static cairo_status_t
_cairo_image_surface_set_matrix (cairo_image_surface_t *surface,
const cairo_matrix_t *matrix)
{
@@ -375,7 +374,7 @@ _cairo_image_surface_set_matrix (cairo_image_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
-cairo_status_t
+static cairo_status_t
_cairo_image_surface_set_filter (cairo_image_surface_t *surface, cairo_filter_t filter)
{
pixman_filter_t pixman_filter;
@@ -405,7 +404,7 @@ _cairo_image_surface_set_filter (cairo_image_surface_t *surface, cairo_filter_t
return CAIRO_STATUS_SUCCESS;
}
-cairo_status_t
+static cairo_status_t
_cairo_image_surface_set_repeat (cairo_image_surface_t *surface, int repeat)
{
pixman_image_set_repeat (surface->pixman_image, repeat);
@@ -518,12 +517,12 @@ _cairo_image_surface_composite (cairo_operator_t operator,
return status;
status = _cairo_image_surface_set_attributes (src, &src_attr);
- if (CAIRO_OK (status))
+ if (status == CAIRO_STATUS_SUCCESS)
{
if (mask)
{
status = _cairo_image_surface_set_attributes (mask, &mask_attr);
- if (CAIRO_OK (status))
+ if (status == CAIRO_STATUS_SUCCESS)
pixman_composite (_pixman_operator (operator),
src->pixman_image,
mask->pixman_image,
@@ -621,7 +620,7 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t operator,
/* XXX: The pixman_trapezoid_t cast is evil and needs to go away
* somehow. */
status = _cairo_image_surface_set_attributes (src, &attributes);
- if (CAIRO_OK (status))
+ if (status == CAIRO_STATUS_SUCCESS)
pixman_composite_trapezoids (_pixman_operator (operator),
src->pixman_image,
dst->pixman_image,
@@ -714,6 +713,7 @@ static const cairo_surface_backend_t cairo_image_surface_backend = {
NULL, /* copy_page */
NULL, /* show_page */
_cairo_image_abstract_surface_set_clip_region,
+ NULL, /* intersect_clip_path */
_cairo_image_abstract_surface_get_extents,
NULL /* show_glyphs */
};
diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c
index 82ec0dbb7..98feb5714 100644
--- a/src/cairo-matrix.c
+++ b/src/cairo-matrix.c
@@ -526,7 +526,9 @@ _cairo_matrix_compute_scale_factors (const cairo_matrix_t *matrix,
_cairo_matrix_compute_determinant (matrix, &det);
if (det == 0)
+ {
*sx = *sy = 0;
+ }
else
{
double x = x_major != 0;
@@ -560,25 +562,29 @@ _cairo_matrix_compute_scale_factors (const cairo_matrix_t *matrix,
}
cairo_bool_t
-_cairo_matrix_is_integer_translation(const cairo_matrix_t *mat,
+_cairo_matrix_is_integer_translation(const cairo_matrix_t *m,
int *itx, int *ity)
{
- double a, b, c, d, tx, ty;
- int ttx, tty;
- int ok = 0;
- _cairo_matrix_get_affine (mat, &a, &b, &c, &d, &tx, &ty);
- ttx = _cairo_fixed_from_double (tx);
- tty = _cairo_fixed_from_double (ty);
- ok = ((a == 1.0)
- && (b == 0.0)
- && (c == 0.0)
- && (d == 1.0)
- && (_cairo_fixed_is_integer(ttx))
- && (_cairo_fixed_is_integer(tty)));
- if (ok) {
- *itx = _cairo_fixed_integer_part(ttx);
- *ity = _cairo_fixed_integer_part(tty);
- return TRUE;
- }
- return FALSE;
+ cairo_bool_t is_integer_translation;
+ cairo_fixed_t x0_fixed, y0_fixed;
+
+ x0_fixed = _cairo_fixed_from_double (m->x0);
+ y0_fixed = _cairo_fixed_from_double (m->y0);
+
+ is_integer_translation = ((m->xx == 1.0) &&
+ (m->yx == 0.0) &&
+ (m->xy == 0.0) &&
+ (m->yy == 1.0) &&
+ (_cairo_fixed_is_integer(x0_fixed)) &&
+ (_cairo_fixed_is_integer(y0_fixed)));
+
+ if (! is_integer_translation)
+ return FALSE;
+
+ if (itx)
+ *itx = _cairo_fixed_integer_part(x0_fixed);
+ if (ity)
+ *ity = _cairo_fixed_integer_part(y0_fixed);
+
+ return TRUE;
}
diff --git a/src/cairo-path-data-private.h b/src/cairo-path-data-private.h
index e47eaaef9..f7f429437 100644
--- a/src/cairo-path-data-private.h
+++ b/src/cairo-path-data-private.h
@@ -38,17 +38,18 @@
#include "cairoint.h"
-extern cairo_path_t _cairo_path_nil;
-
-cairo_path_t *
+cairo_private cairo_path_t *
_cairo_path_data_create (cairo_path_fixed_t *path,
cairo_gstate_t *gstate);
-cairo_path_t *
+cairo_private cairo_path_t *
_cairo_path_data_create_flat (cairo_path_fixed_t *path,
cairo_gstate_t *gstate);
-cairo_status_t
+cairo_private cairo_path_t *
+_cairo_path_data_create_in_error (cairo_status_t status);
+
+cairo_private cairo_status_t
_cairo_path_data_append_to_context (cairo_path_t *path,
cairo_t *cr);
diff --git a/src/cairo-path-data.c b/src/cairo-path-data.c
index 95fc3bb26..519c76315 100644
--- a/src/cairo-path-data.c
+++ b/src/cairo-path-data.c
@@ -37,8 +37,8 @@
#include "cairo-path-fixed-private.h"
#include "cairo-gstate-private.h"
-cairo_path_t
-_cairo_path_nil = { NULL, 0 };
+static cairo_path_t
+cairo_path_nil = { CAIRO_STATUS_NO_MEMORY, NULL, 0 };
/* Closure for path interpretation. */
typedef struct cairo_path_data_count {
@@ -105,14 +105,18 @@ _cpdc_curve_to_flatten (void *closure,
status = _cairo_spline_decompose (&spline, cpdc->tolerance);
if (status)
- return status;
+ goto out;
for (i=1; i < spline.num_points; i++)
_cpdc_line_to (cpdc, &spline.points[i]);
cpdc->current_point = *p3;
- return CAIRO_STATUS_SUCCESS;
+ status = CAIRO_STATUS_SUCCESS;
+
+ out:
+ _cairo_spline_fini (&spline);
+ return status;
}
static cairo_status_t
@@ -276,14 +280,18 @@ _cpdp_curve_to_flatten (void *closure,
status = _cairo_spline_decompose (&spline, cpdp->gstate->tolerance);
if (status)
- return status;
+ goto out;
for (i=1; i < spline.num_points; i++)
_cpdp_line_to (cpdp, &spline.points[i]);
cpdp->current_point = *p3;
- return CAIRO_STATUS_SUCCESS;
+ status = CAIRO_STATUS_SUCCESS;
+
+ out:
+ _cairo_spline_fini (&spline);
+ return status;
}
static cairo_status_t
@@ -339,7 +347,7 @@ _cairo_path_data_create_real (cairo_path_fixed_t *path_fixed,
path = malloc (sizeof (cairo_path_t));
if (path == NULL)
- return &_cairo_path_nil;
+ return &cairo_path_nil;
path->num_data = _cairo_path_data_count (path, path_fixed,
gstate->tolerance, flatten);
@@ -347,23 +355,56 @@ _cairo_path_data_create_real (cairo_path_fixed_t *path_fixed,
path->data = malloc (path->num_data * sizeof (cairo_path_data_t));
if (path->data == NULL) {
free (path);
- return &_cairo_path_nil;
+ return &cairo_path_nil;
}
+ path->status = CAIRO_STATUS_SUCCESS;
+
_cairo_path_data_populate (path, path_fixed,
gstate, flatten);
return path;
}
+/**
+ * cairo_path_destroy:
+ * @path: a path to destroy which was previously returned by either
+ * cairo_copy_path or cairo_copy_path_flat.
+ *
+ * Immediately releases all memory associated with @path. After a call
+ * to cairo_path_destroy() the @path pointer is no longer valid and
+ * should not be used further.
+ *
+ * NOTE: cairo_path_destroy function should only be called with a
+ * pointer to a #cairo_path_t returned by a cairo function. Any path
+ * that is created manually (ie. outside of cairo) should be destroyed
+ * manually as well.
+ **/
void
cairo_path_destroy (cairo_path_t *path)
{
+ if (path == NULL || path == &cairo_path_nil)
+ return;
+
free (path->data);
path->num_data = 0;
free (path);
}
+/**
+ * _cairo_path_data_create:
+ * @path: a fixed-point, device-space path to be converted and copied
+ * @gstate: the current graphics state
+ *
+ * Creates a user-space #cairo_path_t copy of the given device-space
+ * @path. The @gstate parameter provides the inverse CTM for the
+ * conversion.
+ *
+ * Return value: the new copy of the path. If there is insufficient
+ * memory a pointer to a special static cairo_path_nil will be
+ * returned instead with status==CAIRO_STATUS_NO_MEMORY and
+ * data==NULL.
+ **/
cairo_path_t *
_cairo_path_data_create (cairo_path_fixed_t *path,
cairo_gstate_t *gstate)
@@ -371,6 +412,21 @@ _cairo_path_data_create (cairo_path_fixed_t *path,
return _cairo_path_data_create_real (path, gstate, FALSE);
}
+/**
+ * _cairo_path_data_create_flat:
+ * @path: a fixed-point, device-space path to be flattened, converted and copied
+ * @gstate: the current graphics state
+ *
+ * Creates a flattened, user-space #cairo_path_t copy of the given
+ * device-space @path. The @gstate parameter provide the inverse CTM
+ * for the conversion, as well as the tolerance value to control the
+ * accuracy of the flattening.
+ *
+ * Return value: the flattened copy of the path. If there is insufficient
+ * memory a pointer to a special static cairo_path_nil will be
+ * returned instead with status==CAIRO_STATUS_NO_MEMORY and
+ * data==NULL.
+ **/
cairo_path_t *
_cairo_path_data_create_flat (cairo_path_fixed_t *path,
cairo_gstate_t *gstate)
@@ -378,6 +434,45 @@ _cairo_path_data_create_flat (cairo_path_fixed_t *path,
return _cairo_path_data_create_real (path, gstate, TRUE);
}
+/**
+ * _cairo_path_data_create_in_error:
+ * @status: an error status
+ *
+ * Create an empty #cairo_path_t object to hold an error status. This
+ * is useful for propagating status values from an existing object to
+ * a new #cairo_path_t.
+ *
+ * Return value: a #cairo_path_t object with status of @status, NULL
+ * data, and 0 num_data. If there is insufficient memory a pointer to
+ * a special static cairo_path_nil will be returned instead with
+ * status==CAIRO_STATUS_NO_MEMORY rather than @status.
+ **/
+cairo_path_t *
+_cairo_path_data_create_in_error (cairo_status_t status)
+{
+ cairo_path_t *path;
+
+ path = malloc (sizeof (cairo_path_t));
+ if (path == NULL)
+ return &cairo_path_nil;
+
+ path->status = status;
+ path->data = NULL;
+ path->num_data = 0;
+
+ return path;
+}
+
+/**
+ * _cairo_path_data_append_to_context:
+ * @path: the path data to be appended
+ * @cr: a cairo context
+ *
+ * Append @path to the current path within @cr.
+ *
+ * Return value: CAIRO_STATUS_INVALID_PATH_DATA if the data in @path
+ * is invalid, and CAIRO_STATUS_SUCCESS otherwise.
+ **/
cairo_status_t
_cairo_path_data_append_to_context (cairo_path_t *path,
cairo_t *cr)
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 1746b6b2a..cd099fdd2 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -50,20 +50,67 @@ typedef struct _cairo_shader_op {
((unsigned char) \
((((unsigned char) (c1)) * (int) ((unsigned char) (c2))) / 0xff))
+static const cairo_solid_pattern_t cairo_solid_pattern_nil = {
+ { CAIRO_PATTERN_SOLID, /* type */
+ (unsigned int)-1, /* ref_count */
+ CAIRO_STATUS_NO_MEMORY, /* status */
+ { 1., 0., 0., 1., 0., 0., }, /* matrix */
+ CAIRO_FILTER_DEFAULT, /* filter */
+ CAIRO_EXTEND_DEFAULT }, /* extend */
+ { 0.0, 0.0, 0.0, 1.0, /* solid black */
+ 0x0, 0x0, 0x0, 0xffff }
+};
+
+static const cairo_surface_pattern_t cairo_surface_pattern_nil = {
+ { CAIRO_PATTERN_SURFACE, /* type */
+ (unsigned int)-1, /* ref_count */
+ CAIRO_STATUS_NO_MEMORY, /* status */
+ { 1., 0., 0., 1., 0., 0., }, /* matrix */
+ CAIRO_FILTER_DEFAULT, /* filter */
+ CAIRO_EXTEND_DEFAULT }, /* extend */
+ NULL /* surface */
+};
+
+static const cairo_linear_pattern_t cairo_linear_pattern_nil = {
+ { { CAIRO_PATTERN_LINEAR, /* type */
+ (unsigned int)-1, /* ref_count */
+ CAIRO_STATUS_NO_MEMORY, /* status */
+ { 1., 0., 0., 1., 0., 0., }, /* matrix */
+ CAIRO_FILTER_DEFAULT, /* filter */
+ CAIRO_EXTEND_DEFAULT }, /* extend */
+ NULL, /* stops */
+ 0 }, /* n_stops */
+ { 0., 0. }, { 1.0, 1.0 } /* point0, point1 */
+};
+
+static const cairo_radial_pattern_t cairo_radial_pattern_nil = {
+ { { CAIRO_PATTERN_RADIAL, /* type */
+ (unsigned int)-1, /* ref_count */
+ CAIRO_STATUS_NO_MEMORY, /* status */
+ { 1., 0., 0., 1., 0., 0., }, /* matrix */
+ CAIRO_FILTER_DEFAULT, /* filter */
+ CAIRO_EXTEND_DEFAULT }, /* extend */
+ NULL, /* stops */
+ 0 }, /* n_stops */
+ { 0., 0. }, { 0.0, 0.0 }, /* center0, center1 */
+ 1.0, 1.0, /* radius0, radius1 */
+};
+
static void
_cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
{
pattern->type = type;
pattern->ref_count = 1;
+ pattern->status = CAIRO_STATUS_SUCCESS;
pattern->extend = CAIRO_EXTEND_DEFAULT;
pattern->filter = CAIRO_FILTER_DEFAULT;
cairo_matrix_init_identity (&pattern->matrix);
}
-static cairo_status_t
-_cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern,
- cairo_gradient_pattern_t *other)
+static void
+_cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern,
+ const cairo_gradient_pattern_t *other)
{
if (other->base.type == CAIRO_PATTERN_LINEAR)
{
@@ -83,18 +130,22 @@ _cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern,
if (other->n_stops)
{
pattern->stops = malloc (other->n_stops * sizeof (cairo_color_stop_t));
- if (!pattern->stops)
- return CAIRO_STATUS_NO_MEMORY;
+ if (!pattern->stops) {
+ if (other->base.type == CAIRO_PATTERN_LINEAR)
+ _cairo_gradient_pattern_init_copy (pattern, &cairo_linear_pattern_nil.base);
+ else
+ _cairo_gradient_pattern_init_copy (pattern, &cairo_radial_pattern_nil.base);
+ return;
+ }
memcpy (pattern->stops, other->stops,
other->n_stops * sizeof (cairo_color_stop_t));
}
-
- return CAIRO_STATUS_SUCCESS;
}
-cairo_status_t
-_cairo_pattern_init_copy (cairo_pattern_t *pattern, cairo_pattern_t *other)
+void
+_cairo_pattern_init_copy (cairo_pattern_t *pattern,
+ const cairo_pattern_t *other)
{
switch (other->type) {
case CAIRO_PATTERN_SOLID: {
@@ -114,17 +165,12 @@ _cairo_pattern_init_copy (cairo_pattern_t *pattern, cairo_pattern_t *other)
case CAIRO_PATTERN_RADIAL: {
cairo_gradient_pattern_t *dst = (cairo_gradient_pattern_t *) pattern;
cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) other;
- cairo_status_t status;
- status = _cairo_gradient_pattern_init_copy (dst, src);
- if (status)
- return status;
+ _cairo_gradient_pattern_init_copy (dst, src);
} break;
}
pattern->ref_count = 1;
-
- return CAIRO_STATUS_SUCCESS;
}
void
@@ -210,13 +256,44 @@ _cairo_pattern_create_solid (const cairo_color_t *color)
pattern = malloc (sizeof (cairo_solid_pattern_t));
if (pattern == NULL)
- return NULL;
+ return (cairo_pattern_t *) &cairo_solid_pattern_nil.base;
_cairo_pattern_init_solid (pattern, color);
return &pattern->base;
}
+/**
+ * _cairo_pattern_create_in_error:
+ * @status: an error status
+ *
+ * Create an empty #cairo_pattern_t object to hold an error
+ * status. This is useful for propagating status values from an
+ * existing object to a new #cairo_pattern_t.
+ *
+ * Return value: a (solid, black) #cairo_pattern_t object with status
+ * of @status. If there is insufficient memory a pointer to a special,
+ * static cairo_solid_pattern_nil will be returned instead with a
+ * status of CAIRO_STATUS_NO_MEMORY rather than @status.
+ *
+ * Return value:
+ **/
+cairo_pattern_t *
+_cairo_pattern_create_in_error (cairo_status_t status)
+{
+ cairo_solid_pattern_t *pattern;
+
+ pattern = malloc (sizeof (cairo_solid_pattern_t));
+ if (pattern == NULL)
+ return (cairo_pattern_t *) &cairo_solid_pattern_nil.base;
+
+ _cairo_pattern_init_solid (pattern, CAIRO_COLOR_BLACK);
+
+ pattern->base.status = status;
+
+ return &pattern->base;
+}
+
cairo_pattern_t *
cairo_pattern_create_for_surface (cairo_surface_t *surface)
{
@@ -224,16 +301,10 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface)
pattern = malloc (sizeof (cairo_surface_pattern_t));
if (pattern == NULL)
- return NULL;
+ return (cairo_pattern_t *)&cairo_surface_pattern_nil.base;
_cairo_pattern_init_for_surface (pattern, surface);
- /* this will go away when we completely remove the surface attributes */
- if (surface->repeat)
- pattern->base.extend = CAIRO_EXTEND_REPEAT;
- else
- pattern->base.extend = CAIRO_EXTEND_DEFAULT;
-
return &pattern->base;
}
@@ -244,7 +315,7 @@ cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
pattern = malloc (sizeof (cairo_linear_pattern_t));
if (pattern == NULL)
- return NULL;
+ return (cairo_pattern_t *) &cairo_linear_pattern_nil.base;
_cairo_pattern_init_linear (pattern, x0, y0, x1, y1);
@@ -259,7 +330,7 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0,
pattern = malloc (sizeof (cairo_radial_pattern_t));
if (pattern == NULL)
- return NULL;
+ return (cairo_pattern_t *) &cairo_radial_pattern_nil.base;
_cairo_pattern_init_radial (pattern, cx0, cy0, radius0, cx1, cy1, radius1);
@@ -272,15 +343,36 @@ cairo_pattern_reference (cairo_pattern_t *pattern)
if (pattern == NULL)
return;
+ if (pattern->ref_count == (unsigned int)-1)
+ return;
+
pattern->ref_count++;
}
+/**
+ * cairo_pattern_status:
+ * @pattern: a #cairo_pattern_t
+ *
+ * Checks whether an error has previously occurred for this
+ * pattern.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
+ **/
+cairo_status_t
+cairo_pattern_status (cairo_pattern_t *pattern)
+{
+ return pattern->status;
+}
+
void
cairo_pattern_destroy (cairo_pattern_t *pattern)
{
if (pattern == NULL)
return;
+ if (pattern->ref_count == (unsigned int)-1)
+ return;
+
pattern->ref_count--;
if (pattern->ref_count)
return;
@@ -289,31 +381,31 @@ cairo_pattern_destroy (cairo_pattern_t *pattern)
free (pattern);
}
-static cairo_status_t
+static void
_cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
double offset,
cairo_color_t *color)
{
cairo_color_stop_t *stop;
+ cairo_color_stop_t *new_stops;
pattern->n_stops++;
- pattern->stops = realloc (pattern->stops,
- pattern->n_stops * sizeof (cairo_color_stop_t));
- if (pattern->stops == NULL) {
- pattern->n_stops = 0;
-
- return CAIRO_STATUS_NO_MEMORY;
+ new_stops = realloc (pattern->stops,
+ pattern->n_stops * sizeof (cairo_color_stop_t));
+ if (new_stops == NULL) {
+ pattern->base.status = CAIRO_STATUS_NO_MEMORY;
+ return;
}
+
+ pattern->stops = new_stops;
stop = &pattern->stops[pattern->n_stops - 1];
stop->offset = _cairo_fixed_from_double (offset);
stop->color = *color;
-
- return CAIRO_STATUS_SUCCESS;
}
-cairo_status_t
+void
cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
double offset,
double red,
@@ -322,11 +414,14 @@ cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
{
cairo_color_t color;
+ if (pattern->status)
+ return;
+
if (pattern->type != CAIRO_PATTERN_LINEAR &&
pattern->type != CAIRO_PATTERN_RADIAL)
{
- /* XXX: CAIRO_STATUS_INVALID_PATTERN? */
- return CAIRO_STATUS_SUCCESS;
+ pattern->status = CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
+ return;
}
_cairo_restrict_value (&offset, 0.0, 1.0);
@@ -335,12 +430,12 @@ cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
_cairo_restrict_value (&blue, 0.0, 1.0);
_cairo_color_init_rgb (&color, red, green, blue);
- return _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
- offset,
- &color);
+ _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
+ offset,
+ &color);
}
-cairo_status_t
+void
cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
double offset,
double red,
@@ -350,11 +445,14 @@ cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
{
cairo_color_t color;
+ if (pattern->status)
+ return;
+
if (pattern->type != CAIRO_PATTERN_LINEAR &&
pattern->type != CAIRO_PATTERN_RADIAL)
{
- /* XXX: CAIRO_STATUS_INVALID_PATTERN? */
- return CAIRO_STATUS_SUCCESS;
+ pattern->status = CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
+ return;
}
_cairo_restrict_value (&offset, 0.0, 1.0);
@@ -364,34 +462,34 @@ cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
_cairo_restrict_value (&alpha, 0.0, 1.0);
_cairo_color_init_rgba (&color, red, green, blue, alpha);
- return _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
- offset,
- &color);
+ _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
+ offset,
+ &color);
}
-cairo_status_t
+void
cairo_pattern_set_matrix (cairo_pattern_t *pattern,
const cairo_matrix_t *matrix)
{
- pattern->matrix = *matrix;
+ if (pattern->status)
+ return;
- return CAIRO_STATUS_SUCCESS;
+ pattern->matrix = *matrix;
}
-cairo_status_t
+void
cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix)
{
*matrix = pattern->matrix;
-
- return CAIRO_STATUS_SUCCESS;
}
-cairo_status_t
+void
cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
{
- pattern->filter = filter;
+ if (pattern->status)
+ return;
- return CAIRO_STATUS_SUCCESS;
+ pattern->filter = filter;
}
cairo_filter_t
@@ -400,12 +498,13 @@ cairo_pattern_get_filter (cairo_pattern_t *pattern)
return pattern->filter;
}
-cairo_status_t
+void
cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
{
- pattern->extend = extend;
+ if (pattern->status)
+ return;
- return CAIRO_STATUS_SUCCESS;
+ pattern->extend = extend;
}
cairo_extend_t
@@ -418,6 +517,8 @@ void
_cairo_pattern_transform (cairo_pattern_t *pattern,
const cairo_matrix_t *ctm_inverse)
{
+ assert (pattern->status == CAIRO_STATUS_SUCCESS);
+
cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix);
}
@@ -868,8 +969,9 @@ _cairo_image_data_set_radial (cairo_radial_pattern_t *pattern,
c0_x = y_x + c0_y;
factor = (c0_e - r0) / (c0_x - r0);
- } else
+ } else {
factor = -r0;
+ }
}
_cairo_pattern_calc_color_at_pixel (&op, factor * 65536, pixels++);
@@ -960,7 +1062,6 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
attr->extend = repeat ? CAIRO_EXTEND_REPEAT : CAIRO_EXTEND_NONE;
attr->filter = CAIRO_FILTER_NEAREST;
attr->acquired = FALSE;
- attr->clip_saved = FALSE;
return status;
}
@@ -988,7 +1089,6 @@ _cairo_pattern_acquire_surface_for_solid (cairo_solid_pattern_t *pattern,
attribs->extend = CAIRO_EXTEND_REPEAT;
attribs->filter = CAIRO_FILTER_NEAREST;
attribs->acquired = FALSE;
- attribs->clip_saved = FALSE;
return CAIRO_STATUS_SUCCESS;
}
@@ -1015,7 +1115,7 @@ _cairo_pattern_is_opaque_solid (cairo_pattern_t *pattern)
solid = (cairo_solid_pattern_t *) pattern;
- return (solid->color.alpha >= ((double)0xff00 / (double)0xffff));
+ return CAIRO_ALPHA_IS_OPAQUE (solid->color.alpha);
}
static cairo_int_status_t
@@ -1032,35 +1132,23 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
int tx, ty;
attr->acquired = FALSE;
- attr->clip_saved = FALSE;
if (_cairo_surface_is_image (dst))
{
cairo_image_surface_t *image;
- status = _cairo_surface_begin_reset_clip (pattern->surface);
- if (!CAIRO_OK (status))
- return status;
-
status = _cairo_surface_acquire_source_image (pattern->surface,
&image,
&attr->extra);
- if (!CAIRO_OK (status))
+ if (status)
return status;
- _cairo_surface_end (pattern->surface);
-
*out = &image->base;
attr->acquired = TRUE;
}
else
{
- status = _cairo_surface_begin_reset_clip (pattern->surface);
- if (!CAIRO_OK (status))
- return status;
-
status = _cairo_surface_clone_similar (dst, pattern->surface, out);
- _cairo_surface_end (pattern->surface);
}
attr->extend = pattern->base.extend;
@@ -1111,6 +1199,9 @@ _cairo_pattern_acquire_surface (cairo_pattern_t *pattern,
{
cairo_status_t status;
+ if (pattern->status)
+ return pattern->status;
+
switch (pattern->type) {
case CAIRO_PATTERN_SOLID: {
cairo_solid_pattern_t *src = (cairo_solid_pattern_t *) pattern;
@@ -1144,11 +1235,13 @@ _cairo_pattern_acquire_surface (cairo_pattern_t *pattern,
attributes);
}
else
+ {
status = _cairo_pattern_acquire_surface_for_gradient (src, dst,
x, y,
width, height,
surface_out,
attributes);
+ }
} break;
case CAIRO_PATTERN_SURFACE: {
cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) pattern;
@@ -1162,17 +1255,6 @@ _cairo_pattern_acquire_surface (cairo_pattern_t *pattern,
status = CAIRO_INT_STATUS_UNSUPPORTED;
}
-
- if (CAIRO_OK (status) && (*surface_out)->clip_region) {
- status = _cairo_surface_begin_reset_clip (*surface_out);
- if (!CAIRO_OK (status)) {
- _cairo_pattern_release_surface (dst, *surface_out, attributes);
- return status;
- }
-
- attributes->clip_saved = TRUE;
- }
-
return status;
}
@@ -1189,16 +1271,16 @@ _cairo_pattern_release_surface (cairo_surface_t *dst,
cairo_surface_t *surface,
cairo_surface_attributes_t *attributes)
{
- if (attributes->clip_saved)
- _cairo_surface_end (surface);
-
if (attributes->acquired)
{
_cairo_surface_release_source_image (dst,
(cairo_image_surface_t *) surface,
attributes->extra);
- } else
+ }
+ else
+ {
cairo_surface_destroy (surface);
+ }
}
cairo_int_status_t
@@ -1219,6 +1301,11 @@ _cairo_pattern_acquire_surfaces (cairo_pattern_t *src,
cairo_int_status_t status;
cairo_pattern_union_t tmp;
+ if (src->status)
+ return src->status;
+ if (mask && mask->status)
+ return mask->status;
+
/* If src and mask are both solid, then the mask alpha can be
* combined into src and mask can be ignored. */
@@ -1227,7 +1314,7 @@ _cairo_pattern_acquire_surfaces (cairo_pattern_t *src,
* support RENDER-style 4-channel masks. */
if (src->type == CAIRO_PATTERN_SOLID &&
mask && mask->type == CAIRO_PATTERN_SOLID)
- {
+ {
cairo_color_t combined;
cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src;
cairo_solid_pattern_t *mask_solid = (cairo_solid_pattern_t *) mask;
@@ -1238,7 +1325,9 @@ _cairo_pattern_acquire_surfaces (cairo_pattern_t *src,
_cairo_pattern_init_solid (&tmp.solid, &combined);
mask = NULL;
- } else {
+ }
+ else
+ {
_cairo_pattern_init_copy (&tmp.base, src);
}
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 228c2c89a..3d65aa75e 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -126,7 +126,7 @@ struct cairo_pdf_ft_font {
cairo_pdf_font_t base;
ft_subset_glyph_t *glyphs;
FT_Face face;
- unsigned long *checksum_location;
+ int checksum_index;
cairo_array_t output;
int *parent_to_subset;
cairo_status_t status;
@@ -188,6 +188,7 @@ struct cairo_pdf_surface {
cairo_array_t streams;
cairo_array_t alphas;
cairo_array_t fonts;
+ cairo_bool_t has_clip;
};
#define DEFAULT_DPI 300
@@ -291,6 +292,9 @@ cairo_pdf_font_generate (cairo_pdf_font_t *font,
static void
cairo_pdf_font_destroy (cairo_pdf_font_t *font)
{
+ if (font == NULL)
+ return;
+
font->backend->destroy (font);
}
@@ -378,6 +382,9 @@ cairo_pdf_ft_font_destroy (void *abstract_font)
{
cairo_pdf_ft_font_t *font = abstract_font;
+ if (font == NULL)
+ return;
+
_cairo_unscaled_font_destroy (font->base.unscaled_font);
free (font->base.base_font);
free (font->parent_to_subset);
@@ -505,8 +512,7 @@ cairo_pdf_ft_font_write_glyf_table (cairo_pdf_ft_font_t *font,
if (header->Index_To_Loc_Format == 0) {
begin = be16_to_cpu (u.short_offsets[index]) * 2;
end = be16_to_cpu (u.short_offsets[index + 1]) * 2;
- }
- else {
+ } else {
begin = be32_to_cpu (u.long_offsets[index]);
end = be32_to_cpu (u.long_offsets[index + 1]);
}
@@ -541,9 +547,7 @@ cairo_pdf_ft_font_write_head_table (cairo_pdf_ft_font_t *font,
cairo_pdf_ft_font_write_be32 (font, head->Table_Version);
cairo_pdf_ft_font_write_be32 (font, head->Font_Revision);
- font->checksum_location =
- (unsigned long *) _cairo_array_index (&font->output, 0) +
- _cairo_array_num_elements (&font->output) / sizeof (long);
+ font->checksum_index = _cairo_array_num_elements (&font->output);
cairo_pdf_ft_font_write_be32 (font, 0);
cairo_pdf_ft_font_write_be32 (font, head->Magic_Number);
@@ -633,8 +637,7 @@ cairo_pdf_ft_font_write_loca_table (cairo_pdf_ft_font_t *font,
if (header->Index_To_Loc_Format == 0) {
for (i = 0; i < font->base.num_glyphs + 1; i++)
cairo_pdf_ft_font_write_be16 (font, font->glyphs[i].location / 2);
- }
- else {
+ } else {
for (i = 0; i < font->base.num_glyphs + 1; i++)
cairo_pdf_ft_font_write_be32 (font, font->glyphs[i].location);
}
@@ -754,6 +757,7 @@ cairo_pdf_ft_font_generate (void *abstract_font,
{
cairo_pdf_ft_font_t *font = abstract_font;
unsigned long start, end, next, checksum;
+ unsigned long *checksum_location;
int i;
font->face = _cairo_ft_unscaled_font_lock_face (font->base.unscaled_font);
@@ -778,7 +782,8 @@ cairo_pdf_ft_font_generate (void *abstract_font,
checksum =
0xb1b0afba - cairo_pdf_ft_font_calculate_checksum (font, 0, end);
- *font->checksum_location = cpu_to_be32 (checksum);
+ checksum_location = _cairo_array_index (&font->output, font->checksum_index);
+ *checksum_location = cpu_to_be32 (checksum);
*data = _cairo_array_index (&font->output, 0);
*length = _cairo_array_num_elements (&font->output);
@@ -985,6 +990,7 @@ _cairo_pdf_surface_create_for_document (cairo_pdf_document_t *document,
_cairo_array_init (&surface->xobjects, sizeof (cairo_pdf_resource_t));
_cairo_array_init (&surface->alphas, sizeof (double));
_cairo_array_init (&surface->fonts, sizeof (cairo_pdf_resource_t));
+ surface->has_clip = FALSE;
return &surface->base;
}
@@ -1011,7 +1017,6 @@ _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
static cairo_surface_t *
_cairo_pdf_surface_create_similar (void *abstract_src,
cairo_format_t format,
- int drawable,
int width,
int height)
{
@@ -1225,7 +1230,7 @@ _cairo_pdf_surface_composite_image (cairo_pdf_surface_t *dst,
src = pattern->surface;
status = _cairo_surface_acquire_source_image (src, &image, &image_extra);
- if (!CAIRO_OK (status))
+ if (status)
return status;
id = emit_image_data (dst->document, image);
@@ -1281,7 +1286,7 @@ _cairo_pdf_surface_composite_pdf (cairo_pdf_surface_t *dst,
src = (cairo_pdf_surface_t *) pattern->surface;
- i2u = src->base.matrix;
+ i2u = pattern->base.matrix;
cairo_matrix_invert (&i2u);
cairo_matrix_scale (&i2u, 1.0 / src->width, 1.0 / src->height);
@@ -1400,7 +1405,7 @@ emit_surface_pattern (cairo_pdf_surface_t *dst,
}
status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
- if (!CAIRO_OK (status))
+ if (status)
return;
_cairo_pdf_document_close_stream (document);
@@ -1635,6 +1640,7 @@ intersect (cairo_line_t *line, cairo_fixed_t y)
typedef struct
{
cairo_output_stream_t *output_stream;
+ cairo_bool_t has_current_point;
} pdf_path_info_t;
static cairo_status_t
@@ -1646,6 +1652,7 @@ _cairo_pdf_path_move_to (void *closure, cairo_point_t *point)
"%f %f m ",
_cairo_fixed_to_double (point->x),
_cairo_fixed_to_double (point->y));
+ info->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}
@@ -1654,11 +1661,19 @@ static cairo_status_t
_cairo_pdf_path_line_to (void *closure, cairo_point_t *point)
{
pdf_path_info_t *info = closure;
+ const char *pdf_operator;
+
+ if (info->has_current_point)
+ pdf_operator = "l";
+ else
+ pdf_operator = "m";
_cairo_output_stream_printf (info->output_stream,
- "%f %f l ",
+ "%f %f %s ",
_cairo_fixed_to_double (point->x),
- _cairo_fixed_to_double (point->y));
+ _cairo_fixed_to_double (point->y),
+ pdf_operator);
+ info->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}
@@ -1690,6 +1705,7 @@ _cairo_pdf_path_close_path (void *closure)
_cairo_output_stream_printf (info->output_stream,
"h\r\n");
+ info->has_current_point = FALSE;
return CAIRO_STATUS_SUCCESS;
}
@@ -1698,15 +1714,16 @@ static cairo_int_status_t
_cairo_pdf_surface_fill_path (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_dst,
- cairo_path_fixed_t *path)
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance)
{
cairo_pdf_surface_t *surface = abstract_dst;
cairo_pdf_document_t *document = surface->document;
+ const char *pdf_operator;
cairo_status_t status;
pdf_path_info_t info;
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
emit_pattern (surface, pattern);
/* After the above switch the current stream should belong to this
@@ -1715,6 +1732,7 @@ _cairo_pdf_surface_fill_path (cairo_operator_t operator,
document->current_stream == surface->current_stream);
info.output_stream = document->output_stream;
+ info.has_current_point = FALSE;
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
@@ -1724,8 +1742,20 @@ _cairo_pdf_surface_fill_path (cairo_operator_t operator,
_cairo_pdf_path_close_path,
&info);
+ switch (fill_rule) {
+ 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 (document->output_stream,
- "f\r\n");
+ "%s\r\n",
+ pdf_operator);
return status;
}
@@ -1794,10 +1824,12 @@ _cairo_pdf_surface_show_page (void *abstract_surface)
cairo_int_status_t status;
status = _cairo_pdf_document_add_page (document, surface);
- if (status == CAIRO_STATUS_SUCCESS)
- _cairo_pdf_surface_clear (surface);
+ if (status)
+ return status;
- return status;
+ _cairo_pdf_surface_clear (surface);
+
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
@@ -1886,7 +1918,7 @@ _cairo_pdf_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
" %f %f %f %f %f %f Tm (\\%o) Tj",
scaled_font->scale.xx,
scaled_font->scale.yx,
- scaled_font->scale.xy,
+ -scaled_font->scale.xy,
-scaled_font->scale.yy,
glyphs[i].x,
glyphs[i].y,
@@ -1900,6 +1932,62 @@ _cairo_pdf_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
return CAIRO_STATUS_SUCCESS;
}
+static cairo_int_status_t
+_cairo_pdf_surface_intersect_clip_path (void *dst,
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance)
+{
+ cairo_pdf_surface_t *surface = dst;
+ cairo_pdf_document_t *document = surface->document;
+ cairo_output_stream_t *output = document->output_stream;
+ cairo_status_t status;
+ pdf_path_info_t info;
+ const char *pdf_operator;
+
+ _cairo_pdf_surface_ensure_stream (surface);
+
+ if (path == NULL) {
+ if (surface->has_clip)
+ _cairo_output_stream_printf (output, "Q\r\n");
+ surface->has_clip = FALSE;
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ if (!surface->has_clip) {
+ _cairo_output_stream_printf (output, "q ");
+ surface->has_clip = TRUE;
+ }
+
+ info.output_stream = document->output_stream;
+ info.has_current_point = FALSE;
+
+ status = _cairo_path_fixed_interpret (path,
+ CAIRO_DIRECTION_FORWARD,
+ _cairo_pdf_path_move_to,
+ _cairo_pdf_path_line_to,
+ _cairo_pdf_path_curve_to,
+ _cairo_pdf_path_close_path,
+ &info);
+
+ switch (fill_rule) {
+ 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 (document->output_stream,
+ "%s n\r\n",
+ pdf_operator);
+
+ return status;
+}
+
static const cairo_surface_backend_t cairo_pdf_surface_backend = {
_cairo_pdf_surface_create_similar,
_cairo_pdf_surface_finish,
@@ -1914,6 +2002,7 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
_cairo_pdf_surface_copy_page,
_cairo_pdf_surface_show_page,
NULL, /* set_clip_region */
+ _cairo_pdf_surface_intersect_clip_path,
_cairo_pdf_surface_get_extents,
_cairo_pdf_surface_show_glyphs,
_cairo_pdf_surface_fill_path
@@ -2232,6 +2321,11 @@ _cairo_pdf_document_add_page (cairo_pdf_document_t *document,
assert (!document->finished);
+ _cairo_pdf_surface_ensure_stream (surface);
+
+ if (surface->has_clip)
+ _cairo_output_stream_printf (output, "Q\r\n");
+
_cairo_pdf_document_close_stream (document);
page_id = _cairo_pdf_document_new_object (document);
diff --git a/src/cairo-png.c b/src/cairo-png.c
index ecb23ca45..d7297848d 100644
--- a/src/cairo-png.c
+++ b/src/cairo-png.c
@@ -212,7 +212,7 @@ cairo_surface_write_to_png (cairo_surface_t *surface,
status = write_png (surface, stdio_write_func, fp);
- if (fclose (fp) && CAIRO_OK (status))
+ if (fclose (fp) && status == CAIRO_STATUS_SUCCESS)
status = CAIRO_STATUS_WRITE_ERROR;
return status;
@@ -226,10 +226,12 @@ struct png_write_closure_t {
static void
stream_write_func (png_structp png, png_bytep data, png_size_t size)
{
+ cairo_status_t status;
struct png_write_closure_t *png_closure;
png_closure = png_get_io_ptr (png);
- if (!CAIRO_OK (png_closure->write_func (png_closure->closure, data, size)))
+ status = png_closure->write_func (png_closure->closure, data, size);
+ if (status)
png_error(png, "Write Error");
}
@@ -432,10 +434,12 @@ struct png_read_closure_t {
static void
stream_read_func (png_structp png, png_bytep data, png_size_t size)
{
+ cairo_status_t status;
struct png_read_closure_t *png_closure;
png_closure = png_get_io_ptr (png);
- if (!CAIRO_OK (png_closure->read_func (png_closure->closure, data, size)))
+ status = png_closure->read_func (png_closure->closure, data, size);
+ if (status)
png_error(png, "Read Error");
}
diff --git a/src/cairo-private.h b/src/cairo-private.h
index a43c8ef7f..7051f7ebd 100644
--- a/src/cairo-private.h
+++ b/src/cairo-private.h
@@ -42,10 +42,11 @@
struct _cairo {
unsigned int ref_count;
- cairo_gstate_t *gstate;
+ cairo_status_t status;
+
cairo_path_fixed_t path;
- cairo_status_t status;
+ cairo_gstate_t *gstate;
};
#endif /* CAIRO_PRIVATE_H */
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index a79703e1d..dd12c2ca5 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -159,7 +159,6 @@ cairo_ps_surface_create_for_stream (cairo_write_func_t write_func,
static cairo_surface_t *
_cairo_ps_surface_create_similar (void *abstract_src,
cairo_format_t format,
- int drawable,
int width,
int height)
{
@@ -373,6 +372,7 @@ static const cairo_surface_backend_t cairo_ps_surface_backend = {
_cairo_ps_surface_copy_page,
_cairo_ps_surface_show_page,
_cairo_ps_surface_set_clip_region,
+ NULL, /* intersect_clip_path */
_cairo_ps_surface_get_extents,
NULL /* show_glyphs */
};
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 292f5b491..566842515 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -62,7 +62,6 @@ static cairo_surface_t *_cairo_quartz_surface_create_similar(void
*abstract_src,
cairo_format_t
format,
- int drawable,
int width,
int height)
{
@@ -227,6 +226,7 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
NULL, /* copy_page */
NULL, /* show_page */
_cairo_quartz_surface_set_clip_region,
+ NULL, /* intersect_clip_path */
_cairo_quartz_surface_get_extents,
NULL /* show_glyphs */
};
diff --git a/src/cairo-spline.c b/src/cairo-spline.c
index 5119a8e2b..60ad6c54d 100644
--- a/src/cairo-spline.c
+++ b/src/cairo-spline.c
@@ -64,23 +64,21 @@ _cairo_spline_init (cairo_spline_t *spline,
spline->c = *c;
spline->d = *d;
- if (a->x != b->x || a->y != b->y) {
+ if (a->x != b->x || a->y != b->y)
_cairo_slope_init (&spline->initial_slope, &spline->a, &spline->b);
- } else if (a->x != c->x || a->y != c->y) {
+ else if (a->x != c->x || a->y != c->y)
_cairo_slope_init (&spline->initial_slope, &spline->a, &spline->c);
- } else if (a->x != d->x || a->y != d->y) {
+ else if (a->x != d->x || a->y != d->y)
_cairo_slope_init (&spline->initial_slope, &spline->a, &spline->d);
- } else {
+ else
return CAIRO_INT_STATUS_DEGENERATE;
- }
- if (c->x != d->x || c->y != d->y) {
+ if (c->x != d->x || c->y != d->y)
_cairo_slope_init (&spline->final_slope, &spline->c, &spline->d);
- } else if (b->x != d->x || b->y != d->y) {
+ else if (b->x != d->x || b->y != d->y)
_cairo_slope_init (&spline->final_slope, &spline->b, &spline->d);
- } else {
+ else
_cairo_slope_init (&spline->final_slope, &spline->a, &spline->d);
- }
spline->num_points = 0;
spline->points_size = 0;
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 0bcf80cf8..318ee87d9 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -38,17 +38,7 @@
#include <stdlib.h>
#include "cairoint.h"
-
-struct _cairo_surface_save {
- cairo_surface_save_t *next;
- pixman_region16_t *clip_region;
-};
-
-static cairo_status_t
-_cairo_surface_set_clip_region_internal (cairo_surface_t *surface,
- pixman_region16_t *region,
- cairo_bool_t copy_region,
- cairo_bool_t free_existing);
+#include "cairo-gstate-private.h"
void
_cairo_surface_init (cairo_surface_t *surface,
@@ -61,131 +51,23 @@ _cairo_surface_init (cairo_surface_t *surface,
_cairo_user_data_array_init (&surface->user_data);
- cairo_matrix_init_identity (&surface->matrix);
- surface->filter = CAIRO_FILTER_GOOD;
- surface->repeat = 0;
-
surface->device_x_offset = 0;
surface->device_y_offset = 0;
- surface->clip_region = NULL;
-
- surface->saves = NULL;
- surface->level = 0;
-}
-
-static cairo_status_t
-_cairo_surface_begin_internal (cairo_surface_t *surface,
- cairo_bool_t reset_clip)
-{
- cairo_surface_save_t *save;
-
- if (surface->finished)
- return CAIRO_STATUS_SURFACE_FINISHED;
-
- save = malloc (sizeof (cairo_surface_save_t));
- if (!save)
- return CAIRO_STATUS_NO_MEMORY;
-
- if (surface->clip_region) {
- if (reset_clip)
- {
- cairo_status_t status;
-
- save->clip_region = surface->clip_region;
- status = _cairo_surface_set_clip_region_internal (surface, NULL, FALSE, FALSE);
- if (!CAIRO_OK (status)) {
- free (save);
- return status;
- }
- }
- else
- {
- save->clip_region = pixman_region_create ();
- pixman_region_copy (save->clip_region, surface->clip_region);
- }
- } else {
- save->clip_region = NULL;
- }
-
- save->next = surface->saves;
- surface->saves = save;
- surface->level++;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-/**
- * _cairo_surface_begin:
- * @surface: a #cairo_surface_t
- *
- * Must be called before beginning to use the surface. State
- * of the surface like the clip region will be saved then restored
- * on the matching call _cairo_surface_end().
- */
-cairo_private cairo_status_t
-_cairo_surface_begin (cairo_surface_t *surface)
-{
- return _cairo_surface_begin_internal (surface, FALSE);
-}
-
-/**
- * _cairo_surface_begin_reset_clip:
- * @surface: a #cairo_surface_t
- *
- * Must be called before beginning to use the surface. State
- * of the surface like the clip region will be saved then restored
- * on the matching call _cairo_surface_end().
- *
- * After the state is saved, the clip region is cleared. This
- * combination of operations is a little artificial; the caller could
- * simply call _cairo_surface_set_clip_region (surface, NULL); after
- * _cairo_surface_save(). Combining the two saves a copy of the clip
- * region, and also simplifies error handling for the caller.
- **/
-cairo_private cairo_status_t
-_cairo_surface_begin_reset_clip (cairo_surface_t *surface)
-{
- return _cairo_surface_begin_internal (surface, TRUE);
-}
-
-/**
- * _cairo_surface_end:
- * @surface: a #cairo_surface_t
- *
- * Restores any state saved by _cairo_surface_begin()
- **/
-cairo_private cairo_status_t
-_cairo_surface_end (cairo_surface_t *surface)
-{
- cairo_surface_save_t *save;
- pixman_region16_t *clip_region;
-
- if (!surface->saves)
- return CAIRO_STATUS_BAD_NESTING;
-
- save = surface->saves;
- surface->saves = save->next;
- surface->level--;
-
- clip_region = save->clip_region;
- free (save);
-
- return _cairo_surface_set_clip_region_internal (surface, clip_region, FALSE, TRUE);
+ surface->next_clip_serial = 0;
+ surface->current_clip_serial = 0;
}
cairo_surface_t *
_cairo_surface_create_similar_scratch (cairo_surface_t *other,
cairo_format_t format,
- int drawable,
int width,
int height)
{
if (other == NULL)
return NULL;
- return other->backend->create_similar (other, format, drawable,
- width, height);
+ return other->backend->create_similar (other, format, width, height);
}
cairo_surface_t *
@@ -212,7 +94,7 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other,
cairo_status_t status;
cairo_surface_t *surface;
- surface = _cairo_surface_create_similar_scratch (other, format, 1,
+ surface = _cairo_surface_create_similar_scratch (other, format,
width, height);
if (surface == NULL)
@@ -229,6 +111,17 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other,
return surface;
}
+cairo_clip_mode_t
+_cairo_surface_get_clip_mode (cairo_surface_t *surface)
+{
+ if (surface->backend->intersect_clip_path != NULL)
+ return CAIRO_CLIP_MODE_PATH;
+ else if (surface->backend->set_clip_region != NULL)
+ return CAIRO_CLIP_MODE_REGION;
+ else
+ return CAIRO_CLIP_MODE_MASK;
+}
+
void
cairo_surface_reference (cairo_surface_t *surface)
{
@@ -250,7 +143,7 @@ cairo_surface_destroy (cairo_surface_t *surface)
cairo_surface_finish (surface);
- _cairo_user_data_array_destroy (&surface->user_data);
+ _cairo_user_data_array_fini (&surface->user_data);
free (surface);
}
@@ -286,14 +179,6 @@ cairo_surface_finish (cairo_surface_t *surface)
if (surface->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
- if (surface->saves)
- return CAIRO_STATUS_BAD_NESTING;
-
- if (surface->clip_region) {
- pixman_region_destroy (surface->clip_region);
- surface->clip_region = NULL;
- }
-
if (surface->backend->finish) {
status = surface->backend->finish (surface);
if (status)
@@ -521,7 +406,7 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
if (surface->backend->clone_similar) {
status = surface->backend->clone_similar (surface, src, clone_out);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
+ return status;
}
status = _cairo_surface_acquire_source_image (src, &image, &image_extra);
@@ -592,7 +477,7 @@ _fallback_composite (cairo_operator_t operator,
cairo_status_t status;
status = _fallback_init (&state, dst, dst_x, dst_y, width, height);
- if (!CAIRO_OK (status) || !state.image)
+ if (status || !state.image)
return status;
state.image->base.backend->composite (operator, src, mask,
@@ -704,7 +589,7 @@ _fallback_fill_rectangles (cairo_surface_t *surface,
}
status = _fallback_init (&state, surface, x1, y1, x2 - x1, y2 - y1);
- if (!CAIRO_OK (status) || !state.image)
+ if (status || !state.image)
return status;
/* If the fetched image isn't at 0,0, we need to offset the rectangles */
@@ -766,13 +651,16 @@ _cairo_surface_fill_rectangles (cairo_surface_t *surface,
}
cairo_private cairo_int_status_t
-_cairo_surface_fill_path (cairo_operator_t operator,
- cairo_pattern_t *pattern,
- cairo_surface_t *dst,
- cairo_path_fixed_t *path)
+_cairo_surface_fill_path (cairo_operator_t operator,
+ cairo_pattern_t *pattern,
+ cairo_surface_t *dst,
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance)
{
if (dst->backend->fill_path)
- return dst->backend->fill_path (operator, pattern, dst, path);
+ return dst->backend->fill_path (operator, pattern, dst, path,
+ fill_rule, tolerance);
else
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@@ -797,7 +685,7 @@ _fallback_composite_trapezoids (cairo_operator_t operator,
int i;
status = _fallback_init (&state, dst, dst_x, dst_y, width, height);
- if (!CAIRO_OK (status) || !state.image)
+ if (status || !state.image)
return status;
/* If the destination image isn't at 0,0, we need to offset the trapezoids */
@@ -907,62 +795,180 @@ _cairo_surface_show_page (cairo_surface_t *surface)
return surface->backend->show_page (surface);
}
-static cairo_status_t
-_cairo_surface_set_clip_region_internal (cairo_surface_t *surface,
- pixman_region16_t *region,
- cairo_bool_t copy_region,
- cairo_bool_t free_existing)
+/**
+ * _cairo_surface_get_current_clip_serial:
+ * @surface: the #cairo_surface_t to return the serial number for
+ *
+ * Returns the serial number associated with the current
+ * clip in the surface. All gstate functions must
+ * verify that the correct clip is set in the surface before
+ * invoking any surface drawing function
+ */
+cairo_private unsigned int
+_cairo_surface_get_current_clip_serial (cairo_surface_t *surface)
+{
+ return surface->current_clip_serial;
+}
+
+/**
+ * _cairo_surface_allocate_clip_serial:
+ * @surface: the #cairo_surface_t to allocate a serial number from
+ *
+ * Each surface has a separate set of clipping serial numbers,
+ * and this function allocates one from the specified surface.
+ * As zero is reserved for the special no-clipping case,
+ * this function will not return that.
+ */
+cairo_private unsigned int
+_cairo_surface_allocate_clip_serial (cairo_surface_t *surface)
+{
+ unsigned int serial;
+
+ if ((serial = ++(surface->next_clip_serial)) == 0)
+ serial = ++(surface->next_clip_serial);
+ return serial;
+}
+
+/**
+ * _cairo_surface_reset_clip:
+ * @surface: the #cairo_surface_t to reset the clip on
+ *
+ * This function sets the clipping for the surface to
+ * None, which is to say that drawing is entirely
+ * unclipped. It also sets the clip serial number
+ * to zero.
+ */
+cairo_private cairo_status_t
+_cairo_surface_reset_clip (cairo_surface_t *surface)
{
+ cairo_status_t status;
+
if (surface->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
-
- if (region == surface->clip_region)
- return CAIRO_STATUS_SUCCESS;
- if (surface->backend->set_clip_region == NULL)
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ surface->current_clip_serial = 0;
- if (surface->clip_region) {
- if (free_existing)
- pixman_region_destroy (surface->clip_region);
- surface->clip_region = NULL;
+ if (surface->backend->intersect_clip_path) {
+ status = surface->backend->intersect_clip_path (surface,
+ NULL,
+ CAIRO_FILL_RULE_WINDING,
+ 0);
+ if (status)
+ return status;
}
- if (region) {
- if (copy_region) {
- surface->clip_region = pixman_region_create ();
- pixman_region_copy (surface->clip_region, region);
- } else
- surface->clip_region = region;
+ if (surface->backend->set_clip_region != NULL) {
+ status = surface->backend->set_clip_region (surface, NULL);
+ if (status)
+ return status;
}
+ return CAIRO_STATUS_SUCCESS;
+}
+
+/**
+ * _cairo_surface_set_clip_region:
+ * @surface: the #cairo_surface_t to reset the clip on
+ * @region: the #pixman_region16_t to use for clipping
+ * @serial: the clip serial number associated with the region
+ *
+ * This function sets the clipping for the surface to
+ * the specified region and sets the surface clipping
+ * serial number to the associated serial number.
+ */
+cairo_private cairo_status_t
+_cairo_surface_set_clip_region (cairo_surface_t *surface,
+ pixman_region16_t *region,
+ unsigned int serial)
+{
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
+ assert (surface->backend->set_clip_region != NULL);
+
+ surface->current_clip_serial = serial;
return surface->backend->set_clip_region (surface, region);
}
-cairo_status_t
-_cairo_surface_set_clip_region (cairo_surface_t *surface,
- pixman_region16_t *region)
+static cairo_status_t
+_cairo_surface_set_clip_path_recursive (cairo_surface_t *surface,
+ cairo_clip_path_t *clip_path)
{
- return _cairo_surface_set_clip_region_internal (surface, region, TRUE, TRUE);
+ cairo_status_t status;
+
+ if (clip_path == NULL)
+ return CAIRO_STATUS_SUCCESS;
+
+ status = _cairo_surface_set_clip_path_recursive (surface, clip_path->prev);
+ if (status)
+ return status;
+
+ return surface->backend->intersect_clip_path (surface,
+ &clip_path->path,
+ clip_path->fill_rule,
+ clip_path->tolerance);
}
-cairo_status_t
-_cairo_surface_get_clip_extents (cairo_surface_t *surface,
- cairo_rectangle_t *rectangle)
+
+/**
+ * _cairo_surface_set_clip_path:
+ * @surface: the #cairo_surface_t to reset the clip on
+ * @path: the path to intersect against the current clipping path
+ * @fill_rule: fill rule to use for clipping
+ * @tolerance: tesselation to use for tesselating clipping path
+ * @serial: the clip serial number associated with the region
+ *
+ * Sets the clipping path to be the intersection of the current
+ * clipping path of the surface and the given path.
+ **/
+cairo_private cairo_status_t
+_cairo_surface_set_clip_path (cairo_surface_t *surface,
+ cairo_clip_path_t *clip_path,
+ unsigned int serial)
{
+ cairo_status_t status;
+
if (surface->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
- if (surface->clip_region) {
- pixman_box16_t *box = pixman_region_extents (surface->clip_region);
+ assert (surface->backend->intersect_clip_path != NULL);
- rectangle->x = box->x1;
- rectangle->y = box->y1;
- rectangle->width = box->x2 - box->x1;
- rectangle->height = box->y2 - box->y1;
-
- return CAIRO_STATUS_SUCCESS;
- }
+ status = surface->backend->intersect_clip_path (surface,
+ NULL,
+ CAIRO_FILL_RULE_WINDING,
+ 0);
+ if (status)
+ return status;
+
+ status = _cairo_surface_set_clip_path_recursive (surface, clip_path);
+ if (status)
+ return status;
+
+ surface->current_clip_serial = serial;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+/**
+ * _cairo_surface_get_extents:
+ * @surface: the #cairo_surface_t to fetch extents for
+ *
+ * This function returns a bounding box for the surface. The
+ * surface bounds are defined as a region beyond which no
+ * rendering will possibly be recorded, in otherwords,
+ * it is the maximum extent of potentially usable
+ * coordinates. For simple pixel-based surfaces,
+ * it can be a close bound on the retained pixel
+ * region. For virtual surfaces (PDF et al), it
+ * cannot and must extend to the reaches of the
+ * target system coordinate space.
+ */
+
+cairo_status_t
+_cairo_surface_get_extents (cairo_surface_t *surface,
+ cairo_rectangle_t *rectangle)
+{
+ if (surface->finished)
+ return CAIRO_STATUS_SURFACE_FINISHED;
return surface->backend->get_extents (surface, rectangle);
}
diff --git a/src/cairo-traps.c b/src/cairo-traps.c
index 15dfc1bca..a97d58481 100644
--- a/src/cairo-traps.c
+++ b/src/cairo-traps.c
@@ -820,7 +820,7 @@ _cairo_traps_extract_region (cairo_traps_t *traps,
int width = _cairo_fixed_integer_part(traps->traps[i].right.p1.x) - x;
int height = _cairo_fixed_integer_part(traps->traps[i].left.p2.y) - y;
- /* Sometimes we get degenerate trapezoids from the tesellator,
+ /* XXX: Sometimes we get degenerate trapezoids from the tesellator,
* if we call pixman_region_union_rect(), it bizarrly fails on such
* an empty rectangle, so skip them.
*/
diff --git a/src/cairo-wideint.c b/src/cairo-wideint.c
index 953108339..60946d90b 100644
--- a/src/cairo-wideint.c
+++ b/src/cairo-wideint.c
@@ -1,5 +1,5 @@
/*
- * $Id: cairo-wideint.c,v 1.4 2005-01-19 15:07:00 cworth Exp $
+ * $Id: cairo-wideint.c,v 1.5 2005-06-03 21:51:57 cworth Exp $
*
* Copyright © 2004 Keith Packard
*
@@ -421,7 +421,9 @@ _cairo_uint64_divrem (cairo_uint64_t num, cairo_uint64_t den)
num = _cairo_uint64_sub (num, den);
}
else
+ {
q0 = 0;
+ }
q1 = 0;
r0 = num.lo;
@@ -937,7 +939,9 @@ _cairo_uint128_divrem (cairo_uint128_t num, cairo_uint128_t den)
num = _cairo_uint128_sub (num, den);
}
else
+ {
q0 = _cairo_uint32_to_uint64 (0);
+ }
q1 = _cairo_uint32_to_uint64 (0);
r0 = num.lo;
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 78b3ca212..eef2b4e72 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -104,6 +104,8 @@ static void
_compute_transform (cairo_win32_scaled_font_t *scaled_font,
cairo_matrix_t *sc)
{
+ cairo_status_t status;
+
if (NEARLY_ZERO (sc->yx) && NEARLY_ZERO (sc->xy)) {
scaled_font->preserve_axes = TRUE;
scaled_font->x_scale = sc->xx;
@@ -154,8 +156,10 @@ _compute_transform (cairo_win32_scaled_font_t *scaled_font,
1.0 / scaled_font->logical_scale, 1.0 / scaled_font->logical_scale);
scaled_font->device_to_logical = scaled_font->logical_to_device;
- if (!CAIRO_OK (cairo_matrix_invert (&scaled_font->device_to_logical)))
- cairo_matrix_init_identity (&scaled_font->device_to_logical);
+
+ status = cairo_matrix_invert (&scaled_font->device_to_logical);
+ if (status)
+ cairo_matrix_init_identity (&scaled_font->device_to_logical);
}
static BYTE
@@ -194,8 +198,9 @@ _get_system_quality (void)
}
return ANTIALIASED_QUALITY;
- } else
+ } else {
return DEFAULT_QUALITY;
+ }
}
static cairo_scaled_font_t *
@@ -367,7 +372,7 @@ _cairo_win32_scaled_font_select_unscaled_font (cairo_scaled_font_t *scaled_font,
return _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_select_unscaled_font");
status = _win32_scaled_font_set_identity_transform (hdc);
- if (!CAIRO_OK (status)) {
+ if (status) {
SelectObject (hdc, old_hfont);
return status;
}
@@ -399,7 +404,7 @@ _cairo_win32_scaled_font_create (const char *family,
cairo_status_t status;
status = _cairo_utf8_to_utf16 (family, -1, &face_name, &face_name_len);
- if (!CAIRO_OK (status))
+ if (status)
return status;
if (face_name_len > LF_FACESIZE - 1) {
@@ -465,6 +470,9 @@ _cairo_win32_scaled_font_destroy (void *abstract_font)
{
cairo_win32_scaled_font_t *scaled_font = abstract_font;
+ if (scaled_font == NULL)
+ return;
+
if (scaled_font->scaled_hfont)
DeleteObject (scaled_font->scaled_hfont);
@@ -496,7 +504,7 @@ _cairo_win32_scaled_font_text_to_glyphs (void *abstract_font,
HDC hdc = NULL;
status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16);
- if (!CAIRO_OK (status))
+ if (status)
return status;
gcp_results.lStructSize = sizeof (GCP_RESULTS);
@@ -518,7 +526,7 @@ _cairo_win32_scaled_font_text_to_glyphs (void *abstract_font,
}
status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
- if (!CAIRO_OK (status))
+ if (status)
goto FAIL1;
while (TRUE) {
@@ -610,7 +618,7 @@ _cairo_win32_scaled_font_font_extents (void *abstract_font,
* from the GDI in logical space, then convert back to font space
*/
status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
- if (!CAIRO_OK (status))
+ if (status)
return status;
GetTextMetrics (hdc, &metrics);
cairo_win32_scaled_font_done_font (&scaled_font->base);
@@ -629,7 +637,7 @@ _cairo_win32_scaled_font_font_extents (void *abstract_font,
* avoid them.
*/
status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
- if (!CAIRO_OK (status))
+ if (status)
return status;
GetTextMetrics (hdc, &metrics);
_cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
@@ -672,7 +680,7 @@ _cairo_win32_scaled_font_glyph_extents (void *abstract_font,
* from the GDI in device space and convert to font space.
*/
status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
- if (!CAIRO_OK (status))
+ if (status)
return status;
GetGlyphOutlineW (hdc, glyphs[0].index, GGO_METRICS | GGO_GLYPH_INDEX,
&metrics, 0, NULL, &matrix);
@@ -714,7 +722,7 @@ _cairo_win32_scaled_font_glyph_extents (void *abstract_font,
_cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
extents->x_bearing = (double)metrics.gmptGlyphOrigin.x / scaled_font->em_square;
- extents->y_bearing = (double)metrics.gmptGlyphOrigin.y / scaled_font->em_square;
+ extents->y_bearing = - (double)metrics.gmptGlyphOrigin.y / scaled_font->em_square;
extents->width = (double)metrics.gmBlackBoxX / scaled_font->em_square;
extents->height = (double)metrics.gmBlackBoxY / scaled_font->em_square;
extents->x_advance = (double)metrics.gmCellIncX / scaled_font->em_square;
@@ -745,7 +753,7 @@ _cairo_win32_scaled_font_glyph_bbox (void *abstract_font,
return CAIRO_STATUS_NO_MEMORY;
status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
- if (!CAIRO_OK (status))
+ if (status)
return status;
for (i = 0; i < num_glyphs; i++) {
@@ -844,7 +852,7 @@ _add_glyph (cairo_glyph_state_t *state,
if (logical_y != state->last_y) {
cairo_status_t status = _flush_glyphs (state);
- if (!CAIRO_OK (status))
+ if (status)
return status;
state->start_x = logical_x;
}
@@ -890,7 +898,7 @@ _draw_glyphs_on_surface (cairo_win32_surface_t *surface,
return _cairo_win32_print_gdi_error ("_draw_glyphs_on_surface:SaveDC");
status = cairo_win32_scaled_font_select_font (&scaled_font->base, surface->dc);
- if (!CAIRO_OK (status))
+ if (status)
goto FAIL1;
SetTextColor (surface->dc, color);
@@ -902,7 +910,7 @@ _draw_glyphs_on_surface (cairo_win32_surface_t *surface,
for (i = 0; i < num_glyphs; i++) {
status = _add_glyph (&state, glyphs[i].index,
glyphs[i].x - x_offset, glyphs[i].y - y_offset);
- if (!CAIRO_OK (status))
+ if (status)
goto FAIL2;
}
@@ -1152,7 +1160,7 @@ static const cairo_font_face_backend_t _cairo_win32_font_face_backend = {
};
/**
- * cairo_win32_scaled_font_create_for_logfontw:
+ * cairo_win32_font_face_create_for_logfontw:
* @logfont: A #LOGFONTW structure specifying the font to use.
* The lfHeight, lfWidth, lfOrientation and lfEscapement
* fields of this structure are ignored.
@@ -1231,7 +1239,7 @@ cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font,
}
status = _win32_scaled_font_set_world_transform ((cairo_win32_scaled_font_t *)scaled_font, hdc);
- if (!CAIRO_OK (status)) {
+ if (status) {
SetGraphicsMode (hdc, old_mode);
SelectObject (hdc, old_hfont);
return status;
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 9df86380b..8d63adbf3 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -1,6 +1,6 @@
/* Cairo - a vector graphics library with display and print output
*
- * Copyright  2005 Red Hat, Inc.
+ * 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
@@ -292,7 +292,6 @@ _cairo_win32_surface_create_for_dc (HDC original_dc,
static cairo_surface_t *
_cairo_win32_surface_create_similar (void *abstract_src,
cairo_format_t format,
- int drawable,
int width,
int height)
{
@@ -359,7 +358,6 @@ _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface,
local =
(cairo_win32_surface_t *) _cairo_win32_surface_create_similar (surface,
surface->format,
- 0,
width, height);
if (!local)
return CAIRO_STATUS_NO_MEMORY;
@@ -404,12 +402,13 @@ _cairo_win32_surface_acquire_source_image (void *abstract_sur
status = _cairo_win32_surface_get_subimage (abstract_surface, 0, 0,
surface->clip_rect.width,
surface->clip_rect.height, &local);
- if (CAIRO_OK (status)) {
- *image_out = (cairo_image_surface_t *)local->image;
- *image_extra = local;
- }
+ if (status)
+ return status;
- return status;
+ *image_out = (cairo_image_surface_t *)local->image;
+ *image_extra = local;
+
+ return CAIRO_STATUS_SUCCESS;
}
static void
@@ -475,17 +474,18 @@ _cairo_win32_surface_acquire_dest_image (void *abstract_surfa
status = _cairo_win32_surface_get_subimage (abstract_surface,
x1, y1, x2 - x1, y2 - y1,
&local);
- if (CAIRO_OK (status)) {
- *image_out = (cairo_image_surface_t *)local->image;
- *image_extra = local;
-
- image_rect->x = x1;
- image_rect->y = y1;
- image_rect->width = x2 - x1;
- image_rect->height = y2 - y1;
- }
+ if (status)
+ return status;
- return status;
+ *image_out = (cairo_image_surface_t *)local->image;
+ *image_extra = local;
+
+ image_rect->x = x1;
+ image_rect->y = y1;
+ image_rect->width = x2 - x1;
+ image_rect->height = y2 - y1;
+
+ return CAIRO_STATUS_SUCCESS;
}
static void
@@ -941,6 +941,7 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = {
NULL, /* copy_page */
NULL, /* show_page */
_cairo_win32_surface_set_clip_region,
+ NULL, /* intersect_clip_path */
_cairo_win32_surface_get_extents,
NULL /* show_glyphs */
};
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 95568d608..4e3204452 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -229,7 +229,6 @@ _CAIRO_FORMAT_DEPTH (cairo_format_t format)
static cairo_surface_t *
_cairo_xcb_surface_create_similar (void *abstract_src,
cairo_format_t format,
- int drawable,
int width,
int height)
{
@@ -371,7 +370,7 @@ _get_image_surface (cairo_xcb_surface_t *surface,
rect.x = interest_rect->x;
rect.y = interest_rect->y;
rect.width = interest_rect->width;
- rect.height = interest_rect->width;
+ rect.height = interest_rect->height;
if (rect.x > x1)
x1 = rect.x;
@@ -521,9 +520,6 @@ _get_image_surface (cairo_xcb_surface_t *surface,
/* Let the surface take ownership of the data */
_cairo_image_surface_assume_ownership_of_data (image);
- _cairo_image_surface_set_repeat (image, surface->base.repeat);
- _cairo_image_surface_set_matrix (image, &(surface->base.matrix));
-
*image_out = image;
return CAIRO_STATUS_SUCCESS;
}
@@ -569,10 +565,12 @@ _cairo_xcb_surface_acquire_source_image (void *abstract_surfa
cairo_status_t status;
status = _get_image_surface (surface, NULL, &image, NULL);
- if (status == CAIRO_STATUS_SUCCESS)
- *image_out = image;
+ if (status)
+ return status;
- return status;
+ *image_out = image;
+
+ return CAIRO_STATUS_SUCCESS;
}
static void
@@ -595,10 +593,12 @@ _cairo_xcb_surface_acquire_dest_image (void *abstract_surface
cairo_status_t status;
status = _get_image_surface (surface, interest_rect, &image, image_rect_out);
- if (status == CAIRO_STATUS_SUCCESS)
- *image_out = image;
+ if (status)
+ return status;
- return status;
+ *image_out = image;
+
+ return CAIRO_STATUS_SUCCESS;
}
static void
@@ -637,7 +637,7 @@ _cairo_xcb_surface_clone_similar (void *abstract_surface,
cairo_image_surface_t *image_src = (cairo_image_surface_t *)src;
clone = (cairo_xcb_surface_t *)
- _cairo_xcb_surface_create_similar (surface, image_src->format, 0,
+ _cairo_xcb_surface_create_similar (surface, image_src->format,
image_src->width, image_src->height);
if (clone == NULL)
return CAIRO_STATUS_NO_MEMORY;
@@ -850,12 +850,12 @@ _cairo_xcb_surface_composite (cairo_operator_t operator,
return status;
status = _cairo_xcb_surface_set_attributes (src, &src_attr);
- if (CAIRO_OK (status))
+ if (status == CAIRO_STATUS_SUCCESS)
{
if (mask)
{
status = _cairo_xcb_surface_set_attributes (mask, &mask_attr);
- if (CAIRO_OK (status))
+ if (status == CAIRO_STATUS_SUCCESS)
XCBRenderComposite (dst->dpy,
_render_operator (operator),
src->picture,
@@ -966,7 +966,7 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t operator,
/* XXX: _format_from_cairo is slow. should cache something. */
render_format = _format_from_cairo (dst->dpy, CAIRO_FORMAT_A8),
status = _cairo_xcb_surface_set_attributes (src, &attributes);
- if (CAIRO_OK (status))
+ if (status == CAIRO_STATUS_SUCCESS)
XCBRenderTrapezoids (dst->dpy,
_render_operator (operator),
src->picture, dst->picture,
@@ -981,14 +981,6 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t operator,
}
static cairo_int_status_t
-_cairo_xcb_surface_set_clip_region (void *abstract_surface,
- pixman_region16_t *region)
-{
- /* XXX: FIXME */
- return CAIRO_INT_STATUS_UNSUPPORTED;
-}
-
-static cairo_int_status_t
_cairo_xcb_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
{
@@ -1016,7 +1008,8 @@ static const cairo_surface_backend_t cairo_xcb_surface_backend = {
_cairo_xcb_surface_composite_trapezoids,
NULL, /* copy_page */
NULL, /* show_page */
- _cairo_xcb_surface_set_clip_region,
+ NULL, /* _cairo_xcb_surface_set_clip_region */
+ NULL, /* intersect_clip_path */
_cairo_xcb_surface_get_extents,
NULL /* show_glyphs */
};
diff --git a/src/cairo-xcb.h b/src/cairo-xcb.h
index 57a7aebd1..17dfafa02 100644
--- a/src/cairo-xcb.h
+++ b/src/cairo-xcb.h
@@ -47,7 +47,7 @@ CAIRO_BEGIN_DECLS
cairo_surface_t *
cairo_xcb_surface_create (XCBConnection *c,
- XCBDRAWABLE pixmap,
+ XCBDRAWABLE drawable,
XCBVISUALTYPE *visual,
int width,
int height);
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 41fb00c44..f06d409e2 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -46,7 +46,17 @@ typedef int (*cairo_xlib_error_func_t) (Display *display,
typedef struct _cairo_xlib_surface cairo_xlib_surface_t;
-static void _cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface);
+static void
+_cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface);
+
+static void
+_cairo_xlib_surface_ensure_src_picture (cairo_xlib_surface_t *surface);
+
+static void
+_cairo_xlib_surface_ensure_dst_picture (cairo_xlib_surface_t *surface);
+
+static cairo_bool_t
+_cairo_surface_is_xlib (cairo_surface_t *surface);
/*
* Instead of taking two round trips for each blending request,
@@ -70,11 +80,25 @@ struct _cairo_xlib_surface {
int render_major;
int render_minor;
+ /* TRUE if the server has a bug with repeating pictures
+ *
+ * https://bugs.freedesktop.org/show_bug.cgi?id=3566
+ *
+ * We can't test for this because it depends on whether the
+ * picture is in video memory or not.
+ */
+ cairo_bool_t buggy_repeat;
+
int width;
int height;
int depth;
- Picture picture;
+ Picture dst_picture, src_picture;
+
+ cairo_bool_t have_clip_rects;
+ XRectangle *clip_rects;
+ int num_clip_rects;
+
XRenderPictFormat *format;
};
@@ -157,7 +181,6 @@ _CAIRO_FORMAT_XRENDER_FORMAT(Display *dpy, cairo_format_t format)
static cairo_surface_t *
_cairo_xlib_surface_create_similar (void *abstract_src,
cairo_format_t format,
- int drawable,
int width,
int height)
{
@@ -197,8 +220,11 @@ static cairo_status_t
_cairo_xlib_surface_finish (void *abstract_surface)
{
cairo_xlib_surface_t *surface = abstract_surface;
- if (surface->picture)
- XRenderFreePicture (surface->dpy, surface->picture);
+ if (surface->dst_picture)
+ XRenderFreePicture (surface->dpy, surface->dst_picture);
+
+ if (surface->src_picture)
+ XRenderFreePicture (surface->dpy, surface->src_picture);
if (surface->owns_pixmap)
XFreePixmap (surface->dpy, surface->drawable);
@@ -206,6 +232,9 @@ _cairo_xlib_surface_finish (void *abstract_surface)
if (surface->gc)
XFreeGC (surface->dpy, surface->gc);
+ if (surface->clip_rects)
+ free (surface->clip_rects);
+
surface->dpy = NULL;
return CAIRO_STATUS_SUCCESS;
@@ -281,7 +310,7 @@ _get_image_surface (cairo_xlib_surface_t *surface,
rect.x = interest_rect->x;
rect.y = interest_rect->y;
rect.width = interest_rect->width;
- rect.height = interest_rect->width;
+ rect.height = interest_rect->height;
if (rect.x > x1)
x1 = rect.x;
@@ -425,14 +454,54 @@ _get_image_surface (cairo_xlib_surface_t *surface,
ximage->data = NULL;
XDestroyImage (ximage);
- _cairo_image_surface_set_repeat (image, surface->base.repeat);
- _cairo_image_surface_set_matrix (image, &(surface->base.matrix));
-
*image_out = image;
return CAIRO_STATUS_SUCCESS;
}
static void
+_cairo_xlib_surface_ensure_src_picture (cairo_xlib_surface_t *surface)
+{
+ if (!surface->src_picture)
+ surface->src_picture = XRenderCreatePicture (surface->dpy,
+ surface->drawable,
+ surface->format,
+ 0, NULL);
+}
+
+static void
+_cairo_xlib_surface_set_picture_clip_rects (cairo_xlib_surface_t *surface)
+{
+ if (surface->have_clip_rects)
+ XRenderSetPictureClipRectangles (surface->dpy, surface->dst_picture,
+ 0, 0,
+ surface->clip_rects,
+ surface->num_clip_rects);
+}
+
+static void
+_cairo_xlib_surface_set_gc_clip_rects (cairo_xlib_surface_t *surface)
+{
+ if (surface->have_clip_rects)
+ XSetClipRectangles(surface->dpy, surface->gc,
+ 0, 0,
+ surface->clip_rects,
+ surface->num_clip_rects, YXSorted);
+}
+
+static void
+_cairo_xlib_surface_ensure_dst_picture (cairo_xlib_surface_t *surface)
+{
+ if (!surface->dst_picture) {
+ surface->dst_picture = XRenderCreatePicture (surface->dpy,
+ surface->drawable,
+ surface->format,
+ 0, NULL);
+ _cairo_xlib_surface_set_picture_clip_rects (surface);
+ }
+
+}
+
+static void
_cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface)
{
XGCValues gcv;
@@ -443,6 +512,7 @@ _cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface)
gcv.graphics_exposures = False;
surface->gc = XCreateGC (surface->dpy, surface->drawable,
GCGraphicsExposures, &gcv);
+ _cairo_xlib_surface_set_gc_clip_rects (surface);
}
static cairo_status_t
@@ -499,10 +569,12 @@ _cairo_xlib_surface_acquire_source_image (void *abstract_surf
cairo_status_t status;
status = _get_image_surface (surface, NULL, &image, NULL);
- if (status == CAIRO_STATUS_SUCCESS)
- *image_out = image;
+ if (status)
+ return status;
- return status;
+ *image_out = image;
+
+ return CAIRO_STATUS_SUCCESS;
}
static void
@@ -525,10 +597,12 @@ _cairo_xlib_surface_acquire_dest_image (void *abstract_surfac
cairo_status_t status;
status = _get_image_surface (surface, interest_rect, &image, image_rect_out);
- if (status == CAIRO_STATUS_SUCCESS)
- *image_out = image;
+ if (status)
+ return status;
- return status;
+ *image_out = image;
+
+ return CAIRO_STATUS_SUCCESS;
}
static void
@@ -567,7 +641,7 @@ _cairo_xlib_surface_clone_similar (void *abstract_surface,
cairo_image_surface_t *image_src = (cairo_image_surface_t *)src;
clone = (cairo_xlib_surface_t *)
- _cairo_xlib_surface_create_similar (surface, image_src->format, 0,
+ _cairo_xlib_surface_create_similar (surface, image_src->format,
image_src->width, image_src->height);
if (clone == NULL)
return CAIRO_STATUS_NO_MEMORY;
@@ -588,7 +662,7 @@ _cairo_xlib_surface_set_matrix (cairo_xlib_surface_t *surface,
{
XTransform xtransform;
- if (!surface->picture)
+ if (!surface->src_picture)
return CAIRO_STATUS_SUCCESS;
xtransform.matrix[0][0] = _cairo_fixed_from_double (matrix->xx);
@@ -617,7 +691,7 @@ _cairo_xlib_surface_set_matrix (cairo_xlib_surface_t *surface,
return CAIRO_INT_STATUS_UNSUPPORTED;
}
- XRenderSetPictureTransform (surface->dpy, surface->picture, &xtransform);
+ XRenderSetPictureTransform (surface->dpy, surface->src_picture, &xtransform);
return CAIRO_STATUS_SUCCESS;
}
@@ -628,7 +702,7 @@ _cairo_xlib_surface_set_filter (cairo_xlib_surface_t *surface,
{
char *render_filter;
- if (!surface->picture)
+ if (!surface->src_picture)
return CAIRO_STATUS_SUCCESS;
if (!CAIRO_SURFACE_RENDER_HAS_FILTERS (surface))
@@ -660,7 +734,7 @@ _cairo_xlib_surface_set_filter (cairo_xlib_surface_t *surface,
break;
}
- XRenderSetPictureFilter (surface->dpy, surface->picture,
+ XRenderSetPictureFilter (surface->dpy, surface->src_picture,
render_filter, NULL, 0);
return CAIRO_STATUS_SUCCESS;
@@ -672,13 +746,13 @@ _cairo_xlib_surface_set_repeat (cairo_xlib_surface_t *surface, int repeat)
XRenderPictureAttributes pa;
unsigned long mask;
- if (!surface->picture)
+ if (!surface->src_picture)
return CAIRO_STATUS_SUCCESS;
mask = CPRepeat;
pa.repeat = repeat;
- XRenderChangePicture (surface->dpy, surface->picture, mask, &pa);
+ XRenderChangePicture (surface->dpy, surface->src_picture, mask, &pa);
return CAIRO_STATUS_SUCCESS;
}
@@ -689,6 +763,8 @@ _cairo_xlib_surface_set_attributes (cairo_xlib_surface_t *surface,
{
cairo_int_status_t status;
+ _cairo_xlib_surface_ensure_src_picture (surface);
+
status = _cairo_xlib_surface_set_matrix (surface, &attributes->matrix);
if (status)
return status;
@@ -711,6 +787,139 @@ _cairo_xlib_surface_set_attributes (cairo_xlib_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
+/* Checks whether we can can directly draw from src to dst with
+ * the core protocol: either with CopyArea or using src as a
+ * a tile in a GC.
+ */
+static cairo_bool_t
+_surfaces_compatible (cairo_xlib_surface_t *src,
+ cairo_xlib_surface_t *dst)
+{
+
+ if (src->dpy != dst->dpy)
+ return FALSE;
+
+ /* We must not only match depth and format/visual, we must also
+ * match screen. We don't have that information, and rather than
+ * asking for it round-trip, we'll just return FALSE if we have
+ * more than one screen on the display.
+ */
+ if (ScreenCount (dst->dpy) > 1)
+ return FALSE;
+
+ return (src->depth == dst->depth &&
+ ((src->format != NULL && src->format == dst->format) ||
+ (src->visual != NULL && src->visual == dst->visual)));
+}
+
+static cairo_bool_t
+_surface_has_alpha (cairo_xlib_surface_t *surface)
+{
+ if (surface->format) {
+ if (surface->format->type == PictTypeDirect &&
+ surface->format->direct.alphaMask != 0)
+ return TRUE;
+ else
+ return FALSE;
+ } else {
+
+ /* In the no-render case, we never have alpha */
+ return FALSE;
+ }
+}
+
+/* There is a bug in most older X servers with compositing using a repeating
+ * source pattern when the source is in off-screen video memory. When that
+ * bug could be triggered, we need a fallback: in the common case where we have no
+ * transformation and the source and destination have the same format/visual,
+ * we can do the operation using the core protocol, otherwise, we need
+ * a software fallback.
+ */
+typedef enum {
+ DO_RENDER, /* use render */
+ DO_XLIB, /* core protocol fallback */
+ DO_UNSUPPORTED /* software fallback */
+} composite_operation_t;
+
+/* Initial check for the bug; we need to recheck after we turn
+ * patterns into surfaces, since that may introduce a repeating
+ * pattern for gradient patterns.
+ *
+ * All we do here is reject cases where we *know* are going to
+ * hit the bug and won't be able to use a core protocol fallback.
+ */
+static composite_operation_t
+_categorize_composite_repeat (cairo_xlib_surface_t *dst,
+ cairo_operator_t operator,
+ cairo_pattern_t *src_pattern,
+ cairo_bool_t have_mask)
+
+{
+ if (!dst->buggy_repeat)
+ return DO_RENDER;
+
+ if (src_pattern->type == CAIRO_PATTERN_SURFACE)
+ {
+ cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *)src_pattern;
+
+ if (_cairo_matrix_is_integer_translation (&src_pattern->matrix, NULL, NULL) &&
+ src_pattern->extend == CAIRO_EXTEND_REPEAT)
+ {
+ /* This is the case where we have a bug; reject some cases where a
+ * core protocol fallback is impossible.
+ */
+ if (have_mask ||
+ !(operator == CAIRO_OPERATOR_SOURCE || operator == CAIRO_OPERATOR_OVER))
+ return DO_UNSUPPORTED;
+
+ if (_cairo_surface_is_xlib (surface_pattern->surface)) {
+ cairo_xlib_surface_t *src = (cairo_xlib_surface_t *)surface_pattern->surface;
+
+ if (operator == CAIRO_OPERATOR_OVER && _surface_has_alpha (src))
+ return DO_UNSUPPORTED;
+
+ if (src->dpy == dst->dpy && !_surfaces_compatible (src, dst))
+ return DO_UNSUPPORTED;
+ }
+ }
+ }
+
+ return DO_RENDER;
+}
+
+/* Recheck for composite-repeat once we've turned patterns into Xlib surfaces
+ * If we end up returning DO_UNSUPPORTED here, we're throwing away work we
+ * did to turn gradients into a pattern, but most of the time we can handle
+ * that case with core protocol fallback.
+ */
+static composite_operation_t
+_recategorize_composite_repeat (cairo_xlib_surface_t *dst,
+ cairo_operator_t operator,
+ cairo_xlib_surface_t *src,
+ cairo_surface_attributes_t *src_attr,
+ cairo_bool_t have_mask)
+{
+ if (!dst->buggy_repeat)
+ return DO_RENDER;
+
+ if (_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL) &&
+ src_attr->extend == CAIRO_EXTEND_REPEAT &&
+ (src->width != 1 || src->height != 1))
+ {
+ if (!have_mask &&
+ (operator == CAIRO_OPERATOR_SOURCE ||
+ (operator == CAIRO_OPERATOR_OVER && !_surface_has_alpha (src))))
+ {
+ if (_surfaces_compatible (dst, src))
+ return DO_XLIB;
+ }
+
+ return DO_UNSUPPORTED;
+ }
+
+ return DO_RENDER;
+}
+
static int
_render_operator (cairo_operator_t operator)
{
@@ -770,10 +979,16 @@ _cairo_xlib_surface_composite (cairo_operator_t operator,
cairo_xlib_surface_t *src;
cairo_xlib_surface_t *mask;
cairo_int_status_t status;
+ composite_operation_t operation;
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))
return CAIRO_INT_STATUS_UNSUPPORTED;
+ operation = _categorize_composite_repeat (dst, operator, src_pattern,
+ mask_pattern != NULL);
+ if (operation == DO_UNSUPPORTED)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
status = _cairo_pattern_acquire_surfaces (src_pattern, mask_pattern,
&dst->base,
src_x, src_y,
@@ -785,16 +1000,28 @@ _cairo_xlib_surface_composite (cairo_operator_t operator,
if (status)
return status;
+ operation = _recategorize_composite_repeat (dst, operator, src, &src_attr,
+ mask_pattern != NULL);
+ if (operation == DO_UNSUPPORTED) {
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
+ goto FAIL;
+ }
+
status = _cairo_xlib_surface_set_attributes (src, &src_attr);
- if (CAIRO_OK (status)) {
+ if (status)
+ goto FAIL;
+
+ if (operation == DO_RENDER)
+ {
+ _cairo_xlib_surface_ensure_dst_picture (dst);
if (mask) {
status = _cairo_xlib_surface_set_attributes (mask, &mask_attr);
- if (CAIRO_OK (status))
+ if (status == CAIRO_STATUS_SUCCESS)
XRenderComposite (dst->dpy,
_render_operator (operator),
- src->picture,
- mask->picture,
- dst->picture,
+ src->src_picture,
+ mask->src_picture,
+ dst->dst_picture,
src_x + src_attr.x_offset,
src_y + src_attr.y_offset,
mask_x + mask_attr.x_offset,
@@ -804,9 +1031,9 @@ _cairo_xlib_surface_composite (cairo_operator_t operator,
} else {
XRenderComposite (dst->dpy,
_render_operator (operator),
- src->picture,
+ src->src_picture,
0,
- dst->picture,
+ dst->dst_picture,
src_x + src_attr.x_offset,
src_y + src_attr.y_offset,
0, 0,
@@ -814,6 +1041,30 @@ _cairo_xlib_surface_composite (cairo_operator_t operator,
width, height);
}
}
+ else /* DO_XLIB */
+ {
+ /* This case is only used for bug fallbacks, though it is theoretically
+ * applicable to the case where we don't have the RENDER extension as
+ * well.
+ *
+ * We've checked that we have a repeating unscaled source in
+ * _recategorize_composite_repeat.
+ */
+ int itx, ity;
+
+ _cairo_xlib_surface_ensure_gc (dst);
+ _cairo_matrix_is_integer_translation (&src_attr.matrix, &itx, &ity);
+
+ XSetTSOrigin (dst->dpy, dst->gc,
+ - (itx + src_attr.x_offset), - (ity + src_attr.y_offset));
+ XSetTile (dst->dpy, dst->gc, src->drawable);
+ XSetFillStyle (dst->dpy, dst->gc, FillTiled);
+
+ XFillRectangle (dst->dpy, dst->drawable, dst->gc,
+ dst_x, dst_y, width, height);
+ }
+
+ FAIL:
if (mask)
_cairo_pattern_release_surface (&dst->base, &mask->base, &mask_attr);
@@ -842,9 +1093,10 @@ _cairo_xlib_surface_fill_rectangles (void *abstract_surface,
render_color.alpha = color->alpha_short;
/* XXX: This XRectangle cast is evil... it needs to go away somehow. */
+ _cairo_xlib_surface_ensure_dst_picture (surface);
XRenderFillRectangles (surface->dpy,
_render_operator (operator),
- surface->picture,
+ surface->dst_picture,
&render_color, (XRectangle *) rects, num_rects);
return CAIRO_STATUS_SUCCESS;
@@ -867,11 +1119,16 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
cairo_xlib_surface_t *dst = abstract_dst;
cairo_xlib_surface_t *src;
cairo_int_status_t status;
+ composite_operation_t operation;
int render_reference_x, render_reference_y;
int render_src_x, render_src_y;
if (!CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst))
return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ operation = _categorize_composite_repeat (dst, operator, pattern, TRUE);
+ if (operation == DO_UNSUPPORTED)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
status = _cairo_pattern_acquire_surface (pattern, &dst->base,
src_x, src_y, width, height,
@@ -879,7 +1136,13 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
&attributes);
if (status)
return status;
-
+
+ operation = _recategorize_composite_repeat (dst, operator, src, &attributes, TRUE);
+ if (operation == DO_UNSUPPORTED) {
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
+ goto FAIL;
+ }
+
if (traps[0].left.p1.y < traps[0].left.p2.y) {
render_reference_x = _cairo_fixed_integer_floor (traps[0].left.p1.x);
render_reference_y = _cairo_fixed_integer_floor (traps[0].left.p1.y);
@@ -892,16 +1155,18 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
render_src_y = src_y + render_reference_y - dst_y;
/* XXX: The XTrapezoid cast is evil and needs to go away somehow. */
+ _cairo_xlib_surface_ensure_dst_picture (dst);
status = _cairo_xlib_surface_set_attributes (src, &attributes);
- if (CAIRO_OK (status))
+ if (status == CAIRO_STATUS_SUCCESS)
XRenderCompositeTrapezoids (dst->dpy,
_render_operator (operator),
- src->picture, dst->picture,
+ src->src_picture, dst->dst_picture,
XRenderFindStandardFormat (dst->dpy, PictStandardA8),
render_src_x + attributes.x_offset,
render_src_y + attributes.y_offset,
(XTrapezoid *) traps, num_traps);
+ FAIL:
_cairo_pattern_release_surface (&dst->base, &src->base, &attributes);
return status;
@@ -913,14 +1178,22 @@ _cairo_xlib_surface_set_clip_region (void *abstract_surface,
{
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
+ if (surface->clip_rects) {
+ free (surface->clip_rects);
+ surface->clip_rects = NULL;
+ }
+
+ surface->have_clip_rects = FALSE;
+ surface->num_clip_rects = 0;
+
if (region == NULL) {
if (surface->gc)
XSetClipMask (surface->dpy, surface->gc, None);
- if (surface->picture) {
+ if (surface->format && surface->dst_picture) {
XRenderPictureAttributes pa;
pa.clip_mask = None;
- XRenderChangePicture (surface->dpy, surface->picture,
+ XRenderChangePicture (surface->dpy, surface->dst_picture,
CPClipMask, &pa);
}
} else {
@@ -946,15 +1219,15 @@ _cairo_xlib_surface_set_clip_region (void *abstract_surface,
rects[i].height = boxes[i].y2 - boxes[i].y1;
}
+ surface->have_clip_rects = TRUE;
+ surface->clip_rects = rects;
+ surface->num_clip_rects = n_boxes;
+
if (surface->gc)
- XSetClipRectangles(surface->dpy, surface->gc,
- 0, 0, rects, n_boxes, YXSorted);
- if (surface->picture)
- XRenderSetPictureClipRectangles (surface->dpy, surface->picture,
- 0, 0, rects, n_boxes);
-
- if (rects)
- free (rects);
+ _cairo_xlib_surface_set_gc_clip_rects (surface);
+
+ if (surface->dst_picture)
+ _cairo_xlib_surface_set_picture_clip_rects (surface);
}
return CAIRO_STATUS_SUCCESS;
@@ -1003,6 +1276,7 @@ static const cairo_surface_backend_t cairo_xlib_surface_backend = {
NULL, /* copy_page */
NULL, /* show_page */
_cairo_xlib_surface_set_clip_region,
+ NULL, /* intersect_clip_path */
_cairo_xlib_surface_get_extents,
_cairo_xlib_surface_show_glyphs
};
@@ -1043,15 +1317,12 @@ _cairo_xlib_surface_create_internal (Display *dpy,
surface->gc = NULL;
surface->drawable = drawable;
surface->owns_pixmap = FALSE;
- surface->visual = visual;
- surface->format = format;
surface->use_pixmap = 0;
surface->width = width;
surface->height = height;
- surface->depth = depth;
if (format) {
- surface->depth = format->depth;
+ depth = format->depth;
} else if (visual) {
int i, j, k;
@@ -1061,10 +1332,10 @@ _cairo_xlib_surface_create_internal (Display *dpy,
for (i = 0; i < ScreenCount (dpy); i++) {
Screen *screen = ScreenOfDisplay (dpy, i);
for (j = 0; j < screen->ndepths; j++) {
- Depth *depth = &screen->depths[j];
- for (k = 0; k < depth->nvisuals; k++) {
- if (&depth->visuals[k] == visual) {
- surface->depth = depth->depth;
+ Depth *d = &screen->depths[j];
+ for (k = 0; k < d->nvisuals; k++) {
+ if (&d->visuals[k] == visual) {
+ depth = d->depth;
goto found;
}
}
@@ -1080,22 +1351,34 @@ _cairo_xlib_surface_create_internal (Display *dpy,
surface->render_minor = -1;
}
- surface->picture = None;
+ surface->buggy_repeat = FALSE;
+ if (strcmp (ServerVendor (dpy), "The X.Org Foundation") == 0) {
+ if (VendorRelease (dpy) <= 60802000)
+ surface->buggy_repeat = TRUE;
+ }
+
+ surface->dst_picture = None;
+ surface->src_picture = None;
if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface)) {
-
if (!format) {
- if (visual) {
+ if (visual)
format = XRenderFindVisualFormat (dpy, visual);
- } else if (depth == 1)
+ else if (depth == 1)
format = XRenderFindStandardFormat (dpy, PictStandardA1);
}
-
- if (format)
- surface->picture = XRenderCreatePicture (dpy, drawable,
- format, 0, NULL);
+ } else {
+ format = NULL;
}
+ surface->visual = visual;
+ surface->format = format;
+ surface->depth = depth;
+
+ surface->have_clip_rects = FALSE;
+ surface->clip_rects = NULL;
+ surface->num_clip_rects = 0;
+
return (cairo_surface_t *) surface;
}
@@ -1479,8 +1762,8 @@ _cairo_xlib_surface_show_glyphs32 (cairo_scaled_font_t *scaled_font,
XRenderCompositeText32 (self->dpy,
_render_operator (operator),
- src->picture,
- self->picture,
+ src->src_picture,
+ self->dst_picture,
g->a8_pict_format,
source_x, source_y,
0, 0,
@@ -1556,8 +1839,8 @@ _cairo_xlib_surface_show_glyphs16 (cairo_scaled_font_t *scaled_font,
XRenderCompositeText16 (self->dpy,
_render_operator (operator),
- src->picture,
- self->picture,
+ src->src_picture,
+ self->dst_picture,
g->a8_pict_format,
source_x, source_y,
0, 0,
@@ -1632,8 +1915,8 @@ _cairo_xlib_surface_show_glyphs8 (cairo_scaled_font_t *scaled_font,
XRenderCompositeText8 (self->dpy,
_render_operator (operator),
- src->picture,
- self->picture,
+ src->src_picture,
+ self->dst_picture,
g->a8_pict_format,
source_x, source_y,
0, 0,
@@ -1678,11 +1961,16 @@ _cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_glyph_cache_key_t key;
glyphset_cache_entry_t **entries;
glyphset_cache_entry_t *stack_entries [N_STACK_BUF];
+ composite_operation_t operation;
int i;
- if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (self))
+ if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (self) || !self->format)
return CAIRO_INT_STATUS_UNSUPPORTED;
+ operation = _categorize_composite_repeat (self, operator, pattern, TRUE);
+ if (operation == DO_UNSUPPORTED)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
status = _cairo_pattern_acquire_surface (pattern, &self->base,
source_x, source_y, width, height,
(cairo_surface_t **) &src,
@@ -1690,6 +1978,12 @@ _cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
if (status)
return status;
+ operation = _recategorize_composite_repeat (self, operator, src, &attributes, TRUE);
+ if (operation == DO_UNSUPPORTED) {
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
+ goto FAIL;
+ }
+
status = _cairo_xlib_surface_set_attributes (src, &attributes);
if (status)
goto FAIL;
@@ -1738,21 +2032,28 @@ _cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
/* Call the appropriate sub-function. */
+ _cairo_xlib_surface_ensure_dst_picture (self);
if (elt_size == 8)
+ {
status = _cairo_xlib_surface_show_glyphs8 (scaled_font, operator, g, &key, src, self,
source_x + attributes.x_offset,
source_y + attributes.y_offset,
glyphs, entries, num_glyphs);
+ }
else if (elt_size == 16)
+ {
status = _cairo_xlib_surface_show_glyphs16 (scaled_font, operator, g, &key, src, self,
source_x + attributes.x_offset,
source_y + attributes.y_offset,
glyphs, entries, num_glyphs);
+ }
else
+ {
status = _cairo_xlib_surface_show_glyphs32 (scaled_font, operator, g, &key, src, self,
source_x + attributes.x_offset,
source_y + attributes.y_offset,
glyphs, entries, num_glyphs);
+ }
for (i = 0; i < num_glyphs; ++i)
_xlib_glyphset_cache_destroy_entry (g, entries[i]);
diff --git a/src/cairo.c b/src/cairo.c
index f825c733e..73dfc2cdd 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -43,37 +43,56 @@
#define CAIRO_TOLERANCE_MINIMUM 0.0002 /* We're limited by 16 bits of sub-pixel precision */
+static const cairo_t cairo_nil = {
+ (unsigned int)-1, /* ref_count */
+ CAIRO_STATUS_NO_MEMORY, /* status */
+ { /* path */
+ NULL, NULL, /* op_buf_head, op_buf_tail */
+ NULL, NULL, /* arg_buf_head, arg_buf_tail */
+ { 0, 0 }, /* last_move_point */
+ { 0, 0 }, /* current point */
+ FALSE, /* has_current_point */
+ },
+ NULL /* gstate */
+};
+
#include <assert.h>
-#ifdef NDEBUG
-#define CAIRO_CHECK_SANITY(cr)
-#else
-static int
-cairo_sane_state (cairo_t *cr)
-{
- if (cr == NULL)
- return 0;
- switch (cr->status) {
- case CAIRO_STATUS_SUCCESS:
- case CAIRO_STATUS_NO_MEMORY:
- 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_NO_TARGET_SURFACE:
- case CAIRO_STATUS_NULL_POINTER:
- case CAIRO_STATUS_INVALID_STRING:
- case CAIRO_STATUS_INVALID_PATH_DATA:
- break;
- default:
- return 0;
- }
- return 1;
+/* This has to be updated whenever cairo_status_t is extended. That's
+ * a bit of a pain, but it should be easy to always catch as long as
+ * one adds a new test case to test a trigger of the new status value.
+ */
+#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_SURFACE_TYPE_MISMATCH
+
+/**
+ * _cairo_error:
+ * @cr: a cairo context
+ * @status: a status value indicating an error, (eg. not
+ * CAIRO_STATUS_SUCCESS)
+ *
+ * Sets cr->status to @status.
+ *
+ * All assignments of an error status to cr->status should happen
+ * either inside of _cairo_error(), or else _cairo_error() should be
+ * called immediately after the assignment.
+ *
+ * The purpose of this function is to allow the user to set a
+ * breakpoint in _cairo_error() to generate a stack trace for when the
+ * user causes cairo to detect an error.
+ *
+ * _cairo_error also calls the error notify callback function that the
+ * user may have set with cairo_set_error_notify.
+ **/
+static void
+_cairo_error (cairo_t *cr, cairo_status_t status)
+{
+ assert (status > CAIRO_STATUS_SUCCESS &&
+ status <= CAIRO_STATUS_LAST_STATUS);
+
+ cr->status = status;
}
-#define CAIRO_CHECK_SANITY(cr) assert(cairo_sane_state ((cr)))
-#endif
-/*
+/**
* cairo_create:
* @target: target surface for the context
*
@@ -81,7 +100,7 @@ cairo_sane_state (cairo_t *cr)
* default values and with @target as a target surface. The target
* surface should be constructed with a backend-specific function such
* as cairo_image_surface_create (or any other
- * cairo_<backend>_surface_create variant).
+ * cairo_&lt;backend&gt;_surface_create variant).
*
* This function references @target, so you can immediately
* call cairo_surface_destroy() on it if you don't need to
@@ -100,7 +119,12 @@ cairo_sane_state (cairo_t *cr)
* Return value: a newly allocated #cairo_t with a reference
* count of 1. The initial reference count should be released
* with cairo_destroy() when you are done using the #cairo_t.
- */
+ * This function never returns %NULL. If memory cannot be
+ * allocated, a special #cairo_t object will be returned on
+ * which cairo_status() returns %CAIRO_STATUS_NO_MEMORY.
+ * You can use this object normally, but no drawing will
+ * be done.
+ **/
cairo_t *
cairo_create (cairo_surface_t *target)
{
@@ -108,24 +132,24 @@ cairo_create (cairo_surface_t *target)
cr = malloc (sizeof (cairo_t));
if (cr == NULL)
- return NULL;
+ return (cairo_t *) &cairo_nil;
- cr->status = CAIRO_STATUS_SUCCESS;
cr->ref_count = 1;
+ cr->status = CAIRO_STATUS_SUCCESS;
+
_cairo_path_fixed_init (&cr->path);
if (target == NULL) {
cr->gstate = NULL;
- cr->status = CAIRO_STATUS_NULL_POINTER;
+ _cairo_error (cr, CAIRO_STATUS_NULL_POINTER);
return cr;
}
cr->gstate = _cairo_gstate_create (target);
if (cr->gstate == NULL)
- cr->status = CAIRO_STATUS_NO_MEMORY;
+ _cairo_error (cr, CAIRO_STATUS_NO_MEMORY);
- CAIRO_CHECK_SANITY (cr);
return cr;
}
@@ -140,12 +164,10 @@ cairo_create (cairo_surface_t *target)
void
cairo_reference (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->ref_count == (unsigned int)-1)
return;
-
+
cr->ref_count++;
- CAIRO_CHECK_SANITY (cr);
}
/**
@@ -159,7 +181,9 @@ cairo_reference (cairo_t *cr)
void
cairo_destroy (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
+ if (cr->ref_count == (unsigned int)-1)
+ return;
+
cr->ref_count--;
if (cr->ref_count)
return;
@@ -197,21 +221,20 @@ cairo_save (cairo_t *cr)
{
cairo_gstate_t *top;
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
top = _cairo_gstate_clone (cr->gstate);
if (top == NULL) {
- cr->status = CAIRO_STATUS_NO_MEMORY;
- CAIRO_CHECK_SANITY (cr);
+ _cairo_error (cr, CAIRO_STATUS_NO_MEMORY);
return;
}
top->next = cr->gstate;
cr->gstate = top;
- CAIRO_CHECK_SANITY (cr);
}
slim_hidden_def(cairo_save);
@@ -228,9 +251,10 @@ cairo_restore (cairo_t *cr)
{
cairo_gstate_t *top;
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
top = cr->gstate;
cr->gstate = top->next;
@@ -238,12 +262,7 @@ cairo_restore (cairo_t *cr)
_cairo_gstate_destroy (top);
if (cr->gstate == NULL)
- cr->status = CAIRO_STATUS_INVALID_RESTORE;
-
- if (cr->status)
- return;
-
- CAIRO_CHECK_SANITY (cr);
+ _cairo_error (cr, CAIRO_STATUS_INVALID_RESTORE);
}
slim_hidden_def(cairo_restore);
@@ -291,12 +310,26 @@ cairo_pop_group (cairo_t *cr)
void
cairo_set_operator (cairo_t *cr, cairo_operator_t op)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_set_operator (cr->gstate, op);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
+}
+
+static void
+_cairo_set_source_solid (cairo_t *cr, const cairo_color_t *color)
+{
+ cairo_pattern_t *source;
+
+ source = _cairo_pattern_create_solid (color);
+
+ cairo_set_source (cr, source);
+
+ cairo_pattern_destroy (source);
}
/**
@@ -319,9 +352,10 @@ cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue)
{
cairo_color_t color;
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
_cairo_restrict_value (&red, 0.0, 1.0);
_cairo_restrict_value (&green, 0.0, 1.0);
@@ -329,9 +363,7 @@ cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue)
_cairo_color_init_rgb (&color, red, green, blue);
- cr->status = _cairo_gstate_set_source_solid (cr->gstate, &color);
-
- CAIRO_CHECK_SANITY (cr);
+ _cairo_set_source_solid (cr, &color);
}
/**
@@ -357,9 +389,10 @@ cairo_set_source_rgba (cairo_t *cr,
{
cairo_color_t color;
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
_cairo_restrict_value (&red, 0.0, 1.0);
_cairo_restrict_value (&green, 0.0, 1.0);
@@ -368,9 +401,7 @@ cairo_set_source_rgba (cairo_t *cr,
_cairo_color_init_rgba (&color, red, green, blue, alpha);
- cr->status = _cairo_gstate_set_source_solid (cr->gstate, &color);
-
- CAIRO_CHECK_SANITY (cr);
+ _cairo_set_source_solid (cr, &color);
}
void
@@ -382,23 +413,18 @@ cairo_set_source_surface (cairo_t *cr,
cairo_pattern_t *pattern;
cairo_matrix_t matrix;
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
pattern = cairo_pattern_create_for_surface (surface);
- if (!pattern) {
- cr->status = CAIRO_STATUS_NO_MEMORY;
- return;
- }
cairo_matrix_init_translate (&matrix, -x, -y);
cairo_pattern_set_matrix (pattern, &matrix);
cairo_set_source (cr, pattern);
cairo_pattern_destroy (pattern);
-
- CAIRO_CHECK_SANITY (cr);
}
/**
@@ -418,12 +444,24 @@ cairo_set_source_surface (cairo_t *cr,
void
cairo_set_source (cairo_t *cr, cairo_pattern_t *source)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
+ return;
+ }
+
+ if (source == NULL) {
+ _cairo_error (cr, CAIRO_STATUS_NULL_POINTER);
+ return;
+ }
+
+ if (source->status) {
+ _cairo_error (cr, source->status);
return;
+ }
cr->status = _cairo_gstate_set_source (cr->gstate, source);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -439,11 +477,12 @@ cairo_set_source (cairo_t *cr, cairo_pattern_t *source)
cairo_pattern_t *
cairo_get_source (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
- /* XXX: We'll want to do something like this:
- if (cr->status)
- return cairo_pattern_nil;
- */
+ if (cr->status) {
+ cairo_pattern_t *pattern;
+ pattern = _cairo_pattern_create_in_error (cr->status);
+ _cairo_error (cr, cr->status);
+ return pattern;
+ }
return _cairo_gstate_get_source (cr->gstate);
}
@@ -464,14 +503,16 @@ cairo_get_source (cairo_t *cr)
void
cairo_set_tolerance (cairo_t *cr, double tolerance)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
_cairo_restrict_value (&tolerance, CAIRO_TOLERANCE_MINIMUM, tolerance);
cr->status = _cairo_gstate_set_tolerance (cr->gstate, tolerance);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -488,12 +529,14 @@ cairo_set_tolerance (cairo_t *cr, double tolerance)
void
cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_set_fill_rule (cr->gstate, fill_rule);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -513,14 +556,16 @@ cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule)
void
cairo_set_line_width (cairo_t *cr, double width)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
_cairo_restrict_value (&width, 0.0, width);
cr->status = _cairo_gstate_set_line_width (cr->gstate, width);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -540,12 +585,14 @@ cairo_set_line_width (cairo_t *cr, double width)
void
cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_set_line_cap (cr->gstate, line_cap);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -565,34 +612,40 @@ cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap)
void
cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_set_line_join (cr->gstate, line_join);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
void
cairo_set_dash (cairo_t *cr, double *dashes, int ndash, double offset)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_set_dash (cr->gstate, dashes, ndash, offset);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
void
cairo_set_miter_limit (cairo_t *cr, double limit)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_set_miter_limit (cr->gstate, limit);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
@@ -611,12 +664,14 @@ cairo_set_miter_limit (cairo_t *cr, double limit)
void
cairo_translate (cairo_t *cr, double tx, double ty)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_translate (cr->gstate, tx, ty);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -633,12 +688,14 @@ cairo_translate (cairo_t *cr, double tx, double ty)
void
cairo_scale (cairo_t *cr, double sx, double sy)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_scale (cr->gstate, sx, sy);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
@@ -657,12 +714,14 @@ cairo_scale (cairo_t *cr, double sx, double sy)
void
cairo_rotate (cairo_t *cr, double angle)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_rotate (cr->gstate, angle);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -678,12 +737,14 @@ void
cairo_transform (cairo_t *cr,
const cairo_matrix_t *matrix)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_transform (cr->gstate, matrix);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -698,12 +759,14 @@ void
cairo_set_matrix (cairo_t *cr,
const cairo_matrix_t *matrix)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_set_matrix (cr->gstate, matrix);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -718,12 +781,14 @@ cairo_set_matrix (cairo_t *cr,
void
cairo_identity_matrix (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_identity_matrix (cr->gstate);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -739,12 +804,14 @@ cairo_identity_matrix (cairo_t *cr)
void
cairo_user_to_device (cairo_t *cr, double *x, double *y)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_user_to_device (cr->gstate, x, y);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -761,12 +828,14 @@ cairo_user_to_device (cairo_t *cr, double *x, double *y)
void
cairo_user_to_device_distance (cairo_t *cr, double *dx, double *dy)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_user_to_device_distance (cr->gstate, dx, dy);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -782,12 +851,14 @@ cairo_user_to_device_distance (cairo_t *cr, double *dx, double *dy)
void
cairo_device_to_user (cairo_t *cr, double *x, double *y)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_device_to_user (cr->gstate, x, y);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -804,24 +875,25 @@ cairo_device_to_user (cairo_t *cr, double *x, double *y)
void
cairo_device_to_user_distance (cairo_t *cr, double *dx, double *dy)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_device_to_user_distance (cr->gstate, dx, dy);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
void
cairo_new_path (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
_cairo_path_fixed_fini (&cr->path);
-
- CAIRO_CHECK_SANITY (cr);
}
slim_hidden_def(cairo_new_path);
@@ -830,17 +902,18 @@ cairo_move_to (cairo_t *cr, double x, double y)
{
cairo_fixed_t x_fixed, y_fixed;
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
_cairo_gstate_user_to_backend (cr->gstate, &x, &y);
x_fixed = _cairo_fixed_from_double (x);
y_fixed = _cairo_fixed_from_double (y);
cr->status = _cairo_path_fixed_move_to (&cr->path, x_fixed, y_fixed);
-
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
slim_hidden_def(cairo_move_to);
@@ -849,17 +922,18 @@ cairo_line_to (cairo_t *cr, double x, double y)
{
cairo_fixed_t x_fixed, y_fixed;
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
_cairo_gstate_user_to_backend (cr->gstate, &x, &y);
x_fixed = _cairo_fixed_from_double (x);
y_fixed = _cairo_fixed_from_double (y);
cr->status = _cairo_path_fixed_line_to (&cr->path, x_fixed, y_fixed);
-
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
void
@@ -872,9 +946,10 @@ cairo_curve_to (cairo_t *cr,
cairo_fixed_t x2_fixed, y2_fixed;
cairo_fixed_t x3_fixed, y3_fixed;
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
_cairo_gstate_user_to_backend (cr->gstate, &x1, &y1);
_cairo_gstate_user_to_backend (cr->gstate, &x2, &y2);
@@ -893,8 +968,8 @@ cairo_curve_to (cairo_t *cr,
x1_fixed, y1_fixed,
x2_fixed, y2_fixed,
x3_fixed, y3_fixed);
-
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -936,9 +1011,10 @@ cairo_arc (cairo_t *cr,
double radius,
double angle1, double angle2)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
/* Do nothing, successfully, if radius is <= 0 */
if (radius <= 0.0)
@@ -953,8 +1029,6 @@ cairo_arc (cairo_t *cr,
_cairo_arc_path (cr, xc, yc, radius,
angle1, angle2);
-
- CAIRO_CHECK_SANITY (cr);
}
/**
@@ -977,9 +1051,10 @@ cairo_arc_negative (cairo_t *cr,
double radius,
double angle1, double angle2)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
/* Do nothing, successfully, if radius is <= 0 */
if (radius <= 0.0)
@@ -994,8 +1069,6 @@ cairo_arc_negative (cairo_t *cr,
_cairo_arc_path_negative (cr, xc, yc, radius,
angle1, angle2);
-
- CAIRO_CHECK_SANITY (cr);
}
/* XXX: NYI
@@ -1020,17 +1093,18 @@ cairo_rel_move_to (cairo_t *cr, double dx, double dy)
{
cairo_fixed_t dx_fixed, dy_fixed;
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
_cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy);
dx_fixed = _cairo_fixed_from_double (dx);
dy_fixed = _cairo_fixed_from_double (dy);
cr->status = _cairo_path_fixed_rel_move_to (&cr->path, dx_fixed, dy_fixed);
-
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
void
@@ -1038,17 +1112,18 @@ cairo_rel_line_to (cairo_t *cr, double dx, double dy)
{
cairo_fixed_t dx_fixed, dy_fixed;
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
_cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy);
dx_fixed = _cairo_fixed_from_double (dx);
dy_fixed = _cairo_fixed_from_double (dy);
cr->status = _cairo_path_fixed_rel_line_to (&cr->path, dx_fixed, dy_fixed);
-
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
slim_hidden_def(cairo_rel_line_to);
@@ -1062,9 +1137,10 @@ cairo_rel_curve_to (cairo_t *cr,
cairo_fixed_t dx2_fixed, dy2_fixed;
cairo_fixed_t dx3_fixed, dy3_fixed;
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
_cairo_gstate_user_to_device_distance (cr->gstate, &dx1, &dy1);
_cairo_gstate_user_to_device_distance (cr->gstate, &dx2, &dy2);
@@ -1083,8 +1159,8 @@ cairo_rel_curve_to (cairo_t *cr,
dx1_fixed, dy1_fixed,
dx2_fixed, dy2_fixed,
dx3_fixed, dy3_fixed);
-
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
void
@@ -1092,16 +1168,16 @@ cairo_rectangle (cairo_t *cr,
double x, double y,
double width, double height)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cairo_move_to (cr, x, y);
cairo_rel_line_to (cr, width, 0);
cairo_rel_line_to (cr, 0, height);
cairo_rel_line_to (cr, -width, 0);
cairo_close_path (cr);
- CAIRO_CHECK_SANITY (cr);
}
/* XXX: NYI
@@ -1112,19 +1188,22 @@ cairo_stroke_to_path (cairo_t *cr)
return;
cr->status = _cairo_gstate_stroke_path (cr->gstate);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
*/
void
cairo_close_path (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_path_fixed_close_path (&cr->path);
-
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
slim_hidden_def(cairo_close_path);
@@ -1138,13 +1217,14 @@ slim_hidden_def(cairo_close_path);
void
cairo_paint (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_paint (cr->gstate);
-
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -1164,18 +1244,24 @@ cairo_paint_with_alpha (cairo_t *cr,
cairo_color_t color;
cairo_pattern_union_t pattern;
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
+
+ if (CAIRO_ALPHA_IS_OPAQUE (alpha)) {
+ cairo_paint (cr);
+ return;
+ }
_cairo_color_init_rgba (&color, 1., 1., 1., alpha);
_cairo_pattern_init_solid (&pattern.solid, &color);
cr->status = _cairo_gstate_mask (cr->gstate, &pattern.base);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
_cairo_pattern_fini (&pattern.base);
-
- CAIRO_CHECK_SANITY (cr);
}
/**
@@ -1192,13 +1278,24 @@ void
cairo_mask (cairo_t *cr,
cairo_pattern_t *pattern)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
- cr->status = _cairo_gstate_mask (cr->gstate, pattern);
+ if (pattern == NULL) {
+ _cairo_error (cr, CAIRO_STATUS_NULL_POINTER);
+ return;
+ }
+
+ if (pattern->status) {
+ _cairo_error (cr, pattern->status);
+ return;
+ }
- CAIRO_CHECK_SANITY (cr);
+ cr->status = _cairo_gstate_mask (cr->gstate, pattern);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -1222,15 +1319,12 @@ cairo_mask_surface (cairo_t *cr,
cairo_pattern_t *pattern;
cairo_matrix_t matrix;
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
pattern = cairo_pattern_create_for_surface (surface);
- if (!pattern) {
- cr->status = CAIRO_STATUS_NO_MEMORY;
- return;
- }
cairo_matrix_init_translate (&matrix, - surface_x, - surface_y);
cairo_pattern_set_matrix (pattern, &matrix);
@@ -1275,13 +1369,14 @@ cairo_stroke (cairo_t *cr)
void
cairo_stroke_preserve (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_stroke (cr->gstate, &cr->path);
-
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
slim_hidden_def(cairo_stroke_preserve);
@@ -1315,36 +1410,41 @@ cairo_fill (cairo_t *cr)
void
cairo_fill_preserve (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_fill (cr->gstate, &cr->path);
-
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
slim_hidden_def(cairo_fill_preserve);
void
cairo_copy_page (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_copy_page (cr->gstate);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
void
cairo_show_page (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_show_page (cr->gstate);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
cairo_bool_t
@@ -1352,18 +1452,18 @@ cairo_in_stroke (cairo_t *cr, double x, double y)
{
int inside;
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return 0;
+ }
cr->status = _cairo_gstate_in_stroke (cr->gstate,
&cr->path,
x, y, &inside);
-
- CAIRO_CHECK_SANITY (cr);
-
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return 0;
+ }
return inside;
}
@@ -1373,18 +1473,18 @@ cairo_in_fill (cairo_t *cr, double x, double y)
{
int inside;
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return 0;
+ }
cr->status = _cairo_gstate_in_fill (cr->gstate,
&cr->path,
x, y, &inside);
-
- CAIRO_CHECK_SANITY (cr);
-
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return 0;
+ }
return inside;
}
@@ -1393,28 +1493,32 @@ void
cairo_stroke_extents (cairo_t *cr,
double *x1, double *y1, double *x2, double *y2)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_stroke_extents (cr->gstate,
&cr->path,
x1, y1, x2, y2);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
void
cairo_fill_extents (cairo_t *cr,
double *x1, double *y1, double *x2, double *y2)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_fill_extents (cr->gstate,
&cr->path,
x1, y1, x2, y2);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -1472,12 +1576,14 @@ cairo_clip (cairo_t *cr)
void
cairo_clip_preserve (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_clip (cr->gstate, &cr->path);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
slim_hidden_def(cairo_clip_preserve);
@@ -1500,12 +1606,14 @@ slim_hidden_def(cairo_clip_preserve);
void
cairo_reset_clip (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_reset_clip (cr->gstate);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -1529,12 +1637,14 @@ cairo_select_font_face (cairo_t *cr,
cairo_font_slant_t slant,
cairo_font_weight_t weight)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_select_font_face (cr->gstate, family, slant, weight);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -1546,19 +1656,27 @@ cairo_select_font_face (cairo_t *cr,
* Return value: the current font object. Can return %NULL
* on out-of-memory or if the context is already in
* an error state. This object is owned by cairo. To keep
- * a reference to it, you must call cairo_font_reference().
+ * a reference to it, you must call cairo_font_face_reference().
**/
cairo_font_face_t *
cairo_get_font_face (cairo_t *cr)
{
cairo_font_face_t *font_face;
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return NULL;
+ }
cr->status = _cairo_gstate_get_font_face (cr->gstate, &font_face);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
+ /* XXX: When available:
+ return _cairo_font_face_create_in_error (cr->status);
+ */
+ return NULL;
+ }
+
return font_face;
}
@@ -1574,12 +1692,14 @@ void
cairo_font_extents (cairo_t *cr,
cairo_font_extents_t *extents)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_get_font_extents (cr->gstate, extents);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -1595,12 +1715,14 @@ void
cairo_set_font_face (cairo_t *cr,
cairo_font_face_t *font_face)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_set_font_face (cr->gstate, font_face);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -1617,12 +1739,14 @@ cairo_set_font_face (cairo_t *cr,
void
cairo_set_font_size (cairo_t *cr, double size)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_set_font_size (cr->gstate, size);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -1642,12 +1766,14 @@ void
cairo_set_font_matrix (cairo_t *cr,
const cairo_matrix_t *matrix)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_set_font_matrix (cr->gstate, matrix);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -1661,7 +1787,6 @@ cairo_set_font_matrix (cairo_t *cr,
void
cairo_get_font_matrix (cairo_t *cr, cairo_matrix_t *matrix)
{
- CAIRO_CHECK_SANITY (cr);
_cairo_gstate_get_font_matrix (cr->gstate, matrix);
}
@@ -1694,9 +1819,10 @@ cairo_text_extents (cairo_t *cr,
int num_glyphs;
double x, y;
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
if (utf8 == NULL) {
extents->x_bearing = 0.0;
@@ -1713,19 +1839,20 @@ cairo_text_extents (cairo_t *cr,
cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8,
x, y,
&glyphs, &num_glyphs);
- CAIRO_CHECK_SANITY (cr);
if (cr->status) {
if (glyphs)
free (glyphs);
+ _cairo_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_glyph_extents (cr->gstate, glyphs, num_glyphs, extents);
- CAIRO_CHECK_SANITY (cr);
-
if (glyphs)
free (glyphs);
+
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -1752,13 +1879,15 @@ cairo_glyph_extents (cairo_t *cr,
int num_glyphs,
cairo_text_extents_t *extents)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_glyph_extents (cr->gstate, glyphs, num_glyphs,
extents);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
void
@@ -1768,9 +1897,10 @@ cairo_show_text (cairo_t *cr, const char *utf8)
int num_glyphs;
double x, y;
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
if (utf8 == NULL)
return;
@@ -1780,30 +1910,34 @@ cairo_show_text (cairo_t *cr, const char *utf8)
cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8,
x, y,
&glyphs, &num_glyphs);
- CAIRO_CHECK_SANITY (cr);
if (cr->status) {
if (glyphs)
free (glyphs);
+ _cairo_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_show_glyphs (cr->gstate, glyphs, num_glyphs);
- CAIRO_CHECK_SANITY (cr);
if (glyphs)
free (glyphs);
+
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
void
cairo_show_glyphs (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_show_glyphs (cr->gstate, glyphs, num_glyphs);
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
void
@@ -1813,44 +1947,48 @@ cairo_text_path (cairo_t *cr, const char *utf8)
int num_glyphs;
double x, y;
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cairo_get_current_point (cr, &x, &y);
cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8,
x, y,
&glyphs, &num_glyphs);
- CAIRO_CHECK_SANITY (cr);
if (cr->status) {
if (glyphs)
free (glyphs);
+ _cairo_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_glyph_path (cr->gstate,
glyphs, num_glyphs,
&cr->path);
- CAIRO_CHECK_SANITY (cr);
-
if (glyphs)
free (glyphs);
+
+ if (cr->status)
+ _cairo_error (cr, cr->status);
+
}
void
cairo_glyph_path (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
cr->status = _cairo_gstate_glyph_path (cr->gstate,
glyphs, num_glyphs,
&cr->path);
-
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
/**
@@ -1864,7 +2002,6 @@ cairo_glyph_path (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs)
cairo_operator_t
cairo_get_operator (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
return _cairo_gstate_get_operator (cr->gstate);
}
@@ -1879,7 +2016,6 @@ cairo_get_operator (cairo_t *cr)
double
cairo_get_tolerance (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
return _cairo_gstate_get_tolerance (cr->gstate);
}
@@ -1911,8 +2047,6 @@ cairo_get_current_point (cairo_t *cr, double *x_ret, double *y_ret)
cairo_fixed_t x_fixed, y_fixed;
double x, y;
- CAIRO_CHECK_SANITY (cr);
-
status = _cairo_path_fixed_get_current_point (&cr->path, &x_fixed, &y_fixed);
if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
x = 0.0;
@@ -1927,8 +2061,6 @@ cairo_get_current_point (cairo_t *cr, double *x_ret, double *y_ret)
*x_ret = x;
if (y_ret)
*y_ret = y;
-
- CAIRO_CHECK_SANITY (cr);
}
slim_hidden_def(cairo_get_current_point);
@@ -1943,7 +2075,6 @@ slim_hidden_def(cairo_get_current_point);
cairo_fill_rule_t
cairo_get_fill_rule (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
return _cairo_gstate_get_fill_rule (cr->gstate);
}
@@ -1958,7 +2089,6 @@ cairo_get_fill_rule (cairo_t *cr)
double
cairo_get_line_width (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
return _cairo_gstate_get_line_width (cr->gstate);
}
@@ -1973,7 +2103,6 @@ cairo_get_line_width (cairo_t *cr)
cairo_line_cap_t
cairo_get_line_cap (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
return _cairo_gstate_get_line_cap (cr->gstate);
}
@@ -1988,7 +2117,6 @@ cairo_get_line_cap (cairo_t *cr)
cairo_line_join_t
cairo_get_line_join (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
return _cairo_gstate_get_line_join (cr->gstate);
}
@@ -2003,7 +2131,6 @@ cairo_get_line_join (cairo_t *cr)
double
cairo_get_miter_limit (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
return _cairo_gstate_get_miter_limit (cr->gstate);
}
@@ -2017,7 +2144,6 @@ cairo_get_miter_limit (cairo_t *cr)
void
cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix)
{
- CAIRO_CHECK_SANITY (cr);
_cairo_gstate_get_matrix (cr->gstate, matrix);
}
@@ -2030,14 +2156,18 @@ cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix)
*
* Return value: the target surface, (or NULL if @cr is in an error
* state). This object is owned by cairo. To keep a reference to it,
- * you must call cairo_pattern_reference().
+ * you must call cairo_surface_reference().
**/
cairo_surface_t *
cairo_get_target (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
+ /* XXX: Should be as follows when available:
+ return _cairo_surface_create_in_error ();
+ */
return NULL;
+ }
return _cairo_gstate_get_target (cr->gstate);
}
@@ -2053,13 +2183,25 @@ cairo_get_target (cairo_t *cr)
* Return value: the copy of the current path. The caller owns the
* returned object and should call cairo_path_destroy() when finished
* with it.
+ *
+ * This function will always return a valid pointer, but the result
+ * will have no data, (data==NULL and num_data==0), if either of the
+ * following conditions hold:
+ *
+ * 1) If there is insufficient memory to copy the path. In this case
+ * path->status will be set to CAIRO_STATUS_NO_MEMORY.
+ *
+ * 2) If @cr is already in an error state. In this case path->status
+ * will contain the same status that would be returned by
+ * cairo_status(cr).
**/
cairo_path_t *
cairo_copy_path (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
- return &_cairo_path_nil;
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
+ return _cairo_path_data_create_in_error (cr->status);
+ }
return _cairo_path_data_create (&cr->path, cr->gstate);
}
@@ -2082,15 +2224,25 @@ cairo_copy_path (cairo_t *cr)
* Return value: the copy of the current path. The caller owns the
* returned object and should call cairo_path_destroy() when finished
* with it.
+ *
+ * This function will always return a valid pointer, but the result
+ * will have no data, (data==NULL and num_data==0), if either of the
+ * following conditions hold:
+ *
+ * 1) If there is insufficient memory to copy the path. In this case
+ * path->status will be set to CAIRO_STATUS_NO_MEMORY.
+ *
+ * 2) If @cr is already in an error state. In this case path->status
+ * will contain the same status that would be returned by
+ * cairo_status(cr).
**/
cairo_path_t *
cairo_copy_path_flat (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
if (cr->status)
- return &_cairo_path_nil;
-
- return _cairo_path_data_create_flat (&cr->path, cr->gstate);
+ return _cairo_path_data_create_in_error (cr->status);
+ else
+ return _cairo_path_data_create_flat (&cr->path, cr->gstate);
}
/**
@@ -2098,43 +2250,47 @@ cairo_copy_path_flat (cairo_t *cr)
* @cr: a cairo context
* @path: path to be appended
*
- * Append the @path onto the current path. See #cairo_path_t
- * for details on how the path data structure must be initialized.
+ * Append the @path onto the current path. The @path may be either the
+ * return value from one of cairo_copy_path() or
+ * cairo_copy_path_flat() or it may be constructed manually. See
+ * #cairo_path_t for details on how the path data structure should be
+ * initialized, and note that path->status must be initialized to
+ * CAIRO_STATUS_SUCCESS.
**/
void
cairo_append_path (cairo_t *cr,
cairo_path_t *path)
{
- CAIRO_CHECK_SANITY (cr);
- if (cr->status)
+ if (cr->status) {
+ _cairo_error (cr, cr->status);
return;
+ }
if (path == NULL || path->data == NULL) {
- cr->status = CAIRO_STATUS_NULL_POINTER;
+ _cairo_error (cr, CAIRO_STATUS_NULL_POINTER);
return;
}
- if (path == &_cairo_path_nil) {
- cr->status = CAIRO_STATUS_NO_MEMORY;
+ if (path->status) {
+ _cairo_error (cr, path->status);
return;
}
cr->status = _cairo_path_data_append_to_context (path, cr);
-
- CAIRO_CHECK_SANITY (cr);
+ if (cr->status)
+ _cairo_error (cr, cr->status);
}
cairo_status_t
cairo_status (cairo_t *cr)
{
- CAIRO_CHECK_SANITY (cr);
return cr->status;
}
const char *
-cairo_status_string (cairo_t *cr)
+cairo_status_to_string (cairo_status_t status)
{
- switch (cr->status) {
+ switch (status) {
case CAIRO_STATUS_SUCCESS:
return "success";
case CAIRO_STATUS_NO_MEMORY:
@@ -2163,8 +2319,8 @@ cairo_status_string (cairo_t *cr)
return "the target surface has been finished";
case CAIRO_STATUS_SURFACE_TYPE_MISMATCH:
return "the surface type is not appropriate for the operation";
- case CAIRO_STATUS_BAD_NESTING:
- return "drawing operations interleaved for two contexts for the same surface";
+ case CAIRO_STATUS_PATTERN_TYPE_MISMATCH:
+ return "the pattern type is not appropriate for the operation";
}
return "<unknown error status>";
diff --git a/src/cairo.h b/src/cairo.h
index 4cb3a023e..0fcd85602 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -130,6 +130,7 @@ typedef struct _cairo_user_data_key {
* @CAIRO_STATUS_NO_MEMORY:
* @CAIRO_STATUS_INVALID_RESTORE:
* @CAIRO_STATUS_INVALID_POP_GROUP:
+ * @CAIRO_STATUS_NO_CURRENT_POINT:
* @CAIRO_STATUS_INVALID_MATRIX:
* @CAIRO_STATUS_NO_TARGET_SURFACE:
* @CAIRO_STATUS_NULL_POINTER:
@@ -139,11 +140,6 @@ typedef struct _cairo_user_data_key {
* @CAIRO_STATUS_WRITE_ERROR:
* @CAIRO_STATUS_SURFACE_FINISHED:
* @CAIRO_STATUS_SURFACE_TYPE_MISMATCH:
- * @CAIRO_STATUS_BAD_NESTING: the same surface was used as the
- * target surface for two different cairo contexts at once,
- * and more drawing was done on the first context before the
- * surface was unset as the target for the second context.
- * See the documentation for cairo_create().
*
* #cairo_status_t is used to indicate errors that can occur when
* using Cairo. In some cases it is returned directly by functions.
@@ -165,7 +161,7 @@ typedef enum cairo_status {
CAIRO_STATUS_WRITE_ERROR,
CAIRO_STATUS_SURFACE_FINISHED,
CAIRO_STATUS_SURFACE_TYPE_MISMATCH,
- CAIRO_STATUS_BAD_NESTING
+ CAIRO_STATUS_PATTERN_TYPE_MISMATCH
} cairo_status_t;
/**
@@ -767,8 +763,6 @@ cairo_get_miter_limit (cairo_t *cr);
void
cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix);
-/* XXX: Need to decide the memory management semantics of this
- function. Should it reference the surface again? */
cairo_surface_t *
cairo_get_target (cairo_t *cr);
@@ -830,14 +824,16 @@ cairo_get_target (cairo_t *cr);
* cairo_path_destroy (path);
* </programlisting></informalexample>
*/
+typedef enum cairo_path_data_type {
+ CAIRO_PATH_MOVE_TO,
+ CAIRO_PATH_LINE_TO,
+ CAIRO_PATH_CURVE_TO,
+ CAIRO_PATH_CLOSE_PATH
+} cairo_path_data_type_t;
+
typedef union {
struct {
- enum {
- CAIRO_PATH_MOVE_TO,
- CAIRO_PATH_LINE_TO,
- CAIRO_PATH_CURVE_TO,
- CAIRO_PATH_CLOSE_PATH
- } type;
+ cairo_path_data_type_t type;
int length;
} header;
struct {
@@ -862,6 +858,7 @@ typedef union {
* includes both headers and coordinates for each portion.
**/
typedef struct cairo_path {
+ cairo_status_t status;
cairo_path_data_t *data;
int num_data;
} cairo_path_t;
@@ -885,7 +882,7 @@ cairo_status_t
cairo_status (cairo_t *cr);
const char *
-cairo_status_string (cairo_t *cr);
+cairo_status_to_string (cairo_status_t status);
/* Surface manipulation */
@@ -1013,21 +1010,24 @@ void
cairo_pattern_destroy (cairo_pattern_t *pattern);
cairo_status_t
+cairo_pattern_status (cairo_pattern_t *pattern);
+
+void
cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
double offset,
double red, double green, double blue);
-cairo_status_t
+void
cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
double offset,
double red, double green, double blue,
double alpha);
-cairo_status_t
+void
cairo_pattern_set_matrix (cairo_pattern_t *pattern,
const cairo_matrix_t *matrix);
-cairo_status_t
+void
cairo_pattern_get_matrix (cairo_pattern_t *pattern,
cairo_matrix_t *matrix);
@@ -1037,7 +1037,7 @@ typedef enum {
CAIRO_EXTEND_REFLECT
} cairo_extend_t;
-cairo_status_t
+void
cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend);
cairo_extend_t
@@ -1052,7 +1052,7 @@ typedef enum {
CAIRO_FILTER_GAUSSIAN
} cairo_filter_t;
-cairo_status_t
+void
cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter);
cairo_filter_t
@@ -1139,7 +1139,6 @@ cairo_matrix_transform_point (const cairo_matrix_t *matrix,
#define cairo_current_matrix cairo_current_matrix_REPLACED_BY_cairo_get_matrix
#define cairo_current_target_surface cairo_current_target_surface_REPLACED_BY_cairo_get_target
#define cairo_get_status cairo_get_status_REPLACED_BY_cairo_status
-#define cairo_get_status_string cairo_get_status_string_REPLACED_BY_cairo_status_string
#define cairo_concat_matrix cairo_concat_matrix_REPLACED_BY_cairo_transform
#define cairo_scale_font cairo_scale_font_REPLACED_BY_cairo_set_font_size
#define cairo_select_font cairo_select_font_REPLACED_BY_cairo_select_font_face
@@ -1188,6 +1187,8 @@ cairo_matrix_transform_point (const cairo_matrix_t *matrix,
#define cairo_set_target_win32 cairo_set_target_win32_DEPRECATED_BY_cairo_win32_surface_create
#define cairo_set_target_xcb cairo_set_target_xcb_DEPRECATED_BY_cairo_xcb_surface_create
#define cairo_set_target_drawable cairo_set_target_drawable_DEPRECATED_BY_cairo_xlib_surface_create
+#define cairo_get_status_string cairo_get_status_string_DEPRECATED_BY_cairo_status_AND_cairo_status_to_string
+#define cairo_status_string cairo_status_string_DEPRECATED_BY_cairo_status_AND_cairo_status_to_string
#endif
diff --git a/src/cairoint.h b/src/cairoint.h
index 90d59b2cb..1b21228d7 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -147,6 +147,8 @@ typedef cairo_fixed_16_16_t cairo_fixed_t;
#define CAIRO_MAXSHORT SHRT_MAX
#define CAIRO_MINSHORT SHRT_MIN
+#define CAIRO_ALPHA_IS_OPAQUE(alpha) ((alpha) >= ((double)0xff00 / (double)0xffff))
+
typedef struct _cairo_point {
cairo_fixed_t x;
cairo_fixed_t y;
@@ -191,8 +193,6 @@ typedef enum cairo_int_status {
CAIRO_INT_STATUS_UNSUPPORTED
} cairo_int_status_t;
-#define CAIRO_OK(status) ((status) == CAIRO_STATUS_SUCCESS)
-
typedef enum cairo_direction {
CAIRO_DIRECTION_FORWARD,
CAIRO_DIRECTION_REVERSE
@@ -289,7 +289,7 @@ cairo_private void
_cairo_user_data_array_init (cairo_user_data_array_t *array);
cairo_private void
-_cairo_user_data_array_destroy (cairo_user_data_array_t *array);
+_cairo_user_data_array_fini (cairo_user_data_array_t *array);
cairo_private void *
_cairo_user_data_array_get_data (cairo_user_data_array_t *array,
@@ -356,7 +356,6 @@ typedef struct {
#undef CAIRO_MEASURE_CACHE_PERFORMANCE
typedef struct {
- unsigned long refcount;
const cairo_cache_backend_t *backend;
const cairo_cache_arrangement_t *arrangement;
cairo_cache_entry_base_t **entries;
@@ -568,7 +567,6 @@ typedef struct _cairo_surface_backend {
cairo_surface_t *
(*create_similar) (void *surface,
cairo_format_t format,
- int drawable,
int width,
int height);
@@ -646,10 +644,43 @@ typedef struct _cairo_surface_backend {
cairo_int_status_t
(*show_page) (void *surface);
+ /* Set given region as the clip region for the surface, replacing
+ * any previously set clip region. Passing in a NULL region will
+ * clear the surface clip region.
+ *
+ * The surface is expected to store the clip region and clip all
+ * following drawing operations against it until the clip region
+ * is cleared of replaced by another clip region.
+ *
+ * Cairo will call this function whenever a clip path can be
+ * represented as a device pixel aligned set of rectangles. When
+ * this is not possible, cairo will use mask surfaces for
+ * clipping.
+ */
cairo_int_status_t
(*set_clip_region) (void *surface,
pixman_region16_t *region);
+ /* Intersect the given path against the clip path currently set in
+ * the surface, using the given fill_rule and tolerance, and set
+ * the result as the new clipping path for the surface. Passing
+ * in a NULL path will clear the surface clipping path.
+ *
+ * The surface is expected to store the resulting clip path and
+ * clip all following drawing operations against it until the clip
+ * path cleared or intersected with a new path.
+ *
+ * If a surface implements this function, set_clip_region() will
+ * never be called and should not be implemented. If this
+ * function is not implemented cairo will use set_clip_region()
+ * (if available) and mask surfaces for clipping.
+ */
+ cairo_int_status_t
+ (*intersect_clip_path) (void *dst,
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance);
+
/* Get the extents of the current surface. For many surface types
* this will be as simple as { x=0, y=0, width=surface->width,
* height=surface->height}.
@@ -687,7 +718,9 @@ typedef struct _cairo_surface_backend {
(*fill_path) (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *dst,
- cairo_path_fixed_t *path);
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance);
} cairo_surface_backend_t;
@@ -699,7 +732,11 @@ typedef struct _cairo_format_masks {
unsigned long blue_mask;
} cairo_format_masks_t;
-typedef struct _cairo_surface_save cairo_surface_save_t;
+typedef enum _cairo_clip_mode {
+ CAIRO_CLIP_MODE_PATH,
+ CAIRO_CLIP_MODE_REGION,
+ CAIRO_CLIP_MODE_MASK
+} cairo_clip_mode_t;
struct _cairo_surface {
const cairo_surface_backend_t *backend;
@@ -708,17 +745,24 @@ struct _cairo_surface {
cairo_bool_t finished;
cairo_user_data_array_t user_data;
- cairo_matrix_t matrix;
- cairo_filter_t filter;
- int repeat;
-
double device_x_offset;
double device_y_offset;
- cairo_surface_save_t *saves; /* Stack of saved states from cairo_surface_begin/end() */
- int level; /* Number saved states */
-
- pixman_region16_t *clip_region;
+ /*
+ * Each time a clip region is modified, it gets the next value in this
+ * sequence. This means that clip regions for this surface are uniquely
+ * identified andupdates to the clip can be readily identified
+ */
+ unsigned int next_clip_serial;
+ /*
+ * The serial number of the current clip. This is set when
+ * the surface clipping is set. The gstate can then cheaply
+ * check whether the surface clipping is already correct before
+ * performing a rendering operation.
+ *
+ * The special value '0' is reserved for the unclipped case.
+ */
+ unsigned int current_clip_serial;
};
struct _cairo_image_surface {
@@ -779,6 +823,7 @@ typedef struct _cairo_color_stop {
struct _cairo_pattern {
cairo_pattern_type_t type;
unsigned int ref_count;
+ cairo_status_t status;
cairo_matrix_t matrix;
cairo_filter_t filter;
cairo_extend_t extend;
@@ -840,7 +885,6 @@ typedef struct _cairo_surface_attributes {
int x_offset;
int y_offset;
cairo_bool_t acquired;
- cairo_bool_t clip_saved;
void *extra;
} cairo_surface_attributes_t;
@@ -854,19 +898,23 @@ typedef struct _cairo_traps {
#define CAIRO_FONT_SLANT_DEFAULT CAIRO_FONT_SLANT_NORMAL
#define CAIRO_FONT_WEIGHT_DEFAULT CAIRO_FONT_WEIGHT_NORMAL
+#define CAIRO_WIN32_FONT_FAMILY_DEFAULT "Arial"
+#define CAIRO_ATSUI_FONT_FAMILY_DEFAULT "Monaco"
+#define CAIRO_FT_FONT_FAMILY_DEFAULT ""
+
#if CAIRO_HAS_WIN32_FONT
-#define CAIRO_FONT_FAMILY_DEFAULT "Arial"
+#define CAIRO_FONT_FAMILY_DEFAULT CAIRO_WIN32_FONT_FAMILY_DEFAULT
#define CAIRO_FONT_BACKEND_DEFAULT &cairo_win32_scaled_font_backend
#elif CAIRO_HAS_ATSUI_FONT
-#define CAIRO_FONT_FAMILY_DEFAULT "Monaco"
+#define CAIRO_FONT_FAMILY_DEFAULT CAIRO_ATSUI_FONT_FAMILY_DEFAULT
#define CAIRO_FONT_BACKEND_DEFAULT &cairo_atsui_scaled_font_backend
#elif CAIRO_HAS_FT_FONT
-#define CAIRO_FONT_FAMILY_DEFAULT "serif"
+#define CAIRO_FONT_FAMILY_DEFAULT CAIRO_FT_FONT_FAMILY_DEFAULT
#define CAIRO_FONT_BACKEND_DEFAULT &cairo_ft_scaled_font_backend
#endif
@@ -880,13 +928,6 @@ typedef struct _cairo_traps {
#define CAIRO_GSTATE_MITER_LIMIT_DEFAULT 10.0
#define CAIRO_GSTATE_DEFAULT_FONT_SIZE 10.0
-/* Need a name distinct from the cairo_clip function */
-typedef struct _cairo_clip_rec {
- cairo_rectangle_t rect;
- pixman_region16_t *region;
- cairo_surface_t *surface;
-} cairo_clip_rec_t;
-
typedef struct _cairo_gstate cairo_gstate_t;
typedef struct _cairo_stroke_face {
@@ -930,16 +971,6 @@ _cairo_fixed_integer_ceil (cairo_fixed_t f);
cairo_private cairo_gstate_t *
_cairo_gstate_create (cairo_surface_t *target);
-cairo_private cairo_status_t
-_cairo_gstate_init (cairo_gstate_t *gstate,
- cairo_surface_t *target);
-
-cairo_private cairo_status_t
-_cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other);
-
-cairo_private void
-_cairo_gstate_fini (cairo_gstate_t *gstate);
-
cairo_private void
_cairo_gstate_destroy (cairo_gstate_t *gstate);
@@ -947,9 +978,6 @@ cairo_private cairo_gstate_t *
_cairo_gstate_clone (cairo_gstate_t *gstate);
cairo_private cairo_status_t
-_cairo_gstate_copy (cairo_gstate_t *dest, cairo_gstate_t *src);
-
-cairo_private cairo_status_t
_cairo_gstate_begin_group (cairo_gstate_t *gstate);
cairo_private cairo_status_t
@@ -961,10 +989,6 @@ _cairo_gstate_get_target (cairo_gstate_t *gstate);
cairo_private cairo_status_t
_cairo_gstate_set_source (cairo_gstate_t *gstate, cairo_pattern_t *source);
-cairo_status_t
-_cairo_gstate_set_source_solid (cairo_gstate_t *gstate,
- const cairo_color_t *color);
-
cairo_private cairo_pattern_t *
_cairo_gstate_get_source (cairo_gstate_t *gstate);
@@ -1378,11 +1402,10 @@ _cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
cairo_gstate_t *gstate,
cairo_traps_t *traps);
-/* cairo_surface.c */
+/* cairo-surface.c */
cairo_private cairo_surface_t *
_cairo_surface_create_similar_scratch (cairo_surface_t *other,
cairo_format_t format,
- int drawable,
int width,
int height);
@@ -1397,14 +1420,8 @@ cairo_private void
_cairo_surface_init (cairo_surface_t *surface,
const cairo_surface_backend_t *backend);
-cairo_private cairo_status_t
-_cairo_surface_begin (cairo_surface_t *surface);
-
-cairo_private cairo_status_t
-_cairo_surface_begin_reset_clip (cairo_surface_t *surface);
-
-cairo_private cairo_status_t
-_cairo_surface_end (cairo_surface_t *surface);
+cairo_private cairo_clip_mode_t
+_cairo_surface_get_clip_mode (cairo_surface_t *surface);
cairo_private cairo_status_t
_cairo_surface_fill_rectangle (cairo_surface_t *surface,
@@ -1437,10 +1454,12 @@ _cairo_surface_fill_rectangles (cairo_surface_t *surface,
int num_rects);
cairo_private cairo_int_status_t
-_cairo_surface_fill_path (cairo_operator_t operator,
- cairo_pattern_t *pattern,
- cairo_surface_t *dst,
- cairo_path_fixed_t *path);
+_cairo_surface_fill_path (cairo_operator_t operator,
+ cairo_pattern_t *pattern,
+ cairo_surface_t *dst,
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance);
cairo_private cairo_status_t
_cairo_surface_composite_trapezoids (cairo_operator_t operator,
@@ -1490,13 +1509,30 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
cairo_surface_t *src,
cairo_surface_t **clone_out);
+cairo_private unsigned int
+_cairo_surface_get_current_clip_serial (cairo_surface_t *surface);
+
+cairo_private unsigned int
+_cairo_surface_allocate_clip_serial (cairo_surface_t *surface);
+
+cairo_private cairo_status_t
+_cairo_surface_reset_clip (cairo_surface_t *surface);
+
+cairo_private cairo_status_t
+_cairo_surface_set_clip_region (cairo_surface_t *surface,
+ pixman_region16_t *region,
+ unsigned int serial);
+
+typedef struct _cairo_clip_path cairo_clip_path_t;
+
cairo_private cairo_status_t
-_cairo_surface_set_clip_region (cairo_surface_t *surface,
- pixman_region16_t *region);
+_cairo_surface_set_clip_path (cairo_surface_t *surface,
+ cairo_clip_path_t *clip_path,
+ unsigned int serial);
cairo_private cairo_status_t
-_cairo_surface_get_clip_extents (cairo_surface_t *surface,
- cairo_rectangle_t *rectangle);
+_cairo_surface_get_extents (cairo_surface_t *surface,
+ cairo_rectangle_t *rectangle);
cairo_private cairo_status_t
_cairo_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
@@ -1524,18 +1560,6 @@ _cairo_image_surface_create_with_masks (unsigned char *data,
cairo_private void
_cairo_image_surface_assume_ownership_of_data (cairo_image_surface_t *surface);
-cairo_private cairo_status_t
-_cairo_image_surface_set_matrix (cairo_image_surface_t *surface,
- const cairo_matrix_t *matrix);
-
-cairo_private cairo_status_t
-_cairo_image_surface_set_filter (cairo_image_surface_t *surface,
- cairo_filter_t filter);
-
-cairo_private cairo_status_t
-_cairo_image_surface_set_repeat (cairo_image_surface_t *surface,
- int repeat);
-
cairo_private cairo_int_status_t
_cairo_image_surface_set_clip_region (cairo_image_surface_t *surface,
pixman_region16_t *region);
@@ -1689,8 +1713,9 @@ _cairo_slope_counter_clockwise (cairo_slope_t *a, cairo_slope_t *b);
/* cairo_pattern.c */
-cairo_private cairo_status_t
-_cairo_pattern_init_copy (cairo_pattern_t *pattern, cairo_pattern_t *other);
+cairo_private void
+_cairo_pattern_init_copy (cairo_pattern_t *pattern,
+ const cairo_pattern_t *other);
cairo_private void
_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
@@ -1715,6 +1740,9 @@ _cairo_pattern_fini (cairo_pattern_t *pattern);
cairo_private cairo_pattern_t *
_cairo_pattern_create_solid (const cairo_color_t *color);
+cairo_pattern_t *
+_cairo_pattern_create_in_error (cairo_status_t status);
+
cairo_private void
_cairo_pattern_transform (cairo_pattern_t *pattern,
const cairo_matrix_t *ctm_inverse);
diff --git a/test/.cvsignore b/test/.cvsignore
index beaae22b7..0b4c1531c 100644
--- a/test/.cvsignore
+++ b/test/.cvsignore
@@ -20,6 +20,8 @@ move-to-show-surface
paint
paint-with-alpha
path-data
+pdf-clip
+pdf-clip.pdf
pdf-surface
pdf-surface.pdf
ps-surface
@@ -29,6 +31,7 @@ rel-path
scale-source-surface-paint
select-font-no-show-text
self-copy
+self-intersecting
set-source
source-clip
source-surface-scale-paint
diff --git a/test/Makefile.am b/test/Makefile.am
index 0ab593678..48204192d 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -20,6 +20,7 @@ pixman-rotate \
scale-source-surface-paint \
select-font-no-show-text \
self-copy \
+self-intersecting \
set-source \
source-clip \
source-surface-scale-paint \
@@ -34,7 +35,7 @@ user-data \
rel-path
if CAIRO_HAS_PDF_SURFACE
-TESTS += pdf-surface
+TESTS += pdf-surface pdf-clip
endif
if CAIRO_HAS_PS_SURFACE
@@ -67,6 +68,7 @@ path-data-ref.png \
pixman-rotate-ref.png \
romedalen.png \
self-copy-ref.png \
+self-intersecting-ref.png \
scale-source-surface-paint-ref.png \
set-source-ref.png \
source-clip-ref.png \
@@ -93,7 +95,7 @@ rel-path-ref.png
XFAIL_TESTS = \
filter-nearest-offset \
pixman-rotate \
-self-copy \
+self-intersecting \
source-surface-scale-paint \
text-rotate
@@ -103,7 +105,12 @@ check_PROGRAMS = $(TESTS)
# not be the most portable approach, but it is pragmatic and I'm
# willing to do something cleaner as soon as it causes someone a
# problem.
-INCLUDES = -D_GNU_SOURCE -I$(srcdir) $(CAIRO_CFLAGS) -I$(top_srcdir)/src
+INCLUDES = \
+ -D_GNU_SOURCE \
+ $(CAIRO_CFLAGS) \
+ -I$(srcdir) \
+ -I$(top_srcdir)/src \
+ -I$(top_builddir)/src
noinst_LTLIBRARIES = libcairotest.la
@@ -141,11 +148,13 @@ paint_LDADD = $(LDADDS)
paint_with_alpha_LDADD = $(LDADDS)
path_data_LDADD = $(LDADDS)
pdf_surface_LDADD = $(LDADDS)
+pdf_clip_LDADD = $(LDADDS)
ps_surface_LDADD = $(LDADDS)
pixman_rotate_LDADD = $(LDADDS)
scale_source_surface_paint_LDADD = $(LDADDS)
select_font_no_show_text_LDADD = $(LDADDS)
self_copy_LDADD = $(LDADDS)
+self_intersecting_LDADD = $(LDADDS)
set_source_LDADD = $(LDADDS)
source_clip_LDADD = $(LDADDS)
source_surface_scale_paint_LDADD = $(LDADDS)
@@ -163,4 +172,10 @@ xlib_surface_LDADD = $(LDADDS)
noinst_PROGRAMS = imagediff
imagediff_LDADD = $(LDADDS)
-CLEANFILES = *-out.png *-diff.png *.log ps-surface.ps pdf-surface.pdf
+CLEANFILES = \
+ *-out.png \
+ *-diff.png \
+ *.log \
+ ps-surface.ps \
+ pdf-surface.pdf \
+ pdf-clip.pdf
diff --git a/test/cairo-test.c b/test/cairo-test.c
index d8ce6800f..a17cd6f8b 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -440,7 +440,8 @@ cairo_test_for_target (cairo_test_t *test,
}
if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) {
- cairo_test_log ("Error: Function under test left cairo status in an error state: %s\n", cairo_status_string (cr));
+ cairo_test_log ("Error: Function under test left cairo status in an error state: %s\n",
+ cairo_status_to_string (cairo_status (cr)));
return CAIRO_TEST_FAILURE;
}
diff --git a/test/clip-twice-ref.png b/test/clip-twice-ref.png
index ab0ae1aeb..bd3e3dbec 100644
--- a/test/clip-twice-ref.png
+++ b/test/clip-twice-ref.png
Binary files differ
diff --git a/test/clip-twice.c b/test/clip-twice.c
index eebfec944..446447c68 100644
--- a/test/clip-twice.c
+++ b/test/clip-twice.c
@@ -63,6 +63,12 @@ draw (cairo_t *cr, int width, int height)
cairo_close_path (cr);
cairo_fill (cr);
+ cairo_new_path (cr);
+ cairo_arc (cr, WIDTH / 2, HEIGHT / 2, WIDTH / 5, 0, 2 * M_PI);
+ cairo_clip (cr);
+ cairo_set_source_rgb (cr, 1, 1, 0);
+ cairo_paint (cr);
+
return CAIRO_TEST_SUCCESS;
}
diff --git a/test/pdf-clip.c b/test/pdf-clip.c
new file mode 100644
index 000000000..4d6d75cf8
--- /dev/null
+++ b/test/pdf-clip.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * 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
+ * Red Hat, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Kristian Høgsberg <krh@redhat.com>
+ */
+
+#include <stdio.h>
+
+#include <cairo-pdf.h>
+#include "cairo-test.h"
+
+/* Test PDF clipping */
+
+#define WIDTH_IN_POINTS 600
+#define HEIGHT_IN_POINTS 600
+
+static void
+test_clip (cairo_t *cr, double width, double height)
+{
+ cairo_t *cr2;
+
+ /* Basic test; set a square clip and draw a circle to be clipped
+ * against it.*/
+
+ cairo_rectangle (cr, 100, 100, 400, 400);
+ cairo_clip (cr);
+ cairo_arc (cr, 300, 300, 210, 0, 2 * M_PI);
+ cairo_set_source_rgb (cr, 1, 0, 0);
+ cairo_fill (cr);
+
+ /* Add a plus shaped clip path to the square clip and draw a big
+ * green square to test the new clip path. */
+
+ cairo_save (cr);
+
+ cairo_rectangle (cr, 250, 100, 100, 400);
+ cairo_rectangle (cr, 100, 250, 400, 100);
+ cairo_clip (cr);
+
+ cairo_rectangle (cr, 0, 0, 600, 600);
+ cairo_set_source_rgb (cr, 0, 1, 0);
+ cairo_fill (cr);
+
+ cairo_restore (cr);
+
+ /* Set a bezier shape in addition to the rectangle clip set before
+ * the cairo_save() to verify that we successfully removed the
+ * plus shaped clip path and can set a new clip.*/
+
+ cairo_move_to (cr, 600, 0);
+ cairo_curve_to (cr, 300, 600, 0, 300, 600, 0);
+ cairo_clip (cr);
+
+ cairo_rectangle (cr, 0, 0, 600, 600);
+ cairo_set_source_rgb (cr, 0, 0, 1);
+ cairo_fill (cr);
+
+ /* Create a new context for this surface to test overlapped
+ * drawing from two contexts */
+ cr2 = cairo_create (cairo_get_target (cr));
+
+ /* Using the new context, draw a black vertical line, which should
+ * appear unclipped on top of everything drawn so far. */
+ cairo_move_to (cr2, 110, 0);
+ cairo_line_to (cr2, 110, 600);
+ cairo_stroke (cr2);
+
+ /* Using the first context, draw another black vertical line.
+ * This line should be clipped agaist the bezier clipping path set
+ * earlier. */
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_move_to (cr, 400, 0);
+ cairo_line_to (cr, 400, 600);
+ cairo_stroke (cr);
+
+ cairo_destroy (cr2);
+
+ /* Test reset clip. Draw a transparent black circle over
+ * everything. Specifically, make sure the circle extends outside
+ * the square clip set at the top of this function. */
+ cairo_reset_clip (cr);
+ cairo_arc (cr, 300, 300, 220, 0, 2 * M_PI);
+ cairo_set_source_rgba (cr, 0, 0, 0, 0.2);
+ cairo_fill (cr);
+}
+
+int
+main (void)
+{
+ cairo_t *cr;
+ const char *filename = "pdf-clip.pdf";
+ cairo_surface_t *surface;
+
+ printf("\n");
+
+ surface = cairo_pdf_surface_create (filename,
+ WIDTH_IN_POINTS, HEIGHT_IN_POINTS);
+ if (surface == NULL) {
+ fprintf (stderr, "Failed to create pdf surface for file %s\n", filename);
+ return CAIRO_TEST_FAILURE;
+ }
+
+ cr = cairo_create (surface);
+
+ test_clip (cr, WIDTH_IN_POINTS, HEIGHT_IN_POINTS);
+ cairo_show_page (cr);
+
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
+
+ printf ("pdf-surface: Please check %s to make sure it looks happy.\n",
+ filename);
+
+ return 0;
+}
diff --git a/test/self-copy.c b/test/self-copy.c
index 3ad406ecc..5f4398b25 100644
--- a/test/self-copy.c
+++ b/test/self-copy.c
@@ -85,6 +85,5 @@ draw (cairo_t *cr, int width, int height)
int
main (void)
{
- return cairo_test_expect_failure (&test, draw,
- "copying from a surface to itself doesn't handle clipping properly");
+ return cairo_test (&test, draw);
}
diff --git a/test/self-intersecting-ref.png b/test/self-intersecting-ref.png
new file mode 100644
index 000000000..384b0abc0
--- /dev/null
+++ b/test/self-intersecting-ref.png
Binary files differ
diff --git a/test/self-intersecting.c b/test/self-intersecting.c
new file mode 100644
index 000000000..2dfd79681
--- /dev/null
+++ b/test/self-intersecting.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * 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
+ * Red Hat, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Carl D. Worth <cworth@cworth.org>
+ */
+
+/* Bug history
+ *
+ * 2005-06-01 Carl Worth <cworth@cworth.org>
+ *
+ * There's a long-standing bug in that self-intersecting paths give
+ * an incorrect result when stroked. The problem is that the
+ * trapezoids are generated incrementally along the stroke and as
+ * such, are not disjoint. The errant intersections of these
+ * trapezoids then leads to overfilled pixels.
+ *
+ * The test belows first creates and fills a path. Then it creates a
+ * second path which has a stroked boundary identical to the first
+ * filled path. But the results of the two operations are
+ * different. The most obvious difference is in the central region
+ * where the entire path intersects itself. But notice that every
+ * time the path turns there are also errors on the inside of the
+ * turn, (since the subsequent trapezoids along the path intersect).
+ */
+
+#include "cairo-test.h"
+
+cairo_test_t test = {
+ "self-intersecting",
+ "Test strokes of self-intersecting paths",
+ 10, 20
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ cairo_translate (cr, 1.0, 1.0);
+
+ cairo_set_source_rgb (cr, 1, 0, 0); /* red */
+
+ /* First draw the desired shape with a fill */
+ cairo_rectangle (cr, 0.5, 0.5, 4.0, 4.0);
+ cairo_rectangle (cr, 3.5, 3.5, 4.0, 4.0);
+ cairo_rectangle (cr, 3.5, 1.5, -2.0, 2.0);
+ cairo_rectangle (cr, 6.5, 4.5, -2.0, 2.0);
+
+ cairo_fill (cr);
+
+ /* Then try the same thing with a stroke */
+ cairo_translate (cr, 0, 10);
+ cairo_move_to (cr, 1.0, 1.0);
+ cairo_rel_line_to (cr, 3.0, 0.0);
+ cairo_rel_line_to (cr, 0.0, 6.0);
+ cairo_rel_line_to (cr, 3.0, 0.0);
+ cairo_rel_line_to (cr, 0.0, -3.0);
+ cairo_rel_line_to (cr, -6.0, 0.0);
+ cairo_close_path (cr);
+
+ cairo_set_line_width (cr, 1.0);
+ cairo_stroke (cr);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+ return cairo_test_expect_failure (&test, draw,
+ "Self-intersecting strokes are wrong due to incremental trapezoidization.");
+}