summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Worth <cworth@cworth.org>2006-02-13 16:47:50 -0800
committerCarl Worth <cworth@cworth.org>2006-02-13 16:47:50 -0800
commit1049c3c077c6000e25001a1a55e5fc48cf12a61e (patch)
tree33b01fadaed6ea549babbe9d2fb09ca68661ad70
parent73c2eada0d0c80763f0a953cce7fc144f7931fa1 (diff)
parent4bec3d6af49f9a720121617819700bc700ba5951 (diff)
Remove pixman from RELEASE_0_9_0RELEASE_0_9_0
-rw-r--r--BUGS82
-rw-r--r--ChangeLog729
-rw-r--r--Makefile.am3
-rw-r--r--NEWS77
-rw-r--r--RELEASING3
-rw-r--r--ROADMAP47
-rw-r--r--TODO65
-rwxr-xr-xautogen.sh3
-rw-r--r--configure.in41
-rw-r--r--doc/public/Makefile.am1
-rw-r--r--doc/public/cairo-docs.xml1
-rw-r--r--doc/public/cairo-sections.txt14
-rw-r--r--doc/public/tmpl/cairo-font.sgml30
-rw-r--r--doc/public/tmpl/cairo-pattern.sgml1
-rw-r--r--doc/public/tmpl/cairo-surface.sgml38
-rw-r--r--doc/public/tmpl/cairo-xlib.sgml11
-rw-r--r--doc/public/tmpl/cairo.sgml36
-rw-r--r--src/Makefile.am6
-rw-r--r--src/cairo-arc.c2
-rw-r--r--src/cairo-atsui-font.c26
-rw-r--r--src/cairo-clip-private.h123
-rw-r--r--src/cairo-clip.c466
-rw-r--r--src/cairo-debug.c73
-rw-r--r--src/cairo-debug.h48
-rw-r--r--src/cairo-features.h.in8
-rw-r--r--src/cairo-font-subset.c93
-rw-r--r--src/cairo-font.c157
-rw-r--r--src/cairo-ft-font.c526
-rw-r--r--src/cairo-ft-private.h6
-rw-r--r--src/cairo-glitz-surface.c4
-rw-r--r--src/cairo-gstate-private.h43
-rw-r--r--src/cairo-gstate.c1451
-rw-r--r--src/cairo-image-surface.c134
-rw-r--r--src/cairo-matrix.c1
-rw-r--r--src/cairo-meta-surface-private.h3
-rw-r--r--src/cairo-meta-surface.c144
-rw-r--r--src/cairo-output-stream.c4
-rw-r--r--src/cairo-path-data-private.h2
-rw-r--r--src/cairo-path-data.c8
-rw-r--r--src/cairo-path-fill.c20
-rw-r--r--src/cairo-pattern.c13
-rw-r--r--src/cairo-pdf-surface.c13
-rw-r--r--src/cairo-ps-surface.c12
-rw-r--r--src/cairo-quartz-surface.c5
-rw-r--r--src/cairo-surface.c329
-rw-r--r--src/cairo-traps.c29
-rw-r--r--src/cairo-wideint.c461
-rw-r--r--src/cairo-wideint.h18
-rw-r--r--src/cairo-win32-font.c44
-rw-r--r--src/cairo-win32-surface.c16
-rw-r--r--src/cairo-xcb-surface.c14
-rw-r--r--src/cairo-xlib-screen.c53
-rw-r--r--src/cairo-xlib-surface.c302
-rw-r--r--src/cairo.c71
-rw-r--r--src/cairo.h77
-rw-r--r--src/cairoint.h259
-rw-r--r--test/.cvsignore5
-rw-r--r--test/Makefile.am20
-rw-r--r--test/a8-mask-ref.pngbin0 -> 128 bytes
-rw-r--r--test/a8-mask.c72
-rw-r--r--test/buffer-diff.c89
-rw-r--r--test/buffer-diff.h14
-rw-r--r--test/cairo-test.c20
-rw-r--r--test/cairo-test.h1
-rw-r--r--test/clip-operator-ref.pngbin0 -> 37486 bytes
-rw-r--r--test/clip-operator.c205
-rw-r--r--test/composite-integer-translate-over-repeat.c2
-rw-r--r--test/mask-ctm-ref.pngbin0 -> 129 bytes
-rw-r--r--test/mask-ctm.c82
-rw-r--r--test/mask-surface-ctm-ref.pngbin0 -> 129 bytes
-rw-r--r--test/mask-surface-ctm.c75
-rw-r--r--test/read-png.c14
-rw-r--r--test/source-surface-scale-paint-ref.pngbin147 -> 139 bytes
-rw-r--r--test/source-surface-scale-paint.c5
-rw-r--r--test/surface-finish-twice.c1
-rw-r--r--test/text-cache-crash.c14
-rw-r--r--test/unantialiased-shapes-ref.pngbin0 -> 4450 bytes
-rw-r--r--test/unantialiased-shapes.c103
-rw-r--r--test/unbounded-operator-ref.pngbin0 -> 14178 bytes
-rw-r--r--test/unbounded-operator.c201
-rw-r--r--test/xlib-surface.c26
81 files changed, 5005 insertions, 2190 deletions
diff --git a/BUGS b/BUGS
index ea529cb7..43331d08 100644
--- a/BUGS
+++ b/BUGS
@@ -5,50 +5,11 @@ that display.
--
-cairo_show_surface fails when given a non-default CTM, see the
-show_surface.cairo snippet in:
-
- From: Per Bjornsson <perbj@stanford.edu>
- To: Cairo mailing list <cairo@cairographics.org>
- Date: Wed, 09 Feb 2005 20:05:35 -0800
- Message-Id: <1108008335.5349.46.camel@localhost.localdomain>
- Subject: [cairo] How is cairo_show_surface supposed to work?
-
---
-
cairo_image_surface_create should return a blank image
(eg. transparent black) instead of an image with random data in it.
--
-cairo_surface_create_for_image is claiming ownership of the user's data.
-
---
-
-cairo_font_set_transform should be renamed cairo_font_set_matrix
-cairo_font_current_transform should be renamed cairo_font_get_matrix
-
---
-
-Alexis Georges reports a segfault on AMD64 with a simple program,
-(that works in a 32bit chroot).
-
---
-
-The caches need to have some locking (see: [cairo] Static caches and thread-safety)
-
---
-
-Scaling of surface patterns is all broken, (try xsvg
-gradPatt-pattern-BE-07.svg and zoom in and out).
-
---
-
-centi_unfinished.svg has big black portions when drawn with svg2png,
-(but not when drawn with xsvg).
-
---
-
The caches need to be invalidated at font destruction time.
--
@@ -96,24 +57,6 @@ confirmed on a quite default install of debian unstable.
--
-cairo_scale_font modifies objects that the user expects to not change. For example:
-
- cairo_font_t *font;
-
- cairo_select_font (cr, "fixed", 0, 0);
- font = cairo_current_font (cr);
- cairo_scale_font (cr, 10);
- cairo_show_text (cr, "all is good");
- cairo_set_font (cr, font);
- cairo_scale_font (cr, 10);
- cairo_show_text (cr, "WAY TOO BIG!!);
-
-We could fix this by not storing the scale in the font object. Or
-maybe we could just force the size to its default after set_font. Need
-to think about this in more detail.
-
---
-
cairo_show_text is not updating the current point by the string's advance values.
--
@@ -128,34 +71,9 @@ places.
--
-Patterns are broken in various ways. The SVG test case demonstrates
-some regressions, so something has changed in cairo. Also,
-transformation plus repeat doesn't work in either Xrender or
-libpixman, (nor in glitz?).
-
---
-
font-size="0" in an SVG file does very bad things.
--
-move_to_show_surface (see cairo/test):
-
- * 2004-10-25 Carl Worth <cworth@cworth.org>
- *
- * It looks like cairo_show_surface has no effect if it follows a
- * call to cairo_move_to to any coordinate other than 0,0. A little
- * bit of poking around suggests this isn't a regression, (at least
- * not since the last pixman snapshot).
-
---
-
cairo falls over with XFree86 4.2 (probably braindead depth handling
somewhere).
-
---
-
-The caches abort when asked for a too-large item, (should be possible
-to trigger by asking for a giant font, "cairo_scale_font (cr, 2000)"
-perhaps). Even if the caches don't want to hold them, we need to be
-able to allocate these objects.
diff --git a/ChangeLog b/ChangeLog
index 25f8a8f7..f1ce80ba 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,719 @@
+2005-08-08 Carl Worth <cworth@cworth.org>
+
+ * NEWS: Added notes for release 0.9.0.
+
+ * configure.in: Increment CAIRO_VERSION to 0.9.0. Increment
+ LT_CURRENT to 2 to mark the beginning of proper soname management.
+
+2005-08-08 Carl Worth <cworth@cworth.org>
+
+ * src/Makefile.am (libcairo_la_SOURCES): Add missing cairo-debug.h
+ which was hold up make distcheck.
+
+2005-08-08 Carl Worth <cworth@cworth.org>
+
+ * test/Makefile.am (EXTRA_DIST): Fix typo that was holding up make
+ distcheck from working.
+
+2005-08-08 Billy Biggs <vektor@dumbterm.net>
+
+ * src/cairo-path-data-private.h: Declare _cairo_path_nil as extern.
+
+2005-08-08 Billy Biggs <vektor@dumbterm.net>
+
+ reviewed by: cworth, otaylor
+
+ * src/cairo.c: (cairo_set_antialias), (cairo_get_antialias):
+ * src/cairo.h: Add a new API for disabling antialiasing of shapes
+ drawn by cairo. This is a hint and is not supported by all backends.
+
+ * src/cairoint.h:
+ * src/cairo-gstate-private.h:
+ * src/cairo-gstate.c: (_cairo_gstate_init),
+ (_composite_traps_draw_func),
+ (_cairo_surface_clip_and_composite_trapezoids),
+ (_cairo_gstate_clip_and_composite_trapezoids),
+ (_cairo_gstate_clip), (_cairo_gstate_set_antialias),
+ (_cairo_gstate_get_antialias): Store the antialiasing mode in the
+ gstate and pass it to the backend for trapezoid rendering and for
+ clipping.
+
+ * src/cairo-clip-private.h:
+ * src/cairo-clip.c: (_cairo_clip_intersect_path),
+ (_cairo_clip_intersect_mask), (_cairo_clip_clip): Pass the
+ antialiasing parameter down to the backend where appropriate.
+
+ * src/cairo-surface.c: (_fallback_composite_trapezoids),
+ (_cairo_surface_composite_trapezoids), (_cairo_surface_reset_clip),
+ (_cairo_surface_intersect_clip_path),
+ (_cairo_surface_set_clip_path_recursive),
+ (_cairo_surface_set_clip_path): Pass the antialiasing parameter down
+ to the backend where appropriate.
+
+ * src/cairo-image-surface.c:
+ (_cairo_image_surface_composite_trapezoids): Add support for A1 format
+ trapezoid rendering, and remove the _create_mask_image function,
+ creating a temporary image from memory we allocate and clear.
+
+ * src/cairo-xcb-surface.c:
+ (_cairo_xcb_surface_composite_trapezoids): Support A1 masks to disable
+ antialiasing using the RENDER extension when requested.
+
+ * src/cairo-xlib-surface.c: (_create_trapezoid_mask),
+ (_cairo_xlib_surface_composite_trapezoids): Support A1 masks to disable
+ antialiasing using the RENDER extension when requested.
+
+ * src/cairo-meta-surface-private.h:
+ * src/cairo-meta-surface.c:
+ (_cairo_meta_surface_composite_trapezoids),
+ (_cairo_meta_surface_intersect_clip_path),
+ (_cairo_meta_surface_replay): Blindly pass through the antialising
+ parameter.
+
+ * src/cairo-glitz-surface.c:
+ (_cairo_glitz_surface_composite_trapezoids):
+ * src/cairo-pdf-surface.c:
+ (_cairo_pdf_surface_composite_trapezoids),
+ (_cairo_pdf_surface_intersect_clip_path):
+ * src/cairo-ps-surface.c: (_cairo_ps_surface_composite_trapezoids),
+ (_cairo_ps_surface_intersect_clip_path),
+ (_ps_output_composite_trapezoids),
+ (_ps_output_intersect_clip_path): Add the antialiasing parameter but
+ don't support it.
+
+ * test/Makefile.am:
+ * test/unantialiased-shapes-ref.png:
+ * test/unantialiased-shapes.c: (big_star_path), (draw), (main):
+ Add a test case and a reference image from the latest libpixman.
+
+ * doc/public/tmpl/cairo-font.sgml:
+ * doc/public/tmpl/cairo.sgml:
+ * doc/public/cairo-sections.txt: Add the new antialiasing disabling API to
+ the docs.
+
+ * TODO: Update progress on a parameter to disable antialiasing.
+
+2005-08-08 Carl Worth <cworth@cworth.org>
+
+ * test/.cvsignore: Ignore clip-operator and unbounded-operator.
+
+2005-08-08 Carl Worth <cworth@cworth.org>
+
+ * RELEASING: Fix gnome-announce-list address.
+
+2005-08-08 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-xlib-surface.c (_xlib_glyphset_cache_destroy_entry):
+ Don't free the glyph if the entry doesn't have a glyph.
+ (Maybe #3909, Carlos Garnacho Parro)
+
+2005-08-08 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-gstate.c: (_cairo_operator_bounded): Add a return
+ value after ASSERT_NOT_REACHED to quiet an anxious compiler.
+
+2005-08-08 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-gstate.c: (_cairo_surface_clip_and_composite_trapezoids):
+ Fix accidentally committed line.
+
+2005-08-08 Kristian Høgsberg <krh@redhat.com>
+
+ * src/cairo-surface.c (_cairo_surface_set_clip_path): Update doc
+ comment.
+
+2005-08-08 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-gstate.c (_cairo_operator_bounded): Add a function to test
+ whether a cairo_operator_t is bounded (does nothing for 0 src/mask)
+
+ * src/cairo-surface.c (_cairo_surface_composite_fixup_unbounded) cairoint.h:
+ Add a helper function to take clearing areas that are outside the source/mask
+ but are cleared by unbounded operations.
+
+ * src/cairo-image-surface.c (_cairo_image_surface_composite)
+ src/cairo-xlib-surface.c (_cairo_xlib_surface_composite): Use
+ _cairo_surface_composite_fixup_unbounded() as needed.
+
+ * src/cairo-image-surface.c src/cairint.h: Keep track of whether the surface
+ has a clip or not ... we need this for determining when we can bypass
+ an intermediate mask for composite_trapezoids().
+
+ * src/cairo-image-surface.c (_cairo_image_surface_composite_trapezoids):
+ Create an intermediate mask of the right size with pixman_add_trapezoids()
+ and composite that.
+
+ * src/cairo-xlib-surface.c (_cairo_xlib_surface_composite_trapezoids):
+ When rendering with an unbounded operator, create the intermediate mask
+ ourselves and render with ADD to that, then composite the result.
+
+ * src/cairo-ft-font.c (_cairo_ft_scaled_font_show_glyphs): Create an
+ intermediate surface the size of the extents, render the glyphs to that
+ then composite the results.
+
+ * src/cairo-xlib-surface.c (glyphset_cache_entry_t): Add the size of the glyph
+
+ * src/cairo-xlib-surface.c (_show_glyphs_fixup_unbounded): Compute the size
+ of the glyph mask, then use _cairo_surface_composite_fixup_unbounded().
+
+ * src/cairo-xlib-surface.c (_cairo_xlib_surface_show_glyphs32): Use the right
+ mask format. (Unrelated bugfix)
+
+ * src/cairo-gstate.c (_cairo_gstate_clip_and_composite): New function taking
+ a drawing function as a parameter to encapsulate shared logic between
+ compositing trapezoid, glyphs, and masks.
+
+ * src/cairo-gstate.c (_cairo_gstate_mask,
+ _cairo_surface_clip_and_composite_trapezoids, _cairo_gstate_show_glyphs):
+ Use _cairo_gstate_clip_and_composite(). Also fix extents computations for
+ unbounded operators.
+
+ * src/cairo-clip.c src/cairo-clip-private.h (_cairo_clip_combine_to_surface):
+ Add the destination as an extra parameter to allow combining to an intermediate
+ surface.
+
+ * tests/unbounded-operator.c tests/Makefile.am: Add a test for the
+ operation of the 6 unbounded operators against different shapes.
+
+ * tests/clip-operator.c tests/Makefile.am: Add a test that tests
+ surface clipping with different shapes against all the operators.
+
+ * test/composite-integer-translate-over-repeat.c (draw): Make use OVER
+ like the name and description. With fixed semantics, SOURCE does something
+ different.
+
+2005-08-06 Carl Worth <cworth@cworth.org>
+
+ * BUGS: Remove several bugs that have been fixed.
+
+ * ROADMAP: Slip group support off of the 1.0 roadmap. Update
+ status of clipping work which otaylor is working on.
+
+ * TODO: Update for progress on cairo_surface_mark_dirty
+ (committed), non-antialiased rendering (patch), cairo_arc_to
+ (patch), consistent error handling (committed), cairo_content_t
+ (committed). Remove details for some completed items.
+
+ * src/cairo-gstate.c (_cairo_gstate_set_font_face): Don't crash if
+ font_face is NULL, (this is a documented mechanism for returning
+ to the default font_face).
+
+2005-08-06 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.c (cairo_get_font_face): Fix to return
+ &_cairo_font_face_nil instead of NULL on error.
+
+2005-08-06 Jeff Muizelaar <jeff@infidigm.net>
+
+ * test/a8-mask.c: (main): Give reason for failure.
+
+2005-08-06 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-win32-font.c (_cairo_win32_scaled_font_show_glyphs):
+ Remove a non-sensical XXX that crept in at some point; for
+ a solid color, there is no difference between premultiplied
+ and non-premultiplied colors.
+
+2005-08-06 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-ft-font.c: (_cairo_ft_scaled_font_create),
+ (_cairo_ft_scaled_font_create_toy),
+ (_cairo_ft_scaled_font_glyph_extents),
+ (_cairo_ft_font_face_scaled_font_create): Fix up some stale
+ comments. Rename _cairo_ft_scaled_font_create_for_unscaled to its
+ proper name of _cairo_ft_scaled_font_create (which is available
+ now that _cairo_ft_scaled_font_create_toy has its correct
+ name). Also prefer 'scaled_font' over 'f' as an identifier.
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-ft-font.c: (_cairo_ft_unscaled_font_init),
+ (_cairo_ft_unscaled_font_create_from_face),
+ (_cairo_ft_unscaled_font_create_from_filename): Unify
+ initialization for _cairo_ft_unscaled_font_create_from_face and
+ _cairo_ft_unscaled_font_create_from_filename through new
+ _cairo_ft_unscaled_font_init.
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-ft-font.c: (_cairo_ft_font_face_create): Rename
+ _ft_font_face_backend to be preoperly namespaced as
+ _cairo_ft_font_face_backend.
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-ft-font.c: (_cairo_ft_font_face_destroy),
+ (_cairo_ft_font_face_create): Rename cairo_ft_font_face->next_face
+ to next.
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h: Include cairo-hash-private.h.
+
+ * src/Makefile.am (libcairo_la_SOURCES): Add cairo-hash.c and
+ cairo-hash-private.h since we're actually going to start using
+ them now.
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-gstate.c: (_cairo_gstate_set_font_face): Simplify the
+ implementation by taking advantage of the fact that destroy and
+ reference are safe for NULL, and that reference returns its
+ argument.
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-gstate.c: (_cairo_gstate_translate),
+ (_cairo_gstate_scale), (_cairo_gstate_rotate),
+ (_cairo_gstate_transform), (_cairo_gstate_set_matrix),
+ (_cairo_gstate_identity_matrix), (_cairo_gstate_unset_scaled_font),
+ (_cairo_gstate_set_font_size), (_cairo_gstate_set_font_matrix),
+ (_cairo_gstate_set_font_options),
+ (_cairo_gstate_ensure_scaled_font),
+ (_cairo_gstate_get_font_extents), (_cairo_gstate_text_to_glyphs),
+ (_cairo_gstate_set_font_face), (_cairo_gstate_glyph_extents),
+ (_cairo_gstate_show_glyphs), (_cairo_gstate_glyph_path):
+ Rename two functions:
+
+ _cairo_gstate_unset_font -> _cairo_gstate_unset_scaled_font
+ _cairo_gstate_ensure_font -> _cairo_gstate_ensure_scaled_font
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h: Entagle the cairo_unscaled_font_t typedef.
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h: Rename font_face_backend->create_font to
+ scaled_font_create. Group the scaled_font prototypes together. A
+ little more simple -> toy renaming.
+
+ * src/cairo-font.c: (_cairo_toy_font_face_create_from_cache_key),
+ (_cairo_toy_font_face_destroy),
+ (_cairo_toy_font_face_create):
+ * src/cairo-gstate.c: (_cairo_gstate_select_font_face),
+ (_cairo_gstate_ensure_font_face):
+ A little more simple -> toy renaming.
+
+ * src/cairo-font.c: (_cairo_toy_font_face_scaled_font_create),
+ (_cairo_inner_font_cache_create_entry):
+ * src/cairo-ft-font.c: (_cairo_ft_font_face_scaled_font_create):
+ * src/cairo-win32-font.c: (_cairo_win32_font_face_scaled_font_create):
+ Track rename of font_face_backend->scaled_font_create.
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h: Rather gratuitous (though mostly harmless)
+ whitespace changes for font backend tables.
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.c: Document the implicit closing of sub-paths for
+ cairo_fill and cairo_fill_preserve.
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h: Rename parameters to scalend_font_backend from
+ font to scaled_font.
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h: Rename scaled_font_backend->destroy to the more
+ accurate fini, (since it frees only the dependent data within the
+ scaled_font and not the scaled_font itself).
+
+ * src/cairo-atsui-font.c: (_cairo_atsui_font_fini):
+ * src/cairo-font.c: (cairo_scaled_font_destroy):
+ * src/cairo-ft-font.c: (_cairo_ft_scaled_font_fini):
+ * src/cairo-win32-font.c: (_cairo_win32_scaled_font_fini):
+ Track rename of scaled_font_backend->fini.
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h: Rename scaled_font_backend->create to
+ create_toy. Move declaration of cairo_simple_font_face_t from
+ cairo_font.c to cairoint.h and rename it
+ cairo_toy_font_face_t. Rework create_toy to accept a
+ cairo_toy_font_face_t rather than separate family, slant, and
+ weight.
+
+ * src/cairo-atsui-font.c: (_cairo_atsui_font_create_toy):
+ * src/cairo-ft-font.c: (_cairo_ft_scaled_font_create_toy):
+ * src/cairo-win32-font.c: (_cairo_win32_scaled_font_create_toy):
+ Track change in create_toy interface.
+
+ * src/cairo-font.c: (_cairo_toy_font_face_create_from_cache_key),
+ (_cairo_simple_font_cache_create_entry),
+ (_cairo_simple_font_face_destroy),
+ (_cairo_simple_font_face_create_font):
+ Partial rename of simple->toy. It's not complete as this is a step
+ in the process of merging in a large patch of mine which actually
+ removes most of the affected code.
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * test/.cvsignore: ignore a8-mask
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * test/a8-mask.c (draw): Patch memory leaks.
+
+2005-08-05 Jeff Muizelaar <jeff@infidigm.net>
+
+ * test/Makefile.am:
+ * test/a8-mask-ref.png:
+ * test/a8-mask.c: (draw), (main):
+ Add a test case for CAIRO_FORMAT_A8 masks that fails with
+ libpixman.
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * autogen.sh (automake_min_vers): Bump automake_min_vers up to 1.7
+ since we clearly don't work with 1.4 anymore.
+
+2005-08-05 Jeff Muizelaar <jeff@infidigm.net>
+
+ * test/xlib-surface.c: (do_test): use the newly added
+ buffer_diff_noalpha for comparing buffers of
+ CAIRO_FORMAT_RGB24.
+
+2005-08-05 Jeff Muizelaar <jeff@infidigm.net>
+
+ * test/buffer-diff.c: (buffer_diff_core), (buffer_diff),
+ (buffer_diff_noalpha):
+ * test/buffer-diff.h: rewrite buffer_diff to be endian safe
+ and add a new fuction buffer_diff_noalpha
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * doc/public/cairo-sections.txt: Remove CAIRO_BEGIN_DECLS and
+ CAIRO_END_DECLS which don't belong here.
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * test/surface-finish-twice.c (draw): Remove unused variable.
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * doc/public/Makefile.am: Ignore cairo-clip-private.h.
+
+ * doc/public/cairo-docs.xml: Drop non-existent cairo-atsui.xml.
+
+ * src/cairo-font.c: Fix misnamed parameters in comment blocks.
+
+ * test/cairo-test.c: Include config.h so HAVE_UNISTD_H gets
+ picked up as necessary.
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * doc/public/Makefile.am (IGNORE_HFILES): Ignore
+ cairo-clip-private.h.
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * doc/public/cairo-sections.txt: Add some missing declarations to
+ the appropriate sections.
+
+ * doc/public/tmpl/cairo-font.sgml:
+ * doc/public/tmpl/cairo-surface.sgml:
+ * doc/public/tmpl/cairo-xlib.sgml:
+ * doc/public/tmpl/cairo.sgml: churn
+
+ * src/cairo-path-data-private.h: Rename cairo_path_nil to
+ _cairo_path_nil since it may be exported, and tag it cairo_private
+ to try to avoid exporting it. Qualify it as const well.
+
+ * src/cairo-path-data.c: (_cairo_path_data_create_real):
+ * src/cairo.c: (cairo_copy_path), (cairo_copy_path_flat):
+ Track new name of _cairo_path_nil and cast away the const as
+ required.
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-arc.c:
+ * src/cairo-matrix.c: Remove include of math.h since cairoint.h
+ does it more carefully, (for annoying platforms for which just
+ including math.h without extra defines is not enough).
+
+ * src/cairo.c: Replace Cairo with cairo.
+
+ * test/buffer-diff.c: Include config.h so HAVE_UNISTD_H gets
+ picked up as necessary.
+
+ * test/cairo-test.c: Fix non-UTF-8 copyright symbol.
+
+2005-08-05 Carl Worth <cworth@cworth.org>
+
+ Patch from John Ehresman <jpe@wingide.com> to aid win32
+ compilation:
+
+ * src/cairo-output-stream.c: Define snprintf as _snprintf when
+ under the influence of _MSC_VER.
+
+ * test/read-png.c: (read_png_argb32):
+ * src/cairo-wideint.h: Define int32_t and friends as __int32 and
+ friends when under the influence of _MSC_VER.
+
+ * test/buffer-diff.c:
+ * test/cairo-test.c: Make include of unistd.h conditional on
+ HAVE_UNISTD_H.
+
+2005-08-05 Kristian Høgsberg <krh@redhat.com>
+
+ Patch from Adrian Johnson <ajohnson@redneon.com>
+
+ * src/cairo-font-subset.c (cairo_pdf_ft_font_write_glyf_table)
+ (cairo_pdf_ft_font_remap_composite_glyph): Remap composite glyps
+ to use subset font glyph indices.
+
+2005-08-05 Kristian Høgsberg <krh@redhat.com>
+
+ Reviewed by: otaylor
+
+ * src/Makefile.am:
+ * src/cairo-clip-private.h:
+ * src/cairo-clip.c: New files. Move code for manipulating
+ cairo_clip_t out into cairo_clip_* functions and put them in
+ cairo-clip.c.
+
+ * src/cairo-gstate-private.h:
+ * src/cairo-gstate.c: Rewrite to use new cairo_clip_t functions
+ for manipulating the clip state, change the
+ clip_and_composite_trapezoids call tree to use cairo_clip_t
+ instead of cairo_gstate_t.
+
+ * src/cairo-meta-surface.c: Use new cairo_clip_t function to
+ maintain clip state while replaying.
+
+ * src/cairo-path-fill.c: (_cairo_filler_init),
+ (_cairo_filler_curve_to), (_cairo_path_fixed_fill_to_traps): Pass
+ fill rule and tolerance directly, to break gstate dependency.
+
+ * src/cairo-surface.c: (_cairo_surface_set_clip): New function.
+ Set the clip for a surface as specified by the cairo_clip_t.
+
+ * src/cairo-traps.c: (_cairo_traps_translate): Move
+ translate_traps() from cairo-gstate.c to here and rename it.
+
+2005-08-04 Kristian Høgsberg <krh@redhat.com>
+
+ * src/cairo-font.c: (cairo_font_face_reference),
+ (_cairo_unscaled_font_reference), (cairo_scaled_font_reference):
+ * src/cairo-gstate.c: (_cairo_clip_path_reference):
+ * src/cairo-pattern.c: (cairo_pattern_reference):
+ * src/cairo-pdf-surface.c: (_cairo_pdf_document_reference):
+ * src/cairo-surface.c: (cairo_surface_reference):
+ * src/cairo.c: (cairo_reference):
+ * src/cairo.h:
+ * src/cairoint.h:
+ Change *_reference() functions to return the object being
+ referenced.
+
+2005-07-29 T Rowley <tim.rowley@gmail.com>
+
+ Reviewed by: otaylor
+
+ * src/cairo-xlib-surface.c ( _categorize_composite_operation):
+ Check for render bug involving repeated patterns with a general
+ transform matrix.
+
+2005-08-04 Carl Worth <cworth@cworth.org>
+
+ Originally 2005-07-13 Carl Worth <cworth@cworth.org>
+
+ Reviewed by: otaylor
+
+ * src/cairo-ft-private.h: Export opaque cairo_ft_unscaled_font_t
+ and change _cairo_ft_unscaled_font_[un]lock_face to accept
+ cairo_ft_unscaled_font_t rather than cairo_unscaled_font_t.
+
+ * src/cairo-font-subset.c: (_cairo_font_subset_create),
+ (cairo_pdf_ft_font_generate): Cast explicitly to
+ cairo_ft_unscaled_font_t to track change in prototype of
+ _cairo_ft_unscaled_font_[un]lock_face.
+
+ * src/cairo-ft-font.c: Lots of renaming to use consistent
+ namespacing:
+
+ ft_font_transform_t -> cairo_ft_font_transform_t
+ ft_font_face_t -> cairo_ft_font_face_t
+ ft_unscaled_font_t -> cairo_ft_unscaled_font_t
+
+ Add missing _cairo prefix to many functions.
+
+ Disambiguate _ft_scaled_font_create and
+ _cairo_ft_scaled_font_create by renaming the former to
+ _cairo_ft_scaled_font_create_for_unscaled.
+
+2005-08-03 Carl Worth <cworth@cworth.org>
+
+ Fix for bug #3951:
+
+ * configure.in: Add new _CHECK_FUNCS_WITH_FLAGS to abstract out
+ the pain of temporarily setting flags for AC_CHECK_FUNCS. Use this
+ to check for the existence of FcFini.
+
+ * test/cairo-test.c: (cairo_test_expecting): Make call to FcFini
+ conditional on HAVE_FCFINI.
+
+ * test/text-cache-crash.c: (main): Remove stale comment about
+ cleaning up memory which is now handled by cairo-test.c.
+
+2005-08-01 Owen Taylor <otaylor@redhat.com>
+
+ reviewed by: cworth
+
+ * src/cairo-gstate.c src/cairo-gstate-private.h: Store the
+ inverse CTM at the time of cairo_gstate_set_source() to
+ "lock" the user space matrix.
+
+ * src/cairo-gstate.c: Move the source pattern transformation
+ to the outside of _cairo_gstate_clip_and_composite_trapezoids()
+ instead of doing it at the leaves.
+
+ * test/source-surface-scale-paint.c: Change size of output
+ surface for aesthetics.
+
+ * test/source-surface-scale-paint-ref.png: Updated to correspond
+ to the current definition.
+
+ * test/Makefile.am (XFAIL_TESTS):
+ Remove source-surface-scale-paint.
+
+2005-08-01 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-debug.h: New public header file.
+
+ * src/cairo-debug.c: (cairo_debug_reset_static_data): New function
+ to reset all static data (eg. caches) to their initial state.
+
+ * Makefile.am: Fix check-valgrind target to depend on the 'all'
+ target.
+
+ * configure.in: Add check for a new, proposed, XrmFinalize
+ function.
+
+ * src/Makefile.am: Add cairo-debug.c.
+
+ * src/cairo.h:
+ * src/cairo-features.h.in: Move the definition of
+ CAIRO_BEGIN_DECLS to cairo-features.h so that it can be shared
+ between public header files, and so that it doesn't clutter
+ cairo.h
+
+ * src/cairoint.h:
+ * src/cairo-font.c: (_get_global_simple_cache),
+ (_get_outer_font_cache), (_get_inner_font_cache),
+ (_cairo_unlock_global_image_glyph_cache),
+ (_cairo_font_reset_static_data):
+ * src/cairo-ft-font.c: (_cairo_ft_font_reset_static_data):
+ * src/cairo-xlib-screen.c: (_cairo_xlib_close_display),
+ (_cairo_xlib_screen_info_reset),
+ (_cairo_xlib_screen_reset_static_data):
+ * src/cairo-xlib-surface.c: (_unlock_xlib_glyphset_caches),
+ (_destroy_glyphset_cache_recurse),
+ (_cairo_xlib_surface_reset_static_data): Implement
+ reset_static_data in all modules as required.
+
+ * test/xlib-surface.c: (main):
+ * test/cairo-test.h:
+ * test/cairo-test.c: (cairo_test_for_target),
+ (cairo_test_expecting): Call cairo_debug_reset_static_data and
+ FcFini so that we can have all tests be valgrind-clean with
+ respect to memory leaks and still-reachable data.
+
+2005-08-01 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo.h src/cairoint.h src/cairo-surface.c:
+ Add cairo_mark_dirty[_rectangle]() and cairo_flush() for
+
+ * src/cairo-win32-surface.c: Implement a cairo_flush()
+ that restores the original clip. Also restore the original
+ flush when a surface is finished.
+
+ * ROADMAP: Check off the item.
+
+2005-07-31 Billy Biggs <vektor@dumbterm.net>
+
+ reviewed by: keithp
+
+ * src/cairo-ft-font.c: (_ft_unscaled_font_set_scale): Support
+ versions of freetype without exact FT_Bitmap_Size.x/y_ppem
+ values by using the pixel width and height values instead.
+
+ * configure.in: Add a check for FT_Bitmap_Size.y_ppem.
+
+2005-07-31 Billy Biggs <vektor@dumbterm.net>
+
+ * src/cairo-quartz-surface.c: (cairo_quartz_surface_create):
+ Cast away the const on the nil surface to avoid a compiler warning.
+
+2005-07-31 Billy Biggs <vektor@dumbterm.net>
+
+ * src/cairo-atsui-font.c: (_cairo_atsui_font_create): Pass the
+ options down to the scaled font object to keep things compiling.
+
+2005-07-30 Keith Packard <keithp@keithp.com>
+
+ * src/cairo-wideint.c: (_cairo_int32x32_64_mul),
+ (_cairo_uint64_divrem), (_cairo_uint128_divrem):
+ * src/cairo-wideint.h:
+
+ Replace wide integer divide algorithms with
+ trivial bit-at-a-time code. Original code was
+ of unclear provenance, this new code is
+ completely different.
+
+2005-07-29 Carl Worth <cworth@cworth.org>
+
+ * ROADMAP: Remove completed 0.6 tasks. Add cairo_surface_flush to
+ the cairo_surface_mark_dirty task.
+
+2005-07-29 T Rowley <tim.rowley@gmail.com>
+
+ * src/cairo-atsui-font.c ( _cairo_atsui_font_create):
+ src/cairo-quartz-surface.c (_cairo_quartz_surface_acquire_dest_image):
+ Minor updates to keep quartz backend limping along.
+
+2005-07-29 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-font.c src/cairo-ft-font.c src/cairo-win32-font.c
+ src/cairoint.h: Move the font options into the base
+ cairo_scaled_font_t object so that we have them available
+ to use when we are removing a scaled font from the cache.
+ (http://bugzilla.gnome.org/show_bug.cgi?id=311299,
+ Ali Akcaagac, Behdad Esfahbod)
+
+2005-07-28 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-gstate.c: (_cairo_gstate_mask): Run the mask pattern
+ through the CTM in the same way as the source pattern. This fixes
+ the bug demonstrated by the mask-ctm and mask-surface-ctm tests so
+ they should no longer fail.
+
+2005-07-28 Carl Worth <cworth@cworth.org>
+
+ * test/.cvsignore:
+ * test/Makefile.am:
+ * test/mask-ctm-ref.png:
+ * test/mask-ctm.c: (draw), (main):
+ * test/mask-surface-ctm-ref.png:
+ * test/mask-surface-ctm.c: (draw), (main): Add two new tests:
+ mask-ctm
+ mask-surface-ctm
+ demonstrating that masks are not currently being modified by the
+ CTM.
+
+2005-07-28 Carl Worth <cworth@cworth.org>
+
+ * RELEASING: CC gnome-announce-list@gnome.org on cairo release
+ announcements.
+
+2005-07-28 Carl Worth <cworth@cworth.org>
+
+ * configure.in: Add -head to CAIRO_VERSION after tagging with
+ SNAPSHOT_0_6_0.
+
2005-07-28 Carl Worth <cworth@cworth.org>
* NEWS: Added notes for snapshot 0.6.0
@@ -550,6 +1266,19 @@
2005-07-18 Carl Worth <cworth@cworth.org>
+ * test/.valgrind-suppressions: Add valgrind suppressions for
+ libpng/libz use of uninitialized data. There are clearly bugs here
+ that are not cairo's fault as zeroing the buffer before writing
+ the png image actually causes more errors(!). And, notably,
+ setting all the data to random bytes usually makes the errors go
+ away.
+
+ * test/Makefile.am: Change the check-valgrind target to include
+ the .valgrind-suppresions file and to tee output into
+ valgrind.log.
+
+2005-07-18 Carl Worth <cworth@cworth.org>
+
* configure.in: Add -head to CAIRO_VERSION after tagging with
SNAPSHOT_0_5_2.
diff --git a/Makefile.am b/Makefile.am
index c2a9965a..e375b1b1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -15,6 +15,9 @@ EXTRA_DIST = \
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = cairo.pc
+check-valgrind: all
+ $(MAKE) -C test check-valgrind
+
DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc
# Some custom targets to make it easier to release things.
diff --git a/NEWS b/NEWS
index e39f9574..56181fde 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,80 @@
+Release 0.9.0 (2005-08-08 Carl Worth <cworth@cworth.org>)
+=========================================================
+API additions
+-------------
+
+ * Add a new function call to set the current antialiasing mode in the
+ graphics state:
+
+ cairo_set_antialias
+
+ This call accepts the same modes recently added for font options
+ (NONE or GRAY) but affects the rendering of geometry other than
+ text. The intent of this call is to enable more precise control of
+ which pixels are affected by each operation, for example to allow
+ for full-scene antialiasing for seam-free rendering. It is not
+ expected that non-antialiased rendering will perform better than
+ anti-aliased rendering.
+
+ * Three new functions were added to provide support for mixed cairo-
+ and non-cairo drawing to the same surface:
+
+ cairo_surface_mark_dirty
+ cairo_surface_mark_dirty_rectangle
+ cairo_flush
+
+ * The return type of the several "reference" functions was change,
+ (API compatibly), from void to the same type as the argument. The
+ affected functions are:
+
+ cairo_font_face_reference
+ cairo_scaled_font_reference
+ cairo_pattern_reference
+ cairo_surface_reference
+ cairo_reference
+
+ This allows a convenient way to assign and reference in a single
+ statement.
+
+cairo-win32
+-----------
+ * Some portability improvements, (eg. workaround for missing stdint.h).
+
+cairo-ft
+--------
+ * Updated to allow compilation with older versions of freetype.
+
+Bug fixes
+---------
+ * Fix the unbounded operators to actually produce a correct result,
+ (previously the results were artificially restricited to the
+ bounding box of whatever shape was being drawn rather than
+ extending out infinitely). The fixed operators are:
+
+ CAIRO_OPERATOR_CLEAR
+ CAIRO_OPERATOR_SOURCE
+ CAIRO_OPERATOR_OUT
+ CAIRO_OPERATOR_IN
+ CAIRO_OPERATOR_DEST_IN
+ CAIRO_OPERATOR_DEST_ATOP
+
+ * Fix cairo_mask and cairo_mask_surface to transform the mask by the
+ current transformation matrix (CTM).
+
+ * Fix cairo_set_source to lock the CTM used to transform the pattern.
+
+ * Workaround for X server Render bug involving repeating patterns
+ with a general transformation matrix.
+
+ * cairo_get_font_face fixed to return a "nil" font face object rather
+ than NULL on error.
+
+ * cairo_set_font_face fixed to not crash if given a NULL font face,
+ (which is the documented interface for restoring the defauly font
+ face).
+
+ * Fix xlib glyphset caching to not try to free a NULL glyph.
+
Snapshot 0.6.0 (2005-07-28 Carl Worth <cworth@cworth.org>)
==========================================================
API changes
diff --git a/RELEASING b/RELEASING
index c6513f45..3d38068f 100644
--- a/RELEASING
+++ b/RELEASING
@@ -81,6 +81,7 @@ fixes are committed. Here are the steps to follow:
8) Add a "-head" to CAIRO_VERSION in configure, and commit.
-9) Send a message to cairo-announce@cairographics.org to announce the
+9) Send a message to cairo-announce@cairographics.org and CC
+ gnome-announce-list@gnome.org to announce the
new snapshot using the text provided from "make release-publish".
diff --git a/ROADMAP b/ROADMAP
index 7c2d049b..6f3b12ef 100644
--- a/ROADMAP
+++ b/ROADMAP
@@ -1,29 +1,10 @@
-cairo 0.6 release requirements
-==============================
-The cairo 0.6 snapshot is intended to intended to have the last of the
-API _changes_ prior to cairo 1.0. Here they are:
-
-API changes
------------
-✓ A9. consistent error handling for all objects
- Difficulty: Easy to implement to get the API right. Hard to test.
- Status: Done.
-
-✓ A10. cairo_font_options_t
- Difficulty: Moderate
- Status: Done.
-
-✓ A11. cairo_xlib_surface_create needs to be screen-aware
- Difficulty: Easy
- Status: Done.
-
cairo 1.0 release requirements
==============================
Implementation work
-------------------
I1. Fix clipping to be sane
Dificulty: moderate
- Status: cworth has started looking at this
+ Status: otalyor is working on this.
I2. Real PostScript/PDF fallbacks (cairo_meta_surface_t)
Difficulty: hard
@@ -51,19 +32,12 @@ Implementation work
API additions (more detail in TODO file)
----------------------------------------
- A3. Add cairo_begin/end/get_group
- Difficulty: easy to hard (depending on how sophisticated an
- implementation is acceptable, and whether the
- cairo_meta_surface_t mentioned in [I2] is done)
-
- Status: cworth has a posted a preliminary patch, and keithp,
- krh, and otaylor answered all the tough questions it
- raised. There's not much work left to finish this one.
-
- A7. cairo_surface_mark_dirty
+✓A7. cairo_surface_mark_dirty and cairo_surface_flush
Difficulty: trivial to add API, moderate to actually optimize
based on it
- Status: cworth has sent API proposal to list
+ Status: cworth has sent an API proposal to the list for
+ cairo_surface_mark_dirty. Recent discussions suggest
+ that cairo_surface_flush will need to reset the clip.
✓A12. cairo_xlib_surface_set_drawable
Difficulty: Easy
@@ -77,3 +51,14 @@ Performance work
P3. Glyph measurement needs to be sped up.
Status: Now planned as part of I4 above ("cache lock deadlock")
+
+Things that have been dropped from the 1.0 roadmap
+==================================================
+ A3. Add cairo_begin/end/get_group
+ Difficulty: easy to hard (depending on how sophisticated an
+ implementation is acceptable, and whether the
+ cairo_meta_surface_t mentioned in [I2] is done)
+
+ Status: cworth has a posted a preliminary patch, and keithp,
+ krh, and otaylor answered all the tough questions it
+ raised. There's not much work left to finish this one.
diff --git a/TODO b/TODO
index 41f89605..7a8e1641 100644
--- a/TODO
+++ b/TODO
@@ -10,12 +10,12 @@ Changes that are expected to impact the public API
Backwards compatible (API additions only)
-----------------------------------------
cairo_begin_group, cairo_end_group, cairo_get_group
- cairo_surface_mark_dirty (see below for details)
- Add support for non-antialiased rendering. API ?
+PDR C cairo_surface_mark_dirty (see below for details)
+PDRTC 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.
+P 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
@@ -25,29 +25,12 @@ Backwards incompatible (API deletions or changes)
-------------------------------------------------
PDR C cairo_surface_finish, cairo_surface_flush
PDR C A hidden offset for the xlib backend
-P Consistent error handling for all objects
- Split cairo_format_t (see below for details)
+PDR C Consistent error handling for all objects
+PDRTC Split cairo_format_t (see below for details)
P---C Remove cairo_status_string in favor of cairo_status_to_string
Details on some of the above changes
------------------------------------
-* cairo_surface_mark_dirty
-
- 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)
-
- In order to get the intended efficiency benefits, we'll need to make
- two changes:
-
- 1) In the fallback code, never fetch any data from the clean
- region.
-
- 2) Mark clean any region drawn with device-pixel aligned
- rectangles, (cairo_paint with no clip is the most iportant
- one here).
-
* cairo_text_glyphs:
It would function as a sort of bridge between the toy and the
@@ -78,51 +61,13 @@ Details on some of the above changes
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:
-
- - An enumeration that determines the "capabilities" of a surface -
- A vs. ARGB. vs. RGB
- - An enumeration that determines a specific in-memory representation
- of data. (A1/A8/ARGB32/etc.. Could be extensible to things like
- RGBA32_BYTES_NONPREMULTIPLIED. Some consistent naming convention would
- be be good.)
-
- One issue here is that some interfaces, like cairo_surface_create_similar()
- might be useful with either one. We might want to create an A1 surface
- compatible with the backend (are there examples other than A1? Should
- bilevel just be another "capability"?), or we might want to just create
- an alpha surface without caring about the depth.
-
- If we want to support this, we could do something like:
-
- typedef enum cairo_pixel_format_t {
- CAIRO_PIXEL_FORMAT_A8 = CAIRO_FORMAT_ALPHA,
- CAIRO_PIXEL_FORMAT_RGB24 = CAIRO_FORMAT_RGB,
- CAIRO_PIXEL_FORMAT_A1,
- };
-
- To allow passing either in.
-
- (I don't particularly like this idea for create_similar() because then you
- aren't really saying ALPHA-dont-care, you are saying ALPHA-8. I think it
- would be better to have a separate path for create_similar_with_pixel_format()
- if we need that. But it might be useful for cairo_image_surface_create() ...
- people are going to screw up and pass CAIRO_FORMAT_RGB into that, and if it
- "just worked" that would save people trouble....)
-
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).
-
* Fix clipping to work for all operators. The equation we have come up
with is:
((src Op dest) In clip) Add (dest Out clip)
-* 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.
diff --git a/autogen.sh b/autogen.sh
index ae8acc60..8dd21ea6 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -14,8 +14,7 @@ AUTOCONF=${AUTOCONF-autoconf}
# automake 1.8 requires autoconf 2.58
# automake 1.7 requires autoconf 2.54
-# I don't know what automake 1.4 wants, but the following seems to work...
-automake_min_vers=1.4
+automake_min_vers=1.7
aclocal_min_vers=$automake_min_vers
autoconf_min_vers=2.54
libtoolize_min_vers=1.4
diff --git a/configure.in b/configure.in
index 27fe96fa..bb38c53c 100644
--- a/configure.in
+++ b/configure.in
@@ -5,12 +5,12 @@ AC_INIT(src/cairo.h)
dnl ===========================================================================
# Package version number, (as distinct from shared library version)
-CAIRO_VERSION=0.6.0
+CAIRO_VERSION=0.9.0
# libtool shared library version
# Increment if the interface has additions, changes, removals.
-LT_CURRENT=1
+LT_CURRENT=2
# Increment any time the source changes; set to
# 0 if you increment CURRENT
@@ -37,6 +37,27 @@ AM_PROG_LIBTOOL
AC_STDC_HEADERS
AC_C_BIGENDIAN
+dnl ===========================================================================
+dnl === Local macros
+dnl ===========================================================================
+
+# _CHECK_FUNCS_WITH_FLAGS(FUNCTION..., CFLAGS, LIBS
+# [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
+# Like AC_CHECK_FUNCS but with additional CFLAGS and LIBS
+# --------------------------------------------------------------------
+AC_DEFUN([_CHECK_FUNCS_WITH_FLAGS],
+[
+ save_cflags="$CFLAGS"
+ save_libs="$LIBS"
+ CFLAGS="$CFLAGS $2"
+ LIBS="$LIBS $3"
+ AC_CHECK_FUNCS($1, $4, $5)
+ CFLAGS="$save_cflags"
+ LIBS="$save_libs"
+])
+
+dnl ===========================================================================
+
AC_CHECK_FUNCS(vasnprintf)
AC_CHECK_LIBM
@@ -61,6 +82,7 @@ if test "x$use_xlib" = "xyes"; then
XRENDER_LIBS="$X_LIBS -lXrender -lXext -lX11 $X_EXTRA_LIBS"
use_xlib=yes], [
use_xlib="no (requires Xrender http://freedesktop.org/Software/xlibs)"])])
+ _CHECK_FUNCS_WITH_FLAGS(XrmFinalize, $XRENDER_CFLAGS, $XRENDER_LIBS)
fi
AM_CONDITIONAL(CAIRO_HAS_XLIB_SURFACE, test "x$use_xlib" = "xyes")
@@ -225,6 +247,7 @@ AC_ARG_ENABLE(freetype,
if test "x$use_freetype" = "xyes"; then
PKG_CHECK_MODULES(FONTCONFIG, fontconfig,
[use_freetype=yes], [use_freetype=no])
+ _CHECK_FUNCS_WITH_FLAGS(FcFini, $FONTCONFIG_CFLAGS, $FONTCONFIG_LIBS)
fi
CAIRO_CFLAGS="$CAIRO_CFLAGS $FONTCONFIG_CFLAGS"
@@ -273,6 +296,20 @@ if test "x$use_freetype" = "xyes"; then
AC_SUBST(FREETYPE_CFLAGS)
AC_SUBST(FREETYPE_LIBS)
AC_SUBST(FREETYPE_REQUIRES)
+
+ temp_save_libs="$LIBS"
+ temp_save_cflags="$CFLAGS"
+ LIBS="$LIBS $FREETYPE_LIBS"
+ CFLAGS="$CFLAGS $FREETYPE_CFLAGS"
+ AC_CHECK_MEMBER(FT_Bitmap_Size.y_ppem,
+ HAVE_FT_BITMAP_SIZE_Y_PPEM=1,
+ HAVE_FT_BITMAP_SIZE_Y_PPEM=0,
+ [#include<ft2build.h>
+ #include FT_FREETYPE_H])
+ AC_DEFINE_UNQUOTED(HAVE_FT_BITMAP_SIZE_Y_PPEM,$HAVE_FT_BITMAP_SIZE_Y_PPEM,
+ [FT_Bitmap_Size structure includes y_ppem field])
+ LIBS="$temp_save_libs"
+ CFLAGS="$temp_save_cflags"
fi
CAIRO_CFLAGS="$CAIRO_CFLAGS $FREETYPE_CFLAGS"
diff --git a/doc/public/Makefile.am b/doc/public/Makefile.am
index a9faef84..fdd421cb 100644
--- a/doc/public/Makefile.am
+++ b/doc/public/Makefile.am
@@ -20,6 +20,7 @@ CFILE_GLOB=$(top_srcdir)/src/*.c $(top_srcdir)/src/*.h
# Headers to ignore
IGNORE_HFILES= \
+ cairo-clip-private.h \
cairo-features.h \
cairo-font-subset-private.h \
cairo-ft-private.h \
diff --git a/doc/public/cairo-docs.xml b/doc/public/cairo-docs.xml
index 729738aa..5270f950 100644
--- a/doc/public/cairo-docs.xml
+++ b/doc/public/cairo-docs.xml
@@ -13,7 +13,6 @@
<xi:include href="xml/cairo-pattern.xml"/>
<xi:include href="xml/cairo-matrix.xml"/>
<xi:include href="xml/cairo-font.xml"/>
- <xi:include href="xml/cairo-atsui.xml"/>
<xi:include href="xml/cairo-ft.xml"/>
<xi:include href="xml/cairo-glitz.xml"/>
<xi:include href="xml/cairo-pdf.xml"/>
diff --git a/doc/public/cairo-sections.txt b/doc/public/cairo-sections.txt
index 2e237b02..a27a2945 100644
--- a/doc/public/cairo-sections.txt
+++ b/doc/public/cairo-sections.txt
@@ -75,6 +75,7 @@ cairo_xcb_surface_create_with_xrender_format
cairo_xlib_surface_create
cairo_xlib_surface_create_for_bitmap
cairo_xlib_surface_set_size
+cairo_xlib_surface_set_drawable
</SECTION>
<SECTION>
@@ -90,10 +91,14 @@ cairo_surface_t
cairo_surface_create_similar
cairo_surface_reference
cairo_surface_destroy
+cairo_surface_status
cairo_surface_finish
cairo_surface_get_font_options
cairo_surface_set_user_data
cairo_surface_get_user_data
+cairo_surface_flush
+cairo_surface_mark_dirty
+cairo_surface_mark_dirty_rectangle
cairo_surface_set_device_offset
</SECTION>
@@ -145,11 +150,13 @@ cairo_font_face_t
cairo_scaled_font_t
cairo_font_face_reference
cairo_font_face_destroy
+cairo_font_face_status
cairo_font_face_get_user_data
cairo_font_face_set_user_data
cairo_scaled_font_create
cairo_scaled_font_reference
cairo_scaled_font_destroy
+cairo_scaled_font_status
cairo_font_extents_t
cairo_scaled_font_extents
cairo_text_extents_t
@@ -162,7 +169,6 @@ cairo_font_options_status
cairo_font_options_merge
cairo_font_options_hash
cairo_font_options_equal
-cairo_antialias_t
cairo_font_options_set_antialias
cairo_font_options_get_antialias
cairo_subpixel_order_t
@@ -196,6 +202,8 @@ cairo_set_source_rgba
cairo_set_source
cairo_set_source_surface
cairo_set_tolerance
+cairo_antialias_t
+cairo_set_antialias
cairo_fill_rule_t
cairo_set_fill_rule
cairo_set_line_width
@@ -265,6 +273,7 @@ cairo_glyph_path
cairo_get_operator
cairo_get_source
cairo_get_tolerance
+cairo_get_antialias
cairo_get_current_point
cairo_get_fill_rule
cairo_get_line_width
@@ -293,9 +302,8 @@ cairo_destroy_func_t
cairo_user_data_key_t
cairo_read_func_t
cairo_write_func_t
+cairo_debug_reset_static_data
<SUBSECTION Private>
-CAIRO_BEGIN_DECLS
-CAIRO_END_DECLS
cairo_current_font_extents
cairo_get_font_extents
cairo_current_operator
diff --git a/doc/public/tmpl/cairo-font.sgml b/doc/public/tmpl/cairo-font.sgml
index a41b7cce..78c9d3bf 100644
--- a/doc/public/tmpl/cairo-font.sgml
+++ b/doc/public/tmpl/cairo-font.sgml
@@ -35,6 +35,7 @@ Font Handling
</para>
@font_face:
+@Returns:
<!-- ##### FUNCTION cairo_font_face_destroy ##### -->
@@ -45,6 +46,15 @@ Font Handling
@font_face:
+<!-- ##### FUNCTION cairo_font_face_status ##### -->
+<para>
+
+</para>
+
+@font_face:
+@Returns:
+
+
<!-- ##### FUNCTION cairo_font_face_get_user_data ##### -->
<para>
@@ -85,6 +95,7 @@ Font Handling
</para>
@scaled_font:
+@Returns:
<!-- ##### FUNCTION cairo_scaled_font_destroy ##### -->
@@ -95,6 +106,15 @@ Font Handling
@scaled_font:
+<!-- ##### FUNCTION cairo_scaled_font_status ##### -->
+<para>
+
+</para>
+
+@scaled_font:
+@Returns:
+
+
<!-- ##### STRUCT cairo_font_extents_t ##### -->
<para>
@@ -208,16 +228,6 @@ Font Handling
@Returns:
-<!-- ##### ENUM cairo_antialias_t ##### -->
-<para>
-
-</para>
-
-@CAIRO_ANTIALIAS_DEFAULT:
-@CAIRO_ANTIALIAS_NONE:
-@CAIRO_ANTIALIAS_GRAY:
-@CAIRO_ANTIALIAS_SUBPIXEL:
-
<!-- ##### FUNCTION cairo_font_options_set_antialias ##### -->
<para>
diff --git a/doc/public/tmpl/cairo-pattern.sgml b/doc/public/tmpl/cairo-pattern.sgml
index a837252c..78964ef4 100644
--- a/doc/public/tmpl/cairo-pattern.sgml
+++ b/doc/public/tmpl/cairo-pattern.sgml
@@ -87,6 +87,7 @@ cairo_pattern_t
</para>
@pattern:
+@Returns:
<!-- ##### FUNCTION cairo_pattern_destroy ##### -->
diff --git a/doc/public/tmpl/cairo-surface.sgml b/doc/public/tmpl/cairo-surface.sgml
index 5d069fc2..64e65f9d 100644
--- a/doc/public/tmpl/cairo-surface.sgml
+++ b/doc/public/tmpl/cairo-surface.sgml
@@ -43,6 +43,7 @@ cairo_surface_t
</para>
@surface:
+@Returns:
<!-- ##### FUNCTION cairo_surface_destroy ##### -->
@@ -53,6 +54,15 @@ cairo_surface_t
@surface:
+<!-- ##### FUNCTION cairo_surface_status ##### -->
+<para>
+
+</para>
+
+@surface:
+@Returns:
+
+
<!-- ##### FUNCTION cairo_surface_finish ##### -->
<para>
@@ -94,6 +104,34 @@ cairo_surface_t
@Returns:
+<!-- ##### FUNCTION cairo_surface_flush ##### -->
+<para>
+
+</para>
+
+@surface:
+
+
+<!-- ##### FUNCTION cairo_surface_mark_dirty ##### -->
+<para>
+
+</para>
+
+@surface:
+
+
+<!-- ##### FUNCTION cairo_surface_mark_dirty_rectangle ##### -->
+<para>
+
+</para>
+
+@surface:
+@x:
+@y:
+@width:
+@height:
+
+
<!-- ##### FUNCTION cairo_surface_set_device_offset ##### -->
<para>
diff --git a/doc/public/tmpl/cairo-xlib.sgml b/doc/public/tmpl/cairo-xlib.sgml
index cc106e8c..d4cda456 100644
--- a/doc/public/tmpl/cairo-xlib.sgml
+++ b/doc/public/tmpl/cairo-xlib.sgml
@@ -53,3 +53,14 @@ XLib Backend
@height:
+<!-- ##### FUNCTION cairo_xlib_surface_set_drawable ##### -->
+<para>
+
+</para>
+
+@surface:
+@drawable:
+@width:
+@height:
+
+
diff --git a/doc/public/tmpl/cairo.sgml b/doc/public/tmpl/cairo.sgml
index c3398425..3f2ec8d6 100644
--- a/doc/public/tmpl/cairo.sgml
+++ b/doc/public/tmpl/cairo.sgml
@@ -48,6 +48,7 @@ Drawing contexts.
</para>
@cr:
+@Returns:
<!-- ##### FUNCTION cairo_destroy ##### -->
@@ -190,6 +191,25 @@ Drawing contexts.
@tolerance:
+<!-- ##### ENUM cairo_antialias_t ##### -->
+<para>
+
+</para>
+
+@CAIRO_ANTIALIAS_DEFAULT:
+@CAIRO_ANTIALIAS_NONE:
+@CAIRO_ANTIALIAS_GRAY:
+@CAIRO_ANTIALIAS_SUBPIXEL:
+
+<!-- ##### FUNCTION cairo_set_antialias ##### -->
+<para>
+
+</para>
+
+@cr:
+@antialias:
+
+
<!-- ##### ENUM cairo_fill_rule_t ##### -->
<para>
@@ -845,6 +865,15 @@ Drawing contexts.
@Returns:
+<!-- ##### FUNCTION cairo_get_antialias ##### -->
+<para>
+
+</para>
+
+@cr:
+@Returns:
+
+
<!-- ##### FUNCTION cairo_get_current_point ##### -->
<para>
@@ -1115,3 +1144,10 @@ Drawing contexts.
@Returns:
+<!-- ##### FUNCTION cairo_debug_reset_static_data ##### -->
+<para>
+
+</para>
+
+
+
diff --git a/src/Makefile.am b/src/Makefile.am
index 16cbb1c5..de7d8004 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -85,12 +85,18 @@ libcairo_la_SOURCES = \
cairo-arc-private.h \
cairo-array.c \
cairo-cache.c \
+ cairo-clip.c \
+ cairo-clip-private.h \
cairo-color.c \
+ cairo-debug.c \
+ cairo-debug.h \
cairo-fixed.c \
cairo-font.c \
cairo-font-options.c \
cairo-gstate.c \
cairo-gstate-private.h \
+ cairo-hash.c \
+ cairo-hash-private.h \
cairo-hull.c \
cairo-image-surface.c \
cairo-matrix.c \
diff --git a/src/cairo-arc.c b/src/cairo-arc.c
index e653fcda..e9f35993 100644
--- a/src/cairo-arc.c
+++ b/src/cairo-arc.c
@@ -34,8 +34,6 @@
* Carl D. Worth <cworth@cworth.org>
*/
-#include <math.h>
-
#include "cairo-arc-private.h"
/* Spline deviation from the circle in radius would be given by:
diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index 990a2311..8aff8cd6 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -105,12 +105,11 @@ CreateSizedCopyOfStyle(ATSUStyle inStyle, cairo_matrix_t *scale)
static cairo_status_t
-_cairo_atsui_font_create(const char *family,
- cairo_font_slant_t slant,
- cairo_font_weight_t weight,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm,
- cairo_scaled_font_t **font_out)
+_cairo_atsui_font_create_toy(const cairo_toy_font_face *toy_face,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ const cairo_font_options_t *options,
+ cairo_scaled_font_t **font_out)
{
cairo_atsui_font_t *font = NULL;
ATSUStyle style;
@@ -118,11 +117,11 @@ _cairo_atsui_font_create(const char *family,
OSStatus err;
Boolean isItalic, isBold;
cairo_matrix_t scale;
+ const char *family = toy_face->family;
err = ATSUCreateStyle(&style);
-
- switch (weight) {
+ switch (toy_face->weight) {
case CAIRO_FONT_WEIGHT_BOLD:
isBold = true;
break;
@@ -132,7 +131,7 @@ _cairo_atsui_font_create(const char *family,
break;
}
- switch (slant) {
+ switch (toy_face->slant) {
case CAIRO_FONT_SLANT_ITALIC:
isItalic = true;
break;
@@ -188,7 +187,7 @@ _cairo_atsui_font_create(const char *family,
font = malloc(sizeof(cairo_atsui_font_t));
- _cairo_scaled_font_init(&font->base, font_matrix, ctm,
+ _cairo_scaled_font_init(&font->base, font_matrix, ctm, options,
&cairo_atsui_scaled_font_backend);
cairo_matrix_multiply(&scale, font_matrix, ctm);
@@ -213,9 +212,8 @@ _cairo_atsui_font_create(const char *family,
return CAIRO_STATUS_SUCCESS;
}
-
static void
-_cairo_atsui_font_destroy_font(void *abstract_font)
+_cairo_atsui_font_fini(void *abstract_font)
{
cairo_atsui_font_t *font = abstract_font;
@@ -690,8 +688,8 @@ _cairo_atsui_font_glyph_path(void *abstract_font,
}
const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend = {
- _cairo_atsui_font_create,
- _cairo_atsui_font_destroy_font,
+ _cairo_atsui_font_create_toy,
+ _cairo_atsui_font_fini,
_cairo_atsui_font_font_extents,
_cairo_atsui_font_text_to_glyphs,
_cairo_atsui_font_glyph_extents,
diff --git a/src/cairo-clip-private.h b/src/cairo-clip-private.h
new file mode 100644
index 00000000..23eb78c9
--- /dev/null
+++ b/src/cairo-clip-private.h
@@ -0,0 +1,123 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ * Kristian Høgsberg <krh@redhat.com>
+ */
+
+#ifndef CAIRO_CLIP_PRIVATE_H
+#define CAIRO_CLIP_PRIVATE_H
+
+#include "cairo-path-fixed-private.h"
+
+enum _cairo_clip_mode {
+ CAIRO_CLIP_MODE_PATH,
+ CAIRO_CLIP_MODE_REGION,
+ CAIRO_CLIP_MODE_MASK
+};
+
+struct _cairo_clip_path {
+ unsigned int ref_count;
+ cairo_path_fixed_t path;
+ cairo_fill_rule_t fill_rule;
+ double tolerance;
+ cairo_antialias_t antialias;
+ cairo_clip_path_t *prev;
+};
+
+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_private void
+_cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target);
+
+cairo_private void
+_cairo_clip_fini (cairo_clip_t *clip);
+
+cairo_private void
+_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other);
+
+cairo_private cairo_status_t
+_cairo_clip_reset (cairo_clip_t *clip);
+
+cairo_private cairo_status_t
+_cairo_clip_clip (cairo_clip_t *clip,
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance,
+ cairo_antialias_t antialias,
+ cairo_surface_t *target);
+
+cairo_private cairo_status_t
+_cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
+ cairo_rectangle_t *rectangle);
+
+cairo_private cairo_status_t
+_cairo_clip_intersect_to_region (cairo_clip_t *clip,
+ pixman_region16_t *region);
+
+cairo_private cairo_status_t
+_cairo_clip_combine_to_surface (cairo_clip_t *clip,
+ cairo_operator_t operator,
+ cairo_surface_t *dst,
+ int dst_x,
+ int dst_y,
+ const cairo_rectangle_t *extents);
+
+#endif /* CAIRO_CLIP_PRIVATE_H */
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
new file mode 100644
index 00000000..d479da8f
--- /dev/null
+++ b/src/cairo-clip.c
@@ -0,0 +1,466 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2002 University of Southern California
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ * Carl D. Worth <cworth@cworth.org>
+ * Kristian Høgsberg <krh@redhat.com>
+ */
+
+#include "cairoint.h"
+#include "cairo-clip-private.h"
+
+static cairo_clip_path_t *
+_cairo_clip_path_reference (cairo_clip_path_t *clip_path);
+
+static void
+_cairo_clip_path_destroy (cairo_clip_path_t *clip_path);
+
+/* Creates a region from a cairo_rectangle_t */
+static cairo_status_t
+_region_new_from_rect (cairo_rectangle_t *rect,
+ pixman_region16_t **region)
+{
+ *region = pixman_region_create ();
+ if (pixman_region_union_rect (*region, *region,
+ rect->x, rect->y,
+ rect->width, rect->height) != PIXMAN_REGION_STATUS_SUCCESS) {
+ pixman_region_destroy (*region);
+ return CAIRO_STATUS_NO_MEMORY;
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+/* Gets the bounding box of a region as a cairo_rectangle_t */
+static void
+_region_rect_extents (pixman_region16_t *region,
+ cairo_rectangle_t *rect)
+{
+ pixman_box16_t *region_extents = pixman_region_extents (region);
+
+ rect->x = region_extents->x1;
+ rect->y = region_extents->y1;
+ rect->width = region_extents->x2 - region_extents->x1;
+ rect->height = region_extents->y2 - region_extents->y1;
+}
+
+void
+_cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target)
+{
+ clip->mode = _cairo_surface_get_clip_mode (target);
+ clip->region = NULL;
+ clip->surface = NULL;
+ clip->serial = 0;
+ clip->path = NULL;
+}
+
+void
+_cairo_clip_fini (cairo_clip_t *clip)
+{
+ if (clip->surface)
+ cairo_surface_destroy (clip->surface);
+ clip->surface = NULL;
+
+ if (clip->path)
+ _cairo_clip_path_destroy (clip->path);
+ clip->path = NULL;
+
+ if (clip->region)
+ pixman_region_destroy (clip->region);
+ clip->region = NULL;
+ clip->serial = 0;
+}
+
+void
+_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
+{
+ if (other->region) {
+ clip->region = pixman_region_create ();
+ pixman_region_copy (clip->region, other->region);
+ }
+
+ cairo_surface_reference (other->surface);
+ clip->surface = other->surface;
+ _cairo_clip_path_reference (other->path);
+ clip->path = other->path;
+}
+
+cairo_status_t
+_cairo_clip_reset (cairo_clip_t *clip)
+{
+ /* destroy any existing clip-region artifacts */
+ if (clip->surface)
+ cairo_surface_destroy (clip->surface);
+ clip->surface = NULL;
+
+ if (clip->region)
+ pixman_region_destroy (clip->region);
+ clip->region = NULL;
+
+ if (clip->path)
+ _cairo_clip_path_destroy (clip->path);
+ clip->path = NULL;
+
+ clip->serial = 0;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
+ cairo_rectangle_t *rectangle)
+{
+ if (clip->path) {
+ /* Intersect path extents here. */
+ }
+
+ if (clip->region) {
+ pixman_region16_t *intersection;
+ cairo_status_t status;
+ pixman_region_status_t pixman_status;
+
+ status = _region_new_from_rect (rectangle, &intersection);
+ if (status)
+ return status;
+
+ pixman_status = pixman_region_intersect (intersection,
+ clip->region,
+ intersection);
+ if (pixman_status == PIXMAN_REGION_STATUS_SUCCESS)
+ _region_rect_extents (intersection, rectangle);
+ else
+ status = CAIRO_STATUS_NO_MEMORY;
+
+ pixman_region_destroy (intersection);
+
+ if (status)
+ return status;
+ }
+
+ if (clip->surface)
+ _cairo_rectangle_intersect (rectangle, &clip->surface_rect);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_clip_intersect_to_region (cairo_clip_t *clip,
+ pixman_region16_t *region)
+{
+ if (clip->path) {
+ /* Intersect clip path into region. */
+ }
+
+ if (clip->region)
+ pixman_region_intersect (region, clip->region, region);
+
+ if (clip->surface) {
+ pixman_region16_t *clip_rect;
+ pixman_region_status_t pixman_status;
+ cairo_status_t status;
+
+ status = _region_new_from_rect (&clip->surface_rect, &clip_rect);
+ if (status)
+ return status;
+
+ pixman_status = pixman_region_intersect (region,
+ clip_rect,
+ region);
+ if (pixman_status != PIXMAN_REGION_STATUS_SUCCESS)
+ status = CAIRO_STATUS_NO_MEMORY;
+
+ pixman_region_destroy (clip_rect);
+
+ if (status)
+ return status;
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+/* Combines the region of clip->surface given by extents in
+ * device backend coordinates into the given temporary surface,
+ * which has its origin at dst_x, dst_y in backend coordinates
+ */
+cairo_status_t
+_cairo_clip_combine_to_surface (cairo_clip_t *clip,
+ cairo_operator_t operator,
+ cairo_surface_t *dst,
+ int dst_x,
+ int dst_y,
+ const cairo_rectangle_t *extents)
+{
+ cairo_pattern_union_t pattern;
+ cairo_status_t status;
+
+ _cairo_pattern_init_for_surface (&pattern.surface, clip->surface);
+
+ status = _cairo_surface_composite (operator,
+ &pattern.base,
+ NULL,
+ dst,
+ extents->x - clip->surface_rect.x,
+ extents->y - clip->surface_rect.y,
+ 0, 0,
+ extents->x - dst_x,
+ extents->y - dst_y,
+ extents->width, extents->height);
+
+ _cairo_pattern_fini (&pattern.base);
+
+ return status;
+}
+
+static cairo_status_t
+_cairo_clip_intersect_path (cairo_clip_t *clip,
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance,
+ cairo_antialias_t antialias,
+ cairo_surface_t *target)
+{
+ cairo_clip_path_t *clip_path;
+ cairo_status_t status;
+
+ if (clip->mode != CAIRO_CLIP_MODE_PATH)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ 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;
+
+ clip_path->ref_count = 1;
+ clip_path->fill_rule = fill_rule;
+ clip_path->tolerance = tolerance;
+ clip_path->antialias = antialias;
+ clip_path->prev = clip->path;
+ clip->path = clip_path;
+ clip->serial = _cairo_surface_allocate_clip_serial (target);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_clip_path_t *
+_cairo_clip_path_reference (cairo_clip_path_t *clip_path)
+{
+ if (clip_path == NULL)
+ return NULL;
+
+ clip_path->ref_count++;
+
+ return clip_path;
+}
+
+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_clip_intersect_region (cairo_clip_t *clip,
+ cairo_traps_t *traps,
+ cairo_surface_t *target)
+{
+ pixman_region16_t *region;
+ cairo_status_t status;
+
+ if (clip->mode != CAIRO_CLIP_MODE_REGION)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ status = _cairo_traps_extract_region (traps, &region);
+ if (status)
+ return status;
+
+ if (region == NULL)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ status = CAIRO_STATUS_SUCCESS;
+ if (clip->region == NULL) {
+ clip->region = region;
+ } else {
+ pixman_region16_t *intersection = pixman_region_create();
+
+ if (pixman_region_intersect (intersection,
+ clip->region, region)
+ == PIXMAN_REGION_STATUS_SUCCESS) {
+ pixman_region_destroy (clip->region);
+ clip->region = intersection;
+ } else {
+ status = CAIRO_STATUS_NO_MEMORY;
+ }
+ pixman_region_destroy (region);
+ }
+
+ clip->serial = _cairo_surface_allocate_clip_serial (target);
+
+ return status;
+}
+
+static cairo_status_t
+_cairo_clip_intersect_mask (cairo_clip_t *clip,
+ cairo_traps_t *traps,
+ cairo_antialias_t antialias,
+ cairo_surface_t *target)
+{
+ 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 (clip->surface != NULL)
+ _cairo_rectangle_intersect (&surface_rect, &clip->surface_rect);
+
+ surface = _cairo_surface_create_similar_solid (target,
+ CAIRO_CONTENT_ALPHA,
+ surface_rect.width,
+ surface_rect.height,
+ CAIRO_COLOR_WHITE);
+ if (surface->status)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ /* Render the new clipping path into the new mask surface. */
+
+ _cairo_traps_translate (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,
+ surface,
+ antialias,
+ 0, 0,
+ 0, 0,
+ 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 (clip->surface != NULL) {
+ _cairo_pattern_init_for_surface (&pattern.surface, clip->surface);
+
+ status = _cairo_surface_composite (CAIRO_OPERATOR_IN,
+ &pattern.base,
+ NULL,
+ surface,
+ surface_rect.x - clip->surface_rect.x,
+ surface_rect.y - 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 (clip->surface);
+ }
+
+ clip->surface = surface;
+ clip->surface_rect = surface_rect;
+ clip->serial = _cairo_surface_allocate_clip_serial (target);
+
+ return status;
+}
+
+cairo_status_t
+_cairo_clip_clip (cairo_clip_t *clip,
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance,
+ cairo_antialias_t antialias,
+ cairo_surface_t *target)
+{
+ cairo_status_t status;
+ cairo_traps_t traps;
+
+ status = _cairo_clip_intersect_path (clip,
+ path, fill_rule, tolerance,
+ antialias, target);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
+
+ _cairo_traps_init (&traps);
+ status = _cairo_path_fixed_fill_to_traps (path,
+ fill_rule,
+ tolerance,
+ &traps);
+ if (status)
+ goto bail;
+
+ status = _cairo_clip_intersect_region (clip, &traps, target);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ goto bail;
+
+ status = _cairo_clip_intersect_mask (clip, &traps, antialias, target);
+
+ bail:
+ _cairo_traps_fini (&traps);
+
+ return status;
+}
diff --git a/src/cairo-debug.c b/src/cairo-debug.c
new file mode 100644
index 00000000..31eefc5a
--- /dev/null
+++ b/src/cairo-debug.c
@@ -0,0 +1,73 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ * Carl D. Worth <cworth@cworth.org>
+ */
+
+#include "cairoint.h"
+
+/**
+ * cairo_debug_reset_static_data:
+ *
+ * Resets all static data within cairo to its original state,
+ * (ie. identical to the state at the time of program invocation). For
+ * example, all caches within cairo will be flushed empty.
+ *
+ * This function is intended to be useful when using memory-checking
+ * tools such as valgrind. When valgrind's memcheck analyzes a
+ * cairo-using program without a call to cairo_debug_reset_static_data,
+ * it will report all data reachable via cairo's static objects as
+ * "still reachable". Calling cairo_debug_reset_static_data just prior
+ * to program termination will make it easier to get squeaky clean
+ * reports from valgrind.
+ *
+ * WARNING: It is only safe to call this function when there are no
+ * active cairo objects remaining, (ie. the appropriate destroy
+ * functions have been called as necessary). If there are active cairo
+ * objects, this call is likely to cause a crash, (eg. an assertion
+ * failure due to a hash table being destroyed when non-empty).
+ **/
+void
+cairo_debug_reset_static_data (void)
+{
+#if CAIRO_HAS_XLIB_SURFACE
+ _cairo_xlib_surface_reset_static_data ();
+ _cairo_xlib_screen_reset_static_data ();
+#endif
+
+ _cairo_font_reset_static_data ();
+
+#if CAIRO_HAS_FT_FONT
+ _cairo_ft_font_reset_static_data ();
+#endif
+}
+
diff --git a/src/cairo-debug.h b/src/cairo-debug.h
new file mode 100644
index 00000000..1dab2c74
--- /dev/null
+++ b/src/cairo-debug.h
@@ -0,0 +1,48 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ * Carl D. Worth <cworth@cworth.org>
+ */
+
+#ifndef CAIRO_DEBUG_H
+#define CAIRO_DEBUG_H
+
+#include <cairo-features.h>
+
+CAIRO_BEGIN_DECLS
+
+void
+cairo_debug_reset_static_data (void);
+
+CAIRO_END_DECLS
+
+#endif /* CAIRO_H */
diff --git a/src/cairo-features.h.in b/src/cairo-features.h.in
index 8065be35..fdc1e37e 100644
--- a/src/cairo-features.h.in
+++ b/src/cairo-features.h.in
@@ -37,6 +37,14 @@
#ifndef CAIRO_FEATURES_H
#define CAIRO_FEATURES_H
+#ifdef __cplusplus
+# define CAIRO_BEGIN_DECLS extern "C" {
+# define CAIRO_END_DECLS }
+#else
+# define CAIRO_BEGIN_DECLS
+# define CAIRO_END_DECLS
+#endif
+
@PS_SURFACE_FEATURE@
@PDF_SURFACE_FEATURE@
diff --git a/src/cairo-font-subset.c b/src/cairo-font-subset.c
index e3a2784c..bd113f98 100644
--- a/src/cairo-font-subset.c
+++ b/src/cairo-font-subset.c
@@ -71,6 +71,10 @@ struct cairo_pdf_ft_font {
cairo_status_t status;
};
+static int
+cairo_pdf_ft_font_use_glyph (void *abstract_font, int glyph);
+
+
#define ARRAY_LENGTH(a) ( (sizeof (a)) / (sizeof ((a)[0])) )
#define SFNT_VERSION 0x00010000
@@ -134,6 +138,7 @@ _cairo_font_subset_destroy (cairo_font_subset_t *font)
cairo_font_subset_t *
_cairo_font_subset_create (cairo_unscaled_font_t *unscaled_font)
{
+ cairo_ft_unscaled_font_t *ft_unscaled_font;
FT_Face face;
cairo_pdf_ft_font_t *font;
unsigned long size;
@@ -143,7 +148,9 @@ _cairo_font_subset_create (cairo_unscaled_font_t *unscaled_font)
if (! _cairo_unscaled_font_is_ft (unscaled_font))
return NULL;
- face = _cairo_ft_unscaled_font_lock_face (unscaled_font);
+ ft_unscaled_font = (cairo_ft_unscaled_font_t *) unscaled_font;
+
+ face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font);
/* We currently only support freetype truetype fonts. */
size = 0;
@@ -155,8 +162,7 @@ _cairo_font_subset_create (cairo_unscaled_font_t *unscaled_font)
if (font == NULL)
return NULL;
- font->base.unscaled_font = unscaled_font;
- _cairo_unscaled_font_reference (unscaled_font);
+ font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font);
font->base.backend = &cairo_pdf_ft_font_backend;
_cairo_array_init (&font->output, sizeof (char));
@@ -193,7 +199,7 @@ _cairo_font_subset_create (cairo_unscaled_font_t *unscaled_font)
if (font->base.widths == NULL)
goto fail5;
- _cairo_ft_unscaled_font_unlock_face (unscaled_font);
+ _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
font->status = CAIRO_STATUS_SUCCESS;
@@ -310,6 +316,62 @@ cairo_pdf_ft_font_write_generic_table (cairo_pdf_ft_font_t *font,
return 0;
}
+
+typedef struct composite_glyph composite_glyph_t;
+struct composite_glyph {
+ unsigned short flags;
+ unsigned short index;
+ unsigned short args[7]; /* 1 to 7 arguments depending on value of flags */
+};
+
+typedef struct glyph_data glyph_data_t;
+struct glyph_data {
+ short num_contours;
+ char data[8];
+ composite_glyph_t glyph;
+};
+
+/* composite_glyph_t flags */
+#define ARG_1_AND_2_ARE_WORDS 0x0001
+#define WE_HAVE_A_SCALE 0x0008
+#define MORE_COMPONENTS 0x0020
+#define WE_HAVE_AN_X_AND_Y_SCALE 0x0040
+#define WE_HAVE_A_TWO_BY_TWO 0x0080
+
+static void
+cairo_pdf_ft_font_remap_composite_glyph (cairo_pdf_ft_font_t *font,
+ unsigned char *buffer)
+{
+ glyph_data_t *glyph_data;
+ composite_glyph_t *composite_glyph;
+ int num_args;
+ int has_more_components;
+ unsigned short flags;
+ unsigned short index;
+
+ glyph_data = (glyph_data_t *) buffer;
+ if ((short)be16_to_cpu (glyph_data->num_contours) >= 0)
+ return;
+
+ composite_glyph = &glyph_data->glyph;
+ do {
+ flags = be16_to_cpu (composite_glyph->flags);
+ has_more_components = flags & MORE_COMPONENTS;
+ index = cairo_pdf_ft_font_use_glyph (font, be16_to_cpu (composite_glyph->index));
+ composite_glyph->index = cpu_to_be16 (index);
+ num_args = 1;
+ if (flags & ARG_1_AND_2_ARE_WORDS)
+ num_args += 1;
+ if (flags & WE_HAVE_A_SCALE)
+ num_args += 1;
+ else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
+ num_args += 2;
+ else if (flags & WE_HAVE_A_TWO_BY_TWO)
+ num_args += 3;
+ composite_glyph = (composite_glyph_t *) &(composite_glyph->args[num_args]);
+ } while (has_more_components);
+}
+
static int
cairo_pdf_ft_font_write_glyf_table (cairo_pdf_ft_font_t *font,
unsigned long tag)
@@ -357,8 +419,10 @@ cairo_pdf_ft_font_write_glyf_table (cairo_pdf_ft_font_t *font,
buffer = cairo_pdf_ft_font_write (font, NULL, size);
if (buffer == NULL)
break;
- FT_Load_Sfnt_Table (font->face, TTAG_glyf, begin, buffer, &size);
- /* FIXME: remap composite glyphs */
+ if (size != 0) {
+ FT_Load_Sfnt_Table (font->face, TTAG_glyf, begin, buffer, &size);
+ cairo_pdf_ft_font_remap_composite_glyph (font, buffer);
+ }
}
font->glyphs[i].location =
@@ -513,10 +577,14 @@ struct table {
};
static const table_t truetype_tables[] = {
+ /* As we write out the glyf table we remap composite glyphs.
+ * Remapping composite glyphs will reference the sub glyphs the
+ * composite glyph is made up of. That needs to be done first so
+ * we have all the glyphs in the subset before going further. */
+ { TTAG_glyf, cairo_pdf_ft_font_write_glyf_table },
{ TTAG_cmap, cairo_pdf_ft_font_write_cmap_table },
{ TTAG_cvt, cairo_pdf_ft_font_write_generic_table },
{ TTAG_fpgm, cairo_pdf_ft_font_write_generic_table },
- { TTAG_glyf, cairo_pdf_ft_font_write_glyf_table },
{ TTAG_head, cairo_pdf_ft_font_write_head_table },
{ TTAG_hhea, cairo_pdf_ft_font_write_hhea_table },
{ TTAG_hmtx, cairo_pdf_ft_font_write_hmtx_table },
@@ -589,11 +657,18 @@ static cairo_status_t
cairo_pdf_ft_font_generate (void *abstract_font,
const char **data, unsigned long *length)
{
+ cairo_ft_unscaled_font_t *ft_unscaled_font;
cairo_pdf_ft_font_t *font = abstract_font;
unsigned long start, end, next, checksum, *checksum_location;
int i;
- font->face = _cairo_ft_unscaled_font_lock_face (font->base.unscaled_font);
+ /* XXX: It would be cleaner to do something besides this cast
+ * here. Perhaps cairo_pdf_ft_font_t should just have the
+ * cairo_ft_unscaled_font_t rather than having the generic
+ * cairo_unscaled_font_t in the base class? */
+ ft_unscaled_font = (cairo_ft_unscaled_font_t *) font->base.unscaled_font;
+
+ font->face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font);
if (cairo_pdf_ft_font_write_offset_table (font))
goto fail;
@@ -622,7 +697,7 @@ cairo_pdf_ft_font_generate (void *abstract_font,
*length = _cairo_array_num_elements (&font->output);
fail:
- _cairo_ft_unscaled_font_unlock_face (font->base.unscaled_font);
+ _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
font->face = NULL;
return font->status;
diff --git a/src/cairo-font.c b/src/cairo-font.c
index 9645f3df..10fcb5f5 100644
--- a/src/cairo-font.c
+++ b/src/cairo-font.c
@@ -42,7 +42,7 @@
/* Forward declare so we can use it as an arbitrary backend for
* _cairo_font_face_nil.
*/
-static const cairo_font_face_backend_t _cairo_simple_font_face_backend;
+static const cairo_font_face_backend_t _cairo_toy_font_face_backend;
/* cairo_font_face_t */
@@ -50,7 +50,7 @@ const cairo_font_face_t _cairo_font_face_nil = {
CAIRO_STATUS_NO_MEMORY, /* status */
-1, /* ref_count */
{ 0, 0, 0, NULL }, /* user_data */
- &_cairo_simple_font_face_backend
+ &_cairo_toy_font_face_backend
};
void
@@ -72,17 +72,21 @@ _cairo_font_face_init (cairo_font_face_t *font_face,
* 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.
+ *
+ * Return value: the referenced #cairo_font_face_t.
**/
-void
+cairo_font_face_t *
cairo_font_face_reference (cairo_font_face_t *font_face)
{
if (font_face == NULL)
- return;
+ return NULL;
if (font_face->ref_count == (unsigned int)-1)
- return;
+ return font_face;
font_face->ref_count++;
+
+ return font_face;
}
/**
@@ -121,7 +125,7 @@ cairo_font_face_destroy (cairo_font_face_t *font_face)
/**
* cairo_font_face_status:
- * @surface: a #cairo_font_face_t
+ * @font_face: a #cairo_font_face_t
*
* Checks whether an error has previously occurred for this
* font face
@@ -184,19 +188,6 @@ cairo_font_face_set_user_data (cairo_font_face_t *font_face,
key, user_data, destroy);
}
-/* cairo_simple_font_face_t - simple family/slant/weight font faces used for
- * the built-in font API
- */
-
-typedef struct _cairo_simple_font_face cairo_simple_font_face_t;
-
-struct _cairo_simple_font_face {
- cairo_font_face_t base;
- char *family;
- cairo_font_slant_t slant;
- cairo_font_weight_t weight;
-};
-
/* We maintain a global cache from family/weight/slant => cairo_font_face_t
* for cairo_simple_font_t. The primary purpose of this cache is to provide
* unique cairo_font_face_t values so that our cache from
@@ -214,7 +205,7 @@ typedef struct {
typedef struct {
cairo_simple_cache_key_t key;
- cairo_simple_font_face_t *font_face;
+ cairo_toy_font_face_t *font_face;
} cairo_simple_cache_entry_t;
static const cairo_cache_backend_t _cairo_simple_font_cache_backend;
@@ -233,11 +224,11 @@ _unlock_global_simple_cache (void)
CAIRO_MUTEX_UNLOCK (_global_simple_cache_mutex);
}
+static cairo_cache_t *global_simple_cache = NULL;
+
static cairo_cache_t *
_get_global_simple_cache (void)
{
- static cairo_cache_t *global_simple_cache = NULL;
-
if (global_simple_cache == NULL)
{
global_simple_cache = malloc (sizeof (cairo_cache_t));
@@ -287,12 +278,12 @@ _cairo_simple_font_cache_keys_equal (void *cache,
a->weight == b->weight;
}
-static cairo_simple_font_face_t *
-_cairo_simple_font_face_create_from_cache_key (cairo_simple_cache_key_t *key)
+static cairo_toy_font_face_t *
+_cairo_toy_font_face_create_from_cache_key (cairo_simple_cache_key_t *key)
{
- cairo_simple_font_face_t *simple_face;
+ cairo_toy_font_face_t *simple_face;
- simple_face = malloc (sizeof (cairo_simple_font_face_t));
+ simple_face = malloc (sizeof (cairo_toy_font_face_t));
if (!simple_face)
return NULL;
@@ -305,7 +296,7 @@ _cairo_simple_font_face_create_from_cache_key (cairo_simple_cache_key_t *key)
simple_face->slant = key->slant;
simple_face->weight = key->weight;
- _cairo_font_face_init (&simple_face->base, &_cairo_simple_font_face_backend);
+ _cairo_font_face_init (&simple_face->base, &_cairo_toy_font_face_backend);
return simple_face;
}
@@ -322,7 +313,7 @@ _cairo_simple_font_cache_create_entry (void *cache,
if (entry == NULL)
return CAIRO_STATUS_NO_MEMORY;
- entry->font_face = _cairo_simple_font_face_create_from_cache_key (k);
+ entry->font_face = _cairo_toy_font_face_create_from_cache_key (k);
if (!entry->font_face) {
free (entry);
return CAIRO_STATUS_NO_MEMORY;
@@ -366,9 +357,9 @@ static const cairo_cache_backend_t _cairo_simple_font_cache_backend = {
};
static void
-_cairo_simple_font_face_destroy (void *abstract_face)
+_cairo_toy_font_face_destroy (void *abstract_face)
{
- cairo_simple_font_face_t *simple_face = abstract_face;
+ cairo_toy_font_face_t *simple_face = abstract_face;
cairo_cache_t *cache;
cairo_simple_cache_key_t key;
@@ -391,27 +382,27 @@ _cairo_simple_font_face_destroy (void *abstract_face)
}
static cairo_status_t
-_cairo_simple_font_face_create_font (void *abstract_face,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm,
- const cairo_font_options_t *options,
- cairo_scaled_font_t **scaled_font)
+_cairo_toy_font_face_scaled_font_create (void *abstract_face,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ const cairo_font_options_t *options,
+ cairo_scaled_font_t **scaled_font)
{
const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT;
- cairo_simple_font_face_t *simple_face = abstract_face;
+ cairo_toy_font_face_t *simple_face = abstract_face;
- return backend->create (simple_face->family, simple_face->slant, simple_face->weight,
- font_matrix, ctm, options, scaled_font);
+ return backend->create_toy (simple_face,
+ font_matrix, ctm, options, scaled_font);
}
-static const cairo_font_face_backend_t _cairo_simple_font_face_backend = {
- _cairo_simple_font_face_destroy,
- _cairo_simple_font_face_create_font,
+static const cairo_font_face_backend_t _cairo_toy_font_face_backend = {
+ _cairo_toy_font_face_destroy,
+ _cairo_toy_font_face_scaled_font_create
};
/**
- * _cairo_simple_font_face_create:
+ * _cairo_toy_font_face_create:
* @family: a font family name, encoded in UTF-8
* @slant: the slant for the font
* @weight: the weight for the font
@@ -424,9 +415,9 @@ static const cairo_font_face_backend_t _cairo_simple_font_face_backend = {
* cairo_font_face_destroy()
**/
cairo_font_face_t *
-_cairo_simple_font_face_create (const char *family,
- cairo_font_slant_t slant,
- cairo_font_weight_t weight)
+_cairo_toy_font_face_create (const char *family,
+ cairo_font_slant_t slant,
+ cairo_font_weight_t weight)
{
cairo_simple_cache_entry_t *entry;
cairo_simple_cache_key_t key;
@@ -466,6 +457,10 @@ static const cairo_scaled_font_t _cairo_scaled_font_nil = {
{ 1., 0., 0., 1., 0, 0}, /* font_matrix */
{ 1., 0., 0., 1., 0, 0}, /* ctm */
{ 1., 0., 0., 1., 0, 0}, /* scale */
+ { CAIRO_ANTIALIAS_DEFAULT, /* options */
+ CAIRO_SUBPIXEL_ORDER_DEFAULT,
+ CAIRO_HINT_STYLE_DEFAULT,
+ CAIRO_HINT_METRICS_DEFAULT} ,
NULL, /* font_face */
CAIRO_SCALED_FONT_BACKEND_DEFAULT,
};
@@ -497,7 +492,7 @@ _cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font,
/**
* cairo_scaled_font_status:
- * @surface: a #cairo_scaled_font_t
+ * @scaled_font: a #cairo_scaled_font_t
*
* Checks whether an error has previously occurred for this
* scaled_font.
@@ -560,11 +555,11 @@ _unlock_global_font_cache (void)
CAIRO_MUTEX_UNLOCK (_global_font_cache_mutex);
}
+static cairo_cache_t *outer_font_cache = NULL;
+
static cairo_cache_t *
_get_outer_font_cache (void)
{
- static cairo_cache_t *outer_font_cache = NULL;
-
if (outer_font_cache == NULL)
{
outer_font_cache = malloc (sizeof (cairo_cache_t));
@@ -585,11 +580,11 @@ _get_outer_font_cache (void)
return NULL;
}
+static cairo_cache_t *inner_font_cache = NULL;
+
static cairo_cache_t *
_get_inner_font_cache (void)
{
- static cairo_cache_t *inner_font_cache = NULL;
-
if (inner_font_cache == NULL)
{
inner_font_cache = malloc (sizeof (cairo_cache_t));
@@ -743,11 +738,11 @@ _cairo_inner_font_cache_create_entry (void *cache,
if (entry == NULL)
return CAIRO_STATUS_NO_MEMORY;
- status = k->font_face->backend->create_font (k->font_face,
- k->font_matrix,
- k->ctm,
- &k->options,
- &entry->scaled_font);
+ status = k->font_face->backend->scaled_font_create (k->font_face,
+ k->font_matrix,
+ k->ctm,
+ &k->options,
+ &entry->scaled_font);
if (status) {
free (entry);
return status;
@@ -864,6 +859,7 @@ void
_cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
+ const cairo_font_options_t *options,
const cairo_scaled_font_backend_t *backend)
{
scaled_font->status = CAIRO_STATUS_SUCCESS;
@@ -871,6 +867,8 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
scaled_font->font_matrix = *font_matrix;
scaled_font->ctm = *ctm;
cairo_matrix_multiply (&scaled_font->scale, &scaled_font->font_matrix, &scaled_font->ctm);
+
+ scaled_font->options = *options;
scaled_font->ref_count = 1;
scaled_font->backend = backend;
@@ -992,13 +990,15 @@ _cairo_unscaled_font_init (cairo_unscaled_font_t *unscaled_font,
unscaled_font->backend = backend;
}
-void
+cairo_unscaled_font_t *
_cairo_unscaled_font_reference (cairo_unscaled_font_t *unscaled_font)
{
if (unscaled_font == NULL)
- return;
+ return NULL;
unscaled_font->ref_count++;
+
+ return unscaled_font;
}
void
@@ -1027,17 +1027,21 @@ _cairo_unscaled_font_destroy (cairo_unscaled_font_t *unscaled_font)
* Increases the reference count on @scaled_font by one. This prevents
* @scaled_font from being destroyed until a matching call to
* cairo_scaled_font_destroy() is made.
+ *
+ * Return value: the referenced #cairo_scaled_font_t.
**/
-void
+cairo_scaled_font_t *
cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font)
{
if (scaled_font == NULL)
- return;
+ return NULL;
if (scaled_font->ref_count == (unsigned int)-1)
- return;
+ return scaled_font;
scaled_font->ref_count++;
+
+ return scaled_font;
}
/**
@@ -1071,6 +1075,7 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
key.font_face = scaled_font->font_face;
key.font_matrix = &scaled_font->font_matrix;
key.ctm = &scaled_font->ctm;
+ key.options = scaled_font->options;
_cairo_cache_remove (cache, &key);
_unlock_global_font_cache ();
@@ -1078,7 +1083,7 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
cairo_font_face_destroy (scaled_font->font_face);
}
- scaled_font->backend->destroy (scaled_font);
+ scaled_font->backend->fini (scaled_font);
free (scaled_font);
}
@@ -1089,9 +1094,6 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
* @extents: a #cairo_font_extents_t which to store the retrieved extents.
*
* Gets the metrics for a #cairo_scaled_font_t.
- *
- * Return value: %CAIRO_STATUS_SUCCESS on success. Otherwise, an
- * error such as %CAIRO_STATUS_NO_MEMORY.
**/
void
cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font,
@@ -1344,8 +1346,10 @@ _cairo_lock_global_image_glyph_cache()
void
_cairo_unlock_global_image_glyph_cache()
{
- _cairo_cache_shrink_to (_global_image_glyph_cache,
- CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT);
+ if (_global_image_glyph_cache) {
+ _cairo_cache_shrink_to (_global_image_glyph_cache,
+ CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT);
+ }
CAIRO_MUTEX_UNLOCK (_global_image_glyph_cache_mutex);
}
@@ -1372,3 +1376,24 @@ _cairo_get_global_image_glyph_cache ()
_global_image_glyph_cache = NULL;
return NULL;
}
+
+void
+_cairo_font_reset_static_data (void)
+{
+ _lock_global_font_cache ();
+ _cairo_cache_destroy (outer_font_cache);
+ outer_font_cache = NULL;
+ _cairo_cache_destroy (inner_font_cache);
+ inner_font_cache = NULL;
+ _unlock_global_font_cache ();
+
+ _cairo_lock_global_image_glyph_cache();
+ _cairo_cache_destroy (_global_image_glyph_cache);
+ _global_image_glyph_cache = NULL;
+ _cairo_unlock_global_image_glyph_cache();
+
+ _lock_global_simple_cache ();
+ _cairo_cache_destroy (global_simple_cache);
+ global_simple_cache = NULL;
+ _unlock_global_simple_cache ();
+}
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index afe80dff..36a0c674 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -76,31 +76,31 @@
* factors so that hinting works right
*/
-typedef struct {
+typedef struct _cairo_ft_font_transform {
double x_scale, y_scale;
double shape[2][2];
-} ft_font_transform_t;
+} cairo_ft_font_transform_t;
/*
* We create an object that corresponds to a single font on the disk;
* (identified by a filename/id pair) these are shared between all
- * fonts using that file. For cairo_ft_scaled_font_create_for_ft_face(), we
+ * fonts using that file. For cairo_ft_font_face_create_for_ft_face(), we
* just create a one-off version with a permanent face value.
*/
-typedef struct _ft_font_face ft_font_face_t;
+typedef struct _cairo_ft_font_face cairo_ft_font_face_t;
-typedef struct {
+struct _cairo_ft_unscaled_font {
cairo_unscaled_font_t base;
- cairo_bool_t from_face; /* from cairo_ft_scaled_font_create_for_ft_face()? */
+ cairo_bool_t from_face; /* from cairo_ft_font_face_create_for_ft_face()? */
FT_Face face; /* provided or cached face */
/* only set if from_face is false */
char *filename;
int id;
- /* We temporarily scale the unscaled font as neede */
+ /* We temporarily scale the unscaled font as needed */
cairo_bool_t have_scale;
cairo_matrix_t current_scale;
double x_scale; /* Extracted X scale factor */
@@ -109,38 +109,91 @@ typedef struct {
int lock; /* count of how many times this font has been locked */
- ft_font_face_t *faces; /* Linked list of faces for this font */
-} ft_unscaled_font_t;
+ cairo_ft_font_face_t *faces; /* Linked list of faces for this font */
+};
-struct _ft_font_face {
+struct _cairo_ft_font_face {
cairo_font_face_t base;
- ft_unscaled_font_t *unscaled;
+ cairo_ft_unscaled_font_t *unscaled;
int load_flags;
- ft_font_face_t *next_face;
+ cairo_ft_font_face_t *next;
};
const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend;
-static ft_unscaled_font_t *
-_ft_unscaled_font_create_from_face (FT_Face face)
+/**
+ * _cairo_ft_unscaled_font_init:
+ *
+ * Initialize a cairo_ft_unscaled_font_t.
+ *
+ * There are two basic flavors of cairo_ft_unscaled_font_t, one
+ * created from an FT_Face and the other created from a filename/id
+ * pair. These two flavors are identified as from_face and !from_face.
+ *
+ * To initialize a from_face font, pass filename==NULL, id=0 and the
+ * desired face.
+ *
+ * To initialize a !from_face font, pass the filename/id as desired
+ * and face==NULL.
+ *
+ * Note that the code handles these two flavors in very distinct
+ * ways. For example there is a hash_table mapping
+ * filename/id->cairo_unscaled_font_t in the !from_face case, but no
+ * parallel in the from_face case, (where the calling code would have
+ * to do its own mapping to ensure similar sharing).
+ **/
+static cairo_status_t
+_cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
+ const char *filename,
+ int id,
+ FT_Face face)
{
- ft_unscaled_font_t *unscaled = malloc (sizeof(ft_unscaled_font_t));
- if (!unscaled)
- return NULL;
-
- unscaled->from_face = 1;
- unscaled->face = face;
+ char *filename_copy = NULL;
+
+ if (filename) {
+ filename_copy = strdup (filename);
+ if (filename_copy == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+ }
+
+ unscaled->filename = filename_copy;
+ unscaled->id = id;
+
+ if (face) {
+ unscaled->from_face = 1;
+ unscaled->face = face;
+ } else {
+ unscaled->from_face = 0;
+ unscaled->face = NULL;
+ }
- unscaled->filename = NULL;
- unscaled->id = 0;
-
unscaled->have_scale = 0;
unscaled->lock = 0;
-
+
unscaled->faces = NULL;
_cairo_unscaled_font_init (&unscaled->base,
&cairo_ft_unscaled_font_backend);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_ft_unscaled_font_t *
+_cairo_ft_unscaled_font_create_from_face (FT_Face face)
+{
+ cairo_status_t status;
+ cairo_ft_unscaled_font_t *unscaled;
+
+ unscaled = malloc (sizeof (cairo_ft_unscaled_font_t));
+ if (unscaled == NULL)
+ return NULL;
+
+ status = _cairo_ft_unscaled_font_init (unscaled, NULL, 0, face);
+ if (status) {
+ free (unscaled);
+ return NULL;
+ }
+
return unscaled;
}
@@ -150,36 +203,23 @@ _cairo_unscaled_font_is_ft (cairo_unscaled_font_t *unscaled_font)
return unscaled_font->backend == &cairo_ft_unscaled_font_backend;
}
-static ft_unscaled_font_t *
-_ft_unscaled_font_create_from_filename (const char *filename,
- int id)
+static cairo_ft_unscaled_font_t *
+_cairo_ft_unscaled_font_create_from_filename (const char *filename,
+ int id)
{
- ft_unscaled_font_t *unscaled;
- char *new_filename;
+ cairo_status_t status;
+ cairo_ft_unscaled_font_t *unscaled;
- new_filename = strdup (filename);
- if (!new_filename)
+ unscaled = malloc (sizeof (cairo_ft_unscaled_font_t));
+ if (unscaled == NULL)
return NULL;
- unscaled = malloc (sizeof (ft_unscaled_font_t));
- if (!unscaled) {
- free (new_filename);
+ status = _cairo_ft_unscaled_font_init (unscaled, filename, id, NULL);
+ if (status) {
+ free (unscaled);
return NULL;
}
-
- unscaled->from_face = 0;
- unscaled->face = NULL;
-
- unscaled->filename = new_filename;
- unscaled->id = id;
-
- unscaled->have_scale = 0;
- unscaled->lock = 0;
-
- unscaled->faces = NULL;
- _cairo_unscaled_font_init (&unscaled->base,
- &cairo_ft_unscaled_font_backend);
return unscaled;
}
@@ -199,7 +239,7 @@ typedef struct {
typedef struct {
cairo_ft_cache_key_t key;
- ft_unscaled_font_t *unscaled;
+ cairo_ft_unscaled_font_t *unscaled;
} cairo_ft_cache_entry_t;
typedef struct {
@@ -209,7 +249,7 @@ typedef struct {
} ft_cache_t;
static unsigned long
-_ft_font_cache_hash (void *cache, void *key)
+_cairo_ft_font_cache_hash (void *cache, void *key)
{
cairo_ft_cache_key_t *in = (cairo_ft_cache_key_t *) key;
unsigned long hash;
@@ -222,9 +262,9 @@ _ft_font_cache_hash (void *cache, void *key)
}
static int
-_ft_font_cache_keys_equal (void *cache,
- void *k1,
- void *k2)
+_cairo_ft_font_cache_keys_equal (void *cache,
+ void *k1,
+ void *k2)
{
cairo_ft_cache_key_t *a;
cairo_ft_cache_key_t *b;
@@ -236,9 +276,9 @@ _ft_font_cache_keys_equal (void *cache,
}
static cairo_status_t
-_ft_font_cache_create_entry (void *cache,
- void *key,
- void **return_entry)
+_cairo_ft_font_cache_create_entry (void *cache,
+ void *key,
+ void **return_entry)
{
cairo_ft_cache_key_t *k = key;
cairo_ft_cache_entry_t *entry;
@@ -247,8 +287,8 @@ _ft_font_cache_create_entry (void *cache,
if (entry == NULL)
return CAIRO_STATUS_NO_MEMORY;
- entry->unscaled = _ft_unscaled_font_create_from_filename (k->filename,
- k->id);
+ entry->unscaled = _cairo_ft_unscaled_font_create_from_filename (k->filename,
+ k->id);
if (!entry->unscaled) {
free (entry);
return CAIRO_STATUS_NO_MEMORY;
@@ -268,8 +308,8 @@ _ft_font_cache_create_entry (void *cache,
* in the code that removes the entry from the cache
*/
static void
-_ft_font_cache_destroy_entry (void *cache,
- void *entry)
+_cairo_ft_font_cache_destroy_entry (void *cache,
+ void *entry)
{
cairo_ft_cache_entry_t *e = (cairo_ft_cache_entry_t *) entry;
@@ -277,7 +317,7 @@ _ft_font_cache_destroy_entry (void *cache,
}
static void
-_ft_font_cache_destroy_cache (void *cache)
+_cairo_ft_font_cache_destroy_cache (void *cache)
{
ft_cache_t *fc = (ft_cache_t *) cache;
@@ -286,11 +326,11 @@ _ft_font_cache_destroy_cache (void *cache)
}
static const cairo_cache_backend_t _ft_font_cache_backend = {
- _ft_font_cache_hash,
- _ft_font_cache_keys_equal,
- _ft_font_cache_create_entry,
- _ft_font_cache_destroy_entry,
- _ft_font_cache_destroy_cache
+ _cairo_ft_font_cache_hash,
+ _cairo_ft_font_cache_keys_equal,
+ _cairo_ft_font_cache_create_entry,
+ _cairo_ft_font_cache_destroy_entry,
+ _cairo_ft_font_cache_destroy_cache
};
static ft_cache_t *_global_ft_cache = NULL;
@@ -339,8 +379,8 @@ _get_global_ft_cache (void)
/* Finds or creates a ft_unscaled_font for the filename/id from pattern.
* Returns a new reference to the unscaled font.
*/
-static ft_unscaled_font_t *
-_ft_unscaled_font_get_for_pattern (FcPattern *pattern)
+static cairo_ft_unscaled_font_t *
+_cairo_ft_unscaled_font_get_for_pattern (FcPattern *pattern)
{
cairo_ft_cache_entry_t *entry;
cairo_ft_cache_key_t key;
@@ -384,9 +424,12 @@ _has_unlocked_face (void *entry)
/* Ensures that an unscaled font has a face object. If we exceed
* MAX_OPEN_FACES, try to close some.
+ *
+ * This differs from _cairo_ft_scaled_font_lock_face in that it doesn't
+ * set the scale on the face, but just returns it at the last scale.
*/
-static FT_Face
-_ft_unscaled_font_lock_face (ft_unscaled_font_t *unscaled)
+FT_Face
+_cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled)
{
ft_cache_t *ftcache;
FT_Face face = NULL;
@@ -433,8 +476,8 @@ _ft_unscaled_font_lock_face (ft_unscaled_font_t *unscaled)
/* Unlock unscaled font locked with _ft_unscaled_font_lock_face
*/
-static void
-_ft_unscaled_font_unlock_face (ft_unscaled_font_t *unscaled)
+void
+_cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled)
{
assert (unscaled->lock > 0);
@@ -442,7 +485,7 @@ _ft_unscaled_font_unlock_face (ft_unscaled_font_t *unscaled)
}
static void
-_compute_transform (ft_font_transform_t *sf,
+_compute_transform (cairo_ft_font_transform_t *sf,
cairo_matrix_t *scale)
{
cairo_matrix_t normalized = *scale;
@@ -476,10 +519,10 @@ _compute_transform (ft_font_transform_t *sf,
* scaling to the same size, since changing a FT_Face is expensive.
*/
static void
-_ft_unscaled_font_set_scale (ft_unscaled_font_t *unscaled,
- cairo_matrix_t *scale)
+_cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
+ cairo_matrix_t *scale)
{
- ft_font_transform_t sf;
+ cairo_ft_font_transform_t sf;
FT_Matrix mat;
FT_UInt pixel_width, pixel_height;
FT_Error error;
@@ -528,7 +571,11 @@ _ft_unscaled_font_set_scale (ft_unscaled_font_t *unscaled,
pixel_width = pixel_height = 0;
for (i = 0; i < unscaled->face->num_fixed_sizes; i++) {
+#if HAVE_FT_BITMAP_SIZE_Y_PPEM
double size = unscaled->face->available_sizes[i].y_ppem / 64.;
+#else
+ double size = unscaled->face->available_sizes[i].height;
+#endif
double distance = fabs (size - sf.y_scale);
if (distance <= min_distance) {
@@ -536,11 +583,13 @@ _ft_unscaled_font_set_scale (ft_unscaled_font_t *unscaled,
best_i = i;
}
}
+#if HAVE_FT_BITMAP_SIZE_Y_PPEM
error = FT_Set_Char_Size (unscaled->face,
unscaled->face->available_sizes[best_i].x_ppem,
unscaled->face->available_sizes[best_i].y_ppem,
0, 0);
- if (error )
+ if (error)
+#endif
error = FT_Set_Pixel_Sizes (unscaled->face,
unscaled->face->available_sizes[best_i].width,
unscaled->face->available_sizes[best_i].height);
@@ -552,7 +601,7 @@ _ft_unscaled_font_set_scale (ft_unscaled_font_t *unscaled,
static void
_cairo_ft_unscaled_font_destroy (void *abstract_font)
{
- ft_unscaled_font_t *unscaled = abstract_font;
+ cairo_ft_unscaled_font_t *unscaled = abstract_font;
if (unscaled == NULL)
return;
@@ -990,7 +1039,7 @@ _render_glyph_bitmap (FT_Face face,
static cairo_status_t
_transform_glyph_bitmap (cairo_image_glyph_cache_entry_t *val)
{
- ft_font_transform_t sf;
+ cairo_ft_font_transform_t sf;
cairo_matrix_t original_to_transformed;
cairo_matrix_t transformed_to_original;
cairo_image_surface_t *old_image;
@@ -1110,21 +1159,21 @@ static cairo_status_t
_cairo_ft_unscaled_font_create_glyph (void *abstract_font,
cairo_image_glyph_cache_entry_t *val)
{
- ft_unscaled_font_t *unscaled = abstract_font;
+ cairo_ft_unscaled_font_t *unscaled = abstract_font;
FT_GlyphSlot glyphslot;
FT_Face face;
FT_Glyph_Metrics *metrics;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
double x_factor, y_factor;
- face = _ft_unscaled_font_lock_face (unscaled);
+ face = _cairo_ft_unscaled_font_lock_face (unscaled);
if (!face)
return CAIRO_STATUS_NO_MEMORY;
glyphslot = face->glyph;
metrics = &glyphslot->metrics;
- _ft_unscaled_font_set_scale (unscaled, &val->key.scale);
+ _cairo_ft_unscaled_font_set_scale (unscaled, &val->key.scale);
if (FT_Load_Glyph (face, val->key.index, val->key.flags & ~PRIVATE_FLAGS_MASK) != 0) {
status = CAIRO_STATUS_NO_MEMORY;
@@ -1203,7 +1252,7 @@ _cairo_ft_unscaled_font_create_glyph (void *abstract_
val->image = NULL;
}
- _ft_unscaled_font_unlock_face (unscaled);
+ _cairo_ft_unscaled_font_unlock_face (unscaled);
return status;
}
@@ -1215,11 +1264,10 @@ const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend = {
/* cairo_ft_scaled_font_t */
-typedef struct {
+typedef struct _cairo_ft_scaled_font {
cairo_scaled_font_t base;
int load_flags;
- cairo_font_options_t options;
- ft_unscaled_font_t *unscaled;
+ cairo_ft_unscaled_font_t *unscaled;
} cairo_ft_scaled_font_t;
const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend;
@@ -1370,31 +1418,31 @@ _get_options_load_flags (const cairo_font_options_t *options)
}
static cairo_scaled_font_t *
-_ft_scaled_font_create (ft_unscaled_font_t *unscaled,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm,
- const cairo_font_options_t *options,
- int load_flags)
+_cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ const cairo_font_options_t *options,
+ int load_flags)
{
- cairo_ft_scaled_font_t *f = NULL;
+ cairo_ft_scaled_font_t *scaled_font = NULL;
- f = malloc (sizeof(cairo_ft_scaled_font_t));
- if (f == NULL)
+ scaled_font = malloc (sizeof(cairo_ft_scaled_font_t));
+ if (scaled_font == NULL)
return NULL;
- f->unscaled = unscaled;
+ scaled_font->unscaled = unscaled;
_cairo_unscaled_font_reference (&unscaled->base);
- f->options = *options;
-
if (options->hint_metrics != CAIRO_HINT_METRICS_OFF)
load_flags |= PRIVATE_FLAG_HINT_METRICS;
- f->load_flags = load_flags;
+ scaled_font->load_flags = load_flags;
- _cairo_scaled_font_init (&f->base, font_matrix, ctm, &cairo_ft_scaled_font_backend);
+ _cairo_scaled_font_init (&scaled_font->base,
+ font_matrix, ctm, options,
+ &cairo_ft_scaled_font_backend);
- return (cairo_scaled_font_t *)f;
+ return (cairo_scaled_font_t*) scaled_font;
}
cairo_bool_t
@@ -1404,28 +1452,28 @@ _cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font)
}
static cairo_status_t
-_cairo_ft_scaled_font_create (const char *family,
- cairo_font_slant_t slant,
- cairo_font_weight_t weight,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm,
- const cairo_font_options_t *options,
- cairo_scaled_font_t **font)
+_cairo_ft_scaled_font_create_toy (const cairo_toy_font_face_t *toy_face,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ const cairo_font_options_t *options,
+ cairo_scaled_font_t **font)
{
FcPattern *pattern, *resolved;
- ft_unscaled_font_t *unscaled;
+ cairo_ft_unscaled_font_t *unscaled;
cairo_scaled_font_t *new_font;
FcResult result;
int fcslant;
int fcweight;
cairo_matrix_t scale;
- ft_font_transform_t sf;
+ cairo_ft_font_transform_t sf;
+ int load_flags;
+ unsigned char *family = (unsigned char*) toy_face->family;
pattern = FcPatternCreate ();
if (!pattern)
return CAIRO_STATUS_NO_MEMORY;
- switch (weight)
+ switch (toy_face->weight)
{
case CAIRO_FONT_WEIGHT_BOLD:
fcweight = FC_WEIGHT_BOLD;
@@ -1436,7 +1484,7 @@ _cairo_ft_scaled_font_create (const char *family,
break;
}
- switch (slant)
+ switch (toy_face->slant)
{
case CAIRO_FONT_SLANT_ITALIC:
fcslant = FC_SLANT_ITALIC;
@@ -1450,7 +1498,7 @@ _cairo_ft_scaled_font_create (const char *family,
break;
}
- if (!FcPatternAddString (pattern, FC_FAMILY, (unsigned char *) family))
+ if (!FcPatternAddString (pattern, FC_FAMILY, family))
goto FREE_PATTERN;
if (!FcPatternAddInteger (pattern, FC_SLANT, fcslant))
goto FREE_PATTERN;
@@ -1470,13 +1518,15 @@ _cairo_ft_scaled_font_create (const char *family,
if (!resolved)
goto FREE_PATTERN;
- unscaled = _ft_unscaled_font_get_for_pattern (resolved);
+ unscaled = _cairo_ft_unscaled_font_get_for_pattern (resolved);
if (!unscaled)
goto FREE_RESOLVED;
-
- new_font = _ft_scaled_font_create (unscaled,
- font_matrix, ctm,
- options, _get_pattern_load_flags (pattern));
+
+ load_flags = _get_pattern_load_flags (pattern);
+ new_font = _cairo_ft_scaled_font_create (unscaled,
+ font_matrix, ctm,
+ options, load_flags);
+
_cairo_unscaled_font_destroy (&unscaled->base);
FcPatternDestroy (resolved);
@@ -1499,7 +1549,7 @@ _cairo_ft_scaled_font_create (const char *family,
}
static void
-_cairo_ft_scaled_font_destroy (void *abstract_font)
+_cairo_ft_scaled_font_fini (void *abstract_font)
{
cairo_ft_scaled_font_t *scaled_font = abstract_font;
@@ -1599,19 +1649,20 @@ _cairo_ft_scaled_font_font_extents (void *abstract_font,
FT_Face face;
FT_Size_Metrics *metrics;
- face = _ft_unscaled_font_lock_face (scaled_font->unscaled);
+ face = _cairo_ft_unscaled_font_lock_face (scaled_font->unscaled);
if (!face)
return CAIRO_STATUS_NO_MEMORY;
metrics = &face->size->metrics;
- _ft_unscaled_font_set_scale (scaled_font->unscaled, &scaled_font->base.scale);
+ _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
+ &scaled_font->base.scale);
/*
* Get to unscaled metrics so that the upper level can get back to
* user space
*/
- if (scaled_font->options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
+ if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
double x_factor, y_factor;
if (scaled_font->unscaled->x_scale == 0)
@@ -1640,7 +1691,7 @@ _cairo_ft_scaled_font_font_extents (void *abstract_font,
/* FIXME: this doesn't do vertical layout atm. */
extents->max_y_advance = 0.0;
- _ft_unscaled_font_unlock_face (scaled_font->unscaled);
+ _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
return CAIRO_STATUS_SUCCESS;
}
@@ -1697,7 +1748,7 @@ _cairo_ft_scaled_font_glyph_extents (void *abstract_font,
/* XXX: Need to add code here to check the font's FcPattern
for FC_VERTICAL_LAYOUT and if set get vertBearingX/Y
instead. This will require that
- cairo_ft_scaled_font_create_for_ft_face accept an
+ cairo_ft_font_face_create_for_ft_face accept an
FcPattern. */
glyph_min.x = glyphs[i].x + img->extents.x_bearing;
glyph_min.y = glyphs[i].y + img->extents.y_bearing;
@@ -1793,6 +1844,26 @@ _cairo_ft_scaled_font_glyph_bbox (void *abstract_font,
return CAIRO_STATUS_SUCCESS;
}
+static cairo_format_t
+_select_text_mask_format (cairo_bool_t have_a1_glyphs,
+ cairo_bool_t have_a8_glyphs,
+ cairo_bool_t have_argb32_glyphs)
+{
+ if (have_a8_glyphs)
+ return CAIRO_FORMAT_A8;
+
+ if (have_a1_glyphs && have_argb32_glyphs)
+ return CAIRO_FORMAT_A8;
+
+ if (have_a1_glyphs)
+ return CAIRO_FORMAT_A1;
+
+ if (have_argb32_glyphs)
+ return CAIRO_FORMAT_ARGB32;
+
+ /* when there are no glyphs to draw, just pick something */
+ return CAIRO_FORMAT_A8;
+}
static cairo_status_t
_cairo_ft_scaled_font_show_glyphs (void *abstract_font,
@@ -1808,12 +1879,16 @@ _cairo_ft_scaled_font_show_glyphs (void *abstract_font,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
- cairo_image_glyph_cache_entry_t *img;
+ cairo_image_glyph_cache_entry_t **entries;
cairo_cache_t *cache;
cairo_glyph_cache_key_t key;
cairo_ft_scaled_font_t *scaled_font = abstract_font;
cairo_surface_pattern_t glyph_pattern;
- cairo_status_t status;
+ cairo_surface_t *mask;
+ cairo_surface_pattern_t mask_pattern;
+ cairo_format_t mask_format = CAIRO_FORMAT_A1;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_bool_t have_a1_glyphs, have_a8_glyphs, have_argb32_glyphs;
int x, y;
int i;
@@ -1833,44 +1908,98 @@ _cairo_ft_scaled_font_show_glyphs (void *abstract_font,
key.scale = scaled_font->base.scale;
key.flags = scaled_font->load_flags;
+ entries = malloc (num_glyphs * sizeof (cairo_image_glyph_cache_entry_t));
+ if (!entries)
+ goto CLEANUP_CACHE;
+
+ have_a1_glyphs = FALSE;
+ have_a8_glyphs = FALSE;
+ have_argb32_glyphs = FALSE;
+
for (i = 0; i < num_glyphs; i++)
{
- img = NULL;
+ entries[i] = NULL;
key.index = glyphs[i].index;
- if (_cairo_cache_lookup (cache, &key, (void **) &img, NULL)
- != CAIRO_STATUS_SUCCESS
- || img == NULL
- || img->image == NULL)
+ if (_cairo_cache_lookup (cache, &key, (void **) &entries[i], NULL) != CAIRO_STATUS_SUCCESS)
+ continue;
+
+ switch (entries[i]->image->format) {
+ case CAIRO_FORMAT_A1:
+ have_a1_glyphs = TRUE;
+ break;
+ case CAIRO_FORMAT_A8:
+ have_a8_glyphs = TRUE;
+ break;
+ case CAIRO_FORMAT_ARGB32:
+ have_argb32_glyphs = TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ mask_format = _select_text_mask_format (have_a1_glyphs, have_a8_glyphs, have_argb32_glyphs);
+
+ mask = cairo_image_surface_create (mask_format, width, height);
+ if (!mask)
+ goto CLEANUP_ENTRIES;
+
+ status = _cairo_surface_fill_rectangle (mask, CAIRO_OPERATOR_SOURCE,
+ CAIRO_COLOR_TRANSPARENT,
+ 0, 0, width, height);
+ if (status)
+ goto CLEANUP_MASK;
+
+ for (i = 0; i < num_glyphs; i++)
+ {
+ if (entries[i] == NULL
+ || entries[i]->image == NULL)
continue;
x = (int) floor (glyphs[i].x + 0.5);
y = (int) floor (glyphs[i].y + 0.5);
- _cairo_pattern_init_for_surface (&glyph_pattern, &(img->image->base));
+ _cairo_pattern_init_for_surface (&glyph_pattern, &(entries[i]->image->base));
- status = _cairo_surface_composite (operator, pattern,
+ status = _cairo_surface_composite (CAIRO_OPERATOR_ADD, pattern,
&glyph_pattern.base,
- surface,
- x + img->size.x,
- y + img->size.y,
+ mask,
+ x + entries[i]->size.x,
+ y + entries[i]->size.y,
0, 0,
- x + img->size.x,
- y + img->size.y,
- (double) img->size.width,
- (double) img->size.height);
+ x + entries[i]->size.x - dest_x,
+ y + entries[i]->size.y - dest_y,
+ entries[i]->size.width,
+ entries[i]->size.height);
_cairo_pattern_fini (&glyph_pattern.base);
- if (status) {
- _cairo_unlock_global_image_glyph_cache ();
- return status;
- }
- }
+ if (status)
+ goto CLEANUP_MASK;
+ }
+
+ _cairo_pattern_init_for_surface (&mask_pattern, mask);
+
+ status = _cairo_surface_composite (operator, pattern, &mask_pattern.base,
+ surface,
+ source_x, source_y,
+ 0, 0,
+ dest_x, dest_y,
+ width, height);
+
+ _cairo_pattern_fini (&mask_pattern.base);
+
+ CLEANUP_MASK:
+ cairo_surface_destroy (mask);
+
+ CLEANUP_ENTRIES:
+ free (entries);
+ CLEANUP_CACHE:
_cairo_unlock_global_image_glyph_cache ();
- return CAIRO_STATUS_SUCCESS;
+ return status;
}
@@ -2018,26 +2147,26 @@ _cairo_ft_scaled_font_glyph_path (void *abstract_font,
}
const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = {
- _cairo_ft_scaled_font_create,
- _cairo_ft_scaled_font_destroy,
+ _cairo_ft_scaled_font_create_toy,
+ _cairo_ft_scaled_font_fini,
_cairo_ft_scaled_font_font_extents,
_cairo_ft_scaled_font_text_to_glyphs,
_cairo_ft_scaled_font_glyph_extents,
_cairo_ft_scaled_font_glyph_bbox,
_cairo_ft_scaled_font_show_glyphs,
_cairo_ft_scaled_font_glyph_path,
- _cairo_ft_scaled_font_get_glyph_cache_key,
+ _cairo_ft_scaled_font_get_glyph_cache_key
};
/* ft_font_face_t */
static void
-_ft_font_face_destroy (void *abstract_face)
+_cairo_ft_font_face_destroy (void *abstract_face)
{
- ft_font_face_t *font_face = abstract_face;
+ cairo_ft_font_face_t *font_face = abstract_face;
- ft_font_face_t *tmp_face = NULL;
- ft_font_face_t *last_face = NULL;
+ cairo_ft_font_face_t *tmp_face = NULL;
+ cairo_ft_font_face_t *last_face = NULL;
if (font_face == NULL)
return;
@@ -2069,12 +2198,15 @@ _ft_font_face_destroy (void *abstract_face)
if (font_face->unscaled) {
/* Remove face from linked list */
- for (tmp_face = font_face->unscaled->faces; tmp_face; tmp_face = tmp_face->next_face) {
+ for (tmp_face = font_face->unscaled->faces;
+ tmp_face;
+ tmp_face = tmp_face->next)
+ {
if (tmp_face == font_face) {
if (last_face)
- last_face->next_face = tmp_face->next_face;
+ last_face->next = tmp_face->next;
else
- font_face->unscaled->faces = tmp_face->next_face;
+ font_face->unscaled->faces = tmp_face->next;
}
last_face = tmp_face;
@@ -2086,13 +2218,13 @@ _ft_font_face_destroy (void *abstract_face)
}
static cairo_status_t
-_ft_font_face_create_font (void *abstract_face,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm,
- const cairo_font_options_t *options,
- cairo_scaled_font_t **scaled_font)
+_cairo_ft_font_face_scaled_font_create (void *abstract_face,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ const cairo_font_options_t *options,
+ cairo_scaled_font_t **scaled_font)
{
- ft_font_face_t *font_face = abstract_face;
+ cairo_ft_font_face_t *font_face = abstract_face;
int load_flags;
/* The handling of font options is different depending on how the
@@ -2109,36 +2241,37 @@ _ft_font_face_create_font (void *abstract_face,
else
load_flags = font_face->load_flags;
- *scaled_font = _ft_scaled_font_create (font_face->unscaled,
- font_matrix, ctm,
- options, load_flags);
+ *scaled_font = _cairo_ft_scaled_font_create (font_face->unscaled,
+ font_matrix, ctm,
+ options, load_flags);
if (*scaled_font)
return CAIRO_STATUS_SUCCESS;
else
return CAIRO_STATUS_NO_MEMORY;
}
-static const cairo_font_face_backend_t _ft_font_face_backend = {
- _ft_font_face_destroy,
- _ft_font_face_create_font,
+static const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
+ _cairo_ft_font_face_destroy,
+ _cairo_ft_font_face_scaled_font_create
};
static cairo_font_face_t *
-_ft_font_face_create (ft_unscaled_font_t *unscaled,
- int load_flags)
+_cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
+ int load_flags)
{
- ft_font_face_t *font_face;
+ cairo_ft_font_face_t *font_face;
/* Looked for an existing matching font face */
- for (font_face = unscaled->faces; font_face; font_face = font_face->next_face) {
- if (font_face->load_flags == load_flags) {
- cairo_font_face_reference (&font_face->base);
- return &font_face->base;
- }
+ for (font_face = unscaled->faces;
+ font_face;
+ font_face = font_face->next)
+ {
+ if (font_face->load_flags == load_flags)
+ return cairo_font_face_reference (&font_face->base);
}
/* No match found, create a new one */
- font_face = malloc (sizeof (ft_font_face_t));
+ font_face = malloc (sizeof (cairo_ft_font_face_t));
if (!font_face)
return NULL;
@@ -2147,10 +2280,10 @@ _ft_font_face_create (ft_unscaled_font_t *unscaled,
font_face->load_flags = load_flags;
- font_face->next_face = unscaled->faces;
+ font_face->next = unscaled->faces;
unscaled->faces = font_face;
- _cairo_font_face_init (&font_face->base, &_ft_font_face_backend);
+ _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
return &font_face->base;
}
@@ -2272,16 +2405,17 @@ cairo_ft_font_options_substitute (const cairo_font_options_t *options,
cairo_font_face_t *
cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
{
- ft_unscaled_font_t *unscaled;
+ cairo_ft_unscaled_font_t *unscaled;
cairo_font_face_t *font_face;
- unscaled = _ft_unscaled_font_get_for_pattern (pattern);
+ unscaled = _cairo_ft_unscaled_font_get_for_pattern (pattern);
if (unscaled == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_font_face_t *)&_cairo_font_face_nil;
}
- font_face = _ft_font_face_create (unscaled, _get_pattern_load_flags (pattern));
+ font_face = _cairo_ft_font_face_create (unscaled,
+ _get_pattern_load_flags (pattern));
_cairo_unscaled_font_destroy (&unscaled->base);
if (font_face)
@@ -2321,16 +2455,16 @@ cairo_font_face_t *
cairo_ft_font_face_create_for_ft_face (FT_Face face,
int load_flags)
{
- ft_unscaled_font_t *unscaled;
+ cairo_ft_unscaled_font_t *unscaled;
cairo_font_face_t *font_face;
- unscaled = _ft_unscaled_font_create_from_face (face);
+ unscaled = _cairo_ft_unscaled_font_create_from_face (face);
if (unscaled == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_font_face_t *)&_cairo_font_face_nil;
}
- font_face = _ft_font_face_create (unscaled, load_flags);
+ font_face = _cairo_ft_font_face_create (unscaled, load_flags);
_cairo_unscaled_font_destroy (&unscaled->base);
if (font_face) {
@@ -2379,13 +2513,13 @@ cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
if (scaled_font->base.status)
return NULL;
- face = _ft_unscaled_font_lock_face (scaled_font->unscaled);
+ face = _cairo_ft_unscaled_font_lock_face (scaled_font->unscaled);
if (face == NULL) {
_cairo_scaled_font_set_error (&scaled_font->base, CAIRO_STATUS_NO_MEMORY);
return NULL;
}
- _ft_unscaled_font_set_scale (scaled_font->unscaled, &scaled_font->base.scale);
+ _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled, &scaled_font->base.scale);
return face;
}
@@ -2408,7 +2542,7 @@ cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font)
if (scaled_font->base.status)
return;
- _ft_unscaled_font_unlock_face (scaled_font->unscaled);
+ _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
}
/* We expose our unscaled font implementation internally for the the
@@ -2423,17 +2557,15 @@ _cairo_ft_scaled_font_get_unscaled_font (cairo_scaled_font_t *abstract_font)
return &scaled_font->unscaled->base;
}
-/* This differs from _cairo_ft_scaled_font_lock_face in that it doesn't
- * set the scale on the face, but just returns it at the last scale.
- */
-FT_Face
-_cairo_ft_unscaled_font_lock_face (cairo_unscaled_font_t *unscaled_font)
-{
- return _ft_unscaled_font_lock_face ((ft_unscaled_font_t *)unscaled_font);
-}
-
void
-_cairo_ft_unscaled_font_unlock_face (cairo_unscaled_font_t *unscaled_font)
+_cairo_ft_font_reset_static_data (void)
{
- _ft_unscaled_font_unlock_face ((ft_unscaled_font_t *)unscaled_font);
+ _lock_global_ft_cache ();
+ if (_global_ft_cache) {
+ FT_Done_FreeType (_global_ft_cache->lib);
+ _global_ft_cache->lib = NULL;
+ }
+ _cairo_cache_destroy (&_global_ft_cache->base);
+ _global_ft_cache = NULL;
+ _unlock_global_ft_cache ();
}
diff --git a/src/cairo-ft-private.h b/src/cairo-ft-private.h
index e92048b2..8bd43413 100644
--- a/src/cairo-ft-private.h
+++ b/src/cairo-ft-private.h
@@ -44,6 +44,8 @@
CAIRO_BEGIN_DECLS
+typedef struct _cairo_ft_unscaled_font cairo_ft_unscaled_font_t;
+
cairo_bool_t
_cairo_unscaled_font_is_ft (cairo_unscaled_font_t *unscaled_font);
@@ -57,10 +59,10 @@ cairo_private cairo_unscaled_font_t *
_cairo_ft_scaled_font_get_unscaled_font (cairo_scaled_font_t *scaled_font);
cairo_private FT_Face
-_cairo_ft_unscaled_font_lock_face (cairo_unscaled_font_t *unscaled_font);
+_cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled);
cairo_private void
-_cairo_ft_unscaled_font_unlock_face (cairo_unscaled_font_t *unscaled_font);
+_cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled);
CAIRO_END_DECLS
diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c
index 96e92033..7e0f3387 100644
--- a/src/cairo-glitz-surface.c
+++ b/src/cairo-glitz-surface.c
@@ -349,8 +349,7 @@ _cairo_glitz_surface_clone_similar (void *abstract_surface,
if (src->backend == surface->base.backend)
{
- *clone_out = src;
- cairo_surface_reference (src);
+ *clone_out = cairo_surface_reference (src);
return CAIRO_STATUS_SUCCESS;
}
@@ -937,6 +936,7 @@ static cairo_int_status_t
_cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
cairo_pattern_t *pattern,
void *abstract_dst,
+ cairo_antialias_t antialias,
int src_x,
int src_y,
int dst_x,
diff --git a/src/cairo-gstate-private.h b/src/cairo-gstate-private.h
index 0d4d499f..489afdba 100644
--- a/src/cairo-gstate-private.h
+++ b/src/cairo-gstate-private.h
@@ -36,51 +36,13 @@
#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;
+#include "cairo-clip-private.h"
struct _cairo_gstate {
cairo_operator_t operator;
double tolerance;
+ cairo_antialias_t antialias;
/* stroke style */
double line_width;
@@ -103,6 +65,7 @@ struct _cairo_gstate {
cairo_matrix_t ctm;
cairo_matrix_t ctm_inverse;
+ cairo_matrix_t source_ctm_inverse; /* At the time ->source was set */
cairo_pen_t pen_regular;
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index ed3359b9..a657f15e 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -39,6 +39,7 @@
#include "cairoint.h"
+#include "cairo-clip-private.h"
#include "cairo-gstate-private.h"
static cairo_status_t
@@ -53,28 +54,16 @@ _cairo_gstate_fini (cairo_gstate_t *gstate);
static cairo_status_t
_cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
- cairo_pattern_t *src,
- cairo_operator_t operator,
- cairo_surface_t *dst,
- cairo_traps_t *traps);
-
-static cairo_status_t
-_cairo_gstate_ensure_font (cairo_gstate_t *gstate);
+ cairo_traps_t *traps);
static cairo_status_t
_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 cairo_status_t
+_cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate);
static void
-_cairo_clip_path_destroy (cairo_clip_path_t *clip_path);
+_cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate);
cairo_gstate_t *
_cairo_gstate_create (cairo_surface_t *target)
@@ -103,6 +92,7 @@ _cairo_gstate_init (cairo_gstate_t *gstate,
gstate->operator = CAIRO_GSTATE_OPERATOR_DEFAULT;
gstate->tolerance = CAIRO_GSTATE_TOLERANCE_DEFAULT;
+ gstate->antialias = CAIRO_ANTIALIAS_DEFAULT;
gstate->line_width = CAIRO_GSTATE_LINE_WIDTH_DEFAULT;
gstate->line_cap = CAIRO_GSTATE_LINE_CAP_DEFAULT;
@@ -124,18 +114,14 @@ _cairo_gstate_init (cairo_gstate_t *gstate,
_cairo_font_options_init_default (&gstate->font_options);
- gstate->clip.mode = _cairo_surface_get_clip_mode (target);
- gstate->clip.region = NULL;
- gstate->clip.surface = NULL;
- gstate->clip.serial = 0;
- gstate->clip.path = NULL;
+ _cairo_clip_init (&gstate->clip, target);
_cairo_gstate_identity_matrix (gstate);
+ cairo_matrix_init_identity (&gstate->source_ctm_inverse);
_cairo_pen_init_empty (&gstate->pen_regular);
- gstate->target = target;
- cairo_surface_reference (gstate->target);
+ gstate->target = cairo_surface_reference (target);
gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
if (gstate->source->status)
@@ -165,10 +151,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) {
- gstate->clip.region = pixman_region_create ();
- pixman_region_copy (gstate->clip.region, other->clip.region);
- }
+ _cairo_clip_init_copy (&gstate->clip, &other->clip);
if (gstate->font_face)
cairo_font_face_reference (gstate->font_face);
@@ -177,8 +160,6 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
cairo_scaled_font_reference (gstate->scaled_font);
cairo_surface_reference (gstate->target);
- cairo_surface_reference (gstate->clip.surface);
- _cairo_clip_path_reference (gstate->clip.path);
cairo_pattern_reference (gstate->source);
@@ -212,18 +193,7 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
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_clip_fini (&gstate->clip);
cairo_pattern_destroy (gstate->source);
@@ -343,61 +313,6 @@ _cairo_gstate_end_group (cairo_gstate_t *gstate)
}
*/
-static cairo_status_t
-_cairo_gstate_set_clip (cairo_gstate_t *gstate)
-{
- cairo_surface_t *surface = gstate->target;
-
- if (!surface)
- return CAIRO_STATUS_NULL_POINTER;
- if (gstate->clip.serial == _cairo_surface_get_current_clip_serial (surface))
- return CAIRO_STATUS_SUCCESS;
-
- 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);
-}
-
-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);
- }
-
- if (gstate->clip.surface)
- _cairo_rectangle_intersect (rectangle, &gstate->clip.surface_rect);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
cairo_surface_t *
_cairo_gstate_get_target (cairo_gstate_t *gstate)
{
@@ -414,6 +329,7 @@ _cairo_gstate_set_source (cairo_gstate_t *gstate,
cairo_pattern_reference (source);
cairo_pattern_destroy (gstate->source);
gstate->source = source;
+ gstate->source_ctm_inverse = gstate->ctm_inverse;
return CAIRO_STATUS_SUCCESS;
}
@@ -559,7 +475,7 @@ _cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty)
{
cairo_matrix_t tmp;
- _cairo_gstate_unset_font (gstate);
+ _cairo_gstate_unset_scaled_font (gstate);
cairo_matrix_init_translate (&tmp, tx, ty);
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
@@ -578,7 +494,7 @@ _cairo_gstate_scale (cairo_gstate_t *gstate, double sx, double sy)
if (sx == 0 || sy == 0)
return CAIRO_STATUS_INVALID_MATRIX;
- _cairo_gstate_unset_font (gstate);
+ _cairo_gstate_unset_scaled_font (gstate);
cairo_matrix_init_scale (&tmp, sx, sy);
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
@@ -594,7 +510,7 @@ _cairo_gstate_rotate (cairo_gstate_t *gstate, double angle)
{
cairo_matrix_t tmp;
- _cairo_gstate_unset_font (gstate);
+ _cairo_gstate_unset_scaled_font (gstate);
cairo_matrix_init_rotate (&tmp, angle);
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
@@ -611,7 +527,7 @@ _cairo_gstate_transform (cairo_gstate_t *gstate,
{
cairo_matrix_t tmp;
- _cairo_gstate_unset_font (gstate);
+ _cairo_gstate_unset_scaled_font (gstate);
tmp = *matrix;
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
@@ -628,7 +544,7 @@ _cairo_gstate_set_matrix (cairo_gstate_t *gstate,
{
cairo_status_t status;
- _cairo_gstate_unset_font (gstate);
+ _cairo_gstate_unset_scaled_font (gstate);
gstate->ctm = *matrix;
@@ -643,7 +559,7 @@ _cairo_gstate_set_matrix (cairo_gstate_t *gstate,
cairo_status_t
_cairo_gstate_identity_matrix (cairo_gstate_t *gstate)
{
- _cairo_gstate_unset_font (gstate);
+ _cairo_gstate_unset_scaled_font (gstate);
cairo_matrix_init_identity (&gstate->ctm);
cairo_matrix_init_identity (&gstate->ctm_inverse);
@@ -717,11 +633,15 @@ _cairo_gstate_stroke_to_path (cairo_gstate_t *gstate)
*/
static void
-_cairo_gstate_pattern_transform (cairo_gstate_t *gstate,
- cairo_pattern_t *pattern)
+_cairo_gstate_copy_transformed_pattern (cairo_gstate_t *gstate,
+ cairo_pattern_t *pattern,
+ cairo_pattern_t *original,
+ cairo_matrix_t *ctm_inverse)
{
- cairo_matrix_t tmp_matrix = gstate->ctm_inverse;
-
+ cairo_matrix_t tmp_matrix = *ctm_inverse;
+
+ _cairo_pattern_init_copy (pattern, original);
+
if (gstate->target)
cairo_matrix_translate (&tmp_matrix,
- gstate->target->device_x_offset,
@@ -730,6 +650,25 @@ _cairo_gstate_pattern_transform (cairo_gstate_t *gstate,
_cairo_pattern_transform (pattern, &tmp_matrix);
}
+static void
+_cairo_gstate_copy_transformed_source (cairo_gstate_t *gstate,
+ cairo_pattern_t *pattern)
+{
+ _cairo_gstate_copy_transformed_pattern (gstate, pattern,
+ gstate->source,
+ &gstate->source_ctm_inverse);
+}
+
+static void
+_cairo_gstate_copy_transformed_mask (cairo_gstate_t *gstate,
+ cairo_pattern_t *pattern,
+ cairo_pattern_t *mask)
+{
+ _cairo_gstate_copy_transformed_pattern (gstate, pattern,
+ mask,
+ &gstate->ctm_inverse);
+}
+
cairo_status_t
_cairo_gstate_paint (cairo_gstate_t *gstate)
{
@@ -741,11 +680,14 @@ _cairo_gstate_paint (cairo_gstate_t *gstate)
if (gstate->source->status)
return gstate->source->status;
- status = _cairo_gstate_set_clip (gstate);
+ status = _cairo_surface_set_clip (gstate->target, &gstate->clip);
if (status)
return status;
- status = _cairo_gstate_get_clip_extents (gstate, &rectangle);
+ status = _cairo_surface_get_extents (gstate->target, &rectangle);
+ if (status)
+ return status;
+ status = _cairo_clip_intersect_to_rectangle (&gstate->clip, &rectangle);
if (status)
return status;
@@ -757,119 +699,310 @@ _cairo_gstate_paint (cairo_gstate_t *gstate)
if (status)
return status;
- _cairo_gstate_clip_and_composite_trapezoids (gstate,
- gstate->source,
- gstate->operator,
- gstate->target,
- &traps);
+ _cairo_gstate_clip_and_composite_trapezoids (gstate, &traps);
_cairo_traps_fini (&traps);
return CAIRO_STATUS_SUCCESS;
}
-/* Combines @gstate->clip_surface using the IN operator with
- * the given intermediate surface, which corresponds to the
- * rectangle of the destination space given by @extents.
+/**
+ * _cairo_operator_bounded:
+ * @operator: a #cairo_operator_t
+ *
+ * A bounded operator is one where a source or mask pixel
+ * of zero results in no effect on the destination image.
+ *
+ * Unbounded operators often require special handling; if you, for
+ * example, draw trapezoids with an unbounded operator, the effect
+ * extends past the bounding box of the trapezoids.
+ *
+ * Return value: %TRUE if the operator is bounded
+ **/
+cairo_bool_t
+_cairo_operator_bounded (cairo_operator_t operator)
+{
+ switch (operator) {
+ case CAIRO_OPERATOR_OVER:
+ case CAIRO_OPERATOR_ATOP:
+ case CAIRO_OPERATOR_DEST:
+ case CAIRO_OPERATOR_DEST_OVER:
+ case CAIRO_OPERATOR_DEST_OUT:
+ case CAIRO_OPERATOR_XOR:
+ case CAIRO_OPERATOR_ADD:
+ case CAIRO_OPERATOR_SATURATE:
+ return TRUE;
+ case CAIRO_OPERATOR_CLEAR:
+ case CAIRO_OPERATOR_SOURCE:
+ case CAIRO_OPERATOR_OUT:
+ case CAIRO_OPERATOR_IN:
+ case CAIRO_OPERATOR_DEST_IN:
+ case CAIRO_OPERATOR_DEST_ATOP:
+ return FALSE;
+ }
+
+ ASSERT_NOT_REACHED;
+ return FALSE;
+}
+
+typedef cairo_status_t (*cairo_draw_func_t) (void *closure,
+ cairo_operator_t operator,
+ cairo_pattern_t *src,
+ cairo_surface_t *dst,
+ int dst_x,
+ int dst_y,
+ const cairo_rectangle_t *extents);
+
+/* Handles compositing with a clip surface when the operator allows
+ * us to combine the clip with the mask
*/
static cairo_status_t
-_cairo_gstate_combine_clip_surface (cairo_gstate_t *gstate,
- cairo_surface_t *intermediate,
- cairo_rectangle_t *extents)
+_cairo_gstate_clip_and_composite_with_mask (cairo_clip_t *clip,
+ cairo_operator_t operator,
+ cairo_pattern_t *src,
+ cairo_draw_func_t draw_func,
+ void *draw_closure,
+ cairo_surface_t *dst,
+ const cairo_rectangle_t *extents)
{
- cairo_pattern_union_t pattern;
+ cairo_surface_t *intermediate;
+ cairo_surface_pattern_t intermediate_pattern;
cairo_status_t status;
- _cairo_pattern_init_for_surface (&pattern.surface,
- gstate->clip.surface);
+ intermediate = cairo_surface_create_similar (clip->surface,
+ CAIRO_CONTENT_ALPHA,
+ extents->width,
+ extents->height);
+ if (intermediate->status)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ status = (*draw_func) (draw_closure, CAIRO_OPERATOR_SOURCE,
+ NULL, intermediate,
+ extents->x, extents->y,
+ extents);
+ if (status)
+ goto CLEANUP_SURFACE;
- status = _cairo_surface_composite (CAIRO_OPERATOR_IN,
- &pattern.base,
- NULL,
- intermediate,
- extents->x - gstate->clip.surface_rect.x,
- extents->y - gstate->clip.surface_rect.y,
- 0, 0,
- 0, 0,
- extents->width, extents->height);
+ status = _cairo_clip_combine_to_surface (clip, CAIRO_OPERATOR_IN,
+ intermediate,
+ extents->x, extents->y,
+ extents);
+ if (status)
+ goto CLEANUP_SURFACE;
- _cairo_pattern_fini (&pattern.base);
+ _cairo_pattern_init_for_surface (&intermediate_pattern, intermediate);
+
+ status = _cairo_surface_composite (operator,
+ src, &intermediate_pattern.base, dst,
+ extents->x, extents->y,
+ 0, 0,
+ extents->x, extents->y,
+ extents->width, extents->height);
+
+ _cairo_pattern_fini (&intermediate_pattern.base);
+
+ CLEANUP_SURFACE:
+ cairo_surface_destroy (intermediate);
return status;
}
-/* Creates a region from a cairo_rectangle_t */
+/* Handles compositing with a clip surface when the operator allows
+ * us to combine the clip with the mask
+ */
static cairo_status_t
-_region_new_from_rect (cairo_rectangle_t *rect,
- pixman_region16_t **region)
-{
- *region = pixman_region_create ();
- if (pixman_region_union_rect (*region, *region,
- rect->x, rect->y,
- rect->width, rect->height) != PIXMAN_REGION_STATUS_SUCCESS) {
- pixman_region_destroy (*region);
+_cairo_gstate_clip_and_composite_combine (cairo_clip_t *clip,
+ cairo_operator_t operator,
+ cairo_pattern_t *src,
+ cairo_draw_func_t draw_func,
+ void *draw_closure,
+ cairo_surface_t *dst,
+ const cairo_rectangle_t *extents)
+{
+ cairo_surface_t *intermediate;
+ cairo_surface_pattern_t dst_pattern;
+ cairo_surface_pattern_t intermediate_pattern;
+ cairo_status_t status;
+
+ /* We'd be better off here creating a surface identical in format
+ * to dst, but we have no way of getting that information.
+ * A CAIRO_CONTENT_CLONE or something might be useful.
+ */
+ intermediate = cairo_surface_create_similar (dst,
+ CAIRO_CONTENT_COLOR_ALPHA,
+ extents->width,
+ extents->height);
+ if (intermediate->status)
return CAIRO_STATUS_NO_MEMORY;
- }
- return CAIRO_STATUS_SUCCESS;
-}
+ /* Initialize the intermediate surface from the destination surface
+ */
+ _cairo_pattern_init_for_surface (&dst_pattern, dst);
-/* Gets the bounding box of a region as a cairo_rectangle_t */
-static void
-_region_rect_extents (pixman_region16_t *region,
- cairo_rectangle_t *rect)
-{
- pixman_box16_t *region_extents = pixman_region_extents (region);
+ status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
+ &dst_pattern.base, NULL, intermediate,
+ extents->x, extents->y,
+ 0, 0,
+ 0, 0,
+ extents->width, extents->height);
- rect->x = region_extents->x1;
- rect->y = region_extents->y1;
- rect->width = region_extents->x2 - region_extents->x1;
- rect->height = region_extents->y2 - region_extents->y1;
-}
+ _cairo_pattern_fini (&dst_pattern.base);
-/* Intersects @region with the clipping bounds (both region
- * and surface) of @gstate
- */
-static cairo_status_t
-_cairo_gstate_intersect_clip (cairo_gstate_t *gstate,
- pixman_region16_t *region)
-{
- if (gstate->clip.region)
- pixman_region_intersect (region, gstate->clip.region, region);
+ if (status)
+ goto CLEANUP_SURFACE;
+
+ status = (*draw_func) (draw_closure, operator,
+ src, intermediate,
+ extents->x, extents->y,
+ extents);
+ if (status)
+ goto CLEANUP_SURFACE;
+
+ /* Combine that with the clip
+ */
+ status = _cairo_clip_combine_to_surface (clip, CAIRO_OPERATOR_DEST_IN,
+ intermediate,
+ extents->x, extents->y,
+ extents);
+ if (status)
+ goto CLEANUP_SURFACE;
+
+ /* Punch the clip out of the destination
+ */
+ status = _cairo_clip_combine_to_surface (clip, CAIRO_OPERATOR_DEST_OUT,
+ dst,
+ 0, 0,
+ extents);
+ if (status)
+ goto CLEANUP_SURFACE;
- if (gstate->clip.surface) {
- pixman_region16_t *clip_rect;
- cairo_status_t status;
+ /* Now add the two results together
+ */
+ _cairo_pattern_init_for_surface (&intermediate_pattern, intermediate);
- status = _region_new_from_rect (&gstate->clip.surface_rect, &clip_rect);
- if (status)
- return status;
-
- if (pixman_region_intersect (region,
- clip_rect,
- region) != PIXMAN_REGION_STATUS_SUCCESS)
- status = CAIRO_STATUS_NO_MEMORY;
+ status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
+ &intermediate_pattern.base, NULL, dst,
+ 0, 0,
+ 0, 0,
+ extents->x, extents->y,
+ extents->width, extents->height);
- pixman_region_destroy (clip_rect);
+ _cairo_pattern_fini (&intermediate_pattern.base);
+
+ CLEANUP_SURFACE:
+ cairo_surface_destroy (intermediate);
- if (status)
- return status;
- }
+ return status;
+}
- return CAIRO_STATUS_SUCCESS;
+static int
+_cairo_rectangle_empty (const cairo_rectangle_t *rect)
+{
+ return rect->width == 0 || rect->height == 0;
}
+/**
+ * _cairo_gstate_clip_and_composite:
+ * @gstate: a #cairo_gstate_t
+ * @operator: the operator to draw with
+ * @src: source pattern
+ * @draw_func: function that can be called to draw with the mask onto a surface.
+ * @draw_closure: data to pass to @draw_func.
+ * @dst: destination surface
+ * @extents: rectangle holding a bounding box for the operation; this
+ * rectangle will be used as the size for the temporary
+ * surface.
+ *
+ * When there is a surface clip, we typically need to create an intermediate
+ * surface. This function handles the logic of creating a temporary surface
+ * drawing to it, then compositing the result onto the target surface.
+ *
+ * @draw_func is to called to draw the mask; it will be called no more
+ * than once.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS if the drawing succeeded.
+ **/
+static cairo_status_t
+_cairo_gstate_clip_and_composite (cairo_clip_t *clip,
+ cairo_operator_t operator,
+ cairo_pattern_t *src,
+ cairo_draw_func_t draw_func,
+ void *draw_closure,
+ cairo_surface_t *dst,
+ const cairo_rectangle_t *extents)
+{
+ if (_cairo_rectangle_empty (extents))
+ /* Nothing to do */
+ return CAIRO_STATUS_SUCCESS;
+
+ if (clip->surface)
+ {
+ if (_cairo_operator_bounded (operator))
+ return _cairo_gstate_clip_and_composite_with_mask (clip, operator,
+ src,
+ draw_func, draw_closure,
+ dst, extents);
+ else
+ return _cairo_gstate_clip_and_composite_combine (clip, operator,
+ src,
+ draw_func, draw_closure,
+ dst, extents);
+ }
+ else
+ {
+ return (*draw_func) (draw_closure, operator,
+ src, dst,
+ 0, 0,
+ extents);
+ }
+}
+
+
static cairo_status_t
_get_mask_extents (cairo_gstate_t *gstate,
cairo_pattern_t *mask,
cairo_rectangle_t *extents)
{
+ cairo_status_t status;
+
/*
* XXX should take mask extents into account, but
- * that involves checking the transform... For now,
+ * that involves checking the transform and
+ * _cairo_operator_bounded (operator)... For now,
* be lazy and just use the destination extents
*/
- return _cairo_gstate_get_clip_extents (gstate, extents);
+ status = _cairo_surface_get_extents (gstate->target, extents);
+ if (status)
+ return status;
+
+ return _cairo_clip_intersect_to_rectangle (&gstate->clip, extents);
+}
+
+static cairo_status_t
+_cairo_gstate_mask_draw_func (void *closure,
+ cairo_operator_t operator,
+ cairo_pattern_t *src,
+ cairo_surface_t *dst,
+ int dst_x,
+ int dst_y,
+ const cairo_rectangle_t *extents)
+{
+ cairo_pattern_t *mask = closure;
+
+ if (src)
+ return _cairo_surface_composite (operator,
+ src, mask, dst,
+ extents->x, extents->y,
+ extents->x, extents->y,
+ extents->x - dst_x, extents->y - dst_y,
+ extents->width, extents->height);
+ else
+ return _cairo_surface_composite (operator,
+ mask, NULL, dst,
+ extents->x, extents->y,
+ 0, 0, /* unused */
+ extents->x - dst_x, extents->y - dst_y,
+ extents->width, extents->height);
}
cairo_status_t
@@ -877,11 +1010,8 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
cairo_pattern_t *mask)
{
cairo_rectangle_t extents;
- cairo_pattern_union_t pattern;
- cairo_surface_pattern_t intermediate_pattern;
- cairo_pattern_t *effective_mask;
+ cairo_pattern_union_t source_pattern, mask_pattern;
cairo_status_t status;
- int mask_x, mask_y;
if (mask->status)
return mask->status;
@@ -889,69 +1019,23 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
if (gstate->source->status)
return gstate->source->status;
- status = _cairo_gstate_set_clip (gstate);
+ status = _cairo_surface_set_clip (gstate->target, &gstate->clip);
if (status)
return status;
- _get_mask_extents (gstate, mask, &extents);
+ _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
+ _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
- if (gstate->clip.surface) {
- /* When there is clip surface, we'll need to create a
- * temporary surface that combines the clip and mask
- */
- cairo_surface_t *intermediate;
-
- intermediate = cairo_surface_create_similar (gstate->clip.surface,
- CAIRO_CONTENT_ALPHA,
- extents.width,
- extents.height);
- if (intermediate->status)
- return CAIRO_STATUS_NO_MEMORY;
-
- status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
- mask, NULL, intermediate,
- extents.x, extents.y,
- 0, 0,
- 0, 0,
- extents.width, extents.height);
- if (status) {
- cairo_surface_destroy (intermediate);
- return status;
- }
-
- status = _cairo_gstate_combine_clip_surface (gstate, intermediate, &extents);
- if (status) {
- cairo_surface_destroy (intermediate);
- return status;
- }
-
- _cairo_pattern_init_for_surface (&intermediate_pattern, intermediate);
- cairo_surface_destroy (intermediate);
-
- effective_mask = &intermediate_pattern.base;
- mask_x = extents.x;
- mask_y = extents.y;
-
- } else {
- effective_mask = mask;
- mask_x = mask_y = 0;
- }
-
- _cairo_pattern_init_copy (&pattern.base, gstate->source);
- _cairo_gstate_pattern_transform (gstate, &pattern.base);
-
- status = _cairo_surface_composite (gstate->operator,
- &pattern.base,
- effective_mask,
- gstate->target,
- extents.x, extents.y,
- extents.x - mask_x, extents.y - mask_y,
- extents.x, extents.y,
- extents.width, extents.height);
+ _get_mask_extents (gstate, &mask_pattern.base, &extents);
+
+ status = _cairo_gstate_clip_and_composite (&gstate->clip, gstate->operator,
+ &source_pattern.base,
+ _cairo_gstate_mask_draw_func, &mask_pattern.base,
+ gstate->target,
+ &extents);
- if (gstate->clip.surface)
- _cairo_pattern_fini (&intermediate_pattern.base);
- _cairo_pattern_fini (&pattern.base);
+ _cairo_pattern_fini (&source_pattern.base);
+ _cairo_pattern_fini (&mask_pattern.base);
return status;
}
@@ -968,7 +1052,7 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
if (gstate->line_width <= 0.0)
return CAIRO_STATUS_SUCCESS;
- status = _cairo_gstate_set_clip (gstate);
+ status = _cairo_surface_set_clip (gstate->target, &gstate->clip);
if (status)
return status;
@@ -982,11 +1066,7 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
return status;
}
- _cairo_gstate_clip_and_composite_trapezoids (gstate,
- gstate->source,
- gstate->operator,
- gstate->target,
- &traps);
+ _cairo_gstate_clip_and_composite_trapezoids (gstate, &traps);
_cairo_traps_fini (&traps);
@@ -1035,7 +1115,7 @@ BAIL:
* _cairo_rectangle_fixed_round.
*/
-static void
+void
_cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_t *rectangle)
{
rectangle->x = _cairo_fixed_integer_floor (box->p1.x);
@@ -1044,7 +1124,7 @@ _cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_t *rectangle)
rectangle->height = _cairo_fixed_integer_ceil (box->p2.y) - rectangle->y;
}
-static void
+void
_cairo_rectangle_intersect (cairo_rectangle_t *dest, cairo_rectangle_t *src)
{
int x1, y1, x2, y2;
@@ -1067,80 +1147,10 @@ _cairo_rectangle_intersect (cairo_rectangle_t *dest, cairo_rectangle_t *src)
}
}
-static int
-_cairo_rectangle_empty (cairo_rectangle_t *rect)
-{
- return rect->width == 0 || rect->height == 0;
-}
-
-/* Given a region representing a set of trapezoids that will be
- * drawn, clip the region according to the gstate and compute
- * the overall extents.
- */
-static cairo_status_t
-_clip_and_compute_extents_region (cairo_gstate_t *gstate,
- pixman_region16_t *trap_region,
- cairo_rectangle_t *extents)
-{
- cairo_status_t status;
-
- status = _cairo_gstate_intersect_clip (gstate, trap_region);
- if (status)
- return status;
-
- _region_rect_extents (trap_region, extents);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-/* Given a a set of trapezoids to draw, find a bounding box (non-exact)
- * of the trapezoids clipped by the gstate
- */
-static cairo_status_t
-_clip_and_compute_extents_arbitrary (cairo_gstate_t *gstate,
- cairo_traps_t *traps,
- cairo_rectangle_t *extents)
-{
- cairo_box_t trap_extents;
-
- _cairo_traps_extents (traps, &trap_extents);
- _cairo_box_round_to_rectangle (&trap_extents, extents);
-
- if (gstate->clip.region) {
- pixman_region16_t *intersection;
- cairo_status_t status;
-
- status = _region_new_from_rect (extents, &intersection);
- 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 (status)
- return status;
- }
-
- if (gstate->clip.surface)
- _cairo_rectangle_intersect (extents, &gstate->clip.surface_rect);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
/* Composites a region representing a set of trapezoids.
*/
static cairo_status_t
-_composite_trap_region (cairo_gstate_t *gstate,
+_composite_trap_region (cairo_clip_t *clip,
cairo_pattern_t *src,
cairo_operator_t operator,
cairo_surface_t *dst,
@@ -1148,7 +1158,6 @@ _composite_trap_region (cairo_gstate_t *gstate,
cairo_rectangle_t *extents)
{
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;
@@ -1157,146 +1166,42 @@ _composite_trap_region (cairo_gstate_t *gstate,
return CAIRO_STATUS_SUCCESS;
if (num_rects > 1) {
-
- if (gstate->clip.mode != CAIRO_CLIP_MODE_REGION)
+ if (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,
+ clip_serial = _cairo_surface_allocate_clip_serial (dst);
+ status = _cairo_surface_set_clip_region (dst,
trap_region,
clip_serial);
if (status)
return status;
}
- _cairo_pattern_init_copy (&pattern.base, src);
- _cairo_gstate_pattern_transform (gstate, &pattern.base);
-
- if (gstate->clip.surface)
- _cairo_pattern_init_for_surface (&mask.surface, gstate->clip.surface);
+ if (clip->surface)
+ _cairo_pattern_init_for_surface (&mask.surface, clip->surface);
- status = _cairo_surface_composite (gstate->operator,
- &pattern.base,
- gstate->clip.surface ? &mask.base : NULL,
+ status = _cairo_surface_composite (operator,
+ src,
+ clip->surface ? &mask.base : NULL,
dst,
extents->x, extents->y,
- extents->x - (gstate->clip.surface ? gstate->clip.surface_rect.x : 0),
- extents->y - (gstate->clip.surface ? gstate->clip.surface_rect.y : 0),
+ extents->x - (clip->surface ? clip->surface_rect.x : 0),
+ extents->y - (clip->surface ? clip->surface_rect.y : 0),
extents->x, extents->y,
extents->width, extents->height);
- _cairo_pattern_fini (&pattern.base);
- if (gstate->clip.surface)
+ if (clip->surface)
_cairo_pattern_fini (&mask.base);
return status;
}
-static void
-translate_traps (cairo_traps_t *traps, int x, int y)
-{
- cairo_fixed_t xoff, yoff;
- cairo_trapezoid_t *t;
- int i;
-
- /* Ugh. The cairo_composite/(Render) interface doesn't allow
- an offset for the trapezoids. Need to manually shift all
- the coordinates to align with the offset origin of the
- intermediate surface. */
-
- xoff = _cairo_fixed_from_int (x);
- yoff = _cairo_fixed_from_int (y);
-
- for (i = 0, t = traps->traps; i < traps->num_traps; i++, t++) {
- t->top += yoff;
- t->bottom += yoff;
- t->left.p1.x += xoff;
- t->left.p1.y += yoff;
- t->left.p2.x += xoff;
- t->left.p2.y += yoff;
- t->right.p1.x += xoff;
- t->right.p1.y += yoff;
- t->right.p2.x += xoff;
- t->right.p2.y += yoff;
- }
-}
-
-/* Composites a set of trapezoids in the case where we need to create
- * an intermediate surface to handle gstate->clip.surface
- *
- * Warning: This call modifies the coordinates of traps
- */
-static cairo_status_t
-_composite_traps_intermediate_surface (cairo_gstate_t *gstate,
- cairo_pattern_t *src,
- cairo_operator_t operator,
- cairo_surface_t *dst,
- cairo_traps_t *traps,
- cairo_rectangle_t *extents)
-{
- cairo_pattern_union_t pattern;
- cairo_surface_t *intermediate;
- cairo_surface_pattern_t intermediate_pattern;
- cairo_status_t status;
-
- translate_traps (traps, -extents->x, -extents->y);
-
- intermediate = _cairo_surface_create_similar_solid (gstate->clip.surface,
- CAIRO_CONTENT_ALPHA,
- extents->width,
- extents->height,
- CAIRO_COLOR_TRANSPARENT);
- if (intermediate->status)
- return CAIRO_STATUS_NO_MEMORY;
-
- _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
-
- status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_ADD,
- &pattern.base,
- intermediate,
- extents->x, extents->y,
- 0, 0,
- extents->width,
- extents->height,
- traps->traps,
- traps->num_traps);
- _cairo_pattern_fini (&pattern.base);
-
- if (status)
- goto out;
-
- status = _cairo_gstate_combine_clip_surface (gstate, intermediate, extents);
- if (status)
- goto out;
-
- _cairo_pattern_init_for_surface (&intermediate_pattern, intermediate);
- _cairo_pattern_init_copy (&pattern.base, src);
- _cairo_gstate_pattern_transform (gstate, &pattern.base);
-
- status = _cairo_surface_composite (operator,
- &pattern.base,
- &intermediate_pattern.base,
- dst,
- extents->x, extents->y,
- 0, 0,
- extents->x, extents->y,
- extents->width, extents->height);
-
- _cairo_pattern_fini (&pattern.base);
- _cairo_pattern_fini (&intermediate_pattern.base);
-
- out:
- cairo_surface_destroy (intermediate);
-
- return status;
-}
-
/* Composites a region representing a set of trapezoids in the
* case of a solid source (so we can use
* _cairo_surface_fill_rectangles).
*/
static cairo_status_t
-_composite_trap_region_solid (cairo_gstate_t *gstate,
+_composite_trap_region_solid (cairo_clip_t *clip,
cairo_solid_pattern_t *src,
cairo_operator_t operator,
cairo_surface_t *dst,
@@ -1330,48 +1235,69 @@ _composite_trap_region_solid (cairo_gstate_t *gstate,
return status;
}
-/* Composites a set of trapezoids in the general case where
- gstate->clip.surface == NULL
- */
+typedef struct {
+ cairo_traps_t *traps;
+ cairo_antialias_t antialias;
+} cairo_composite_traps_info_t;
+
static cairo_status_t
-_composite_traps (cairo_gstate_t *gstate,
- cairo_pattern_t *src,
- cairo_operator_t operator,
- cairo_surface_t *dst,
- cairo_traps_t *traps,
- cairo_rectangle_t *extents)
-{
+_composite_traps_draw_func (void *closure,
+ cairo_operator_t operator,
+ cairo_pattern_t *src,
+ cairo_surface_t *dst,
+ int dst_x,
+ int dst_y,
+ const cairo_rectangle_t *extents)
+{
+ cairo_composite_traps_info_t *info = closure;
cairo_pattern_union_t pattern;
cairo_status_t status;
-
- _cairo_pattern_init_copy (&pattern.base, src);
- _cairo_gstate_pattern_transform (gstate, &pattern.base);
- status = _cairo_surface_composite_trapezoids (gstate->operator,
- &pattern.base, dst,
- extents->x, extents->y,
- extents->x, extents->y,
- extents->width,
- extents->height,
- traps->traps,
- traps->num_traps);
+ if (dst_x != 0 || dst_y != 0)
+ _cairo_traps_translate (info->traps, - dst_x, - dst_y);
+ _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
+ if (!src)
+ src = &pattern.base;
+
+ status = _cairo_surface_composite_trapezoids (operator,
+ src, dst, info->antialias,
+ extents->x, extents->y,
+ extents->x - dst_x, extents->y - dst_y,
+ extents->width, extents->height,
+ info->traps->traps,
+ info->traps->num_traps);
_cairo_pattern_fini (&pattern.base);
return status;
}
+/* Gets the bounding box of a region as a cairo_rectangle_t */
+static void
+_region_rect_extents (pixman_region16_t *region,
+ cairo_rectangle_t *rect)
+{
+ pixman_box16_t *region_extents = pixman_region_extents (region);
+
+ rect->x = region_extents->x1;
+ rect->y = region_extents->y1;
+ rect->width = region_extents->x2 - region_extents->x1;
+ rect->height = region_extents->y2 - region_extents->y1;
+}
+
/* Warning: This call modifies the coordinates of traps */
-static cairo_status_t
-_cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
- cairo_pattern_t *src,
- cairo_operator_t operator,
- cairo_surface_t *dst,
- cairo_traps_t *traps)
+cairo_status_t
+_cairo_surface_clip_and_composite_trapezoids (cairo_pattern_t *src,
+ cairo_operator_t operator,
+ cairo_surface_t *dst,
+ cairo_traps_t *traps,
+ cairo_clip_t *clip,
+ cairo_antialias_t antialias)
{
cairo_status_t status;
pixman_region16_t *trap_region;
cairo_rectangle_t extents;
+ cairo_composite_traps_info_t traps_info;
if (traps->num_traps == 0)
return CAIRO_STATUS_SUCCESS;
@@ -1380,60 +1306,65 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
if (status)
return status;
- if (trap_region)
- status = _clip_and_compute_extents_region (gstate, trap_region, &extents);
+ if (_cairo_operator_bounded (operator))
+ {
+ if (trap_region) {
+ status = _cairo_clip_intersect_to_region (clip, trap_region);
+ _region_rect_extents (trap_region, &extents);
+ } else {
+ cairo_box_t trap_extents;
+ _cairo_traps_extents (traps, &trap_extents);
+ _cairo_box_round_to_rectangle (&trap_extents, &extents);
+ status = _cairo_clip_intersect_to_rectangle (clip, &extents);
+ }
+ }
else
- status = _clip_and_compute_extents_arbitrary (gstate, traps, &extents);
+ {
+ status = _cairo_surface_get_extents (dst, &extents);
+ if (status)
+ return status;
+ status = _cairo_clip_intersect_to_rectangle (clip, &extents);
+ if (status)
+ return status;
+ }
if (status)
goto out;
- if (_cairo_rectangle_empty (&extents))
- /* Nothing to do */
- goto out;
-
- if (gstate->clip.surface) {
- if (trap_region) {
- /* If we are compositing a set of rectangles, we can set them as the
- * clip region for the destination surface and use the clip surface
- * as the mask. A clip region might not be supported, in which case
- * we fall through to the next method
- */
- status = _composite_trap_region (gstate, src, operator, dst,
- trap_region, &extents);
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- goto out;
- }
-
- /* Handle a clip surface by creating an intermediate surface. */
- status = _composite_traps_intermediate_surface (gstate, src, operator,
- dst, traps, &extents);
- } else {
- /* No clip surface */
- if (trap_region && src->type == CAIRO_PATTERN_SOLID) {
- /* Solid rectangles are handled specially */
- status = _composite_trap_region_solid (gstate, (cairo_solid_pattern_t *)src,
+ if (trap_region && _cairo_operator_bounded (operator))
+ {
+ if (src->type == CAIRO_PATTERN_SOLID && !clip->surface)
+ {
+ /* Solid rectangles special case */
+ status = _composite_trap_region_solid (clip, (cairo_solid_pattern_t *)src,
operator, dst, trap_region);
- } else {
- 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);
+ goto out;
}
+
+ /* 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.
+ *
+ * If we have a clip surface, we set it as the mask.
+ *
+ * CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has
+ * more than rectangle and the destination doesn't support clip
+ * regions. In that case, we fall through.
+ */
+ status = _composite_trap_region (clip, src, operator, dst,
+ trap_region, &extents);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ goto out;
}
+ traps_info.traps = traps;
+ traps_info.antialias = antialias;
+
+ status = _cairo_gstate_clip_and_composite (clip, operator, src,
+ _composite_traps_draw_func, &traps_info,
+ dst, &extents);
+
out:
if (trap_region)
pixman_region_destroy (trap_region);
@@ -1441,6 +1372,28 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
return status;
}
+/* Warning: This call modifies the coordinates of traps */
+static cairo_status_t
+_cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
+ cairo_traps_t *traps)
+{
+ cairo_pattern_union_t pattern;
+ cairo_status_t status;
+
+ _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
+
+ status = _cairo_surface_clip_and_composite_trapezoids (&pattern.base,
+ gstate->operator,
+ gstate->target,
+ traps,
+ &gstate->clip,
+ gstate->antialias);
+
+ _cairo_pattern_fini (&pattern.base);
+
+ return status;
+}
+
cairo_status_t
_cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
{
@@ -1450,7 +1403,7 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
if (gstate->source->status)
return gstate->source->status;
- status = _cairo_gstate_set_clip (gstate);
+ status = _cairo_surface_set_clip (gstate->target, &gstate->clip);
if (status)
return status;
@@ -1466,17 +1419,16 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
_cairo_traps_init (&traps);
- status = _cairo_path_fixed_fill_to_traps (path, gstate, &traps);
+ status = _cairo_path_fixed_fill_to_traps (path,
+ gstate->fill_rule,
+ gstate->tolerance,
+ &traps);
if (status) {
_cairo_traps_fini (&traps);
return status;
}
- _cairo_gstate_clip_and_composite_trapezoids (gstate,
- gstate->source,
- gstate->operator,
- gstate->target,
- &traps);
+ _cairo_gstate_clip_and_composite_trapezoids (gstate, &traps);
_cairo_traps_fini (&traps);
@@ -1497,7 +1449,10 @@ _cairo_gstate_in_fill (cairo_gstate_t *gstate,
_cairo_traps_init (&traps);
- status = _cairo_path_fixed_fill_to_traps (path, gstate, &traps);
+ status = _cairo_path_fixed_fill_to_traps (path,
+ gstate->fill_rule,
+ gstate->tolerance,
+ &traps);
if (status)
goto BAIL;
@@ -1567,7 +1522,10 @@ _cairo_gstate_fill_extents (cairo_gstate_t *gstate,
_cairo_traps_init (&traps);
- status = _cairo_path_fixed_fill_to_traps (path, gstate, &traps);
+ status = _cairo_path_fixed_fill_to_traps (path,
+ gstate->fill_rule,
+ gstate->tolerance,
+ &traps);
if (status)
goto BAIL;
@@ -1590,226 +1548,19 @@ BAIL:
cairo_status_t
_cairo_gstate_reset_clip (cairo_gstate_t *gstate)
{
- /* destroy any existing clip-region artifacts */
- if (gstate->clip.surface)
- cairo_surface_destroy (gstate->clip.surface);
- gstate->clip.surface = NULL;
-
- if (gstate->clip.region)
- pixman_region_destroy (gstate->clip.region);
- gstate->clip.region = NULL;
-
- if (gstate->clip.path)
- _cairo_clip_path_destroy (gstate->clip.path);
- gstate->clip.path = NULL;
-
- gstate->clip.serial = 0;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-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;
-
- if (gstate->clip.mode != CAIRO_CLIP_MODE_PATH)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- 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;
-
- 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);
-
- 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;
-
- status = _cairo_traps_extract_region (traps, &region);
- if (status)
- return status;
-
- if (region == NULL)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- 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;
-}
-
-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);
-
- surface = _cairo_surface_create_similar_solid (gstate->target,
- CAIRO_CONTENT_ALPHA,
- surface_rect.width,
- surface_rect.height,
- CAIRO_COLOR_WHITE);
- if (surface->status)
- 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,
- surface,
- 0, 0,
- 0, 0,
- 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;
+ return _cairo_clip_reset (&gstate->clip);
}
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 status;
+ return _cairo_clip_clip (&gstate->clip,
+ path, gstate->fill_rule, gstate->tolerance,
+ gstate->antialias, gstate->target);
}
static void
-_cairo_gstate_unset_font (cairo_gstate_t *gstate)
+_cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate)
{
if (gstate->scaled_font) {
cairo_scaled_font_destroy (gstate->scaled_font);
@@ -1825,7 +1576,7 @@ _cairo_gstate_select_font_face (cairo_gstate_t *gstate,
{
cairo_font_face_t *font_face;
- font_face = _cairo_simple_font_face_create (family, slant, weight);
+ font_face = _cairo_toy_font_face_create (family, slant, weight);
if (font_face->status)
return font_face->status;
@@ -1839,7 +1590,7 @@ cairo_status_t
_cairo_gstate_set_font_size (cairo_gstate_t *gstate,
double size)
{
- _cairo_gstate_unset_font (gstate);
+ _cairo_gstate_unset_scaled_font (gstate);
cairo_matrix_init_scale (&gstate->font_matrix, size, size);
@@ -1850,7 +1601,7 @@ cairo_status_t
_cairo_gstate_set_font_matrix (cairo_gstate_t *gstate,
const cairo_matrix_t *matrix)
{
- _cairo_gstate_unset_font (gstate);
+ _cairo_gstate_unset_scaled_font (gstate);
gstate->font_matrix = *matrix;
@@ -1868,7 +1619,7 @@ cairo_status_t
_cairo_gstate_set_font_options (cairo_gstate_t *gstate,
const cairo_font_options_t *options)
{
- _cairo_gstate_unset_font (gstate);
+ _cairo_gstate_unset_scaled_font (gstate);
gstate->font_options = *options;
@@ -1979,9 +1730,9 @@ _cairo_gstate_ensure_font_face (cairo_gstate_t *gstate)
if (!gstate->font_face) {
cairo_font_face_t *font_face;
- font_face = _cairo_simple_font_face_create (CAIRO_FONT_FAMILY_DEFAULT,
- CAIRO_FONT_SLANT_DEFAULT,
- CAIRO_FONT_WEIGHT_DEFAULT);
+ font_face = _cairo_toy_font_face_create (CAIRO_FONT_FAMILY_DEFAULT,
+ CAIRO_FONT_SLANT_DEFAULT,
+ CAIRO_FONT_WEIGHT_DEFAULT);
if (font_face->status)
return font_face->status;
else
@@ -1992,7 +1743,7 @@ _cairo_gstate_ensure_font_face (cairo_gstate_t *gstate)
}
static cairo_status_t
-_cairo_gstate_ensure_font (cairo_gstate_t *gstate)
+_cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate)
{
cairo_status_t status;
cairo_font_options_t options;
@@ -2022,7 +1773,7 @@ cairo_status_t
_cairo_gstate_get_font_extents (cairo_gstate_t *gstate,
cairo_font_extents_t *extents)
{
- cairo_status_t status = _cairo_gstate_ensure_font (gstate);
+ cairo_status_t status = _cairo_gstate_ensure_scaled_font (gstate);
if (status)
return status;
@@ -2042,7 +1793,7 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
cairo_status_t status;
int i;
- status = _cairo_gstate_ensure_font (gstate);
+ status = _cairo_gstate_ensure_scaled_font (gstate);
if (status)
return status;
@@ -2071,18 +1822,15 @@ cairo_status_t
_cairo_gstate_set_font_face (cairo_gstate_t *gstate,
cairo_font_face_t *font_face)
{
- if (font_face->status)
+ if (font_face && font_face->status)
return font_face->status;
if (font_face != gstate->font_face) {
- if (gstate->font_face)
- cairo_font_face_destroy (gstate->font_face);
- gstate->font_face = font_face;
- if (gstate->font_face)
- cairo_font_face_reference (gstate->font_face);
+ cairo_font_face_destroy (gstate->font_face);
+ gstate->font_face = cairo_font_face_reference (font_face);
}
- _cairo_gstate_unset_font (gstate);
+ _cairo_gstate_unset_scaled_font (gstate);
return CAIRO_STATUS_SUCCESS;
}
@@ -2095,7 +1843,7 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
{
cairo_status_t status;
- status = _cairo_gstate_ensure_font (gstate);
+ status = _cairo_gstate_ensure_scaled_font (gstate);
if (status)
return status;
@@ -2106,6 +1854,58 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
return CAIRO_STATUS_SUCCESS;
}
+typedef struct {
+ cairo_scaled_font_t *font;
+ cairo_glyph_t *glyphs;
+ int num_glyphs;
+} cairo_show_glyphs_info_t;
+
+static cairo_status_t
+_cairo_gstate_show_glyphs_draw_func (void *closure,
+ cairo_operator_t operator,
+ cairo_pattern_t *src,
+ cairo_surface_t *dst,
+ int dst_x,
+ int dst_y,
+ const cairo_rectangle_t *extents)
+{
+ cairo_show_glyphs_info_t *glyph_info = closure;
+ cairo_pattern_union_t pattern;
+ cairo_status_t status;
+
+ /* Modifying the glyph array is fine because we know that this function
+ * will be called only once, and we've already made a copy of the
+ * glyphs in the wrapper.
+ */
+ if (dst_x != 0 || dst_y != 0) {
+ int i;
+
+ for (i = 0; i < glyph_info->num_glyphs; ++i)
+ {
+ glyph_info->glyphs[i].x -= dst_x;
+ glyph_info->glyphs[i].y -= dst_y;
+ }
+ }
+
+ _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
+ if (!src)
+ src = &pattern.base;
+
+ status = _cairo_scaled_font_show_glyphs (glyph_info->font,
+ operator,
+ src, dst,
+ extents->x, extents->y,
+ extents->x - dst_x, extents->y - dst_y,
+ extents->width, extents->height,
+ glyph_info->glyphs,
+ glyph_info->num_glyphs);
+
+ if (src == &pattern.base)
+ _cairo_pattern_fini (&pattern.base);
+
+ return status;
+}
+
cairo_status_t
_cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
cairo_glyph_t *glyphs,
@@ -2117,15 +1917,16 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
cairo_pattern_union_t pattern;
cairo_box_t bbox;
cairo_rectangle_t extents;
+ cairo_show_glyphs_info_t glyph_info;
if (gstate->source->status)
return gstate->source->status;
- status = _cairo_gstate_set_clip (gstate);
+ status = _cairo_surface_set_clip (gstate->target, &gstate->clip);
if (status)
return status;
- status = _cairo_gstate_ensure_font (gstate);
+ status = _cairo_gstate_ensure_scaled_font (gstate);
if (status)
return status;
@@ -2140,113 +1941,41 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
&transformed_glyphs[i].x,
&transformed_glyphs[i].y);
}
-
- status = _cairo_scaled_font_glyph_bbox (gstate->scaled_font,
- transformed_glyphs, num_glyphs,
- &bbox);
- _cairo_box_round_to_rectangle (&bbox, &extents);
- if (status)
- goto CLEANUP_GLYPHS;
-
- if (gstate->clip.surface)
+ if (_cairo_operator_bounded (gstate->operator))
{
- cairo_surface_t *intermediate;
- cairo_surface_pattern_t intermediate_pattern;
-
- _cairo_rectangle_intersect (&extents, &gstate->clip.surface_rect);
-
- /* Shortcut if empty */
- if (_cairo_rectangle_empty (&extents)) {
- status = CAIRO_STATUS_SUCCESS;
- goto BAIL1;
- }
-
- intermediate = _cairo_surface_create_similar_solid (gstate->clip.surface,
- CAIRO_CONTENT_ALPHA,
- extents.width,
- extents.height,
- CAIRO_COLOR_TRANSPARENT);
- if (intermediate->status) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto BAIL1;
- }
-
- /* move the glyphs again, from dev space to intermediate space */
- for (i = 0; i < num_glyphs; ++i)
- {
- transformed_glyphs[i].x -= extents.x;
- transformed_glyphs[i].y -= extents.y;
- }
-
- _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
-
- status = _cairo_scaled_font_show_glyphs (gstate->scaled_font,
- CAIRO_OPERATOR_ADD,
- &pattern.base, intermediate,
- extents.x, extents.y,
- 0, 0,
- extents.width, extents.height,
- transformed_glyphs, num_glyphs);
-
- _cairo_pattern_fini (&pattern.base);
-
+ status = _cairo_scaled_font_glyph_bbox (gstate->scaled_font,
+ transformed_glyphs, num_glyphs,
+ &bbox);
if (status)
- goto BAIL2;
-
- _cairo_pattern_init_for_surface (&pattern.surface,
- gstate->clip.surface);
-
- status = _cairo_surface_composite (CAIRO_OPERATOR_IN,
- &pattern.base,
- NULL,
- intermediate,
- extents.x - gstate->clip.surface_rect.x,
- extents.y - gstate->clip.surface_rect.y,
- 0, 0,
- 0, 0,
- extents.width, extents.height);
-
- _cairo_pattern_fini (&pattern.base);
-
- if (status)
- goto BAIL2;
-
- _cairo_pattern_init_for_surface (&intermediate_pattern, intermediate);
- _cairo_pattern_init_copy (&pattern.base, gstate->source);
- _cairo_gstate_pattern_transform (gstate, &pattern.base);
-
- status = _cairo_surface_composite (gstate->operator,
- &pattern.base,
- &intermediate_pattern.base,
- gstate->target,
- extents.x, extents.y,
- 0, 0,
- extents.x, extents.y,
- extents.width, extents.height);
- _cairo_pattern_fini (&pattern.base);
- _cairo_pattern_fini (&intermediate_pattern.base);
-
- BAIL2:
- cairo_surface_destroy (intermediate);
- BAIL1:
- ;
+ goto CLEANUP_GLYPHS;
+
+ _cairo_box_round_to_rectangle (&bbox, &extents);
}
else
{
- _cairo_pattern_init_copy (&pattern.base, gstate->source);
- _cairo_gstate_pattern_transform (gstate, &pattern.base);
+ status = _cairo_surface_get_extents (gstate->target, &extents);
+ if (status)
+ goto CLEANUP_GLYPHS;
+ }
+
+ status = _cairo_clip_intersect_to_rectangle (&gstate->clip, &extents);
+ if (status)
+ goto CLEANUP_GLYPHS;
+
+ _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
- status = _cairo_scaled_font_show_glyphs (gstate->scaled_font,
- gstate->operator, &pattern.base,
- gstate->target,
- extents.x, extents.y,
- extents.x, extents.y,
- extents.width, extents.height,
- transformed_glyphs, num_glyphs);
+ glyph_info.font = gstate->scaled_font;
+ glyph_info.glyphs = transformed_glyphs;
+ glyph_info.num_glyphs = num_glyphs;
+
+ status = _cairo_gstate_clip_and_composite (&gstate->clip, gstate->operator,
+ &pattern.base,
+ _cairo_gstate_show_glyphs_draw_func, &glyph_info,
+ gstate->target,
+ &extents);
- _cairo_pattern_fini (&pattern.base);
- }
+ _cairo_pattern_fini (&pattern.base);
CLEANUP_GLYPHS:
free (transformed_glyphs);
@@ -2264,7 +1993,7 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
int i;
cairo_glyph_t *transformed_glyphs = NULL;
- status = _cairo_gstate_ensure_font (gstate);
+ status = _cairo_gstate_ensure_scaled_font (gstate);
if (status)
return status;
@@ -2287,3 +2016,19 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
free (transformed_glyphs);
return status;
}
+
+cairo_private cairo_status_t
+_cairo_gstate_set_antialias (cairo_gstate_t *gstate,
+ cairo_antialias_t antialias)
+{
+ gstate->antialias = antialias;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_private cairo_antialias_t
+_cairo_gstate_get_antialias (cairo_gstate_t *gstate)
+{
+ return gstate->antialias;
+}
+
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index b21cf122..f7dbc8cf 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -69,7 +69,8 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
surface->format = format;
surface->data = (unsigned char *) pixman_image_get_data (pixman_image);
- surface->owns_data = 0;
+ surface->owns_data = FALSE;
+ surface->has_clip = FALSE;
surface->width = pixman_image_get_width (pixman_image);
surface->height = pixman_image_get_height (pixman_image);
@@ -408,8 +409,7 @@ _cairo_image_surface_clone_similar (void *abstract_surface,
cairo_image_surface_t *surface = abstract_surface;
if (src->backend == surface->base.backend) {
- *clone_out = src;
- cairo_surface_reference (src);
+ *clone_out = cairo_surface_reference (src);
return CAIRO_STATUS_SUCCESS;
}
@@ -614,6 +614,16 @@ _cairo_image_surface_composite (cairo_operator_t operator,
}
}
+ if (!_cairo_operator_bounded (operator))
+ _cairo_surface_composite_fixup_unbounded (&dst->base,
+ &src_attr, src->width, src->height,
+ mask ? &mask_attr : NULL,
+ mask ? mask->width : 0,
+ mask ? mask->height : 0,
+ src_x, src_y,
+ mask_x, mask_y,
+ dst_x, dst_y, width, height);
+
if (mask)
_cairo_pattern_release_surface (mask_pattern, &mask->base, &mask_attr);
@@ -645,10 +655,25 @@ _cairo_image_surface_fill_rectangles (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
+static cairo_bool_t
+_cairo_image_surface_is_alpha_only (cairo_image_surface_t *surface)
+{
+ int bpp, alpha, red, green, blue;
+
+ if (surface->format != (cairo_format_t) -1)
+ return surface->format == CAIRO_FORMAT_A1 || surface->format == CAIRO_FORMAT_A8;
+
+ pixman_format_get_masks (pixman_image_get_format (surface->pixman_image),
+ &bpp, &alpha, &red, &green, &blue);
+
+ return red == 0 && blue == 0 && green == 0;
+}
+
static cairo_int_status_t
_cairo_image_surface_composite_trapezoids (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_dst,
+ cairo_antialias_t antialias,
int src_x,
int src_y,
int dst_x,
@@ -662,8 +687,35 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t operator,
cairo_image_surface_t *dst = abstract_dst;
cairo_image_surface_t *src;
cairo_int_status_t status;
- int render_reference_x, render_reference_y;
- int render_src_x, render_src_y;
+ pixman_image_t *mask;
+ pixman_format_t *format;
+ pixman_bits_t *mask_data;
+ int mask_stride;
+ int mask_bpp;
+
+ /* Special case adding trapezoids onto a mask surface; we want to avoid
+ * creating an intermediate temporary mask unecessarily.
+ *
+ * We make the assumption here that the portion of the trapezoids
+ * contained within the surface is bounded by [dst_x,dst_y,width,height];
+ * the Cairo core code passes bounds based on the trapezoid extents.
+ *
+ * Currently the check surface->has_clip is needed for correct
+ * functioning, since pixman_add_trapezoids() doesn't obey the
+ * surface clip, which is a libpixman bug , but there's no harm in
+ * falling through to the general case when the surface is clipped
+ * since libpixman would have to generate an intermediate mask anyways.
+ */
+ if (operator == CAIRO_OPERATOR_ADD &&
+ _cairo_pattern_is_opaque_solid (pattern) &&
+ _cairo_image_surface_is_alpha_only (dst) &&
+ !dst->has_clip &&
+ antialias != CAIRO_ANTIALIAS_NONE)
+ {
+ pixman_add_trapezoids (dst->pixman_image, 0, 0,
+ (pixman_trapezoid_t *) traps, num_traps);
+ return CAIRO_STATUS_SUCCESS;
+ }
status = _cairo_pattern_acquire_surface (pattern, &dst->base,
src_x, src_y, width, height,
@@ -672,28 +724,64 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t operator,
if (status)
return status;
- 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);
- } else {
- render_reference_x = _cairo_fixed_integer_floor (traps[0].left.p2.x);
- render_reference_y = _cairo_fixed_integer_floor (traps[0].left.p2.y);
+ status = _cairo_image_surface_set_attributes (src, &attributes);
+ if (status)
+ goto CLEANUP_SOURCE;
+
+ switch (antialias) {
+ case CAIRO_ANTIALIAS_NONE:
+ format = pixman_format_create (PIXMAN_FORMAT_NAME_A1);
+ mask_stride = (width + 31)/8;
+ mask_bpp = 1;
+ break;
+ default:
+ format = pixman_format_create (PIXMAN_FORMAT_NAME_A8);
+ mask_stride = (width + 3) & ~3;
+ mask_bpp = 8;
+ break;
+ }
+ if (!format) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto CLEANUP_SOURCE;
+ }
+
+ /* The image must be initially transparent */
+ mask_data = calloc (1, mask_stride * height);
+ if (!mask_data) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ pixman_format_destroy (format);
+ goto CLEANUP_SOURCE;
}
- render_src_x = src_x + render_reference_x - dst_x;
- render_src_y = src_y + render_reference_y - dst_y;
+ mask = pixman_image_create_for_data (mask_data, format, width, height,
+ mask_bpp, mask_stride);
+ pixman_format_destroy (format);
+ if (!mask) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto CLEANUP_IMAGE_DATA;
+ }
/* XXX: The pixman_trapezoid_t cast is evil and needs to go away
* somehow. */
- status = _cairo_image_surface_set_attributes (src, &attributes);
- if (status == CAIRO_STATUS_SUCCESS)
- pixman_composite_trapezoids (_pixman_operator (operator),
- src->pixman_image,
- dst->pixman_image,
- render_src_x + attributes.x_offset,
- render_src_y + attributes.y_offset,
- (pixman_trapezoid_t *) traps, num_traps);
-
+ pixman_add_trapezoids (mask, - dst_x, - dst_y,
+ (pixman_trapezoid_t *) traps, num_traps);
+
+ pixman_composite (_pixman_operator (operator),
+ src->pixman_image,
+ mask,
+ dst->pixman_image,
+ src_x + attributes.x_offset,
+ src_y + attributes.y_offset,
+ 0, 0,
+ dst_x, dst_y,
+ width, height);
+
+ pixman_image_destroy (mask);
+
+ CLEANUP_IMAGE_DATA:
+ free (mask_data);
+
+ CLEANUP_SOURCE:
_cairo_pattern_release_surface (pattern, &src->base, &attributes);
return status;
@@ -714,6 +802,8 @@ _cairo_image_surface_set_clip_region (cairo_image_surface_t *surface,
{
pixman_image_set_clip_region (surface->pixman_image, region);
+ surface->has_clip = region != NULL;
+
return CAIRO_STATUS_SUCCESS;
}
diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c
index 98feb571..7596b084 100644
--- a/src/cairo-matrix.c
+++ b/src/cairo-matrix.c
@@ -36,7 +36,6 @@
#define _GNU_SOURCE
#include <stdlib.h>
-#include <math.h>
#include "cairoint.h"
diff --git a/src/cairo-meta-surface-private.h b/src/cairo-meta-surface-private.h
index 234c6ccf..f37a8916 100644
--- a/src/cairo-meta-surface-private.h
+++ b/src/cairo-meta-surface-private.h
@@ -77,6 +77,7 @@ typedef struct _cairo_command_composite_trapezoids {
cairo_command_type_t type;
cairo_operator_t operator;
cairo_pattern_union_t pattern;
+ cairo_antialias_t antialias;
int x_src;
int y_src;
int x_dst;
@@ -99,6 +100,7 @@ typedef struct _cairo_command_intersect_clip_path {
cairo_path_fixed_t path;
cairo_fill_rule_t fill_rule;
double tolerance;
+ cairo_antialias_t antialias;
} cairo_command_intersect_clip_path_t;
typedef struct _cairo_command_show_glyphs {
@@ -123,6 +125,7 @@ typedef struct _cairo_command_fill_path {
cairo_path_fixed_t path;
cairo_fill_rule_t fill_rule;
double tolerance;
+ cairo_antialias_t antialias;
} cairo_command_fill_path_t;
typedef union _cairo_command {
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index 8a893d66..f218ae24 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -35,15 +35,7 @@
#include "cairoint.h"
#include "cairo-meta-surface-private.h"
-
-/*
- * Notes:
- *
- * Can't use cairo_surface_* calls since we often don't want
- * fallbacks. For example, when determining the font subsets or the
- * fallback areas. Hmm... but maybe those passes could be integrated
- * into the delegation wrappers and the ps output pass, respectively.
- */
+#include "cairo-gstate-private.h"
static const cairo_surface_backend_t cairo_meta_surface_backend;
@@ -106,10 +98,6 @@ _cairo_meta_surface_finish (void *abstract_surface)
free (command);
break;
- case CAIRO_COMMAND_SET_CLIP_REGION:
- free (command);
- break;
-
case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
if (command->intersect_clip_path.path_pointer)
_cairo_path_fixed_fini (&command->intersect_clip_path.path);
@@ -229,6 +217,7 @@ static cairo_int_status_t
_cairo_meta_surface_composite_trapezoids (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_surface,
+ cairo_antialias_t antialias,
int x_src,
int y_src,
int x_dst,
@@ -248,6 +237,7 @@ _cairo_meta_surface_composite_trapezoids (cairo_operator_t operator,
command->type = CAIRO_COMMAND_COMPOSITE_TRAPEZOIDS;
command->operator = operator;
_cairo_pattern_init_copy (&command->pattern.base, pattern);
+ command->antialias = antialias;
command->x_src = x_src;
command->y_src = y_src;
command->x_dst = x_dst;
@@ -276,42 +266,11 @@ _cairo_meta_surface_composite_trapezoids (cairo_operator_t operator,
}
static cairo_int_status_t
-_cairo_meta_surface_set_clip_region (void *abstract_surface,
- pixman_region16_t *region)
-{
- cairo_meta_surface_t *meta = abstract_surface;
- cairo_command_set_clip_region_t *command;
-
- command = malloc (sizeof (cairo_command_set_clip_region_t));
- if (command == NULL)
- return CAIRO_STATUS_NO_MEMORY;
-
- command->type = CAIRO_COMMAND_SET_CLIP_REGION;
-
- if (region) {
- command->region = pixman_region_create ();
- pixman_region_copy (command->region, region);
- } else {
- command->region = NULL;
- }
-
- command->serial = meta->base.current_clip_serial;
-
- if (_cairo_array_append (&meta->commands, &command, 1) == NULL) {
- if (command->region)
- pixman_region_destroy (command->region);
- free (command);
- return CAIRO_STATUS_NO_MEMORY;
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
_cairo_meta_surface_intersect_clip_path (void *dst,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
- double tolerance)
+ double tolerance,
+ cairo_antialias_t antialias)
{
cairo_meta_surface_t *meta = dst;
cairo_command_intersect_clip_path_t *command;
@@ -335,6 +294,7 @@ _cairo_meta_surface_intersect_clip_path (void *dst,
}
command->fill_rule = fill_rule;
command->tolerance = tolerance;
+ command->antialias = antialias;
if (_cairo_array_append (&meta->commands, &command, 1) == NULL) {
if (path)
@@ -387,8 +347,7 @@ _cairo_meta_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
return CAIRO_STATUS_NO_MEMORY;
command->type = CAIRO_COMMAND_SHOW_GLYPHS;
- command->scaled_font = scaled_font;
- cairo_scaled_font_reference (scaled_font);
+ command->scaled_font = cairo_scaled_font_reference (scaled_font);
command->operator = operator;
_cairo_pattern_init_copy (&command->pattern.base, pattern);
command->source_x = source_x;
@@ -469,7 +428,7 @@ static const cairo_surface_backend_t cairo_meta_surface_backend = {
_cairo_meta_surface_composite_trapezoids,
NULL, /* copy_page */
NULL, /* show_page */
- _cairo_meta_surface_set_clip_region,
+ NULL, /* set_clip_region */
_cairo_meta_surface_intersect_clip_path,
_cairo_meta_surface_get_extents,
_cairo_meta_surface_show_glyphs,
@@ -484,16 +443,24 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
cairo_command_t *command, **elements;
int i, num_elements;
cairo_int_status_t status;
+ cairo_traps_t traps;
+ cairo_clip_t clip;
meta = (cairo_meta_surface_t *) surface;
status = CAIRO_STATUS_SUCCESS;
+ _cairo_clip_init (&clip, target);
+
num_elements = meta->commands.num_elements;
elements = (cairo_command_t **) meta->commands.elements;
for (i = 0; i < num_elements; i++) {
command = elements[i];
switch (command->type) {
case CAIRO_COMMAND_COMPOSITE:
+ status = _cairo_surface_set_clip (target, &clip);
+ if (status)
+ break;
+
status = _cairo_surface_composite
(command->composite.operator,
&command->composite.src_pattern.base,
@@ -510,6 +477,10 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
break;
case CAIRO_COMMAND_FILL_RECTANGLES:
+ status = _cairo_surface_set_clip (target, &clip);
+ if (status)
+ break;
+
status = _cairo_surface_fill_rectangles
(target,
command->fill_rectangles.operator,
@@ -519,10 +490,15 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
break;
case CAIRO_COMMAND_COMPOSITE_TRAPEZOIDS:
+ status = _cairo_surface_set_clip (target, &clip);
+ if (status)
+ break;
+
status = _cairo_surface_composite_trapezoids
(command->composite_trapezoids.operator,
&command->composite_trapezoids.pattern.base,
target,
+ command->composite_trapezoids.antialias,
command->composite_trapezoids.x_src,
command->composite_trapezoids.y_src,
command->composite_trapezoids.x_dst,
@@ -533,27 +509,25 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
command->composite_trapezoids.num_traps);
break;
- case CAIRO_COMMAND_SET_CLIP_REGION:
- status = _cairo_surface_set_clip_region
- (target,
- command->set_clip_region.region,
- command->set_clip_region.serial);
- break;
-
case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
/* XXX Meta surface clipping is broken and requires some
* cairo-gstate.c rewriting. Work around it for now. */
- if (target->backend->intersect_clip_path == NULL)
- break;
-
- status = _cairo_surface_intersect_clip_path
- (target,
- command->intersect_clip_path.path_pointer,
- command->intersect_clip_path.fill_rule,
- command->intersect_clip_path.tolerance);
+ if (command->intersect_clip_path.path_pointer == NULL)
+ status = _cairo_clip_reset (&clip);
+ else
+ status = _cairo_clip_clip (&clip,
+ command->intersect_clip_path.path_pointer,
+ command->intersect_clip_path.fill_rule,
+ command->intersect_clip_path.tolerance,
+ command->intersect_clip_path.antialias,
+ target);
break;
case CAIRO_COMMAND_SHOW_GLYPHS:
+ status = _cairo_surface_set_clip (target, &clip);
+ if (status)
+ break;
+
status = _cairo_surface_show_glyphs
(command->show_glyphs.scaled_font,
command->show_glyphs.operator,
@@ -570,18 +544,38 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
break;
case CAIRO_COMMAND_FILL_PATH:
- /* XXX Meta surface fill_path is broken and requires some
- * cairo-gstate.c rewriting. Work around it for now. */
- if (target->backend->fill_path == NULL)
+ status = _cairo_surface_set_clip (target, &clip);
+ if (status)
break;
- status = _cairo_surface_fill_path
- (command->fill_path.operator,
- &command->fill_path.pattern.base,
- target,
- &command->fill_path.path,
- command->fill_path.fill_rule,
- command->fill_path.tolerance);
+ status = _cairo_surface_fill_path (command->fill_path.operator,
+ &command->fill_path.pattern.base,
+ target,
+ &command->fill_path.path,
+ command->fill_path.fill_rule,
+ command->fill_path.tolerance);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ break;
+
+ _cairo_traps_init (&traps);
+
+ status = _cairo_path_fixed_fill_to_traps (&command->fill_path.path,
+ command->fill_path.fill_rule,
+ command->fill_path.tolerance,
+ &traps);
+ if (status) {
+ _cairo_traps_fini (&traps);
+ break;
+ }
+
+ status = _cairo_surface_clip_and_composite_trapezoids (&command->fill_path.pattern.base,
+ command->fill_path.operator,
+ target,
+ &traps,
+ &clip,
+ command->fill_path.antialias);
+
+ _cairo_traps_fini (&traps);
break;
default:
@@ -592,5 +586,7 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
break;
}
+ _cairo_clip_fini (&clip);
+
return status;
}
diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c
index 17ef7e2c..afb4d428 100644
--- a/src/cairo-output-stream.c
+++ b/src/cairo-output-stream.c
@@ -39,6 +39,10 @@
#include <ctype.h>
#include "cairoint.h"
+#ifdef _MSC_VER
+#define snprintf _snprintf
+#endif /* _MSC_VER */
+
struct _cairo_output_stream {
cairo_write_func_t write_data;
void *closure;
diff --git a/src/cairo-path-data-private.h b/src/cairo-path-data-private.h
index d680f901..06ab187d 100644
--- a/src/cairo-path-data-private.h
+++ b/src/cairo-path-data-private.h
@@ -38,7 +38,7 @@
#include "cairoint.h"
-extern cairo_path_t cairo_path_nil;
+extern cairo_private const cairo_path_t _cairo_path_nil;
cairo_private cairo_path_t *
_cairo_path_data_create (cairo_path_fixed_t *path,
diff --git a/src/cairo-path-data.c b/src/cairo-path-data.c
index b3bd3123..11a0d0f0 100644
--- a/src/cairo-path-data.c
+++ b/src/cairo-path-data.c
@@ -37,7 +37,7 @@
#include "cairo-path-fixed-private.h"
#include "cairo-gstate-private.h"
-cairo_path_t cairo_path_nil = { CAIRO_STATUS_NO_MEMORY, NULL, 0 };
+const cairo_path_t _cairo_path_nil = { CAIRO_STATUS_NO_MEMORY, NULL, 0 };
/* Closure for path interpretation. */
typedef struct cairo_path_data_count {
@@ -346,7 +346,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_t*) &_cairo_path_nil;
path->num_data = _cairo_path_data_count (path, path_fixed,
gstate->tolerance, flatten);
@@ -354,7 +354,7 @@ _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_t*) &_cairo_path_nil;
}
path->status = CAIRO_STATUS_SUCCESS;
@@ -382,7 +382,7 @@ _cairo_path_data_create_real (cairo_path_fixed_t *path_fixed,
void
cairo_path_destroy (cairo_path_t *path)
{
- if (path == NULL || path == &cairo_path_nil)
+ if (path == NULL || path == &_cairo_path_nil)
return;
free (path->data);
diff --git a/src/cairo-path-fill.c b/src/cairo-path-fill.c
index c0015fc9..31b83ade 100644
--- a/src/cairo-path-fill.c
+++ b/src/cairo-path-fill.c
@@ -36,10 +36,8 @@
#include "cairoint.h"
-#include "cairo-gstate-private.h"
-
typedef struct cairo_filler {
- cairo_gstate_t *gstate;
+ double tolerance;
cairo_traps_t *traps;
cairo_point_t current_point;
@@ -48,7 +46,7 @@ typedef struct cairo_filler {
} cairo_filler_t;
static void
-_cairo_filler_init (cairo_filler_t *filler, cairo_gstate_t *gstate, cairo_traps_t *traps);
+_cairo_filler_init (cairo_filler_t *filler, double tolerance, cairo_traps_t *traps);
static void
_cairo_filler_fini (cairo_filler_t *filler);
@@ -69,9 +67,9 @@ static cairo_status_t
_cairo_filler_close_path (void *closure);
static void
-_cairo_filler_init (cairo_filler_t *filler, cairo_gstate_t *gstate, cairo_traps_t *traps)
+_cairo_filler_init (cairo_filler_t *filler, double tolerance, cairo_traps_t *traps)
{
- filler->gstate = gstate;
+ filler->tolerance = tolerance;
filler->traps = traps;
filler->current_point.x = 0;
@@ -132,7 +130,6 @@ _cairo_filler_curve_to (void *closure,
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_filler_t *filler = closure;
cairo_polygon_t *polygon = &filler->polygon;
- cairo_gstate_t *gstate = filler->gstate;
cairo_spline_t spline;
status = _cairo_spline_init (&spline, &filler->current_point, b, c, d);
@@ -140,7 +137,7 @@ _cairo_filler_curve_to (void *closure,
if (status == CAIRO_INT_STATUS_DEGENERATE)
return CAIRO_STATUS_SUCCESS;
- _cairo_spline_decompose (&spline, gstate->tolerance);
+ _cairo_spline_decompose (&spline, filler->tolerance);
if (status)
goto CLEANUP_SPLINE;
@@ -174,13 +171,14 @@ _cairo_filler_close_path (void *closure)
cairo_status_t
_cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,
- cairo_gstate_t *gstate,
+ cairo_fill_rule_t fill_rule,
+ double tolerance,
cairo_traps_t *traps)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_filler_t filler;
- _cairo_filler_init (&filler, gstate, traps);
+ _cairo_filler_init (&filler, tolerance, traps);
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
@@ -198,7 +196,7 @@ _cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,
status = _cairo_traps_tessellate_polygon (filler.traps,
&filler.polygon,
- filler.gstate->fill_rule);
+ fill_rule);
if (status)
goto BAIL;
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 1fb17217..ca93dde4 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -236,8 +236,7 @@ _cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern,
{
_cairo_pattern_init (&pattern->base, CAIRO_PATTERN_SURFACE);
- pattern->surface = surface;
- cairo_surface_reference (surface);
+ pattern->surface = cairo_surface_reference (surface);
}
static void
@@ -489,17 +488,21 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0,
* Increases the reference count on @pattern by one. This prevents
* @pattern from being destroyed until a matching call to
* cairo_pattern_destroy() is made.
+ *
+ * Return value: the referenced #cairo_pattern_t.
**/
-void
+cairo_pattern_t *
cairo_pattern_reference (cairo_pattern_t *pattern)
{
if (pattern == NULL)
- return;
+ return NULL;
if (pattern->ref_count == (unsigned int)-1)
- return;
+ return pattern;
pattern->ref_count++;
+
+ return pattern;
}
/**
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 485c1a0e..6b863721 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -159,7 +159,7 @@ _cairo_pdf_document_destroy (cairo_pdf_document_t *document);
static cairo_status_t
_cairo_pdf_document_finish (cairo_pdf_document_t *document);
-static void
+static cairo_pdf_document_t *
_cairo_pdf_document_reference (cairo_pdf_document_t *document);
static unsigned int
@@ -365,8 +365,7 @@ _cairo_pdf_surface_create_for_document (cairo_pdf_document_t *document,
surface->width = width;
surface->height = height;
- _cairo_pdf_document_reference (document);
- surface->document = document;
+ surface->document = _cairo_pdf_document_reference (document);
_cairo_array_init (&surface->streams, sizeof (cairo_pdf_stream_t *));
_cairo_array_init (&surface->patterns, sizeof (cairo_pdf_resource_t));
_cairo_array_init (&surface->xobjects, sizeof (cairo_pdf_resource_t));
@@ -1152,6 +1151,7 @@ static cairo_int_status_t
_cairo_pdf_surface_composite_trapezoids (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_dst,
+ cairo_antialias_t antialias,
int x_src,
int y_src,
int x_dst,
@@ -1335,7 +1335,8 @@ 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)
+ double tolerance,
+ cairo_antialias_t antialias)
{
cairo_pdf_surface_t *surface = dst;
cairo_pdf_document_t *document = surface->document;
@@ -1658,10 +1659,12 @@ _cairo_pdf_document_write_xref (cairo_pdf_document_t *document)
return offset;
}
-static void
+static cairo_pdf_document_t *
_cairo_pdf_document_reference (cairo_pdf_document_t *document)
{
document->ref_count++;
+
+ return document;
}
static void
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 0b2962c2..a897ed0e 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -272,6 +272,7 @@ static cairo_int_status_t
_cairo_ps_surface_composite_trapezoids (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_dst,
+ cairo_antialias_t antialias,
int x_src,
int y_src,
int x_dst,
@@ -286,6 +287,7 @@ _cairo_ps_surface_composite_trapezoids (cairo_operator_t operator,
return _cairo_surface_composite_trapezoids (operator,
pattern,
surface->current_page,
+ antialias,
x_src,
y_src,
x_dst,
@@ -324,14 +326,16 @@ static cairo_int_status_t
_cairo_ps_surface_intersect_clip_path (void *dst,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
- double tolerance)
+ double tolerance,
+ cairo_antialias_t antialias)
{
cairo_ps_surface_t *surface = dst;
return _cairo_surface_intersect_clip_path (surface->current_page,
path,
fill_rule,
- tolerance);
+ tolerance,
+ antialias);
}
static cairo_int_status_t
@@ -929,6 +933,7 @@ static cairo_int_status_t
_ps_output_composite_trapezoids (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_dst,
+ cairo_antialias_t antialias,
int x_src,
int y_src,
int x_dst,
@@ -1054,7 +1059,8 @@ static cairo_int_status_t
_ps_output_intersect_clip_path (void *abstract_surface,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
- double tolerance)
+ double tolerance,
+ cairo_antialias_t antialias)
{
ps_output_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->parent->stream;
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index af92c010..70f408a3 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -152,7 +152,8 @@ _cairo_quartz_surface_acquire_dest_image(void *abstract_surface,
image_rect->height = surface->image->height;
*image_out = surface->image;
- *image_extra = NULL;
+ if (image_extra)
+ *image_extra = NULL;
return CAIRO_STATUS_SUCCESS;
}
@@ -233,7 +234,7 @@ cairo_surface_t *cairo_quartz_surface_create(CGContextRef context,
surface = malloc(sizeof(cairo_quartz_surface_t));
if (surface == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
- return &_cairo_surface_nil;
+ return (cairo_surface_t*) &_cairo_surface_nil;
}
_cairo_surface_init(&surface->base, &cairo_quartz_surface_backend);
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 11fbc609..8353d329 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -245,18 +245,38 @@ _cairo_surface_get_clip_mode (cairo_surface_t *surface)
return CAIRO_CLIP_MODE_MASK;
}
-void
+/**
+ * cairo_surface_reference:
+ * @surface: a #cairo_surface_t
+ *
+ * Increases the reference count on @surface by one. This prevents
+ * @surface from being destroyed until a matching call to
+ * cairo_surface_destroy() is made.
+ *
+ * Return value: the referenced #cairo_surface_t.
+ **/
+cairo_surface_t *
cairo_surface_reference (cairo_surface_t *surface)
{
if (surface == NULL)
- return;
+ return NULL;
if (surface->ref_count == (unsigned int)-1)
- return;
+ return surface;
surface->ref_count++;
+
+ return surface;
}
+/**
+ * cairo_surface_destroy:
+ * @surface: a #cairo_t
+ *
+ * Decreases the reference count on @surface by one. If the result is
+ * zero, then @surface and all associated resources are freed. See
+ * cairo_surface_reference().
+ **/
void
cairo_surface_destroy (cairo_surface_t *surface)
{
@@ -310,7 +330,15 @@ cairo_surface_finish (cairo_surface_t *surface)
surface->finished = TRUE;
return;
}
-
+
+ if (!surface->status && surface->backend->flush) {
+ status = surface->backend->flush (surface);
+ if (status) {
+ _cairo_surface_set_error (surface, status);
+ return;
+ }
+ }
+
status = surface->backend->finish (surface);
if (status) {
_cairo_surface_set_error (surface, status);
@@ -393,6 +421,93 @@ cairo_surface_get_font_options (cairo_surface_t *surface,
}
/**
+ * cairo_surface_flush:
+ * @surface: a #cairo_surface_t
+ *
+ * Do any pending drawing for the surface and also restore any
+ * temporary modification's cairo has made to the surface's
+ * state. This function must be called before switching from
+ * drawing on the surface with cairo to drawing on it directly
+ * with native APIs. If the surface doesn't support direct access,
+ * then this function does nothing.
+ **/
+void
+cairo_surface_flush (cairo_surface_t *surface)
+{
+ if (surface->status) {
+ _cairo_surface_set_error (surface, surface->status);
+ return;
+ }
+
+ if (surface->finished) {
+ _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
+ return;
+ }
+
+ if (surface->backend->flush) {
+ cairo_status_t status;
+
+ status = surface->backend->flush (surface);
+
+ if (status)
+ _cairo_surface_set_error (surface, status);
+ }
+}
+
+/**
+ * cairo_surface_mark_dirty:
+ * @surface: a #cairo_surface_t
+ *
+ * Tells cairo that drawing has been done to surface using means other
+ * than cairo, and that cairo should reread any cached areas. Note
+ * that you must call cairo_surface_flush() before doing such drawing.
+ */
+void
+cairo_surface_mark_dirty (cairo_surface_t *surface)
+{
+ cairo_surface_mark_dirty_rectangle (surface, 0, 0, -1, -1);
+}
+
+/**
+ * cairo_surface_mark_dirty_rectangle:
+ * @surface: a #cairo_surface_t
+ * @x: X coordinate of dirty rectangle
+ * @y: Y coordinate of dirty rectangle
+ * @width: width of dirty rectangle
+ * @height: height of dirty rectangle
+ *
+ * Like cairo_surface_mark_dirty(), but drawing has been done only to
+ * the specified rectangle, so that cairo can retain cached contents
+ * for other parts of the surface.
+ */
+void
+cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ if (surface->status) {
+ _cairo_surface_set_error (surface, surface->status);
+ return;
+ }
+
+ if (surface->finished) {
+ _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
+ return;
+ }
+
+ if (surface->backend->mark_dirty_rectangle) {
+ cairo_status_t status;
+
+ status = surface->backend->mark_dirty_rectangle (surface, x, y, width, height);
+
+ if (status)
+ _cairo_surface_set_error (surface, status);
+ }
+}
+
+/**
* cairo_surface_set_device_offset:
* @surface: a #cairo_surface_t
* @x_offset: the offset in the X direction, in device units
@@ -876,6 +991,7 @@ static cairo_status_t
_fallback_composite_trapezoids (cairo_operator_t operator,
cairo_pattern_t *pattern,
cairo_surface_t *dst,
+ cairo_antialias_t antialias,
int src_x,
int src_y,
int dst_x,
@@ -928,6 +1044,7 @@ _fallback_composite_trapezoids (cairo_operator_t operator,
state.image->base.backend->composite_trapezoids (operator, pattern,
&state.image->base,
+ antialias,
src_x, src_y,
dst_x - state.image_rect.x,
dst_y - state.image_rect.y,
@@ -945,6 +1062,7 @@ cairo_status_t
_cairo_surface_composite_trapezoids (cairo_operator_t operator,
cairo_pattern_t *pattern,
cairo_surface_t *dst,
+ cairo_antialias_t antialias,
int src_x,
int src_y,
int dst_x,
@@ -965,6 +1083,7 @@ _cairo_surface_composite_trapezoids (cairo_operator_t operator,
if (dst->backend->composite_trapezoids) {
status = dst->backend->composite_trapezoids (operator,
pattern, dst,
+ antialias,
src_x, src_y,
dst_x, dst_y,
width, height,
@@ -974,6 +1093,7 @@ _cairo_surface_composite_trapezoids (cairo_operator_t operator,
}
return _fallback_composite_trapezoids (operator, pattern, dst,
+ antialias,
src_x, src_y,
dst_x, dst_y,
width, height,
@@ -1076,7 +1196,8 @@ _cairo_surface_reset_clip (cairo_surface_t *surface)
status = surface->backend->intersect_clip_path (surface,
NULL,
CAIRO_FILL_RULE_WINDING,
- 0);
+ 0,
+ CAIRO_ANTIALIAS_DEFAULT);
if (status)
return status;
}
@@ -1122,7 +1243,8 @@ cairo_int_status_t
_cairo_surface_intersect_clip_path (cairo_surface_t *surface,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
- double tolerance)
+ double tolerance,
+ cairo_antialias_t antialias)
{
if (surface->status)
return surface->status;
@@ -1135,7 +1257,8 @@ _cairo_surface_intersect_clip_path (cairo_surface_t *surface,
return surface->backend->intersect_clip_path (surface,
path,
fill_rule,
- tolerance);
+ tolerance,
+ antialias);
}
static cairo_status_t
@@ -1154,21 +1277,20 @@ _cairo_surface_set_clip_path_recursive (cairo_surface_t *surface,
return surface->backend->intersect_clip_path (surface,
&clip_path->path,
clip_path->fill_rule,
- clip_path->tolerance);
+ clip_path->tolerance,
+ clip_path->antialias);
}
/**
* _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
+ * @surface: the #cairo_surface_t to set the clip on
+ * @clip_path: the clip path to set
+ * @serial: the clip serial number associated with the clip path
*
- * Sets the clipping path to be the intersection of the current
- * clipping path of the surface and the given path.
+ * Sets the given clipping path for the surface and assigns the
+ * clipping serial to the surface.
**/
-cairo_status_t
+static cairo_status_t
_cairo_surface_set_clip_path (cairo_surface_t *surface,
cairo_clip_path_t *clip_path,
unsigned int serial)
@@ -1186,7 +1308,8 @@ _cairo_surface_set_clip_path (cairo_surface_t *surface,
status = surface->backend->intersect_clip_path (surface,
NULL,
CAIRO_FILL_RULE_WINDING,
- 0);
+ 0,
+ CAIRO_ANTIALIAS_DEFAULT);
if (status)
return status;
@@ -1199,6 +1322,27 @@ _cairo_surface_set_clip_path (cairo_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
+cairo_status_t
+_cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip)
+{
+ if (!surface)
+ return CAIRO_STATUS_NULL_POINTER;
+ if (clip->serial == _cairo_surface_get_current_clip_serial (surface))
+ return CAIRO_STATUS_SUCCESS;
+
+ if (clip->path)
+ return _cairo_surface_set_clip_path (surface,
+ clip->path,
+ clip->serial);
+
+ if (clip->region)
+ return _cairo_surface_set_clip_region (surface,
+ clip->region,
+ clip->serial);
+
+ return _cairo_surface_reset_clip (surface);
+}
+
/**
* _cairo_surface_get_extents:
* @surface: the #cairo_surface_t to fetch extents for
@@ -1260,3 +1404,154 @@ _cairo_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
return status;
}
+
+/**
+ * _cairo_surface_composite_fixup_unbounded:
+ * @dst: the destination surface
+ * @src_attr: source surface attributes (from _cairo_pattern_acquire_surface())
+ * @src_width: width of source surface
+ * @src_height: height of source surface
+ * @mask_attr: mask surface attributes or %NULL if no mask
+ * @mask_width: width of mask surface
+ * @mask_height: height of mask surface
+ * @src_x: @src_x from _cairo_surface_composite()
+ * @src_y: @src_y from _cairo_surface_composite()
+ * @mask_x: @mask_x from _cairo_surface_composite()
+ * @mask_y: @mask_y from _cairo_surface_composite()
+ * @dst_x: @dst_x from _cairo_surface_composite()
+ * @dst_y: @dst_y from _cairo_surface_composite()
+ * @width: @width from _cairo_surface_composite()
+ * @height: @height_x from _cairo_surface_composite()
+ *
+ * Eeek! Too many parameters! This is a helper function to take care of fixing
+ * up for bugs in libpixman and RENDER where, when asked to composite an
+ * untransformed surface with an unbounded operator (like CLEAR or SOURCE)
+ * only the region inside both the source and the mask is affected.
+ * This function clears the region that should have been drawn but was wasn't.
+ **/
+void
+_cairo_surface_composite_fixup_unbounded (cairo_surface_t *dst,
+ cairo_surface_attributes_t *src_attr,
+ int src_width,
+ int src_height,
+ cairo_surface_attributes_t *mask_attr,
+ int mask_width,
+ int mask_height,
+ int src_x,
+ int src_y,
+ int mask_x,
+ int mask_y,
+ int dst_x,
+ int dst_y,
+ unsigned int width,
+ unsigned int height)
+{
+ cairo_bool_t have_src = TRUE;
+ cairo_bool_t have_mask = mask_attr != NULL;
+ cairo_rectangle_t dst_rectangle;
+ cairo_rectangle_t drawn_rectangle;
+ cairo_rectangle_t rects[4];
+ int num_rects = 0;
+
+ /* The RENDER/libpixman operators are clipped to the bounds of the untransformed,
+ * non-repeating sources and masks. Other sources and masks can be ignored.
+ */
+ if (!_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL) ||
+ src_attr->extend != CAIRO_EXTEND_NONE)
+ have_src = FALSE;
+
+ if (have_mask &&
+ (!_cairo_matrix_is_integer_translation (&mask_attr->matrix, NULL, NULL) ||
+ mask_attr->extend != CAIRO_EXTEND_NONE))
+ have_mask = FALSE;
+
+ /* The area that was drawn is the area in the destination rectangle but not within
+ * the source or the mask.
+ */
+ dst_rectangle.x = dst_x;
+ dst_rectangle.y = dst_y;
+ dst_rectangle.width = width;
+ dst_rectangle.height = height;
+
+ drawn_rectangle = dst_rectangle;
+
+ if (have_src) {
+ cairo_rectangle_t src_rectangle;
+
+ src_rectangle.x = (dst_x - (src_x + src_attr->x_offset));
+ src_rectangle.y = (dst_y - (src_y + src_attr->y_offset));
+ src_rectangle.width = src_width;
+ src_rectangle.height = src_height;
+
+ _cairo_rectangle_intersect (&drawn_rectangle, &src_rectangle);
+ }
+
+ if (have_mask) {
+ cairo_rectangle_t mask_rectangle;
+
+ mask_rectangle.x = (dst_x - (mask_x + mask_attr->x_offset));
+ mask_rectangle.y = (dst_y - (mask_y + mask_attr->y_offset));
+ mask_rectangle.width = mask_width;
+ mask_rectangle.height = mask_height;
+
+ _cairo_rectangle_intersect (&drawn_rectangle, &mask_rectangle);
+ }
+
+ /* Now compute the area that is in dst_rectangle but not in drawn_rectangle;
+ * this is the area we must clear; This computation could be done with
+ * regions, but the clumsiness of the libpixman API makes this easier.
+ */
+ if (drawn_rectangle.width == 0 || drawn_rectangle.height == 0)
+ {
+ rects[num_rects].x = dst_rectangle.x;
+ rects[num_rects].y = dst_rectangle.y;
+ rects[num_rects].width = dst_rectangle.width;
+ rects[num_rects].height = dst_rectangle.height;
+
+ num_rects++;
+ }
+ else
+ {
+ if (dst_rectangle.y < drawn_rectangle.y) {
+ rects[num_rects].x = dst_rectangle.x;
+ rects[num_rects].y = dst_rectangle.y;
+ rects[num_rects].width = dst_rectangle.width;
+ rects[num_rects].height = drawn_rectangle.y - dst_rectangle.y;
+
+ num_rects++;
+ }
+
+ if (dst_rectangle.x < drawn_rectangle.x) {
+ rects[num_rects].x = dst_rectangle.x;
+ rects[num_rects].y = drawn_rectangle.y;
+ rects[num_rects].width = drawn_rectangle.x - dst_rectangle.x;
+ rects[num_rects].height = drawn_rectangle.height;
+
+ num_rects++;
+ }
+
+ if (dst_rectangle.x + dst_rectangle.width > drawn_rectangle.x + drawn_rectangle.width) {
+ rects[num_rects].x = drawn_rectangle.x + drawn_rectangle.width;
+ rects[num_rects].y = drawn_rectangle.y;
+ rects[num_rects].width = (dst_rectangle.x + dst_rectangle.width) - (drawn_rectangle.x + drawn_rectangle.width);
+ rects[num_rects].height = drawn_rectangle.height;
+
+ num_rects++;
+ }
+
+ if (dst_rectangle.y + dst_rectangle.height > drawn_rectangle.y + drawn_rectangle.height) {
+ rects[num_rects].x = dst_rectangle.x;
+ rects[num_rects].y = drawn_rectangle.y + drawn_rectangle.height;
+ rects[num_rects].width = dst_rectangle.width;
+ rects[num_rects].height = (dst_rectangle.y + dst_rectangle.height) - (drawn_rectangle.y + drawn_rectangle.height);
+
+ num_rects++;
+ }
+ }
+
+ if (num_rects > 0) {
+ _cairo_surface_fill_rectangles (dst, CAIRO_OPERATOR_SOURCE, CAIRO_COLOR_TRANSPARENT,
+ rects, num_rects);
+ }
+}
+
diff --git a/src/cairo-traps.c b/src/cairo-traps.c
index a97d5848..18b944c1 100644
--- a/src/cairo-traps.c
+++ b/src/cairo-traps.c
@@ -229,6 +229,35 @@ _compare_point_fixed_by_y (const void *av, const void *bv)
return ret;
}
+void
+_cairo_traps_translate (cairo_traps_t *traps, int x, int y)
+{
+ cairo_fixed_t xoff, yoff;
+ cairo_trapezoid_t *t;
+ int i;
+
+ /* Ugh. The cairo_composite/(Render) interface doesn't allow
+ an offset for the trapezoids. Need to manually shift all
+ the coordinates to align with the offset origin of the
+ intermediate surface. */
+
+ xoff = _cairo_fixed_from_int (x);
+ yoff = _cairo_fixed_from_int (y);
+
+ for (i = 0, t = traps->traps; i < traps->num_traps; i++, t++) {
+ t->top += yoff;
+ t->bottom += yoff;
+ t->left.p1.x += xoff;
+ t->left.p1.y += yoff;
+ t->left.p2.x += xoff;
+ t->left.p2.y += yoff;
+ t->right.p1.x += xoff;
+ t->right.p1.y += yoff;
+ t->right.p2.x += xoff;
+ t->right.p2.y += yoff;
+ }
+}
+
cairo_status_t
_cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3])
{
diff --git a/src/cairo-wideint.c b/src/cairo-wideint.c
index 60946d90..9e4914e6 100644
--- a/src/cairo-wideint.c
+++ b/src/cairo-wideint.c
@@ -1,5 +1,5 @@
/*
- * $Id: cairo-wideint.c,v 1.5 2005-06-03 21:51:57 cworth Exp $
+ * $Id: cairo-wideint.c,v 1.6 2005-07-30 19:57:54 keithp Exp $
*
* Copyright © 2004 Keith Packard
*
@@ -36,22 +36,6 @@
#include "cairoint.h"
-#if !HAVE_UINT64_T || !HAVE_UINT128_T
-
-static const unsigned char top_bit[256] =
-{
- 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-};
-
-#endif
-
#if HAVE_UINT64_T
#define _cairo_uint32s_to_uint64(h,l) ((uint64_t) (h) << 32 | (l))
@@ -157,7 +141,8 @@ _cairo_uint32x32_64_mul (uint32_t a, uint32_t b)
cairo_int64_t
_cairo_int32x32_64_mul (int32_t a, int32_t b)
{
- s = _cairo_uint32x32_64_mul ((uint32_t) a, (uint32_t b));
+ cairo_int64_t s;
+ s = _cairo_uint32x32_64_mul ((uint32_t) a, (uint32_t) b);
if (a < 0)
s.hi -= b;
if (b < 0)
@@ -270,200 +255,38 @@ _cairo_uint64_negate (cairo_uint64_t a)
}
/*
- * The design of this algorithm comes from GCC,
- * but the actual implementation is new
+ * Simple bit-at-a-time divide.
*/
-
-static const int
-_cairo_leading_zeros32 (uint32_t i)
-{
- int top;
-
- if (i < 0x100)
- top = 0;
- else if (i < 0x10000)
- top = 8;
- else if (i < 0x1000000)
- top = 16;
- else
- top = 24;
- top = top + top_bit [i >> top];
- return 32 - top;
-}
-
-typedef struct _cairo_uquorem32_t {
- uint32_t quo;
- uint32_t rem;
-} cairo_uquorem32_t;
-
-/*
- * den >= num.hi
- */
-static const cairo_uquorem32_t
-_cairo_uint64x32_normalized_divrem (cairo_uint64_t num, uint32_t den)
-{
- cairo_uquorem32_t qr;
- uint32_t q0, q1, r0, r1;
- uint16_t d0, d1;
- uint32_t t;
-
- d0 = den & 0xffff;
- d1 = den >> 16;
-
- q1 = num.hi / d1;
- r1 = num.hi % d1;
-
- t = q1 * d0;
- r1 = (r1 << 16) | (num.lo >> 16);
- if (r1 < t)
- {
- q1--;
- r1 += den;
- if (r1 >= den && r1 < t)
- {
- q1--;
- r1 += den;
- }
- }
-
- r1 -= t;
-
- q0 = r1 / d1;
- r0 = r1 % d1;
- t = q0 * d0;
- r0 = (r0 << 16) | (num.lo & 0xffff);
- if (r0 < t)
- {
- q0--;
- r0 += den;
- if (r0 >= den && r0 < t)
- {
- q0--;
- r0 += den;
- }
- }
- r0 -= t;
- qr.quo = (q1 << 16) | q0;
- qr.rem = r0;
- return qr;
-}
-
cairo_uquorem64_t
_cairo_uint64_divrem (cairo_uint64_t num, cairo_uint64_t den)
{
- cairo_uquorem32_t qr32;
cairo_uquorem64_t qr;
- int norm;
- uint32_t q1, q0, r1, r0;
-
- if (den.hi == 0)
+ cairo_uint64_t bit;
+ cairo_uint64_t quo;
+
+ bit = _cairo_uint32_to_uint64 (1);
+
+ /* normalize to make den >= num, but not overflow */
+ while (_cairo_uint64_lt (den, num) && (den.hi & 0x80000000) == 0)
{
- if (den.lo > num.hi)
- {
- /* 0q = nn / 0d */
-
- norm = _cairo_leading_zeros32 (den.lo);
- if (norm)
- {
- den.lo <<= norm;
- num = _cairo_uint64_lsl (num, norm);
- }
- q1 = 0;
- }
- else
- {
- /* qq = NN / 0d */
-
- if (den.lo == 0)
- den.lo = 1 / den.lo;
-
- norm = _cairo_leading_zeros32 (den.lo);
- if (norm)
- {
- cairo_uint64_t num1;
- den.lo <<= norm;
- num1 = _cairo_uint64_rsl (num, 32 - norm);
- qr32 = _cairo_uint64x32_normalized_divrem (num1, den.lo);
- q1 = qr32.quo;
- num.hi = qr32.rem;
- num.lo <<= norm;
- }
- else
- {
- num.hi -= den.lo;
- q1 = 1;
- }
- }
- qr32 = _cairo_uint64x32_normalized_divrem (num, den.lo);
- q0 = qr32.quo;
- r1 = 0;
- r0 = qr32.rem >> norm;
+ bit = _cairo_uint64_lsl (bit, 1);
+ den = _cairo_uint64_lsl (den, 1);
}
- else
+ quo = _cairo_uint32_to_uint64 (0);
+
+ /* generate quotient, one bit at a time */
+ while (bit.hi | bit.lo)
{
- if (den.hi > num.hi)
- {
- /* 00 = nn / DD */
- q0 = q1 = 0;
- r0 = num.lo;
- r1 = num.hi;
- }
- else
+ if (_cairo_uint64_le (den, num))
{
- /* 0q = NN / dd */
-
- norm = _cairo_leading_zeros32 (den.hi);
- if (norm == 0)
- {
- if (num.hi > den.hi || num.lo >= den.lo)
- {
- q0 = 1;
- num = _cairo_uint64_sub (num, den);
- }
- else
- {
- q0 = 0;
- }
-
- q1 = 0;
- r0 = num.lo;
- r1 = num.hi;
- }
- else
- {
- cairo_uint64_t num1;
- cairo_uint64_t part;
-
- num1 = _cairo_uint64_rsl (num, 32 - norm);
- den = _cairo_uint64_lsl (den, norm);
-
- qr32 = _cairo_uint64x32_normalized_divrem (num1, den.hi);
- part = _cairo_uint32x32_64_mul (qr32.quo, den.lo);
-
- q0 = qr32.quo;
-
- num.lo <<= norm;
- num.hi = qr32.rem;
-
- if (_cairo_uint64_gt (part, num))
- {
- q0--;
- part = _cairo_uint64_sub (part, den);
- }
-
- q1 = 0;
-
- num = _cairo_uint64_sub (num, part);
- num = _cairo_uint64_rsl (num, norm);
- r0 = num.lo;
- r1 = num.hi;
- }
+ num = _cairo_uint64_sub (num, den);
+ quo = _cairo_uint64_add (quo, bit);
}
+ bit = _cairo_uint64_rsl (bit, 1);
+ den = _cairo_uint64_rsl (den, 1);
}
- qr.quo.lo = q0;
- qr.quo.hi = q1;
- qr.rem.lo = r0;
- qr.rem.hi = r1;
+ qr.quo = quo;
+ qr.rem = num;
return qr;
}
@@ -754,234 +577,42 @@ _cairo_uint128_eq (cairo_uint128_t a, cairo_uint128_t b)
_cairo_uint64_eq (a.lo, b.lo));
}
-/*
- * The design of this algorithm comes from GCC,
- * but the actual implementation is new
- */
-
-/*
- * den >= num.hi
- */
-static cairo_uquorem64_t
-_cairo_uint128x64_normalized_divrem (cairo_uint128_t num, cairo_uint64_t den)
-{
- cairo_uquorem64_t qr64;
- cairo_uquorem64_t qr;
- uint32_t q0, q1;
- cairo_uint64_t r0, r1;
- uint32_t d0, d1;
- cairo_uint64_t t;
-
- d0 = uint64_lo32 (den);
- d1 = uint64_hi32 (den);
-
- qr64 = _cairo_uint64_divrem (num.hi, _cairo_uint32_to_uint64 (d1));
- q1 = _cairo_uint64_to_uint32 (qr64.quo);
- r1 = qr64.rem;
-
- t = _cairo_uint32x32_64_mul (q1, d0);
-
- r1 = _cairo_uint64_add (_cairo_uint64_lsl (r1, 32),
- _cairo_uint64_rsl (num.lo, 32));
-
- if (_cairo_uint64_lt (r1, t))
- {
- q1--;
- r1 = _cairo_uint64_add (r1, den);
- if (_cairo_uint64_ge (r1, den) && _cairo_uint64_lt (r1, t))
- {
- q1--;
- r1 = _cairo_uint64_add (r1, den);
- }
- }
-
- r1 = _cairo_uint64_sub (r1, t);
-
- qr64 = _cairo_uint64_divrem (r1, _cairo_uint32_to_uint64 (d1));
-
- q0 = _cairo_uint64_to_uint32 (qr64.quo);
- r0 = qr64.rem;
-
- t = _cairo_uint32x32_64_mul (q0, d0);
-
- r0 = _cairo_uint64_add (_cairo_uint64_lsl (r0, 32),
- _cairo_uint32_to_uint64 (_cairo_uint64_to_uint32 (num.lo)));
- if (_cairo_uint64_lt (r0, t))
- {
- q0--;
- r0 = _cairo_uint64_add (r0, den);
- if (_cairo_uint64_ge (r0, den) && _cairo_uint64_lt (r0, t))
- {
- q0--;
- r0 = _cairo_uint64_add (r0, den);
- }
- }
-
- r0 = _cairo_uint64_sub (r0, t);
-
- qr.quo = _cairo_uint32s_to_uint64 (q1, q0);
- qr.rem = r0;
- return qr;
-}
-
#if HAVE_UINT64_T
-
-static int
-_cairo_leading_zeros64 (cairo_uint64_t q)
-{
- int top = 0;
-
- if (q >= (uint64_t) 0x10000 << 16)
- {
- top += 32;
- q >>= 32;
- }
- if (q >= (uint64_t) 0x10000)
- {
- top += 16;
- q >>= 16;
- }
- if (q >= (uint64_t) 0x100)
- {
- top += 8;
- q >>= 8;
- }
- top += top_bit [q];
- return 64 - top;
-}
-
+#define _cairo_msbset64(q) (q & ((uint64_t) 1 << 63))
#else
-
-static const int
-_cairo_leading_zeros64 (cairo_uint64_t d)
-{
- if (d.hi)
- return _cairo_leading_zeros32 (d.hi);
- else
- return 32 + _cairo_leading_zeros32 (d.lo);
-}
-
+#define _cairo_msbset64(q) (q.hi & ((uint32_t) 1 << 31))
#endif
cairo_uquorem128_t
_cairo_uint128_divrem (cairo_uint128_t num, cairo_uint128_t den)
{
- cairo_uquorem64_t qr64;
cairo_uquorem128_t qr;
- int norm;
- cairo_uint64_t q1, q0, r1, r0;
-
- if (_cairo_uint64_eq (den.hi, _cairo_uint32_to_uint64 (0)))
+ cairo_uint128_t bit;
+ cairo_uint128_t quo;
+
+ bit = _cairo_uint32_to_uint128 (1);
+
+ /* normalize to make den >= num, but not overflow */
+ while (_cairo_uint128_lt (den, num) && !_cairo_msbset64(den.hi))
{
- if (_cairo_uint64_gt (den.lo, num.hi))
- {
- /* 0q = nn / 0d */
-
- norm = _cairo_leading_zeros64 (den.lo);
- if (norm)
- {
- den.lo = _cairo_uint64_lsl (den.lo, norm);
- num = _cairo_uint128_lsl (num, norm);
- }
- q1 = _cairo_uint32_to_uint64 (0);
- }
- else
- {
- /* qq = NN / 0d */
-
- if (_cairo_uint64_eq (den.lo, _cairo_uint32_to_uint64 (0)))
- den.lo = _cairo_uint64_divrem (_cairo_uint32_to_uint64 (1),
- den.lo).quo;
-
- norm = _cairo_leading_zeros64 (den.lo);
- if (norm)
- {
- cairo_uint128_t num1;
-
- den.lo = _cairo_uint64_lsl (den.lo, norm);
- num1 = _cairo_uint128_rsl (num, 64 - norm);
- qr64 = _cairo_uint128x64_normalized_divrem (num1, den.lo);
- q1 = qr64.quo;
- num.hi = qr64.rem;
- num.lo = _cairo_uint64_lsl (num.lo, norm);
- }
- else
- {
- num.hi = _cairo_uint64_sub (num.hi, den.lo);
- q1 = _cairo_uint32_to_uint64 (1);
- }
- }
- qr64 = _cairo_uint128x64_normalized_divrem (num, den.lo);
- q0 = qr64.quo;
- r1 = _cairo_uint32_to_uint64 (0);
- r0 = _cairo_uint64_rsl (qr64.rem, norm);
+ bit = _cairo_uint128_lsl (bit, 1);
+ den = _cairo_uint128_lsl (den, 1);
}
- else
+ quo = _cairo_uint32_to_uint128 (0);
+
+ /* generate quotient, one bit at a time */
+ while (_cairo_uint128_ne (bit, _cairo_uint32_to_uint128(0)))
{
- if (_cairo_uint64_gt (den.hi, num.hi))
- {
- /* 00 = nn / DD */
- q0 = q1 = _cairo_uint32_to_uint64 (0);
- r0 = num.lo;
- r1 = num.hi;
- }
- else
+ if (_cairo_uint128_le (den, num))
{
- /* 0q = NN / dd */
-
- norm = _cairo_leading_zeros64 (den.hi);
- if (norm == 0)
- {
- if (_cairo_uint64_gt (num.hi, den.hi) ||
- _cairo_uint64_ge (num.lo, den.lo))
- {
- q0 = _cairo_uint32_to_uint64 (1);
- num = _cairo_uint128_sub (num, den);
- }
- else
- {
- q0 = _cairo_uint32_to_uint64 (0);
- }
-
- q1 = _cairo_uint32_to_uint64 (0);
- r0 = num.lo;
- r1 = num.hi;
- }
- else
- {
- cairo_uint128_t num1;
- cairo_uint128_t part;
-
- num1 = _cairo_uint128_rsl (num, 64 - norm);
- den = _cairo_uint128_lsl (den, norm);
-
- qr64 = _cairo_uint128x64_normalized_divrem (num1, den.hi);
- part = _cairo_uint64x64_128_mul (qr64.quo, den.lo);
-
- q0 = qr64.quo;
-
- num.lo = _cairo_uint64_lsl (num.lo, norm);
- num.hi = qr64.rem;
-
- if (_cairo_uint128_gt (part, num))
- {
- q0 = _cairo_uint64_sub (q0, _cairo_uint32_to_uint64 (1));
- part = _cairo_uint128_sub (part, den);
- }
-
- q1 = _cairo_uint32_to_uint64 (0);
-
- num = _cairo_uint128_sub (num, part);
- num = _cairo_uint128_rsl (num, norm);
- r0 = num.lo;
- r1 = num.hi;
- }
+ num = _cairo_uint128_sub (num, den);
+ quo = _cairo_uint128_add (quo, bit);
}
+ bit = _cairo_uint128_rsl (bit, 1);
+ den = _cairo_uint128_rsl (den, 1);
}
- qr.quo.lo = q0;
- qr.quo.hi = q1;
- qr.rem.lo = r0;
- qr.rem.hi = r1;
+ qr.quo = quo;
+ qr.rem = num;
return qr;
}
diff --git a/src/cairo-wideint.h b/src/cairo-wideint.h
index 3afea5a6..b008b5d5 100644
--- a/src/cairo-wideint.h
+++ b/src/cairo-wideint.h
@@ -1,5 +1,5 @@
/*
- * $Id: cairo-wideint.h,v 1.10 2005-05-10 19:42:32 cworth Exp $
+ * $Id: cairo-wideint.h,v 1.12 2005-08-05 14:48:19 cworth Exp $
*
* Copyright © 2004 Keith Packard
*
@@ -44,6 +44,18 @@
# include <inttypes.h>
#elif HAVE_SYS_INT_TYPES_H
# include <sys/int_types.h>
+#elif defined(_MSC_VER)
+ typedef __int8 int8_t;
+ typedef unsigned __int8 uint8_t;
+ typedef __int16 int16_t;
+ typedef unsigned __int16 uint16_t;
+ typedef __int32 int32_t;
+ typedef unsigned __int32 uint32_t;
+ typedef __int64 int64_t;
+ typedef unsigned __int64 uint64_t;
+# ifndef HAVE_UINT64_T
+# define HAVE_UINT64_T 1
+# endif
#else
#error Cannot find definitions for fixed-width integral types (uint8_t, uint32_t, etc.)
#endif
@@ -85,7 +97,7 @@ cairo_int64_t I _cairo_int32_to_int64(int32_t i);
#define _cairo_int64_add(a,b) _cairo_uint64_add (a,b)
#define _cairo_int64_sub(a,b) _cairo_uint64_sub (a,b)
#define _cairo_int64_mul(a,b) _cairo_uint64_mul (a,b)
-int I _cairo_int32x32_64_mul (int32_t a, int32_t b);
+cairo_int64_t I _cairo_int32x32_64_mul (int32_t a, int32_t b);
int I _cairo_int64_lt (cairo_uint64_t a, cairo_uint64_t b);
#define _cairo_int64_eq(a,b) _cairo_uint64_eq (a,b)
#define _cairo_int64_lsl(a,b) _cairo_uint64_lsl (a,b)
@@ -208,7 +220,7 @@ cairo_int128_t I _cairo_int64_to_int128 (cairo_int64_t i);
#define _cairo_int128_add(a,b) _cairo_uint128_add(a,b)
#define _cairo_int128_sub(a,b) _cairo_uint128_sub(a,b)
#define _cairo_int128_mul(a,b) _cairo_uint128_mul(a,b)
-cairo_uint128_t I _cairo_int64x64_128_mul (cairo_int64_t a, cairo_int64_t b);
+cairo_int128_t I _cairo_int64x64_128_mul (cairo_int64_t a, cairo_int64_t b);
#define _cairo_int128_lsl(a,b) _cairo_uint128_lsl(a,b)
#define _cairo_int128_rsl(a,b) _cairo_uint128_rsl(a,b)
#define _cairo_int128_rsa(a,b) _cairo_uint128_rsa(a,b)
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 15dd96b3..4867fc0f 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -58,7 +58,6 @@ typedef struct {
cairo_scaled_font_t base;
LOGFONTW logfont;
- cairo_font_options_t options;
BYTE quality;
@@ -227,7 +226,6 @@ _win32_scaled_font_create (LOGFONTW *logfont,
return NULL;
f->logfont = *logfont;
- f->options = *options;
/* We don't have any control over the hinting style or subpixel
* order in the Win32 font API, so we ignore those parts of
@@ -263,7 +261,7 @@ _win32_scaled_font_create (LOGFONTW *logfont,
cairo_matrix_multiply (&scale, font_matrix, ctm);
_compute_transform (f, &scale);
- _cairo_scaled_font_init (&f->base, font_matrix, ctm, &cairo_win32_scaled_font_backend);
+ _cairo_scaled_font_init (&f->base, font_matrix, ctm, options, &cairo_win32_scaled_font_backend);
return &f->base;
}
@@ -429,13 +427,11 @@ _cairo_win32_scaled_font_done_unscaled_font (cairo_scaled_font_t *scaled_font)
/* implement the font backend interface */
static cairo_status_t
-_cairo_win32_scaled_font_create (const char *family,
- cairo_font_slant_t slant,
- cairo_font_weight_t weight,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm,
- const cairo_font_options_t *options,
- cairo_scaled_font_t **scaled_font_out)
+_cairo_win32_scaled_font_create_toy (const cairo_toy_font_face_t *toy_face,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ const cairo_font_options_t *options,
+ cairo_scaled_font_t **scaled_font_out)
{
LOGFONTW logfont;
cairo_scaled_font_t *scaled_font;
@@ -443,7 +439,8 @@ _cairo_win32_scaled_font_create (const char *family,
int face_name_len;
cairo_status_t status;
- status = _cairo_utf8_to_utf16 (family, -1, &face_name, &face_name_len);
+ status = _cairo_utf8_to_utf16 (toy_face->family, -1,
+ &face_name, &face_name_len);
if (status)
return status;
@@ -460,7 +457,7 @@ _cairo_win32_scaled_font_create (const char *family,
logfont.lfEscapement = 0; /* filled in later */
logfont.lfOrientation = 0; /* filled in later */
- switch (weight) {
+ switch (toy_face->weight) {
case CAIRO_FONT_WEIGHT_NORMAL:
default:
logfont.lfWeight = FW_NORMAL;
@@ -470,7 +467,7 @@ _cairo_win32_scaled_font_create (const char *family,
break;
}
- switch (slant) {
+ switch (toy_face->slant) {
case CAIRO_FONT_SLANT_NORMAL:
default:
logfont.lfItalic = FALSE;
@@ -506,7 +503,7 @@ _cairo_win32_scaled_font_create (const char *family,
}
static void
-_cairo_win32_scaled_font_destroy (void *abstract_font)
+_cairo_win32_scaled_font_fini (void *abstract_font)
{
cairo_win32_scaled_font_t *scaled_font = abstract_font;
@@ -1059,7 +1056,6 @@ _cairo_win32_scaled_font_show_glyphs (void *abstract_font,
*/
COLORREF new_color;
- /* XXX Use the unpremultiplied or premultiplied color? */
new_color = RGB (((int)solid_pattern->color.red_short) >> 8,
((int)solid_pattern->color.green_short) >> 8,
((int)solid_pattern->color.blue_short) >> 8);
@@ -1274,15 +1270,15 @@ FAIL:
}
const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend = {
- _cairo_win32_scaled_font_create,
- _cairo_win32_scaled_font_destroy,
+ _cairo_win32_scaled_font_create_toy,
+ _cairo_win32_scaled_font_fini,
_cairo_win32_scaled_font_font_extents,
_cairo_win32_scaled_font_text_to_glyphs,
_cairo_win32_scaled_font_glyph_extents,
_cairo_win32_scaled_font_glyph_bbox,
_cairo_win32_scaled_font_show_glyphs,
_cairo_win32_scaled_font_glyph_path,
- _cairo_win32_scaled_font_get_glyph_cache_key,
+ _cairo_win32_scaled_font_get_glyph_cache_key
};
/* cairo_win32_font_face_t */
@@ -1302,11 +1298,11 @@ _cairo_win32_font_face_destroy (void *abstract_face)
}
static cairo_status_t
-_cairo_win32_font_face_create_font (void *abstract_face,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm,
- const cairo_font_options_t *options,
- cairo_scaled_font_t **font)
+_cairo_win32_font_face_scaled_font_create (void *abstract_face,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ const cairo_font_options_t *options,
+ cairo_scaled_font_t **font)
{
cairo_win32_font_face_t *font_face = abstract_face;
@@ -1320,7 +1316,7 @@ _cairo_win32_font_face_create_font (void *abstract_face,
static const cairo_font_face_backend_t _cairo_win32_font_face_backend = {
_cairo_win32_font_face_destroy,
- _cairo_win32_font_face_create_font,
+ _cairo_win32_font_face_scaled_font_create
};
/**
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index f9201245..95c37d99 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -340,8 +340,9 @@ _cairo_win32_surface_finish (void *abstract_surface)
if (surface->image)
cairo_surface_destroy (surface->image);
- if (surface->saved_clip)
+ if (surface->saved_clip) {
DeleteObject (surface->saved_clip);
+ }
/* If we created the Bitmap and DC, destroy them */
if (surface->bitmap) {
@@ -792,7 +793,6 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface,
surface->set_clip = 0;
}
-
return CAIRO_STATUS_SUCCESS;
} else {
@@ -893,6 +893,12 @@ _cairo_win32_surface_get_extents (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
+static cairo_status_t
+_cairo_win32_surface_flush (void *abstract_surface)
+{
+ return _cairo_surface_reset_clip (abstract_surface);
+}
+
cairo_surface_t *
cairo_win32_surface_create (HDC hdc)
{
@@ -964,5 +970,9 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = {
_cairo_win32_surface_set_clip_region,
NULL, /* intersect_clip_path */
_cairo_win32_surface_get_extents,
- NULL /* show_glyphs */
+ NULL, /* show_glyphs */
+ NULL, /* fill_path */
+ NULL, /* get_font_options */
+ _cairo_win32_surface_flush,
+ NULL /* mark_dirty_rectangle */
};
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index b743cf4d..2a7395f6 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -643,8 +643,7 @@ _cairo_xcb_surface_clone_similar (void *abstract_surface,
cairo_xcb_surface_t *xcb_src = (cairo_xcb_surface_t *)src;
if (xcb_src->dpy == surface->dpy) {
- *clone_out = src;
- cairo_surface_reference (src);
+ *clone_out = cairo_surface_reference (src);
return CAIRO_STATUS_SUCCESS;
}
@@ -943,6 +942,7 @@ static cairo_int_status_t
_cairo_xcb_surface_composite_trapezoids (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_dst,
+ cairo_antialias_t antialias,
int src_x,
int src_y,
int dst_x,
@@ -981,9 +981,17 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t operator,
render_src_x = src_x + render_reference_x - dst_x;
render_src_y = src_y + render_reference_y - dst_y;
+ switch (antialias) {
+ case CAIRO_ANTIALIAS_NONE:
+ render_format = _format_from_cairo (dst->dpy, CAIRO_FORMAT_A1),
+ break;
+ default:
+ render_format = _format_from_cairo (dst->dpy, CAIRO_FORMAT_A8),
+ break;
+ }
+
/* XXX: The XTrapezoid cast is evil and needs to go away somehow. */
/* 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 (status == CAIRO_STATUS_SUCCESS)
XCBRenderTrapezoids (dst->dpy,
diff --git a/src/cairo-xlib-screen.c b/src/cairo-xlib-screen.c
index 6a4efdbd..e71d10ec 100644
--- a/src/cairo-xlib-screen.c
+++ b/src/cairo-xlib-screen.c
@@ -245,34 +245,59 @@ _cairo_xlib_init_screen_font_options (cairo_xlib_screen_info_t *info)
CAIRO_MUTEX_DECLARE(_xlib_screen_mutex);
-static cairo_xlib_screen_info_t *_cairo_xlib_screen_list;
+static cairo_xlib_screen_info_t *_cairo_xlib_screen_list = NULL;
static int
_cairo_xlib_close_display (Display *dpy, XExtCodes *codes)
{
- cairo_xlib_screen_info_t *info;
- cairo_xlib_screen_info_t **prev;
+ cairo_xlib_screen_info_t *info, *prev;
/*
* Unhook from the global list
*/
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
- for (prev = &_cairo_xlib_screen_list; (info = *prev); prev = &(*prev)->next) {
+ prev = NULL;
+ for (info = _cairo_xlib_screen_list; info; info = info->next) {
if (info->display == dpy) {
- *prev = info->next;
+ if (prev)
+ prev->next = info->next;
+ else
+ _cairo_xlib_screen_list = info->next;
free (info);
- if (!*prev)
- break;
+ break;
}
+ prev = info;
}
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
-
+
+ /* Return value in accordance with requirements of
+ * XESetCloseDisplay */
return 0;
}
+static void
+_cairo_xlib_screen_info_reset (void)
+{
+ cairo_xlib_screen_info_t *info, *next;
+
+ /*
+ * Delete everything in the list.
+ */
+ CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
+
+ for (info = _cairo_xlib_screen_list; info; info = next) {
+ next = info->next;
+ free (info);
+ }
+
+ _cairo_xlib_screen_list = NULL;
+
+ CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
+
+}
-cairo_private cairo_xlib_screen_info_t *
+cairo_xlib_screen_info_t *
_cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
{
cairo_xlib_screen_info_t *info;
@@ -344,3 +369,13 @@ _cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
return info;
}
+void
+_cairo_xlib_screen_reset_static_data (void)
+{
+ _cairo_xlib_screen_info_reset ();
+
+#if HAVE_XRMFINALIZE
+ XrmFinalize ();
+#endif
+
+}
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 5f26a2f4..7f4b8489 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -91,6 +91,14 @@ struct _cairo_xlib_surface {
*
* We can't test for this because it depends on whether the
* picture is in video memory or not.
+ *
+ * We also use this variable as a guard against a second
+ * independent bug with transformed repeating pictures:
+ *
+ * http://lists.freedesktop.org/archives/cairo/2004-September/001839.html
+ *
+ * Both are fixed in xorg >= 6.9 and hopefully in > 6.8.2, so
+ * we can reuse the test for now.
*/
cairo_bool_t buggy_repeat;
@@ -662,8 +670,7 @@ _cairo_xlib_surface_clone_similar (void *abstract_surface,
cairo_xlib_surface_t *xlib_src = (cairo_xlib_surface_t *)src;
if (_cairo_xlib_surface_same_screen (surface, xlib_src)) {
- *clone_out = src;
- cairo_surface_reference (src);
+ *clone_out = cairo_surface_reference (src);
return CAIRO_STATUS_SUCCESS;
}
@@ -878,11 +885,13 @@ _operator_needs_alpha_composite (cairo_operator_t operator,
return TRUE;
}
-/* 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
+/* There is a bug in most older X servers with compositing using a
+ * untransformed repeating source pattern when the source is in off-screen
+ * video memory, and another with repeated transformed images using a
+ * general tranform matrix. When these bugs 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 for the first bug, otherwise, we need
* a software fallback.
*
* We can also often optimize a compositing operation by calling XCopyArea
@@ -896,9 +905,11 @@ typedef enum {
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.
+/* Initial check for the render bugs; we need to recheck for the
+ * offscreen-memory bug after we turn patterns into surfaces, since that
+ * may introduce a repeating pattern for gradient patterns. We don't need
+ * to check for the repeat+transform bug because gradient surfaces aren't
+ * transformed.
*
* 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.
@@ -920,8 +931,10 @@ _categorize_composite_operation (cairo_xlib_surface_t *dst,
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.
+ /* This is the case where we have the bug involving
+ * untransformed repeating source patterns with off-screen
+ * video memory; reject some cases where a core protocol
+ * fallback is impossible.
*/
if (have_mask ||
!(operator == CAIRO_OPERATOR_SOURCE || operator == CAIRO_OPERATOR_OVER))
@@ -942,6 +955,12 @@ _categorize_composite_operation (cairo_xlib_surface_t *dst,
return DO_UNSUPPORTED;
}
}
+
+ /* Check for the other bug involving repeat patterns with general
+ * transforms. */
+ if (!_cairo_matrix_is_integer_translation (&src_pattern->matrix, NULL, NULL) &&
+ src_pattern->extend == CAIRO_EXTEND_REPEAT)
+ return DO_UNSUPPORTED;
}
return DO_RENDER;
@@ -1118,6 +1137,16 @@ _cairo_xlib_surface_composite (cairo_operator_t operator,
dst_x, dst_y,
width, height);
}
+
+ if (!_cairo_operator_bounded (operator))
+ _cairo_surface_composite_fixup_unbounded (&dst->base,
+ &src_attr, src->width, src->height,
+ mask ? &mask_attr : NULL,
+ mask ? mask->width : 0,
+ mask ? mask->height : 0,
+ src_x, src_y,
+ mask_x, mask_y,
+ dst_x, dst_y, width, height);
break;
case DO_XCOPYAREA:
@@ -1195,10 +1224,101 @@ _cairo_xlib_surface_fill_rectangles (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
+/* Creates an A8 picture of size @width x @height, initialized with @color
+ */
+static Picture
+_create_a8_picture (cairo_xlib_surface_t *surface,
+ XRenderColor *color,
+ int width,
+ int height,
+ cairo_bool_t repeat)
+{
+ XRenderPictureAttributes pa;
+ unsigned long mask = 0;
+
+ Pixmap pixmap = XCreatePixmap (surface->dpy, surface->drawable,
+ width, height,
+ 8);
+ Picture picture;
+
+ if (repeat) {
+ pa.repeat = TRUE;
+ mask = CPRepeat;
+ }
+
+ picture = XRenderCreatePicture (surface->dpy, pixmap,
+ XRenderFindStandardFormat (surface->dpy, PictStandardA8),
+ mask, &pa);
+ XRenderFillRectangle (surface->dpy, PictOpSrc, picture, color,
+ 0, 0, width, height);
+ XFreePixmap (surface->dpy, pixmap);
+
+ return picture;
+}
+
+/* Creates a temporary mask for the trapezoids covering the area
+ * [@dst_x, @dst_y, @width, @height] of the destination surface.
+ */
+static Picture
+_create_trapezoid_mask (cairo_xlib_surface_t *dst,
+ cairo_trapezoid_t *traps,
+ int num_traps,
+ int dst_x,
+ int dst_y,
+ int width,
+ int height,
+ XRenderPictFormat *pict_format)
+{
+ XRenderColor transparent = { 0, 0, 0, 0 };
+ XRenderColor solid = { 0xffff, 0xffff, 0xffff, 0xffff };
+ Picture mask_picture, solid_picture;
+ XTrapezoid *offset_traps;
+ int i;
+
+ /* This would be considerably simpler using XRenderAddTraps(), but since
+ * we are only using this in the unbounded-operator case, we stick with
+ * XRenderCompositeTrapezoids, which is available on older versions
+ * of RENDER rather than conditionalizing. We should still hit an
+ * optimization that avoids creating another intermediate surface on
+ * the servers that have XRenderAddTraps().
+ */
+ mask_picture = _create_a8_picture (dst, &transparent, width, height, FALSE);
+ solid_picture = _create_a8_picture (dst, &solid, width, height, TRUE);
+
+ offset_traps = malloc (sizeof (XTrapezoid) * num_traps);
+ if (!offset_traps)
+ return None;
+
+ for (i = 0; i < num_traps; i++) {
+ offset_traps[i].top = traps[i].top - 0x10000 * dst_y;
+ offset_traps[i].bottom = traps[i].bottom - 0x10000 * dst_y;
+ offset_traps[i].left.p1.x = traps[i].left.p1.x - 0x10000 * dst_x;
+ offset_traps[i].left.p1.y = traps[i].left.p1.y - 0x10000 * dst_y;
+ offset_traps[i].left.p2.x = traps[i].left.p2.x - 0x10000 * dst_x;
+ offset_traps[i].left.p2.y = traps[i].left.p2.y - 0x10000 * dst_y;
+ offset_traps[i].right.p1.x = traps[i].right.p1.x - 0x10000 * dst_x;
+ offset_traps[i].right.p1.y = traps[i].right.p1.y - 0x10000 * dst_y;
+ offset_traps[i].right.p2.x = traps[i].right.p2.x - 0x10000 * dst_x;
+ offset_traps[i].right.p2.y = traps[i].right.p2.y - 0x10000 * dst_y;
+ }
+
+ XRenderCompositeTrapezoids (dst->dpy, PictOpAdd,
+ solid_picture, mask_picture,
+ pict_format,
+ 0, 0,
+ offset_traps, num_traps);
+
+ XRenderFreePicture (dst->dpy, solid_picture);
+ free (offset_traps);
+
+ return mask_picture;
+}
+
static cairo_int_status_t
_cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_dst,
+ cairo_antialias_t antialias,
int src_x,
int src_y,
int dst_x,
@@ -1215,6 +1335,7 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
composite_operation_t operation;
int render_reference_x, render_reference_y;
int render_src_x, render_src_y;
+ XRenderPictFormat *pict_format;
if (!CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst))
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -1235,6 +1356,15 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto FAIL;
}
+
+ switch (antialias) {
+ case CAIRO_ANTIALIAS_NONE:
+ pict_format = XRenderFindStandardFormat (dst->dpy, PictStandardA1);
+ break;
+ default:
+ pict_format = XRenderFindStandardFormat (dst->dpy, PictStandardA8);
+ break;
+ }
if (traps[0].left.p1.y < traps[0].left.p2.y) {
render_reference_x = _cairo_fixed_integer_floor (traps[0].left.p1.x);
@@ -1247,17 +1377,52 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t operator,
render_src_x = src_x + render_reference_x - dst_x;
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 (status == CAIRO_STATUS_SUCCESS)
+ if (status)
+ goto FAIL;
+
+ if (!_cairo_operator_bounded (operator)) {
+ /* XRenderCompositeTrapezoids() creates a mask only large enough for the
+ * trapezoids themselves, but if the operator is unbounded, then we need
+ * to actually composite all the way out to the bounds, so we create
+ * the mask and composite ourselves. There actually would
+ * be benefit to doing this in all cases, since RENDER implementations
+ * will frequently create a too temporary big mask, ignoring destination
+ * bounds and clip. (XRenderAddTraps() could be used to make creating
+ * the mask somewhat cheaper.)
+ */
+ Picture mask_picture = _create_trapezoid_mask (dst, traps, num_traps,
+ dst_x, dst_y, width, height,
+ pict_format);
+ if (!mask_picture) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto FAIL;
+ }
+
+ XRenderComposite (dst->dpy,
+ _render_operator (operator),
+ src->src_picture,
+ mask_picture,
+ dst->dst_picture,
+ src_x + attributes.x_offset,
+ src_y + attributes.y_offset,
+ 0, 0,
+ dst_x, dst_y,
+ width, height);
+
+ XRenderFreePicture (dst->dpy, mask_picture);
+
+ } else {
+ /* XXX: The XTrapezoid cast is evil and needs to go away somehow. */
XRenderCompositeTrapezoids (dst->dpy,
_render_operator (operator),
src->src_picture, dst->dst_picture,
- XRenderFindStandardFormat (dst->dpy, PictStandardA8),
+ pict_format,
render_src_x + attributes.x_offset,
render_src_y + attributes.y_offset,
(XTrapezoid *) traps, num_traps);
+ }
FAIL:
_cairo_pattern_release_surface (pattern, &src->base, &attributes);
@@ -1716,6 +1881,7 @@ typedef struct {
cairo_glyph_cache_key_t key;
GlyphSet glyphset;
Glyph glyph;
+ cairo_glyph_size_t size;
} glyphset_cache_entry_t;
static Glyph
@@ -1770,6 +1936,7 @@ _xlib_glyphset_cache_create_entry (void *abstract_cache,
entry->glyph = None;
entry->glyphset = None;
entry->key.base.memory = 0;
+ entry->size.x = entry->size.y = entry->size.width = entry->size.height = 0;
goto out;
}
@@ -1778,6 +1945,8 @@ _xlib_glyphset_cache_create_entry (void *abstract_cache,
data = im->image->data;
+ entry->size = im->size;
+
glyph_info.width = im->size.width;
glyph_info.height = im->size.height;
@@ -1916,8 +2085,9 @@ _xlib_glyphset_cache_destroy_entry (void *abstract_cache,
glyphset_cache_entry_t *entry = abstract_entry;
_cairo_unscaled_font_destroy (entry->key.unscaled);
- XRenderFreeGlyphs (cache->display, entry->glyphset,
- &(entry->glyph), 1);
+ if (entry->glyph)
+ XRenderFreeGlyphs (cache->display, entry->glyphset,
+ &(entry->glyph), 1);
free (entry);
}
@@ -1943,8 +2113,10 @@ _lock_xlib_glyphset_caches (void)
static void
_unlock_xlib_glyphset_caches (glyphset_cache_t *cache)
{
- _cairo_cache_shrink_to (&cache->base,
- CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT);
+ if (cache) {
+ _cairo_cache_shrink_to (&cache->base,
+ CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT);
+ }
CAIRO_MUTEX_UNLOCK(_xlib_glyphset_caches_mutex);
}
@@ -2102,7 +2274,7 @@ _cairo_xlib_surface_show_glyphs32 (cairo_scaled_font_t *scaled_font,
_render_operator (operator),
src->src_picture,
self->dst_picture,
- cache->a8_pict_format,
+ mask_format,
source_x, source_y,
0, 0,
elts, count);
@@ -2330,7 +2502,70 @@ _cairo_xlib_surface_show_glyphs8 (cairo_scaled_font_t *scaled_font,
return CAIRO_STATUS_NO_MEMORY;
}
+/* Handles clearing the regions that are outside of the temporary
+ * mask created by XRenderCompositeText[N] but should be affected
+ * by an unbounded operator like CAIRO_OPERATOR_SOURCE.
+ */
+static void
+_show_glyphs_fixup_unbounded (cairo_xlib_surface_t *self,
+ cairo_surface_attributes_t *src_attr,
+ cairo_xlib_surface_t *src,
+ const cairo_glyph_t *glyphs,
+ glyphset_cache_entry_t **entries,
+ int num_glyphs,
+ int src_x,
+ int src_y,
+ int dst_x,
+ int dst_y,
+ int width,
+ int height)
+{
+ cairo_surface_attributes_t mask_attr;
+ int x1 = INT_MAX;
+ int x2 = INT_MIN;
+ int y1 = INT_MAX;
+ int y2 = INT_MIN;
+ int i;
+
+ /* Compute the size of the glyph mask as the bounding box
+ * of all the glyphs.
+ */
+ for (i = 0; i < num_glyphs; ++i) {
+ int thisX, thisY;
+
+ if (entries[i] == NULL || !entries[i]->glyph)
+ continue;
+
+ thisX = (int) floor (glyphs[i].x + 0.5);
+ thisY = (int) floor (glyphs[i].y + 0.5);
+
+ if (thisX + entries[i]->size.x < x1)
+ x1 = thisX + entries[i]->size.x;
+ if (thisX + entries[i]->size.x + entries[i]->size.width > x2)
+ x2 = thisX + entries[i]->size.x + entries[i]->size.width;
+ if (thisY + entries[i]->size.y < y1)
+ y1 = thisY + entries[i]->size.y;
+ if (thisY + entries[i]->size.y + entries[i]->size.height > y2)
+ y2 = thisY + entries[i]->size.y + entries[i]->size.height;
+ }
+ if (x1 >= x2 || y1 >= y2)
+ x1 = x2 = y1 = y2 = 0;
+
+ cairo_matrix_init_identity (&mask_attr.matrix);
+ mask_attr.extend = CAIRO_EXTEND_NONE;
+ mask_attr.filter = CAIRO_FILTER_NEAREST;
+ mask_attr.x_offset = 0;
+ mask_attr.y_offset = 0;
+
+ _cairo_surface_composite_fixup_unbounded (&self->base,
+ src_attr, src->width, src->height,
+ &mask_attr, x2 - x1, y2 - y1,
+ src_x, src_y,
+ dst_x - x1, dst_y - y1,
+ dst_x, dst_y, width, height);
+}
+
static cairo_int_status_t
_cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
@@ -2441,6 +2676,13 @@ _cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
glyphs, entries, num_glyphs);
}
+ if (!_cairo_operator_bounded (operator))
+ _show_glyphs_fixup_unbounded (self,
+ &attributes, src,
+ glyphs, entries, num_glyphs,
+ source_x, source_y,
+ dest_x, dest_y, width, height);
+
UNLOCK:
_unlock_xlib_glyphset_caches (cache);
@@ -2452,3 +2694,23 @@ _cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
return status;
}
+
+static void
+_destroy_glyphset_cache_recurse (glyphset_cache_t *cache)
+{
+ if (cache == NULL)
+ return;
+
+ _destroy_glyphset_cache_recurse (cache->next);
+ _cairo_cache_destroy (&cache->base);
+ free (cache);
+}
+
+void
+_cairo_xlib_surface_reset_static_data (void)
+{
+ _lock_xlib_glyphset_caches ();
+ _destroy_glyphset_cache_recurse (_xlib_glyphset_caches);
+ _xlib_glyphset_caches = NULL;
+ _unlock_xlib_glyphset_caches (NULL);
+}
diff --git a/src/cairo.c b/src/cairo.c
index b4fc5464..4c4b03eb 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -178,14 +178,18 @@ cairo_create (cairo_surface_t *target)
* Increases the reference count on @cr by one. This prevents
* @cr from being destroyed until a matching call to cairo_destroy()
* is made.
+ *
+ * Return value: the referenced #cairo_t.
**/
-void
+cairo_t *
cairo_reference (cairo_t *cr)
{
if (cr->ref_count == (unsigned int)-1)
- return;
+ return cr;
cr->ref_count++;
+
+ return cr;
}
/**
@@ -532,6 +536,32 @@ cairo_set_tolerance (cairo_t *cr, double tolerance)
}
/**
+ * cairo_set_antialias:
+ * @cr: a #cairo_t
+ * @antialias: the new antialiasing mode
+ *
+ * Set the antialiasing mode of the rasterizer used for drawing shapes.
+ * This value is a hint, and a particular backend may or may not support
+ * a particular value. At the current time, no backend supports
+ * %CAIRO_ANTIALIAS_SUBPIXEL when drawing shapes.
+ *
+ * Note that this option does not affect text rendering, instead see
+ * cairo_font_options_set_antialias().
+ **/
+void
+cairo_set_antialias (cairo_t *cr, cairo_antialias_t antialias)
+{
+ if (cr->status) {
+ _cairo_set_error (cr, cr->status);
+ return;
+ }
+
+ cr->status = _cairo_gstate_set_antialias (cr->gstate, antialias);
+ if (cr->status)
+ _cairo_set_error (cr, cr->status);
+}
+
+/**
* cairo_set_fill_rule:
* @cr: a #cairo_t
* @fill_rule: a fill rule, specified as a #cairo_fill_rule_t
@@ -1401,8 +1431,9 @@ slim_hidden_def(cairo_stroke_preserve);
* @cr: a cairo context
*
* A drawing operator that fills the current path according to the
- * current fill rule. After cairo_fill, the current path will be
- * cleared from the cairo context. See cairo_set_fill_rule() and
+ * current fill rule, (each sub-path is implicitly closed before being
+ * filled). After cairo_fill, the current path will be cleared from
+ * the cairo context. See cairo_set_fill_rule() and
* cairo_fill_preserve().
**/
void
@@ -1418,8 +1449,9 @@ cairo_fill (cairo_t *cr)
* @cr: a cairo context
*
* A drawing operator that fills the current path according to the
- * current fill rule. Unlike cairo_fill(), cairo_fill_preserve
- * preserves the path within the cairo context.
+ * current fill rule, (each sub-path is implicitly closed before being
+ * filled). Unlike cairo_fill(), cairo_fill_preserve preserves the
+ * path within the cairo context.
*
* See cairo_set_fill_rule() and cairo_fill().
**/
@@ -1645,7 +1677,7 @@ cairo_reset_clip (cairo_t *cr)
* for operations such as listing all available fonts on the system,
* and it is expected that most applications will need to use a more
* comprehensive font handling and text layout library in addition to
- * Cairo.
+ * cairo.
**/
void
cairo_select_font_face (cairo_t *cr,
@@ -1681,16 +1713,13 @@ cairo_get_font_face (cairo_t *cr)
if (cr->status) {
_cairo_set_error (cr, cr->status);
- return NULL;
+ return (cairo_font_face_t*) &_cairo_font_face_nil;
}
cr->status = _cairo_gstate_get_font_face (cr->gstate, &font_face);
if (cr->status) {
_cairo_set_error (cr, cr->status);
- /* XXX: When available:
- return _cairo_font_face_nil;
- */
- return NULL;
+ return (cairo_font_face_t*) &_cairo_font_face_nil;
}
return font_face;
@@ -2079,6 +2108,20 @@ cairo_get_tolerance (cairo_t *cr)
}
/**
+ * cairo_get_antialias:
+ * @cr: a cairo context
+ *
+ * Gets the current shape antialiasing mode, as set by cairo_set_shape_antialias().
+ *
+ * Return value: the current shape antialiasing mode.
+ **/
+cairo_antialias_t
+cairo_get_antialias (cairo_t *cr)
+{
+ return _cairo_gstate_get_antialias (cr->gstate);
+}
+
+/**
* cairo_get_current_point:
* @cr: a cairo context
* @x: return value for X coordinate of the current point
@@ -2257,7 +2300,7 @@ cairo_path_t *
cairo_copy_path (cairo_t *cr)
{
if (cr->status)
- return &cairo_path_nil;
+ return (cairo_path_t*) &_cairo_path_nil;
return _cairo_path_data_create (&cr->path, cr->gstate);
}
@@ -2296,7 +2339,7 @@ cairo_path_t *
cairo_copy_path_flat (cairo_t *cr)
{
if (cr->status)
- return &cairo_path_nil;
+ return (cairo_path_t*) &_cairo_path_nil;
else
return _cairo_path_data_create_flat (&cr->path, cr->gstate);
}
diff --git a/src/cairo.h b/src/cairo.h
index ba899981..1d871c81 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -38,14 +38,6 @@
#ifndef CAIRO_H
#define CAIRO_H
-#ifdef __cplusplus
-# define CAIRO_BEGIN_DECLS extern "C" {
-# define CAIRO_END_DECLS }
-#else
-# define CAIRO_BEGIN_DECLS
-# define CAIRO_END_DECLS
-#endif
-
#include <cairo-features.h>
CAIRO_BEGIN_DECLS
@@ -230,7 +222,7 @@ typedef cairo_status_t (*cairo_read_func_t) (void *closure,
cairo_t *
cairo_create (cairo_surface_t *target);
-void
+cairo_t *
cairo_reference (cairo_t *cr);
void
@@ -296,6 +288,29 @@ void
cairo_set_tolerance (cairo_t *cr, double tolerance);
/**
+ * cairo_antialias_t:
+ * @CAIRO_ANTIALIAS_DEFAULT: Use the default antialiasing for
+ * the subsystem and target device
+ * @CAIRO_ANTIALIAS_NONE: Use a bilevel alpha mask
+ * @CAIRO_ANTIALIAS_GRAY: Perform single-color antialiasing (using
+ * shades of gray for black text on a white background, for example).
+ * @CAIRO_ANTIALIAS_SUBPIXEL: Perform antialiasing by taking
+ * advantage of the order of subpixel elements on devices
+ * such as LCD panels
+ *
+ * Specifies the type of antialiasing to do when rendering text or shapes.
+ **/
+typedef enum _cairo_antialias {
+ CAIRO_ANTIALIAS_DEFAULT,
+ CAIRO_ANTIALIAS_NONE,
+ CAIRO_ANTIALIAS_GRAY,
+ CAIRO_ANTIALIAS_SUBPIXEL
+} cairo_antialias_t;
+
+void
+cairo_set_antialias (cairo_t *cr, cairo_antialias_t antialias);
+
+/**
* cairo_fill_rule_t
* @CAIRO_FILL_RULE_WINDING: If the path crosses the ray from
* left-to-right, counts +1. If the path crosses the ray
@@ -668,26 +683,6 @@ typedef enum _cairo_font_weight {
} cairo_font_weight_t;
/**
- * cairo_antialias_t:
- * @CAIRO_ANTIALIAS_DEFAULT: Use the default antialiasing for
- * the font subsystem and target device
- * @CAIRO_ANTIALIAS_NONE: Do no antialiasing of fonts; use bilevel text
- * @CAIRO_ANTIALIAS_GRAY: Perform single-color antialiasing (using
- * shades of gray for black text on a white background, for example).
- * @CAIRO_ANTIALIAS_SUBPIXEL: Perform antialiasing by taking
- * advantage of the order of subpixel elements on devices
- * such as LCD panels
- *
- * Specifies the type of antialiasing to do when rendering text.
- **/
-typedef enum _cairo_antialias {
- CAIRO_ANTIALIAS_DEFAULT,
- CAIRO_ANTIALIAS_NONE,
- CAIRO_ANTIALIAS_GRAY,
- CAIRO_ANTIALIAS_SUBPIXEL
-} cairo_antialias_t;
-
-/**
* cairo_subpixel_order_t:
* @CAIRO_SUBPIXEL_ORDER_DEFAULT: Use the default subpixel order for
* for the target device
@@ -871,7 +866,7 @@ cairo_glyph_path (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs);
/* Generic identifier for a font style */
-void
+cairo_font_face_t *
cairo_font_face_reference (cairo_font_face_t *font_face);
void
@@ -898,7 +893,7 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
const cairo_matrix_t *ctm,
const cairo_font_options_t *options);
-void
+cairo_scaled_font_t *
cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font);
void
@@ -928,6 +923,9 @@ cairo_get_source (cairo_t *cr);
double
cairo_get_tolerance (cairo_t *cr);
+cairo_antialias_t
+cairo_get_antialias (cairo_t *cr);
+
void
cairo_get_current_point (cairo_t *cr, double *x, double *y);
@@ -1109,7 +1107,7 @@ cairo_surface_create_similar (cairo_surface_t *other,
int width,
int height);
-void
+cairo_surface_t *
cairo_surface_reference (cairo_surface_t *surface);
void
@@ -1149,6 +1147,19 @@ cairo_surface_get_font_options (cairo_surface_t *surface,
cairo_font_options_t *options);
void
+cairo_surface_flush (cairo_surface_t *surface);
+
+void
+cairo_surface_mark_dirty (cairo_surface_t *surface);
+
+void
+cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
+ int x,
+ int y,
+ int width,
+ int height);
+
+void
cairo_surface_set_device_offset (cairo_surface_t *surface,
double x_offset,
double y_offset);
@@ -1236,7 +1247,7 @@ cairo_pattern_t *
cairo_pattern_create_radial (double cx0, double cy0, double radius0,
double cx1, double cy1, double radius1);
-void
+cairo_pattern_t *
cairo_pattern_reference (cairo_pattern_t *pattern);
void
diff --git a/src/cairoint.h b/src/cairoint.h
index 45747838..2a5f45e3 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -63,6 +63,7 @@
#include <stdio.h>
#include "cairo.h"
+#include "cairo-debug.h"
#include <pixman.h>
#if __GNUC__ >= 3 && defined(__ELF__)
@@ -188,6 +189,8 @@ typedef cairo_fixed_16_16_t cairo_fixed_t;
#define CAIRO_ALPHA_IS_OPAQUE(alpha) ((alpha) >= ((double)0xff00 / (double)0xffff))
+#include "cairo-hash-private.h"
+
typedef struct _cairo_point {
cairo_fixed_t x;
cairo_fixed_t y;
@@ -239,6 +242,9 @@ typedef enum cairo_direction {
} cairo_direction_t;
typedef struct _cairo_path_fixed cairo_path_fixed_t;
+typedef enum _cairo_clip_mode cairo_clip_mode_t;
+typedef struct _cairo_clip_path cairo_clip_path_t;
+typedef struct _cairo_clip cairo_clip_t;
typedef struct _cairo_edge {
cairo_line_t edge;
@@ -288,6 +294,13 @@ typedef struct _cairo_pen {
typedef struct _cairo_color cairo_color_t;
typedef struct _cairo_image_surface cairo_image_surface_t;
+cairo_private void
+_cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_t *rectangle);
+
+cairo_private void
+_cairo_rectangle_intersect (cairo_rectangle_t *dest, cairo_rectangle_t *src);
+
+
/* cairo_array.c structures and functions */
typedef struct _cairo_array cairo_array_t;
@@ -443,8 +456,6 @@ _cairo_hash_string (const char *c);
#define CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT 0x100000
#define CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT 0x100000
-typedef struct _cairo_unscaled_font cairo_unscaled_font_t;
-
typedef struct _cairo_unscaled_font_backend cairo_unscaled_font_backend_t;
typedef struct _cairo_scaled_font_backend cairo_scaled_font_backend_t;
typedef struct _cairo_font_face_backend cairo_font_face_backend_t;
@@ -453,9 +464,16 @@ typedef struct _cairo_font_face_backend cairo_font_face_backend_t;
* A cairo_unscaled_font_t is just an opaque handle we use in the
* glyph cache.
*/
-struct _cairo_unscaled_font {
+typedef struct _cairo_unscaled_font {
int ref_count;
const cairo_unscaled_font_backend_t *backend;
+} cairo_unscaled_font_t;
+
+struct _cairo_font_options {
+ cairo_antialias_t antialias;
+ cairo_subpixel_order_t subpixel_order;
+ cairo_hint_style_t hint_style;
+ cairo_hint_metrics_t hint_metrics;
};
struct _cairo_scaled_font {
@@ -464,7 +482,9 @@ struct _cairo_scaled_font {
cairo_matrix_t font_matrix; /* font space => user space */
cairo_matrix_t ctm; /* user space => device space */
cairo_matrix_t scale; /* font space => device space */
+ cairo_font_options_t options;
cairo_font_face_t *font_face; /* may be NULL */
+
const cairo_scaled_font_backend_t *backend;
};
@@ -475,13 +495,6 @@ struct _cairo_font_face {
const cairo_font_face_backend_t *backend;
};
-struct _cairo_font_options {
- cairo_antialias_t antialias;
- cairo_subpixel_order_t subpixel_order;
- cairo_hint_style_t hint_style;
- cairo_hint_metrics_t hint_metrics;
-};
-
/* cairo_font.c is responsible for a global glyph cache:
*
* - glyph entries: [[[base], cairo_unscaled_font_t, scale, flags, index],
@@ -516,6 +529,18 @@ _cairo_unlock_global_image_glyph_cache (void);
cairo_private cairo_cache_t *
_cairo_get_global_image_glyph_cache (void);
+cairo_private void
+_cairo_font_reset_static_data (void);
+
+cairo_private void
+_cairo_ft_font_reset_static_data (void);
+
+cairo_private void
+_cairo_xlib_surface_reset_static_data (void);
+
+cairo_private void
+_cairo_xlib_screen_reset_static_data (void);
+
/* Some glyph cache functions you can reuse. */
cairo_private unsigned long
@@ -534,66 +559,88 @@ struct _cairo_unscaled_font_backend {
cairo_image_glyph_cache_entry_t *entry);
};
+/* cairo_toy_font_face_t - simple family/slant/weight font faces used for
+ * the built-in font API
+ */
+
+typedef struct _cairo_toy_font_face {
+ cairo_font_face_t base;
+ char *family;
+ cairo_font_slant_t slant;
+ cairo_font_weight_t weight;
+} cairo_toy_font_face_t;
+
struct _cairo_scaled_font_backend {
- cairo_status_t (*create) (const char *family,
- cairo_font_slant_t slant,
- cairo_font_weight_t weight,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm,
- const cairo_font_options_t *options,
- cairo_scaled_font_t **font);
-
- void (*destroy) (void *font);
+ cairo_status_t
+ (*create_toy) (const cairo_toy_font_face_t *toy_face,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ const cairo_font_options_t *options,
+ cairo_scaled_font_t **scaled_font);
+
+ void
+ (*fini) (void *scaled_font);
- cairo_status_t (*font_extents) (void *font,
- cairo_font_extents_t *extents);
+ cairo_status_t
+ (*font_extents) (void *scaled_font,
+ cairo_font_extents_t *extents);
- cairo_status_t (*text_to_glyphs) (void *font,
- const char *utf8,
- cairo_glyph_t **glyphs,
- int *num_glyphs);
+ cairo_status_t
+ (*text_to_glyphs) (void *scaled_font,
+ const char *utf8,
+ cairo_glyph_t **glyphs,
+ int *num_glyphs);
- cairo_status_t (*glyph_extents) (void *font,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_text_extents_t *extents);
+ cairo_status_t
+ (*glyph_extents) (void *scaled_font,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_text_extents_t *extents);
- cairo_status_t (*glyph_bbox) (void *font,
- const cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_box_t *bbox);
-
- cairo_status_t (*show_glyphs) (void *font,
- cairo_operator_t operator,
- cairo_pattern_t *pattern,
- cairo_surface_t *surface,
- int source_x,
- int source_y,
- int dest_x,
- int dest_y,
- unsigned int width,
- unsigned int height,
- const cairo_glyph_t *glyphs,
- int num_glyphs);
+ cairo_status_t
+ (*glyph_bbox) (void *scaled_font,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_box_t *bbox);
+
+ cairo_status_t
+ (*show_glyphs) (void *scaled_font,
+ cairo_operator_t operator,
+ cairo_pattern_t *pattern,
+ cairo_surface_t *surface,
+ int source_x,
+ int source_y,
+ int dest_x,
+ int dest_y,
+ unsigned int width,
+ unsigned int height,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs);
- cairo_status_t (*glyph_path) (void *font,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_path_fixed_t *path);
- void (*get_glyph_cache_key) (void *font,
- cairo_glyph_cache_key_t *key);
+ cairo_status_t
+ (*glyph_path) (void *scaled_font,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_path_fixed_t *path);
+
+ void
+ (*get_glyph_cache_key) (void *scaled_font,
+ cairo_glyph_cache_key_t *key);
};
struct _cairo_font_face_backend {
/* The destroy() function is allowed to resurrect the font face
* by re-referencing. This is needed for the FreeType backend.
*/
- void (*destroy) (void *font_face);
- cairo_status_t (*create_font) (void *font_face,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm,
- const cairo_font_options_t *options,
- cairo_scaled_font_t **scaled_font);
+ void
+ (*destroy) (void *font_face);
+
+ cairo_status_t
+ (*scaled_font_create) (void *font_face,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ const cairo_font_options_t *options,
+ cairo_scaled_font_t **scaled_font);
};
/* concrete font backends */
@@ -681,6 +728,7 @@ typedef struct _cairo_surface_backend {
(*composite_trapezoids) (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *dst,
+ cairo_antialias_t antialias,
int src_x,
int src_y,
int dst_x,
@@ -731,7 +779,8 @@ typedef struct _cairo_surface_backend {
(*intersect_clip_path) (void *dst,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
- double tolerance);
+ double tolerance,
+ cairo_antialias_t antialias);
/* Get the extents of the current surface. For many surface types
* this will be as simple as { x=0, y=0, width=surface->width,
@@ -777,6 +826,17 @@ typedef struct _cairo_surface_backend {
void
(*get_font_options) (void *surface,
cairo_font_options_t *options);
+
+ cairo_status_t
+ (*flush) (void *surface);
+
+ cairo_status_t
+ (*mark_dirty_rectangle) (void *surface,
+ int x,
+ int y,
+ int width,
+ int height);
+
} cairo_surface_backend_t;
typedef struct _cairo_format_masks {
@@ -787,12 +847,6 @@ typedef struct _cairo_format_masks {
unsigned long blue_mask;
} cairo_format_masks_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;
@@ -827,7 +881,9 @@ struct _cairo_image_surface {
/* libic-specific fields */
cairo_format_t format;
unsigned char *data;
- int owns_data;
+ cairo_bool_t owns_data;
+ cairo_bool_t has_clip;
+
int width;
int height;
@@ -1260,6 +1316,8 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
int num_glyphs,
cairo_path_fixed_t *path);
+cairo_bool_t
+_cairo_operator_bounded (cairo_operator_t operator);
/* cairo_color.c */
cairo_private const cairo_color_t *
@@ -1312,26 +1370,27 @@ _cairo_font_face_init (cairo_font_face_t *font_face,
const cairo_font_face_backend_t *backend);
cairo_private cairo_font_face_t *
-_cairo_simple_font_face_create (const char *family,
- cairo_font_slant_t slant,
- cairo_font_weight_t weight);
-
-cairo_private void
-_cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm,
- const cairo_scaled_font_backend_t *backend);
+_cairo_toy_font_face_create (const char *family,
+ cairo_font_slant_t slant,
+ cairo_font_weight_t weight);
cairo_private void
_cairo_unscaled_font_init (cairo_unscaled_font_t *font,
const cairo_unscaled_font_backend_t *backend);
-cairo_private void
+cairo_private cairo_unscaled_font_t *
_cairo_unscaled_font_reference (cairo_unscaled_font_t *font);
cairo_private void
_cairo_unscaled_font_destroy (cairo_unscaled_font_t *font);
+cairo_private void
+_cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ const cairo_font_options_t *options,
+ const cairo_scaled_font_backend_t *backend);
+
cairo_private cairo_status_t
_cairo_scaled_font_font_extents (cairo_scaled_font_t *scaled_font,
cairo_font_extents_t *extents);
@@ -1472,7 +1531,8 @@ _cairo_path_fixed_bounds (cairo_path_fixed_t *path,
/* cairo_path_fill.c */
cairo_private cairo_status_t
_cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,
- cairo_gstate_t *gstate,
+ cairo_fill_rule_t fill_rule,
+ double tolerance,
cairo_traps_t *traps);
/* cairo_path_stroke.c */
@@ -1549,6 +1609,7 @@ cairo_private cairo_status_t
_cairo_surface_composite_trapezoids (cairo_operator_t operator,
cairo_pattern_t *pattern,
cairo_surface_t *dst,
+ cairo_antialias_t antialias,
int src_x,
int src_y,
int dst_x,
@@ -1558,6 +1619,14 @@ _cairo_surface_composite_trapezoids (cairo_operator_t operator,
cairo_trapezoid_t *traps,
int ntraps);
+cairo_status_t
+_cairo_surface_clip_and_composite_trapezoids (cairo_pattern_t *src,
+ cairo_operator_t operator,
+ cairo_surface_t *dst,
+ cairo_traps_t *traps,
+ cairo_clip_t *clip,
+ cairo_antialias_t antialias);
+
cairo_private cairo_status_t
_cairo_surface_copy_page (cairo_surface_t *surface);
@@ -1611,14 +1680,11 @@ cairo_private cairo_int_status_t
_cairo_surface_intersect_clip_path (cairo_surface_t *surface,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
- double tolerance);
-
-typedef struct _cairo_clip_path cairo_clip_path_t;
+ double tolerance,
+ cairo_antialias_t antialias);
cairo_private cairo_status_t
-_cairo_surface_set_clip_path (cairo_surface_t *surface,
- cairo_clip_path_t *clip_path,
- unsigned int serial);
+_cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_surface_get_extents (cairo_surface_t *surface,
@@ -1638,6 +1704,23 @@ _cairo_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
const cairo_glyph_t *glyphs,
int num_glyphs);
+void
+_cairo_surface_composite_fixup_unbounded (cairo_surface_t *dst,
+ cairo_surface_attributes_t *src_attr,
+ int src_width,
+ int src_height,
+ cairo_surface_attributes_t *mask_attr,
+ int mask_width,
+ int mask_height,
+ int src_x,
+ int src_y,
+ int mask_x,
+ int mask_y,
+ int dst_x,
+ int dst_y,
+ unsigned int width,
+ unsigned int height);
+
/* cairo_image_surface.c */
cairo_private cairo_format_t
@@ -1773,6 +1856,9 @@ _cairo_traps_init_box (cairo_traps_t *traps,
cairo_private void
_cairo_traps_fini (cairo_traps_t *traps);
+cairo_private void
+_cairo_traps_translate (cairo_traps_t *traps, int x, int y);
+
cairo_private cairo_status_t
_cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3]);
@@ -1873,6 +1959,13 @@ _cairo_pattern_acquire_surfaces (cairo_pattern_t *src,
cairo_surface_attributes_t *src_attributes,
cairo_surface_attributes_t *mask_attributes);
+cairo_private cairo_status_t
+_cairo_gstate_set_antialias (cairo_gstate_t *gstate,
+ cairo_antialias_t antialias);
+
+cairo_private cairo_antialias_t
+_cairo_gstate_get_antialias (cairo_gstate_t *gstate);
+
/* cairo_unicode.c */
diff --git a/test/.cvsignore b/test/.cvsignore
index 1d037fa0..c1895986 100644
--- a/test/.cvsignore
+++ b/test/.cvsignore
@@ -2,7 +2,9 @@
.libs
Makefile
Makefile.in
+a8-mask
clip-nesting
+clip-operator
clip-twice
composite-integer-translate-source
composite-integer-translate-over
@@ -20,6 +22,8 @@ leaky-polygon
line-width
linear-gradient
mask
+mask-ctm
+mask-surface-ctm
move-to-show-surface
paint
paint-with-alpha
@@ -49,6 +53,7 @@ text-rotate
transforms
translate-show-surface
trap-clip
+unbounded-operator
user-data
xlib-surface
*-image-out.png
diff --git a/test/Makefile.am b/test/Makefile.am
index 649c4012..e630b66b 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,6 +1,8 @@
# All test cases go here
TESTS = \
+a8-mask \
clip-nesting \
+clip-operator \
clip-twice \
composite-integer-translate-source \
composite-integer-translate-over \
@@ -16,6 +18,8 @@ leaky-polygon \
line-width \
linear-gradient \
mask \
+mask-ctm \
+mask-surface-ctm \
move-to-show-surface \
paint \
paint-with-alpha \
@@ -38,6 +42,8 @@ text-rotate \
transforms \
translate-show-surface \
trap-clip \
+unantialiased-shapes \
+unbounded-operator \
user-data \
rel-path
@@ -57,7 +63,9 @@ endif
# I really don't like having to repeat this list. Anyone know a good
# way to avoid it? Can I use a wildcard here?
EXTRA_DIST = \
+a8-mask-ref.png \
clip-nesting-ref.png \
+clip-operator-ref.png \
clip-twice-ref.png \
composite-integer-translate-source-ref.png \
composite-integer-translate-over-ref.png \
@@ -72,6 +80,8 @@ leaky-polygon-ref.png \
line-width-ref.png \
linear-gradient-ref.png \
mask-ref.png \
+mask-ctm-ref.png \
+mask-surface-ctm-ref.png \
move-to-show-surface-ref.png \
paint-ref.png \
paint-with-alpha-ref.png \
@@ -90,6 +100,8 @@ text-antialias-none-ref.png \
transforms-ref.png \
translate-show-surface-ref.png \
trap-clip-ref.png \
+unantialiased-shapes-ref.png \
+unbounded-operator-ref.png \
rel-path-ref.png
# Any test for which the code committed to CVS is expected to fail
@@ -106,10 +118,10 @@ rel-path-ref.png
# Also, any test listed here should call cairo_test_expect_failure and
# provide an explanation for the expected failure.
XFAIL_TESTS = \
+a8-mask \
filter-nearest-offset \
pixman-rotate \
self-intersecting \
-source-surface-scale-paint \
text-antialias-subpixel \
text-rotate
@@ -145,7 +157,9 @@ LDADDS = libcairotest.la $(top_builddir)/src/libcairo.la
# ARGH! I have to repeat the list of tests a third time. Maybe it's
# time to break down and auto-generate the Makefile.am or something
# from autogen.sh. My, but this is painful...
+a8_mask_LDADD = $(LDADDS)
clip_nesting_LDADD = $(LDADDS)
+clip_operator_LDADD = $(LDADDS)
clip_twice_LDADD = $(LDADDS)
composite_integer_translate_source_LDADD = $(LDADDS)
composite_integer_translate_over_LDADD = $(LDADDS)
@@ -161,6 +175,8 @@ leaky_polygon_LDADD = $(LDADDS)
line_width_LDADD = $(LDADDS)
linear_gradient_LDADD = $(LDADDS)
mask_LDADD = $(LDADDS)
+mask_ctm_LDADD = $(LDADDS)
+mask_surface_ctm_LDADD = $(LDADDS)
move_to_show_surface_LDADD = $(LDADDS)
paint_LDADD = $(LDADDS)
paint_with_alpha_LDADD = $(LDADDS)
@@ -186,6 +202,8 @@ text_rotate_LDADD = $(LDADDS)
transforms_LDADD = $(LDADDS)
translate_show_surface_LDADD = $(LDADDS)
trap_clip_LDADD = $(LDADDS)
+unantialiased_shapes_LDADD = $(LDADDS)
+unbounded_operator_LDADD = $(LDADDS)
user_data_LDADD = $(LDADDS)
rel_path_LDADD = $(LDADDS)
xlib_surface_LDADD = $(LDADDS)
diff --git a/test/a8-mask-ref.png b/test/a8-mask-ref.png
new file mode 100644
index 00000000..38556156
--- /dev/null
+++ b/test/a8-mask-ref.png
Binary files differ
diff --git a/test/a8-mask.c b/test/a8-mask.c
new file mode 100644
index 00000000..e547ecce
--- /dev/null
+++ b/test/a8-mask.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright © Jeff Muizelaar
+ *
+ * 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.
+ *
+ * JEFF MUIZELAAR 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: Jeff Muizelaar <jeff@infidigm.net>
+ */
+
+#include "cairo-test.h"
+
+cairo_test_t test = {
+ "a8-mask",
+ "test masks of CAIRO_FORMAT_A8",
+ 8, 8
+};
+
+static unsigned char mask[] = {
+ 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ cairo_surface_t *surface;
+ cairo_pattern_t *pattern;
+
+ cairo_set_source_rgb (cr, 0, 0, 1);
+ cairo_paint (cr);
+
+ surface = cairo_image_surface_create_for_data (mask, CAIRO_FORMAT_A8,
+ 7, 8, 7);
+ pattern = cairo_pattern_create_for_surface (surface);
+
+ cairo_set_source_rgb (cr, 1, 0, 0);
+ cairo_mask (cr, pattern);
+
+ cairo_pattern_destroy (pattern);
+ cairo_surface_destroy (surface);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+ return cairo_test_expect_failure (&test, draw,
+ "image backend fails because libpixman only handles (stride % sizeof(pixman_bits) == 0)");
+}
diff --git a/test/buffer-diff.c b/test/buffer-diff.c
index e5ba513a..78284efc 100644
--- a/test/buffer-diff.c
+++ b/test/buffer-diff.c
@@ -23,10 +23,17 @@
*
* Author: Richard D. Worth <richard@theworths.org> */
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include <stdio.h>
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
+#endif
#include <errno.h>
#include <string.h>
+#include <pixman.h>
#include "cairo-test.h"
@@ -45,18 +52,27 @@ xunlink (const char *pathname)
}
}
-int
-buffer_diff (unsigned char *buf_a,
- unsigned char *buf_b,
- unsigned char *buf_diff,
- int width,
- int height,
- int stride)
+
+/* This function should be rewritten to compare all formats supported by
+ * cairo_format_t instead of taking a mask as a parameter.
+ */
+static int
+buffer_diff_core (unsigned char *_buf_a,
+ unsigned char *_buf_b,
+ unsigned char *_buf_diff,
+ int width,
+ int height,
+ int stride,
+ pixman_bits_t mask)
{
int x, y;
- unsigned char *row_a, *row_b, *row;
+ pixman_bits_t *row_a, *row_b, *row;
int pixels_changed = 0;
+ pixman_bits_t *buf_a = (pixman_bits_t*)_buf_a;
+ pixman_bits_t *buf_b = (pixman_bits_t*)_buf_b;
+ pixman_bits_t *buf_diff = (pixman_bits_t*)_buf_diff;
+ stride /= sizeof(pixman_bits_t);
for (y = 0; y < height; y++)
{
row_a = buf_a + y * stride;
@@ -64,33 +80,54 @@ buffer_diff (unsigned char *buf_a,
row = buf_diff + y * stride;
for (x = 0; x < width; x++)
{
- int channel;
- unsigned char value_a, value_b;
- int pixel_differs = 0;
- for (channel = 0; channel < 4; channel++)
- {
- double diff;
- value_a = row_a[x * 4 + channel];
- value_b = row_b[x * 4 + channel];
- if (value_a != value_b)
- pixel_differs = 1;
- diff = value_a - value_b;
- row[x * 4 + channel] = 128 + diff / 3.0;
- }
- if (pixel_differs) {
+ /* check if the pixels are the same */
+ if ((row_a[x] & mask) != (row_b[x] & mask)) {
+ int channel;
+ pixman_bits_t diff_pixel = 0;
+
+ /* calculate a difference value for all 4 channels */
+ for (channel = 0; channel < 4; channel++) {
+ unsigned char value_a = (row_a[x] >> (channel*8));
+ unsigned char value_b = (row_b[x] >> (channel*8));
+ double diff;
+ diff = value_a - value_b;
+ diff_pixel |= (unsigned char)(128 + diff / 3.0) << (channel*8);
+ }
+
pixels_changed++;
+ row[x] = diff_pixel;
} else {
- row[x*4+0] = 0;
- row[x*4+1] = 0;
- row[x*4+2] = 0;
+ row[x] = 0;
}
- row[x * 4 + 3] = 0xff; /* Set ALPHA to 100% (opaque) */
+ row[x] |= 0xff000000; /* Set ALPHA to 100% (opaque) */
}
}
return pixels_changed;
}
+int
+buffer_diff (unsigned char *buf_a,
+ unsigned char *buf_b,
+ unsigned char *buf_diff,
+ int width,
+ int height,
+ int stride)
+{
+ return buffer_diff_core(buf_a, buf_b, buf_diff, width, height, stride, 0xffffffff);
+}
+
+int
+buffer_diff_noalpha (unsigned char *buf_a,
+ unsigned char *buf_b,
+ unsigned char *buf_diff,
+ int width,
+ int height,
+ int stride)
+{
+ return buffer_diff_core(buf_a, buf_b, buf_diff, width, height, stride, 0x00ffffff);
+}
+
/* Image comparison code courtesy of Richard Worth <richard@theworths.org>
* Returns number of pixels changed, (or -1 on error).
* Also saves a "diff" image intended to visually show where the
diff --git a/test/buffer-diff.h b/test/buffer-diff.h
index a02834f3..2734713a 100644
--- a/test/buffer-diff.h
+++ b/test/buffer-diff.h
@@ -26,7 +26,7 @@
#ifndef BUFFER_DIFF_H
#define BUFFER_DIFF_H
-/* Returns number of pixels changed, (or -1 on error).
+/* Returns number of pixels changed.
* Also fills in a "diff" buffer intended to visually show where the
* images differ.
*/
@@ -38,6 +38,18 @@ buffer_diff (unsigned char *buf_a,
int height,
int stride);
+/* Returns number of pixels changed ignoring the alpha channel.
+ * Also fills in a "diff" buffer intended to visually show where the
+ * images differ.
+ */
+int
+buffer_diff_noalpha (unsigned char *buf_a,
+ unsigned char *buf_b,
+ unsigned char *buf_diff,
+ int width,
+ int height,
+ int stride);
+
/* Returns number of pixels changed, (or -1 on error).
* Also saves a "diff" image intended to visually show where the
* images differ.
diff --git a/test/cairo-test.c b/test/cairo-test.c
index 456d7d85..6759c849 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -1,5 +1,5 @@
/*
- * Copyright  2004 Red Hat, Inc.
+ * Copyright © 2004 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
@@ -23,12 +23,19 @@
* Author: Carl D. Worth <cworth@cworth.org>
*/
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
+#endif
#include <errno.h>
#include <string.h>
+#include <fontconfig/fontconfig.h>
#include "cairo-test.h"
@@ -37,6 +44,10 @@
#include "write-png.h"
#include "xmalloc.h"
+#ifdef _MSC_VER
+#define vsnprintf _vsnprintf
+#endif
+
#define CAIRO_TEST_LOG_SUFFIX ".log"
#define CAIRO_TEST_PNG_SUFFIX "-out.png"
#define CAIRO_TEST_REF_SUFFIX "-ref.png"
@@ -469,6 +480,9 @@ cairo_test_for_target (cairo_test_t *test,
UNWIND_CAIRO:
cairo_destroy (cr);
cairo_surface_destroy (surface);
+
+ cairo_debug_reset_static_data ();
+
target->cleanup_target (target->closure);
UNWIND_STRINGS:
@@ -557,6 +571,10 @@ cairo_test_expecting (cairo_test_t *test, cairo_test_draw_function_t draw,
fclose (cairo_test_log_file);
+#if HAVE_FCFINI
+ FcFini ();
+#endif
+
return ret;
}
diff --git a/test/cairo-test.h b/test/cairo-test.h
index beabc6a5..d35faab8 100644
--- a/test/cairo-test.h
+++ b/test/cairo-test.h
@@ -28,6 +28,7 @@
#include <math.h>
#include <cairo.h>
+#include <cairo-debug.h>
typedef enum cairo_test_status {
CAIRO_TEST_SUCCESS = 0,
diff --git a/test/clip-operator-ref.png b/test/clip-operator-ref.png
new file mode 100644
index 00000000..551d13f7
--- /dev/null
+++ b/test/clip-operator-ref.png
Binary files differ
diff --git a/test/clip-operator.c b/test/clip-operator.c
new file mode 100644
index 00000000..6cc5216c
--- /dev/null
+++ b/test/clip-operator.c
@@ -0,0 +1,205 @@
+/*
+ * 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 <math.h>
+#include "cairo-test.h"
+#include <stdio.h>
+
+#define WIDTH 64
+#define HEIGHT 64
+#define PAD 10
+
+const char png_filename[] = "romedalen.png";
+
+static void
+draw_mask (cairo_t *cr, int x, int y)
+{
+ cairo_surface_t *mask_surface;
+ cairo_t *cr2;
+
+ double width = (int)(0.9 * WIDTH);
+ double height = (int)(0.9 * HEIGHT);
+ x += 0.05 * WIDTH;
+ y += 0.05 * HEIGHT;
+
+ mask_surface = cairo_surface_create_similar (cairo_get_target (cr),
+ CAIRO_CONTENT_ALPHA,
+ width, height);
+ cr2 = cairo_create (mask_surface);
+
+ cairo_save (cr2);
+ cairo_set_source_rgba (cr2, 0, 0, 0, 0); /* transparent */
+ cairo_set_operator (cr2, CAIRO_OPERATOR_SOURCE);
+ cairo_paint (cr2);
+ cairo_restore (cr2);
+
+ cairo_set_source_rgb (cr2, 1, 1, 1); /* white */
+
+ cairo_arc (cr2, 0.5 * width, 0.5 * height, 0.45 * height, 0, 2 * M_PI);
+ cairo_fill (cr2);
+
+ cairo_destroy (cr2);
+
+ cairo_mask_surface (cr, mask_surface, x, y);
+
+ cairo_surface_destroy (mask_surface);
+}
+
+static void
+draw_glyphs (cairo_t *cr, int x, int y)
+{
+ cairo_text_extents_t extents;
+
+ cairo_set_font_size (cr, 0.8 * HEIGHT);
+
+ cairo_text_extents (cr, "FG", &extents);
+ cairo_move_to (cr,
+ x + (WIDTH - extents.width) / 2 - extents.x_bearing,
+ y + (HEIGHT - extents.height) / 2 - extents.y_bearing);
+ cairo_show_text (cr, "FG");
+}
+
+static void
+draw_polygon (cairo_t *cr, int x, int y)
+{
+ double width = (int)(0.9 * WIDTH);
+ double height = (int)(0.9 * HEIGHT);
+ x += 0.05 * WIDTH;
+ y += 0.05 * HEIGHT;
+
+ cairo_new_path (cr);
+ cairo_move_to (cr, x, y);
+ cairo_line_to (cr, x, y + height);
+ cairo_line_to (cr, x + width / 2, y + 3 * height / 4);
+ cairo_line_to (cr, x + width, y + height);
+ cairo_line_to (cr, x + width, y);
+ cairo_line_to (cr, x + width / 2, y + height / 4);
+ cairo_close_path (cr);
+ cairo_fill (cr);
+}
+
+static void
+draw_rects (cairo_t *cr, int x, int y)
+{
+ double block_width = (int)(0.33 * WIDTH + 0.5);
+ double block_height = (int)(0.33 * HEIGHT + 0.5);
+ int i, j;
+
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < 3; j++)
+ if ((i + j) % 2 == 0)
+ cairo_rectangle (cr,
+ x + block_width * i, y + block_height * j,
+ block_width, block_height);
+
+ cairo_fill (cr);
+}
+
+static void (*draw_funcs[])(cairo_t *cr, int x, int y) = {
+ draw_mask,
+ draw_glyphs,
+ draw_polygon,
+ draw_rects
+};
+
+#define N_OPERATORS (1 + CAIRO_OPERATOR_SATURATE - CAIRO_OPERATOR_CLEAR)
+
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
+#define IMAGE_WIDTH (N_OPERATORS * (WIDTH + PAD) + PAD)
+#define IMAGE_HEIGHT (ARRAY_SIZE (draw_funcs) * (HEIGHT + PAD) + PAD)
+
+static cairo_test_t test = {
+ "clip-operator",
+ "Surface clipping with different operators",
+ IMAGE_WIDTH, IMAGE_HEIGHT
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ int j, x, y;
+ cairo_operator_t op;
+ cairo_font_options_t *font_options;
+ cairo_pattern_t *pattern;
+
+ cairo_select_font_face (cr, "Bitstream Vera Sans",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_NORMAL);
+ cairo_set_font_size (cr, 0.9 * HEIGHT);
+
+ font_options = cairo_font_options_create ();
+
+ cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
+ cairo_font_options_set_antialias (font_options, CAIRO_ANTIALIAS_GRAY);
+
+ cairo_set_font_options (cr, font_options);
+ cairo_font_options_destroy (font_options);
+
+ for (j = 0; j < ARRAY_SIZE (draw_funcs); j++) {
+ for (op = CAIRO_OPERATOR_CLEAR; op <= CAIRO_OPERATOR_SATURATE; op++) {
+ x = op * (WIDTH + PAD) + PAD;
+ y = j * (HEIGHT + PAD) + PAD;
+
+ cairo_save (cr);
+
+ pattern = cairo_pattern_create_linear (x + WIDTH, y,
+ x, y + HEIGHT);
+ cairo_pattern_add_color_stop_rgba (pattern, 0.2,
+ 0.0, 0.0, 1.0, 1.0); /* Solid blue */
+ cairo_pattern_add_color_stop_rgba (pattern, 0.8,
+ 0.0, 0.0, 1.0, 0.0); /* Transparent blue */
+ cairo_set_source (cr, pattern);
+ cairo_pattern_destroy (pattern);
+
+ cairo_rectangle (cr, x, y, WIDTH, HEIGHT);
+ cairo_fill (cr);
+
+ cairo_set_operator (cr, op);
+ cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
+
+ cairo_move_to (cr, x, y);
+ cairo_line_to (cr, x + WIDTH, y);
+ cairo_line_to (cr, x, y + HEIGHT);
+ cairo_clip (cr);
+
+ draw_funcs[j] (cr, x, y);
+ if (cairo_status (cr))
+ cairo_test_log ("%d %d HERE!\n", op, j);
+
+ cairo_restore (cr);
+ }
+ }
+
+ if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
+ cairo_test_log ("%d %d .HERE!\n", op, j);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+ return cairo_test (&test, draw);
+}
diff --git a/test/composite-integer-translate-over-repeat.c b/test/composite-integer-translate-over-repeat.c
index ed55f63a..61a0ea71 100644
--- a/test/composite-integer-translate-over-repeat.c
+++ b/test/composite-integer-translate-over-repeat.c
@@ -44,7 +44,7 @@ draw (cairo_t *cr, int width, int height)
cairo_fill (cr);
cairo_translate (cr, OFFSET, OFFSET);
- cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
cairo_set_source (cr, pat);
cairo_rectangle (cr, 0, 0, SIZE - OFFSET, SIZE - OFFSET);
cairo_fill (cr);
diff --git a/test/mask-ctm-ref.png b/test/mask-ctm-ref.png
new file mode 100644
index 00000000..88a0402c
--- /dev/null
+++ b/test/mask-ctm-ref.png
Binary files differ
diff --git a/test/mask-ctm.c b/test/mask-ctm.c
new file mode 100644
index 00000000..1fd48285
--- /dev/null
+++ b/test/mask-ctm.c
@@ -0,0 +1,82 @@
+/*
+ * 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>
+ */
+
+#include "cairo-test.h"
+
+cairo_test_t test = {
+ "mask-ctm",
+ "Test that cairo_mask is affected properly by the CTM",
+ 10, 10
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ cairo_surface_t *mask_surface;
+ cairo_pattern_t *mask;
+ unsigned long data[] = {
+ 0x80000000, 0x80000000,
+ 0x80000000, 0x80000000,
+ };
+ cairo_matrix_t matrix;
+
+ mask_surface = cairo_image_surface_create_for_data ((unsigned char *) data,
+ CAIRO_FORMAT_ARGB32, 2, 2, 8);
+ mask = cairo_pattern_create_for_surface (mask_surface);
+ cairo_surface_destroy (mask_surface);
+
+ cairo_set_source_rgb (cr, 1.0, 0, 0);
+
+ /* We can translate with the CTM, with the pattern matrix, or with
+ * both. */
+
+ /* 1. CTM alone. */
+ cairo_save (cr);
+ {
+ cairo_translate (cr, 2, 2);
+ cairo_mask (cr, mask);
+ }
+ cairo_restore (cr);
+
+ /* 2. Pattern matrix alone. */
+ cairo_matrix_init_translate (&matrix, -4, -4);
+ cairo_pattern_set_matrix (mask, &matrix);
+
+ cairo_mask (cr, mask);
+
+ /* 3. CTM + pattern matrix */
+ cairo_translate (cr, 2, 2);
+ cairo_mask (cr, mask);
+
+ cairo_pattern_destroy (mask);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+ return cairo_test (&test, draw);
+}
diff --git a/test/mask-surface-ctm-ref.png b/test/mask-surface-ctm-ref.png
new file mode 100644
index 00000000..744b1dd3
--- /dev/null
+++ b/test/mask-surface-ctm-ref.png
Binary files differ
diff --git a/test/mask-surface-ctm.c b/test/mask-surface-ctm.c
new file mode 100644
index 00000000..6eb2bf26
--- /dev/null
+++ b/test/mask-surface-ctm.c
@@ -0,0 +1,75 @@
+/*
+ * 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>
+ */
+
+#include "cairo-test.h"
+
+cairo_test_t test = {
+ "mask-surface-ctm",
+ "Test that cairo_mask_surface is affected properly by the CTM",
+ 10, 10
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ cairo_surface_t *mask;
+ unsigned long data[] = {
+ 0x80000000, 0x80000000,
+ 0x80000000, 0x80000000,
+ };
+
+ mask = cairo_image_surface_create_for_data ((unsigned char *) data,
+ CAIRO_FORMAT_ARGB32, 2, 2, 8);
+
+ cairo_set_source_rgb (cr, 1.0, 0, 0);
+
+ /* We can translate with the CTM, with the mask_surface offset, or
+ * with both. */
+
+ /* 1. CTM alone. */
+ cairo_save (cr);
+ {
+ cairo_translate (cr, 2, 2);
+ cairo_mask_surface (cr, mask, 0, 0);
+ }
+ cairo_restore (cr);
+
+ /* 2. Offset alone. */
+ cairo_mask_surface (cr, mask, 4, 4);
+
+ /* 3. CTM + offset */
+ cairo_translate (cr, 2, 2);
+ cairo_mask_surface (cr, mask, 4, 4);
+
+ cairo_surface_destroy (mask);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+ return cairo_test (&test, draw);
+}
diff --git a/test/read-png.c b/test/read-png.c
index 96259dfe..ff311c28 100644
--- a/test/read-png.c
+++ b/test/read-png.c
@@ -35,6 +35,18 @@
# include <inttypes.h>
#elif HAVE_SYS_INT_TYPES_H
# include <sys/int_types.h>
+#elif defined(_MSC_VER)
+ typedef __int8 int8_t;
+ typedef unsigned __int8 uint8_t;
+ typedef __int16 int16_t;
+ typedef unsigned __int16 uint16_t;
+ typedef __int32 int32_t;
+ typedef unsigned __int32 uint32_t;
+ typedef __int64 int64_t;
+ typedef unsigned __int64 uint64_t;
+# ifndef HAVE_UINT64_T
+# define HAVE_UINT64_T 1
+# endif
#else
#error Cannot find definitions for fixed-width integral types (uint8_t, uint32_t, etc.)
#endif
@@ -79,7 +91,7 @@ read_png_argb32 (const char *filename,
{
int i;
FILE *file;
- static const int PNG_SIG_SIZE = 8;
+#define PNG_SIG_SIZE 8
unsigned char png_sig[PNG_SIG_SIZE];
int sig_bytes;
png_struct *png;
diff --git a/test/source-surface-scale-paint-ref.png b/test/source-surface-scale-paint-ref.png
index ec3c059f..a81f93d9 100644
--- a/test/source-surface-scale-paint-ref.png
+++ b/test/source-surface-scale-paint-ref.png
Binary files differ
diff --git a/test/source-surface-scale-paint.c b/test/source-surface-scale-paint.c
index 9862ba59..1af972f2 100644
--- a/test/source-surface-scale-paint.c
+++ b/test/source-surface-scale-paint.c
@@ -28,7 +28,7 @@
cairo_test_t test = {
"source-surface-scale-paint",
"Test call sequence: cairo_set_source_surface; cairo_scale; cairo_paint",
- 12, 12
+ 8, 8
};
static cairo_test_status_t
@@ -59,6 +59,5 @@ draw (cairo_t *cr, int width, int height)
int
main (void)
{
- return cairo_test_expect_failure (&test, draw,
- "cairo_set_source needs user space locking semantics");
+ return cairo_test (&test, draw);
}
diff --git a/test/surface-finish-twice.c b/test/surface-finish-twice.c
index ce4f0659..ad6c0e94 100644
--- a/test/surface-finish-twice.c
+++ b/test/surface-finish-twice.c
@@ -52,7 +52,6 @@ static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
cairo_surface_t *surface;
- cairo_status_t status;
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
diff --git a/test/text-cache-crash.c b/test/text-cache-crash.c
index 547e2a34..08e85739 100644
--- a/test/text-cache-crash.c
+++ b/test/text-cache-crash.c
@@ -118,20 +118,6 @@ main (void)
ret = cairo_test (&test, draw);
- /* It's convenient to be able to free all memory (including
- * statically allocated memory). This makes it quite easy to use
- * tools such as valgrind to verify that there are no memory leaks
- * whatsoever.
- *
- * But I'm not sure what would be a sensible cairo API function
- * for this. The cairo_destroy_caches call below is just something
- * I made as a local modification to cairo.
- */
- /*
- cairo_destroy_caches ();
- FcFini ();
- */
-
return ret;
}
diff --git a/test/unantialiased-shapes-ref.png b/test/unantialiased-shapes-ref.png
new file mode 100644
index 00000000..b9485922
--- /dev/null
+++ b/test/unantialiased-shapes-ref.png
Binary files differ
diff --git a/test/unantialiased-shapes.c b/test/unantialiased-shapes.c
new file mode 100644
index 00000000..eaadf417
--- /dev/null
+++ b/test/unantialiased-shapes.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright © 2005 Billy Biggs
+ *
+ * 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
+ * Billy Biggs not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Billy Biggs makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * BILLY BIGGS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL BILLY BIGGS 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: Billy Biggs <vektor@dumbterm.net>
+ */
+
+#include "cairo-test.h"
+
+cairo_test_t test = {
+ "unantialiased-shapes",
+ "Test shape drawing without antialiasing",
+ 320, 240
+};
+
+/* The star shape from the SVG test suite, from the fill rule test */
+static void
+big_star_path (cairo_t *cr)
+{
+ cairo_move_to (cr, 40, 0);
+ cairo_rel_line_to (cr, 25, 80);
+ cairo_rel_line_to (cr, -65, -50);
+ cairo_rel_line_to (cr, 80, 0);
+ cairo_rel_line_to (cr, -65, 50);
+ cairo_close_path (cr);
+}
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ int i;
+
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_paint (cr);
+
+ cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
+
+ /* Try a circle */
+ cairo_arc (cr, 40, 40, 20, 0, 2 * M_PI);
+ cairo_set_source_rgb (cr, 1, 0, 0);
+ cairo_fill (cr);
+
+ /* Try using clipping to draw a circle */
+ cairo_arc (cr, 100, 40, 20, 0, 2 * M_PI);
+ cairo_clip (cr);
+ cairo_rectangle (cr, 80, 20, 40, 40);
+ cairo_set_source_rgb (cr, 0, 0, 1);
+ cairo_fill (cr);
+
+ /* Reset the clipping */
+ cairo_reset_clip (cr);
+
+ /* Draw a bunch of lines */
+ cairo_set_line_width (cr, 1.0);
+ cairo_set_source_rgb (cr, 0, 1, 0);
+ for (i = 0; i < 10; i++) {
+ cairo_move_to (cr, 10, 70 + (i * 4));
+ cairo_line_to (cr, 120, 70 + (i * 18));
+ cairo_stroke (cr);
+ }
+
+ /* Try filling a poly */
+ cairo_translate (cr, 160, 120);
+ cairo_set_source_rgb (cr, 1, 1, 0);
+ big_star_path (cr);
+ cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_fill (cr);
+ cairo_translate (cr, -160, -120);
+
+ /* How about some curves? */
+ cairo_set_source_rgb (cr, 1, 0, 1);
+ for (i = 0; i < 10; i++) {
+ cairo_move_to (cr, 150, 50 + (i * 5));
+ cairo_curve_to (cr, 250, 50, 200, (i * 10), 300, 50 + (i * 10));
+ cairo_stroke (cr);
+ }
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+ return cairo_test (&test, draw);
+}
diff --git a/test/unbounded-operator-ref.png b/test/unbounded-operator-ref.png
new file mode 100644
index 00000000..7e3b3a07
--- /dev/null
+++ b/test/unbounded-operator-ref.png
Binary files differ
diff --git a/test/unbounded-operator.c b/test/unbounded-operator.c
new file mode 100644
index 00000000..45535b97
--- /dev/null
+++ b/test/unbounded-operator.c
@@ -0,0 +1,201 @@
+/*
+ * 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.
+ *
+ * Authors: Kristian Høgsberg <krh@redhat.com>
+ * Owen Taylor <otaylor@redhat.com>
+ */
+
+#include <math.h>
+#include "cairo-test.h"
+#include <stdio.h>
+
+#define WIDTH 64
+#define HEIGHT 64
+#define PAD 10
+
+static void
+draw_mask (cairo_t *cr, int x, int y)
+{
+ cairo_surface_t *mask_surface;
+ cairo_t *cr2;
+
+ double width = (int)(0.9 * WIDTH);
+ double height = (int)(0.9 * HEIGHT);
+ x += 0.05 * WIDTH;
+ y += 0.05 * HEIGHT;
+
+ mask_surface = cairo_surface_create_similar (cairo_get_target (cr),
+ CAIRO_CONTENT_ALPHA,
+ width, height);
+ cr2 = cairo_create (mask_surface);
+
+ cairo_save (cr2);
+ cairo_set_source_rgba (cr2, 0, 0, 0, 0); /* transparent */
+ cairo_set_operator (cr2, CAIRO_OPERATOR_SOURCE);
+ cairo_paint (cr2);
+ cairo_restore (cr2);
+
+ cairo_set_source_rgb (cr2, 1, 1, 1); /* white */
+
+ cairo_arc (cr2, 0.5 * width, 0.5 * height, 0.45 * height, 0, 2 * M_PI);
+ cairo_fill (cr2);
+
+ cairo_destroy (cr2);
+
+ cairo_mask_surface (cr, mask_surface, x, y);
+
+ cairo_surface_destroy (mask_surface);
+}
+
+static void
+draw_glyphs (cairo_t *cr, int x, int y)
+{
+ cairo_text_extents_t extents;
+
+ cairo_set_font_size (cr, 0.8 * HEIGHT);
+
+ cairo_text_extents (cr, "FG", &extents);
+ cairo_move_to (cr,
+ x + (WIDTH - extents.width) / 2 - extents.x_bearing,
+ y + (HEIGHT - extents.height) / 2 - extents.y_bearing);
+ cairo_show_text (cr, "FG");
+}
+
+static void
+draw_polygon (cairo_t *cr, int x, int y)
+{
+ double width = (int)(0.9 * WIDTH);
+ double height = (int)(0.9 * HEIGHT);
+ x += 0.05 * WIDTH;
+ y += 0.05 * HEIGHT;
+
+ cairo_new_path (cr);
+ cairo_move_to (cr, x, y);
+ cairo_line_to (cr, x, y + height);
+ cairo_line_to (cr, x + width / 2, y + 3 * height / 4);
+ cairo_line_to (cr, x + width, y + height);
+ cairo_line_to (cr, x + width, y);
+ cairo_line_to (cr, x + width / 2, y + height / 4);
+ cairo_close_path (cr);
+ cairo_fill (cr);
+}
+
+static void
+draw_rects (cairo_t *cr, int x, int y)
+{
+ double block_width = (int)(0.33 * WIDTH + 0.5);
+ double block_height = (int)(0.33 * HEIGHT + 0.5);
+ int i, j;
+
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < 3; j++)
+ if ((i + j) % 2 == 0)
+ cairo_rectangle (cr,
+ x + block_width * i, y + block_height * j,
+ block_width, block_height);
+
+ cairo_fill (cr);
+}
+
+static void (*draw_funcs[])(cairo_t *cr, int x, int y) = {
+ draw_mask,
+ draw_glyphs,
+ draw_polygon,
+ draw_rects
+};
+
+static cairo_operator_t operators[] = {
+ CAIRO_OPERATOR_CLEAR, CAIRO_OPERATOR_SOURCE, CAIRO_OPERATOR_IN,
+ CAIRO_OPERATOR_OUT, CAIRO_OPERATOR_DEST_IN, CAIRO_OPERATOR_DEST_ATOP
+};
+
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
+#define IMAGE_WIDTH (ARRAY_SIZE (operators) * (WIDTH + PAD) + PAD)
+#define IMAGE_HEIGHT (ARRAY_SIZE (draw_funcs) * (HEIGHT + PAD) + PAD)
+
+static cairo_test_t test = {
+ "unbounded-operator",
+ "Operators with an effect for transparent source/mask",
+ IMAGE_WIDTH, IMAGE_HEIGHT
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ int i, j, x, y;
+ cairo_font_options_t *font_options;
+ cairo_pattern_t *pattern;
+
+ cairo_select_font_face (cr, "Bitstream Vera Sans",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_NORMAL);
+
+ font_options = cairo_font_options_create ();
+
+ cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
+ cairo_font_options_set_antialias (font_options, CAIRO_ANTIALIAS_GRAY);
+
+ cairo_set_font_options (cr, font_options);
+ cairo_font_options_destroy (font_options);
+
+ for (j = 0; j < ARRAY_SIZE (draw_funcs); j++) {
+ for (i = 0; i < ARRAY_SIZE (operators); i++) {
+ x = i * (WIDTH + PAD) + PAD;
+ y = j * (HEIGHT + PAD) + PAD;
+
+ cairo_save (cr);
+
+ pattern = cairo_pattern_create_linear (x + WIDTH, y,
+ x, y + HEIGHT);
+ cairo_pattern_add_color_stop_rgba (pattern, 0.2,
+ 0.0, 0.0, 1.0, 1.0); /* Solid blue */
+ cairo_pattern_add_color_stop_rgba (pattern, 0.8,
+ 0.0, 0.0, 1.0, 0.0); /* Transparent blue */
+ cairo_set_source (cr, pattern);
+ cairo_pattern_destroy (pattern);
+
+ cairo_rectangle (cr, x, y, WIDTH, HEIGHT);
+ cairo_fill_preserve (cr);
+ cairo_clip (cr);
+
+ cairo_set_operator (cr, operators[i]);
+ cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
+
+ draw_funcs[j] (cr, x, y);
+ if (cairo_status (cr))
+ cairo_test_log ("%d %d HERE!\n", i, j);
+
+ cairo_restore (cr);
+ }
+ }
+
+ if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
+ cairo_test_log ("%d %d .HERE!\n", i, j);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+ return cairo_test (&test, draw);
+}
diff --git a/test/xlib-surface.c b/test/xlib-surface.c
index 2921eb85..0df5514f 100644
--- a/test/xlib-surface.c
+++ b/test/xlib-surface.c
@@ -155,19 +155,19 @@ do_test (Display *dpy,
if (offscreen) {
size_t offset = 4 * (SIZE * OFFSCREEN_OFFSET + OFFSCREEN_OFFSET);
- result = !buffer_diff (reference_data + offset,
- test_data + offset,
- diff_data + offset,
- SIZE - OFFSCREEN_OFFSET,
- SIZE - OFFSCREEN_OFFSET,
- 4 * SIZE);
+ result = !buffer_diff_noalpha (reference_data + offset,
+ test_data + offset,
+ diff_data + offset,
+ SIZE - OFFSCREEN_OFFSET,
+ SIZE - OFFSCREEN_OFFSET,
+ 4 * SIZE);
} else {
- result = !buffer_diff (reference_data,
- test_data,
- diff_data,
- SIZE,
- SIZE,
- 4 * SIZE);
+ result = !buffer_diff_noalpha (reference_data,
+ test_data,
+ diff_data,
+ SIZE,
+ SIZE,
+ 4 * SIZE);
}
fprintf (log_file, "xlib-surface: %s, %s, %s%s: %s\n",
@@ -267,6 +267,8 @@ main (void)
XCloseDisplay (dpy);
+ cairo_debug_reset_static_data ();
+
fclose (log_file);
return result;