summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog555
-rw-r--r--Makefile.am8
-rw-r--r--NEWS152
-rw-r--r--ROADMAP121
-rw-r--r--configure.in55
-rw-r--r--doc/public/Makefile.am4
-rw-r--r--doc/public/cairo-sections.txt31
-rw-r--r--doc/public/language-bindings.xml2
-rw-r--r--doc/public/tmpl/cairo-font.sgml185
-rw-r--r--doc/public/tmpl/cairo-ft.sgml9
-rw-r--r--doc/public/tmpl/cairo-pattern.sgml23
-rw-r--r--doc/public/tmpl/cairo-surface.sgml14
-rw-r--r--doc/public/tmpl/cairo-xlib-xrender.sgml1
-rw-r--r--doc/public/tmpl/cairo-xlib.sgml1
-rw-r--r--doc/public/tmpl/cairo.sgml49
-rw-r--r--doc/tutorial/slides/.cvsignore7
-rw-r--r--doc/tutorial/slides/Makefile7
-rw-r--r--doc/tutorial/slides/cairo-blank.svg487
-rw-r--r--doc/tutorial/slides/cairo-code.svg508
-rw-r--r--doc/tutorial/slides/cairo-separator.svg491
-rw-r--r--doc/tutorial/slides/cairo-title.svg373
-rw-r--r--doc/tutorial/slides/cairo.svg508
-rw-r--r--doc/tutorial/slides/circle-cairo-large.pngbin0 -> 3362 bytes
-rw-r--r--doc/tutorial/slides/circle-cairo.pngbin0 -> 1429 bytes
-rw-r--r--doc/tutorial/slides/circle-ooo-large.pngbin0 -> 1491 bytes
-rw-r--r--doc/tutorial/slides/circle-ooo.pngbin0 -> 383 bytes
-rw-r--r--doc/tutorial/slides/expander-fuzzy-large.pngbin0 -> 1300 bytes
-rw-r--r--doc/tutorial/slides/expander-fuzzy.pngbin0 -> 296 bytes
-rw-r--r--doc/tutorial/slides/expander-sharp-large.pngbin0 -> 929 bytes
-rw-r--r--doc/tutorial/slides/expander-sharp.pngbin0 -> 183 bytes
-rw-r--r--doc/tutorial/slides/fuzzies.svg11
-rw-r--r--doc/tutorial/slides/jaggies.svg11
-rw-r--r--doc/tutorial/slides/tutorial.xml468
-rw-r--r--doc/tutorial/src/.cvsignore7
-rw-r--r--doc/tutorial/src/Makefile30
-rw-r--r--doc/tutorial/src/cairo-tutorial-gtk.h116
-rw-r--r--doc/tutorial/src/cairo-tutorial-pdf.h74
-rw-r--r--doc/tutorial/src/cairo-tutorial-png.h74
-rw-r--r--doc/tutorial/src/cairo-tutorial-xlib.h219
-rw-r--r--doc/tutorial/src/cairo-tutorial.h41
-rw-r--r--doc/tutorial/src/circle.c22
-rw-r--r--doc/tutorial/src/expander.c16
-rw-r--r--src/Makefile.am3
-rw-r--r--src/cairo-array.c5
-rw-r--r--src/cairo-atsui-font.c3
-rw-r--r--src/cairo-font-options.c352
-rw-r--r--src/cairo-font.c218
-rw-r--r--src/cairo-ft-font.c882
-rw-r--r--src/cairo-ft.h4
-rw-r--r--src/cairo-glitz-surface.c126
-rw-r--r--src/cairo-gstate-private.h1
-rw-r--r--src/cairo-gstate.c67
-rw-r--r--src/cairo-image-surface.c90
-rw-r--r--src/cairo-meta-surface.c6
-rw-r--r--src/cairo-path-data-private.h5
-rw-r--r--src/cairo-path-data.c32
-rw-r--r--src/cairo-pattern.c114
-rw-r--r--src/cairo-pdf-surface.c47
-rw-r--r--src/cairo-png.c60
-rw-r--r--src/cairo-ps-surface.c63
-rw-r--r--src/cairo-quartz-surface.c23
-rw-r--r--src/cairo-quartz.h6
-rw-r--r--src/cairo-surface.c374
-rw-r--r--src/cairo-win32-font.c126
-rw-r--r--src/cairo-win32-surface.c41
-rw-r--r--src/cairo-xcb-surface.c51
-rw-r--r--src/cairo-xlib-private.h54
-rw-r--r--src/cairo-xlib-screen.c346
-rw-r--r--src/cairo-xlib-surface.c530
-rw-r--r--src/cairo-xlib-xrender.h1
-rw-r--r--src/cairo-xlib.h7
-rw-r--r--src/cairo.c400
-rw-r--r--src/cairo.h229
-rw-r--r--src/cairoint.h70
-rw-r--r--test/.cvsignore4
-rw-r--r--test/.valgrind-suppressions26
-rw-r--r--test/Makefile.am14
-rw-r--r--test/cairo-test.c8
-rw-r--r--test/create-from-png-stream-ref.pngbin0 -> 100 bytes
-rw-r--r--test/create-from-png-stream.c95
-rw-r--r--test/create-from-png.c17
-rw-r--r--test/surface-finish-twice.c9
-rw-r--r--test/text-antialias-gray-ref.pngbin0 -> 723 bytes
-rw-r--r--test/text-antialias-gray.c77
-rw-r--r--test/text-antialias-none-ref.pngbin0 -> 277 bytes
-rw-r--r--test/text-antialias-none.c77
-rw-r--r--test/text-antialias-subpixel.c82
87 files changed, 8391 insertions, 1034 deletions
diff --git a/ChangeLog b/ChangeLog
index b7e6f2b91..25f8a8f7d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,558 @@
+2005-07-28 Carl Worth <cworth@cworth.org>
+
+ * NEWS: Added notes for snapshot 0.6.0
+
+ * configure.in: Increment CAIRO_VERSION to 0.6.0
+
+2005-07-28 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-ft-font.c: (_move_to), (_line_to), (_conic_to),
+ (_cubic_to): Remove const qualifiers that only make things happy
+ with a from-cvs version of freetype. Now we should be back to
+ being happy with a released version.
+
+2005-07-28 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-png.c (read_png): Add missing cast.
+
+2005-07-28 Carl Worth <cworth@cworth.org>
+
+ * test/Makefile.am (EXTRA_DIST): Remove
+ text-antialias-subpixel-ref.png from the list since it doesn't
+ exist yet.
+
+2005-07-28 Carl Worth <cworth@cworth.org>
+
+ * doc/public/tmpl/cairo.sgml: More doc/public/tmpl churn.
+
+2005-07-28 Carl Worth <cworth@cworth.org>
+
+ * test/Makefile.am (EXTRA_DIST): Add
+ text-antialias-{gray|none|subpixel}-ref.png so they get
+ distributed.
+
+2005-07-28 Dave Beckett <Dave.Beckett@bristol.ac.uk>
+
+ * test/cairo-test.c (cairo_test_create_surface_from_png): Use
+ cairo_surface_status(image) instead of testing for NULL from
+ cairo_image_surface_create_from_png to enable testing when srcdir
+ != builddir again.
+
+2005-07-28 Carl Worth <cworth@cworth.org>
+
+ * ROADMAP: Note that consistent error handling is done now.
+
+2005-07-28 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-image-surface.c: (cairo_image_surface_get_width),
+ (cairo_image_surface_get_height): Fix to call _cairo_error and
+ return 0 on surface-type mismatch.
+
+2005-07-28 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in Makefile.am: Skip tests/ directory if
+ libpng was disabled. (#3423, reported by Steve Chaplin)
+
+2005-07-28 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-png.c: (read_png),
+ (cairo_image_surface_create_from_png): Fix so that one of three
+ different error status values will be returned:
+
+ CAIRO_STATUS_NO_MEMORY
+ CAIRO_STATUS_FILE_NOT_FOUND
+ CAIRO_STATUS_READ_ERROR
+
+ * src/cairo.h:
+ * src/cairo.c: (cairo_status_to_string): Add new
+ CAIRO_STATUS_FILE_NOT_FOUND.
+
+ * src/cairoint.h:
+ * src/cairo-surface.c: Add new _cairo_surface_nil_read_error and
+ _cairo_surface_nil_file_not_found.
+
+ * test/create-from-png.c: (draw): Test the new FILE_NOT_FOUND
+ error.
+
+2005-07-28 Stuart Parmenter <pavlov@pavlov.net>
+
+ * src/cairo-win32-font.c
+ * src/cairo-win32-surface.c
+ Use surface->base.status instead of just surface on
+ cairo_win32_surface_t *s
+
+2005-07-28 Owen Taylor <otaylor@redhat.com>
+
+ * configure.in: Disable PS surface build if no freetype.
+
+2005-07-28 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-win32-font.c (_draw_glyphs_on_surface): Pass
+ -1 not 1 to RestoreDC to restore to the last SaveDC.
+ (#3905, Stuart Parmenter)
+
+2005-07-16 Owen Taylor <otaylor@redhat.com>
+
+ Patch from Martin Kretzschmar <martink@gnome.org>, #3798
+
+ * src/cairo-xlib-surface.c (_get_image_surface): prevent
+ sign-extension of masks.*_mask on 64bit architectures.
+
+ * src/cairo-xcb-surface.c (_get_image_surface): ditto.
+
+2005-07-28 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-image-surface.c (_cairo_image_surface_acquire_source,dest_image)
+ src/cairo-quartz-surface.c (_cairo_quartz_surface_acquire_dest_image)
+ src/cairo-xcb-surface.c (_cairo_xcb_surface_acquire_source,dest_image):
+ src/cairo-xlib-surface.c (_cairo_xlib_surface_acquire_source,dest_image):
+ Set image_extra to NULL to avoid purify warnings. (#3777, Stuart Parmenter)
+
+2005-07-27 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h:
+ * src/cairo-path-data-private.h:
+ * src/cairo-path-data.c:
+ * src/cairo-pattern.c:
+ * src/cairo-surface.c:
+ Remove all create_in_error functions as they were just muddling up
+ the memory management semantics:
+
+ _cairo_path_data_create_in_error
+ _cairo_pattern_create_in_error
+ _cairo_surface_create_in_error
+
+ * src/cairo-gstate.c: (_cairo_gstate_mask),
+ (_composite_traps_intermediate_surface),
+ (_cairo_gstate_intersect_clip_mask), (_cairo_gstate_show_glyphs):
+
+ Don't bother with extra check of other->status to anticipate and
+ try to prevent cairo_surface_create_similar from returning through
+ cairo_surface_create_in_error.
+
+ * src/cairo-glitz-surface.c: (cairo_glitz_surface_create):
+ * src/cairo-image-surface.c: (cairo_image_surface_create),
+ (cairo_image_surface_create_for_data):
+ * src/cairo-png.c: (cairo_image_surface_create_from_png):
+ * src/cairo-surface.c: (_cairo_surface_create_similar_scratch),
+ (cairo_surface_create_similar),
+ (_cairo_surface_create_similar_solid):
+ * src/cairo-win32-surface.c: (_cairo_win32_surface_create_for_dc):
+ * src/cairo-xlib-surface.c: (cairo_xlib_surface_create):
+ * src/cairo.c: (cairo_get_source), (cairo_get_font_face):
+ (cairo_get_target), (cairo_copy_path), (cairo_copy_path_flat):
+
+ Just return &_cairo_surface|pattern|path_nil rather than
+ _cairo_surface|pattern|path_create_in_error.
+
+ * src/cairo-ft-font.c:
+ * src/cairo-glitz-surface.c:
+ * src/cairo-gstate.c:
+ * src/cairo-pattern.c:
+ * src/cairo-ps-surface.c:
+ * src/cairo-win32-font.c:
+ * src/cairo-win32-surface.c:
+ * src/cairo-xcb-surface.c:
+ * src/cairo-xlib-surface.c:
+ After checking surface->status from a cairo_<foo>_surface_create
+ function, just return CAIRO_STATUS_NO_MEMORY since that's the only
+ error we'll get from one of these create functions.
+
+ * src/cairo-gstate.c: (_cairo_gstate_get_target):
+ Remove unnecessary check for gstate == NULL;
+
+ * src/cairo-pattern.c:
+ (_cairo_pattern_acquire_surface_for_gradient): Fix old check for
+ image == NULL instead of image->base.status.
+
+ * src/cairo-quartz-surface.c:
+ (_cairo_quartz_surface_acquire_source_image):
+
+ Add missing check of surface->image_base.status after creating
+ surface->image.
+
+ * src/cairo-xcb-surface.c: (_cairo_xcb_surface_create_similar):
+ * src/cairo-xlib-surface.c: (_cairo_xlib_surface_create_similar):
+ Add missing check of surface->base.status after creating surface.
+
+2005-07-27 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-font.c src/cairoint.h: Define _cairo_font_face_nil.
+ (cairo_font_face_reference, cairo_font_face_destroy
+ cairo_font_face_set_user_data): Handle a nil font face.
+ (cairo_font_face_status): New function.
+
+ * src/cairo-font.c (_cairo_simple_font_face_create)
+ src/cairo-ft-font.c (cairo_ft_font_face_create_for_pattern):
+ src/cairo-ft-font.c (cairo_ft_font_face_create_for_ft_face):
+ src/cairo-win32-font.c (cairo_win32_font_face_create_for_logfontw):
+ Return _cairo_font_face_nil on out-of-memory.
+
+ * src/cairo-gstate.c (_cairo_gstate_select_font_face)
+ * src/cairo-gstate.c (_cairo_gstate_ensure_font_face): Check return
+ of _cairo_simple_font_face_create().
+
+ * src/cairo-gstate.c (_cairo_gstate_set_font_face): Error out
+ if font_face has a status.
+
+ * src/cairo-surface.c (cairo_surface_set_user_data): Handle a nil
+ surface.
+
+2005-07-27 Owen Taylor <otaylor@redhat.com>
+
+ * test/Makefile.am (XFAIL_TESTS): Remove
+ text-antialias-none which is now fixed.
+
+ * test/text-antialias-none.c (main): No longer xfail.
+
+2005-07-27 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-win32-font.c (_win32_scaled_font_create):
+ * src/cairo-ft-font.c (_ft_scaled_font_create): Go back to
+ returning NULL.
+
+ * src/cairoint.h src/cairo-ft-font.c: Stop exporting
+ _cairo_scaled_font_nil, since we dont' need it publically
+ any more.
+
+ * src/cairo-surface.c (_cairo_surface_reset_clip): return
+ surface->status not status. (Fixes warning)
+
+2005-07-26 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.h: Add CAIRO_STATUS_INVALID_CONTENT,
+ CAIRO_STATUS_INVALID_FORMAT, and CAIRO_STATUS_INVALID_VISUAL.
+
+ Change functions to return type of void:
+
+ cairo_scaled_font_extents
+ cairo_surface_finish
+
+ Add new functions to query object status:
+
+ cairo_scaled_font_status
+ cairo_surface_status
+
+ * doc/public/tmpl/cairo.sgml:
+ * src/cairo-array.c:
+ * src/cairo-atsui-font.c:
+ * src/cairo-font.c:
+ * src/cairo-ft-font.c:
+ * src/cairo-glitz-surface.c:
+ * src/cairo-gstate.c:
+ * src/cairo-image-surface.c:
+ * src/cairo-meta-surface.c:
+ * src/cairo-path-data.c:
+ * src/cairo-pattern.c:
+ * src/cairo-pdf-surface.c:
+ * src/cairo-png.c:
+ * src/cairo-ps-surface.c:
+ * src/cairo-quartz-surface.c:
+ * src/cairo-surface.c:
+ * src/cairo-win32-font.c:
+ * src/cairo-win32-surface.c:
+ * src/cairo-xcb-surface.c:
+ * src/cairo-xlib-surface.c:
+ * src/cairo.c:
+ * src/cairoint.h: Implementation of new error handling scheme for
+ cairo_surface_t and cairo_scaled_font_t.
+
+ * test/surface-finish-twice.c: Track change in return value of
+ cairo_surface_finish.
+
+2005-07-27 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-xlib-surface.c (_cairo_xlib_surface_get_font_options):
+ Turn off antialiasing for rendering to alpha surfaces.
+
+2005-07-27 Carl Worth <cworth@cworth.org>
+
+ * ROADMAP: Note that the XFAIL tests all need to be fixed before
+ 1.0.
+
+ * test/.cvsignore:
+ * test/Makefile.am:
+ * test/text-antialias-gray-ref.png:
+ * test/text-antialias-gray.c: (draw), (main):
+ * test/text-antialias-none-ref.png:
+ * test/text-antialias-none.c: (draw), (main):
+ * test/text-antialias-subpixel.c: (draw), (main): Add three new
+ tests for testing the various antialiasing options for text
+ rendering.
+
+2005-07-27 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-png.c: (cairo_image_surface_create_from_png_stream):
+ Fix typo that caused cairo_image_surface_create_from_png_stream to
+ segfault. Closes bug #3863 (thanks to Steve Chaplin).
+
+ * test/.cvsignore:
+ * test/Makefile.am:
+ * test/create-from-png-stream-ref.png:
+ * test/create-from-png-stream.c:
+ * test/create-from-png.c: Add a test to actually call
+ cairo_image_surface_create_from_png_stream.
+
+2005-07-27 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-xlib-surface.c (_xlib_glyphset_cache_create_entry): Deal
+ with glyphs with entry->im->image NULL. (This can happen if fonts
+ have size-zero bitmaps for some characters, for example)
+ (http://bugzilla.gnome.org/show_bug.cgi?id=311709, Sangu Kim)
+
+2005-07-27 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-ft-font.c (_get_bitmap_surface): FreeType bitmaps may
+ only be padded out to 8-bit boundaries, not 32-bit boundaries.
+ (_render_glyph_bitmap): Fix sign error in using glyphslot->bitmap_left.
+
+2005-07-27 David Reveman <davidr@novell.com>
+
+ * src/cairo-xlib-surface.c (_cairo_xlib_screen_from_visual): Trivial
+ fix for typo that caused infinite loop when using non-default visuals.
+
+2005-07-25 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h:
+ * src/cairo-font.c:
+ * src/cairo-ft-font.c:
+ * src/cairo-glitz-surface.c:
+ * src/cairo-pdf-surface.c: Replace all occurences of refcount with
+ ref_count.
+
+ * doc/public/language-bindings.xml: Replace refcounted with
+ reference-counted.
+
+2005-07-25 Owen Taylor <otaylor@redhat.com>
+
+ reviewed by: cworth
+
+ * src/cairo.[ch] src/cairo-gstate-private.h src/cairo-gstate.c
+ src/cairoint.c: Add cairo_{get,set}_font_options().
+
+ * doc/public/Makefile.am (IGNORE_HFILES): Add cairo-xlib-private.h
+
+ * doc/public/cairo-sections.txt: Update
+
+2005-07-24 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-ft-font.c (_render_glyph_outline): Fix size of allocated buffer
+ for vertical subpixel rendering. (Reported by Fryderyk Dziarmagowski,
+ http://bugzilla.gnome.org/show_bug.cgi?id=310935)
+ (_get_pattern_load_flags): Fix a problem where we were OR'ing multiple
+ FT_LOAD_* flags together.
+
+ * src/cairo-xlib-screen.c (_cairo_xlib_init_screen_font_options): Fix
+ reversed check for subpixel or not.
+
+2005-07-23 Malcolm Tredinnick <malcolm@commsecure.com.au>
+
+ * src/cairo-ft-font.c:
+ * src/cairo.h: Add some missing parameters for API docs.
+
+2005-07-23 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-xlib-private.h src/cairo-xlib-screen.c: Switch to using
+ Screen * not screen number to match surface code.
+
+ * src/cairo-xlib-screen.c: Get the screen info for the right screen
+ for the surface.
+
+2005-07-22 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-ft-font.c: Protect against division by zero in various places.
+ (http://bugzilla.gnome.org/show_bug.cgi?id=311299, reported by Ali Akcaagac)
+
+2005-07-22 Owen Taylor <otaylor@redhat.com>
+
+ Patch from Tor Lillqvist <tml@novell.com>
+
+ * src/cairo-win32-font.c: Define TT_PRIM_CSPLINE if it wasn't in
+ the headers.
+ (_get_system_quality): Add missing variable smoothing_type.
+
+2005-07-22 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h: Get the case right. It's cairo, not Cairo.
+
+2005-07-22 Carl Worth <cworth@cworth.org>
+
+ * ROADMAP: Note that sub-pixel text rendering is done now.
+
+2005-07-21 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-ft-font.c: The FT_LOAD_TARGET_* flags aren't separate
+ bitfields, but rather an embedded subfield, so test with
+ FT_LOAD_TARGET_MODE (val->key.flags) == FT_RENDER_LCD, and similar.
+
+2005-07-21 Keith Packard <keithp@keithp.com>
+
+ reviewed by: cworth, otaylor
+
+ * src/cairo-ft-font.c: (_ft_font_cache_create_entry),
+ (_ft_unscaled_font_set_scale), (_native_byte_order_lsb),
+ (_get_bitmap_surface), (_render_glyph_outline),
+ (_render_glyph_bitmap), (_get_pattern_load_flags),
+ (_get_options_load_flags):
+ * src/cairo-xlib-surface.c: (cairo_xlib_surface_set_size),
+ (_native_byte_order_lsb), (_xlib_glyphset_cache_create_entry),
+ (_xlib_glyphset_cache_destroy_entry), (_get_glyphset_cache),
+ (_select_text_mask_format), (_cairo_xlib_surface_show_glyphs32),
+ (_cairo_xlib_surface_show_glyphs16),
+ (_cairo_xlib_surface_show_glyphs8):
+ * src/cairoint.h:
+
+ Add ARGB glyph support.
+
+ Change Bi-level glyph support to use A1 format.
+
+ Support bit/byte swapping of glyph image data in
+ the Xlib backend.
+
+2005-07-21 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-ft.h:
+ * src/cairo-quartz.h: Whitespace fixes.
+
+2005-07-21 David Reveman <davidr@novell.com>
+
+ * src/cairo-glitz-surface.c (_cairo_glitz_area_move_out): Check if
+ empty area.
+
+2005-07-21 Keith Packard <keithp@keithp.com>
+
+ reviewed by: otaylor, cworth
+
+ * ROADMAP:
+ * src/cairo-xlib-surface.c: (cairo_xlib_surface_set_drawable):
+ * src/cairo-xlib.h:
+ Add cairo_xlib_surface_set_drawable which changes the
+ target drawable for an xlib cairo_t to another which
+ shares the same format, screen and display.
+
+2005-07-21 Carl Worth <cworth@cworth.org>
+
+ * ROADMAP: Note that cairo_font_options_t is done now.
+
+2005-07-13 Owen Taylor <otaylor@redhat.com>
+
+ reviewed by: cworth
+
+ * src/cairo-font-options.c src/cairo.h src/cairoint.h
+ src/Makefile.am: Add an opaque cairo_font_options_t structure.
+
+ * src/cairo-font.c src/cairo.h src/cairoint.h: Add a
+ cairo_font_options_t object to cairo_scaled_font_create().
+
+ * src/cairo-surface.c src/cairoint.h: Add virtualized
+ cairo_surface_get_font_options() to get the font options for
+ a surface.
+
+ * src/cairo-gstate.c: Adapt to cairo_scaled_font_create() change.
+
+ * src/cairo-pdf-surface.c: Add an implementation of
+ get_font_options() that turns off metrics hinting.
+
+ * src/cairo-xlib-screen.c src/cairo-xlib-private.h: Add
+ a "screen info" structure that holds (for now) information
+ about the default font options for the screen.
+
+ * src/cairo-xlib-surface.c: Implement get_font_options()
+
+ * src/cairo-ft-font.c src/cairo-ft.h: Add functions to apply
+ a cairo_font_options_t to a FcPattern or get the load flags
+ for a cairo_font_options_t.
+
+ * src/cairo-ft-font.c: Adapt to font options additions.
+ Add support for non-antialiased rendering of scalable fonts.
+ Add support for turning off metrics hinting.
+
+ * src/cairo-win32-font.c: Adapt to font options additions.
+
+ * doc/public/Makefile.am doc/public/cairo-sections.txt: Update.
+
+2005-07-21 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-glitz-surface.c:
+ (_cairo_glitz_pattern_release_surface),
+ (_cairo_glitz_pattern_acquire_surfaces),
+ (_cairo_glitz_surface_composite),
+ (_cairo_glitz_surface_composite_trapezoids),
+ (_cairo_glitz_surface_show_glyphs): Finally grepped through and
+ fixed up the last remaining calls to
+ cairo_pattern_release_surface.
+
+2005-07-21 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-xcb-surface.c: (_cairo_xcb_surface_composite),
+ (_cairo_xcb_surface_composite_trapezoids): Fix yet another file
+ that I missed when I made the cairo_pattern_release_surface
+ change. You would think that I would have grepped for all uses of
+ this function by now.
+
+2005-07-21 Carl Worth <cworth@cworth.org>
+
+ * ROADMAP: Mark cairo_xlib_surface_create as complete. Move
+ cairo_xlib_surface_set_drawable from 0.6 to 1.0 since it is an API
+ addition, not a change.
+
+2005-07-20 Carl Worth <cworth@cworth.org>
+
+ reviewed by: keithp
+
+ * src/cairo.h (CAIRO_CONTENT_VALID): Fix macro to not consider
+ CAIRO_FORMAT_ARGB32 (==0) as a valid cairo_content_t.
+
+2005-07-20 Keith Packard <keithp@keithp.com>
+
+ reviewed by: otaylor
+
+ * src/cairo-xlib-surface.c: (_cairo_xlib_surface_create_similar),
+ (_cairo_xlib_surface_same_screen),
+ (_cairo_xlib_surface_clone_similar), (_surfaces_compatible),
+ (_categorize_composite_operation),
+ (_cairo_xlib_surface_create_internal),
+ (_cairo_xlib_screen_from_visual), (cairo_xlib_surface_create),
+ (cairo_xlib_surface_create_for_bitmap),
+ (cairo_xlib_surface_create_with_xrender_format):
+ * src/cairo-xlib-xrender.h:
+ * src/cairo-xlib.h:
+ * test/cairo-test.c: (create_xlib_surface):
+
+ Add Screen* arguments to:
+
+ cairo_xlib_surface_create_with_xrender_format
+ cairo_xlib_surface_create_for_bitmap
+
+ Required to correctly identify when two Xlib surfaces are
+ compatible with Core and Render rendering requests.
+
+ cairo_xlib_surface_create can determine the screen given
+ the required Visual *
+
+2005-07-20 Carl Worth <cworth@cworth.org>
+
+ * ROADMAP: Move all API changes from 1.0 to 0.6. Other 1.0 API
+ issues are strictly additions.
+
+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.
+
2005-07-18 Carl Worth <cworth@cworth.org>
* src/cairo-quartz-surface.c:
diff --git a/Makefile.am b/Makefile.am
index 31aea9118..c2a9965a6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,10 @@
-SUBDIRS = src test doc
+DIST_SUBDIRS = src test doc
+SUBDIRS = src doc
+
+# libpng is required for our test programs
+if CAIRO_HAS_PNG_FUNCTIONS
+SUBDIRS += test
+endif
EXTRA_DIST = \
COPYING \
diff --git a/NEWS b/NEWS
index 1859a71bc..e39f95742 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,155 @@
+Snapshot 0.6.0 (2005-07-28 Carl Worth <cworth@cworth.org>)
+==========================================================
+API changes
+-----------
+* The prototypes of the following functions have changed:
+
+ cairo_xlib_surface_create_with_xrender_format
+ cairo_xlib_surface_create_for_bitmap
+
+ A Screen* parameter has been added to each. This allows the cairo
+ xlib backend to work correctly with multi-head X servers.
+
+* The following function has been modified:
+
+ cairo_scaled_font_create
+
+ to accept a cairo_font_options_t*. See below fore more details.
+
+* All opaque, reference-counted cairo objects have now been moved to a
+ standard error-handling scheme. The new objects to receive this
+ treatment are cairo_font_face_t, cairo_scaled_font_t, and
+ cairo_surface_t. (Previous snapshots already provided this scheme
+ for cairo_t, cairo_path_t, and cairo_pattern_t.)
+
+ This changes two functions to have a return type of void rather than
+ cairo_status_t:
+
+ cairo_scaled_font_extent
+ cairo_surface_finish
+
+ And significantly, none of the create functions for any of the
+ objects listed above will return NULL. The pointer returned from any
+ function will now always be a valid pointer and should always be
+ passed to the corresponding destroy function when finished
+
+ The simplest strategy for porting code is to switch from:
+
+ object = cairo_<object>_create ();
+ if (object == NULL)
+ goto BAILOUT;
+
+ /* act on object */
+
+ cairo_<object>_destroy (object);
+
+ to:
+
+ object = cairo_<object>_create ();
+ if (cairo_<object>_status (object))
+ goto BAILOUT;
+
+ /* act on object */
+
+ cairo_<object>_destroy (object);
+
+ But significantly, it is not required to check for an error status
+ before the "act on object" portions of the code above. All
+ operations on an object with an error status are, by definition,
+ no-ops without side effect. So new code might be written in an
+ easier-to-read style of:
+
+ object = cairo_<object>_create ();
+
+ /* act on object */
+
+ cairo_<object>_destroy (object);
+
+ with cairo_<object>_status checks placed only at strategic
+ locations. For example, passing an error object to another object,
+ (eg. cairo_set_source with an in-error pattern), will propagate the
+ error to the subsequent object (eg. the cairo_t). This means that
+ error checking can often be deferred even beyond the destruction of
+ a temporary object.
+
+API additions
+-------------
+* New functions for checking the status of objects that have been
+ switched to the common error-handling scheme:
+
+ cairo_font_face_status
+ cairo_scaled_font_status
+ cairo_surface_status
+
+* The _cairo_error function which was added in 0.5.1 has now been made
+ much more useful. In 0.5.1 only errors on cairo_t objects passed
+ through _cairo_error. Now, an error on any object should pass
+ through _cairo_error making it much more reliable as a debugging
+ mechanism for finding when an error first occurs.
+
+* Added new font options support with a myriad of functions:
+
+ cairo_font_options_create
+ cairo_font_options_copy
+ cairo_font_options_destroy
+
+ cairo_font_options_status
+
+ cairo_font_options_merge
+ cairo_font_options_equal
+ cairo_font_options_hash
+
+ cairo_font_options_set_antialias
+ cairo_font_options_get_antialias
+ cairo_font_options_set_subpixel_order
+ cairo_font_options_get_subpixel_order
+ cairo_font_options_set_hint_style
+ cairo_font_options_get_hint_style
+ cairo_font_options_set_hint_metrics
+ cairo_font_options_get_hint_metrics
+
+ cairo_surface_get_font_options
+
+ cairo_ft_font_options_substitute
+
+ cairo_set_font_options
+ cairo_get_font_options
+
+ This new font options support allows the application to have much
+ more fine-grained control over how fonts are rendered.
+ Significantly, it also allows surface backends to have some
+ influence over the process. For example, the xlib backend now
+ queries existing Xft properties to set font option defaults.
+
+* New function:
+
+ cairo_xlib_surface_set_drawable
+
+ which allos the target drawable for an xlib cairo_surface_t to be
+ changed to another with the same format, screen, and display. This
+ is necessary in certain double-buffering techniques.
+
+New features
+------------
+* Sub-pixel text antialiasing is now supported.
+
+Bug fixes
+---------
+* Fixed assertion failure in cairo_surface_create_similar when
+ application commits an error by passing a cairo_format_t rather than
+ a cairo_content_t.
+
+* Avoid division by zero in various places (cairo-ft).
+
+* Fix infinite loop when using non-default visuals (cairo-xlib).
+
+* Eliminate segfault in cairo_image_surface_create_from_png_stream.
+
+* Prevent errant sign-extension of masks on 64-bit architectures
+ (cairo-xlib and cairo-xcb).
+
+* Other miscellaneous fixes.
+
Snapshot 0.5.2 (2005-07-18 Carl Worth <cworth@cworth.org>)
==========================================================
API changes
diff --git a/ROADMAP b/ROADMAP
index d979adbbb..7c2d049be 100644
--- a/ROADMAP
+++ b/ROADMAP
@@ -1,30 +1,24 @@
-cairo 0.5.2
-===========
-✓ Get tor to sign off that the win32 stuff is up to snuff
- ✓ glyph path patch reviewed and committed
-
-✓ Fix the BadMatch error introduced between 0.5.0 and 0.5.1:
- https://bugs.freedesktop.org/show_bug.cgi?id=3604
+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:
- (It turns out this was just exposing an old bug in libpixman
- 0.1.4 which is already fixed in libpixman 0.1.5)
+API changes
+-----------
+✓ A9. consistent error handling for all objects
+ Difficulty: Easy to implement to get the API right. Hard to test.
+ Status: Done.
- Add a workaround for Render's overlapping source/dest bug
- ✓ Use XCopyArea when possible (integer translation)
- Otherwise make a copy of the source
+✓ A10. cairo_font_options_t
+ Difficulty: Moderate
+ Status: Done.
- Fix the cache lock deadlocking problems.
- Difficulty: Hard
- Status: The cache code was ugly enough that I ended up doing a
- major rewrite rather than just reviewing the
- locking. The upside is that the rewrite should also
- add the missing metrics caches which will fix some
- performance problems with text measurement. Almost
- done now.
+✓ 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
@@ -36,21 +30,27 @@ Implementation work
Status: krh has committed cairo_meta_surface_t and a preliminary
version of cairo_ps_surface_t that uses it.
- I3. Add support for sub-pixel (ARGB) rendering of text.
- Status: keithp walked cworth through this. Patch sent to the
- list is almost complete.
+✓I3. Add support for sub-pixel (ARGB) rendering of text.
+ Status: Done.
-API Issues (more detail in TODO file)
--------------------------------------
-✓A1. Add cairo_paint
- Difficulty: moderate or moderate to minor
- Dependencies: much easier after [I1]. needs some cleanups from [A4]
- Status: Done
+ I4. Fix the cache lock deadlocking problems.
+ Difficulty: Hard
+ Status: The cache code was ugly enough that I ended up doing a
+ major rewrite rather than just reviewing the
+ locking. The upside is that the rewrite should also
+ add the missing metrics caches which will fix some
+ performance problems with text measurement. Almost
+ done now.
+
+ I5. Finish the workaround for Render's overlapping source/dest bug
+ (Copy the source as needed)
-✓A2. Add cairo_mask
- Difficulty: moderate
- Status: Done
+ I6. Fix all expected failures (XFAIL) in the test suite. Either
+ there's a bug that needs to be fixed, or there are illegitimate
+ tests that should be removed.
+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
@@ -60,69 +60,20 @@ API Issues (more detail in TODO file)
krh, and otaylor answered all the tough questions it
raised. There's not much work left to finish this one.
-✓A4. Make set_source consistent
- Difficulty: easy
- Dependencies: needs [A2,A3] to avoid losing functionality,
- (but we may just live with that as we've now got
- a circular dependency)
- Status: Done.
-
-✓A5. Add cairo_clip/fill/stroke_preserve
- Difficulty: easy
- Status: Done.
-
-✓A6. Just eliminate a bunch of functions:
-
- ✓ cairo_set_target_*
- ✓ cairo_copy
- ✓ cairo_surface_set_repeat/matrix/filter
- ✓ cairo_show_surface
-
- Difficulty: trivial
- Dependencies: eliminating cairo_show_surface depends on [A1]
- Status: Done.
-
A7. cairo_surface_mark_dirty
Difficulty: trivial to add API, moderate to actually optimize
based on it
Status: cworth has sent API proposal to list
-✓A8. cairo_content_t:
- Difficulty: moderate. It's just going through and examining
- each use of cairo_format_t, but there are a lot
- of them.
- Status: Done.
-
- A9. consistent error handling for all objects
- Difficulty: Easy to implement to get the API right. Hard to test.
- Status: Done for cairo_t, cairo_path_t, and cairo_pattern_t.
- Still need to do cairo_font_face_t,
- cairo_scaled_font_t, and cairo_surface_t.
-
- A10. cairo_font_options_t
- Difficulty: Moderate
- Status: Owen has done all the hard thinking, and we've got
- consensus on the API now. Owen's working on a patch.
-
- A11. cairo_xlib_surface_create needs to be screen-aware
+✓A12. cairo_xlib_surface_set_drawable
Difficulty: Easy
- Status: Keith has cooked up a patch with an APi that should be
- sufficient. It still needs testing on multi-screen X
- server.
-
- A12. cairo_xlib_surface_set_drawable
- Difficulty: Easy
- Status: Keith has a patch sitting ready on the list.
+ Status: Done.
Performance work
----------------
-✓P1. Make pixel-aligned rectangle compositing fast
- Difficulty: moderate to easy
- Status: Done.
-
P2. Generate better trapezoids to go easier on the rasterizer
Difficulty: moderate to hard
Status: cworth drafted a plan to the list
P3. Glyph measurement needs to be sped up.
- Status: Now planned as part of "cache lock deadlock" above.
+ Status: Now planned as part of I4 above ("cache lock deadlock")
diff --git a/configure.in b/configure.in
index 7d6aa47d5..27fe96fa3 100644
--- a/configure.in
+++ b/configure.in
@@ -5,7 +5,7 @@ AC_INIT(src/cairo.h)
dnl ===========================================================================
# Package version number, (as distinct from shared library version)
-CAIRO_VERSION=0.5.2
+CAIRO_VERSION=0.6.0
# libtool shared library version
@@ -151,29 +151,6 @@ AC_SUBST(WIN32_FONT_FEATURE)
dnl ===========================================================================
-AC_ARG_ENABLE(ps,
- [ --disable-ps Disable cairo's PostScript backend],
- [use_ps=$enableval], [use_ps=yes])
-
-# The postscript module requires zlib.
-AC_CHECK_LIB(z, compress,
- [AC_CHECK_HEADER(zlib.h, [],
- [use_ps="no (requires zlib http://www.gzip.org/zlib/)"])],
- [use_ps="no (requires zlib http://www.gzip.org/zlib/)"])
-
-AM_CONDITIONAL(CAIRO_HAS_PS_SURFACE, test "x$use_ps" = "xyes")
-if test "x$use_ps" = "xyes"; then
- PS_SURFACE_FEATURE="#define CAIRO_HAS_PS_SURFACE 1"
- PS_LIBS=-lz
-fi
-AC_SUBST(PS_SURFACE_FEATURE)
-
-CAIRO_LIBS="$CAIRO_LIBS $PS_LIBS"
-
-AC_SUBST(PS_LIBS)
-
-dnl ===========================================================================
-
AC_ARG_ENABLE(png,
[ --disable-png Disable cairo's PNG functions],
[use_png=$enableval], [use_png=yes])
@@ -200,6 +177,8 @@ fi
AM_CONDITIONAL(CAIRO_HAS_PNG_FUNCTIONS, test "x$use_png" = "xyes")
if test "x$use_png" = "xyes"; then
PNG_FUNCTIONS_FEATURE="#define CAIRO_HAS_PNG_FUNCTIONS 1"
+else
+ AC_MSG_WARN("*** To run the tests, cairo must be built with png support ***)
fi
AC_SUBST(PNG_FUNCTIONS_FEATURE)
@@ -315,6 +294,34 @@ AC_CHECK_HEADERS([pthread.h])
dnl ===========================================================================
+AC_ARG_ENABLE(ps,
+ [ --disable-ps Disable cairo's PostScript backend],
+ [use_ps=$enableval], [use_ps=yes])
+
+if test x"$use_freetype" != "xyes" ; then
+ AC_MSG_WARN([PS backend requires FreeType, disabling])
+ use_ps=no
+fi
+
+# The postscript module requires zlib.
+AC_CHECK_LIB(z, compress,
+ [AC_CHECK_HEADER(zlib.h, [],
+ [use_ps="no (requires zlib http://www.gzip.org/zlib/)"])],
+ [use_ps="no (requires zlib http://www.gzip.org/zlib/)"])
+
+AM_CONDITIONAL(CAIRO_HAS_PS_SURFACE, test "x$use_ps" = "xyes")
+if test "x$use_ps" = "xyes"; then
+ PS_SURFACE_FEATURE="#define CAIRO_HAS_PS_SURFACE 1"
+ PS_LIBS=-lz
+fi
+AC_SUBST(PS_SURFACE_FEATURE)
+
+CAIRO_LIBS="$CAIRO_LIBS $PS_LIBS"
+
+AC_SUBST(PS_LIBS)
+
+dnl ===========================================================================
+
AC_ARG_ENABLE(pdf,
[ --disable-pdf Disable cairo's PDF backend],
[use_pdf=$enableval], [use_pdf=yes])
diff --git a/doc/public/Makefile.am b/doc/public/Makefile.am
index 9e4c10365..a9faef844 100644
--- a/doc/public/Makefile.am
+++ b/doc/public/Makefile.am
@@ -21,11 +21,15 @@ CFILE_GLOB=$(top_srcdir)/src/*.c $(top_srcdir)/src/*.h
# Headers to ignore
IGNORE_HFILES= \
cairo-features.h \
+ cairo-font-subset-private.h \
cairo-ft-private.h \
cairo-gstate-private.h \
+ cairo-hash-private.h \
+ cairo-meta-surface-private.h \
cairo-path-fixed-private.h \
cairo-private.h \
cairo-win32-private.h \
+ cairo-xlib-private.h \
cairo-xlib-test.h \
cairoint.h \
cairo-wideint.h
diff --git a/doc/public/cairo-sections.txt b/doc/public/cairo-sections.txt
index 4db600b2a..2e237b020 100644
--- a/doc/public/cairo-sections.txt
+++ b/doc/public/cairo-sections.txt
@@ -1,6 +1,7 @@
<SECTION>
<FILE>cairo-ft</FILE>
<TITLE>FreeType Fonts</TITLE>
+cairo_ft_font_options_substitute
cairo_ft_font_face_create_for_pattern
cairo_ft_font_face_create_for_ft_face
cairo_ft_scaled_font_lock_face
@@ -90,6 +91,7 @@ cairo_surface_create_similar
cairo_surface_reference
cairo_surface_destroy
cairo_surface_finish
+cairo_surface_get_font_options
cairo_surface_set_user_data
cairo_surface_get_user_data
cairo_surface_set_device_offset
@@ -99,6 +101,8 @@ cairo_surface_set_device_offset
<FILE>cairo-pattern</FILE>
<TITLE>cairo_pattern_t</TITLE>
cairo_pattern_t
+cairo_pattern_create_rgb
+cairo_pattern_create_rgba
cairo_pattern_create_for_surface
cairo_pattern_create_linear
cairo_pattern_create_radial
@@ -150,6 +154,26 @@ cairo_font_extents_t
cairo_scaled_font_extents
cairo_text_extents_t
cairo_scaled_font_glyph_extents
+cairo_font_options_t
+cairo_font_options_create
+cairo_font_options_copy
+cairo_font_options_destroy
+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
+cairo_font_options_set_subpixel_order
+cairo_font_options_get_subpixel_order
+cairo_hint_style_t
+cairo_font_options_set_hint_style
+cairo_font_options_get_hint_style
+cairo_hint_metrics_t
+cairo_font_options_set_hint_metrics
+cairo_font_options_get_hint_metrics
</SECTION>
<SECTION>
@@ -161,7 +185,10 @@ cairo_reference
cairo_destroy
cairo_save
cairo_restore
+cairo_content_t
+CAIRO_CONTENT_VALID
cairo_format_t
+CAIRO_FORMAT_VALID
cairo_operator_t
cairo_set_operator
cairo_set_source_rgb
@@ -224,6 +251,8 @@ cairo_select_font_face
cairo_set_font_size
cairo_set_font_matrix
cairo_get_font_matrix
+cairo_set_font_options
+cairo_get_font_options
cairo_show_text
cairo_show_glyphs
cairo_get_font_face
@@ -255,8 +284,6 @@ cairo_status_t
cairo_status
cairo_status_string
cairo_status_to_string
-cairo_error_notify_func_t
-cairo_set_error_notify
cairo_filter_t
cairo_image_surface_create
cairo_image_surface_create_for_data
diff --git a/doc/public/language-bindings.xml b/doc/public/language-bindings.xml
index b0ee8e879..26b98e1be 100644
--- a/doc/public/language-bindings.xml
+++ b/doc/public/language-bindings.xml
@@ -47,7 +47,7 @@
<title>Memory Management</title>
<para>
The objects in cairo can roughly be divided into two types:
- refcounted opaque types like
+ reference-counted, opaque types like
<link
linkend="cairo-surface-t"><type>cairo_surface_t</type></link>
and plain structures like
diff --git a/doc/public/tmpl/cairo-font.sgml b/doc/public/tmpl/cairo-font.sgml
index d6c7043d2..a41b7ccea 100644
--- a/doc/public/tmpl/cairo-font.sgml
+++ b/doc/public/tmpl/cairo-font.sgml
@@ -75,6 +75,7 @@ Font Handling
@font_face:
@font_matrix:
@ctm:
+@options:
@Returns:
@@ -112,6 +113,7 @@ Font Handling
@scaled_font:
@extents:
+<!-- # Unused Parameters # -->
@Returns:
@@ -138,3 +140,186 @@ Font Handling
@extents:
+<!-- ##### TYPEDEF cairo_font_options_t ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION cairo_font_options_create ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
+<!-- ##### FUNCTION cairo_font_options_copy ##### -->
+<para>
+
+</para>
+
+@original:
+@Returns:
+
+
+<!-- ##### FUNCTION cairo_font_options_destroy ##### -->
+<para>
+
+</para>
+
+@options:
+
+
+<!-- ##### FUNCTION cairo_font_options_status ##### -->
+<para>
+
+</para>
+
+@options:
+@Returns:
+
+
+<!-- ##### FUNCTION cairo_font_options_merge ##### -->
+<para>
+
+</para>
+
+@options:
+@other:
+
+
+<!-- ##### FUNCTION cairo_font_options_hash ##### -->
+<para>
+
+</para>
+
+@options:
+@Returns:
+
+
+<!-- ##### FUNCTION cairo_font_options_equal ##### -->
+<para>
+
+</para>
+
+@options:
+@other:
+@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>
+
+</para>
+
+@options:
+@antialias:
+
+
+<!-- ##### FUNCTION cairo_font_options_get_antialias ##### -->
+<para>
+
+</para>
+
+@options:
+@Returns:
+
+
+<!-- ##### ENUM cairo_subpixel_order_t ##### -->
+<para>
+
+</para>
+
+@CAIRO_SUBPIXEL_ORDER_DEFAULT:
+@CAIRO_SUBPIXEL_ORDER_RGB:
+@CAIRO_SUBPIXEL_ORDER_BGR:
+@CAIRO_SUBPIXEL_ORDER_VRGB:
+@CAIRO_SUBPIXEL_ORDER_VBGR:
+
+<!-- ##### FUNCTION cairo_font_options_set_subpixel_order ##### -->
+<para>
+
+</para>
+
+@options:
+@subpixel_order:
+
+
+<!-- ##### FUNCTION cairo_font_options_get_subpixel_order ##### -->
+<para>
+
+</para>
+
+@options:
+@Returns:
+<!-- # Unused Parameters # -->
+@option:
+
+
+<!-- ##### ENUM cairo_hint_style_t ##### -->
+<para>
+
+</para>
+
+@CAIRO_HINT_STYLE_DEFAULT:
+@CAIRO_HINT_STYLE_NONE:
+@CAIRO_HINT_STYLE_SLIGHT:
+@CAIRO_HINT_STYLE_MEDIUM:
+@CAIRO_HINT_STYLE_FULL:
+
+<!-- ##### FUNCTION cairo_font_options_set_hint_style ##### -->
+<para>
+
+</para>
+
+@options:
+@hint_style:
+
+
+<!-- ##### FUNCTION cairo_font_options_get_hint_style ##### -->
+<para>
+
+</para>
+
+@options:
+@Returns:
+
+
+<!-- ##### ENUM cairo_hint_metrics_t ##### -->
+<para>
+
+</para>
+
+@CAIRO_HINT_METRICS_DEFAULT:
+@CAIRO_HINT_METRICS_OFF:
+@CAIRO_HINT_METRICS_ON:
+
+<!-- ##### FUNCTION cairo_font_options_set_hint_metrics ##### -->
+<para>
+
+</para>
+
+@options:
+@hint_metrics:
+
+
+<!-- ##### FUNCTION cairo_font_options_get_hint_metrics ##### -->
+<para>
+
+</para>
+
+@options:
+@Returns:
+
+
diff --git a/doc/public/tmpl/cairo-ft.sgml b/doc/public/tmpl/cairo-ft.sgml
index d9f7cbfc1..383cf1935 100644
--- a/doc/public/tmpl/cairo-ft.sgml
+++ b/doc/public/tmpl/cairo-ft.sgml
@@ -17,6 +17,15 @@ FreeType Fonts
<!-- ##### SECTION Stability_Level ##### -->
+<!-- ##### FUNCTION cairo_ft_font_options_substitute ##### -->
+<para>
+
+</para>
+
+@options:
+@pattern:
+
+
<!-- ##### FUNCTION cairo_ft_font_face_create_for_pattern ##### -->
<para>
diff --git a/doc/public/tmpl/cairo-pattern.sgml b/doc/public/tmpl/cairo-pattern.sgml
index dadd7870c..a837252c6 100644
--- a/doc/public/tmpl/cairo-pattern.sgml
+++ b/doc/public/tmpl/cairo-pattern.sgml
@@ -23,6 +23,29 @@ cairo_pattern_t
</para>
+<!-- ##### FUNCTION cairo_pattern_create_rgb ##### -->
+<para>
+
+</para>
+
+@red:
+@green:
+@blue:
+@Returns:
+
+
+<!-- ##### FUNCTION cairo_pattern_create_rgba ##### -->
+<para>
+
+</para>
+
+@red:
+@green:
+@blue:
+@alpha:
+@Returns:
+
+
<!-- ##### FUNCTION cairo_pattern_create_for_surface ##### -->
<para>
diff --git a/doc/public/tmpl/cairo-surface.sgml b/doc/public/tmpl/cairo-surface.sgml
index fab1306f6..5d069fc2c 100644
--- a/doc/public/tmpl/cairo-surface.sgml
+++ b/doc/public/tmpl/cairo-surface.sgml
@@ -29,10 +29,12 @@ cairo_surface_t
</para>
@other:
-@format:
+@content:
@width:
@height:
@Returns:
+<!-- # Unused Parameters # -->
+@format:
<!-- ##### FUNCTION cairo_surface_reference ##### -->
@@ -57,9 +59,19 @@ cairo_surface_t
</para>
@surface:
+<!-- # Unused Parameters # -->
@Returns:
+<!-- ##### FUNCTION cairo_surface_get_font_options ##### -->
+<para>
+
+</para>
+
+@surface:
+@options:
+
+
<!-- ##### FUNCTION cairo_surface_set_user_data ##### -->
<para>
diff --git a/doc/public/tmpl/cairo-xlib-xrender.sgml b/doc/public/tmpl/cairo-xlib-xrender.sgml
index 4ceab1968..398900e88 100644
--- a/doc/public/tmpl/cairo-xlib-xrender.sgml
+++ b/doc/public/tmpl/cairo-xlib-xrender.sgml
@@ -24,6 +24,7 @@ XLib/Xrender Backend
@dpy:
@drawable:
+@screen:
@format:
@width:
@height:
diff --git a/doc/public/tmpl/cairo-xlib.sgml b/doc/public/tmpl/cairo-xlib.sgml
index ae8bb785c..cc106e8c5 100644
--- a/doc/public/tmpl/cairo-xlib.sgml
+++ b/doc/public/tmpl/cairo-xlib.sgml
@@ -37,6 +37,7 @@ XLib Backend
@dpy:
@bitmap:
+@screen:
@width:
@height:
@Returns:
diff --git a/doc/public/tmpl/cairo.sgml b/doc/public/tmpl/cairo.sgml
index 992ace500..c3398425f 100644
--- a/doc/public/tmpl/cairo.sgml
+++ b/doc/public/tmpl/cairo.sgml
@@ -74,6 +74,23 @@ Drawing contexts.
@cr:
+<!-- ##### ENUM cairo_content_t ##### -->
+<para>
+
+</para>
+
+@CAIRO_CONTENT_COLOR:
+@CAIRO_CONTENT_ALPHA:
+@CAIRO_CONTENT_COLOR_ALPHA:
+
+<!-- ##### MACRO CAIRO_CONTENT_VALID ##### -->
+<para>
+
+</para>
+
+@content:
+
+
<!-- ##### ENUM cairo_format_t ##### -->
<para>
@@ -84,6 +101,14 @@ Drawing contexts.
@CAIRO_FORMAT_A8:
@CAIRO_FORMAT_A1:
+<!-- ##### MACRO CAIRO_FORMAT_VALID ##### -->
+<para>
+
+</para>
+
+@format:
+
+
<!-- ##### ENUM cairo_operator_t ##### -->
<para>
@@ -689,6 +714,24 @@ Drawing contexts.
@matrix:
+<!-- ##### FUNCTION cairo_set_font_options ##### -->
+<para>
+
+</para>
+
+@cr:
+@options:
+
+
+<!-- ##### FUNCTION cairo_get_font_options ##### -->
+<para>
+
+</para>
+
+@cr:
+@options:
+
+
<!-- ##### FUNCTION cairo_show_text ##### -->
<para>
@@ -942,7 +985,7 @@ Drawing contexts.
@CAIRO_STATUS_INVALID_POP_GROUP:
@CAIRO_STATUS_NO_CURRENT_POINT:
@CAIRO_STATUS_INVALID_MATRIX:
-@CAIRO_STATUS_NO_TARGET_SURFACE:
+@CAIRO_STATUS_INVALID_STATUS:
@CAIRO_STATUS_NULL_POINTER:
@CAIRO_STATUS_INVALID_STRING:
@CAIRO_STATUS_INVALID_PATH_DATA:
@@ -951,6 +994,10 @@ Drawing contexts.
@CAIRO_STATUS_SURFACE_FINISHED:
@CAIRO_STATUS_SURFACE_TYPE_MISMATCH:
@CAIRO_STATUS_PATTERN_TYPE_MISMATCH:
+@CAIRO_STATUS_INVALID_CONTENT:
+@CAIRO_STATUS_INVALID_FORMAT:
+@CAIRO_STATUS_INVALID_VISUAL:
+@CAIRO_STATUS_FILE_NOT_FOUND:
<!-- ##### FUNCTION cairo_status ##### -->
<para>
diff --git a/doc/tutorial/slides/.cvsignore b/doc/tutorial/slides/.cvsignore
new file mode 100644
index 000000000..02a98448c
--- /dev/null
+++ b/doc/tutorial/slides/.cvsignore
@@ -0,0 +1,7 @@
+tutorial-???.html
+tutorial-???.png
+tutorial-???.svg
+tutorial-index.xml
+tutorial.pdf
+index.html
+
diff --git a/doc/tutorial/slides/Makefile b/doc/tutorial/slides/Makefile
new file mode 100644
index 000000000..273cc3fb4
--- /dev/null
+++ b/doc/tutorial/slides/Makefile
@@ -0,0 +1,7 @@
+PROJ=tutorial
+
+all: ${PROJ}.xml
+ svgslides $^
+
+clean:
+ rm -f ${PROJ}-index.xml index.html ${PROJ}-???.html ${PROJ}-???.svg *~
diff --git a/doc/tutorial/slides/cairo-blank.svg b/doc/tutorial/slides/cairo-blank.svg
new file mode 100644
index 000000000..881198110
--- /dev/null
+++ b/doc/tutorial/slides/cairo-blank.svg
@@ -0,0 +1,487 @@
+<?xml version="1.0" ?>
+<svg width="1024" height="768"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:ss="http://www.svgslides.org/svgslides0.1"
+ fill="black">
+
+
+ <defs id="cairo-artwork_defs">
+ <g id="hacker_emblem">
+ <!-- Note: This is similar though not identical to Keith Packard's SVG version
+ of the hacker emblem (http://www.catb.org/hacker-emblem/glider.svg) -->
+ <g id="hacker_emblem_grid" fill="white" stroke="none">
+ <!-- Outside: Top, Right, Bottom, Left -->
+ <rect x="-2.95" y="-3.05" width="6" height="0.1" />
+ <rect x="2.95" y="-2.95" width="0.1" height="6" />
+ <rect x="-3.05" y="2.95" width="6" height="0.1" />
+ <rect x="-3.05" y="-3.05" width="0.1" height="6" />
+ <!-- Vertical: Left, Right -->
+ <rect x="-1.05" y="-2.95" width="0.1" height="5.9" />
+ <rect x="0.95" y="-2.95" width="0.1" height="5.9" />
+ <!-- Horizontal: TopLeft, TopMiddle, TopRight -->
+ <rect x="-2.95" y="-1.05" width="1.9" height="0.1" />
+ <rect x="-0.95" y="-1.05" width="1.9" height="0.1" />
+ <rect x="1.05" y="-1.05" width="1.9" height="0.1" />
+ <!-- Horizontal: BottomLeft, BottomMiddle, BottomRight -->
+ <rect x="-2.95" y="0.95" width="1.9" height="0.1" />
+ <rect x="-0.95" y="0.95" width="1.9" height="0.1" />
+ <rect x="1.05" y="0.95" width="1.9" height="0.1" />
+ </g>
+ <g id="hacker_emblem_dots" fill="white">
+ <circle cx="0" cy="-2" r="0.7" />
+ <circle cx="2" cy="0" r="0.7" />
+ <circle cx="-2" cy="2" r="0.7" />
+ <circle cx="0" cy="2" r="0.7" />
+ <circle cx="2" cy="2" r="0.7" />
+ </g>
+ </g>
+ <g id="scarab" fill="#3B80AE">
+ <g transform="translate(-150, -170)">
+ <path id="scarab_head" d="M205.599,94.567c0-11.668-24.914-21.129-55.628-21.129
+ c-30.723,0-55.624,9.46-55.624,21.129c0,10.203,24.901,7.346,55.624,7.346C180.685,101.913,205.599,104.233,205.599,94.567z"/>
+ <path id="scarab_torso" d="M136.423,161.506c0,0,12.751,12.577,13.547,13.362
+ c2.262-2.232,13.545-13.362,13.545-13.362c7.135-7.036,87.111-6.399,91.066-6.363c-0.469-6.298-1.254-12.472-2.325-18.519
+ c-15.183-19.279-42.811-32.225-74.485-32.225h-55.518c-31.745,0-59.439,13.011-74.598,32.37c-1.054,6-1.829,12.128-2.296,18.374
+ C49.321,155.106,129.288,154.47,136.423,161.506z"/>
+ <path id="scarab_spine" d="M149.97,301.187c2.005-24.729,8.386-103.483,8.405-103.721
+ c-0.09-0.219-6.478-15.578-8.405-20.214c-1.936,4.655-8.316,19.995-8.408,20.214C141.582,197.704,147.965,276.458,149.97,301.187z"/>
+ <path id="scarab_wing_left" d="M140.403,197.149l8.862-21.31l-13.686-13.499
+ c-5.65-5.573-67.074-6.235-90.259-6.019l-0.006-0.622c-0.154,2.144-0.271,4.302-0.35,6.475
+ c-0.076,2.207,10.392,4.706,10.392,6.717c0,2.319-10.457,5.084-10.359,7.631c2.993,73.349,48.53,131.631,104.372,132.048
+ l-9.02-111.29L140.403,197.149z"/>
+ <path id="scarab_wing_right" d="M244.585,168.891c0-2.011,10.467-4.506,10.391-6.715
+ c-0.079-2.174-0.195-4.332-0.351-6.479l-0.004,0.624c-23.186-0.216-84.608,0.445-90.26,6.017l-13.688,13.502l8.915,21.438
+ l-9.017,111.29c55.854-0.417,101.378-58.698,104.373-132.049C255.04,173.976,244.585,171.209,244.585,168.891z"/>
+ <path id="scarab_leg_front_left" d="M44.506,141.12c-4.135-0.856-4.895-1.54-7.935-2.92
+ c-9.59-3.364-10.376-5.481-16.08-11.86c-7.426-8.306-12.661-20.142-17.1-29.463c-3.576-7.525-3.984-16.409-2.86-24.273
+ c0.991-6.935,7.144-12.869,12.074-18.92c5.844-7.191,10.356-14.822,17.924-21.354c7.736-6.682,23.203-9.809,26.168-19.648
+ C57.86,8.819,54.334,1.766,61.482,0c-0.366,4.703,3.639,8.477,2.397,13.575c-1.129,4.627-4.368,5.811-9.611,9.099
+ c-7.564,4.746-18.366,8.779-24.748,13.965c-7.175,5.827-4.369,13.771-10.569,20.057c-2.001,2.03-7.901,4.706-9.137,6.83
+ c-1.861,3.199-0.297,9.572-0.116,13.12c0.425,8.284,5.588,14.244,9.555,22.045c4.152,8.141,6.429,15.409,13.411,22.519
+ c4.183,4.262,11.429,4.802,16.21,10.647l-3.555,4.186L44.506,141.12z"/>
+ <path id="scarab_leg_middle_left" d="M43.94,191.922l-0.809-7.346
+ c-9.506-4.579-10.339-9.772-20.738-12.466c-23.728-6.151-21.361,11.25-15.532,26.373c5.676,14.726,8.237,30.23,14.345,44.795
+ c2.805,6.688,6.919,13.213,14.298,15.127c0.372-8.435-0.917-10.651-6.113-16.919c-4.395-5.293-3.326-12.548-6.072-18.504
+ c-3.581-7.804-4.196-15.646-7.279-23.502c-1.363-3.479-8.33-13.966-6.452-17.861c3.183-6.603,9.178-0.083,12.179,2.077
+ c4.218,3.036,6.467,2.223,11.681,2.898C34.041,186.673,37.005,188.756,43.94,191.922z"/>
+ <path id="scarab_leg_back_left" d="M65.839,257.063l-2.771-4.837
+ c-6.68,8.928-6.993,16.228-10.056,23.347c-5.277,12.263-0.157,28.851,9.854,37.676c6.052,5.375,15.907,9.618,23.122,13.136
+ c10.035,4.892,20.113,11.286,31.336,13.396c2.482,0.466,8.798,1.295,6.693-3.522c-0.975-2.237-8.091-4.591-10.146-5.734
+ c-8.312-4.623-16.377-10.524-24.142-16.176c-9.498-6.862-20.843-11.186-28.311-20.684c-3.054-3.885-3.544-4.922-2.816-9.39
+ c0.693-4.263,1.344-9.174,2.241-13.439C61.855,266.029,63.274,261.378,65.839,257.063z"/>
+ <path id="scarab_leg_front_right" d="M255.487,141.12c4.134-0.856,4.896-1.54,7.936-2.92
+ c9.583-3.364,10.369-5.481,16.071-11.86c7.428-8.306,12.661-20.142,17.115-29.463c3.574-7.525,3.983-16.409,2.86-24.273
+ c-0.992-6.935-7.157-12.869-12.087-18.92c-5.843-7.191-10.356-14.822-17.919-21.354c-7.735-6.682-23.202-9.809-26.167-19.648
+ C242.135,8.819,245.66,1.766,238.511,0c0.366,4.703-3.637,8.477-2.396,13.575c1.131,4.627,4.368,5.811,9.611,9.099
+ c7.563,4.746,18.367,8.779,24.747,13.965c7.17,5.827,4.362,13.771,10.563,20.057c2.001,2.03,7.901,4.706,9.139,6.83
+ c1.859,3.199,0.295,9.572,0.113,13.12c-0.424,8.284-5.588,14.244-9.553,22.045c-4.152,8.141-6.431,15.409-13.404,22.519
+ c-4.184,4.262-11.429,4.802-16.211,10.647l3.556,4.186L255.487,141.12z"/>
+ <path id="scarab_leg_middle_right" d="M256.053,191.922l0.81-7.346
+ c9.507-4.579,10.34-9.772,20.73-12.466c23.741-6.151,21.374,11.25,15.534,26.373c-5.676,14.726-8.238,30.23-14.347,44.795
+ c-2.804,6.688-6.911,13.213-14.291,15.127c-0.371-8.435,0.918-10.651,6.113-16.919c4.39-5.293,3.319-12.548,6.066-18.504
+ c3.58-7.804,4.197-15.646,7.278-23.502c1.363-3.479,8.33-13.966,6.453-17.861c-3.184-6.603-9.179-0.083-12.181,2.077
+ c-4.217,3.036-6.458,2.223-11.672,2.898C265.951,186.673,262.986,188.756,256.053,191.922z"/>
+ <path id="scarab_leg_back_right" d="M234.155,257.063l2.771-4.837
+ c6.679,8.928,6.991,16.228,10.057,23.347c5.274,12.263,0.154,28.851-9.854,37.676c-6.055,5.375-15.903,9.618-23.117,13.136
+ c-10.034,4.892-20.127,11.286-31.351,13.396c-2.481,0.466-8.789,1.295-6.691-3.522c0.976-2.237,8.092-4.591,10.146-5.734
+ c8.312-4.623,16.392-10.524,24.155-16.176c9.498-6.862,20.838-11.186,28.305-20.684c3.055-3.885,3.543-4.922,2.818-9.39
+ c-0.696-4.263-1.346-9.174-2.244-13.439C238.137,266.029,236.718,261.378,234.155,257.063z"/>
+ </g>
+ </g>
+ <radialGradient id="gradient_radial_dung"
+ cx="0" cy="0" r="60"
+ fx="0" fy="0" gradientUnits="userSpaceOnUse"
+ >
+ <stop offset="0" stop-color="#9a9a9a" />
+ <stop offset="0.70" stop-color="#bababa" />
+ <stop offset="0.95" stop-color="#FFFFFF" />
+ </radialGradient>
+ <g id="dung">
+ <circle cx="0" cy="0" r="60" fill="url(#gradient_radial_dung)" />
+ <g transform="translate(-61, -61)">
+ <!-- rough equivalent: <circle cx="0" cy="0" r="60" stroke="#8a8a8a" stroke-width="2" /> -->
+ <path fill="#8a8a8a" d="M0,61c0,33.636,27.364,61,61,61s61-27.364,61-61S94.636,0,61,0S0,27.364,0,61z
+ M2,61C2,28.467,28.467,2,61,2c32.532,0,59,26.467,59,59c0,32.533-26.468,59-59,59C28.467,120,2,93.533,2,61z"/>
+ </g>
+ <use xlink:href="#hacker_emblem" x="0" y="0" transform="scale(9)" />
+ </g>
+
+ <!-- scarab dimensions: 300x340 -->
+ <!-- dung dimensions: 120x120 (radius: 60) -->
+ <!-- scarab and dung dimensions: 300x400 -->
+
+ <g id="cairo_logo">
+ <!-- dimensions: 300x400, centered -->
+ <!-- The logo (scarab and dung), with the center-point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, -140)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, 30)" />
+ </g>
+ <g id="cairo_logo_dung-centered">
+ <!-- The logo (scarab and dung), with the dung at (0,0), the scarab below -->
+ <use xlink:href="#dung" x="0" y="0" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0,170)" />
+ </g>
+ <g id="cairo_logo_scarab-centered">
+ <!-- The logo (scarab and dung), with the scarab's rotational center at (0,0), the dung above -->
+ <!-- The scarab's rotational center in this case is not the center of its bounding box,
+ but is calculated to be the intersection-point of the torso, spine and wings -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, -175.85)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, -5.85)" />
+ </g>
+ <g id="cairo_logo_top-centered">
+ <!-- The logo (scarab and dung), with the top-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, 60)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, 230)" /><!-- (0,170+60) -->
+ </g>
+ <g id="cairo_logo_bottom-centered">
+ <!-- The logo (scarab and dung), with the bottom-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, -340)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, -170)" />
+ </g>
+ <g id="cairo_logo_right-centered">
+ <!-- The logo (scarab and dung), with the right-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(-150, -140)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(-150, 30)" />
+ </g>
+ <g id="cairo_logo_left-centered">
+ <!-- The logo (scarab and dung), with the left-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(150, -140)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(150, 30)" />
+ </g>
+ <g id="cairo_logo_topleft-centered">
+ <!-- The logo (scarab and dung), with the top-left point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(150, 60)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(150, 230)" /><!-- (150, 170+60) -->
+ </g>
+ <g id="cairo_logo_topright-centered">
+ <!-- The logo (scarab and dung), with the top-right point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(-150, 60)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(-150, 230)" /><!-- (-150,170+60) -->
+ </g>
+ <g id="cairo_logo_bottomleft-centered">
+ <!-- The logo (scarab and dung), with the bottom-left point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(150, -340)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(150, -170)" />
+ </g>
+ <g id="cairo_logo_bottomright-centered">
+ <!-- The logo (scarab and dung), with the bottom-right point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(-150, -340)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(-150, -170)" />
+ </g>
+
+ <g id="cairo_text" transform="translate(0,-97)">
+ <g transform="scale(0.1484,0.1484)"> <g transform="translate(-1139,-208.5)">
+ <!-- 63 (c), advance 444, 0 horiBearing 38,522 -->
+ <path transform="translate(65,0)" d="
+ M 412, 433
+ C 385, 422 336, 413 298, 413
+ C 142, 413 38, 525 38, 680
+ C 38, 826 144, 947 298, 947
+ C 332, 947 377, 944 416, 926
+ L 409, 842
+ C 380, 861 340, 871 308, 871
+ C 187, 871 138, 771 138, 680
+ C 138, 583 197, 489 302, 489
+ C 332, 489 368, 496 404, 511
+ L 412, 433 " />
+ <!-- 61 (a), advance 556, 0 horiBearing 46,522 -->
+ <path transform="translate(486.75,0)" d="
+ M 109, 541
+ C 147, 509 204, 489 257, 489
+ C 351, 489 383, 534 383, 622
+ C 346, 620 320, 620 283, 620
+ C 186, 620 46, 660 46, 788
+ C 46, 899 123, 947 233, 947
+ C 319, 947 369, 900 391, 869
+ L 393, 869
+ L 393, 935
+ L 481, 935
+ C 479, 920 477, 893 477, 835
+ L 477, 624
+ C 477, 485 418, 413 272, 413
+ C 207, 413 151, 433 104, 461
+ L 109, 541
+ M 383, 737
+ C 383, 813 334, 871 241, 871
+ C 198, 871 146, 842 146, 788
+ C 146, 698 272, 690 323, 690
+ C 343, 690 363, 692 383, 692
+ L 383, 737 " />
+ <!-- 69 (i), advance 278, 0 horiBearing 86,730 -->
+ <path transform="translate(1000,0)" d="
+ M 92, 935
+ L 186, 935
+ L 186, 425
+ L 92, 425
+ L 92, 935
+ M 88, 261
+ A 51, 51 0 1 1 190,261
+ A 51, 51 0 1 1 88,261" />
+ <!-- 72 (r), advance 389, 0 horiBearing 80,522 -->
+ <path transform="translate(1234.25,0)" d="
+ M 80, 935
+ L 174, 935
+ L 174, 703
+ C 174, 575 229, 495 313, 495
+ C 329, 495 348, 497 365, 504
+ L 365, 420
+ C 345, 416 331, 413 303, 413
+ C 249, 413 195, 451 170, 504
+ L 168, 504
+ L 168, 425
+ L 80, 425
+ L 80, 935 " />
+ <!-- 6f (o), advance 611, 0 horiBearing 46,522 -->
+ <path transform="translate(1610,0)" d="
+ M 46, 680
+ C 46, 826 152, 947 306, 947
+ C 459, 947 565, 826 565, 680
+ C 565, 525 461, 413 306, 413
+ C 150, 413 46, 525 46, 680
+ M 146, 680
+ C 146, 583 205, 489 306, 489
+ C 406, 489 465, 583 465, 680
+ C 465, 771 416, 871 306, 871
+ C 195, 871 146, 771 146, 680 " />
+ <!-- bounds: 38, 205 <-> 2232, 947 -->
+ </g> </g>
+ </g>
+
+ <!-- scaled by 0.72, shifted around to hit pixel boundaries -->
+ <g id="cairo_text_small_spaced" transform="translate(0,-71)">
+ <g transform="scale(0.085,0.085)"> <g transform="translate(-1139,-208.5)">
+ <!-- 63 (c), advance 444, 0 horiBearing 38,522 -->
+ <path transform="translate(-151,0)" d="
+ M 412, 433
+ C 385, 422 336, 413 298, 413
+ C 142, 413 38, 525 38, 680
+ C 38, 826 144, 947 298, 947
+ C 332, 947 377, 944 416, 926
+ L 409, 842
+ C 380, 861 340, 871 308, 871
+ C 187, 871 138, 771 138, 680
+ C 138, 583 197, 489 302, 489
+ C 332, 489 368, 496 404, 511
+ L 412, 433 " />
+ <!-- 61 (a), advance 556, 0 horiBearing 46,522 -->
+ <path transform="translate(379.5,0)" d="
+ M 109, 541
+ C 147, 509 204, 489 257, 489
+ C 351, 489 383, 534 383, 622
+ C 346, 620 320, 620 283, 620
+ C 186, 620 46, 660 46, 788
+ C 46, 899 123, 947 233, 947
+ C 319, 947 369, 900 391, 869
+ L 393, 869
+ L 393, 935
+ L 481, 935
+ C 479, 920 477, 893 477, 835
+ L 477, 624
+ C 477, 485 418, 413 272, 413
+ C 207, 413 151, 433 104, 461
+ L 109, 541
+ M 383, 737
+ C 383, 813 334, 871 241, 871
+ C 198, 871 146, 842 146, 788
+ C 146, 698 272, 690 323, 690
+ C 343, 690 363, 692 383, 692
+ L 383, 737 " />
+ <!-- 69 (i), advance 278, 0 horiBearing 86,730 -->
+ <path transform="translate(1000,0)" d="
+ M 92, 935
+ L 186, 935
+ L 186, 425
+ L 92, 425
+ L 92, 935
+ M 88, 261
+ A 51, 51 0 1 1 190,261
+ A 51, 51 0 1 1 88,261" />
+ <!-- 72 (r), advance 389, 0 horiBearing 80,522 -->
+ <path transform="translate(1341.5,0)" d="
+ M 80, 935
+ L 174, 935
+ L 174, 703
+ C 174, 575 229, 495 313, 495
+ C 329, 495 348, 497 365, 504
+ L 365, 420
+ C 345, 416 331, 413 303, 413
+ C 249, 413 195, 451 170, 504
+ L 168, 504
+ L 168, 425
+ L 80, 425
+ L 80, 935 " />
+ <!-- 6f (o), advance 611, 0 horiBearing 46,522 -->
+ <path transform="translate(1826,0)" d="
+ M 46, 680
+ C 46, 826 152, 947 306, 947
+ C 459, 947 565, 826 565, 680
+ C 565, 525 461, 413 306, 413
+ C 150, 413 46, 525 46, 680
+ M 146, 680
+ C 146, 583 205, 489 306, 489
+ C 406, 489 465, 583 465, 680
+ C 465, 771 416, 871 306, 871
+ C 195, 871 146, 771 146, 680 " />
+ <!-- bounds: 38, 205 <-> 2232, 947 -->
+ </g> </g>
+ </g>
+
+
+ <!-- scaled by 0.72, shifted around to hit pixel boundaries -->
+ <g id="cairo_text_small" transform="translate(0,-71)">
+ <g transform="scale(0.085,0.085)"> <g transform="translate(-1139,-208.5)">
+ <!-- 63 (c), advance 444, 0 horiBearing 38,522 -->
+ <path transform="translate(-151,0)" d="
+ M 412, 433
+ C 385, 422 336, 413 298, 413
+ C 142, 413 38, 525 38, 680
+ C 38, 826 144, 947 298, 947
+ C 332, 947 377, 944 416, 926
+ L 409, 842
+ C 380, 861 340, 871 308, 871
+ C 187, 871 138, 771 138, 680
+ C 138, 583 197, 489 302, 489
+ C 332, 489 368, 496 404, 511
+ L 412, 433 " />
+ <!-- 61 (a), advance 556, 0 horiBearing 46,522 -->
+ <path transform="translate(261.75,0)" d="
+ M 109, 541
+ C 147, 509 204, 489 257, 489
+ C 351, 489 383, 534 383, 622
+ C 346, 620 320, 620 283, 620
+ C 186, 620 46, 660 46, 788
+ C 46, 899 123, 947 233, 947
+ C 319, 947 369, 900 391, 869
+ L 393, 869
+ L 393, 935
+ L 481, 935
+ C 479, 920 477, 893 477, 835
+ L 477, 624
+ C 477, 485 418, 413 272, 413
+ C 207, 413 151, 433 104, 461
+ L 109, 541
+ M 383, 737
+ C 383, 813 334, 871 241, 871
+ C 198, 871 146, 842 146, 788
+ C 146, 698 272, 690 323, 690
+ C 343, 690 363, 692 383, 692
+ L 383, 737 " />
+ <!-- 69 (i), advance 278, 0 horiBearing 86,730 -->
+ <path transform="translate(764.75)" d="
+ M 92, 935
+ L 186, 935
+ L 186, 425
+ L 92, 425
+ L 92, 935
+ M 88, 261
+ A 51, 51 0 1 1 190,261
+ A 51, 51 0 1 1 88,261" />
+ <!-- 72 (r), advance 389, 0 horiBearing 80,522 -->
+ <path transform="translate(988.5,0)" d="
+ M 80, 935
+ L 174, 935
+ L 174, 703
+ C 174, 575 229, 495 313, 495
+ C 329, 495 348, 497 365, 504
+ L 365, 420
+ C 345, 416 331, 413 303, 413
+ C 249, 413 195, 451 170, 504
+ L 168, 504
+ L 168, 425
+ L 80, 425
+ L 80, 935 " />
+ <!-- 6f (o), advance 611, 0 horiBearing 46,522 -->
+ <path transform="translate(1355.5,0)" d="
+ M 46, 680
+ C 46, 826 152, 947 306, 947
+ C 459, 947 565, 826 565, 680
+ C 565, 525 461, 413 306, 413
+ C 150, 413 46, 525 46, 680
+ M 146, 680
+ C 146, 583 205, 489 306, 489
+ C 406, 489 465, 583 465, 680
+ C 465, 771 416, 871 306, 871
+ C 195, 871 146, 771 146, 680 " />
+ <!-- bounds: 38, 205 <-> 2232, 947 -->
+ </g> </g>
+ </g>
+
+ <g id="cairo_logo_text_small">
+ <!-- The logo on the left, the text 'cairo' on the right -->
+ <use xlink:href="#cairo_logo_bottomleft-centered" transform="translate(0, 78), scale(0.1944)" />
+ <use xlink:href="#cairo_text_small" transform="translate(175,82)"/>
+ </g>
+
+ <g id="cairo_logo_with_text">
+ <!-- The logo (scarab and dung), with the text 'cairo' below, the dot of the 'i' positioned between the hind legs of the scarab -->
+ <!-- dimensions: 300x490, centered -->
+ <use xlink:href="#cairo_logo_top-centered" transform="translate(0, -245)" />
+ <use xlink:href="#cairo_text" transform="translate(0, 245)" />
+ </g>
+
+ <g id="cairo_banner">
+ <!-- The logo on the left, the text 'cairo' in the center, and a mirror image of the logo on the right -->
+ <!-- The logos are scaled such that the scarab body nearly matches the height of the text characters (excepting the 'i')
+ and the dung should nearly aligns with the dot of the 'i'. The bottoms of the logos are aligned with the bottom of the text. -->
+ <!-- dimensions: 370x88, centered -->
+ <use xlink:href="#cairo_logo_bottomleft-centered" transform="translate(-180, 40), scale(0.1944)" />
+ <use xlink:href="#cairo_text_small" transform="translate(0, 42)" fill="black" />
+ <use xlink:href="#cairo_logo_bottomleft-centered" transform="translate(180, 40), scale(0.1944), scale(-1, 1)" />
+ </g>
+
+ <g id="freedesktop_org_logo" style="fill:#FFFFFF;stroke:#3B80AE;stroke-width:2.4588;">
+ <g>
+ <path style="stroke:#BABABA;" d="M85.277,40.796c2.058,7.884-2.667,15.942-10.551,17.999L27.143,71.21c-7.884,2.057-15.943-2.667-18-10.552
+ l-7.448-28.55c-2.057-7.884,2.667-15.942,10.551-17.999L59.83,1.695c7.884-2.057,15.942,2.667,17.999,10.551
+ l7.449,28.55z"/>>
+ <path style="fill:#3B80AE;stroke:none;" d="M80.444,39.778c1.749,7.854-1.816,13.621-9.504,15.447l-42.236,11.02c-7.569,2.396-14.089-1.181
+ -15.838-8.836L6.53,33.127c-1.749-8.145,0.709-12.889,9.503-15.447L58.27,6.661
+ c8.144-1.826,14.089,1.363,15.838,8.835l6.336,24.282z"/>>
+ </g>g>
+ <path style="opacity:0.5;fill:none;stroke:#FFFFFF;" d="M45.542,51.793L24.104,31.102l38.1-4.393L45.542,51.793z"/>>
+ <path d="M72.325,28.769c0.405,1.55-0.525,3.136-2.075,3.541l-12.331,3.217c-1.551,0.404-3.137-0.525-3.542-2.076l-2.295-8.801
+ c-0.405-1.551,0.524-3.137,2.076-3.542l12.33-3.217c1.551-0.405,3.137,0.525,3.542,2.076l2.295,8.801z"/>>
+ <path d="M36.51,33.625c0.496,1.9-0.645,3.844-2.545,4.34l-15.112,3.943c-1.901,0.496-3.845-0.644-4.34-2.544l-2.814-10.786
+ c-0.496-1.901,0.644-3.844,2.544-4.34l15.113-3.942c1.901-0.496,3.845,0.643,4.34,2.544l2.814,10.786z"/>>
+ <path d="M52.493,53.208c0.278,1.065-0.36,2.154-1.425,2.432L42.6,57.848c-1.064,0.277-2.153-0.36-2.431-1.426l-1.577-6.043
+ c-0.277-1.064,0.36-2.153,1.425-2.432l8.468-2.209c1.064-0.277,2.154,0.361,2.431,1.426l1.577,6.043z"/>>
+ </g>g>
+ </defs>
+
+ <g font-family="Frutiger">
+ <!-- Slide title -->
+ <g id="slide_title" transform="translate(512, 153)">
+ <rect stroke="#bababa" fill="none"
+ x="-365.5"
+ y="-55.5"
+ width="731"
+ height="81"
+ rx="10" ry="10"
+ />
+ <rect fill="#bababa" fill-opacity="0.3"
+ x="-360"
+ y="-50"
+ width="720"
+ height="70"
+ rx="10" ry="10"
+ />
+ <text text-anchor="middle"
+ fill="black"
+ x="0"
+ y="4" font-size="55"
+ ss:variable="title">Slide Title</text>
+ </g>
+
+ <!-- Slide content -->
+ <g ss:region="default">
+ <rect x="112" y="200" width="800" height="480" fill="none" stroke="blue"/>
+ <text font-size="40" fill="black"
+ x="112" y="232">Slide content</text>
+ </g>
+
+ <!-- Footer -->
+ <text ss:variable="URL" x="1016" y="760" text-anchor="end" font-size="20">http://cairographics.org</text>
+ </g>
+
+</svg>
diff --git a/doc/tutorial/slides/cairo-code.svg b/doc/tutorial/slides/cairo-code.svg
new file mode 100644
index 000000000..297d4c742
--- /dev/null
+++ b/doc/tutorial/slides/cairo-code.svg
@@ -0,0 +1,508 @@
+<?xml version="1.0" ?>
+<svg width="1024" height="768"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:ss="http://www.svgslides.org/svgslides0.1"
+ fill="black">
+
+
+ <defs id="cairo-artwork_defs">
+ <g id="hacker_emblem">
+ <!-- Note: This is similar though not identical to Keith Packard's SVG version
+ of the hacker emblem (http://www.catb.org/hacker-emblem/glider.svg) -->
+ <g id="hacker_emblem_grid" fill="white" stroke="none">
+ <!-- Outside: Top, Right, Bottom, Left -->
+ <rect x="-2.95" y="-3.05" width="6" height="0.1" />
+ <rect x="2.95" y="-2.95" width="0.1" height="6" />
+ <rect x="-3.05" y="2.95" width="6" height="0.1" />
+ <rect x="-3.05" y="-3.05" width="0.1" height="6" />
+ <!-- Vertical: Left, Right -->
+ <rect x="-1.05" y="-2.95" width="0.1" height="5.9" />
+ <rect x="0.95" y="-2.95" width="0.1" height="5.9" />
+ <!-- Horizontal: TopLeft, TopMiddle, TopRight -->
+ <rect x="-2.95" y="-1.05" width="1.9" height="0.1" />
+ <rect x="-0.95" y="-1.05" width="1.9" height="0.1" />
+ <rect x="1.05" y="-1.05" width="1.9" height="0.1" />
+ <!-- Horizontal: BottomLeft, BottomMiddle, BottomRight -->
+ <rect x="-2.95" y="0.95" width="1.9" height="0.1" />
+ <rect x="-0.95" y="0.95" width="1.9" height="0.1" />
+ <rect x="1.05" y="0.95" width="1.9" height="0.1" />
+ </g>
+ <g id="hacker_emblem_dots" fill="white">
+ <circle cx="0" cy="-2" r="0.7" />
+ <circle cx="2" cy="0" r="0.7" />
+ <circle cx="-2" cy="2" r="0.7" />
+ <circle cx="0" cy="2" r="0.7" />
+ <circle cx="2" cy="2" r="0.7" />
+ </g>
+ </g>
+ <g id="scarab" fill="#3B80AE">
+ <g transform="translate(-150, -170)">
+ <path id="scarab_head" d="M205.599,94.567c0-11.668-24.914-21.129-55.628-21.129
+ c-30.723,0-55.624,9.46-55.624,21.129c0,10.203,24.901,7.346,55.624,7.346C180.685,101.913,205.599,104.233,205.599,94.567z"/>
+ <path id="scarab_torso" d="M136.423,161.506c0,0,12.751,12.577,13.547,13.362
+ c2.262-2.232,13.545-13.362,13.545-13.362c7.135-7.036,87.111-6.399,91.066-6.363c-0.469-6.298-1.254-12.472-2.325-18.519
+ c-15.183-19.279-42.811-32.225-74.485-32.225h-55.518c-31.745,0-59.439,13.011-74.598,32.37c-1.054,6-1.829,12.128-2.296,18.374
+ C49.321,155.106,129.288,154.47,136.423,161.506z"/>
+ <path id="scarab_spine" d="M149.97,301.187c2.005-24.729,8.386-103.483,8.405-103.721
+ c-0.09-0.219-6.478-15.578-8.405-20.214c-1.936,4.655-8.316,19.995-8.408,20.214C141.582,197.704,147.965,276.458,149.97,301.187z"/>
+ <path id="scarab_wing_left" d="M140.403,197.149l8.862-21.31l-13.686-13.499
+ c-5.65-5.573-67.074-6.235-90.259-6.019l-0.006-0.622c-0.154,2.144-0.271,4.302-0.35,6.475
+ c-0.076,2.207,10.392,4.706,10.392,6.717c0,2.319-10.457,5.084-10.359,7.631c2.993,73.349,48.53,131.631,104.372,132.048
+ l-9.02-111.29L140.403,197.149z"/>
+ <path id="scarab_wing_right" d="M244.585,168.891c0-2.011,10.467-4.506,10.391-6.715
+ c-0.079-2.174-0.195-4.332-0.351-6.479l-0.004,0.624c-23.186-0.216-84.608,0.445-90.26,6.017l-13.688,13.502l8.915,21.438
+ l-9.017,111.29c55.854-0.417,101.378-58.698,104.373-132.049C255.04,173.976,244.585,171.209,244.585,168.891z"/>
+ <path id="scarab_leg_front_left" d="M44.506,141.12c-4.135-0.856-4.895-1.54-7.935-2.92
+ c-9.59-3.364-10.376-5.481-16.08-11.86c-7.426-8.306-12.661-20.142-17.1-29.463c-3.576-7.525-3.984-16.409-2.86-24.273
+ c0.991-6.935,7.144-12.869,12.074-18.92c5.844-7.191,10.356-14.822,17.924-21.354c7.736-6.682,23.203-9.809,26.168-19.648
+ C57.86,8.819,54.334,1.766,61.482,0c-0.366,4.703,3.639,8.477,2.397,13.575c-1.129,4.627-4.368,5.811-9.611,9.099
+ c-7.564,4.746-18.366,8.779-24.748,13.965c-7.175,5.827-4.369,13.771-10.569,20.057c-2.001,2.03-7.901,4.706-9.137,6.83
+ c-1.861,3.199-0.297,9.572-0.116,13.12c0.425,8.284,5.588,14.244,9.555,22.045c4.152,8.141,6.429,15.409,13.411,22.519
+ c4.183,4.262,11.429,4.802,16.21,10.647l-3.555,4.186L44.506,141.12z"/>
+ <path id="scarab_leg_middle_left" d="M43.94,191.922l-0.809-7.346
+ c-9.506-4.579-10.339-9.772-20.738-12.466c-23.728-6.151-21.361,11.25-15.532,26.373c5.676,14.726,8.237,30.23,14.345,44.795
+ c2.805,6.688,6.919,13.213,14.298,15.127c0.372-8.435-0.917-10.651-6.113-16.919c-4.395-5.293-3.326-12.548-6.072-18.504
+ c-3.581-7.804-4.196-15.646-7.279-23.502c-1.363-3.479-8.33-13.966-6.452-17.861c3.183-6.603,9.178-0.083,12.179,2.077
+ c4.218,3.036,6.467,2.223,11.681,2.898C34.041,186.673,37.005,188.756,43.94,191.922z"/>
+ <path id="scarab_leg_back_left" d="M65.839,257.063l-2.771-4.837
+ c-6.68,8.928-6.993,16.228-10.056,23.347c-5.277,12.263-0.157,28.851,9.854,37.676c6.052,5.375,15.907,9.618,23.122,13.136
+ c10.035,4.892,20.113,11.286,31.336,13.396c2.482,0.466,8.798,1.295,6.693-3.522c-0.975-2.237-8.091-4.591-10.146-5.734
+ c-8.312-4.623-16.377-10.524-24.142-16.176c-9.498-6.862-20.843-11.186-28.311-20.684c-3.054-3.885-3.544-4.922-2.816-9.39
+ c0.693-4.263,1.344-9.174,2.241-13.439C61.855,266.029,63.274,261.378,65.839,257.063z"/>
+ <path id="scarab_leg_front_right" d="M255.487,141.12c4.134-0.856,4.896-1.54,7.936-2.92
+ c9.583-3.364,10.369-5.481,16.071-11.86c7.428-8.306,12.661-20.142,17.115-29.463c3.574-7.525,3.983-16.409,2.86-24.273
+ c-0.992-6.935-7.157-12.869-12.087-18.92c-5.843-7.191-10.356-14.822-17.919-21.354c-7.735-6.682-23.202-9.809-26.167-19.648
+ C242.135,8.819,245.66,1.766,238.511,0c0.366,4.703-3.637,8.477-2.396,13.575c1.131,4.627,4.368,5.811,9.611,9.099
+ c7.563,4.746,18.367,8.779,24.747,13.965c7.17,5.827,4.362,13.771,10.563,20.057c2.001,2.03,7.901,4.706,9.139,6.83
+ c1.859,3.199,0.295,9.572,0.113,13.12c-0.424,8.284-5.588,14.244-9.553,22.045c-4.152,8.141-6.431,15.409-13.404,22.519
+ c-4.184,4.262-11.429,4.802-16.211,10.647l3.556,4.186L255.487,141.12z"/>
+ <path id="scarab_leg_middle_right" d="M256.053,191.922l0.81-7.346
+ c9.507-4.579,10.34-9.772,20.73-12.466c23.741-6.151,21.374,11.25,15.534,26.373c-5.676,14.726-8.238,30.23-14.347,44.795
+ c-2.804,6.688-6.911,13.213-14.291,15.127c-0.371-8.435,0.918-10.651,6.113-16.919c4.39-5.293,3.319-12.548,6.066-18.504
+ c3.58-7.804,4.197-15.646,7.278-23.502c1.363-3.479,8.33-13.966,6.453-17.861c-3.184-6.603-9.179-0.083-12.181,2.077
+ c-4.217,3.036-6.458,2.223-11.672,2.898C265.951,186.673,262.986,188.756,256.053,191.922z"/>
+ <path id="scarab_leg_back_right" d="M234.155,257.063l2.771-4.837
+ c6.679,8.928,6.991,16.228,10.057,23.347c5.274,12.263,0.154,28.851-9.854,37.676c-6.055,5.375-15.903,9.618-23.117,13.136
+ c-10.034,4.892-20.127,11.286-31.351,13.396c-2.481,0.466-8.789,1.295-6.691-3.522c0.976-2.237,8.092-4.591,10.146-5.734
+ c8.312-4.623,16.392-10.524,24.155-16.176c9.498-6.862,20.838-11.186,28.305-20.684c3.055-3.885,3.543-4.922,2.818-9.39
+ c-0.696-4.263-1.346-9.174-2.244-13.439C238.137,266.029,236.718,261.378,234.155,257.063z"/>
+ </g>
+ </g>
+ <radialGradient id="gradient_radial_dung"
+ cx="0" cy="0" r="60"
+ fx="0" fy="0" gradientUnits="userSpaceOnUse"
+ >
+ <stop offset="0" stop-color="#9a9a9a" />
+ <stop offset="0.70" stop-color="#bababa" />
+ <stop offset="0.95" stop-color="#FFFFFF" />
+ </radialGradient>
+ <g id="dung">
+ <circle cx="0" cy="0" r="60" fill="url(#gradient_radial_dung)" />
+ <g transform="translate(-61, -61)">
+ <!-- rough equivalent: <circle cx="0" cy="0" r="60" stroke="#8a8a8a" stroke-width="2" /> -->
+ <path fill="#8a8a8a" d="M0,61c0,33.636,27.364,61,61,61s61-27.364,61-61S94.636,0,61,0S0,27.364,0,61z
+ M2,61C2,28.467,28.467,2,61,2c32.532,0,59,26.467,59,59c0,32.533-26.468,59-59,59C28.467,120,2,93.533,2,61z"/>
+ </g>
+ <use xlink:href="#hacker_emblem" x="0" y="0" transform="scale(9)" />
+ </g>
+
+ <!-- scarab dimensions: 300x340 -->
+ <!-- dung dimensions: 120x120 (radius: 60) -->
+ <!-- scarab and dung dimensions: 300x400 -->
+
+ <g id="cairo_logo">
+ <!-- dimensions: 300x400, centered -->
+ <!-- The logo (scarab and dung), with the center-point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, -140)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, 30)" />
+ </g>
+ <g id="cairo_logo_dung-centered">
+ <!-- The logo (scarab and dung), with the dung at (0,0), the scarab below -->
+ <use xlink:href="#dung" x="0" y="0" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0,170)" />
+ </g>
+ <g id="cairo_logo_scarab-centered">
+ <!-- The logo (scarab and dung), with the scarab's rotational center at (0,0), the dung above -->
+ <!-- The scarab's rotational center in this case is not the center of its bounding box,
+ but is calculated to be the intersection-point of the torso, spine and wings -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, -175.85)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, -5.85)" />
+ </g>
+ <g id="cairo_logo_top-centered">
+ <!-- The logo (scarab and dung), with the top-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, 60)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, 230)" /><!-- (0,170+60) -->
+ </g>
+ <g id="cairo_logo_bottom-centered">
+ <!-- The logo (scarab and dung), with the bottom-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, -340)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, -170)" />
+ </g>
+ <g id="cairo_logo_right-centered">
+ <!-- The logo (scarab and dung), with the right-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(-150, -140)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(-150, 30)" />
+ </g>
+ <g id="cairo_logo_left-centered">
+ <!-- The logo (scarab and dung), with the left-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(150, -140)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(150, 30)" />
+ </g>
+ <g id="cairo_logo_topleft-centered">
+ <!-- The logo (scarab and dung), with the top-left point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(150, 60)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(150, 230)" /><!-- (150, 170+60) -->
+ </g>
+ <g id="cairo_logo_topright-centered">
+ <!-- The logo (scarab and dung), with the top-right point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(-150, 60)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(-150, 230)" /><!-- (-150,170+60) -->
+ </g>
+ <g id="cairo_logo_bottomleft-centered">
+ <!-- The logo (scarab and dung), with the bottom-left point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(150, -340)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(150, -170)" />
+ </g>
+ <g id="cairo_logo_bottomright-centered">
+ <!-- The logo (scarab and dung), with the bottom-right point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(-150, -340)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(-150, -170)" />
+ </g>
+
+ <g id="cairo_text" transform="translate(0,-97)">
+ <g transform="scale(0.1484,0.1484)"> <g transform="translate(-1139,-208.5)">
+ <!-- 63 (c), advance 444, 0 horiBearing 38,522 -->
+ <path transform="translate(65,0)" d="
+ M 412, 433
+ C 385, 422 336, 413 298, 413
+ C 142, 413 38, 525 38, 680
+ C 38, 826 144, 947 298, 947
+ C 332, 947 377, 944 416, 926
+ L 409, 842
+ C 380, 861 340, 871 308, 871
+ C 187, 871 138, 771 138, 680
+ C 138, 583 197, 489 302, 489
+ C 332, 489 368, 496 404, 511
+ L 412, 433 " />
+ <!-- 61 (a), advance 556, 0 horiBearing 46,522 -->
+ <path transform="translate(486.75,0)" d="
+ M 109, 541
+ C 147, 509 204, 489 257, 489
+ C 351, 489 383, 534 383, 622
+ C 346, 620 320, 620 283, 620
+ C 186, 620 46, 660 46, 788
+ C 46, 899 123, 947 233, 947
+ C 319, 947 369, 900 391, 869
+ L 393, 869
+ L 393, 935
+ L 481, 935
+ C 479, 920 477, 893 477, 835
+ L 477, 624
+ C 477, 485 418, 413 272, 413
+ C 207, 413 151, 433 104, 461
+ L 109, 541
+ M 383, 737
+ C 383, 813 334, 871 241, 871
+ C 198, 871 146, 842 146, 788
+ C 146, 698 272, 690 323, 690
+ C 343, 690 363, 692 383, 692
+ L 383, 737 " />
+ <!-- 69 (i), advance 278, 0 horiBearing 86,730 -->
+ <path transform="translate(1000,0)" d="
+ M 92, 935
+ L 186, 935
+ L 186, 425
+ L 92, 425
+ L 92, 935
+ M 88, 261
+ A 51, 51 0 1 1 190,261
+ A 51, 51 0 1 1 88,261" />
+ <!-- 72 (r), advance 389, 0 horiBearing 80,522 -->
+ <path transform="translate(1234.25,0)" d="
+ M 80, 935
+ L 174, 935
+ L 174, 703
+ C 174, 575 229, 495 313, 495
+ C 329, 495 348, 497 365, 504
+ L 365, 420
+ C 345, 416 331, 413 303, 413
+ C 249, 413 195, 451 170, 504
+ L 168, 504
+ L 168, 425
+ L 80, 425
+ L 80, 935 " />
+ <!-- 6f (o), advance 611, 0 horiBearing 46,522 -->
+ <path transform="translate(1610,0)" d="
+ M 46, 680
+ C 46, 826 152, 947 306, 947
+ C 459, 947 565, 826 565, 680
+ C 565, 525 461, 413 306, 413
+ C 150, 413 46, 525 46, 680
+ M 146, 680
+ C 146, 583 205, 489 306, 489
+ C 406, 489 465, 583 465, 680
+ C 465, 771 416, 871 306, 871
+ C 195, 871 146, 771 146, 680 " />
+ <!-- bounds: 38, 205 <-> 2232, 947 -->
+ </g> </g>
+ </g>
+
+ <!-- scaled by 0.72, shifted around to hit pixel boundaries -->
+ <g id="cairo_text_small_spaced" transform="translate(0,-71)">
+ <g transform="scale(0.085,0.085)"> <g transform="translate(-1139,-208.5)">
+ <!-- 63 (c), advance 444, 0 horiBearing 38,522 -->
+ <path transform="translate(-151,0)" d="
+ M 412, 433
+ C 385, 422 336, 413 298, 413
+ C 142, 413 38, 525 38, 680
+ C 38, 826 144, 947 298, 947
+ C 332, 947 377, 944 416, 926
+ L 409, 842
+ C 380, 861 340, 871 308, 871
+ C 187, 871 138, 771 138, 680
+ C 138, 583 197, 489 302, 489
+ C 332, 489 368, 496 404, 511
+ L 412, 433 " />
+ <!-- 61 (a), advance 556, 0 horiBearing 46,522 -->
+ <path transform="translate(379.5,0)" d="
+ M 109, 541
+ C 147, 509 204, 489 257, 489
+ C 351, 489 383, 534 383, 622
+ C 346, 620 320, 620 283, 620
+ C 186, 620 46, 660 46, 788
+ C 46, 899 123, 947 233, 947
+ C 319, 947 369, 900 391, 869
+ L 393, 869
+ L 393, 935
+ L 481, 935
+ C 479, 920 477, 893 477, 835
+ L 477, 624
+ C 477, 485 418, 413 272, 413
+ C 207, 413 151, 433 104, 461
+ L 109, 541
+ M 383, 737
+ C 383, 813 334, 871 241, 871
+ C 198, 871 146, 842 146, 788
+ C 146, 698 272, 690 323, 690
+ C 343, 690 363, 692 383, 692
+ L 383, 737 " />
+ <!-- 69 (i), advance 278, 0 horiBearing 86,730 -->
+ <path transform="translate(1000,0)" d="
+ M 92, 935
+ L 186, 935
+ L 186, 425
+ L 92, 425
+ L 92, 935
+ M 88, 261
+ A 51, 51 0 1 1 190,261
+ A 51, 51 0 1 1 88,261" />
+ <!-- 72 (r), advance 389, 0 horiBearing 80,522 -->
+ <path transform="translate(1341.5,0)" d="
+ M 80, 935
+ L 174, 935
+ L 174, 703
+ C 174, 575 229, 495 313, 495
+ C 329, 495 348, 497 365, 504
+ L 365, 420
+ C 345, 416 331, 413 303, 413
+ C 249, 413 195, 451 170, 504
+ L 168, 504
+ L 168, 425
+ L 80, 425
+ L 80, 935 " />
+ <!-- 6f (o), advance 611, 0 horiBearing 46,522 -->
+ <path transform="translate(1826,0)" d="
+ M 46, 680
+ C 46, 826 152, 947 306, 947
+ C 459, 947 565, 826 565, 680
+ C 565, 525 461, 413 306, 413
+ C 150, 413 46, 525 46, 680
+ M 146, 680
+ C 146, 583 205, 489 306, 489
+ C 406, 489 465, 583 465, 680
+ C 465, 771 416, 871 306, 871
+ C 195, 871 146, 771 146, 680 " />
+ <!-- bounds: 38, 205 <-> 2232, 947 -->
+ </g> </g>
+ </g>
+
+
+ <!-- scaled by 0.72, shifted around to hit pixel boundaries -->
+ <g id="cairo_text_small" transform="translate(0,-71)">
+ <g transform="scale(0.085,0.085)"> <g transform="translate(-1139,-208.5)">
+ <!-- 63 (c), advance 444, 0 horiBearing 38,522 -->
+ <path transform="translate(-151,0)" d="
+ M 412, 433
+ C 385, 422 336, 413 298, 413
+ C 142, 413 38, 525 38, 680
+ C 38, 826 144, 947 298, 947
+ C 332, 947 377, 944 416, 926
+ L 409, 842
+ C 380, 861 340, 871 308, 871
+ C 187, 871 138, 771 138, 680
+ C 138, 583 197, 489 302, 489
+ C 332, 489 368, 496 404, 511
+ L 412, 433 " />
+ <!-- 61 (a), advance 556, 0 horiBearing 46,522 -->
+ <path transform="translate(261.75,0)" d="
+ M 109, 541
+ C 147, 509 204, 489 257, 489
+ C 351, 489 383, 534 383, 622
+ C 346, 620 320, 620 283, 620
+ C 186, 620 46, 660 46, 788
+ C 46, 899 123, 947 233, 947
+ C 319, 947 369, 900 391, 869
+ L 393, 869
+ L 393, 935
+ L 481, 935
+ C 479, 920 477, 893 477, 835
+ L 477, 624
+ C 477, 485 418, 413 272, 413
+ C 207, 413 151, 433 104, 461
+ L 109, 541
+ M 383, 737
+ C 383, 813 334, 871 241, 871
+ C 198, 871 146, 842 146, 788
+ C 146, 698 272, 690 323, 690
+ C 343, 690 363, 692 383, 692
+ L 383, 737 " />
+ <!-- 69 (i), advance 278, 0 horiBearing 86,730 -->
+ <path transform="translate(764.75)" d="
+ M 92, 935
+ L 186, 935
+ L 186, 425
+ L 92, 425
+ L 92, 935
+ M 88, 261
+ A 51, 51 0 1 1 190,261
+ A 51, 51 0 1 1 88,261" />
+ <!-- 72 (r), advance 389, 0 horiBearing 80,522 -->
+ <path transform="translate(988.5,0)" d="
+ M 80, 935
+ L 174, 935
+ L 174, 703
+ C 174, 575 229, 495 313, 495
+ C 329, 495 348, 497 365, 504
+ L 365, 420
+ C 345, 416 331, 413 303, 413
+ C 249, 413 195, 451 170, 504
+ L 168, 504
+ L 168, 425
+ L 80, 425
+ L 80, 935 " />
+ <!-- 6f (o), advance 611, 0 horiBearing 46,522 -->
+ <path transform="translate(1355.5,0)" d="
+ M 46, 680
+ C 46, 826 152, 947 306, 947
+ C 459, 947 565, 826 565, 680
+ C 565, 525 461, 413 306, 413
+ C 150, 413 46, 525 46, 680
+ M 146, 680
+ C 146, 583 205, 489 306, 489
+ C 406, 489 465, 583 465, 680
+ C 465, 771 416, 871 306, 871
+ C 195, 871 146, 771 146, 680 " />
+ <!-- bounds: 38, 205 <-> 2232, 947 -->
+ </g> </g>
+ </g>
+
+ <g id="cairo_logo_text_small">
+ <!-- The logo on the left, the text 'cairo' on the right -->
+ <use xlink:href="#cairo_logo_bottomleft-centered" transform="translate(0, 78), scale(0.1944)" />
+ <use xlink:href="#cairo_text_small" transform="translate(175,82)"/>
+ </g>
+
+ <g id="cairo_logo_with_text">
+ <!-- The logo (scarab and dung), with the text 'cairo' below, the dot of the 'i' positioned between the hind legs of the scarab -->
+ <!-- dimensions: 300x490, centered -->
+ <use xlink:href="#cairo_logo_top-centered" transform="translate(0, -245)" />
+ <use xlink:href="#cairo_text" transform="translate(0, 245)" />
+ </g>
+
+ <g id="cairo_banner">
+ <!-- The logo on the left, the text 'cairo' in the center, and a mirror image of the logo on the right -->
+ <!-- The logos are scaled such that the scarab body nearly matches the height of the text characters (excepting the 'i')
+ and the dung should nearly aligns with the dot of the 'i'. The bottoms of the logos are aligned with the bottom of the text. -->
+ <!-- dimensions: 370x88, centered -->
+ <use xlink:href="#cairo_logo_bottomleft-centered" transform="translate(-180, 40), scale(0.1944)" />
+ <use xlink:href="#cairo_text_small" transform="translate(0, 42)" fill="black" />
+ <use xlink:href="#cairo_logo_bottomleft-centered" transform="translate(180, 40), scale(0.1944), scale(-1, 1)" />
+ </g>
+
+ <g id="freedesktop_org_logo" style="fill:#FFFFFF;stroke:#3B80AE;stroke-width:2.4588;">
+ <g>
+ <path style="stroke:#BABABA;" d="M85.277,40.796c2.058,7.884-2.667,15.942-10.551,17.999L27.143,71.21c-7.884,2.057-15.943-2.667-18-10.552
+ l-7.448-28.55c-2.057-7.884,2.667-15.942,10.551-17.999L59.83,1.695c7.884-2.057,15.942,2.667,17.999,10.551
+ l7.449,28.55z"/>>
+ <path style="fill:#3B80AE;stroke:none;" d="M80.444,39.778c1.749,7.854-1.816,13.621-9.504,15.447l-42.236,11.02c-7.569,2.396-14.089-1.181
+ -15.838-8.836L6.53,33.127c-1.749-8.145,0.709-12.889,9.503-15.447L58.27,6.661
+ c8.144-1.826,14.089,1.363,15.838,8.835l6.336,24.282z"/>>
+ </g>g>
+ <path style="opacity:0.5;fill:none;stroke:#FFFFFF;" d="M45.542,51.793L24.104,31.102l38.1-4.393L45.542,51.793z"/>>
+ <path d="M72.325,28.769c0.405,1.55-0.525,3.136-2.075,3.541l-12.331,3.217c-1.551,0.404-3.137-0.525-3.542-2.076l-2.295-8.801
+ c-0.405-1.551,0.524-3.137,2.076-3.542l12.33-3.217c1.551-0.405,3.137,0.525,3.542,2.076l2.295,8.801z"/>>
+ <path d="M36.51,33.625c0.496,1.9-0.645,3.844-2.545,4.34l-15.112,3.943c-1.901,0.496-3.845-0.644-4.34-2.544l-2.814-10.786
+ c-0.496-1.901,0.644-3.844,2.544-4.34l15.113-3.942c1.901-0.496,3.845,0.643,4.34,2.544l2.814,10.786z"/>>
+ <path d="M52.493,53.208c0.278,1.065-0.36,2.154-1.425,2.432L42.6,57.848c-1.064,0.277-2.153-0.36-2.431-1.426l-1.577-6.043
+ c-0.277-1.064,0.36-2.153,1.425-2.432l8.468-2.209c1.064-0.277,2.154,0.361,2.431,1.426l1.577,6.043z"/>>
+ </g>g>
+ <g id="bullet">
+ <use x="0" y="0" xlink:href="#cairo_logo" transform="translate(-6,-2) scale(0.1, 0.1)"/>>
+ </g>
+ </defs>
+
+ <g id="watermark" transform="translate(200, 185), rotate(-50), scale(2.5)">
+ <use xlink:href="#scarab" x="0" y="170" fill-opacity="0.08"/>
+ </g>
+
+ <!-- Blue bar at top of slide -->
+ <rect x="0" y="0" width="1024" height="50" fill="#3B80AE" fill-opacity="0.3" />
+
+ <!-- Scarab and "cairo" at upper-left -->
+ <g transform="translate(10,0)">
+ <use xlink:href="#cairo_logo_text_small"/>
+ </g>
+
+ <!-- Presentation title at upper-left -->
+ <text ss:variable="presentation-subtitle" x="260" y="50" font-size="20">Presentation Sub-title</text>
+
+ <!-- freedesktop.org logo at upper-right -->
+ <use xlink:href="#freedesktop_org_logo" transform="translate(910, 12)" />
+
+ <g font-family="Frutiger">
+ <!-- Slide title -->
+ <g id="slide_title" transform="translate(512, 138)">
+ <rect stroke="#bababa" fill="none"
+ x="-365.5"
+ y="-55.5"
+ width="731"
+ height="81"
+ rx="10" ry="10"
+ />
+ <rect fill="#bababa" fill-opacity="0.3"
+ x="-360"
+ y="-50"
+ width="720"
+ height="70"
+ rx="10" ry="10"
+ />
+ <text text-anchor="middle"
+ fill="black"
+ x="0"
+ y="4" font-size="55"
+ ss:variable="title">Slide Title</text>
+ </g>
+
+ <!-- Slide content -->
+ <g ss:region="default" font-family="Mono">
+ <rect x="112" y="170" width="800" height="480" fill="none" stroke="blue"/>
+ <text font-size="20" fill="black"
+ x="112" y="203">Slide content</text>
+ </g>
+
+ <!-- Footer -->
+ <text ss:variable="URL" x="1016" y="760" text-anchor="end" font-size="20">http://cairographics.org</text>
+ </g>
+
+</svg>
diff --git a/doc/tutorial/slides/cairo-separator.svg b/doc/tutorial/slides/cairo-separator.svg
new file mode 100644
index 000000000..4fe417643
--- /dev/null
+++ b/doc/tutorial/slides/cairo-separator.svg
@@ -0,0 +1,491 @@
+<?xml version="1.0" ?>
+<svg width="1024" height="768"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:ss="http://www.svgslides.org/svgslides0.1"
+ fill="black">
+
+
+ <defs id="cairo-artwork_defs">
+ <g id="hacker_emblem">
+ <!-- Note: This is similar though not identical to Keith Packard's SVG version
+ of the hacker emblem (http://www.catb.org/hacker-emblem/glider.svg) -->
+ <g id="hacker_emblem_grid" fill="white" stroke="none">
+ <!-- Outside: Top, Right, Bottom, Left -->
+ <rect x="-2.95" y="-3.05" width="6" height="0.1" />
+ <rect x="2.95" y="-2.95" width="0.1" height="6" />
+ <rect x="-3.05" y="2.95" width="6" height="0.1" />
+ <rect x="-3.05" y="-3.05" width="0.1" height="6" />
+ <!-- Vertical: Left, Right -->
+ <rect x="-1.05" y="-2.95" width="0.1" height="5.9" />
+ <rect x="0.95" y="-2.95" width="0.1" height="5.9" />
+ <!-- Horizontal: TopLeft, TopMiddle, TopRight -->
+ <rect x="-2.95" y="-1.05" width="1.9" height="0.1" />
+ <rect x="-0.95" y="-1.05" width="1.9" height="0.1" />
+ <rect x="1.05" y="-1.05" width="1.9" height="0.1" />
+ <!-- Horizontal: BottomLeft, BottomMiddle, BottomRight -->
+ <rect x="-2.95" y="0.95" width="1.9" height="0.1" />
+ <rect x="-0.95" y="0.95" width="1.9" height="0.1" />
+ <rect x="1.05" y="0.95" width="1.9" height="0.1" />
+ </g>
+ <g id="hacker_emblem_dots" fill="white">
+ <circle cx="0" cy="-2" r="0.7" />
+ <circle cx="2" cy="0" r="0.7" />
+ <circle cx="-2" cy="2" r="0.7" />
+ <circle cx="0" cy="2" r="0.7" />
+ <circle cx="2" cy="2" r="0.7" />
+ </g>
+ </g>
+ <g id="scarab" fill="#3B80AE">
+ <g transform="translate(-150, -170)">
+ <path id="scarab_head" d="M205.599,94.567c0-11.668-24.914-21.129-55.628-21.129
+ c-30.723,0-55.624,9.46-55.624,21.129c0,10.203,24.901,7.346,55.624,7.346C180.685,101.913,205.599,104.233,205.599,94.567z"/>
+ <path id="scarab_torso" d="M136.423,161.506c0,0,12.751,12.577,13.547,13.362
+ c2.262-2.232,13.545-13.362,13.545-13.362c7.135-7.036,87.111-6.399,91.066-6.363c-0.469-6.298-1.254-12.472-2.325-18.519
+ c-15.183-19.279-42.811-32.225-74.485-32.225h-55.518c-31.745,0-59.439,13.011-74.598,32.37c-1.054,6-1.829,12.128-2.296,18.374
+ C49.321,155.106,129.288,154.47,136.423,161.506z"/>
+ <path id="scarab_spine" d="M149.97,301.187c2.005-24.729,8.386-103.483,8.405-103.721
+ c-0.09-0.219-6.478-15.578-8.405-20.214c-1.936,4.655-8.316,19.995-8.408,20.214C141.582,197.704,147.965,276.458,149.97,301.187z"/>
+ <path id="scarab_wing_left" d="M140.403,197.149l8.862-21.31l-13.686-13.499
+ c-5.65-5.573-67.074-6.235-90.259-6.019l-0.006-0.622c-0.154,2.144-0.271,4.302-0.35,6.475
+ c-0.076,2.207,10.392,4.706,10.392,6.717c0,2.319-10.457,5.084-10.359,7.631c2.993,73.349,48.53,131.631,104.372,132.048
+ l-9.02-111.29L140.403,197.149z"/>
+ <path id="scarab_wing_right" d="M244.585,168.891c0-2.011,10.467-4.506,10.391-6.715
+ c-0.079-2.174-0.195-4.332-0.351-6.479l-0.004,0.624c-23.186-0.216-84.608,0.445-90.26,6.017l-13.688,13.502l8.915,21.438
+ l-9.017,111.29c55.854-0.417,101.378-58.698,104.373-132.049C255.04,173.976,244.585,171.209,244.585,168.891z"/>
+ <path id="scarab_leg_front_left" d="M44.506,141.12c-4.135-0.856-4.895-1.54-7.935-2.92
+ c-9.59-3.364-10.376-5.481-16.08-11.86c-7.426-8.306-12.661-20.142-17.1-29.463c-3.576-7.525-3.984-16.409-2.86-24.273
+ c0.991-6.935,7.144-12.869,12.074-18.92c5.844-7.191,10.356-14.822,17.924-21.354c7.736-6.682,23.203-9.809,26.168-19.648
+ C57.86,8.819,54.334,1.766,61.482,0c-0.366,4.703,3.639,8.477,2.397,13.575c-1.129,4.627-4.368,5.811-9.611,9.099
+ c-7.564,4.746-18.366,8.779-24.748,13.965c-7.175,5.827-4.369,13.771-10.569,20.057c-2.001,2.03-7.901,4.706-9.137,6.83
+ c-1.861,3.199-0.297,9.572-0.116,13.12c0.425,8.284,5.588,14.244,9.555,22.045c4.152,8.141,6.429,15.409,13.411,22.519
+ c4.183,4.262,11.429,4.802,16.21,10.647l-3.555,4.186L44.506,141.12z"/>
+ <path id="scarab_leg_middle_left" d="M43.94,191.922l-0.809-7.346
+ c-9.506-4.579-10.339-9.772-20.738-12.466c-23.728-6.151-21.361,11.25-15.532,26.373c5.676,14.726,8.237,30.23,14.345,44.795
+ c2.805,6.688,6.919,13.213,14.298,15.127c0.372-8.435-0.917-10.651-6.113-16.919c-4.395-5.293-3.326-12.548-6.072-18.504
+ c-3.581-7.804-4.196-15.646-7.279-23.502c-1.363-3.479-8.33-13.966-6.452-17.861c3.183-6.603,9.178-0.083,12.179,2.077
+ c4.218,3.036,6.467,2.223,11.681,2.898C34.041,186.673,37.005,188.756,43.94,191.922z"/>
+ <path id="scarab_leg_back_left" d="M65.839,257.063l-2.771-4.837
+ c-6.68,8.928-6.993,16.228-10.056,23.347c-5.277,12.263-0.157,28.851,9.854,37.676c6.052,5.375,15.907,9.618,23.122,13.136
+ c10.035,4.892,20.113,11.286,31.336,13.396c2.482,0.466,8.798,1.295,6.693-3.522c-0.975-2.237-8.091-4.591-10.146-5.734
+ c-8.312-4.623-16.377-10.524-24.142-16.176c-9.498-6.862-20.843-11.186-28.311-20.684c-3.054-3.885-3.544-4.922-2.816-9.39
+ c0.693-4.263,1.344-9.174,2.241-13.439C61.855,266.029,63.274,261.378,65.839,257.063z"/>
+ <path id="scarab_leg_front_right" d="M255.487,141.12c4.134-0.856,4.896-1.54,7.936-2.92
+ c9.583-3.364,10.369-5.481,16.071-11.86c7.428-8.306,12.661-20.142,17.115-29.463c3.574-7.525,3.983-16.409,2.86-24.273
+ c-0.992-6.935-7.157-12.869-12.087-18.92c-5.843-7.191-10.356-14.822-17.919-21.354c-7.735-6.682-23.202-9.809-26.167-19.648
+ C242.135,8.819,245.66,1.766,238.511,0c0.366,4.703-3.637,8.477-2.396,13.575c1.131,4.627,4.368,5.811,9.611,9.099
+ c7.563,4.746,18.367,8.779,24.747,13.965c7.17,5.827,4.362,13.771,10.563,20.057c2.001,2.03,7.901,4.706,9.139,6.83
+ c1.859,3.199,0.295,9.572,0.113,13.12c-0.424,8.284-5.588,14.244-9.553,22.045c-4.152,8.141-6.431,15.409-13.404,22.519
+ c-4.184,4.262-11.429,4.802-16.211,10.647l3.556,4.186L255.487,141.12z"/>
+ <path id="scarab_leg_middle_right" d="M256.053,191.922l0.81-7.346
+ c9.507-4.579,10.34-9.772,20.73-12.466c23.741-6.151,21.374,11.25,15.534,26.373c-5.676,14.726-8.238,30.23-14.347,44.795
+ c-2.804,6.688-6.911,13.213-14.291,15.127c-0.371-8.435,0.918-10.651,6.113-16.919c4.39-5.293,3.319-12.548,6.066-18.504
+ c3.58-7.804,4.197-15.646,7.278-23.502c1.363-3.479,8.33-13.966,6.453-17.861c-3.184-6.603-9.179-0.083-12.181,2.077
+ c-4.217,3.036-6.458,2.223-11.672,2.898C265.951,186.673,262.986,188.756,256.053,191.922z"/>
+ <path id="scarab_leg_back_right" d="M234.155,257.063l2.771-4.837
+ c6.679,8.928,6.991,16.228,10.057,23.347c5.274,12.263,0.154,28.851-9.854,37.676c-6.055,5.375-15.903,9.618-23.117,13.136
+ c-10.034,4.892-20.127,11.286-31.351,13.396c-2.481,0.466-8.789,1.295-6.691-3.522c0.976-2.237,8.092-4.591,10.146-5.734
+ c8.312-4.623,16.392-10.524,24.155-16.176c9.498-6.862,20.838-11.186,28.305-20.684c3.055-3.885,3.543-4.922,2.818-9.39
+ c-0.696-4.263-1.346-9.174-2.244-13.439C238.137,266.029,236.718,261.378,234.155,257.063z"/>
+ </g>
+ </g>
+ <radialGradient id="gradient_radial_dung"
+ cx="0" cy="0" r="60"
+ fx="0" fy="0" gradientUnits="userSpaceOnUse"
+ >
+ <stop offset="0" stop-color="#9a9a9a" />
+ <stop offset="0.70" stop-color="#bababa" />
+ <stop offset="0.95" stop-color="#FFFFFF" />
+ </radialGradient>
+ <g id="dung">
+ <circle cx="0" cy="0" r="60" fill="url(#gradient_radial_dung)" />
+ <g transform="translate(-61, -61)">
+ <!-- rough equivalent: <circle cx="0" cy="0" r="60" stroke="#8a8a8a" stroke-width="2" /> -->
+ <path fill="#8a8a8a" d="M0,61c0,33.636,27.364,61,61,61s61-27.364,61-61S94.636,0,61,0S0,27.364,0,61z
+ M2,61C2,28.467,28.467,2,61,2c32.532,0,59,26.467,59,59c0,32.533-26.468,59-59,59C28.467,120,2,93.533,2,61z"/>
+ </g>
+ <use xlink:href="#hacker_emblem" x="0" y="0" transform="scale(9)" />
+ </g>
+
+ <!-- scarab dimensions: 300x340 -->
+ <!-- dung dimensions: 120x120 (radius: 60) -->
+ <!-- scarab and dung dimensions: 300x400 -->
+
+ <g id="cairo_logo">
+ <!-- dimensions: 300x400, centered -->
+ <!-- The logo (scarab and dung), with the center-point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, -140)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, 30)" />
+ </g>
+ <g id="cairo_logo_dung-centered">
+ <!-- The logo (scarab and dung), with the dung at (0,0), the scarab below -->
+ <use xlink:href="#dung" x="0" y="0" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0,170)" />
+ </g>
+ <g id="cairo_logo_scarab-centered">
+ <!-- The logo (scarab and dung), with the scarab's rotational center at (0,0), the dung above -->
+ <!-- The scarab's rotational center in this case is not the center of its bounding box,
+ but is calculated to be the intersection-point of the torso, spine and wings -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, -175.85)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, -5.85)" />
+ </g>
+ <g id="cairo_logo_top-centered">
+ <!-- The logo (scarab and dung), with the top-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, 60)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, 230)" /><!-- (0,170+60) -->
+ </g>
+ <g id="cairo_logo_bottom-centered">
+ <!-- The logo (scarab and dung), with the bottom-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, -340)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, -170)" />
+ </g>
+ <g id="cairo_logo_right-centered">
+ <!-- The logo (scarab and dung), with the right-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(-150, -140)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(-150, 30)" />
+ </g>
+ <g id="cairo_logo_left-centered">
+ <!-- The logo (scarab and dung), with the left-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(150, -140)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(150, 30)" />
+ </g>
+ <g id="cairo_logo_topleft-centered">
+ <!-- The logo (scarab and dung), with the top-left point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(150, 60)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(150, 230)" /><!-- (150, 170+60) -->
+ </g>
+ <g id="cairo_logo_topright-centered">
+ <!-- The logo (scarab and dung), with the top-right point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(-150, 60)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(-150, 230)" /><!-- (-150,170+60) -->
+ </g>
+ <g id="cairo_logo_bottomleft-centered">
+ <!-- The logo (scarab and dung), with the bottom-left point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(150, -340)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(150, -170)" />
+ </g>
+ <g id="cairo_logo_bottomright-centered">
+ <!-- The logo (scarab and dung), with the bottom-right point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(-150, -340)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(-150, -170)" />
+ </g>
+
+ <g id="cairo_text" transform="translate(0,-97)">
+ <g transform="scale(0.1484,0.1484)"> <g transform="translate(-1139,-208.5)">
+ <!-- 63 (c), advance 444, 0 horiBearing 38,522 -->
+ <path transform="translate(65,0)" d="
+ M 412, 433
+ C 385, 422 336, 413 298, 413
+ C 142, 413 38, 525 38, 680
+ C 38, 826 144, 947 298, 947
+ C 332, 947 377, 944 416, 926
+ L 409, 842
+ C 380, 861 340, 871 308, 871
+ C 187, 871 138, 771 138, 680
+ C 138, 583 197, 489 302, 489
+ C 332, 489 368, 496 404, 511
+ L 412, 433 " />
+ <!-- 61 (a), advance 556, 0 horiBearing 46,522 -->
+ <path transform="translate(486.75,0)" d="
+ M 109, 541
+ C 147, 509 204, 489 257, 489
+ C 351, 489 383, 534 383, 622
+ C 346, 620 320, 620 283, 620
+ C 186, 620 46, 660 46, 788
+ C 46, 899 123, 947 233, 947
+ C 319, 947 369, 900 391, 869
+ L 393, 869
+ L 393, 935
+ L 481, 935
+ C 479, 920 477, 893 477, 835
+ L 477, 624
+ C 477, 485 418, 413 272, 413
+ C 207, 413 151, 433 104, 461
+ L 109, 541
+ M 383, 737
+ C 383, 813 334, 871 241, 871
+ C 198, 871 146, 842 146, 788
+ C 146, 698 272, 690 323, 690
+ C 343, 690 363, 692 383, 692
+ L 383, 737 " />
+ <!-- 69 (i), advance 278, 0 horiBearing 86,730 -->
+ <path transform="translate(1000,0)" d="
+ M 92, 935
+ L 186, 935
+ L 186, 425
+ L 92, 425
+ L 92, 935
+ M 88, 261
+ A 51, 51 0 1 1 190,261
+ A 51, 51 0 1 1 88,261" />
+ <!-- 72 (r), advance 389, 0 horiBearing 80,522 -->
+ <path transform="translate(1234.25,0)" d="
+ M 80, 935
+ L 174, 935
+ L 174, 703
+ C 174, 575 229, 495 313, 495
+ C 329, 495 348, 497 365, 504
+ L 365, 420
+ C 345, 416 331, 413 303, 413
+ C 249, 413 195, 451 170, 504
+ L 168, 504
+ L 168, 425
+ L 80, 425
+ L 80, 935 " />
+ <!-- 6f (o), advance 611, 0 horiBearing 46,522 -->
+ <path transform="translate(1610,0)" d="
+ M 46, 680
+ C 46, 826 152, 947 306, 947
+ C 459, 947 565, 826 565, 680
+ C 565, 525 461, 413 306, 413
+ C 150, 413 46, 525 46, 680
+ M 146, 680
+ C 146, 583 205, 489 306, 489
+ C 406, 489 465, 583 465, 680
+ C 465, 771 416, 871 306, 871
+ C 195, 871 146, 771 146, 680 " />
+ <!-- bounds: 38, 205 <-> 2232, 947 -->
+ </g> </g>
+ </g>
+
+ <!-- scaled by 0.72, shifted around to hit pixel boundaries -->
+ <g id="cairo_text_small_spaced" transform="translate(0,-71)">
+ <g transform="scale(0.085,0.085)"> <g transform="translate(-1139,-208.5)">
+ <!-- 63 (c), advance 444, 0 horiBearing 38,522 -->
+ <path transform="translate(-151,0)" d="
+ M 412, 433
+ C 385, 422 336, 413 298, 413
+ C 142, 413 38, 525 38, 680
+ C 38, 826 144, 947 298, 947
+ C 332, 947 377, 944 416, 926
+ L 409, 842
+ C 380, 861 340, 871 308, 871
+ C 187, 871 138, 771 138, 680
+ C 138, 583 197, 489 302, 489
+ C 332, 489 368, 496 404, 511
+ L 412, 433 " />
+ <!-- 61 (a), advance 556, 0 horiBearing 46,522 -->
+ <path transform="translate(379.5,0)" d="
+ M 109, 541
+ C 147, 509 204, 489 257, 489
+ C 351, 489 383, 534 383, 622
+ C 346, 620 320, 620 283, 620
+ C 186, 620 46, 660 46, 788
+ C 46, 899 123, 947 233, 947
+ C 319, 947 369, 900 391, 869
+ L 393, 869
+ L 393, 935
+ L 481, 935
+ C 479, 920 477, 893 477, 835
+ L 477, 624
+ C 477, 485 418, 413 272, 413
+ C 207, 413 151, 433 104, 461
+ L 109, 541
+ M 383, 737
+ C 383, 813 334, 871 241, 871
+ C 198, 871 146, 842 146, 788
+ C 146, 698 272, 690 323, 690
+ C 343, 690 363, 692 383, 692
+ L 383, 737 " />
+ <!-- 69 (i), advance 278, 0 horiBearing 86,730 -->
+ <path transform="translate(1000,0)" d="
+ M 92, 935
+ L 186, 935
+ L 186, 425
+ L 92, 425
+ L 92, 935
+ M 88, 261
+ A 51, 51 0 1 1 190,261
+ A 51, 51 0 1 1 88,261" />
+ <!-- 72 (r), advance 389, 0 horiBearing 80,522 -->
+ <path transform="translate(1341.5,0)" d="
+ M 80, 935
+ L 174, 935
+ L 174, 703
+ C 174, 575 229, 495 313, 495
+ C 329, 495 348, 497 365, 504
+ L 365, 420
+ C 345, 416 331, 413 303, 413
+ C 249, 413 195, 451 170, 504
+ L 168, 504
+ L 168, 425
+ L 80, 425
+ L 80, 935 " />
+ <!-- 6f (o), advance 611, 0 horiBearing 46,522 -->
+ <path transform="translate(1826,0)" d="
+ M 46, 680
+ C 46, 826 152, 947 306, 947
+ C 459, 947 565, 826 565, 680
+ C 565, 525 461, 413 306, 413
+ C 150, 413 46, 525 46, 680
+ M 146, 680
+ C 146, 583 205, 489 306, 489
+ C 406, 489 465, 583 465, 680
+ C 465, 771 416, 871 306, 871
+ C 195, 871 146, 771 146, 680 " />
+ <!-- bounds: 38, 205 <-> 2232, 947 -->
+ </g> </g>
+ </g>
+
+
+ <!-- scaled by 0.72, shifted around to hit pixel boundaries -->
+ <g id="cairo_text_small" transform="translate(0,-71)">
+ <g transform="scale(0.085,0.085)"> <g transform="translate(-1139,-208.5)">
+ <!-- 63 (c), advance 444, 0 horiBearing 38,522 -->
+ <path transform="translate(-151,0)" d="
+ M 412, 433
+ C 385, 422 336, 413 298, 413
+ C 142, 413 38, 525 38, 680
+ C 38, 826 144, 947 298, 947
+ C 332, 947 377, 944 416, 926
+ L 409, 842
+ C 380, 861 340, 871 308, 871
+ C 187, 871 138, 771 138, 680
+ C 138, 583 197, 489 302, 489
+ C 332, 489 368, 496 404, 511
+ L 412, 433 " />
+ <!-- 61 (a), advance 556, 0 horiBearing 46,522 -->
+ <path transform="translate(261.75,0)" d="
+ M 109, 541
+ C 147, 509 204, 489 257, 489
+ C 351, 489 383, 534 383, 622
+ C 346, 620 320, 620 283, 620
+ C 186, 620 46, 660 46, 788
+ C 46, 899 123, 947 233, 947
+ C 319, 947 369, 900 391, 869
+ L 393, 869
+ L 393, 935
+ L 481, 935
+ C 479, 920 477, 893 477, 835
+ L 477, 624
+ C 477, 485 418, 413 272, 413
+ C 207, 413 151, 433 104, 461
+ L 109, 541
+ M 383, 737
+ C 383, 813 334, 871 241, 871
+ C 198, 871 146, 842 146, 788
+ C 146, 698 272, 690 323, 690
+ C 343, 690 363, 692 383, 692
+ L 383, 737 " />
+ <!-- 69 (i), advance 278, 0 horiBearing 86,730 -->
+ <path transform="translate(764.75)" d="
+ M 92, 935
+ L 186, 935
+ L 186, 425
+ L 92, 425
+ L 92, 935
+ M 88, 261
+ A 51, 51 0 1 1 190,261
+ A 51, 51 0 1 1 88,261" />
+ <!-- 72 (r), advance 389, 0 horiBearing 80,522 -->
+ <path transform="translate(988.5,0)" d="
+ M 80, 935
+ L 174, 935
+ L 174, 703
+ C 174, 575 229, 495 313, 495
+ C 329, 495 348, 497 365, 504
+ L 365, 420
+ C 345, 416 331, 413 303, 413
+ C 249, 413 195, 451 170, 504
+ L 168, 504
+ L 168, 425
+ L 80, 425
+ L 80, 935 " />
+ <!-- 6f (o), advance 611, 0 horiBearing 46,522 -->
+ <path transform="translate(1355.5,0)" d="
+ M 46, 680
+ C 46, 826 152, 947 306, 947
+ C 459, 947 565, 826 565, 680
+ C 565, 525 461, 413 306, 413
+ C 150, 413 46, 525 46, 680
+ M 146, 680
+ C 146, 583 205, 489 306, 489
+ C 406, 489 465, 583 465, 680
+ C 465, 771 416, 871 306, 871
+ C 195, 871 146, 771 146, 680 " />
+ <!-- bounds: 38, 205 <-> 2232, 947 -->
+ </g> </g>
+ </g>
+
+ <g id="cairo_logo_text_small">
+ <!-- The logo on the left, the text 'cairo' on the right -->
+ <use xlink:href="#cairo_logo_bottomleft-centered" transform="translate(0, 78), scale(0.1944)" />
+ <use xlink:href="#cairo_text_small" transform="translate(175,82)"/>
+ </g>
+
+ <g id="cairo_logo_with_text">
+ <!-- The logo (scarab and dung), with the text 'cairo' below, the dot of the 'i' positioned between the hind legs of the scarab -->
+ <!-- dimensions: 300x490, centered -->
+ <use xlink:href="#cairo_logo_top-centered" transform="translate(0, -245)" />
+ <use xlink:href="#cairo_text" transform="translate(0, 245)" />
+ </g>
+
+ <g id="cairo_banner">
+ <!-- The logo on the left, the text 'cairo' in the center, and a mirror image of the logo on the right -->
+ <!-- The logos are scaled such that the scarab body nearly matches the height of the text characters (excepting the 'i')
+ and the dung should nearly aligns with the dot of the 'i'. The bottoms of the logos are aligned with the bottom of the text. -->
+ <!-- dimensions: 370x88, centered -->
+ <use xlink:href="#cairo_logo_bottomleft-centered" transform="translate(-180, 40), scale(0.1944)" />
+ <use xlink:href="#cairo_text_small" transform="translate(0, 42)" fill="black" />
+ <use xlink:href="#cairo_logo_bottomleft-centered" transform="translate(180, 40), scale(0.1944), scale(-1, 1)" />
+ </g>
+
+ <g id="freedesktop_org_logo" style="fill:#FFFFFF;stroke:#3B80AE;stroke-width:2.4588;">
+ <g>
+ <path style="stroke:#BABABA;" d="M85.277,40.796c2.058,7.884-2.667,15.942-10.551,17.999L27.143,71.21c-7.884,2.057-15.943-2.667-18-10.552
+ l-7.448-28.55c-2.057-7.884,2.667-15.942,10.551-17.999L59.83,1.695c7.884-2.057,15.942,2.667,17.999,10.551
+ l7.449,28.55z"/>>
+ <path style="fill:#3B80AE;stroke:none;" d="M80.444,39.778c1.749,7.854-1.816,13.621-9.504,15.447l-42.236,11.02c-7.569,2.396-14.089-1.181
+ -15.838-8.836L6.53,33.127c-1.749-8.145,0.709-12.889,9.503-15.447L58.27,6.661
+ c8.144-1.826,14.089,1.363,15.838,8.835l6.336,24.282z"/>>
+ </g>g>
+ <path style="opacity:0.5;fill:none;stroke:#FFFFFF;" d="M45.542,51.793L24.104,31.102l38.1-4.393L45.542,51.793z"/>>
+ <path d="M72.325,28.769c0.405,1.55-0.525,3.136-2.075,3.541l-12.331,3.217c-1.551,0.404-3.137-0.525-3.542-2.076l-2.295-8.801
+ c-0.405-1.551,0.524-3.137,2.076-3.542l12.33-3.217c1.551-0.405,3.137,0.525,3.542,2.076l2.295,8.801z"/>>
+ <path d="M36.51,33.625c0.496,1.9-0.645,3.844-2.545,4.34l-15.112,3.943c-1.901,0.496-3.845-0.644-4.34-2.544l-2.814-10.786
+ c-0.496-1.901,0.644-3.844,2.544-4.34l15.113-3.942c1.901-0.496,3.845,0.643,4.34,2.544l2.814,10.786z"/>>
+ <path d="M52.493,53.208c0.278,1.065-0.36,2.154-1.425,2.432L42.6,57.848c-1.064,0.277-2.153-0.36-2.431-1.426l-1.577-6.043
+ c-0.277-1.064,0.36-2.153,1.425-2.432l8.468-2.209c1.064-0.277,2.154,0.361,2.431,1.426l1.577,6.043z"/>>
+ </g>g>
+ <g id="bullet">
+ <use x="0" y="0" xlink:href="#cairo_logo" transform="translate(-6,-2) scale(0.1, 0.1)"/>>
+ </g>
+ </defs>
+
+ <g id="watermark" transform="translate(200, 185), rotate(-50), scale(2.5)">
+ <use xlink:href="#scarab" x="0" y="170" fill-opacity="0.08"/>
+ </g>
+
+ <!-- Blue bar at top of slide -->
+ <rect x="0" y="0" width="1024" height="50" fill="#3B80AE" fill-opacity="0.3" />
+
+ <!-- Scarab and "cairo" at upper-left -->
+ <g transform="translate(10,0)">
+ <use xlink:href="#cairo_logo_text_small"/>
+ </g>
+
+ <!-- Presentation title at upper-left -->
+ <text ss:variable="presentation-subtitle" x="260" y="50" font-size="20">Presentation Sub-title</text>
+
+ <!-- freedesktop.org logo at upper-right -->
+ <use xlink:href="#freedesktop_org_logo" transform="translate(910, 12)" />
+
+ <g font-family="Frutiger">
+ <text text-anchor="middle"
+ fill="black"
+ x="512"
+ y="300" font-size="90"
+ ss:variable="title">Slide Title</text>
+
+ <!-- Slide content -->
+ <g ss:region="default">
+ <rect x="112" y="400" width="800" height="280" fill="none" stroke="blue"/>
+ <text font-size="40" fill="black"
+ x="112" y="232">Slide content</text>
+ </g>
+
+ <!-- Footer -->
+ <text ss:variable="URL" x="1016" y="760" text-anchor="end" font-size="20">http://cairographics.org</text>
+ </g>
+
+</svg>
diff --git a/doc/tutorial/slides/cairo-title.svg b/doc/tutorial/slides/cairo-title.svg
new file mode 100644
index 000000000..6e397e939
--- /dev/null
+++ b/doc/tutorial/slides/cairo-title.svg
@@ -0,0 +1,373 @@
+<?xml version="1.0" ?>
+<svg width="1024" height="768"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:ss="http://www.svgslides.org/svgslides0.1"
+ fill="black">
+
+ <defs id="cairo-artwork_defs">
+ <g id="hacker_emblem">
+ <!-- Note: This is similar though not identical to Keith Packard's SVG version
+ of the hacker emblem (http://www.catb.org/hacker-emblem/glider.svg) -->
+ <g id="hacker_emblem_grid" fill="white" stroke="none">
+ <!-- Outside: Top, Right, Bottom, Left -->
+ <rect x="-2.95" y="-3.05" width="6" height="0.1" />
+ <rect x="2.95" y="-2.95" width="0.1" height="6" />
+ <rect x="-3.05" y="2.95" width="6" height="0.1" />
+ <rect x="-3.05" y="-3.05" width="0.1" height="6" />
+ <!-- Vertical: Left, Right -->
+ <rect x="-1.05" y="-2.95" width="0.1" height="5.9" />
+ <rect x="0.95" y="-2.95" width="0.1" height="5.9" />
+ <!-- Horizontal: TopLeft, TopMiddle, TopRight -->
+ <rect x="-2.95" y="-1.05" width="1.9" height="0.1" />
+ <rect x="-0.95" y="-1.05" width="1.9" height="0.1" />
+ <rect x="1.05" y="-1.05" width="1.9" height="0.1" />
+ <!-- Horizontal: BottomLeft, BottomMiddle, BottomRight -->
+ <rect x="-2.95" y="0.95" width="1.9" height="0.1" />
+ <rect x="-0.95" y="0.95" width="1.9" height="0.1" />
+ <rect x="1.05" y="0.95" width="1.9" height="0.1" />
+ </g>
+ <g id="hacker_emblem_dots" fill="white">
+ <circle cx="0" cy="-2" r="0.7" />
+ <circle cx="2" cy="0" r="0.7" />
+ <circle cx="-2" cy="2" r="0.7" />
+ <circle cx="0" cy="2" r="0.7" />
+ <circle cx="2" cy="2" r="0.7" />
+ </g>
+ </g>
+ <g id="scarab" fill="#3B80AE">
+ <g transform="translate(-150, -170)">
+ <path id="scarab_head" d="M205.599,94.567c0-11.668-24.914-21.129-55.628-21.129
+ c-30.723,0-55.624,9.46-55.624,21.129c0,10.203,24.901,7.346,55.624,7.346C180.685,101.913,205.599,104.233,205.599,94.567z"/>
+ <path id="scarab_torso" d="M136.423,161.506c0,0,12.751,12.577,13.547,13.362
+ c2.262-2.232,13.545-13.362,13.545-13.362c7.135-7.036,87.111-6.399,91.066-6.363c-0.469-6.298-1.254-12.472-2.325-18.519
+ c-15.183-19.279-42.811-32.225-74.485-32.225h-55.518c-31.745,0-59.439,13.011-74.598,32.37c-1.054,6-1.829,12.128-2.296,18.374
+ C49.321,155.106,129.288,154.47,136.423,161.506z"/>
+ <path id="scarab_spine" d="M149.97,301.187c2.005-24.729,8.386-103.483,8.405-103.721
+ c-0.09-0.219-6.478-15.578-8.405-20.214c-1.936,4.655-8.316,19.995-8.408,20.214C141.582,197.704,147.965,276.458,149.97,301.187z"/>
+ <path id="scarab_wing_left" d="M140.403,197.149l8.862-21.31l-13.686-13.499
+ c-5.65-5.573-67.074-6.235-90.259-6.019l-0.006-0.622c-0.154,2.144-0.271,4.302-0.35,6.475
+ c-0.076,2.207,10.392,4.706,10.392,6.717c0,2.319-10.457,5.084-10.359,7.631c2.993,73.349,48.53,131.631,104.372,132.048
+ l-9.02-111.29L140.403,197.149z"/>
+ <path id="scarab_wing_right" d="M244.585,168.891c0-2.011,10.467-4.506,10.391-6.715
+ c-0.079-2.174-0.195-4.332-0.351-6.479l-0.004,0.624c-23.186-0.216-84.608,0.445-90.26,6.017l-13.688,13.502l8.915,21.438
+ l-9.017,111.29c55.854-0.417,101.378-58.698,104.373-132.049C255.04,173.976,244.585,171.209,244.585,168.891z"/>
+ <path id="scarab_leg_front_left" d="M44.506,141.12c-4.135-0.856-4.895-1.54-7.935-2.92
+ c-9.59-3.364-10.376-5.481-16.08-11.86c-7.426-8.306-12.661-20.142-17.1-29.463c-3.576-7.525-3.984-16.409-2.86-24.273
+ c0.991-6.935,7.144-12.869,12.074-18.92c5.844-7.191,10.356-14.822,17.924-21.354c7.736-6.682,23.203-9.809,26.168-19.648
+ C57.86,8.819,54.334,1.766,61.482,0c-0.366,4.703,3.639,8.477,2.397,13.575c-1.129,4.627-4.368,5.811-9.611,9.099
+ c-7.564,4.746-18.366,8.779-24.748,13.965c-7.175,5.827-4.369,13.771-10.569,20.057c-2.001,2.03-7.901,4.706-9.137,6.83
+ c-1.861,3.199-0.297,9.572-0.116,13.12c0.425,8.284,5.588,14.244,9.555,22.045c4.152,8.141,6.429,15.409,13.411,22.519
+ c4.183,4.262,11.429,4.802,16.21,10.647l-3.555,4.186L44.506,141.12z"/>
+ <path id="scarab_leg_middle_left" d="M43.94,191.922l-0.809-7.346
+ c-9.506-4.579-10.339-9.772-20.738-12.466c-23.728-6.151-21.361,11.25-15.532,26.373c5.676,14.726,8.237,30.23,14.345,44.795
+ c2.805,6.688,6.919,13.213,14.298,15.127c0.372-8.435-0.917-10.651-6.113-16.919c-4.395-5.293-3.326-12.548-6.072-18.504
+ c-3.581-7.804-4.196-15.646-7.279-23.502c-1.363-3.479-8.33-13.966-6.452-17.861c3.183-6.603,9.178-0.083,12.179,2.077
+ c4.218,3.036,6.467,2.223,11.681,2.898C34.041,186.673,37.005,188.756,43.94,191.922z"/>
+ <path id="scarab_leg_back_left" d="M65.839,257.063l-2.771-4.837
+ c-6.68,8.928-6.993,16.228-10.056,23.347c-5.277,12.263-0.157,28.851,9.854,37.676c6.052,5.375,15.907,9.618,23.122,13.136
+ c10.035,4.892,20.113,11.286,31.336,13.396c2.482,0.466,8.798,1.295,6.693-3.522c-0.975-2.237-8.091-4.591-10.146-5.734
+ c-8.312-4.623-16.377-10.524-24.142-16.176c-9.498-6.862-20.843-11.186-28.311-20.684c-3.054-3.885-3.544-4.922-2.816-9.39
+ c0.693-4.263,1.344-9.174,2.241-13.439C61.855,266.029,63.274,261.378,65.839,257.063z"/>
+ <path id="scarab_leg_front_right" d="M255.487,141.12c4.134-0.856,4.896-1.54,7.936-2.92
+ c9.583-3.364,10.369-5.481,16.071-11.86c7.428-8.306,12.661-20.142,17.115-29.463c3.574-7.525,3.983-16.409,2.86-24.273
+ c-0.992-6.935-7.157-12.869-12.087-18.92c-5.843-7.191-10.356-14.822-17.919-21.354c-7.735-6.682-23.202-9.809-26.167-19.648
+ C242.135,8.819,245.66,1.766,238.511,0c0.366,4.703-3.637,8.477-2.396,13.575c1.131,4.627,4.368,5.811,9.611,9.099
+ c7.563,4.746,18.367,8.779,24.747,13.965c7.17,5.827,4.362,13.771,10.563,20.057c2.001,2.03,7.901,4.706,9.139,6.83
+ c1.859,3.199,0.295,9.572,0.113,13.12c-0.424,8.284-5.588,14.244-9.553,22.045c-4.152,8.141-6.431,15.409-13.404,22.519
+ c-4.184,4.262-11.429,4.802-16.211,10.647l3.556,4.186L255.487,141.12z"/>
+ <path id="scarab_leg_middle_right" d="M256.053,191.922l0.81-7.346
+ c9.507-4.579,10.34-9.772,20.73-12.466c23.741-6.151,21.374,11.25,15.534,26.373c-5.676,14.726-8.238,30.23-14.347,44.795
+ c-2.804,6.688-6.911,13.213-14.291,15.127c-0.371-8.435,0.918-10.651,6.113-16.919c4.39-5.293,3.319-12.548,6.066-18.504
+ c3.58-7.804,4.197-15.646,7.278-23.502c1.363-3.479,8.33-13.966,6.453-17.861c-3.184-6.603-9.179-0.083-12.181,2.077
+ c-4.217,3.036-6.458,2.223-11.672,2.898C265.951,186.673,262.986,188.756,256.053,191.922z"/>
+ <path id="scarab_leg_back_right" d="M234.155,257.063l2.771-4.837
+ c6.679,8.928,6.991,16.228,10.057,23.347c5.274,12.263,0.154,28.851-9.854,37.676c-6.055,5.375-15.903,9.618-23.117,13.136
+ c-10.034,4.892-20.127,11.286-31.351,13.396c-2.481,0.466-8.789,1.295-6.691-3.522c0.976-2.237,8.092-4.591,10.146-5.734
+ c8.312-4.623,16.392-10.524,24.155-16.176c9.498-6.862,20.838-11.186,28.305-20.684c3.055-3.885,3.543-4.922,2.818-9.39
+ c-0.696-4.263-1.346-9.174-2.244-13.439C238.137,266.029,236.718,261.378,234.155,257.063z"/>
+ </g>
+ </g>
+ <radialGradient id="gradient_radial_dung"
+ cx="0" cy="0" r="60"
+ fx="0" fy="0" gradientUnits="userSpaceOnUse"
+ >
+ <stop offset="0" stop-color="#9a9a9a" />
+ <stop offset="0.70" stop-color="#bababa" />
+ <stop offset="0.95" stop-color="#FFFFFF" />
+ </radialGradient>
+ <g id="dung">
+ <circle cx="0" cy="0" r="60" fill="url(#gradient_radial_dung)" />
+ <g transform="translate(-61, -61)">
+ <!-- rough equivalent: <circle cx="0" cy="0" r="60" stroke="#8a8a8a" stroke-width="2" /> -->
+ <path fill="#8a8a8a" d="M0,61c0,33.636,27.364,61,61,61s61-27.364,61-61S94.636,0,61,0S0,27.364,0,61z
+ M2,61C2,28.467,28.467,2,61,2c32.532,0,59,26.467,59,59c0,32.533-26.468,59-59,59C28.467,120,2,93.533,2,61z"/>
+ </g>
+ <use xlink:href="#hacker_emblem" x="0" y="0" transform="scale(9)" />
+ </g>
+
+ <!-- scarab dimensions: 300x340 -->
+ <!-- dung dimensions: 120x120 (radius: 60) -->
+ <!-- scarab and dung dimensions: 300x400 -->
+
+ <g id="cairo_logo">
+ <!-- dimensions: 300x400, centered -->
+ <!-- The logo (scarab and dung), with the center-point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, -140)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, 30)" />
+ </g>
+ <g id="cairo_logo_dung-centered">
+ <!-- The logo (scarab and dung), with the dung at (0,0), the scarab below -->
+ <use xlink:href="#dung" x="0" y="0" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0,170)" />
+ </g>
+ <g id="cairo_logo_scarab-centered">
+ <!-- The logo (scarab and dung), with the scarab's rotational center at (0,0), the dung above -->
+ <!-- The scarab's rotational center in this case is not the center of its bounding box,
+ but is calculated to be the intersection-point of the torso, spine and wings -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, -175.85)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, -5.85)" />
+ </g>
+ <g id="cairo_logo_top-centered">
+ <!-- The logo (scarab and dung), with the top-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, 60)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, 230)" /><!-- (0,170+60) -->
+ </g>
+ <g id="cairo_logo_bottom-centered">
+ <!-- The logo (scarab and dung), with the bottom-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, -340)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, -170)" />
+ </g>
+ <g id="cairo_logo_right-centered">
+ <!-- The logo (scarab and dung), with the right-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(-150, -140)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(-150, 30)" />
+ </g>
+ <g id="cairo_logo_left-centered">
+ <!-- The logo (scarab and dung), with the left-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(150, -140)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(150, 30)" />
+ </g>
+ <g id="cairo_logo_topleft-centered">
+ <!-- The logo (scarab and dung), with the top-left point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(150, 60)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(150, 230)" /><!-- (150, 170+60) -->
+ </g>
+ <g id="cairo_logo_topright-centered">
+ <!-- The logo (scarab and dung), with the top-right point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(-150, 60)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(-150, 230)" /><!-- (-150,170+60) -->
+ </g>
+ <g id="cairo_logo_bottomleft-centered">
+ <!-- The logo (scarab and dung), with the bottom-left point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(150, -340)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(150, -170)" />
+ </g>
+ <g id="cairo_logo_bottomright-centered">
+ <!-- The logo (scarab and dung), with the bottom-right point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(-150, -340)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(-150, -170)" />
+ </g>
+
+ <g id="cairo_text" transform="translate(0,-97)">
+ <g transform="scale(0.1484,0.1484)"> <g transform="translate(-1139,-208.5)">
+ <!-- 63 (c), advance 444, 0 horiBearing 38,522 -->
+ <path transform="translate(65,0)" d="
+ M 412, 433
+ C 385, 422 336, 413 298, 413
+ C 142, 413 38, 525 38, 680
+ C 38, 826 144, 947 298, 947
+ C 332, 947 377, 944 416, 926
+ L 409, 842
+ C 380, 861 340, 871 308, 871
+ C 187, 871 138, 771 138, 680
+ C 138, 583 197, 489 302, 489
+ C 332, 489 368, 496 404, 511
+ L 412, 433 " />
+ <!-- 61 (a), advance 556, 0 horiBearing 46,522 -->
+ <path transform="translate(486.75,0)" d="
+ M 109, 541
+ C 147, 509 204, 489 257, 489
+ C 351, 489 383, 534 383, 622
+ C 346, 620 320, 620 283, 620
+ C 186, 620 46, 660 46, 788
+ C 46, 899 123, 947 233, 947
+ C 319, 947 369, 900 391, 869
+ L 393, 869
+ L 393, 935
+ L 481, 935
+ C 479, 920 477, 893 477, 835
+ L 477, 624
+ C 477, 485 418, 413 272, 413
+ C 207, 413 151, 433 104, 461
+ L 109, 541
+ M 383, 737
+ C 383, 813 334, 871 241, 871
+ C 198, 871 146, 842 146, 788
+ C 146, 698 272, 690 323, 690
+ C 343, 690 363, 692 383, 692
+ L 383, 737 " />
+ <!-- 69 (i), advance 278, 0 horiBearing 86,730 -->
+ <path transform="translate(1000,0)" d="
+ M 92, 935
+ L 186, 935
+ L 186, 425
+ L 92, 425
+ L 92, 935
+ M 88, 261
+ A 51, 51 0 1 1 190,261
+ A 51, 51 0 1 1 88,261" />
+ <!-- 72 (r), advance 389, 0 horiBearing 80,522 -->
+ <path transform="translate(1234.25,0)" d="
+ M 80, 935
+ L 174, 935
+ L 174, 703
+ C 174, 575 229, 495 313, 495
+ C 329, 495 348, 497 365, 504
+ L 365, 420
+ C 345, 416 331, 413 303, 413
+ C 249, 413 195, 451 170, 504
+ L 168, 504
+ L 168, 425
+ L 80, 425
+ L 80, 935 " />
+ <!-- 6f (o), advance 611, 0 horiBearing 46,522 -->
+ <path transform="translate(1610,0)" d="
+ M 46, 680
+ C 46, 826 152, 947 306, 947
+ C 459, 947 565, 826 565, 680
+ C 565, 525 461, 413 306, 413
+ C 150, 413 46, 525 46, 680
+ M 146, 680
+ C 146, 583 205, 489 306, 489
+ C 406, 489 465, 583 465, 680
+ C 465, 771 416, 871 306, 871
+ C 195, 871 146, 771 146, 680 " />
+ <!-- bounds: 38, 205 <-> 2232, 947 -->
+ </g> </g>
+ </g>
+
+ <!-- scaled by 0.72, shifted around to hit pixel boundaries -->
+ <g id="cairo_text_small" transform="translate(0,-71)">
+ <g transform="scale(0.085,0.085)"> <g transform="translate(-1139,-208.5)">
+ <!-- 63 (c), advance 444, 0 horiBearing 38,522 -->
+ <path transform="translate(-151,0)" d="
+ M 412, 433
+ C 385, 422 336, 413 298, 413
+ C 142, 413 38, 525 38, 680
+ C 38, 826 144, 947 298, 947
+ C 332, 947 377, 944 416, 926
+ L 409, 842
+ C 380, 861 340, 871 308, 871
+ C 187, 871 138, 771 138, 680
+ C 138, 583 197, 489 302, 489
+ C 332, 489 368, 496 404, 511
+ L 412, 433 " />
+ <!-- 61 (a), advance 556, 0 horiBearing 46,522 -->
+ <path transform="translate(379.5,0)" d="
+ M 109, 541
+ C 147, 509 204, 489 257, 489
+ C 351, 489 383, 534 383, 622
+ C 346, 620 320, 620 283, 620
+ C 186, 620 46, 660 46, 788
+ C 46, 899 123, 947 233, 947
+ C 319, 947 369, 900 391, 869
+ L 393, 869
+ L 393, 935
+ L 481, 935
+ C 479, 920 477, 893 477, 835
+ L 477, 624
+ C 477, 485 418, 413 272, 413
+ C 207, 413 151, 433 104, 461
+ L 109, 541
+ M 383, 737
+ C 383, 813 334, 871 241, 871
+ C 198, 871 146, 842 146, 788
+ C 146, 698 272, 690 323, 690
+ C 343, 690 363, 692 383, 692
+ L 383, 737 " />
+ <!-- 69 (i), advance 278, 0 horiBearing 86,730 -->
+ <path transform="translate(1000,0)" d="
+ M 92, 935
+ L 186, 935
+ L 186, 425
+ L 92, 425
+ L 92, 935
+ M 88, 261
+ A 51, 51 0 1 1 190,261
+ A 51, 51 0 1 1 88,261" />
+ <!-- 72 (r), advance 389, 0 horiBearing 80,522 -->
+ <path transform="translate(1341.5,0)" d="
+ M 80, 935
+ L 174, 935
+ L 174, 703
+ C 174, 575 229, 495 313, 495
+ C 329, 495 348, 497 365, 504
+ L 365, 420
+ C 345, 416 331, 413 303, 413
+ C 249, 413 195, 451 170, 504
+ L 168, 504
+ L 168, 425
+ L 80, 425
+ L 80, 935 " />
+ <!-- 6f (o), advance 611, 0 horiBearing 46,522 -->
+ <path transform="translate(1826,0)" d="
+ M 46, 680
+ C 46, 826 152, 947 306, 947
+ C 459, 947 565, 826 565, 680
+ C 565, 525 461, 413 306, 413
+ C 150, 413 46, 525 46, 680
+ M 146, 680
+ C 146, 583 205, 489 306, 489
+ C 406, 489 465, 583 465, 680
+ C 465, 771 416, 871 306, 871
+ C 195, 871 146, 771 146, 680 " />
+ <!-- bounds: 38, 205 <-> 2232, 947 -->
+ </g> </g>
+ </g>
+
+ <g id="cairo_logo_with_text">
+ <!-- The logo (scarab and dung), with the text 'cairo' below, the dot of the 'i' positioned between the hind legs of the scarab -->
+ <!-- dimensions: 300x490, centered -->
+ <use xlink:href="#cairo_logo_top-centered" transform="translate(0, -245)" />
+ <use xlink:href="#cairo_text" transform="translate(0, 245)" />
+ </g>
+
+ <g id="cairo_banner">
+ <!-- The logo on the left, the text 'cairo' in the center, and a mirror image of the logo on the right -->
+ <!-- The logos are scaled such that the scarab body nearly matches the height of the text characters (excepting the 'i')
+ and the dung should nearly aligns with the dot of the 'i'. The bottoms of the logos are aligned with the bottom of the text. -->
+ <!-- dimensions: 370x88, centered -->
+ <use xlink:href="#cairo_logo_bottomleft-centered" transform="translate(-180, 40), scale(0.1944)" />
+ <use xlink:href="#cairo_text_small" transform="translate(0, 42)" fill="black" />
+ <use xlink:href="#cairo_logo_bottomleft-centered" transform="translate(180, 40), scale(0.1944), scale(-1, 1)" />
+ </g>
+ </defs>
+
+<g fill="black">
+
+ <!-- freedesktop.org logo at upper-right -->
+ <use xlink:href="#freedesktop_org_logo" transform="translate(910, 12)" />
+
+ <g font-family="Frutiger">
+
+ <use xlink:href="#cairo_logo_with_text" transform="translate(256, 420)" />
+
+ <g id="slide_title" transform="translate(512, 80)">
+ <text text-anchor="middle"
+ fill="black"
+ x="0"
+ y="10" font-size="55"
+ ss:variable="presentation">Presentation Title</text>
+ </g>
+
+ <g ss:region="default" text-anchor="middle">
+ <rect x="690" y="270" width="2" height="350" fill="none" stroke="blue"/>
+ <text font-size="40" fill="black"
+ x="690" y="310">Slide content</text>
+ </g>
+ </g>
+
+</g>
+
+</svg>
diff --git a/doc/tutorial/slides/cairo.svg b/doc/tutorial/slides/cairo.svg
new file mode 100644
index 000000000..5a9449b76
--- /dev/null
+++ b/doc/tutorial/slides/cairo.svg
@@ -0,0 +1,508 @@
+<?xml version="1.0" ?>
+<svg width="1024" height="768"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:ss="http://www.svgslides.org/svgslides0.1"
+ fill="black">
+
+
+ <defs id="cairo-artwork_defs">
+ <g id="hacker_emblem">
+ <!-- Note: This is similar though not identical to Keith Packard's SVG version
+ of the hacker emblem (http://www.catb.org/hacker-emblem/glider.svg) -->
+ <g id="hacker_emblem_grid" fill="white" stroke="none">
+ <!-- Outside: Top, Right, Bottom, Left -->
+ <rect x="-2.95" y="-3.05" width="6" height="0.1" />
+ <rect x="2.95" y="-2.95" width="0.1" height="6" />
+ <rect x="-3.05" y="2.95" width="6" height="0.1" />
+ <rect x="-3.05" y="-3.05" width="0.1" height="6" />
+ <!-- Vertical: Left, Right -->
+ <rect x="-1.05" y="-2.95" width="0.1" height="5.9" />
+ <rect x="0.95" y="-2.95" width="0.1" height="5.9" />
+ <!-- Horizontal: TopLeft, TopMiddle, TopRight -->
+ <rect x="-2.95" y="-1.05" width="1.9" height="0.1" />
+ <rect x="-0.95" y="-1.05" width="1.9" height="0.1" />
+ <rect x="1.05" y="-1.05" width="1.9" height="0.1" />
+ <!-- Horizontal: BottomLeft, BottomMiddle, BottomRight -->
+ <rect x="-2.95" y="0.95" width="1.9" height="0.1" />
+ <rect x="-0.95" y="0.95" width="1.9" height="0.1" />
+ <rect x="1.05" y="0.95" width="1.9" height="0.1" />
+ </g>
+ <g id="hacker_emblem_dots" fill="white">
+ <circle cx="0" cy="-2" r="0.7" />
+ <circle cx="2" cy="0" r="0.7" />
+ <circle cx="-2" cy="2" r="0.7" />
+ <circle cx="0" cy="2" r="0.7" />
+ <circle cx="2" cy="2" r="0.7" />
+ </g>
+ </g>
+ <g id="scarab" fill="#3B80AE">
+ <g transform="translate(-150, -170)">
+ <path id="scarab_head" d="M205.599,94.567c0-11.668-24.914-21.129-55.628-21.129
+ c-30.723,0-55.624,9.46-55.624,21.129c0,10.203,24.901,7.346,55.624,7.346C180.685,101.913,205.599,104.233,205.599,94.567z"/>
+ <path id="scarab_torso" d="M136.423,161.506c0,0,12.751,12.577,13.547,13.362
+ c2.262-2.232,13.545-13.362,13.545-13.362c7.135-7.036,87.111-6.399,91.066-6.363c-0.469-6.298-1.254-12.472-2.325-18.519
+ c-15.183-19.279-42.811-32.225-74.485-32.225h-55.518c-31.745,0-59.439,13.011-74.598,32.37c-1.054,6-1.829,12.128-2.296,18.374
+ C49.321,155.106,129.288,154.47,136.423,161.506z"/>
+ <path id="scarab_spine" d="M149.97,301.187c2.005-24.729,8.386-103.483,8.405-103.721
+ c-0.09-0.219-6.478-15.578-8.405-20.214c-1.936,4.655-8.316,19.995-8.408,20.214C141.582,197.704,147.965,276.458,149.97,301.187z"/>
+ <path id="scarab_wing_left" d="M140.403,197.149l8.862-21.31l-13.686-13.499
+ c-5.65-5.573-67.074-6.235-90.259-6.019l-0.006-0.622c-0.154,2.144-0.271,4.302-0.35,6.475
+ c-0.076,2.207,10.392,4.706,10.392,6.717c0,2.319-10.457,5.084-10.359,7.631c2.993,73.349,48.53,131.631,104.372,132.048
+ l-9.02-111.29L140.403,197.149z"/>
+ <path id="scarab_wing_right" d="M244.585,168.891c0-2.011,10.467-4.506,10.391-6.715
+ c-0.079-2.174-0.195-4.332-0.351-6.479l-0.004,0.624c-23.186-0.216-84.608,0.445-90.26,6.017l-13.688,13.502l8.915,21.438
+ l-9.017,111.29c55.854-0.417,101.378-58.698,104.373-132.049C255.04,173.976,244.585,171.209,244.585,168.891z"/>
+ <path id="scarab_leg_front_left" d="M44.506,141.12c-4.135-0.856-4.895-1.54-7.935-2.92
+ c-9.59-3.364-10.376-5.481-16.08-11.86c-7.426-8.306-12.661-20.142-17.1-29.463c-3.576-7.525-3.984-16.409-2.86-24.273
+ c0.991-6.935,7.144-12.869,12.074-18.92c5.844-7.191,10.356-14.822,17.924-21.354c7.736-6.682,23.203-9.809,26.168-19.648
+ C57.86,8.819,54.334,1.766,61.482,0c-0.366,4.703,3.639,8.477,2.397,13.575c-1.129,4.627-4.368,5.811-9.611,9.099
+ c-7.564,4.746-18.366,8.779-24.748,13.965c-7.175,5.827-4.369,13.771-10.569,20.057c-2.001,2.03-7.901,4.706-9.137,6.83
+ c-1.861,3.199-0.297,9.572-0.116,13.12c0.425,8.284,5.588,14.244,9.555,22.045c4.152,8.141,6.429,15.409,13.411,22.519
+ c4.183,4.262,11.429,4.802,16.21,10.647l-3.555,4.186L44.506,141.12z"/>
+ <path id="scarab_leg_middle_left" d="M43.94,191.922l-0.809-7.346
+ c-9.506-4.579-10.339-9.772-20.738-12.466c-23.728-6.151-21.361,11.25-15.532,26.373c5.676,14.726,8.237,30.23,14.345,44.795
+ c2.805,6.688,6.919,13.213,14.298,15.127c0.372-8.435-0.917-10.651-6.113-16.919c-4.395-5.293-3.326-12.548-6.072-18.504
+ c-3.581-7.804-4.196-15.646-7.279-23.502c-1.363-3.479-8.33-13.966-6.452-17.861c3.183-6.603,9.178-0.083,12.179,2.077
+ c4.218,3.036,6.467,2.223,11.681,2.898C34.041,186.673,37.005,188.756,43.94,191.922z"/>
+ <path id="scarab_leg_back_left" d="M65.839,257.063l-2.771-4.837
+ c-6.68,8.928-6.993,16.228-10.056,23.347c-5.277,12.263-0.157,28.851,9.854,37.676c6.052,5.375,15.907,9.618,23.122,13.136
+ c10.035,4.892,20.113,11.286,31.336,13.396c2.482,0.466,8.798,1.295,6.693-3.522c-0.975-2.237-8.091-4.591-10.146-5.734
+ c-8.312-4.623-16.377-10.524-24.142-16.176c-9.498-6.862-20.843-11.186-28.311-20.684c-3.054-3.885-3.544-4.922-2.816-9.39
+ c0.693-4.263,1.344-9.174,2.241-13.439C61.855,266.029,63.274,261.378,65.839,257.063z"/>
+ <path id="scarab_leg_front_right" d="M255.487,141.12c4.134-0.856,4.896-1.54,7.936-2.92
+ c9.583-3.364,10.369-5.481,16.071-11.86c7.428-8.306,12.661-20.142,17.115-29.463c3.574-7.525,3.983-16.409,2.86-24.273
+ c-0.992-6.935-7.157-12.869-12.087-18.92c-5.843-7.191-10.356-14.822-17.919-21.354c-7.735-6.682-23.202-9.809-26.167-19.648
+ C242.135,8.819,245.66,1.766,238.511,0c0.366,4.703-3.637,8.477-2.396,13.575c1.131,4.627,4.368,5.811,9.611,9.099
+ c7.563,4.746,18.367,8.779,24.747,13.965c7.17,5.827,4.362,13.771,10.563,20.057c2.001,2.03,7.901,4.706,9.139,6.83
+ c1.859,3.199,0.295,9.572,0.113,13.12c-0.424,8.284-5.588,14.244-9.553,22.045c-4.152,8.141-6.431,15.409-13.404,22.519
+ c-4.184,4.262-11.429,4.802-16.211,10.647l3.556,4.186L255.487,141.12z"/>
+ <path id="scarab_leg_middle_right" d="M256.053,191.922l0.81-7.346
+ c9.507-4.579,10.34-9.772,20.73-12.466c23.741-6.151,21.374,11.25,15.534,26.373c-5.676,14.726-8.238,30.23-14.347,44.795
+ c-2.804,6.688-6.911,13.213-14.291,15.127c-0.371-8.435,0.918-10.651,6.113-16.919c4.39-5.293,3.319-12.548,6.066-18.504
+ c3.58-7.804,4.197-15.646,7.278-23.502c1.363-3.479,8.33-13.966,6.453-17.861c-3.184-6.603-9.179-0.083-12.181,2.077
+ c-4.217,3.036-6.458,2.223-11.672,2.898C265.951,186.673,262.986,188.756,256.053,191.922z"/>
+ <path id="scarab_leg_back_right" d="M234.155,257.063l2.771-4.837
+ c6.679,8.928,6.991,16.228,10.057,23.347c5.274,12.263,0.154,28.851-9.854,37.676c-6.055,5.375-15.903,9.618-23.117,13.136
+ c-10.034,4.892-20.127,11.286-31.351,13.396c-2.481,0.466-8.789,1.295-6.691-3.522c0.976-2.237,8.092-4.591,10.146-5.734
+ c8.312-4.623,16.392-10.524,24.155-16.176c9.498-6.862,20.838-11.186,28.305-20.684c3.055-3.885,3.543-4.922,2.818-9.39
+ c-0.696-4.263-1.346-9.174-2.244-13.439C238.137,266.029,236.718,261.378,234.155,257.063z"/>
+ </g>
+ </g>
+ <radialGradient id="gradient_radial_dung"
+ cx="0" cy="0" r="60"
+ fx="0" fy="0" gradientUnits="userSpaceOnUse"
+ >
+ <stop offset="0" stop-color="#9a9a9a" />
+ <stop offset="0.70" stop-color="#bababa" />
+ <stop offset="0.95" stop-color="#FFFFFF" />
+ </radialGradient>
+ <g id="dung">
+ <circle cx="0" cy="0" r="60" fill="url(#gradient_radial_dung)" />
+ <g transform="translate(-61, -61)">
+ <!-- rough equivalent: <circle cx="0" cy="0" r="60" stroke="#8a8a8a" stroke-width="2" /> -->
+ <path fill="#8a8a8a" d="M0,61c0,33.636,27.364,61,61,61s61-27.364,61-61S94.636,0,61,0S0,27.364,0,61z
+ M2,61C2,28.467,28.467,2,61,2c32.532,0,59,26.467,59,59c0,32.533-26.468,59-59,59C28.467,120,2,93.533,2,61z"/>
+ </g>
+ <use xlink:href="#hacker_emblem" x="0" y="0" transform="scale(9)" />
+ </g>
+
+ <!-- scarab dimensions: 300x340 -->
+ <!-- dung dimensions: 120x120 (radius: 60) -->
+ <!-- scarab and dung dimensions: 300x400 -->
+
+ <g id="cairo_logo">
+ <!-- dimensions: 300x400, centered -->
+ <!-- The logo (scarab and dung), with the center-point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, -140)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, 30)" />
+ </g>
+ <g id="cairo_logo_dung-centered">
+ <!-- The logo (scarab and dung), with the dung at (0,0), the scarab below -->
+ <use xlink:href="#dung" x="0" y="0" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0,170)" />
+ </g>
+ <g id="cairo_logo_scarab-centered">
+ <!-- The logo (scarab and dung), with the scarab's rotational center at (0,0), the dung above -->
+ <!-- The scarab's rotational center in this case is not the center of its bounding box,
+ but is calculated to be the intersection-point of the torso, spine and wings -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, -175.85)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, -5.85)" />
+ </g>
+ <g id="cairo_logo_top-centered">
+ <!-- The logo (scarab and dung), with the top-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, 60)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, 230)" /><!-- (0,170+60) -->
+ </g>
+ <g id="cairo_logo_bottom-centered">
+ <!-- The logo (scarab and dung), with the bottom-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, -340)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, -170)" />
+ </g>
+ <g id="cairo_logo_right-centered">
+ <!-- The logo (scarab and dung), with the right-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(-150, -140)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(-150, 30)" />
+ </g>
+ <g id="cairo_logo_left-centered">
+ <!-- The logo (scarab and dung), with the left-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(150, -140)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(150, 30)" />
+ </g>
+ <g id="cairo_logo_topleft-centered">
+ <!-- The logo (scarab and dung), with the top-left point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(150, 60)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(150, 230)" /><!-- (150, 170+60) -->
+ </g>
+ <g id="cairo_logo_topright-centered">
+ <!-- The logo (scarab and dung), with the top-right point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(-150, 60)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(-150, 230)" /><!-- (-150,170+60) -->
+ </g>
+ <g id="cairo_logo_bottomleft-centered">
+ <!-- The logo (scarab and dung), with the bottom-left point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(150, -340)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(150, -170)" />
+ </g>
+ <g id="cairo_logo_bottomright-centered">
+ <!-- The logo (scarab and dung), with the bottom-right point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(-150, -340)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(-150, -170)" />
+ </g>
+
+ <g id="cairo_text" transform="translate(0,-97)">
+ <g transform="scale(0.1484,0.1484)"> <g transform="translate(-1139,-208.5)">
+ <!-- 63 (c), advance 444, 0 horiBearing 38,522 -->
+ <path transform="translate(65,0)" d="
+ M 412, 433
+ C 385, 422 336, 413 298, 413
+ C 142, 413 38, 525 38, 680
+ C 38, 826 144, 947 298, 947
+ C 332, 947 377, 944 416, 926
+ L 409, 842
+ C 380, 861 340, 871 308, 871
+ C 187, 871 138, 771 138, 680
+ C 138, 583 197, 489 302, 489
+ C 332, 489 368, 496 404, 511
+ L 412, 433 " />
+ <!-- 61 (a), advance 556, 0 horiBearing 46,522 -->
+ <path transform="translate(486.75,0)" d="
+ M 109, 541
+ C 147, 509 204, 489 257, 489
+ C 351, 489 383, 534 383, 622
+ C 346, 620 320, 620 283, 620
+ C 186, 620 46, 660 46, 788
+ C 46, 899 123, 947 233, 947
+ C 319, 947 369, 900 391, 869
+ L 393, 869
+ L 393, 935
+ L 481, 935
+ C 479, 920 477, 893 477, 835
+ L 477, 624
+ C 477, 485 418, 413 272, 413
+ C 207, 413 151, 433 104, 461
+ L 109, 541
+ M 383, 737
+ C 383, 813 334, 871 241, 871
+ C 198, 871 146, 842 146, 788
+ C 146, 698 272, 690 323, 690
+ C 343, 690 363, 692 383, 692
+ L 383, 737 " />
+ <!-- 69 (i), advance 278, 0 horiBearing 86,730 -->
+ <path transform="translate(1000,0)" d="
+ M 92, 935
+ L 186, 935
+ L 186, 425
+ L 92, 425
+ L 92, 935
+ M 88, 261
+ A 51, 51 0 1 1 190,261
+ A 51, 51 0 1 1 88,261" />
+ <!-- 72 (r), advance 389, 0 horiBearing 80,522 -->
+ <path transform="translate(1234.25,0)" d="
+ M 80, 935
+ L 174, 935
+ L 174, 703
+ C 174, 575 229, 495 313, 495
+ C 329, 495 348, 497 365, 504
+ L 365, 420
+ C 345, 416 331, 413 303, 413
+ C 249, 413 195, 451 170, 504
+ L 168, 504
+ L 168, 425
+ L 80, 425
+ L 80, 935 " />
+ <!-- 6f (o), advance 611, 0 horiBearing 46,522 -->
+ <path transform="translate(1610,0)" d="
+ M 46, 680
+ C 46, 826 152, 947 306, 947
+ C 459, 947 565, 826 565, 680
+ C 565, 525 461, 413 306, 413
+ C 150, 413 46, 525 46, 680
+ M 146, 680
+ C 146, 583 205, 489 306, 489
+ C 406, 489 465, 583 465, 680
+ C 465, 771 416, 871 306, 871
+ C 195, 871 146, 771 146, 680 " />
+ <!-- bounds: 38, 205 <-> 2232, 947 -->
+ </g> </g>
+ </g>
+
+ <!-- scaled by 0.72, shifted around to hit pixel boundaries -->
+ <g id="cairo_text_small_spaced" transform="translate(0,-71)">
+ <g transform="scale(0.085,0.085)"> <g transform="translate(-1139,-208.5)">
+ <!-- 63 (c), advance 444, 0 horiBearing 38,522 -->
+ <path transform="translate(-151,0)" d="
+ M 412, 433
+ C 385, 422 336, 413 298, 413
+ C 142, 413 38, 525 38, 680
+ C 38, 826 144, 947 298, 947
+ C 332, 947 377, 944 416, 926
+ L 409, 842
+ C 380, 861 340, 871 308, 871
+ C 187, 871 138, 771 138, 680
+ C 138, 583 197, 489 302, 489
+ C 332, 489 368, 496 404, 511
+ L 412, 433 " />
+ <!-- 61 (a), advance 556, 0 horiBearing 46,522 -->
+ <path transform="translate(379.5,0)" d="
+ M 109, 541
+ C 147, 509 204, 489 257, 489
+ C 351, 489 383, 534 383, 622
+ C 346, 620 320, 620 283, 620
+ C 186, 620 46, 660 46, 788
+ C 46, 899 123, 947 233, 947
+ C 319, 947 369, 900 391, 869
+ L 393, 869
+ L 393, 935
+ L 481, 935
+ C 479, 920 477, 893 477, 835
+ L 477, 624
+ C 477, 485 418, 413 272, 413
+ C 207, 413 151, 433 104, 461
+ L 109, 541
+ M 383, 737
+ C 383, 813 334, 871 241, 871
+ C 198, 871 146, 842 146, 788
+ C 146, 698 272, 690 323, 690
+ C 343, 690 363, 692 383, 692
+ L 383, 737 " />
+ <!-- 69 (i), advance 278, 0 horiBearing 86,730 -->
+ <path transform="translate(1000,0)" d="
+ M 92, 935
+ L 186, 935
+ L 186, 425
+ L 92, 425
+ L 92, 935
+ M 88, 261
+ A 51, 51 0 1 1 190,261
+ A 51, 51 0 1 1 88,261" />
+ <!-- 72 (r), advance 389, 0 horiBearing 80,522 -->
+ <path transform="translate(1341.5,0)" d="
+ M 80, 935
+ L 174, 935
+ L 174, 703
+ C 174, 575 229, 495 313, 495
+ C 329, 495 348, 497 365, 504
+ L 365, 420
+ C 345, 416 331, 413 303, 413
+ C 249, 413 195, 451 170, 504
+ L 168, 504
+ L 168, 425
+ L 80, 425
+ L 80, 935 " />
+ <!-- 6f (o), advance 611, 0 horiBearing 46,522 -->
+ <path transform="translate(1826,0)" d="
+ M 46, 680
+ C 46, 826 152, 947 306, 947
+ C 459, 947 565, 826 565, 680
+ C 565, 525 461, 413 306, 413
+ C 150, 413 46, 525 46, 680
+ M 146, 680
+ C 146, 583 205, 489 306, 489
+ C 406, 489 465, 583 465, 680
+ C 465, 771 416, 871 306, 871
+ C 195, 871 146, 771 146, 680 " />
+ <!-- bounds: 38, 205 <-> 2232, 947 -->
+ </g> </g>
+ </g>
+
+
+ <!-- scaled by 0.72, shifted around to hit pixel boundaries -->
+ <g id="cairo_text_small" transform="translate(0,-71)">
+ <g transform="scale(0.085,0.085)"> <g transform="translate(-1139,-208.5)">
+ <!-- 63 (c), advance 444, 0 horiBearing 38,522 -->
+ <path transform="translate(-151,0)" d="
+ M 412, 433
+ C 385, 422 336, 413 298, 413
+ C 142, 413 38, 525 38, 680
+ C 38, 826 144, 947 298, 947
+ C 332, 947 377, 944 416, 926
+ L 409, 842
+ C 380, 861 340, 871 308, 871
+ C 187, 871 138, 771 138, 680
+ C 138, 583 197, 489 302, 489
+ C 332, 489 368, 496 404, 511
+ L 412, 433 " />
+ <!-- 61 (a), advance 556, 0 horiBearing 46,522 -->
+ <path transform="translate(261.75,0)" d="
+ M 109, 541
+ C 147, 509 204, 489 257, 489
+ C 351, 489 383, 534 383, 622
+ C 346, 620 320, 620 283, 620
+ C 186, 620 46, 660 46, 788
+ C 46, 899 123, 947 233, 947
+ C 319, 947 369, 900 391, 869
+ L 393, 869
+ L 393, 935
+ L 481, 935
+ C 479, 920 477, 893 477, 835
+ L 477, 624
+ C 477, 485 418, 413 272, 413
+ C 207, 413 151, 433 104, 461
+ L 109, 541
+ M 383, 737
+ C 383, 813 334, 871 241, 871
+ C 198, 871 146, 842 146, 788
+ C 146, 698 272, 690 323, 690
+ C 343, 690 363, 692 383, 692
+ L 383, 737 " />
+ <!-- 69 (i), advance 278, 0 horiBearing 86,730 -->
+ <path transform="translate(764.75)" d="
+ M 92, 935
+ L 186, 935
+ L 186, 425
+ L 92, 425
+ L 92, 935
+ M 88, 261
+ A 51, 51 0 1 1 190,261
+ A 51, 51 0 1 1 88,261" />
+ <!-- 72 (r), advance 389, 0 horiBearing 80,522 -->
+ <path transform="translate(988.5,0)" d="
+ M 80, 935
+ L 174, 935
+ L 174, 703
+ C 174, 575 229, 495 313, 495
+ C 329, 495 348, 497 365, 504
+ L 365, 420
+ C 345, 416 331, 413 303, 413
+ C 249, 413 195, 451 170, 504
+ L 168, 504
+ L 168, 425
+ L 80, 425
+ L 80, 935 " />
+ <!-- 6f (o), advance 611, 0 horiBearing 46,522 -->
+ <path transform="translate(1355.5,0)" d="
+ M 46, 680
+ C 46, 826 152, 947 306, 947
+ C 459, 947 565, 826 565, 680
+ C 565, 525 461, 413 306, 413
+ C 150, 413 46, 525 46, 680
+ M 146, 680
+ C 146, 583 205, 489 306, 489
+ C 406, 489 465, 583 465, 680
+ C 465, 771 416, 871 306, 871
+ C 195, 871 146, 771 146, 680 " />
+ <!-- bounds: 38, 205 <-> 2232, 947 -->
+ </g> </g>
+ </g>
+
+ <g id="cairo_logo_text_small">
+ <!-- The logo on the left, the text 'cairo' on the right -->
+ <use xlink:href="#cairo_logo_bottomleft-centered" transform="translate(0, 78), scale(0.1944)" />
+ <use xlink:href="#cairo_text_small" transform="translate(175,82)"/>
+ </g>
+
+ <g id="cairo_logo_with_text">
+ <!-- The logo (scarab and dung), with the text 'cairo' below, the dot of the 'i' positioned between the hind legs of the scarab -->
+ <!-- dimensions: 300x490, centered -->
+ <use xlink:href="#cairo_logo_top-centered" transform="translate(0, -245)" />
+ <use xlink:href="#cairo_text" transform="translate(0, 245)" />
+ </g>
+
+ <g id="cairo_banner">
+ <!-- The logo on the left, the text 'cairo' in the center, and a mirror image of the logo on the right -->
+ <!-- The logos are scaled such that the scarab body nearly matches the height of the text characters (excepting the 'i')
+ and the dung should nearly aligns with the dot of the 'i'. The bottoms of the logos are aligned with the bottom of the text. -->
+ <!-- dimensions: 370x88, centered -->
+ <use xlink:href="#cairo_logo_bottomleft-centered" transform="translate(-180, 40), scale(0.1944)" />
+ <use xlink:href="#cairo_text_small" transform="translate(0, 42)" fill="black" />
+ <use xlink:href="#cairo_logo_bottomleft-centered" transform="translate(180, 40), scale(0.1944), scale(-1, 1)" />
+ </g>
+
+ <g id="freedesktop_org_logo" style="fill:#FFFFFF;stroke:#3B80AE;stroke-width:2.4588;">
+ <g>
+ <path style="stroke:#BABABA;" d="M85.277,40.796c2.058,7.884-2.667,15.942-10.551,17.999L27.143,71.21c-7.884,2.057-15.943-2.667-18-10.552
+ l-7.448-28.55c-2.057-7.884,2.667-15.942,10.551-17.999L59.83,1.695c7.884-2.057,15.942,2.667,17.999,10.551
+ l7.449,28.55z"/>>
+ <path style="fill:#3B80AE;stroke:none;" d="M80.444,39.778c1.749,7.854-1.816,13.621-9.504,15.447l-42.236,11.02c-7.569,2.396-14.089-1.181
+ -15.838-8.836L6.53,33.127c-1.749-8.145,0.709-12.889,9.503-15.447L58.27,6.661
+ c8.144-1.826,14.089,1.363,15.838,8.835l6.336,24.282z"/>>
+ </g>g>
+ <path style="opacity:0.5;fill:none;stroke:#FFFFFF;" d="M45.542,51.793L24.104,31.102l38.1-4.393L45.542,51.793z"/>>
+ <path d="M72.325,28.769c0.405,1.55-0.525,3.136-2.075,3.541l-12.331,3.217c-1.551,0.404-3.137-0.525-3.542-2.076l-2.295-8.801
+ c-0.405-1.551,0.524-3.137,2.076-3.542l12.33-3.217c1.551-0.405,3.137,0.525,3.542,2.076l2.295,8.801z"/>>
+ <path d="M36.51,33.625c0.496,1.9-0.645,3.844-2.545,4.34l-15.112,3.943c-1.901,0.496-3.845-0.644-4.34-2.544l-2.814-10.786
+ c-0.496-1.901,0.644-3.844,2.544-4.34l15.113-3.942c1.901-0.496,3.845,0.643,4.34,2.544l2.814,10.786z"/>>
+ <path d="M52.493,53.208c0.278,1.065-0.36,2.154-1.425,2.432L42.6,57.848c-1.064,0.277-2.153-0.36-2.431-1.426l-1.577-6.043
+ c-0.277-1.064,0.36-2.153,1.425-2.432l8.468-2.209c1.064-0.277,2.154,0.361,2.431,1.426l1.577,6.043z"/>>
+ </g>g>
+ <g id="bullet">
+ <use x="0" y="0" xlink:href="#cairo_logo" transform="translate(-6,-2) scale(0.1, 0.1)"/>>
+ </g>
+ </defs>
+
+ <g id="watermark" transform="translate(200, 185), rotate(-50), scale(2.5)">
+ <use xlink:href="#scarab" x="0" y="170" fill-opacity="0.08"/>
+ </g>
+
+ <!-- Blue bar at top of slide -->
+ <rect x="0" y="0" width="1024" height="50" fill="#3B80AE" fill-opacity="0.3" />
+
+ <!-- Scarab and "cairo" at upper-left -->
+ <g transform="translate(10,0)">
+ <use xlink:href="#cairo_logo_text_small"/>
+ </g>
+
+ <!-- Presentation title at upper-left -->
+ <text ss:variable="presentation-subtitle" x="260" y="50" font-size="20">Presentation Sub-title</text>
+
+ <!-- freedesktop.org logo at upper-right -->
+ <use xlink:href="#freedesktop_org_logo" transform="translate(910, 12)" />
+
+ <g font-family="Frutiger">
+ <!-- Slide title -->
+ <g id="slide_title" transform="translate(512, 153)">
+ <rect stroke="#bababa" fill="none"
+ x="-365.5"
+ y="-55.5"
+ width="731"
+ height="81"
+ rx="10" ry="10"
+ />
+ <rect fill="#bababa" fill-opacity="0.3"
+ x="-360"
+ y="-50"
+ width="720"
+ height="70"
+ rx="10" ry="10"
+ />
+ <text text-anchor="middle"
+ fill="black"
+ x="0"
+ y="4" font-size="55"
+ ss:variable="title">Slide Title</text>
+ </g>
+
+ <!-- Slide content -->
+ <g ss:region="default">
+ <rect x="112" y="200" width="800" height="480" fill="none" stroke="blue"/>
+ <text font-size="40" fill="black"
+ x="112" y="232">Slide content</text>
+ </g>
+
+ <!-- Footer -->
+ <text ss:variable="URL" x="1016" y="760" text-anchor="end" font-size="20">http://cairographics.org</text>
+ </g>
+
+</svg>
diff --git a/doc/tutorial/slides/circle-cairo-large.png b/doc/tutorial/slides/circle-cairo-large.png
new file mode 100644
index 000000000..a08e1193a
--- /dev/null
+++ b/doc/tutorial/slides/circle-cairo-large.png
Binary files differ
diff --git a/doc/tutorial/slides/circle-cairo.png b/doc/tutorial/slides/circle-cairo.png
new file mode 100644
index 000000000..f5d8cd438
--- /dev/null
+++ b/doc/tutorial/slides/circle-cairo.png
Binary files differ
diff --git a/doc/tutorial/slides/circle-ooo-large.png b/doc/tutorial/slides/circle-ooo-large.png
new file mode 100644
index 000000000..dfa40997f
--- /dev/null
+++ b/doc/tutorial/slides/circle-ooo-large.png
Binary files differ
diff --git a/doc/tutorial/slides/circle-ooo.png b/doc/tutorial/slides/circle-ooo.png
new file mode 100644
index 000000000..eb90666e6
--- /dev/null
+++ b/doc/tutorial/slides/circle-ooo.png
Binary files differ
diff --git a/doc/tutorial/slides/expander-fuzzy-large.png b/doc/tutorial/slides/expander-fuzzy-large.png
new file mode 100644
index 000000000..3a485da6a
--- /dev/null
+++ b/doc/tutorial/slides/expander-fuzzy-large.png
Binary files differ
diff --git a/doc/tutorial/slides/expander-fuzzy.png b/doc/tutorial/slides/expander-fuzzy.png
new file mode 100644
index 000000000..b01fd636e
--- /dev/null
+++ b/doc/tutorial/slides/expander-fuzzy.png
Binary files differ
diff --git a/doc/tutorial/slides/expander-sharp-large.png b/doc/tutorial/slides/expander-sharp-large.png
new file mode 100644
index 000000000..f97fa06a4
--- /dev/null
+++ b/doc/tutorial/slides/expander-sharp-large.png
Binary files differ
diff --git a/doc/tutorial/slides/expander-sharp.png b/doc/tutorial/slides/expander-sharp.png
new file mode 100644
index 000000000..40759aef7
--- /dev/null
+++ b/doc/tutorial/slides/expander-sharp.png
Binary files differ
diff --git a/doc/tutorial/slides/fuzzies.svg b/doc/tutorial/slides/fuzzies.svg
new file mode 100644
index 000000000..df12b8a71
--- /dev/null
+++ b/doc/tutorial/slides/fuzzies.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ width="800" height="500">
+
+ <image xlink:href="expander-fuzzy.png" x="175" y="25" width="50" height="50"/>
+ <image xlink:href="expander-sharp.png" x="575" y="25" width="50" height="50"/>
+
+ <image xlink:href="expander-fuzzy-large.png" x="0" y="100" width="400" height="400"/>
+ <image xlink:href="expander-sharp-large.png" x="400" y="100" width="400" height="400"/>
+</svg>
diff --git a/doc/tutorial/slides/jaggies.svg b/doc/tutorial/slides/jaggies.svg
new file mode 100644
index 000000000..e99d07ba5
--- /dev/null
+++ b/doc/tutorial/slides/jaggies.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ width="800" height="500">
+
+ <image xlink:href="circle-ooo.png" x="175" y="25" width="50" height="50"/>
+ <image xlink:href="circle-cairo.png" x="575" y="25" width="50" height="50"/>
+
+ <image xlink:href="circle-ooo-large.png" x="0" y="100" width="400" height="400"/>
+ <image xlink:href="circle-cairo-large.png" x="400" y="100" width="400" height="400"/>
+</svg>
diff --git a/doc/tutorial/slides/tutorial.xml b/doc/tutorial/slides/tutorial.xml
new file mode 100644
index 000000000..4b5248e0d
--- /dev/null
+++ b/doc/tutorial/slides/tutorial.xml
@@ -0,0 +1,468 @@
+<?xml version="1.0" ?>
+<svgslides
+ xmlns="http://www.svgslides.org/svgslides0.1"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ >
+
+ <slides theme="cairo"
+ presentation="How to Recognize Ugly Graphics"
+ presentation-subtitle="How to recognize ugly graphics—and what you can do about it."
+ URL="http://cairographics.org"
+ bullet="bullet">
+
+ <slide title="Tutorial Preparation" variant="blank" bullet="">
+ <lc></lc>
+ <lc align="center">http://cairographics.org/tutorial</lc>
+ <lc></lc>
+ <li>tar xzf tutorial.tar.gz</li>
+ <li>cd tutorial</li>
+ <li>make</li>
+ <lc></lc>
+ <lc align="center">IRC help: freenode.net #cairo</lc>
+ </slide>
+
+ <slide variant="title">
+ <lc>Carl Worth</lc>
+ <lc>Red Hat, Inc.</lc>
+ <lc></lc>
+ <lc>Ottawa Linux Symposium</lc>
+ <lc>2005-07-22</lc>
+ <lc>http://cairographics.org</lc>
+ </slide>
+
+ <slide title="Ugly Graphics" variant="separator">
+ <lc align="left">Jaggies</lc>
+ <lc align="center">Fuzzies</lc>
+ <lc align="right">Fireworks</lc>
+ </slide>
+
+ <slide title="Jaggies">
+ <img src="jaggies.svg"/>
+ </slide>
+
+ <slide title="Fuzzies">
+ <img src="fuzzies.svg"/>
+ </slide>
+
+ <slide title="Fireworks">
+ </slide>
+
+ <slide title="Getting Started" variant="separator">
+ <lc align="center">Various shell cairo program</lc>
+ </slide>
+
+ <slide title="Minimal cairo-xlib program" variant="code">
+ <lc>#include &lt;cairo.h&gt;</lc>
+ <lc>#include &lt;cairo-xlib.h&gt;</lc>
+ <lc>int main (void) {</lc>
+ <lc> Display *dpy = XOpenDisplay (0);</lc>
+ <lc> Window w = XCreateSimpleWindow (dpy,RootWindow (dpy, 0),</lc>
+ <lc> 0, 0, WIDTH, HEIGHT, 0, 0, WhitePixel (dpy, 0));</lc>
+ <lc> cairo_surface_t *surface = cairo_xlib_surface_create (dpy, w,</lc>
+ <lc> DefaultVisual (dpy, DefaultScreen (dpy)),</lc>
+ <lc> WIDTH, HEIGHT);</lc>
+ <lc> XEvent ev;</lc>
+ <lc> XSelectInput (dpy, w, ExposureMask);</lc>
+ <lc> XMapWindow (dpy, w);</lc>
+ <lc> while (XNextEvent (dpy, &amp;ev) == 0)</lc>
+ <lc> if (ev.type == Expose &amp;&amp; !ev.xexpose.count) {</lc>
+ <lc> cairo_t *cr = cairo_create (surface);</lc>
+ <lc> draw (cr);</lc>
+ <lc> cairo_destroy (cr);</lc>
+ <lc> }</lc>
+ <lc>}</lc>
+ </slide>
+
+ <slide title="Minimal cairo-gtk program" variant="code">
+ <lc>#include &lt;gtk/gtk.h&gt;</lc>
+ <lc>static gboolean</lc>
+ <lc>handle_expose (GtkWidget *widget, GdkEventExpose *event, gpointer data) {</lc>
+ <lc> cairo_t *cr = gdk_cairo_create (widget->window);</lc>
+ <lc> draw (cr);</lc>
+ <lc> cairo_destroy (cr);</lc>
+ <lc> return FALSE;</lc>
+ <lc>}</lc>
+ <lc>int main (int argc, char **argv) {</lc>
+ <lc> GtkWidget *window, *drawing_area;</lc>
+ <lc> gtk_init (&amp;argc, &amp;argv);</lc>
+ <lc> window = gtk_window_new (GTK_WINDOW_TOPLEVEL);</lc>
+ <lc> gtk_window_set_default_size (GTK_WINDOW (window), WIDTH, HEIGHT);</lc>
+ <lc> drawing_area = gtk_drawing_area_new ();</lc>
+ <lc> gtk_container_add (GTK_CONTAINER (window), drawing_area);</lc>
+ <lc> g_signal_connect (drawing_area, "expose-event",</lc>
+ <lc> G_CALLBACK (handle_expose), NULL);</lc>
+ <lc> gtk_widget_show_all (window);</lc>
+ <lc> gtk_main ();</lc>
+ <lc>}</lc>
+ </slide>
+
+ <slide title="Minimal cairo-png program" variant="code">
+ <lc>#include &lt;cairo.h&gt;</lc>
+ <lc></lc>
+ <lc>int main (void)</lc>
+ <lc>{</lc>
+ <lc> cairo_surface_t *surface;</lc>
+ <lc> cairo_t *cr;</lc>
+ <lc></lc>
+ <lc> surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,</lc>
+ <lc> WIDTH, HEIGHT);</lc>
+ <lc> </lc>
+ <lc> cr = cairo_create (surface);</lc>
+ <lc> draw (cr);</lc>
+ <lc> cairo_surface_write_to_png (surface, "foo.png");</lc>
+ <lc></lc>
+ <lc> cairo_surface_destroy (surface);</lc>
+ <lc> cairo_destroy (cr);</lc>
+ <lc></lc>
+ <lc> return 0;</lc>
+ <lc>}</lc>
+ </slide>
+
+ <slide title="Minimal cairo-pdf program" variant="code">
+ <lc>#include &lt;cairo.h&gt;</lc>
+ <lc>#include &lt;cairo-pdf.h&gt;</lc>
+ <lc></lc>
+ <lc>int main (void)</lc>
+ <lc>{</lc>
+ <lc> cairo_surface_t *surface;</lc>
+ <lc> cairo_t *cr;</lc>
+ <lc></lc>
+ <lc> surface = cairo_pdf_surface_create (foo.pdf, WIDTH, HEIGHT);</lc>
+ <lc> </lc>
+ <lc> cr = cairo_create (surface);</lc>
+ <lc> draw (cr);</lc>
+ <lc> cairo_show_page (cr);</lc>
+ <lc></lc>
+ <lc> cairo_surface_destroy (surface);</lc>
+ <lc> cairo_destroy (cr);</lc>
+ <lc></lc>
+ <lc> return 0;</lc>
+ <lc>}</lc>
+ </slide>
+
+ <slide title="Minimal pycairo-gtk shell" variant="code">
+ <lc>import gtk</lc>
+ <lc>import cairo</lc>
+ <lc>import cairo.gtk</lc>
+ <lc></lc>
+ <lc>def handle_expose (widget, event):</lc>
+ <lc> cr = cairo.gtk.gdk_cairo_create (widget.window)</lc>
+ <lc> draw (c)</lc>
+ <lc></lc>
+ <lc>win = gtk.Window ()</lc>
+ <lc>win.connect ('destroy', lambda x: gtk.main_quit ())</lc>
+ <lc>drawingarea = gtk.DrawingArea ()</lc>
+ <lc>win.add (drawingarea)</lc>
+ <lc>drawingarea.connect ('expose_event', handle_expose)</lc>
+ <lc>drawingarea.set_size_request (WIDTH, HEIGHT)</lc>
+ <lc>drawingarea.set_double_buffered (False)</lc>
+ <lc>win.show_all ()</lc>
+ <lc>gtk.main ()</lc>
+ </slide>
+
+ <slide title="Minimal pycairo-png shell" variant="code">
+ <lc>import cairo</lc>
+ <lc></lc>
+ <lc>surface = cairo.ImageSurface (cairo.FORMAT_ARGB32, WIDTH, HEIGHT)</lc>
+ <lc>cr = cairo.Context (surface)</lc>
+ <lc></lc>
+ <lc>draw (cr)</lc>
+ <lc></lc>
+ <lc>surface.write_to_png ('foo.png')</lc>
+ </slide>
+
+ <slide title="Minimal nickle program" variant="code">
+ <lc>autoimport Cairo;</lc>
+ <lc></lc>
+ <lc>cairo_t cr = new (WIDTH, HEIGHT);</lc>
+ <lc>draw (cr);</lc>
+ </slide>
+
+ <slide title="Drawing" variant="separator">
+ <lc align="center">Here comes the fun part</lc>
+ </slide>
+
+ <slide title="Cairo API">
+ <ul>
+ <li>Paths</li>
+ <ul>
+ <li>construction</li>
+ <li>filling, stroking</li>
+ </ul>
+ <li>Images</li>
+ <ul>
+ <li>loading from disk</li>
+ <li>transforming</li>
+ <li>using as pattern</li>
+ </ul>
+ <li>Text</li>
+ <ul>
+ <li>Simple API example</li>
+ </ul>
+ </ul>
+ </slide>
+
+ <slide title="Paths">
+ <ul>
+ <li>Built from lines and splines.</li>
+ <ul>
+ <li>cairo_move_to() set current point</li>
+ <li>cairo_line_to() draw line</li>
+ <li>cairo_curve_to() draw Bézier spline</li>
+ <li>cairo_close_path() draw line to start</li>
+ </ul>
+ <li>Can also be built from glyphs</li>
+ <ul>
+ <li>cairo_text_path() path from UTF-8</li>
+ <li>cairo_glyph_path() path from glyphs</li>
+ </ul>
+ <li>Part of graphics state</li>
+ <ul>
+ <li>cairo_save()/cairo_restore() affect path</li>
+ </ul>
+ </ul>
+ </slide>
+
+ <slide title="Using Paths">
+ <ul>
+ <li>Stroke or Fill</li>
+ <ul>
+ <li>cairo_stroke walks path outline with pen</li>
+ <li>cairo_fill paints interior of path</li>
+ <li>both operations consume the path, resetting the current path to empty</li>
+ </ul>
+ <li>Clip</li>
+ <ul>
+ <li>cairo_clip intersects interior of path with current clip</li>
+ </ul>
+ <li>Convert path to stroked version</li>
+ <ul>
+ <li>not yet named</li>
+ </ul>
+ </ul>
+ </slide>
+
+ <slide title="Path Example">
+ </slide>
+
+ <slide title="Stroking Paths">
+ <ul>
+ <li>Elliptical pen (line width radius)</li>
+ <li>Join styles</li>
+ <ul>
+ <li>CAIRO_LINE_JOIN_MITER with limit</li>
+ <LI>CAIRO_LINE_JOIN_BEVEL</LI>
+ <li>CAIRO_LINE_JOIN_ROUND uses pen</li>
+ </ul>
+ <li>Cap styles</li>
+ <ul>
+ <LI>CAIRO_LINE_CAP_BUTT</LI>
+ <LI>CAIRO_LINE_CAP_ROUND</LI>
+ <LI>CAIRO_LINE_CAP_SQUARE</LI>
+ </ul>
+ </ul>
+ </slide>
+
+ <slide title="Stroke Example">
+ </slide>
+
+ <slide title="Closing the Path">
+ <li>cairo_close_path</li>
+ <li>Draws a line (if necessary) to the start of the path</li>
+ <li>Draws a join from that line to the first element of the path</li>
+ </slide>
+
+ <slide title="Close Path Example">
+ </slide>
+
+ <slide title="Caps and Joins">
+ <ul>
+ <li>cairo_set_line_cap</li>
+ <ul>
+ <LI>CAIRO_LINE_CAP_BUTT</LI>
+ <LI>CAIRO_LINE_CAP_ROUND</LI>
+ <LI>CAIRO_LINE_CAP_SQUARE</LI>
+ </ul>
+ <li>cairo_set_line_join</li>
+ <ul>
+ <LI>CAIRO_LINE_JOIN_BEVEL</LI>
+ <LI>CAIRO_LINE_JOIN_ROUND</LI>
+ <LI>CAIRO_LINE_JOIN_MITER</LI>
+ </ul>
+ </ul>
+ </slide>
+
+ <slide title="Caps and Joins Setup">
+ </slide>
+
+ <slide title="Caps and Joins Example">
+ </slide>
+
+ <slide title="Filling Paths">
+ <ul>
+ <li>Closes path with line_to if necessary</li>
+ <ul>
+ <li>line drawn from current point to last move_to location</li>
+ </ul>
+ <li>Fills interior</li>
+ <li>Even/odd or winding fill rules</li>
+ </ul>
+ </slide>
+
+ <slide title="Fill Example">
+ </slide>
+
+ <slide title="Source color">
+ <li>cairo_set_source_rgb sets a solid color source</li>
+ <li>Source color is used for any drawing operation (stroke, fill, or</li>
+ <li>others)</li>
+ </slide>
+
+ <slide title="Fill and Stroke">
+ <li>cairo_stroke/fill_preserve preserve the path</li>
+ <li>Could just walk the figure twice</li>
+ </slide>
+
+ <slide title="Fill and Stroke Example">
+ </slide>
+
+ <slide title="Affine Transformations">
+ <ul>
+ <li>Single matrix combines rotation, translation, scale and shear</li>
+ <li>Non-projective transformations</li>
+ <ul>
+ <li>Pen doesn't change shape along the stroke</li>
+ </ul>
+ <li>Transformations are cumulative</li>
+ <ul>
+ <li>translate, scale != scale, translate</li>
+ </ul>
+ </ul>
+ </slide>
+
+ <slide title="Affine Transform Example">
+ </slide>
+
+ <slide title="Even/Odd vs Winding">
+ <li>Even/Odd counts edges, fills when odd</li>
+ <li>Winding counts up for clockwise edges, down for counterclockwise, fills when !zero</li>
+ </slide>
+
+ <slide title="Combining Images">
+ <li>Cairo memory surfaces are images</li>
+ <li>cairo_show_surface paints one surface into another</li>
+ <li>Transformed through matrix</li>
+ <li>No projective transforms yet</li>
+ </slide>
+
+ <slide title="Loading an Image File">
+ </slide>
+
+ <slide title="Image Example">
+ </slide>
+
+ <slide title="Image Transformation">
+ </slide>
+
+ <slide title="Resampling Modes">
+ <li>Nearest Neighbor</li>
+ </slide>
+
+ <slide title="Patterns">
+ <li>Apply one surface as pattern on another</li>
+ <li>Pattern transformed through source surface matrix</li>
+ <li>Patterns may repeat</li>
+ </slide>
+
+ <slide title="Pattern Example">
+ </slide>
+
+ <slide title="Pattern Transformations">
+ <ul>
+ <li>Source surface holds matrix</li>
+ <li>Constructed with matrix operations</li>
+ <li>Some thought to changing this API</li>
+ <ul>
+ <li>Need to add projective transformations</li>
+ <li>May want procedural patterns</li>
+ </ul>
+ </ul>
+ </slide>
+
+ <slide title="Pattern Transform">
+ </slide>
+
+ <slide title="Gradients">
+ <ul>
+ <li>No primitive gradients in cairo</li>
+ <ul>
+ <li>Implemented as patterns</li>
+ <li>Bilinear interpolation smooths result</li>
+ </ul>
+ <li>Future API may include more</li>
+ <ul>
+ <li>Procedural patterns</li>
+ <li>Triangular patches</li>
+ </ul>
+ </ul>
+ </slide>
+
+ <slide title="Gradient Setup">
+ </slide>
+
+ <slide title="Gradient Creation">
+ </slide>
+
+ <slide title="Gradient Example">
+ </slide>
+
+ <slide title="Text">
+ <ul>
+ <li>API is getting replaced</li>
+ <li>“Toy” API will be similar to current code</li>
+ <li>“Full” API will have</li>
+ <ul>
+ <li>OS dependent font selection</li>
+ <li>Use Glyph Ids instead of Unicode chars</li>
+ </ul>
+ <li>New implementation will provide device-independent fonts</li>
+ <li>Old API worked only on X</li>
+ </ul>
+ </slide>
+
+ <slide title="“Toy” Text API"/>
+ <ul>
+ <li>Simple font selection</li>
+ <ul>
+ <li>family, weight, slant</li>
+ <li>OS independent</li>
+ <li>No font listing support</li>
+ </ul>
+ <li>UTF-8 text drawing and extents functions</li>
+ <li>Still supports full font transformations</li>
+ </ul>
+
+ <slide title="“Toy” Text Example">
+ </slide>
+
+ <slide title="Error Handling in C">
+ <li>C has no exceptions</li>
+ <li>Checking each return is tedious</li>
+ <li>C programmers rarely bother</li>
+ <li>Lots of broken programs result</li>
+ </slide>
+
+ <slide title="Cairo Error Handling">
+ <li>Cairo returns status</li>
+ <li>Status is “persistant”</li>
+ <li>cairo_status function returns error state</li>
+ <li>API “shuts down” when an error occurs</li>
+ <li>All cairo functions are benign (and well defined) after any error.</li>
+ </slide>
+
+ <slide title="Cairo Error Example">
+ </slide>
+
+ </slides>
+</svgslides>
diff --git a/doc/tutorial/src/.cvsignore b/doc/tutorial/src/.cvsignore
new file mode 100644
index 000000000..59488b844
--- /dev/null
+++ b/doc/tutorial/src/.cvsignore
@@ -0,0 +1,7 @@
+*-gtk
+*-pdf
+*-png
+*-xlib
+*.pdf
+*.png
+
diff --git a/doc/tutorial/src/Makefile b/doc/tutorial/src/Makefile
new file mode 100644
index 000000000..1d80f2c34
--- /dev/null
+++ b/doc/tutorial/src/Makefile
@@ -0,0 +1,30 @@
+MYCFLAGS=$(shell pkg-config --cflags --libs cairo gtk+-2.0) -Wall -g -Wpointer-arith -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -fno-strict-aliasing
+
+# If you don't want to/can't compile all of these targets, then trim
+# this list.
+all: gtk xlib pdf png
+
+GTK_EXAMPLES=$(patsubst %.c,%-gtk,$(wildcard *.c))
+gtk: $(GTK_EXAMPLES)
+%-gtk:%.c cairo-tutorial-gtk.h
+ $(CC) -DCAIRO_TUTORIAL_GTK $(CFLAGS) $(MYCFLAGS) -o $@ $<
+
+XLIB_EXAMPLES=$(patsubst %.c,%-xlib,$(wildcard *.c))
+xlib: $(XLIB_EXAMPLES)
+%-xlib:%.c cairo-tutorial-xlib.h
+ $(CC) -DCAIRO_TUTORIAL_XLIB $(CFLAGS) $(MYCFLAGS) -o $@ $<
+
+PDF_EXAMPLES=$(patsubst %.c,%-pdf,$(wildcard *.c))
+pdf: $(PDF_EXAMPLES)
+%-pdf:%.c cairo-tutorial-pdf.h
+ $(CC) -DCAIRO_TUTORIAL_PDF $(CFLAGS) $(MYCFLAGS) -o $@ $<
+
+PNG_EXAMPLES=$(patsubst %.c,%-png,$(wildcard *.c))
+png: $(PNG_EXAMPLES)
+%-png:%.c cairo-tutorial-png.h
+ $(CC) -DCAIRO_TUTORIAL_PNG $(CFLAGS) $(MYCFLAGS) -o $@ $<
+
+clean:
+ rm -f $(GTK_EXAMPLES) $(XLIB_EXAMPLES) $(PDF_EXAMPLES) $(PNG_EXAMPLES)
+
+.PHONY: all gtk xlib pdf png clean
diff --git a/doc/tutorial/src/cairo-tutorial-gtk.h b/doc/tutorial/src/cairo-tutorial-gtk.h
new file mode 100644
index 000000000..adb10a054
--- /dev/null
+++ b/doc/tutorial/src/cairo-tutorial-gtk.h
@@ -0,0 +1,116 @@
+/* cairo-tutorial-gtk.h - a tutorial framework for cairo with gtk+
+ *
+ * Copyright © 2005, Carl Worth
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <gtk/gtk.h>
+#include <cairo.h>
+
+#ifndef WIDTH
+#define WIDTH 400
+#endif
+
+#ifndef HEIGHT
+#define HEIGHT 400
+#endif
+
+static void
+draw (cairo_t *cr);
+
+#if ! GTK_CHECK_VERSION(2,7,0)
+/* copied from gtk+/gdk/gdkcairo.c and gtk+/gdk/x11/gdkdrawable-x11.c
+ * gdk_cairo_create() which is available in 2.7.0 and later.
+ */
+static cairo_t *
+gdk_cairo_create (GdkDrawable *drawable)
+{
+ int width, height;
+ cairo_t *cr = NULL;
+ cairo_surface_t *surface = NULL;
+ GdkVisual *visual = gdk_drawable_get_visual (drawable);
+
+ gdk_drawable_get_size (drawable, &width, &height);
+ if (visual)
+ surface = cairo_xlib_surface_create (GDK_DRAWABLE_XDISPLAY (drawable),
+ GDK_DRAWABLE_XID (drawable),
+ GDK_VISUAL_XVISUAL (visual),
+ width, height);
+ else if (gdk_drawable_get_depth (drawable) == 1)
+ surface = cairo_xlib_surface_create_for_bitmap
+ (GDK_PIXMAP_XDISPLAY (drawable),
+ GDK_PIXMAP_XID (drawable),
+ GDK_SCREEN_XSCREEN (gdk_drawable_get_screen (drawable)),
+ width, height);
+ else {
+ g_warning ("Using Cairo rendering requires the drawable argument to\n"
+ "have a specified colormap. All windows have a colormap,\n"
+ "however, pixmaps only have colormap by default if they\n"
+ "were created with a non-NULL window argument. Otherwise\n"
+ "a colormap must be set on them with "
+ "gdk_drawable_set_colormap");
+ return NULL;
+ }
+ if (surface) {
+ cr = cairo_create (surface);
+ cairo_surface_destroy (surface);
+ }
+ return cr;
+}
+#endif
+
+static gboolean
+handle_expose (GtkWidget *widget,
+ GdkEventExpose *event,
+ gpointer data)
+{
+ cairo_t *cr;
+
+ cr = gdk_cairo_create (widget->window);
+
+ draw (cr);
+
+ cairo_destroy (cr);
+
+ return FALSE;
+}
+
+int
+main (int argc, char **argv)
+{
+ GtkWidget *window, *drawing_area;
+
+ gtk_init (&argc, &argv);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_window_set_default_size (GTK_WINDOW (window), WIDTH, HEIGHT);
+ gtk_window_set_title (GTK_WINDOW (window), "cairo demo");
+
+ g_signal_connect (window, "destroy-event",
+ G_CALLBACK (gtk_main_quit), NULL);
+
+ drawing_area = gtk_drawing_area_new ();
+ gtk_container_add (GTK_CONTAINER (window), drawing_area);
+
+ g_signal_connect (drawing_area, "expose-event",
+ G_CALLBACK (handle_expose), NULL);
+
+ gtk_widget_show_all (window);
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/doc/tutorial/src/cairo-tutorial-pdf.h b/doc/tutorial/src/cairo-tutorial-pdf.h
new file mode 100644
index 000000000..563ea763e
--- /dev/null
+++ b/doc/tutorial/src/cairo-tutorial-pdf.h
@@ -0,0 +1,74 @@
+/* cairo-tutorial-png.h - a tutorial framework for cairo to write a PNG image
+ *
+ * Copyright © 2005, Carl Worth
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <cairo.h>
+#include <cairo-pdf.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#ifndef WIDTH
+#define WIDTH 400
+#endif
+
+#ifndef HEIGHT
+#define HEIGHT 400
+#endif
+
+static void
+draw (cairo_t *cr);
+
+int
+main (int argc, char **argv)
+{
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ char *filename, *dash;
+
+ filename = strdup (argv[0]);
+ assert (filename != NULL);
+
+ dash = strrchr (filename, '-');
+
+ if (strcmp (dash, "-pdf") == 0) {
+ *dash = '.';
+ } else {
+ char *new_filename;
+ new_filename = malloc (strlen (filename) + 5);
+ sprintf (new_filename, "%s.pdf", filename);
+ free (filename);
+ filename = new_filename;
+ }
+
+ surface = cairo_pdf_surface_create (filename, WIDTH, HEIGHT);
+
+ cr = cairo_create (surface);
+
+ draw (cr);
+
+ cairo_show_page (cr);
+
+ cairo_surface_destroy (surface);
+ cairo_destroy (cr);
+
+ free (filename);
+
+ return 0;
+}
diff --git a/doc/tutorial/src/cairo-tutorial-png.h b/doc/tutorial/src/cairo-tutorial-png.h
new file mode 100644
index 000000000..a6800c8b7
--- /dev/null
+++ b/doc/tutorial/src/cairo-tutorial-png.h
@@ -0,0 +1,74 @@
+/* cairo-tutorial-png.h - a tutorial framework for cairo to write a PNG image
+ *
+ * Copyright © 2005, Carl Worth
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <cairo.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#ifndef WIDTH
+#define WIDTH 400
+#endif
+
+#ifndef HEIGHT
+#define HEIGHT 400
+#endif
+
+static void
+draw (cairo_t *cr);
+
+int
+main (int argc, char **argv)
+{
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ char *filename, *dash;
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ WIDTH, HEIGHT);
+
+ cr = cairo_create (surface);
+
+ draw (cr);
+
+ filename = strdup (argv[0]);
+ assert (filename != NULL);
+
+ dash = strrchr (filename, '-');
+
+ if (strcmp (dash, "-png") == 0) {
+ *dash = '.';
+ } else {
+ char *new_filename;
+ new_filename = malloc (strlen (filename) + 5);
+ sprintf (new_filename, "%s.png", filename);
+ free (filename);
+ filename = new_filename;
+ }
+
+ cairo_surface_write_to_png (surface, filename);
+
+ free (filename);
+
+ cairo_surface_destroy (surface);
+ cairo_destroy (cr);
+
+ return 0;
+}
diff --git a/doc/tutorial/src/cairo-tutorial-xlib.h b/doc/tutorial/src/cairo-tutorial-xlib.h
new file mode 100644
index 000000000..301b9524c
--- /dev/null
+++ b/doc/tutorial/src/cairo-tutorial-xlib.h
@@ -0,0 +1,219 @@
+/* cairo-tutorial-xlib.h - a tutorial framework for cairo with xlib
+ *
+ * Copyright © 2005, Keith Packard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <strings.h>
+#include <X11/Xos.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <cairo.h>
+#include <cairo-xlib.h>
+
+#ifndef WIDTH
+#define WIDTH 400
+#endif
+
+#ifndef HEIGHT
+#define HEIGHT 400
+#endif
+
+#ifndef DEFAULT_VISUAL
+#define DEFAULT_VISUAL 0
+#endif
+
+static void
+Usage (char *program)
+{
+ fprintf (stderr, "Usage: %s\n", program);
+ fprintf (stderr, "\t-display <display-name>\n");
+ fprintf (stderr, "\t-geometry <geometry>\n");
+ exit (1);
+}
+
+char *dpy_name;
+VisualID vid = DEFAULT_VISUAL;
+Colormap colormap;
+Visual *visual;
+int depth;
+unsigned int width = WIDTH, height = HEIGHT;
+
+static void
+draw (cairo_t *cr);
+
+static void
+handle_expose (Display *dpy, Drawable d)
+{
+ cairo_surface_t *surface;
+ cairo_t *cr;
+
+ surface = cairo_xlib_surface_create (dpy, d, visual,
+ width, height);
+ cr = cairo_create (surface);
+
+ draw (cr);
+
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
+}
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ Display *dpy;
+ Window win;
+ Window root = 0;
+ char **init_argv = argv;
+ XSetWindowAttributes attr;
+ int scr;
+ int x = 0, y = 0;
+ int geometryMask;
+ int border_width = 1;
+ XSizeHints sizeHints;
+ XWMHints wmHints;
+ XClassHint classHints;
+ XEvent ev;
+ XEvent eev;
+ int HasExpose = 0;
+ int sync = 0;
+ XTextProperty wm_name, icon_name;
+ Atom wm_delete_window;
+ unsigned long gc_mask;
+ char quit_string[10];
+ unsigned long window_mask;
+ int has_colormap = 0;
+
+ wm_name.value = (unsigned char *) argv[0];
+ wm_name.encoding = XA_STRING;
+ wm_name.format = 8;
+ wm_name.nitems = strlen (argv[0]) + 1;
+ icon_name = wm_name;
+ gc_mask = 0;
+ while (*++argv) {
+ if (!strcmp (*argv, "-display"))
+ dpy_name = *++argv;
+ else if (!strcmp (*argv, "-visual"))
+ vid = strtol(*++argv, NULL, 0);
+ else if (!strcmp (*argv, "-geometry"))
+ geometryMask = XParseGeometry (*++argv, &x, &y, &width, &height);
+ else if (!strcmp (*argv, "-sync"))
+ sync = 1;
+ else if (!strcmp (*argv, "-bw"))
+ border_width = strtol(*++argv, NULL, 0);
+ else if (!strcmp (*argv, "-root"))
+ root = strtol (*++argv, NULL, 0);
+ else
+ Usage (*init_argv);
+ }
+ sizeHints.flags = 0;
+ wmHints.flags = InputHint;
+ wmHints.input = True;
+ classHints.res_name = init_argv[0];
+ classHints.res_class = init_argv[0];
+ dpy = XOpenDisplay (dpy_name);
+ if (!dpy) {
+ fprintf (stderr, "Error: failed to open display: %s\n",
+ XDisplayName (dpy_name));
+ exit (1);
+ }
+ if (sync)
+ XSynchronize (dpy, sync);
+ scr = DefaultScreen (dpy);
+ if (!root)
+ root = RootWindow (dpy, scr);
+ window_mask = CWBackPixel|CWBorderPixel|CWEventMask;
+ if (!has_colormap)
+ colormap = DefaultColormap (dpy, scr);
+ else
+ {
+ window_mask |= CWColormap;
+ attr.colormap = colormap;
+ }
+ visual = DefaultVisual (dpy, scr);
+ depth = DefaultDepth (dpy, scr);
+ if (vid)
+ {
+ XVisualInfo vi, *vi_ret;
+ int n;
+
+ vi.visualid = vid;
+ vi.screen = scr;
+ vi_ret = XGetVisualInfo (dpy, VisualIDMask|VisualScreenMask,
+ &vi, &n);
+ if (vi_ret)
+ {
+ visual = vi_ret->visual;
+ if (!has_colormap)
+ {
+ colormap = XCreateColormap (dpy, root, visual, AllocNone);
+ window_mask |= CWColormap;
+ attr.colormap = colormap;
+ }
+ depth = vi_ret->depth;
+ }
+ }
+ attr.background_pixel = WhitePixel (dpy, scr);
+ attr.border_pixel = 0;
+ attr.event_mask = ExposureMask|KeyPressMask|KeyReleaseMask;
+ wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+ win = XCreateWindow (dpy, root, x, y, width, height, border_width,
+ depth, InputOutput,
+ visual,
+ window_mask,
+ &attr);
+ XSetWMProperties (dpy, win,
+ &wm_name, &icon_name,
+ init_argv, argc,
+ &sizeHints, &wmHints, 0);
+ XSetWMProtocols (dpy, win, &wm_delete_window, 1);
+ XMapWindow (dpy, win);
+ for (;;) {
+ XNextEvent (dpy, &ev);
+ if (HasExpose && ev.type != Expose) {
+ HasExpose = 0;
+ handle_expose (dpy, eev.xexpose.window);
+ }
+ switch (ev.type) {
+ case Expose:
+ if (QLength(dpy)) {
+ eev = ev;
+ HasExpose = 1;
+ } else if (ev.xexpose.count == 0) {
+ handle_expose (dpy, ev.xexpose.window);
+ }
+ break;
+ case KeyPress:
+ if (XLookupString ((XKeyEvent *) &ev, quit_string, sizeof (quit_string), 0, 0) == 1) {
+ switch (quit_string[0]) {
+ case 'q':
+ exit (0);
+ case 'c':
+ XClearArea (dpy, ev.xkey.window, 0, 0, 0, 0, True);
+ break;
+ }
+ }
+ break;
+ case ClientMessage:
+ exit (0);
+ }
+ }
+}
diff --git a/doc/tutorial/src/cairo-tutorial.h b/doc/tutorial/src/cairo-tutorial.h
new file mode 100644
index 000000000..65a431afe
--- /dev/null
+++ b/doc/tutorial/src/cairo-tutorial.h
@@ -0,0 +1,41 @@
+/* cairo-tutorial-gtk.h - a tutorial framework for cairo
+ *
+ * Copyright © 2005, Carl Worth
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <cairo.h>
+#include <math.h>
+
+/* The application program may override these before including
+ * cairo-tutorial.h in order to get a window of a different size. */
+#ifndef WIDTH
+#define WIDTH 400
+#endif
+
+#ifndef HEIGHT
+#define HEIGHT 400
+#endif
+
+#ifdef CAIRO_TUTORIAL_GTK
+#include "cairo-tutorial-gtk.h"
+#elif CAIRO_TUTORIAL_XLIB
+#include "cairo-tutorial-xlib.h"
+#elif CAIRO_TUTORIAL_PDF
+#include "cairo-tutorial-pdf.h"
+#elif CAIRO_TUTORIAL_PNG
+#include "cairo-tutorial-png.h"
+#endif
+
diff --git a/doc/tutorial/src/circle.c b/doc/tutorial/src/circle.c
new file mode 100644
index 000000000..06ca8fc9b
--- /dev/null
+++ b/doc/tutorial/src/circle.c
@@ -0,0 +1,22 @@
+#define WIDTH 50
+#define HEIGHT 50
+
+#include "cairo-tutorial.h"
+
+static void
+draw (cairo_t *cr)
+{
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+ cairo_paint (cr);
+
+ cairo_move_to (cr, 47.5, 25);
+ cairo_arc (cr, 25, 25, 22.5,
+ 0.0, 2 * M_PI);
+
+ cairo_set_source_rgb (cr, 0.6, 0.8, 1.0);
+ cairo_fill_preserve (cr);
+
+ cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+ cairo_set_line_width (cr, 1.0);
+ cairo_stroke (cr);
+}
diff --git a/doc/tutorial/src/expander.c b/doc/tutorial/src/expander.c
new file mode 100644
index 000000000..a00865fbd
--- /dev/null
+++ b/doc/tutorial/src/expander.c
@@ -0,0 +1,16 @@
+#define WIDTH 50
+#define HEIGHT 50
+
+#include "cairo-tutorial.h"
+
+static void
+draw (cairo_t *cr)
+{
+ cairo_translate (cr, 24.5, 25);
+ cairo_move_to (cr, 5, -2.5);
+ cairo_line_to (cr, 0, 2.5);
+ cairo_line_to (cr, -5, -2.5);
+ cairo_close_path (cr);
+ cairo_set_line_width (cr, 1);
+ cairo_stroke (cr);
+}
diff --git a/src/Makefile.am b/src/Makefile.am
index 888105503..16cbb1c50 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -17,7 +17,7 @@ endif
if CAIRO_HAS_XLIB_SURFACE
libcairo_xlib_headers = cairo-xlib.h cairo-xlib-xrender.h
-libcairo_xlib_sources = cairo-xlib-surface.c cairo-xlib-test.h
+libcairo_xlib_sources = cairo-xlib-surface.c cairo-xlib-screen.c cairo-xlib-private.h cairo-xlib-test.h
endif
if CAIRO_HAS_QUARTZ_SURFACE
@@ -88,6 +88,7 @@ libcairo_la_SOURCES = \
cairo-color.c \
cairo-fixed.c \
cairo-font.c \
+ cairo-font-options.c \
cairo-gstate.c \
cairo-gstate-private.h \
cairo-hull.c \
diff --git a/src/cairo-array.c b/src/cairo-array.c
index a9f148a07..ef7f77fca 100644
--- a/src/cairo-array.c
+++ b/src/cairo-array.c
@@ -198,6 +198,11 @@ _cairo_user_data_array_get_data (cairo_user_data_array_t *array,
int i, num_slots;
cairo_user_data_slot_t *slots;
+ /* We allow this to support degenerate objects such as
+ * cairo_image_surface_nil. */
+ if (array == NULL)
+ return NULL;
+
num_slots = array->num_elements;
slots = (cairo_user_data_slot_t *) array->elements;
for (i = 0; i < num_slots; i++) {
diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index bcb079150..990a23117 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -68,7 +68,6 @@ typedef struct cairo_ATSUI_glyph_path_callback_info_t {
const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend;
-
static CGAffineTransform
CGAffineTransformMakeWithCairoFontScale(cairo_matrix_t *scale)
{
@@ -77,7 +76,6 @@ CGAffineTransformMakeWithCairoFontScale(cairo_matrix_t *scale)
0, 0);
}
-
static ATSUStyle
CreateSizedCopyOfStyle(ATSUStyle inStyle, cairo_matrix_t *scale)
{
@@ -691,7 +689,6 @@ _cairo_atsui_font_glyph_path(void *abstract_font,
return CAIRO_STATUS_SUCCESS;
}
-
const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend = {
_cairo_atsui_font_create,
_cairo_atsui_font_destroy_font,
diff --git a/src/cairo-font-options.c b/src/cairo-font-options.c
new file mode 100644
index 000000000..d7f2529dc
--- /dev/null
+++ b/src/cairo-font-options.c
@@ -0,0 +1,352 @@
+/* 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 University of Southern
+ * California.
+ *
+ * Contributor(s):
+ * Owen Taylor <otaylor@redhat.com>
+ */
+
+#include "cairoint.h"
+
+static const cairo_font_options_t cairo_font_options_nil = {
+ CAIRO_ANTIALIAS_DEFAULT,
+ CAIRO_SUBPIXEL_ORDER_DEFAULT,
+ CAIRO_HINT_STYLE_DEFAULT,
+ CAIRO_HINT_METRICS_DEFAULT
+};
+
+/**
+ * _cairo_font_options_init_default:
+ * @options: a #cairo_font_options_t
+ *
+ * Initializes all fileds of the font options object to default values.
+ **/
+void
+_cairo_font_options_init_default (cairo_font_options_t *options)
+{
+ if (options == (cairo_font_options_t *)&cairo_font_options_nil)
+ return;
+
+ options->antialias = CAIRO_ANTIALIAS_DEFAULT;
+ options->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
+ options->hint_style = CAIRO_HINT_STYLE_DEFAULT;
+ options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT;
+}
+
+/**
+ * cairo_font_options_create:
+ *
+ * Allocates a new font options object with all options initialized
+ * to default values.
+ *
+ * Return value: a newly allocated #cairo_font_options_t. Free with
+ * cairo_font_options_destroy(). This function always returns a
+ * valid pointer; if memory cannot be allocated, then a special
+ * error object is returned where all operations on the object do nothing.
+ * You can check for this with cairo_font_options_status().
+ **/
+cairo_font_options_t *
+cairo_font_options_create (void)
+{
+ cairo_font_options_t *options = malloc (sizeof (cairo_font_options_t));
+
+ if (!options)
+ return (cairo_font_options_t *)&cairo_font_options_nil;
+
+ _cairo_font_options_init_default (options);
+
+ return options;
+}
+
+/**
+ * cairo_font_options_copy:
+ * @original: a #cairo_font_options_t
+ *
+ * Allocates a new font options object copying the option values from
+ * @original.
+ *
+ * Return value: a newly allocated #cairo_font_options_t. Free with
+ * cairo_font_options_destroy(). This function always returns a
+ * valid pointer; if memory cannot be allocated, then a special
+ * error object is returned where all operations on the object do nothing.
+ * You can check for this with cairo_font_options_status().
+ **/
+cairo_font_options_t *
+cairo_font_options_copy (const cairo_font_options_t *original)
+{
+ cairo_font_options_t *options = malloc (sizeof (cairo_font_options_t));
+
+ if (!options)
+ return (cairo_font_options_t *)&cairo_font_options_nil;
+
+ *options = *original;
+
+ return options;
+}
+
+/**
+ * cairo_font_options_destroy:
+ * @options: a #cairo_font_options_t
+ *
+ * Destroys a #cairo_font_options_t object created with with
+ * cairo_font_options_create() or cairo_font_options_copy().
+ **/
+void
+cairo_font_options_destroy (cairo_font_options_t *options)
+{
+ if (options == (cairo_font_options_t *)&cairo_font_options_nil)
+ return;
+
+ free (options);
+}
+
+/**
+ * cairo_font_options_status:
+ * @options: a #cairo_font_options_t
+ *
+ * Checks whether an error has previously occurred for this
+ * font options object
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
+ **/
+cairo_status_t
+cairo_font_options_status (cairo_font_options_t *options)
+{
+ if (options == (cairo_font_options_t *)&cairo_font_options_nil)
+ return CAIRO_STATUS_NO_MEMORY;
+ else
+ return CAIRO_STATUS_SUCCESS;
+}
+
+/**
+ * cairo_font_options_merge:
+ * @options: a #cairo_font_options_t
+ * @other: another #cairo_font_options_t
+ *
+ * Merges non-default options from @other into @options, replacing
+ * existing values. This operation can be thought of as somewhat
+ * similar to compositing @other onto @options with the operation
+ * of %CAIRO_OPERATION_OVER.
+ **/
+void
+cairo_font_options_merge (cairo_font_options_t *options,
+ const cairo_font_options_t *other)
+{
+ if (options == (cairo_font_options_t *)&cairo_font_options_nil)
+ return;
+
+ if (other->antialias != CAIRO_ANTIALIAS_DEFAULT)
+ options->antialias = other->antialias;
+ if (other->subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT)
+ options->subpixel_order = other->subpixel_order;
+ if (other->hint_style != CAIRO_HINT_STYLE_DEFAULT)
+ options->hint_style = other->hint_style;
+ if (other->hint_metrics != CAIRO_HINT_METRICS_DEFAULT)
+ options->hint_metrics = other->hint_metrics;
+}
+
+/**
+ * cairo_font_options_equal:
+ * @options: a #cairo_font_options_t
+ * @other: another #cairo_font_options_t
+ *
+ * Compares two font options objects for equality.
+ *
+ * Return value: %TRUE if all fields of the two font options objects match
+ **/
+cairo_bool_t
+cairo_font_options_equal (const cairo_font_options_t *options,
+ const cairo_font_options_t *other)
+{
+ return (options->antialias == other->antialias &&
+ options->subpixel_order == other->subpixel_order &&
+ options->hint_style == other->hint_style &&
+ options->hint_metrics == other->hint_metrics);
+}
+
+/**
+ * cairo_font_options_hash:
+ * @options: a #cairo_font_options_t
+ *
+ * Compute a hash for the font options object; this value will
+ * be useful when storing an object containing a cairo_font_options_t
+ * in a hash table.
+ *
+ * Return value: the hash value for the font options object.
+ * The return value can be cast to a 32-bit type if a
+ * 32-bit hash value is needed.
+ **/
+unsigned long
+cairo_font_options_hash (const cairo_font_options_t *options)
+{
+ return ((options->antialias) |
+ (options->subpixel_order << 4) |
+ (options->hint_style << 8) |
+ (options->hint_metrics << 16));
+}
+
+/**
+ * cairo_font_options_set_antialias:
+ * @options: a #cairo_font_options_t
+ * @antialias: the new antialiasing mode
+ *
+ * Sets the antiliasing mode for the font options object. This
+ * specifies the type of antialiasing to do when rendering text.
+ **/
+void
+cairo_font_options_set_antialias (cairo_font_options_t *options,
+ cairo_antialias_t antialias)
+{
+ if (options == (cairo_font_options_t *)&cairo_font_options_nil)
+ return;
+
+ options->antialias = antialias;
+}
+
+/**
+ * cairo_font_options_get_antialias:
+ * @options: a #cairo_font_options_t
+ *
+ * Gets the antialising mode for the font options object.
+ *
+ * Return value: the antialiasing mode
+ **/
+cairo_antialias_t
+cairo_font_options_get_antialias (const cairo_font_options_t *options)
+{
+ return options->antialias;
+}
+
+/**
+ * cairo_font_options_set_subpixel_order:
+ * @options: a #cairo_font_options_t
+ * @subpixel_order: the new subpixel order
+ *
+ * Sets the subpixel order for the font options object. The subpixel
+ * order specifies the order of color elements within each pixel on
+ * the display device when rendering with an antialiasing mode of
+ * %CAIRO_ANTIALIAS_SUBPIXEL. See the documentation for
+ * #cairo_subpixel_order_t for full details.
+ **/
+void
+cairo_font_options_set_subpixel_order (cairo_font_options_t *options,
+ cairo_subpixel_order_t subpixel_order)
+{
+ if (options == (cairo_font_options_t *)&cairo_font_options_nil)
+ return;
+
+ options->subpixel_order = subpixel_order;
+}
+
+/**
+ * cairo_font_options_get_subpixel_order:
+ * @options: a #cairo_font_options_t
+ *
+ * Gets the subpixel order for the font options object.
+ * See the documentation for #cairo_subpixel_order_t for full details.
+ *
+ * Return value: the subpixel order for the font options object
+ **/
+cairo_subpixel_order_t
+cairo_font_options_get_subpixel_order (const cairo_font_options_t *options)
+{
+ return options->subpixel_order;
+}
+
+/**
+ * cairo_font_options_set_hint_style:
+ * @options: a #cairo_font_options_t
+ * @hint_style: the new hint style
+ *
+ * Sets the hint style for font outlines for the font options object.
+ * This controls whether to fit font outlines to the pixel grid,
+ * and if so, whether to optimize for fidelity or contrast.
+ * See the documentation for #cairo_hint_style_t for full details.
+ **/
+void
+cairo_font_options_set_hint_style (cairo_font_options_t *options,
+ cairo_hint_style_t hint_style)
+{
+ if (options == (cairo_font_options_t *)&cairo_font_options_nil)
+ return;
+
+ options->hint_style = hint_style;
+}
+
+/**
+ * cairo_font_options_get_hint_style:
+ * @options: a #cairo_font_options_t
+ *
+ * Gets the hint style for font outlines for the font options object.
+ * See the documentation for #cairo_hint_style_t for full details.
+ *
+ * Return value: the hint style for the font options object
+ **/
+cairo_hint_style_t
+cairo_font_options_get_hint_style (const cairo_font_options_t *options)
+{
+ return options->hint_style;
+}
+
+/**
+ * cairo_font_options_set_hint_metrics:
+ * @options: a #cairo_font_options_t
+ * @hint_metrics: the new metrics hinting mode
+ *
+ * Sets the metrics hinting mode for the font options object. This
+ * controls whether metrics are quantized to integer values in
+ * device units.
+ * See the documentation for #cairo_hint_metrics_t for full details.
+ **/
+void
+cairo_font_options_set_hint_metrics (cairo_font_options_t *options,
+ cairo_hint_metrics_t hint_metrics)
+{
+ if (options == (cairo_font_options_t *)&cairo_font_options_nil)
+ return;
+
+ options->hint_metrics = hint_metrics;
+}
+
+/**
+ * cairo_font_options_get_hint_metrics:
+ * @options: a #cairo_font_options_t
+ *
+ * Gets the metrics hinting mode for the font options object.
+ * See the documentation for #cairo_hint_metrics_t for full details.
+ *
+ * Return value: the metrics hinting mode for the font options object
+ **/
+cairo_hint_metrics_t
+cairo_font_options_get_hint_metrics (const cairo_font_options_t *options)
+{
+ return options->hint_metrics;
+}
diff --git a/src/cairo-font.c b/src/cairo-font.c
index a74cac453..9645f3df2 100644
--- a/src/cairo-font.c
+++ b/src/cairo-font.c
@@ -39,13 +39,26 @@
#include "cairoint.h"
+/* 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;
+
/* cairo_font_face_t */
+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
+};
+
void
_cairo_font_face_init (cairo_font_face_t *font_face,
const cairo_font_face_backend_t *backend)
{
- font_face->refcount = 1;
+ font_face->status = CAIRO_STATUS_SUCCESS;
+ font_face->ref_count = 1;
font_face->backend = backend;
_cairo_user_data_array_init (&font_face->user_data);
@@ -66,7 +79,10 @@ cairo_font_face_reference (cairo_font_face_t *font_face)
if (font_face == NULL)
return;
- font_face->refcount++;
+ if (font_face->ref_count == (unsigned int)-1)
+ return;
+
+ font_face->ref_count++;
}
/**
@@ -83,7 +99,10 @@ cairo_font_face_destroy (cairo_font_face_t *font_face)
if (font_face == NULL)
return;
- if (--(font_face->refcount) > 0)
+ if (font_face->ref_count == (unsigned int)-1)
+ return;
+
+ if (--(font_face->ref_count) > 0)
return;
font_face->backend->destroy (font_face);
@@ -92,7 +111,7 @@ cairo_font_face_destroy (cairo_font_face_t *font_face)
* FreeType backend where cairo_ft_font_face_t and cairo_ft_unscaled_font_t
* need to effectively mutually reference each other
*/
- if (font_face->refcount > 0)
+ if (font_face->ref_count > 0)
return;
_cairo_user_data_array_fini (&font_face->user_data);
@@ -101,6 +120,22 @@ cairo_font_face_destroy (cairo_font_face_t *font_face)
}
/**
+ * cairo_font_face_status:
+ * @surface: a #cairo_font_face_t
+ *
+ * Checks whether an error has previously occurred for this
+ * font face
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS or another error such as
+ * %CAIRO_STATUS_NO_MEMORY.
+ **/
+cairo_status_t
+cairo_font_face_status (cairo_font_face_t *font_face)
+{
+ return font_face->status;
+}
+
+/**
* cairo_font_face_get_user_data:
* @font_face: a #cairo_font_face_t
* @key: the address of the #cairo_user_data_key_t the user data was
@@ -142,6 +177,9 @@ cairo_font_face_set_user_data (cairo_font_face_t *font_face,
void *user_data,
cairo_destroy_func_t destroy)
{
+ if (font_face->ref_count == -1)
+ return CAIRO_STATUS_NO_MEMORY;
+
return _cairo_user_data_array_set_data (&font_face->user_data,
key, user_data, destroy);
}
@@ -159,8 +197,6 @@ struct _cairo_simple_font_face {
cairo_font_weight_t weight;
};
-static const cairo_font_face_backend_t _cairo_simple_font_face_backend;
-
/* 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
@@ -355,17 +391,18 @@ _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,
- cairo_scaled_font_t **scaled_font)
+_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)
{
const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT;
cairo_simple_font_face_t *simple_face = abstract_face;
return backend->create (simple_face->family, simple_face->slant, simple_face->weight,
- font_matrix, ctm, scaled_font);
+ font_matrix, ctm, options, scaled_font);
}
static const cairo_font_face_backend_t _cairo_simple_font_face_backend = {
@@ -405,21 +442,75 @@ _cairo_simple_font_face_create (const char *family,
cache = _get_global_simple_cache ();
if (cache == NULL) {
_unlock_global_simple_cache ();
- return NULL;
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_font_face_t *)&_cairo_font_face_nil;
}
status = _cairo_cache_lookup (cache, &key, (void **) &entry, &created_entry);
if (status == CAIRO_STATUS_SUCCESS && !created_entry)
cairo_font_face_reference (&entry->font_face->base);
_unlock_global_simple_cache ();
- if (status)
- return NULL;
+ if (status) {
+ _cairo_error (status);
+ return (cairo_font_face_t *)&_cairo_font_face_nil;
+ }
return &entry->font_face->base;
}
/* cairo_scaled_font_t */
+static const cairo_scaled_font_t _cairo_scaled_font_nil = {
+ CAIRO_STATUS_NO_MEMORY, /* status */
+ -1, /* ref_count */
+ { 1., 0., 0., 1., 0, 0}, /* font_matrix */
+ { 1., 0., 0., 1., 0, 0}, /* ctm */
+ { 1., 0., 0., 1., 0, 0}, /* scale */
+ NULL, /* font_face */
+ CAIRO_SCALED_FONT_BACKEND_DEFAULT,
+};
+
+/**
+ * _cairo_scaled_font_set_error:
+ * @scaled_font: a scaled_font
+ * @status: a status value indicating an error, (eg. not
+ * CAIRO_STATUS_SUCCESS)
+ *
+ * Sets scaled_font->status to @status and calls _cairo_error;
+ *
+ * All assignments of an error status to scaled_font->status should happen
+ * through _cairo_scaled_font_set_error() or else _cairo_error() should be
+ * called immediately after the assignment.
+ *
+ * The purpose of this function is to allow the user to set a
+ * breakpoint in _cairo_error() to generate a stack trace for when the
+ * user causes cairo to detect an error.
+ **/
+void
+_cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font,
+ cairo_status_t status)
+{
+ scaled_font->status = status;
+
+ _cairo_error (status);
+}
+
+/**
+ * cairo_scaled_font_status:
+ * @surface: a #cairo_scaled_font_t
+ *
+ * Checks whether an error has previously occurred for this
+ * scaled_font.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS or another error such as
+ * %CAIRO_STATUS_NO_MEMORY.
+ **/
+cairo_status_t
+cairo_scaled_font_status (cairo_scaled_font_t *scaled_font)
+{
+ return scaled_font->status;
+}
+
/* Here we keep a cache from cairo_font_face_t/matrix/ctm => cairo_scaled_font_t.
*
* The implementation is messy because we want
@@ -444,6 +535,7 @@ typedef struct {
cairo_font_face_t *font_face;
const cairo_matrix_t *font_matrix;
const cairo_matrix_t *ctm;
+ cairo_font_options_t options;
} cairo_font_cache_key_t;
typedef struct {
@@ -554,7 +646,9 @@ _cairo_font_cache_hash (void *cache, void *key)
sizeof(double) * 4,
hash);
- return hash ^ (unsigned long)k->font_face;
+ return (hash ^
+ (unsigned long)k->font_face ^
+ cairo_font_options_hash (&k->options));
}
static int
@@ -573,7 +667,8 @@ _cairo_font_cache_keys_equal (void *cache,
sizeof(double) * 4) == 0 &&
memcmp ((unsigned char *)(&a->ctm->xx),
(unsigned char *)(&b->ctm->xx),
- sizeof(double) * 4) == 0);
+ sizeof(double) * 4) == 0 &&
+ cairo_font_options_equal (&a->options, &b->options));
}
/* The cache lookup failed in the outer cache, so we pull
@@ -614,6 +709,7 @@ _cairo_outer_font_cache_create_entry (void *cache,
entry->key.font_face = entry->scaled_font->font_face;
entry->key.font_matrix = &entry->scaled_font->font_matrix;
entry->key.ctm = &entry->scaled_font->ctm;
+ entry->key.options = ((cairo_font_cache_key_t *) key)->options;
*return_entry = entry;
@@ -650,6 +746,7 @@ _cairo_inner_font_cache_create_entry (void *cache,
status = k->font_face->backend->create_font (k->font_face,
k->font_matrix,
k->ctm,
+ &k->options,
&entry->scaled_font);
if (status) {
free (entry);
@@ -663,6 +760,7 @@ _cairo_inner_font_cache_create_entry (void *cache,
entry->key.font_face = k->font_face;
entry->key.font_matrix = &entry->scaled_font->font_matrix;
entry->key.ctm = &entry->scaled_font->ctm;
+ entry->key.options = k->options;
*return_entry = entry;
@@ -712,6 +810,8 @@ static const cairo_cache_backend_t _cairo_inner_font_cache_backend = {
* cairo_set_font_matrix().
* @ctm: user to device transformation matrix with which the font will
* be used.
+ * @options: options to use when getting metrics for the font and
+ * rendering with it.
*
* Creates a #cairo_scaled_font_t object from a font face and matrices that
* describe the size of the font and the environment in which it will
@@ -721,24 +821,30 @@ static const cairo_cache_backend_t _cairo_inner_font_cache_backend = {
* cairo_scaled_font_destroy()
**/
cairo_scaled_font_t *
-cairo_scaled_font_create (cairo_font_face_t *font_face,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm)
+cairo_scaled_font_create (cairo_font_face_t *font_face,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ const cairo_font_options_t *options)
{
cairo_font_cache_entry_t *entry;
cairo_font_cache_key_t key;
cairo_cache_t *cache;
cairo_status_t status;
+ if (font_face->status)
+ return (cairo_scaled_font_t*) &_cairo_scaled_font_nil;
+
key.font_face = font_face;
key.font_matrix = font_matrix;
key.ctm = ctm;
+ key.options = *options;
_lock_global_font_cache ();
cache = _get_outer_font_cache ();
if (cache == NULL) {
_unlock_global_font_cache ();
- return NULL;
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_scaled_font_t*) &_cairo_scaled_font_nil;
}
status = _cairo_cache_lookup (cache, &key, (void **) &entry, NULL);
@@ -746,8 +852,10 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
cairo_scaled_font_reference (entry->scaled_font);
_unlock_global_font_cache ();
- if (status)
- return NULL;
+ if (status) {
+ _cairo_error (status);
+ return (cairo_scaled_font_t*) &_cairo_scaled_font_nil;
+ }
return entry->scaled_font;
}
@@ -758,11 +866,13 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
const cairo_matrix_t *ctm,
const cairo_scaled_font_backend_t *backend)
{
+ scaled_font->status = CAIRO_STATUS_SUCCESS;
+
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->refcount = 1;
+ scaled_font->ref_count = 1;
scaled_font->backend = backend;
}
@@ -772,6 +882,9 @@ _cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
cairo_glyph_t **glyphs,
int *num_glyphs)
{
+ if (scaled_font->status)
+ return scaled_font->status;
+
return scaled_font->backend->text_to_glyphs (scaled_font, utf8, glyphs, num_glyphs);
}
@@ -781,6 +894,9 @@ _cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
int num_glyphs,
cairo_text_extents_t *extents)
{
+ if (scaled_font->status)
+ return scaled_font->status;
+
return scaled_font->backend->glyph_extents (scaled_font, glyphs, num_glyphs, extents);
}
@@ -791,6 +907,9 @@ _cairo_scaled_font_glyph_bbox (cairo_scaled_font_t *scaled_font,
int num_glyphs,
cairo_box_t *bbox)
{
+ if (scaled_font->status)
+ return scaled_font->status;
+
return scaled_font->backend->glyph_bbox (scaled_font, glyphs, num_glyphs, bbox);
}
@@ -810,6 +929,9 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
{
cairo_status_t status;
+ if (scaled_font->status)
+ return scaled_font->status;
+
status = _cairo_surface_show_glyphs (scaled_font, operator, pattern,
surface,
source_x, source_y,
@@ -834,20 +956,31 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
int num_glyphs,
cairo_path_fixed_t *path)
{
+ if (scaled_font->status)
+ return scaled_font->status;
+
return scaled_font->backend->glyph_path (scaled_font, glyphs, num_glyphs, path);
}
-void
+cairo_status_t
_cairo_scaled_font_get_glyph_cache_key (cairo_scaled_font_t *scaled_font,
cairo_glyph_cache_key_t *key)
{
+ if (scaled_font->status)
+ return scaled_font->status;
+
scaled_font->backend->get_glyph_cache_key (scaled_font, key);
+
+ return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_scaled_font_font_extents (cairo_scaled_font_t *scaled_font,
cairo_font_extents_t *extents)
{
+ if (scaled_font->status)
+ return scaled_font->status;
+
return scaled_font->backend->font_extents (scaled_font, extents);
}
@@ -855,7 +988,7 @@ void
_cairo_unscaled_font_init (cairo_unscaled_font_t *unscaled_font,
const cairo_unscaled_font_backend_t *backend)
{
- unscaled_font->refcount = 1;
+ unscaled_font->ref_count = 1;
unscaled_font->backend = backend;
}
@@ -865,7 +998,7 @@ _cairo_unscaled_font_reference (cairo_unscaled_font_t *unscaled_font)
if (unscaled_font == NULL)
return;
- unscaled_font->refcount++;
+ unscaled_font->ref_count++;
}
void
@@ -874,7 +1007,7 @@ _cairo_unscaled_font_destroy (cairo_unscaled_font_t *unscaled_font)
if (unscaled_font == NULL)
return;
- if (--(unscaled_font->refcount) > 0)
+ if (--(unscaled_font->ref_count) > 0)
return;
unscaled_font->backend->destroy (unscaled_font);
@@ -901,7 +1034,10 @@ cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font)
if (scaled_font == NULL)
return;
- scaled_font->refcount++;
+ if (scaled_font->ref_count == (unsigned int)-1)
+ return;
+
+ scaled_font->ref_count++;
}
/**
@@ -921,7 +1057,10 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
if (scaled_font == NULL)
return;
- if (--(scaled_font->refcount) > 0)
+ if (scaled_font->ref_count == (unsigned int)-1)
+ return;
+
+ if (--(scaled_font->ref_count) > 0)
return;
if (scaled_font->font_face) {
@@ -954,17 +1093,23 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
* Return value: %CAIRO_STATUS_SUCCESS on success. Otherwise, an
* error such as %CAIRO_STATUS_NO_MEMORY.
**/
-cairo_status_t
+void
cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font,
cairo_font_extents_t *extents)
{
cairo_int_status_t status;
double font_scale_x, font_scale_y;
+
+ if (scaled_font->status) {
+ _cairo_scaled_font_set_error (scaled_font, scaled_font->status);
+ return;
+ }
status = _cairo_scaled_font_font_extents (scaled_font, extents);
-
- if (status)
- return status;
+ if (status) {
+ _cairo_scaled_font_set_error (scaled_font, status);
+ return;
+ }
_cairo_matrix_compute_scale_factors (&scaled_font->font_matrix,
&font_scale_x, &font_scale_y,
@@ -980,8 +1125,6 @@ cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font,
extents->height *= font_scale_y;
extents->max_x_advance *= font_scale_x;
extents->max_y_advance *= font_scale_y;
-
- return status;
}
/**
@@ -1008,6 +1151,11 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
double x_pos = 0.0, y_pos = 0.0;
int set = 0;
+ if (scaled_font->status) {
+ _cairo_scaled_font_set_error (scaled_font, scaled_font->status);
+ return;
+ }
+
if (!num_glyphs)
{
extents->x_bearing = 0.0;
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 99776764b..afe80dffd 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -1,5 +1,6 @@
/* cairo - a vector graphics library with display and print output
*
+ * Copyright © 2000 Keith Packard
* Copyright © 2005 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
@@ -32,6 +33,8 @@
* Contributor(s):
* Graydon Hoare <graydon@redhat.com>
* Owen Taylor <otaylor@redhat.com>
+ * Keith Packard <keithp@keithp.com>
+ * Carl Worth <cworth@cworth.org>
*/
#include <float.h>
@@ -51,6 +54,19 @@
#define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
#define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0)
+/* We pack some of our own information into the bits unused
+ * by FreeType's load flags. If FreeType ever uses up all
+ * the load flag bits, we'll have to do something else.
+ * (probably just store what we care about in load_flags
+ * then convert into FreeType terms.
+ */
+#define PRIVATE_FLAG_HINT_METRICS (0x01 << 24)
+#define PRIVATE_FLAGS_MASK (0xff << 24)
+
+ /* This is the max number of FT_face objects we keep open at once
+ */
+ #define MAX_OPEN_FACES 10
+
/* This is the max number of FT_face objects we keep open at once
*/
#define MAX_OPEN_FACES 10
@@ -72,7 +88,6 @@ typedef struct {
* just create a one-off version with a permanent face value.
*/
-
typedef struct _ft_font_face ft_font_face_t;
typedef struct {
@@ -225,7 +240,7 @@ _ft_font_cache_create_entry (void *cache,
void *key,
void **return_entry)
{
- cairo_ft_cache_key_t *k = (cairo_ft_cache_key_t *) key;
+ cairo_ft_cache_key_t *k = key;
cairo_ft_cache_entry_t *entry;
entry = malloc (sizeof (cairo_ft_cache_entry_t));
@@ -443,11 +458,18 @@ _compute_transform (ft_font_transform_t *sf,
_cairo_matrix_compute_scale_factors (&normalized,
&sf->x_scale, &sf->y_scale,
/* XXX */ 1);
- cairo_matrix_scale (&normalized, 1.0 / sf->x_scale, 1.0 / sf->y_scale);
- _cairo_matrix_get_affine (&normalized,
- &sf->shape[0][0], &sf->shape[0][1],
- &sf->shape[1][0], &sf->shape[1][1],
- &tx, &ty);
+
+ if (sf->x_scale != 0 && sf->y_scale != 0) {
+ cairo_matrix_scale (&normalized, 1.0 / sf->x_scale, 1.0 / sf->y_scale);
+
+ _cairo_matrix_get_affine (&normalized,
+ &sf->shape[0][0], &sf->shape[0][1],
+ &sf->shape[1][0], &sf->shape[1][1],
+ &tx, &ty);
+ } else {
+ sf->shape[0][0] = sf->shape[1][1] = 1.0;
+ sf->shape[0][1] = sf->shape[1][0] = 0.0;
+ }
}
/* Temporarily scales an unscaled font to the give scale. We catch
@@ -460,6 +482,7 @@ _ft_unscaled_font_set_scale (ft_unscaled_font_t *unscaled,
ft_font_transform_t sf;
FT_Matrix mat;
FT_UInt pixel_width, pixel_height;
+ FT_Error error;
assert (unscaled->face != NULL);
@@ -493,9 +516,14 @@ _ft_unscaled_font_set_scale (ft_unscaled_font_t *unscaled,
if ((unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) {
pixel_width = sf.x_scale;
pixel_height = sf.y_scale;
+ error = FT_Set_Char_Size (unscaled->face,
+ sf.x_scale * 64.0,
+ sf.y_scale * 64.0,
+ 0, 0);
} else {
double min_distance = DBL_MAX;
int i;
+ int best_i = 0;
pixel_width = pixel_height = 0;
@@ -505,13 +533,20 @@ _ft_unscaled_font_set_scale (ft_unscaled_font_t *unscaled,
if (distance <= min_distance) {
min_distance = distance;
- pixel_width = unscaled->face->available_sizes[i].x_ppem >> 6;
- pixel_height = unscaled->face->available_sizes[i].y_ppem >> 6;
+ best_i = i;
}
}
+ 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 )
+ error = FT_Set_Pixel_Sizes (unscaled->face,
+ unscaled->face->available_sizes[best_i].width,
+ unscaled->face->available_sizes[best_i].height);
}
- FT_Set_Pixel_Sizes (unscaled->face, pixel_width, pixel_height);
+ assert (error == 0);
}
static void
@@ -551,6 +586,232 @@ _cairo_ft_unscaled_font_destroy (void *abstract_font)
}
}
+/* Empirically-derived subpixel filtering values thanks to Keith
+ * Packard and libXft. */
+static const int filters[3][3] = {
+ /* red */
+#if 0
+ { 65538*4/7,65538*2/7,65538*1/7 },
+ /* green */
+ { 65536*1/4, 65536*2/4, 65537*1/4 },
+ /* blue */
+ { 65538*1/7,65538*2/7,65538*4/7 },
+#endif
+ { 65538*9/13,65538*3/13,65538*1/13 },
+ /* green */
+ { 65538*1/6, 65538*4/6, 65538*1/6 },
+ /* blue */
+ { 65538*1/13,65538*3/13,65538*9/13 },
+};
+
+static cairo_bool_t
+_native_byte_order_lsb (void)
+{
+ int x = 1;
+
+ return *((char *) &x) == 1;
+}
+
+/* Fills in val->image with an image surface created from @bitmap
+ */
+static cairo_status_t
+_get_bitmap_surface (cairo_image_glyph_cache_entry_t *val,
+ FT_Bitmap *bitmap,
+ cairo_bool_t own_buffer,
+ int rgba)
+{
+ int width, height, stride;
+ unsigned char *data;
+ int format = CAIRO_FORMAT_A8;
+ cairo_bool_t subpixel = FALSE;
+
+ width = bitmap->width;
+ height = bitmap->rows;
+
+ if (width * height == 0) {
+ if (own_buffer && bitmap->buffer)
+ free (bitmap->buffer);
+
+ val->image = NULL;
+ } else {
+ switch (bitmap->pixel_mode) {
+ case FT_PIXEL_MODE_MONO:
+ stride = (((width + 31) & ~31) >> 3);
+ if (own_buffer) {
+ data = bitmap->buffer;
+ assert (stride == bitmap->pitch);
+ } else {
+ data = malloc (stride * height);
+ if (!data)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ if (stride == bitmap->pitch) {
+ memcpy (data, bitmap->buffer, stride * height);
+ } else {
+ int i;
+ unsigned char *source, *dest;
+
+ source = bitmap->buffer;
+ dest = data;
+ for (i = height; i; i--) {
+ memcpy (dest, source, bitmap->pitch);
+ memset (dest + bitmap->pitch, '\0', stride - bitmap->pitch);
+
+ source += bitmap->pitch;
+ dest += stride;
+ }
+ }
+ }
+
+ if (_native_byte_order_lsb())
+ {
+ unsigned char *d = data, c;
+ int count = stride * height;
+
+ while (count--) {
+ c = *d;
+ c = ((c << 1) & 0xaa) | ((c >> 1) & 0x55);
+ c = ((c << 2) & 0xcc) | ((c >> 2) & 0x33);
+ c = ((c << 4) & 0xf0) | ((c >> 4) & 0x0f);
+ *d++ = c;
+ }
+ }
+ format = CAIRO_FORMAT_A1;
+ break;
+
+ case FT_PIXEL_MODE_LCD:
+ case FT_PIXEL_MODE_LCD_V:
+ case FT_PIXEL_MODE_GRAY:
+ if (rgba == FC_RGBA_NONE || rgba == FC_RGBA_UNKNOWN)
+ {
+ stride = bitmap->pitch;
+ if (own_buffer) {
+ data = bitmap->buffer;
+ } else {
+ data = malloc (stride * height);
+ if (!data)
+ return CAIRO_STATUS_NO_MEMORY;
+ memcpy (data, bitmap->buffer, stride * height);
+ }
+ format = CAIRO_FORMAT_A8;
+ } else {
+ int x, y;
+ unsigned char *in_line, *out_line, *in;
+ unsigned int *out;
+ unsigned int red, green, blue;
+ int rf, gf, bf;
+ int s;
+ int o, os;
+ unsigned char *data_rgba;
+ unsigned int width_rgba, stride_rgba;
+ int vmul = 1;
+ int hmul = 1;
+
+ switch (rgba) {
+ case FC_RGBA_RGB:
+ case FC_RGBA_BGR:
+ default:
+ width /= 3;
+ hmul = 3;
+ break;
+ case FC_RGBA_VRGB:
+ case FC_RGBA_VBGR:
+ vmul = 3;
+ height /= 3;
+ break;
+ }
+ subpixel = TRUE;
+ /*
+ * Filter the glyph to soften the color fringes
+ */
+ width_rgba = width;
+ stride = bitmap->pitch;
+ stride_rgba = (width_rgba * 4 + 3) & ~3;
+ data_rgba = calloc (1, stride_rgba * height);
+
+ os = 1;
+ switch (rgba) {
+ case FC_RGBA_VRGB:
+ os = stride;
+ case FC_RGBA_RGB:
+ default:
+ rf = 0;
+ gf = 1;
+ bf = 2;
+ break;
+ case FC_RGBA_VBGR:
+ os = stride;
+ case FC_RGBA_BGR:
+ bf = 0;
+ gf = 1;
+ rf = 2;
+ break;
+ }
+ in_line = bitmap->buffer;
+ out_line = data_rgba;
+ for (y = 0; y < height; y++)
+ {
+ in = in_line;
+ out = (unsigned int *) out_line;
+ in_line += stride * vmul;
+ out_line += stride_rgba;
+ for (x = 0; x < width * hmul; x += hmul)
+ {
+ red = green = blue = 0;
+ o = 0;
+ for (s = 0; s < 3; s++)
+ {
+ red += filters[rf][s]*in[x+o];
+ green += filters[gf][s]*in[x+o];
+ blue += filters[bf][s]*in[x+o];
+ o += os;
+ }
+ red = red / 65536;
+ green = green / 65536;
+ blue = blue / 65536;
+ *out++ = (green << 24) | (red << 16) | (green << 8) | blue;
+ }
+ }
+
+ /* Images here are stored in native format. The
+ * backend must convert to its own format as needed
+ */
+
+ if (own_buffer)
+ free (bitmap->buffer);
+ data = data_rgba;
+ stride = stride_rgba;
+ format = CAIRO_FORMAT_ARGB32;
+ }
+ break;
+ case FT_PIXEL_MODE_GRAY2:
+ case FT_PIXEL_MODE_GRAY4:
+ /* These could be triggered by very rare types of TrueType fonts */
+ default:
+ return CAIRO_STATUS_NO_MEMORY;
+ }
+
+ val->image = (cairo_image_surface_t *)
+ cairo_image_surface_create_for_data (data,
+ format,
+ width, height, stride);
+ if (val->image->base.status) {
+ free (data);
+ return CAIRO_STATUS_NO_MEMORY;
+ }
+
+ if (subpixel)
+ pixman_image_set_component_alpha (val->image->pixman_image, TRUE);
+
+ _cairo_image_surface_assume_ownership_of_data (val->image);
+ }
+
+ val->size.width = width;
+ val->size.height = height;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
/* Converts an outline FT_GlyphSlot into an image
*
* This could go through _render_glyph_bitmap as well, letting
@@ -570,12 +831,18 @@ static cairo_status_t
_render_glyph_outline (FT_Face face,
cairo_image_glyph_cache_entry_t *val)
{
+ int rgba = FC_RGBA_UNKNOWN;
FT_GlyphSlot glyphslot = face->glyph;
FT_Outline *outline = &glyphslot->outline;
- unsigned int width, height, stride;
FT_Bitmap bitmap;
FT_BBox cbox;
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ FT_Matrix matrix;
+ int hmul = 1;
+ int vmul = 1;
+ unsigned int width, height, stride;
+ cairo_format_t format;
+ cairo_bool_t subpixel = FALSE;
+ cairo_status_t status;
FT_Outline_Get_CBox (outline, &cbox);
@@ -583,43 +850,88 @@ _render_glyph_outline (FT_Face face,
cbox.yMin &= -64;
cbox.xMax = (cbox.xMax + 63) & -64;
cbox.yMax = (cbox.yMax + 63) & -64;
-
+
width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
- stride = (width + 3) & -4;
-
+ stride = (width * hmul + 3) & ~3;
+
if (width * height == 0) {
- val->image = NULL;
+ /* Looks like fb handles zero-sized images just fine */
+ if ((val->key.flags & FT_LOAD_MONOCHROME) != 0)
+ format = CAIRO_FORMAT_A8;
+ else if (FT_LOAD_TARGET_MODE (val->key.flags) == FT_RENDER_MODE_LCD ||
+ FT_LOAD_TARGET_MODE (val->key.flags) == FT_RENDER_MODE_LCD_V)
+ format= CAIRO_FORMAT_ARGB32;
+ else
+ format = CAIRO_FORMAT_A8;
+
+ val->image = (cairo_image_surface_t *)
+ cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
+ if (val->image->base.status)
+ return CAIRO_STATUS_NO_MEMORY;
} else {
- bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
- bitmap.num_grays = 256;
- bitmap.width = width;
- bitmap.rows = height;
+ matrix.xx = matrix.yy = 0x10000L;
+ matrix.xy = matrix.yx = 0;
+
+ if ((val->key.flags & FT_LOAD_MONOCHROME) != 0) {
+ bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
+ bitmap.num_grays = 1;
+ stride = ((width + 31) & -32) >> 3;
+ } else {
+ /* XXX not a complete set of flags. This code
+ * will go away when cworth rewrites the glyph
+ * cache code */
+ if (FT_LOAD_TARGET_MODE (val->key.flags) == FT_RENDER_MODE_LCD)
+ rgba = FC_RGBA_RGB;
+ else if (FT_LOAD_TARGET_MODE (val->key.flags) == FT_RENDER_MODE_LCD_V)
+ rgba = FC_RGBA_VBGR;
+
+ switch (rgba) {
+ case FC_RGBA_RGB:
+ case FC_RGBA_BGR:
+ matrix.xx *= 3;
+ hmul = 3;
+ subpixel = TRUE;
+ break;
+ case FC_RGBA_VRGB:
+ case FC_RGBA_VBGR:
+ matrix.yy *= 3;
+ vmul = 3;
+ subpixel = TRUE;
+ break;
+ }
+ if (subpixel)
+ format = CAIRO_FORMAT_ARGB32;
+ else
+ format = CAIRO_FORMAT_A8;
+
+ if (subpixel)
+ FT_Outline_Transform (outline, &matrix);
+
+ bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
+ bitmap.num_grays = 256;
+ stride = (width * hmul + 3) & -4;
+ }
bitmap.pitch = stride;
- bitmap.buffer = calloc (1, stride * height);
+ bitmap.width = width * hmul;
+ bitmap.rows = height * vmul;
+ bitmap.buffer = calloc (1, stride * bitmap.rows);
if (bitmap.buffer == NULL) {
return CAIRO_STATUS_NO_MEMORY;
}
- FT_Outline_Translate (outline, -cbox.xMin, -cbox.yMin);
+ FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul);
if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
free (bitmap.buffer);
return CAIRO_STATUS_NO_MEMORY;
}
-
- val->image = (cairo_image_surface_t *)
- cairo_image_surface_create_for_data (bitmap.buffer,
- CAIRO_FORMAT_A8,
- width, height, stride);
- if (val->image == NULL) {
- free (bitmap.buffer);
- return CAIRO_STATUS_NO_MEMORY;
- }
-
- _cairo_image_surface_assume_ownership_of_data (val->image);
+
+ status = _get_bitmap_surface (val, &bitmap, TRUE, rgba);
+ if (status)
+ return status;
}
/*
@@ -627,12 +939,10 @@ _render_glyph_outline (FT_Face face,
* Y coordinate of the control box needs to be negated.
*/
- val->size.width = (unsigned short) width;
- val->size.height = (unsigned short) height;
val->size.x = (short) (cbox.xMin >> 6);
val->size.y = - (short) (cbox.yMax >> 6);
- return status;
+ return CAIRO_STATUS_SUCCESS;
}
/* Converts a bitmap (or other) FT_GlyphSlot into an image
@@ -655,12 +965,8 @@ _render_glyph_bitmap (FT_Face face,
cairo_image_glyph_cache_entry_t *val)
{
FT_GlyphSlot glyphslot = face->glyph;
- FT_Bitmap *bitmap;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
- int width, height, stride;
- unsigned char *data;
FT_Error error;
- int i, j;
/* According to the FreeType docs, glyphslot->format could be
* something other than FT_GLYPH_FORMAT_OUTLINE or
@@ -673,65 +979,9 @@ _render_glyph_bitmap (FT_Face face,
if (error)
return CAIRO_STATUS_NO_MEMORY;
- bitmap = &glyphslot->bitmap;
+ _get_bitmap_surface (val, &glyphslot->bitmap, FALSE, FC_RGBA_NONE);
- width = bitmap->width;
- height = bitmap->rows;
-
- if (width * height == 0) {
- val->image = NULL;
- } else {
- switch (bitmap->pixel_mode) {
- case FT_PIXEL_MODE_MONO:
- stride = (width + 3) & ~3;
- data = calloc (stride * height, 1);
- if (!data)
- return CAIRO_STATUS_NO_MEMORY;
- for (j = 0; j < height; j++) {
- const unsigned char *p = bitmap->buffer + j * bitmap->pitch;
- unsigned char *q = data + j * stride;
- for (i = 0; i < width; i++) {
- /* FreeType bitmaps are always stored MSB */
- unsigned char byte = p[i >> 3];
- unsigned char bit = 1 << (7 - (i % 8));
-
- if (byte & bit)
- q[i] = 0xff;
- }
- }
- break;
- case FT_PIXEL_MODE_GRAY:
- stride = bitmap->pitch;
- data = malloc (stride * height);
- if (!data)
- return CAIRO_STATUS_NO_MEMORY;
- memcpy (data, bitmap->buffer, stride * height);
- break;
- case FT_PIXEL_MODE_GRAY2:
- case FT_PIXEL_MODE_GRAY4:
- /* These could be triggered by very rare types of TrueType fonts */
- case FT_PIXEL_MODE_LCD:
- case FT_PIXEL_MODE_LCD_V:
- /* These should never be triggered unless we ask for them */
- default:
- return CAIRO_STATUS_NO_MEMORY;
- }
-
- val->image = (cairo_image_surface_t *)
- cairo_image_surface_create_for_data (data,
- CAIRO_FORMAT_A8,
- width, height, stride);
- if (val->image == NULL) {
- free (data);
- return CAIRO_STATUS_NO_MEMORY;
- }
-
- _cairo_image_surface_assume_ownership_of_data (val->image);
- }
-
- val->size.width = width;
- val->size.height = height;
- val->size.x = - glyphslot->bitmap_left;
+ val->size.x = glyphslot->bitmap_left;
val->size.y = - glyphslot->bitmap_top;
return status;
@@ -813,7 +1063,7 @@ _transform_glyph_bitmap (cairo_image_glyph_cache_entry_t *val)
/* We need to pad out the width to 32-bit intervals for cairo-xlib-surface.c */
width = (width + 3) & ~3;
image = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
- if (!image)
+ if (image->status)
return CAIRO_STATUS_NO_MEMORY;
/* Initialize it to empty
@@ -865,6 +1115,7 @@ _cairo_ft_unscaled_font_create_glyph (void *abstract_
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);
if (!face)
@@ -875,33 +1126,67 @@ _cairo_ft_unscaled_font_create_glyph (void *abstract_
_ft_unscaled_font_set_scale (unscaled, &val->key.scale);
- if (FT_Load_Glyph (face, val->key.index, val->key.flags) != 0) {
+ if (FT_Load_Glyph (face, val->key.index, val->key.flags & ~PRIVATE_FLAGS_MASK) != 0) {
status = CAIRO_STATUS_NO_MEMORY;
goto FAIL;
}
+ if (unscaled->x_scale == 0)
+ x_factor = 0;
+ else
+ x_factor = 1 / unscaled->x_scale;
+
+ if (unscaled->y_scale == 0)
+ y_factor = 0;
+ else
+ y_factor = 1 / unscaled->y_scale;
+
/*
* Note: the font's coordinate system is upside down from ours, so the
* Y coordinates of the bearing and advance need to be negated.
*
* Scale metrics back to glyph space from the scaled glyph space returned
* by FreeType
+ *
+ * If we want hinted metrics but aren't asking for hinted glyphs from
+ * FreeType, then we need to do the metric hinting ourselves.
*/
-
- val->extents.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) / unscaled->x_scale;
- val->extents.y_bearing = -DOUBLE_FROM_26_6 (metrics->horiBearingY) / unscaled->y_scale;
-
- val->extents.width = DOUBLE_FROM_26_6 (metrics->width) / unscaled->x_scale;
- val->extents.height = DOUBLE_FROM_26_6 (metrics->height) / unscaled->y_scale;
-
- /*
- * use untransformed advance values
- * XXX uses horizontal advance only at present;
- should provide FT_LOAD_VERTICAL_LAYOUT
- */
-
- val->extents.x_advance = DOUBLE_FROM_26_6 (face->glyph->metrics.horiAdvance) / unscaled->x_scale;
- val->extents.y_advance = 0 / unscaled->y_scale;
+
+ if ((val->key.flags & PRIVATE_FLAG_HINT_METRICS) &&
+ (val->key.flags & FT_LOAD_NO_HINTING)) {
+ FT_Pos x1, x2;
+ FT_Pos y1, y2;
+ FT_Pos advance;
+
+ x1 = (metrics->horiBearingX) & -64;
+ x2 = (metrics->horiBearingX + metrics->width + 63) & -64;
+ y1 = (metrics->horiBearingY) & -64;
+ y2 = (metrics->horiBearingY + metrics->height + 63) & -64;
+
+ advance = ((metrics->horiAdvance + 32) & -64);
+
+ val->extents.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor;
+ val->extents.y_bearing = -DOUBLE_FROM_26_6 (y1) * y_factor;
+
+ val->extents.width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor;
+ val->extents.height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor;
+
+ /*
+ * use untransformed advance values
+ * XXX uses horizontal advance only at present; should provide FT_LOAD_VERTICAL_LAYOUT
+ */
+ val->extents.x_advance = DOUBLE_FROM_26_6 (advance) * x_factor;
+ val->extents.y_advance = 0;
+ } else {
+ val->extents.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) * x_factor;
+ val->extents.y_bearing = -DOUBLE_FROM_26_6 (metrics->horiBearingY) * y_factor;
+
+ val->extents.width = DOUBLE_FROM_26_6 (metrics->width) * x_factor;
+ val->extents.height = DOUBLE_FROM_26_6 (metrics->height) * y_factor;
+
+ val->extents.x_advance = DOUBLE_FROM_26_6 (face->glyph->metrics.horiAdvance) * x_factor;
+ val->extents.y_advance = 0 * y_factor;
+ }
if (glyphslot->format == FT_GLYPH_FORMAT_OUTLINE)
status = _render_glyph_outline (face, val);
@@ -933,43 +1218,41 @@ const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend = {
typedef struct {
cairo_scaled_font_t base;
int load_flags;
+ cairo_font_options_t options;
ft_unscaled_font_t *unscaled;
} cairo_ft_scaled_font_t;
const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend;
-/* for compatibility with older freetype versions */
-#ifndef FT_LOAD_TARGET_MONO
-#define FT_LOAD_TARGET_MONO FT_LOAD_MONOCHROME
-#endif
-
/* The load flags passed to FT_Load_Glyph control aspects like hinting and
* antialiasing. Here we compute them from the fields of a FcPattern.
*/
static int
-_get_load_flags (FcPattern *pattern)
+_get_pattern_load_flags (FcPattern *pattern)
{
- FcBool antialias, hinting, autohint;
+ FcBool antialias, vertical_layout, hinting, autohint;
+ int rgba;
#ifdef FC_HINT_STYLE
int hintstyle;
#endif
int load_flags = 0;
+ int target_flags = 0;
/* disable antialiasing if requested */
if (FcPatternGetBool (pattern,
FC_ANTIALIAS, 0, &antialias) != FcResultMatch)
antialias = FcTrue;
-
+
if (antialias)
load_flags |= FT_LOAD_NO_BITMAP;
else
- load_flags |= FT_LOAD_TARGET_MONO;
+ load_flags |= FT_LOAD_MONOCHROME;
/* disable hinting if requested */
if (FcPatternGetBool (pattern,
FC_HINTING, 0, &hinting) != FcResultMatch)
hinting = FcTrue;
-
+
#ifdef FC_HINT_STYLE
if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch)
hintstyle = FC_HINT_FULL;
@@ -977,19 +1260,46 @@ _get_load_flags (FcPattern *pattern)
if (!hinting || hintstyle == FC_HINT_NONE)
load_flags |= FT_LOAD_NO_HINTING;
- switch (hintstyle) {
- case FC_HINT_SLIGHT:
- case FC_HINT_MEDIUM:
- load_flags |= FT_LOAD_TARGET_LIGHT;
- break;
- default:
- load_flags |= FT_LOAD_TARGET_NORMAL;
- break;
+ if (antialias) {
+ switch (hintstyle) {
+ case FC_HINT_SLIGHT:
+ case FC_HINT_MEDIUM:
+ target_flags = FT_LOAD_TARGET_LIGHT;
+ break;
+ default:
+ target_flags = FT_LOAD_TARGET_NORMAL;
+ break;
+ }
+ } else {
+#ifdef FT_LOAD_TARGET_MONO
+ target_flags = FT_LOAD_TARGET_MONO;
+#endif
}
#else /* !FC_HINT_STYLE */
if (!hinting)
- load_flags |= FT_LOAD_NO_HINTING;
+ target_flags = FT_LOAD_NO_HINTING;
#endif /* FC_FHINT_STYLE */
+
+ if (FcPatternGetInteger (pattern,
+ FC_RGBA, 0, &rgba) != FcResultMatch)
+ rgba = FC_RGBA_UNKNOWN;
+
+ switch (rgba) {
+ case FC_RGBA_UNKNOWN:
+ case FC_RGBA_NONE:
+ default:
+ break;
+ case FC_RGBA_RGB:
+ case FC_RGBA_BGR:
+ target_flags = FT_LOAD_TARGET_LCD;
+ break;
+ case FC_RGBA_VRGB:
+ case FC_RGBA_VBGR:
+ target_flags = FT_LOAD_TARGET_LCD_V;
+ break;
+ }
+
+ load_flags |= target_flags;
/* force autohinting if requested */
if (FcPatternGetBool (pattern,
@@ -999,24 +1309,87 @@ _get_load_flags (FcPattern *pattern)
if (autohint)
load_flags |= FT_LOAD_FORCE_AUTOHINT;
+ if (FcPatternGetBool (pattern,
+ FC_VERTICAL_LAYOUT, 0, &vertical_layout) != FcResultMatch)
+ vertical_layout = FcFalse;
+
+ if (vertical_layout)
+ load_flags |= FT_LOAD_VERTICAL_LAYOUT;
+
+ return load_flags;
+}
+
+static int
+_get_options_load_flags (const cairo_font_options_t *options)
+{
+ int load_flags = 0;
+
+ /* disable antialiasing if requested */
+ switch (options->antialias) {
+ case CAIRO_ANTIALIAS_NONE:
+#ifdef FT_LOAD_TARGET_MONO
+ load_flags |= FT_LOAD_TARGET_MONO;
+#endif
+ load_flags |= FT_LOAD_MONOCHROME;
+ break;
+ case CAIRO_ANTIALIAS_SUBPIXEL:
+ switch (options->subpixel_order) {
+ case CAIRO_SUBPIXEL_ORDER_DEFAULT:
+ case CAIRO_SUBPIXEL_ORDER_RGB:
+ case CAIRO_SUBPIXEL_ORDER_BGR:
+ load_flags |= FT_LOAD_TARGET_LCD;
+ break;
+ case CAIRO_SUBPIXEL_ORDER_VRGB:
+ case CAIRO_SUBPIXEL_ORDER_VBGR:
+ load_flags |= FT_LOAD_TARGET_LCD_V;
+ break;
+ }
+ /* fall through ... */
+ case CAIRO_ANTIALIAS_DEFAULT:
+ case CAIRO_ANTIALIAS_GRAY:
+ load_flags |= FT_LOAD_NO_BITMAP;
+ break;
+ }
+
+ /* disable hinting if requested */
+ switch (options->hint_style) {
+ case CAIRO_HINT_STYLE_NONE:
+ load_flags |= FT_LOAD_NO_HINTING;
+ break;
+ case CAIRO_HINT_STYLE_SLIGHT:
+ case CAIRO_HINT_STYLE_MEDIUM:
+ load_flags |= FT_LOAD_TARGET_LIGHT;
+ break;
+ case CAIRO_HINT_STYLE_FULL:
+ default:
+ load_flags |= FT_LOAD_TARGET_NORMAL;
+ break;
+ }
+
return load_flags;
}
static cairo_scaled_font_t *
-_ft_scaled_font_create (ft_unscaled_font_t *unscaled,
- int load_flags,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm)
+_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_t *f = NULL;
f = malloc (sizeof(cairo_ft_scaled_font_t));
- if (f == NULL)
+ if (f == NULL)
return NULL;
f->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;
_cairo_scaled_font_init (&f->base, font_matrix, ctm, &cairo_ft_scaled_font_backend);
@@ -1031,12 +1404,13 @@ _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,
- cairo_scaled_font_t **font)
+_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)
{
FcPattern *pattern, *resolved;
ft_unscaled_font_t *unscaled;
@@ -1089,6 +1463,7 @@ _cairo_ft_scaled_font_create (const char *family,
FcPatternAddInteger (pattern, FC_PIXEL_SIZE, sf.y_scale);
FcConfigSubstitute (NULL, pattern, FcMatchPattern);
+ cairo_ft_font_options_substitute (options, pattern);
FcDefaultSubstitute (pattern);
resolved = FcFontMatch (NULL, pattern, &result);
@@ -1099,8 +1474,9 @@ _cairo_ft_scaled_font_create (const char *family,
if (!unscaled)
goto FREE_RESOLVED;
- new_font = _ft_scaled_font_create (unscaled, _get_load_flags (pattern),
- font_matrix, ctm);
+ new_font = _ft_scaled_font_create (unscaled,
+ font_matrix, ctm,
+ options, _get_pattern_load_flags (pattern));
_cairo_unscaled_font_destroy (&unscaled->base);
FcPatternDestroy (resolved);
@@ -1230,15 +1606,36 @@ _cairo_ft_scaled_font_font_extents (void *abstract_font,
metrics = &face->size->metrics;
_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
*/
- extents->ascent = DOUBLE_FROM_26_6(metrics->ascender) / scaled_font->unscaled->y_scale;
- extents->descent = DOUBLE_FROM_26_6(- metrics->descender) / scaled_font->unscaled->y_scale;
- extents->height = DOUBLE_FROM_26_6(metrics->height) / scaled_font->unscaled->y_scale;
- extents->max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance) / scaled_font->unscaled->x_scale;
+ if (scaled_font->options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
+ double x_factor, y_factor;
+
+ if (scaled_font->unscaled->x_scale == 0)
+ x_factor = 0;
+ else
+ x_factor = 1 / scaled_font->unscaled->x_scale;
+
+ if (scaled_font->unscaled->y_scale == 0)
+ y_factor = 0;
+ else
+ y_factor = 1 / scaled_font->unscaled->y_scale;
+
+ extents->ascent = DOUBLE_FROM_26_6(metrics->ascender) * y_factor;
+ extents->descent = DOUBLE_FROM_26_6(- metrics->descender) * y_factor;
+ extents->height = DOUBLE_FROM_26_6(metrics->height) * y_factor;
+ extents->max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance) * x_factor;
+ } else {
+ double scale = face->units_per_EM;
+
+ extents->ascent = face->ascender / scale;
+ extents->descent = - face->descender / scale;
+ extents->height = face->height / scale;
+ extents->max_x_advance = face->max_advance_width / scale;
+ }
/* FIXME: this doesn't do vertical layout atm. */
extents->max_y_advance = 0.0;
@@ -1540,7 +1937,8 @@ _conic_to (FT_Vector *control, FT_Vector *to, void *closure)
}
static int
-_cubic_to (FT_Vector *control1, FT_Vector *control2, FT_Vector *to, void *closure)
+_cubic_to (FT_Vector *control1, FT_Vector *control2,
+ FT_Vector *to, void *closure)
{
cairo_path_fixed_t *path = closure;
cairo_fixed_t x0, y0;
@@ -1660,7 +2058,7 @@ _ft_font_face_destroy (void *abstract_face)
if (font_face->unscaled &&
font_face->unscaled->from_face &&
- font_face->unscaled->base.refcount > 1) {
+ font_face->unscaled->base.ref_count > 1) {
cairo_font_face_reference (&font_face->base);
_cairo_unscaled_font_destroy (&font_face->unscaled->base);
@@ -1688,16 +2086,32 @@ _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,
- cairo_scaled_font_t **scaled_font)
+_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)
{
ft_font_face_t *font_face = abstract_face;
+ int load_flags;
+
+ /* The handling of font options is different depending on how the
+ * font face was created. When the user creates a font face with
+ * cairo_ft_font_face_create_for_ft_face(), then the load flags
+ * passed in augment the load flags for the options. But for
+ * cairo_ft_font_face_create_for_pattern(), the load flags are
+ * derived from a pattern where the user has called
+ * cairo_ft_font_options_substitute(), so *just* use those load
+ * flags and ignore the options.
+ */
+ if (font_face->unscaled->from_face)
+ load_flags = _get_options_load_flags (options) | font_face->load_flags;
+ else
+ load_flags = font_face->load_flags;
*scaled_font = _ft_scaled_font_create (font_face->unscaled,
- font_face->load_flags,
- font_matrix, ctm);
+ font_matrix, ctm,
+ options, load_flags);
if (*scaled_font)
return CAIRO_STATUS_SUCCESS;
else
@@ -1744,6 +2158,93 @@ _ft_font_face_create (ft_unscaled_font_t *unscaled,
/* implement the platform-specific interface */
/**
+ * cairo_ft_font_options_substitute:
+ * @options: a #cairo_font_options_t object
+ * @pattern: an existing #FcPattern
+ *
+ * Add options to a #FcPattern based on a #cairo_font_options_t font
+ * options object. Options that are already in the pattern, are not overriden,
+ * so you should call this function after calling FcConfigSubstitute() (the
+ * user's settings should override options based on the surface type), but
+ * before calling FcDefaultSubstitute().
+ **/
+void
+cairo_ft_font_options_substitute (const cairo_font_options_t *options,
+ FcPattern *pattern)
+{
+ FcValue v;
+
+ if (options->antialias != CAIRO_ANTIALIAS_DEFAULT)
+ {
+ if (FcPatternGet (pattern, FC_ANTIALIAS, 0, &v) == FcResultNoMatch)
+ {
+ FcPatternAddBool (pattern, FC_ANTIALIAS, options->antialias != CAIRO_ANTIALIAS_NONE);
+ }
+ }
+
+ if (options->antialias != CAIRO_ANTIALIAS_DEFAULT)
+ {
+ if (FcPatternGet (pattern, FC_RGBA, 0, &v) == FcResultNoMatch)
+ {
+ int rgba;
+
+ if (options->antialias == CAIRO_ANTIALIAS_SUBPIXEL) {
+ switch (options->subpixel_order) {
+ case CAIRO_SUBPIXEL_ORDER_DEFAULT:
+ case CAIRO_SUBPIXEL_ORDER_RGB:
+ default:
+ rgba = FC_RGBA_RGB;
+ break;
+ case CAIRO_SUBPIXEL_ORDER_BGR:
+ rgba = FC_RGBA_BGR;
+ break;
+ case CAIRO_SUBPIXEL_ORDER_VRGB:
+ rgba = FC_RGBA_VRGB;
+ break;
+ case CAIRO_SUBPIXEL_ORDER_VBGR:
+ rgba = FC_RGBA_VBGR;
+ break;
+ }
+ } else {
+ rgba = FC_RGBA_NONE;
+ }
+
+ FcPatternAddInteger (pattern, FC_RGBA, rgba);
+ }
+ }
+
+ if (options->hint_style != CAIRO_HINT_STYLE_DEFAULT)
+ {
+ if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch)
+ {
+ FcPatternAddBool (pattern, FC_HINTING, options->hint_style != CAIRO_HINT_STYLE_NONE);
+ }
+
+#ifdef FC_HINT_STYLE
+ if (FcPatternGet (pattern, FC_HINT_STYLE, 0, &v) == FcResultNoMatch)
+ {
+ int hint_style;
+
+ switch (options->hint_style) {
+ case CAIRO_HINT_STYLE_SLIGHT:
+ hint_style = FC_HINT_SLIGHT;
+ break;
+ case CAIRO_HINT_STYLE_MEDIUM:
+ hint_style = FC_HINT_MEDIUM;
+ break;
+ case CAIRO_HINT_STYLE_FULL:
+ default:
+ hint_style = FC_HINT_FULL;
+ break;
+ }
+
+ FcPatternAddInteger (pattern, FC_HINT_STYLE, hint_style);
+ }
+#endif
+ }
+}
+
+/**
* cairo_ft_font_face_create_for_pattern:
* @pattern: A fully resolved fontconfig
* pattern. A pattern can be resolved, by, among other things, calling
@@ -1759,6 +2260,12 @@ _ft_font_face_create (ft_unscaled_font_t *unscaled,
* returned from cairo_font_create() is also for the FreeType backend
* and can be used with functions such as cairo_ft_font_lock_face().
*
+ * Font rendering options are representated both here and when you
+ * call cairo_scaled_font_create(). Font options that have a representation
+ * in a #FcPattern must be passed in here; to modify #FcPattern
+ * appropriately to reflect the options in a #cairo_font_options_t, call
+ * cairo_ft_font_options_substitute().
+ *
* Return value: a newly created #cairo_font_face_t. Free with
* cairo_font_face_destroy() when you are done using it.
**/
@@ -1769,27 +2276,37 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
cairo_font_face_t *font_face;
unscaled = _ft_unscaled_font_get_for_pattern (pattern);
- if (unscaled == NULL)
- return NULL;
+ 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_load_flags (pattern));
+ font_face = _ft_font_face_create (unscaled, _get_pattern_load_flags (pattern));
_cairo_unscaled_font_destroy (&unscaled->base);
- return font_face;
+ if (font_face)
+ return font_face;
+ else {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_font_face_t *)&_cairo_font_face_nil;
+ }
}
/**
* cairo_ft_font_face_create_for_ft_face:
* @face: A FreeType face object, already opened. This must
- * be kept around until the face's refcount drops to
+ * be kept around until the face's ref_count drops to
* zero and it is freed. Since the face may be referenced
* internally to Cairo, the best way to determine when it
* is safe to free the face is to pass a
* #cairo_destroy_func_t to cairo_font_face_set_user_data()
- * @load_flags: The flags to pass to FT_Load_Glyph when loading
- * glyphs from the font. These flags control aspects of
- * rendering such as hinting and antialiasing. See the FreeType
- * docs for full information.
+ * @load_flags: flags to pass to FT_Load_Glyph when loading
+ * glyphs from the font. These flags are OR'ed together with
+ * the flags derived from the #cairo_font_options_t passed
+ * to cairo_scaled_font_create(), so only a few values such
+ * as %FT_LOAD_VERTICAL_LAYOUT, and %FT_LOAD_FORCE_AUTOHINT
+ * are useful. You should not pass any of the flags affecting
+ * the load target, such as %FT_LOAD_TARGET_LIGHT.
*
* Creates a new font face for the FreeType font backend from a pre-opened
* FreeType face. This font can then be used with
@@ -1808,13 +2325,20 @@ cairo_ft_font_face_create_for_ft_face (FT_Face face,
cairo_font_face_t *font_face;
unscaled = _ft_unscaled_font_create_from_face (face);
- if (unscaled == NULL)
- return NULL;
+ 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);
_cairo_unscaled_font_destroy (&unscaled->base);
- return font_face;
+ if (font_face) {
+ return font_face;
+ } else {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_font_face_t *)&_cairo_font_face_nil;
+ }
}
/**
@@ -1842,7 +2366,9 @@ cairo_ft_font_face_create_for_ft_face (FT_Face face,
* implemented, so this function cannot be currently safely used in a
* threaded application.)
- * Return value: The #FT_Face object for @font, scaled appropriately.
+ * Return value: The #FT_Face object for @font, scaled appropriately,
+ * or %NULL if @scaled_font is in an error state (see
+ * cairo_scaled_font_status()) or there is insufficient memory.
**/
FT_Face
cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
@@ -1850,9 +2376,14 @@ cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
FT_Face face;
+ if (scaled_font->base.status)
+ return NULL;
+
face = _ft_unscaled_font_lock_face (scaled_font->unscaled);
- if (!face)
+ 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);
@@ -1874,6 +2405,9 @@ cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font)
{
cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
+ if (scaled_font->base.status)
+ return;
+
_ft_unscaled_font_unlock_face (scaled_font->unscaled);
}
diff --git a/src/cairo-ft.h b/src/cairo-ft.h
index 4e8b8bcdb..3bdbae1bd 100644
--- a/src/cairo-ft.h
+++ b/src/cairo-ft.h
@@ -52,6 +52,10 @@ CAIRO_BEGIN_DECLS
cairo_font_face_t *
cairo_ft_font_face_create_for_pattern (FcPattern *pattern);
+void
+cairo_ft_font_options_substitute (const cairo_font_options_t *options,
+ FcPattern *pattern);
+
cairo_font_face_t *
cairo_ft_font_face_create_for_ft_face (FT_Face face,
int load_flags);
diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c
index 4b9d619e6..96e920339 100644
--- a/src/cairo-glitz-surface.c
+++ b/src/cairo-glitz-surface.c
@@ -83,12 +83,16 @@ _cairo_glitz_surface_create_similar (void *abstract_src,
gformat = glitz_find_standard_format (drawable,
_glitz_format_from_content (content));
- if (!gformat)
- return NULL;
+ if (!gformat) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
surface = glitz_surface_create (drawable, gformat, width, height, 0, NULL);
- if (!surface)
- return NULL;
+ if (surface == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
crsurface = cairo_glitz_surface_create (surface);
@@ -206,8 +210,7 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
&format,
width, height,
pf.bytes_per_line);
-
- if (!image)
+ if (image->base.status)
{
free (pixels);
return CAIRO_STATUS_NO_MEMORY;
@@ -341,6 +344,9 @@ _cairo_glitz_surface_clone_similar (void *abstract_surface,
cairo_glitz_surface_t *surface = abstract_surface;
cairo_glitz_surface_t *clone;
+ if (surface->base.status)
+ return surface->base.status;
+
if (src->backend == surface->base.backend)
{
*clone_out = src;
@@ -357,7 +363,7 @@ _cairo_glitz_surface_clone_similar (void *abstract_surface,
_cairo_glitz_surface_create_similar (surface, content,
image_src->width,
image_src->height);
- if (!clone)
+ if (clone->base.status)
return CAIRO_STATUS_NO_MEMORY;
_cairo_glitz_surface_set_image (clone, image_src, 0, 0);
@@ -570,7 +576,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
_cairo_surface_create_similar_scratch (&dst->base,
CAIRO_CONTENT_COLOR_ALPHA,
gradient->n_stops, 1);
- if (!src)
+ if (src->base.status)
{
glitz_buffer_destroy (buffer);
free (data);
@@ -688,13 +694,12 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
}
static void
-_cairo_glitz_pattern_release_surface (cairo_glitz_surface_t *dst,
+_cairo_glitz_pattern_release_surface (cairo_pattern_t *pattern,
cairo_glitz_surface_t *surface,
cairo_glitz_surface_attributes_t *attr)
{
if (attr->acquired)
- _cairo_pattern_release_surface (&dst->base, &surface->base,
- &attr->base);
+ _cairo_pattern_release_surface (pattern, &surface->base, &attr->base);
else
cairo_surface_destroy (&surface->base);
}
@@ -760,13 +765,12 @@ _cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src,
width, height,
mask_out, mattr);
+ if (status)
+ _cairo_glitz_pattern_release_surface (&tmp.base, *src_out, sattr);
+
_cairo_pattern_fini (&tmp.base);
- if (status)
- {
- _cairo_glitz_pattern_release_surface (dst, *src_out, sattr);
- return status;
- }
+ return status;
}
else
{
@@ -840,7 +844,7 @@ _cairo_glitz_surface_composite (cairo_operator_t op,
if (mask_attr.n_params)
free (mask_attr.params);
- _cairo_glitz_pattern_release_surface (dst, mask, &mask_attr);
+ _cairo_glitz_pattern_release_surface (mask_pattern, mask, &mask_attr);
}
else
{
@@ -858,7 +862,7 @@ _cairo_glitz_surface_composite (cairo_operator_t op,
if (src_attr.n_params)
free (src_attr.params);
- _cairo_glitz_pattern_release_surface (dst, src, &src_attr);
+ _cairo_glitz_pattern_release_surface (src_pattern, src, &src_attr);
if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED)
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -902,7 +906,7 @@ _cairo_glitz_surface_fill_rectangles (void *abstract_dst,
CAIRO_CONTENT_COLOR_ALPHA,
1, 1,
(cairo_color_t *) color);
- if (!src)
+ if (src->base.status)
return CAIRO_STATUS_NO_MEMORY;
glitz_surface_set_fill (src->surface, GLITZ_FILL_REPEAT);
@@ -942,6 +946,8 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
cairo_trapezoid_t *traps,
int n_traps)
{
+ cairo_pattern_union_t tmp_src_pattern;
+ cairo_pattern_t *src_pattern;
cairo_glitz_surface_attributes_t attributes;
cairo_glitz_surface_t *dst = abstract_dst;
cairo_glitz_surface_t *src;
@@ -951,6 +957,9 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
cairo_int_status_t status;
unsigned short alpha;
+ if (dst->base.status)
+ return dst->base.status;
+
if (op == CAIRO_OPERATOR_SATURATE)
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -959,16 +968,13 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
if (pattern->type == CAIRO_PATTERN_SURFACE)
{
- cairo_pattern_union_t tmp;
-
- _cairo_pattern_init_copy (&tmp.base, pattern);
+ _cairo_pattern_init_copy (&tmp_src_pattern.base, pattern);
- status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst,
+ status = _cairo_glitz_pattern_acquire_surface (&tmp_src_pattern.base, dst,
src_x, src_y,
width, height,
&src, &attributes);
-
- _cairo_pattern_fini (&tmp.base);
+ src_pattern = &tmp_src_pattern.base;
}
else
{
@@ -976,6 +982,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
src_x, src_y,
width, height,
&src, &attributes);
+ src_pattern = pattern;
}
alpha = 0xffff;
@@ -1004,10 +1011,13 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
_cairo_glitz_surface_create_similar (&dst->base,
CAIRO_CONTENT_ALPHA,
2, 1);
- if (!mask)
+ if (mask->base.status)
{
- _cairo_glitz_pattern_release_surface (dst, src, &attributes);
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
+ if (src_pattern == &tmp_src_pattern.base)
+ _cairo_pattern_fini (&tmp_src_pattern.base);
+
+ return CAIRO_STATUS_NO_MEMORY;
}
color.red = color.green = color.blue = color.alpha = 0xffff;
@@ -1030,8 +1040,10 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
data = realloc (data, data_size);
if (!data)
{
- _cairo_glitz_pattern_release_surface (dst, src,
+ _cairo_glitz_pattern_release_surface (src_pattern, src,
&attributes);
+ if (src_pattern == &tmp_src_pattern.base)
+ _cairo_pattern_fini (&tmp_src_pattern.base);
return CAIRO_STATUS_NO_MEMORY;
}
@@ -1041,8 +1053,10 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
buffer = glitz_buffer_create_for_data (data);
if (!buffer) {
free (data);
- _cairo_glitz_pattern_release_surface (dst, src,
+ _cairo_glitz_pattern_release_surface (src_pattern, src,
&attributes);
+ if (src_pattern == &tmp_src_pattern.base)
+ _cairo_pattern_fini (&tmp_src_pattern.base);
return CAIRO_STATUS_NO_MEMORY;
}
}
@@ -1076,7 +1090,9 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
data = malloc (stride * height);
if (!data)
{
- _cairo_glitz_pattern_release_surface (dst, src, &attributes);
+ _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
+ if (src_pattern == &tmp_src_pattern.base)
+ _cairo_pattern_fini (&tmp_src_pattern.base);
return CAIRO_STATUS_NO_MEMORY;
}
@@ -1090,7 +1106,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
CAIRO_FORMAT_A8,
width, height,
-stride);
- if (!image)
+ if (image->base.status)
{
cairo_surface_destroy (&src->base);
free (data);
@@ -1104,9 +1120,9 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
_cairo_surface_create_similar_scratch (&dst->base,
CAIRO_CONTENT_ALPHA,
width, height);
- if (!mask)
+ if (mask->base.status)
{
- _cairo_glitz_pattern_release_surface (dst, src, &attributes);
+ _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
free (data);
cairo_surface_destroy (&image->base);
return CAIRO_STATUS_NO_MEMORY;
@@ -1139,7 +1155,10 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
free (data);
- _cairo_glitz_pattern_release_surface (dst, src, &attributes);
+ _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
+ if (src_pattern == &tmp_src_pattern.base)
+ _cairo_pattern_fini (&tmp_src_pattern.base);
+
if (mask)
cairo_surface_destroy (&mask->base);
@@ -1256,10 +1275,13 @@ _cairo_glitz_area_move_in (cairo_glitz_area_t *area,
static void
_cairo_glitz_area_move_out (cairo_glitz_area_t *area)
{
- (*area->root->funcs->move_out) (area, area->closure);
+ if (area->root)
+ {
+ (*area->root->funcs->move_out) (area, area->closure);
- area->closure = NULL;
- area->state = CAIRO_GLITZ_AREA_AVAILABLE;
+ area->closure = NULL;
+ area->state = CAIRO_GLITZ_AREA_AVAILABLE;
+ }
}
static cairo_glitz_area_t *
@@ -1535,7 +1557,7 @@ typedef struct _cairo_glitz_glyph_cache {
typedef struct {
cairo_glyph_cache_key_t key;
- int refcount;
+ int ref_count;
cairo_glyph_size_t size;
cairo_glitz_area_t *area;
cairo_bool_t locked;
@@ -1593,7 +1615,7 @@ _cairo_glitz_glyph_cache_create_entry (void *abstract_cache,
if (!entry)
return CAIRO_STATUS_NO_MEMORY;
- entry->refcount = 1;
+ entry->ref_count = 1;
entry->key = *key;
entry->area = NULL;
entry->locked = FALSE;
@@ -1611,8 +1633,8 @@ _cairo_glitz_glyph_cache_destroy_entry (void *abstract_cache,
{
cairo_glitz_glyph_cache_entry_t *entry = abstract_entry;
- entry->refcount--;
- if (entry->refcount)
+ entry->ref_count--;
+ if (entry->ref_count)
return;
if (entry->area)
@@ -1628,7 +1650,7 @@ _cairo_glitz_glyph_cache_entry_reference (void *abstract_entry)
{
cairo_glitz_glyph_cache_entry_t *entry = abstract_entry;
- entry->refcount++;
+ entry->ref_count++;
}
static void
@@ -1681,7 +1703,7 @@ _cairo_glitz_get_glyph_cache (cairo_glitz_surface_t *surface)
GLYPH_CACHE_TEXTURE_SIZE,
GLYPH_CACHE_TEXTURE_SIZE,
0, NULL);
- if (!cache->surface)
+ if (cache->surface == NULL)
{
free (cache);
return NULL;
@@ -1885,7 +1907,9 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
goto UNLOCK;
}
- _cairo_scaled_font_get_glyph_cache_key (scaled_font, &key);
+ status = _cairo_scaled_font_get_glyph_cache_key (scaled_font, &key);
+ if (status)
+ goto UNLOCK;
for (i = 0; i < num_glyphs; i++)
{
@@ -2075,7 +2099,7 @@ UNLOCK:
if (attributes.n_params)
free (attributes.params);
- _cairo_glitz_pattern_release_surface (dst, src, &attributes);
+ _cairo_glitz_pattern_release_surface (pattern, src, &attributes);
if (status)
return status;
@@ -2110,12 +2134,14 @@ cairo_glitz_surface_create (glitz_surface_t *surface)
{
cairo_glitz_surface_t *crsurface;
- if (!surface)
- return NULL;
+ if (surface == NULL)
+ return (cairo_surface_t*) &_cairo_surface_nil;
crsurface = malloc (sizeof (cairo_glitz_surface_t));
- if (crsurface == NULL)
- return NULL;
+ if (crsurface == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
_cairo_surface_init (&crsurface->base, &cairo_glitz_surface_backend);
diff --git a/src/cairo-gstate-private.h b/src/cairo-gstate-private.h
index 7e2c8597c..0d4d499fe 100644
--- a/src/cairo-gstate-private.h
+++ b/src/cairo-gstate-private.h
@@ -97,6 +97,7 @@ struct _cairo_gstate {
cairo_font_face_t *font_face;
cairo_scaled_font_t *scaled_font; /* Specific to the current CTM */
cairo_matrix_t font_matrix;
+ cairo_font_options_t font_options;
cairo_clip_t clip;
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index ed6210cfb..ed3359b99 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -121,6 +121,8 @@ _cairo_gstate_init (cairo_gstate_t *gstate,
cairo_matrix_init_scale (&gstate->font_matrix,
CAIRO_GSTATE_DEFAULT_FONT_SIZE,
CAIRO_GSTATE_DEFAULT_FONT_SIZE);
+
+ _cairo_font_options_init_default (&gstate->font_options);
gstate->clip.mode = _cairo_surface_get_clip_mode (target);
gstate->clip.region = NULL;
@@ -280,8 +282,8 @@ _cairo_gstate_begin_group (cairo_gstate_t *gstate)
return CAIRO_STATUS_NO_MEMORY;
gstate->target = cairo_surface_create (gstate->dpy);
- if (gstate->target == NULL)
- return CAIRO_STATUS_NO_MEMORY;
+ if (gstate->target->status)
+ return gstate->target->status;
_cairo_surface_set_drawableWH (gstate->target, pix, width, height);
@@ -399,9 +401,6 @@ _cairo_gstate_get_clip_extents (cairo_gstate_t *gstate,
cairo_surface_t *
_cairo_gstate_get_target (cairo_gstate_t *gstate)
{
- if (gstate == NULL)
- return NULL;
-
return gstate->target;
}
@@ -906,7 +905,7 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
CAIRO_CONTENT_ALPHA,
extents.width,
extents.height);
- if (intermediate == NULL)
+ if (intermediate->status)
return CAIRO_STATUS_NO_MEMORY;
status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
@@ -1247,7 +1246,7 @@ _composite_traps_intermediate_surface (cairo_gstate_t *gstate,
extents->width,
extents->height,
CAIRO_COLOR_TRANSPARENT);
- if (intermediate == NULL)
+ if (intermediate->status)
return CAIRO_STATUS_NO_MEMORY;
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
@@ -1723,7 +1722,7 @@ _cairo_gstate_intersect_clip_mask (cairo_gstate_t *gstate,
surface_rect.width,
surface_rect.height,
CAIRO_COLOR_WHITE);
- if (surface == NULL)
+ if (surface->status)
return CAIRO_STATUS_NO_MEMORY;
/* Render the new clipping path into the new mask surface. */
@@ -1827,8 +1826,8 @@ _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);
- if (!font_face)
- return CAIRO_STATUS_NO_MEMORY;
+ if (font_face->status)
+ return font_face->status;
_cairo_gstate_set_font_face (gstate, font_face);
cairo_font_face_destroy (font_face);
@@ -1866,6 +1865,24 @@ _cairo_gstate_get_font_matrix (cairo_gstate_t *gstate,
}
cairo_status_t
+_cairo_gstate_set_font_options (cairo_gstate_t *gstate,
+ const cairo_font_options_t *options)
+{
+ _cairo_gstate_unset_font (gstate);
+
+ gstate->font_options = *options;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+void
+_cairo_gstate_get_font_options (cairo_gstate_t *gstate,
+ cairo_font_options_t *options)
+{
+ *options = gstate->font_options;
+}
+
+cairo_status_t
_cairo_gstate_get_font_face (cairo_gstate_t *gstate,
cairo_font_face_t **font_face)
{
@@ -1960,11 +1977,15 @@ static cairo_status_t
_cairo_gstate_ensure_font_face (cairo_gstate_t *gstate)
{
if (!gstate->font_face) {
- gstate->font_face = _cairo_simple_font_face_create (CAIRO_FONT_FAMILY_DEFAULT,
- CAIRO_FONT_SLANT_DEFAULT,
- CAIRO_FONT_WEIGHT_DEFAULT);
- if (!gstate->font_face)
- return CAIRO_STATUS_NO_MEMORY;
+ 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);
+ if (font_face->status)
+ return font_face->status;
+ else
+ gstate->font_face = font_face;
}
return CAIRO_STATUS_SUCCESS;
@@ -1974,6 +1995,7 @@ static cairo_status_t
_cairo_gstate_ensure_font (cairo_gstate_t *gstate)
{
cairo_status_t status;
+ cairo_font_options_t options;
if (gstate->scaled_font)
return CAIRO_STATUS_SUCCESS;
@@ -1982,9 +2004,13 @@ _cairo_gstate_ensure_font (cairo_gstate_t *gstate)
if (status)
return status;
+ cairo_surface_get_font_options (gstate->target, &options);
+ cairo_font_options_merge (&options, &gstate->font_options);
+
gstate->scaled_font = cairo_scaled_font_create (gstate->font_face,
&gstate->font_matrix,
- &gstate->ctm);
+ &gstate->ctm,
+ &options);
if (!gstate->scaled_font)
return CAIRO_STATUS_NO_MEMORY;
@@ -2000,7 +2026,9 @@ _cairo_gstate_get_font_extents (cairo_gstate_t *gstate,
if (status)
return status;
- return cairo_scaled_font_extents (gstate->scaled_font, extents);
+ cairo_scaled_font_extents (gstate->scaled_font, extents);
+
+ return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
@@ -2043,6 +2071,9 @@ cairo_status_t
_cairo_gstate_set_font_face (cairo_gstate_t *gstate,
cairo_font_face_t *font_face)
{
+ if (font_face->status)
+ return font_face->status;
+
if (font_face != gstate->font_face) {
if (gstate->font_face)
cairo_font_face_destroy (gstate->font_face);
@@ -2136,7 +2167,7 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
extents.width,
extents.height,
CAIRO_COLOR_TRANSPARENT);
- if (intermediate == NULL) {
+ if (intermediate->status) {
status = CAIRO_STATUS_NO_MEMORY;
goto BAIL1;
}
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index aff35ce3c..b21cf1228 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -36,8 +36,6 @@
#include "cairoint.h"
-static const cairo_surface_backend_t cairo_image_surface_backend;
-
static int
_cairo_format_bpp (cairo_format_t format)
{
@@ -53,15 +51,17 @@ _cairo_format_bpp (cairo_format_t format)
}
}
-static cairo_image_surface_t *
+static cairo_surface_t *
_cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
cairo_format_t format)
{
cairo_image_surface_t *surface;
surface = malloc (sizeof (cairo_image_surface_t));
- if (surface == NULL)
- return NULL;
+ if (surface == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
_cairo_surface_init (&surface->base, &cairo_image_surface_backend);
@@ -76,17 +76,17 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
surface->stride = pixman_image_get_stride (pixman_image);
surface->depth = pixman_image_get_depth (pixman_image);
- return surface;
+ return &surface->base;
}
-cairo_image_surface_t *
+cairo_surface_t *
_cairo_image_surface_create_with_masks (unsigned char *data,
cairo_format_masks_t *format,
int width,
int height,
int stride)
{
- cairo_image_surface_t *surface;
+ cairo_surface_t *surface;
pixman_format_t *pixman_format;
pixman_image_t *pixman_image;
@@ -96,16 +96,20 @@ _cairo_image_surface_create_with_masks (unsigned char *data,
format->green_mask,
format->blue_mask);
- if (pixman_format == NULL)
- return NULL;
+ if (pixman_format == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
pixman_image = pixman_image_create_for_data ((pixman_bits_t *) data, pixman_format,
width, height, format->bpp, stride);
pixman_format_destroy (pixman_format);
- if (pixman_image == NULL)
- return NULL;
+ if (pixman_image == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
surface = _cairo_image_surface_create_for_pixman_image (pixman_image,
(cairo_format_t)-1);
@@ -152,28 +156,31 @@ cairo_image_surface_create (cairo_format_t format,
int width,
int height)
{
- cairo_image_surface_t *surface;
+ cairo_surface_t *surface;
pixman_format_t *pixman_format;
pixman_image_t *pixman_image;
- /* XXX: Really need to make this kind of thing pass through _cairo_error. */
if (! CAIRO_FORMAT_VALID (format))
- return NULL;
+ return (cairo_surface_t*) &_cairo_surface_nil;
pixman_format = _create_pixman_format (format);
- if (pixman_format == NULL)
- return NULL;
+ if (pixman_format == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
pixman_image = pixman_image_create (pixman_format, width, height);
pixman_format_destroy (pixman_format);
- if (pixman_image == NULL)
- return NULL;
+ if (pixman_image == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
surface = _cairo_image_surface_create_for_pixman_image (pixman_image, format);
- return &surface->base;
+ return surface;
}
/**
@@ -205,17 +212,18 @@ cairo_image_surface_create_for_data (unsigned char *data,
int height,
int stride)
{
- cairo_image_surface_t *surface;
+ cairo_surface_t *surface;
pixman_format_t *pixman_format;
pixman_image_t *pixman_image;
- /* XXX: Really need to make this kind of thing pass through _cairo_error. */
if (! CAIRO_FORMAT_VALID (format))
- return NULL;
+ return (cairo_surface_t*) &_cairo_surface_nil;
pixman_format = _create_pixman_format (format);
- if (pixman_format == NULL)
- return NULL;
+ if (pixman_format == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
pixman_image = pixman_image_create_for_data ((pixman_bits_t *) data, pixman_format,
width, height,
@@ -224,12 +232,14 @@ cairo_image_surface_create_for_data (unsigned char *data,
pixman_format_destroy (pixman_format);
- if (pixman_image == NULL)
- return NULL;
+ if (pixman_image == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
surface = _cairo_image_surface_create_for_pixman_image (pixman_image, format);
- return &surface->base;
+ return surface;
}
/**
@@ -245,6 +255,11 @@ cairo_image_surface_get_width (cairo_surface_t *surface)
{
cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
+ if (!_cairo_surface_is_image (surface)) {
+ _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+ return 0;
+ }
+
return image_surface->width;
}
@@ -261,6 +276,11 @@ cairo_image_surface_get_height (cairo_surface_t *surface)
{
cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
+ if (!_cairo_surface_is_image (surface)) {
+ _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+ return 0;
+ }
+
return image_surface->height;
}
@@ -303,9 +323,7 @@ _cairo_image_surface_create_similar (void *abstract_src,
int width,
int height)
{
- /* XXX: Really need to make this kind of thing pass through _cairo_error. */
- if (! CAIRO_CONTENT_VALID (content))
- return NULL;
+ assert (CAIRO_CONTENT_VALID (content));
return cairo_image_surface_create (_cairo_format_from_content (content),
width, height);
@@ -341,6 +359,7 @@ _cairo_image_surface_acquire_source_image (void *abstract_sur
void **image_extra)
{
*image_out = abstract_surface;
+ *image_extra = NULL;
return CAIRO_STATUS_SUCCESS;
}
@@ -367,7 +386,8 @@ _cairo_image_surface_acquire_dest_image (void *abstract_surfa
image_rect_out->height = surface->height;
*image_out = surface;
-
+ *image_extra = NULL;
+
return CAIRO_STATUS_SUCCESS;
}
@@ -724,15 +744,15 @@ _cairo_image_abstract_surface_get_extents (void *abstract_surface,
*
* Checks if a surface is an #cairo_image_surface_t
*
- * Return value: True if the surface is an image surface
+ * Return value: TRUE if the surface is an image surface
**/
-int
+cairo_bool_t
_cairo_surface_is_image (cairo_surface_t *surface)
{
return surface->backend == &cairo_image_surface_backend;
}
-static const cairo_surface_backend_t cairo_image_surface_backend = {
+const cairo_surface_backend_t cairo_image_surface_backend = {
_cairo_image_surface_create_similar,
_cairo_image_abstract_surface_finish,
_cairo_image_surface_acquire_source_image,
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index ae869f0ed..8a893d661 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -53,8 +53,10 @@ _cairo_meta_surface_create (double width, double height)
cairo_meta_surface_t *meta;
meta = malloc (sizeof (cairo_meta_surface_t));
- if (meta == NULL)
- return NULL;
+ if (meta == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
meta->width = width;
meta->height = height;
diff --git a/src/cairo-path-data-private.h b/src/cairo-path-data-private.h
index f7f429437..d680f901e 100644
--- a/src/cairo-path-data-private.h
+++ b/src/cairo-path-data-private.h
@@ -38,6 +38,8 @@
#include "cairoint.h"
+extern cairo_path_t cairo_path_nil;
+
cairo_private cairo_path_t *
_cairo_path_data_create (cairo_path_fixed_t *path,
cairo_gstate_t *gstate);
@@ -46,9 +48,6 @@ cairo_private cairo_path_t *
_cairo_path_data_create_flat (cairo_path_fixed_t *path,
cairo_gstate_t *gstate);
-cairo_private cairo_path_t *
-_cairo_path_data_create_in_error (cairo_status_t status);
-
cairo_private cairo_status_t
_cairo_path_data_append_to_context (cairo_path_t *path,
cairo_t *cr);
diff --git a/src/cairo-path-data.c b/src/cairo-path-data.c
index 519c76315..b3bd31232 100644
--- a/src/cairo-path-data.c
+++ b/src/cairo-path-data.c
@@ -37,8 +37,7 @@
#include "cairo-path-fixed-private.h"
#include "cairo-gstate-private.h"
-static cairo_path_t
-cairo_path_nil = { CAIRO_STATUS_NO_MEMORY, NULL, 0 };
+cairo_path_t cairo_path_nil = { CAIRO_STATUS_NO_MEMORY, NULL, 0 };
/* Closure for path interpretation. */
typedef struct cairo_path_data_count {
@@ -435,35 +434,6 @@ _cairo_path_data_create_flat (cairo_path_fixed_t *path,
}
/**
- * _cairo_path_data_create_in_error:
- * @status: an error status
- *
- * Create an empty #cairo_path_t object to hold an error status. This
- * is useful for propagating status values from an existing object to
- * a new #cairo_path_t.
- *
- * Return value: a #cairo_path_t object with status of @status, NULL
- * data, and 0 num_data. If there is insufficient memory a pointer to
- * a special static cairo_path_nil will be returned instead with
- * status==CAIRO_STATUS_NO_MEMORY rather than @status.
- **/
-cairo_path_t *
-_cairo_path_data_create_in_error (cairo_status_t status)
-{
- cairo_path_t *path;
-
- path = malloc (sizeof (cairo_path_t));
- if (path == NULL)
- return &cairo_path_nil;
-
- path->status = status;
- path->data = NULL;
- path->num_data = 0;
-
- return path;
-}
-
-/**
* _cairo_path_data_append_to_context:
* @path: the path data to be appended
* @cr: a cairo context
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index b309e8e38..1fb172179 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -50,7 +50,7 @@ typedef struct _cairo_shader_op {
((unsigned char) \
((((unsigned char) (c1)) * (int) ((unsigned char) (c2))) / 0xff))
-static const cairo_solid_pattern_t cairo_solid_pattern_nil = {
+const cairo_solid_pattern_t cairo_solid_pattern_nil = {
{ CAIRO_PATTERN_SOLID, /* type */
(unsigned int)-1, /* ref_count */
CAIRO_STATUS_NO_MEMORY, /* status */
@@ -96,6 +96,31 @@ static const cairo_radial_pattern_t cairo_radial_pattern_nil = {
1.0, 1.0, /* radius0, radius1 */
};
+/**
+ * _cairo_pattern_set_error:
+ * @pattern: a pattern
+ * @status: a status value indicating an error, (eg. not
+ * CAIRO_STATUS_SUCCESS)
+ *
+ * Sets pattern->status to @status and calls _cairo_error;
+ *
+ * All assignments of an error status to pattern->status should happen
+ * through _cairo_pattern_set_error() or else _cairo_error() should be
+ * called immediately after the assignment.
+ *
+ * The purpose of this function is to allow the user to set a
+ * breakpoint in _cairo_error() to generate a stack trace for when the
+ * user causes cairo to detect an error.
+ **/
+static void
+_cairo_pattern_set_error (cairo_pattern_t *pattern,
+ cairo_status_t status)
+{
+ pattern->status = status;
+
+ _cairo_error (status);
+}
+
static void
_cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
{
@@ -127,10 +152,13 @@ _cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern,
*dst = *src;
}
+ if (other->base.status)
+ _cairo_pattern_set_error (&pattern->base, other->base.status);
+
if (other->n_stops)
{
pattern->stops = malloc (other->n_stops * sizeof (cairo_color_stop_t));
- if (!pattern->stops) {
+ if (pattern->stops == NULL) {
if (other->base.type == CAIRO_PATTERN_LINEAR)
_cairo_gradient_pattern_init_copy (pattern, &cairo_linear_pattern_nil.base);
else
@@ -264,37 +292,6 @@ _cairo_pattern_create_solid (const cairo_color_t *color)
}
/**
- * _cairo_pattern_create_in_error:
- * @status: an error status
- *
- * Create an empty #cairo_pattern_t object to hold an error
- * status. This is useful for propagating status values from an
- * existing object to a new #cairo_pattern_t.
- *
- * Return value: a (solid, black) #cairo_pattern_t object with status
- * of @status. If there is insufficient memory a pointer to a special,
- * static cairo_solid_pattern_nil will be returned instead with a
- * status of CAIRO_STATUS_NO_MEMORY rather than @status.
- *
- * Return value:
- **/
-cairo_pattern_t *
-_cairo_pattern_create_in_error (cairo_status_t status)
-{
- cairo_solid_pattern_t *pattern;
-
- pattern = malloc (sizeof (cairo_solid_pattern_t));
- if (pattern == NULL)
- return (cairo_pattern_t *) &cairo_solid_pattern_nil.base;
-
- _cairo_pattern_init_solid (pattern, CAIRO_COLOR_BLACK);
-
- pattern->base.status = status;
-
- return &pattern->base;
-}
-
-/**
* cairo_pattern_create_rgb:
* @red: red component of the color
* @green: green component of the color
@@ -317,6 +314,7 @@ _cairo_pattern_create_in_error (cairo_status_t status)
cairo_pattern_t *
cairo_pattern_create_rgb (double red, double green, double blue)
{
+ cairo_pattern_t *pattern;
cairo_color_t color;
_cairo_restrict_value (&red, 0.0, 1.0);
@@ -325,7 +323,11 @@ cairo_pattern_create_rgb (double red, double green, double blue)
_cairo_color_init_rgb (&color, red, green, blue);
- return _cairo_pattern_create_solid (&color);
+ pattern = _cairo_pattern_create_solid (&color);
+ if (pattern->status)
+ _cairo_pattern_set_error (pattern, pattern->status);
+
+ return pattern;
}
/**
@@ -353,6 +355,7 @@ cairo_pattern_t *
cairo_pattern_create_rgba (double red, double green, double blue,
double alpha)
{
+ cairo_pattern_t *pattern;
cairo_color_t color;
_cairo_restrict_value (&red, 0.0, 1.0);
@@ -362,7 +365,11 @@ cairo_pattern_create_rgba (double red, double green, double blue,
_cairo_color_init_rgba (&color, red, green, blue, alpha);
- return _cairo_pattern_create_solid (&color);
+ pattern = _cairo_pattern_create_solid (&color);
+ if (pattern->status)
+ _cairo_pattern_set_error (pattern, pattern->status);
+
+ return pattern;
}
/**
@@ -386,8 +393,10 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface)
cairo_surface_pattern_t *pattern;
pattern = malloc (sizeof (cairo_surface_pattern_t));
- if (pattern == NULL)
+ if (pattern == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_pattern_t *)&cairo_surface_pattern_nil.base;
+ }
_cairo_pattern_init_for_surface (pattern, surface);
@@ -422,8 +431,10 @@ cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
cairo_linear_pattern_t *pattern;
pattern = malloc (sizeof (cairo_linear_pattern_t));
- if (pattern == NULL)
+ if (pattern == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_pattern_t *) &cairo_linear_pattern_nil.base;
+ }
_cairo_pattern_init_linear (pattern, x0, y0, x1, y1);
@@ -461,8 +472,10 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0,
cairo_radial_pattern_t *pattern;
pattern = malloc (sizeof (cairo_radial_pattern_t));
- if (pattern == NULL)
+ if (pattern == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_pattern_t *) &cairo_radial_pattern_nil.base;
+ }
_cairo_pattern_init_radial (pattern, cx0, cy0, radius0, cx1, cy1, radius1);
@@ -541,7 +554,7 @@ _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
new_stops = realloc (pattern->stops,
pattern->n_stops * sizeof (cairo_color_stop_t));
if (new_stops == NULL) {
- pattern->base.status = CAIRO_STATUS_NO_MEMORY;
+ _cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
return;
}
@@ -568,7 +581,7 @@ cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
if (pattern->type != CAIRO_PATTERN_LINEAR &&
pattern->type != CAIRO_PATTERN_RADIAL)
{
- pattern->status = CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
+ _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
return;
}
@@ -599,7 +612,7 @@ cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
if (pattern->type != CAIRO_PATTERN_LINEAR &&
pattern->type != CAIRO_PATTERN_RADIAL)
{
- pattern->status = CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
+ _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
return;
}
@@ -619,8 +632,10 @@ void
cairo_pattern_set_matrix (cairo_pattern_t *pattern,
const cairo_matrix_t *matrix)
{
- if (pattern->status)
+ if (pattern->status) {
+ _cairo_pattern_set_error (pattern, pattern->status);
return;
+ }
pattern->matrix = *matrix;
}
@@ -634,8 +649,10 @@ cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix)
void
cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
{
- if (pattern->status)
+ if (pattern->status) {
+ _cairo_pattern_set_error (pattern, pattern->status);
return;
+ }
pattern->filter = filter;
}
@@ -649,8 +666,10 @@ cairo_pattern_get_filter (cairo_pattern_t *pattern)
void
cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
{
- if (pattern->status)
+ if (pattern->status) {
+ _cairo_pattern_set_error (pattern, pattern->status);
return;
+ }
pattern->extend = extend;
}
@@ -1164,7 +1183,7 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
}
data = malloc (width * height * 4);
- if (!data)
+ if (data == NULL)
return CAIRO_STATUS_NO_MEMORY;
if (pattern->base.type == CAIRO_PATTERN_LINEAR)
@@ -1193,7 +1212,7 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
width, height,
width * 4);
- if (image == NULL) {
+ if (image->base.status) {
free (data);
return CAIRO_STATUS_NO_MEMORY;
}
@@ -1228,8 +1247,7 @@ _cairo_pattern_acquire_surface_for_solid (cairo_solid_pattern_t *pattern,
CAIRO_CONTENT_COLOR_ALPHA,
1, 1,
&pattern->color);
-
- if (*out == NULL)
+ if ((*out)->status)
return CAIRO_STATUS_NO_MEMORY;
attribs->x_offset = attribs->y_offset = 0;
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 1c5026ce3..485c1a0ea 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -109,7 +109,7 @@ struct cairo_pdf_stream {
struct cairo_pdf_document {
cairo_output_stream_t *output_stream;
- unsigned long refcount;
+ unsigned long ref_count;
cairo_surface_t *owner;
cairo_bool_t finished;
@@ -290,8 +290,10 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *stream,
cairo_surface_t *surface;
document = _cairo_pdf_document_create (stream, width, height);
- if (document == NULL)
- return NULL;
+ if (document == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
surface = _cairo_pdf_surface_create_for_document (document, width, height);
@@ -310,8 +312,10 @@ cairo_pdf_surface_create_for_stream (cairo_write_func_t write,
cairo_output_stream_t *stream;
stream = _cairo_output_stream_create (write, closure);
- if (stream == NULL)
- return NULL;
+ if (stream == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
return _cairo_pdf_surface_create_for_stream_internal (stream, width, height);
}
@@ -324,8 +328,10 @@ cairo_pdf_surface_create (const char *filename,
cairo_output_stream_t *stream;
stream = _cairo_output_stream_create_for_file (filename);
- if (stream == NULL)
- return NULL;
+ if (stream == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
return _cairo_pdf_surface_create_for_stream_internal (stream, width, height);
}
@@ -349,8 +355,10 @@ _cairo_pdf_surface_create_for_document (cairo_pdf_document_t *document,
cairo_pdf_surface_t *surface;
surface = malloc (sizeof (cairo_pdf_surface_t));
- if (surface == NULL)
- return NULL;
+ if (surface == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
_cairo_surface_init (&surface->base, &cairo_pdf_surface_backend);
@@ -1379,6 +1387,16 @@ _cairo_pdf_surface_intersect_clip_path (void *dst,
return status;
}
+static void
+_cairo_pdf_surface_get_font_options (void *abstract_surface,
+ cairo_font_options_t *options)
+{
+ _cairo_font_options_init_default (options);
+
+ cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
+ cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
+}
+
static const cairo_surface_backend_t cairo_pdf_surface_backend = {
_cairo_pdf_surface_create_similar,
_cairo_pdf_surface_finish,
@@ -1396,7 +1414,8 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
_cairo_pdf_surface_intersect_clip_path,
_cairo_pdf_surface_get_extents,
_cairo_pdf_surface_show_glyphs,
- _cairo_pdf_surface_fill_path
+ _cairo_pdf_surface_fill_path,
+ _cairo_pdf_surface_get_font_options
};
static cairo_pdf_document_t *
@@ -1411,7 +1430,7 @@ _cairo_pdf_document_create (cairo_output_stream_t *output_stream,
return NULL;
document->output_stream = output_stream;
- document->refcount = 1;
+ document->ref_count = 1;
document->owner = NULL;
document->finished = FALSE;
document->width = width;
@@ -1642,14 +1661,14 @@ _cairo_pdf_document_write_xref (cairo_pdf_document_t *document)
static void
_cairo_pdf_document_reference (cairo_pdf_document_t *document)
{
- document->refcount++;
+ document->ref_count++;
}
static void
_cairo_pdf_document_destroy (cairo_pdf_document_t *document)
{
- document->refcount--;
- if (document->refcount > 0)
+ document->ref_count--;
+ if (document->ref_count > 0)
return;
_cairo_pdf_document_finish (document);
diff --git a/src/cairo-png.c b/src/cairo-png.c
index 532054e51..afe9e6ea1 100644
--- a/src/cairo-png.c
+++ b/src/cairo-png.c
@@ -36,6 +36,7 @@
*/
#include <png.h>
+#include <errno.h>
#include "cairoint.h"
/* Unpremultiplies data and converts native endian ARGB => RGBA bytes */
@@ -315,19 +316,15 @@ static cairo_surface_t *
read_png (png_rw_ptr read_func,
void *closure)
{
- cairo_surface_t *surface;
- png_byte *data;
+ cairo_surface_t *surface = (cairo_surface_t*) &_cairo_surface_nil;
+ png_byte *data = NULL;
int i;
- png_struct *png;
+ png_struct *png = NULL;
png_info *info;
png_uint_32 png_width, png_height, stride;
int depth, color_type, interlace;
unsigned int pixel_size;
- png_byte **row_pointers;
-
- surface = NULL;
- data = NULL;
- row_pointers = NULL;
+ png_byte **row_pointers = NULL;
/* XXX: Perhaps we'll want some other error handlers? */
png = png_create_read_struct (PNG_LIBPNG_VER_STRING,
@@ -335,7 +332,7 @@ read_png (png_rw_ptr read_func,
NULL,
NULL);
if (png == NULL)
- return NULL;
+ goto BAIL;
info = png_create_info_struct (png);
if (info == NULL)
@@ -343,8 +340,10 @@ read_png (png_rw_ptr read_func,
png_set_read_fn (png, closure, read_func);
- if (setjmp (png_jmpbuf (png)))
+ if (setjmp (png_jmpbuf (png))) {
+ surface = (cairo_surface_t*) &_cairo_surface_nil_read_error;
goto BAIL;
+ }
png_read_info (png, info);
@@ -402,13 +401,22 @@ read_png (png_rw_ptr read_func,
surface = cairo_image_surface_create_for_data (data,
CAIRO_FORMAT_ARGB32,
png_width, png_height, stride);
+ if (surface->status)
+ goto BAIL;
+
_cairo_image_surface_assume_ownership_of_data ((cairo_image_surface_t*)surface);
data = NULL;
BAIL:
- free (row_pointers);
- free (data);
- png_destroy_read_struct (&png, &info, NULL);
+ if (row_pointers)
+ free (row_pointers);
+ if (data)
+ free (data);
+ if (png)
+ png_destroy_read_struct (&png, &info, NULL);
+
+ if (surface->status)
+ _cairo_error (surface->status);
return surface;
}
@@ -431,8 +439,13 @@ stdio_read_func (png_structp png, png_bytep data, png_size_t size)
* given PNG file.
*
* Return value: a new #cairo_surface_t initialized with the contents
- * of the PNG file or %NULL if the file is not a valid PNG file or
- * memory could not be allocated for the operation.
+ * of the PNG file, or a "nil" surface if any error occurred. A nil
+ * surface can be checked for with cairo_surface_status(surface) which
+ * may return one of the following values:
+ *
+ * CAIRO_STATUS_NO_MEMORY
+ * CAIRO_STATUS_FILE_NOT_FOUND
+ * CAIRO_STATUS_READ_ERROR
**/
cairo_surface_t *
cairo_image_surface_create_from_png (const char *filename)
@@ -441,8 +454,19 @@ cairo_image_surface_create_from_png (const char *filename)
cairo_surface_t *surface;
fp = fopen (filename, "rb");
- if (fp == NULL)
- return NULL;
+ if (fp == NULL) {
+ switch (errno) {
+ case ENOMEM:
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ case ENOENT:
+ _cairo_error (CAIRO_STATUS_FILE_NOT_FOUND);
+ return (cairo_surface_t*) &_cairo_surface_nil_file_not_found;
+ default:
+ _cairo_error (CAIRO_STATUS_READ_ERROR);
+ return (cairo_surface_t*) &_cairo_surface_nil_read_error;
+ }
+ }
surface = read_png (stdio_read_func, fp);
@@ -489,6 +513,6 @@ cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func,
png_closure.read_func = read_func;
png_closure.closure = closure;
- return read_png (stream_read_func, &closure);
+ return read_png (stream_read_func, &png_closure);
}
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 0464b5a0a..0b2962c28 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -89,8 +89,10 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
cairo_ps_surface_t *surface;
surface = malloc (sizeof (cairo_ps_surface_t));
- if (surface == NULL)
- return NULL;
+ if (surface == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
_cairo_surface_init (&surface->base, &cairo_ps_surface_backend);
@@ -103,9 +105,10 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
surface->current_page = _cairo_meta_surface_create (width,
height);
- if (surface->current_page == NULL) {
+ if (surface->current_page->status) {
free (surface);
- return NULL;
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
}
_cairo_array_init (&surface->pages, sizeof (cairo_surface_t *));
@@ -122,8 +125,10 @@ cairo_ps_surface_create (const char *filename,
cairo_output_stream_t *stream;
stream = _cairo_output_stream_create_for_file (filename);
- if (stream == NULL)
- return NULL;
+ if (stream == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
return _cairo_ps_surface_create_for_stream_internal (stream,
width_in_points,
@@ -139,23 +144,16 @@ cairo_ps_surface_create_for_stream (cairo_write_func_t write_func,
cairo_output_stream_t *stream;
stream = _cairo_output_stream_create (write_func, closure);
- if (stream == NULL)
- return NULL;
+ if (stream == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
return _cairo_ps_surface_create_for_stream_internal (stream,
width_in_points,
height_in_points);
}
-static cairo_surface_t *
-_cairo_ps_surface_create_similar (void *abstract_src,
- cairo_content_t content,
- int width,
- int height)
-{
- return NULL;
-}
-
static cairo_status_t
_cairo_ps_surface_finish (void *abstract_surface)
{
@@ -316,7 +314,7 @@ _cairo_ps_surface_show_page (void *abstract_surface)
_cairo_array_append (&surface->pages, &surface->current_page, 1);
surface->current_page = _cairo_meta_surface_create (surface->width,
surface->height);
- if (surface->current_page == NULL)
+ if (surface->current_page->status)
return CAIRO_STATUS_NO_MEMORY;
return CAIRO_STATUS_SUCCESS;
@@ -453,7 +451,7 @@ _cairo_ps_surface_fill_path (cairo_operator_t operator,
}
static const cairo_surface_backend_t cairo_ps_surface_backend = {
- _cairo_ps_surface_create_similar,
+ NULL, /* create_similar */
_cairo_ps_surface_finish,
NULL, /* acquire_source_image */
NULL, /* release_source_image */
@@ -652,7 +650,7 @@ emit_image (cairo_ps_surface_t *surface,
cairo_image_surface_t *image,
cairo_matrix_t *matrix)
{
- cairo_status_t status = CAIRO_STATUS_NO_MEMORY;
+ cairo_status_t status;
unsigned char *rgb, *compressed;
unsigned long rgb_size, compressed_size;
cairo_surface_t *opaque;
@@ -663,13 +661,18 @@ emit_image (cairo_ps_surface_t *surface,
/* PostScript can not represent the alpha channel, so we blend the
current image over a white RGB surface to eliminate it. */
+ if (image->base.status)
+ return image->base.status;
+
opaque = _cairo_surface_create_similar_solid (&image->base,
CAIRO_CONTENT_COLOR,
image->width,
image->height,
CAIRO_COLOR_WHITE);
- if (opaque == NULL)
+ if (opaque->status) {
+ status = CAIRO_STATUS_NO_MEMORY;
goto bail0;
+ }
_cairo_pattern_init_for_surface (&pattern.surface, &image->base);
@@ -687,8 +690,10 @@ emit_image (cairo_ps_surface_t *surface,
rgb_size = 3 * image->width * image->height;
rgb = malloc (rgb_size);
- if (rgb == NULL)
+ if (rgb == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
goto bail1;
+ }
i = 0;
for (y = 0; y < image->height; y++) {
@@ -701,8 +706,10 @@ emit_image (cairo_ps_surface_t *surface,
}
compressed = compress_dup (rgb, rgb_size, &compressed_size);
- if (compressed == NULL)
+ if (compressed == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
goto bail2;
+ }
/* matrix transforms from user space to image space. We need to
* transform from device space to image space to compensate for
@@ -1242,7 +1249,7 @@ _ps_output_render_fallbacks (cairo_surface_t *surface,
height = ps_output->parent->height * ps_output->parent->y_dpi / 72;
image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
- if (image == NULL)
+ if (image->status)
return CAIRO_STATUS_NO_MEMORY;
status = _cairo_surface_fill_rectangle (image,
@@ -1278,8 +1285,10 @@ _ps_output_surface_create (cairo_ps_surface_t *parent)
ps_output_surface_t *ps_output;
ps_output = malloc (sizeof (ps_output_surface_t));
- if (ps_output == NULL)
- return NULL;
+ if (ps_output == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
_cairo_surface_init (&ps_output->base, &ps_output_backend);
ps_output->parent = parent;
@@ -1301,7 +1310,7 @@ _cairo_ps_surface_render_page (cairo_ps_surface_t *surface,
page_number);
ps_output = _ps_output_surface_create (surface);
- if (ps_output == NULL)
+ if (ps_output->status)
return CAIRO_STATUS_NO_MEMORY;
status = _cairo_meta_surface_replay (page, ps_output);
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 17d51303b..af92c0104 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -58,15 +58,6 @@ ImageDataReleaseFunc(void *info, const void *data, size_t size)
}
}
-static cairo_surface_t *
-_cairo_quartz_surface_create_similar (void *abstract_src,
- cairo_content_t content,
- int width,
- int height)
-{
- return NULL;
-}
-
static cairo_status_t
_cairo_quartz_surface_finish(void *abstract_surface)
{
@@ -133,6 +124,11 @@ _cairo_quartz_surface_acquire_source_image(void *abstract_surface,
CAIRO_FORMAT_ARGB32,
surface->width,
surface->height, rowBytes);
+ if (surface->image->base.status) {
+ /* XXX: I assume we're leaking memory here, but I don't know
+ * the right call to use to clean up from CGImageCreate. */
+ return CAIRO_STATUS_NO_MEMORY;
+ }
*image_out = surface->image;
*image_extra = NULL;
@@ -156,6 +152,7 @@ _cairo_quartz_surface_acquire_dest_image(void *abstract_surface,
image_rect->height = surface->image->height;
*image_out = surface->image;
+ *image_extra = NULL;
return CAIRO_STATUS_SUCCESS;
}
@@ -209,7 +206,7 @@ _cairo_quartz_surface_get_extents (void *abstract_surface,
}
static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
- _cairo_quartz_surface_create_similar,
+ NULL, /* create_similar */
_cairo_quartz_surface_finish,
_cairo_quartz_surface_acquire_source_image,
NULL, /* release_source_image */
@@ -234,8 +231,10 @@ cairo_surface_t *cairo_quartz_surface_create(CGContextRef context,
cairo_quartz_surface_t *surface;
surface = malloc(sizeof(cairo_quartz_surface_t));
- if (surface == NULL)
- return NULL;
+ if (surface == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return &_cairo_surface_nil;
+ }
_cairo_surface_init(&surface->base, &cairo_quartz_surface_backend);
diff --git a/src/cairo-quartz.h b/src/cairo-quartz.h
index 6f59f6a79..dd929b297 100644
--- a/src/cairo-quartz.h
+++ b/src/cairo-quartz.h
@@ -46,9 +46,9 @@
CAIRO_BEGIN_DECLS
cairo_surface_t *
-cairo_quartz_surface_create ( CGContextRef context,
- int width,
- int height);
+cairo_quartz_surface_create (CGContextRef context,
+ int width,
+ int height);
CAIRO_END_DECLS
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 75f887c1f..11fbc6092 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -40,6 +40,97 @@
#include "cairoint.h"
#include "cairo-gstate-private.h"
+const cairo_surface_t _cairo_surface_nil = {
+ &cairo_image_surface_backend, /* backend */
+ -1, /* ref_count */
+ CAIRO_STATUS_NO_MEMORY, /* status */
+ FALSE, /* finished */
+ { 0, /* size */
+ 0, /* num_elements */
+ 0, /* element_size */
+ NULL, /* elements */
+ }, /* user_data */
+ 0.0, /* device_x_offset */
+ 0.0, /* device_y_offset */
+ 0, /* next_clip_serial */
+ 0 /* current_clip_serial */
+};
+
+const cairo_surface_t _cairo_surface_nil_file_not_found = {
+ &cairo_image_surface_backend, /* backend */
+ -1, /* ref_count */
+ CAIRO_STATUS_FILE_NOT_FOUND, /* status */
+ FALSE, /* finished */
+ { 0, /* size */
+ 0, /* num_elements */
+ 0, /* element_size */
+ NULL, /* elements */
+ }, /* user_data */
+ 0.0, /* device_x_offset */
+ 0.0, /* device_y_offset */
+ 0, /* next_clip_serial */
+ 0 /* current_clip_serial */
+};
+
+const cairo_surface_t _cairo_surface_nil_read_error = {
+ &cairo_image_surface_backend, /* backend */
+ -1, /* ref_count */
+ CAIRO_STATUS_READ_ERROR, /* status */
+ FALSE, /* finished */
+ { 0, /* size */
+ 0, /* num_elements */
+ 0, /* element_size */
+ NULL, /* elements */
+ }, /* user_data */
+ 0.0, /* device_x_offset */
+ 0.0, /* device_y_offset */
+ 0, /* next_clip_serial */
+ 0 /* current_clip_serial */
+};
+
+/**
+ * _cairo_surface_set_error:
+ * @surface: a surface
+ * @status: a status value indicating an error, (eg. not
+ * CAIRO_STATUS_SUCCESS)
+ *
+ * Sets surface->status to @status and calls _cairo_error;
+ *
+ * All assignments of an error status to surface->status should happen
+ * through _cairo_surface_set_error() or else _cairo_error() should be
+ * called immediately after the assignment.
+ *
+ * The purpose of this function is to allow the user to set a
+ * breakpoint in _cairo_error() to generate a stack trace for when the
+ * user causes cairo to detect an error.
+ **/
+static void
+_cairo_surface_set_error (cairo_surface_t *surface,
+ cairo_status_t status)
+{
+ surface->status = status;
+
+ _cairo_error (status);
+}
+
+/**
+ * cairo_surface_status:
+ * @surface: a #cairo_surface_t
+ *
+ * Checks whether an error has previously occurred for this
+ * surface.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_STATUS_NULL_POINTER,
+ * %CAIRO_STATUS_NO_MEMORY, %CAIRO_STATUS_READ_ERROR,
+ * %CAIRO_STATUS_INVALID_CONTENT, %CAIRO_STATUS_INVALUE_FORMAT, or
+ * %CAIRO_STATUS_INVALID_VISUAL.
+ **/
+cairo_status_t
+cairo_surface_status (cairo_surface_t *surface)
+{
+ return surface->status;
+}
+
void
_cairo_surface_init (cairo_surface_t *surface,
const cairo_surface_backend_t *backend)
@@ -47,6 +138,7 @@ _cairo_surface_init (cairo_surface_t *surface,
surface->backend = backend;
surface->ref_count = 1;
+ surface->status = CAIRO_STATUS_SUCCESS;
surface->finished = FALSE;
_cairo_user_data_array_init (&surface->user_data);
@@ -64,10 +156,15 @@ _cairo_surface_create_similar_scratch (cairo_surface_t *other,
int width,
int height)
{
- if (other == NULL)
- return NULL;
+ cairo_format_t format = _cairo_format_from_content (content);
- return other->backend->create_similar (other, content, width, height);
+ if (other->status)
+ return (cairo_surface_t*) &_cairo_surface_nil;
+
+ if (other->backend->create_similar)
+ return other->backend->create_similar (other, content, width, height);
+ else
+ return cairo_image_surface_create (format, width, height);
}
/**
@@ -81,9 +178,13 @@ _cairo_surface_create_similar_scratch (cairo_surface_t *other,
* existing surface. The new surface will use the same backend as
* @other unless that is not possible for some reason.
*
- * Return value: a pointer to the newly allocated surface, or NULL in
- * the case of errors. The caller owns the surface and should call
- * cairo_surface_destroy when done with it.
+ * Return value: a pointer to the newly allocated surface. The caller
+ * owns the surface and should call cairo_surface_destroy when done
+ * with it.
+ *
+ * This function always returns a valid pointer, but it will return a
+ * pointer to a "nil" surface if @other is already in an error state
+ * or any other error occurs.
**/
cairo_surface_t *
cairo_surface_create_similar (cairo_surface_t *other,
@@ -91,12 +192,13 @@ cairo_surface_create_similar (cairo_surface_t *other,
int width,
int height)
{
- if (other == NULL)
- return NULL;
+ if (other->status)
+ return (cairo_surface_t*) &_cairo_surface_nil;
- /* XXX: Really need to make this kind of thing pass through _cairo_error. */
- if (! CAIRO_CONTENT_VALID (content))
- return NULL;
+ if (! CAIRO_CONTENT_VALID (content)) {
+ _cairo_error (CAIRO_STATUS_INVALID_CONTENT);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
return _cairo_surface_create_similar_solid (other, content,
width, height,
@@ -112,20 +214,21 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other,
{
cairo_status_t status;
cairo_surface_t *surface;
- cairo_format_t format = _cairo_format_from_content (content);
surface = _cairo_surface_create_similar_scratch (other, content,
width, height);
-
- if (surface == NULL)
- surface = cairo_image_surface_create (format, width, height);
+ if (surface->status) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
status = _cairo_surface_fill_rectangle (surface,
CAIRO_OPERATOR_SOURCE, color,
0, 0, width, height);
if (status) {
cairo_surface_destroy (surface);
- return NULL;
+ _cairo_error (status);
+ return (cairo_surface_t*) &_cairo_surface_nil;
}
return surface;
@@ -148,6 +251,9 @@ cairo_surface_reference (cairo_surface_t *surface)
if (surface == NULL)
return;
+ if (surface->ref_count == (unsigned int)-1)
+ return;
+
surface->ref_count++;
}
@@ -157,6 +263,9 @@ cairo_surface_destroy (cairo_surface_t *surface)
if (surface == NULL)
return;
+ if (surface->ref_count == (unsigned int)-1)
+ return;
+
surface->ref_count--;
if (surface->ref_count)
return;
@@ -178,36 +287,37 @@ slim_hidden_def(cairo_surface_destroy);
* that cairo will no longer access the drawable, which can be freed.
* After calling cairo_surface_finish() the only valid operations on a
* surface are getting and setting user data and referencing and
- * destroying it. Further drawing the the surface will not affect the
- * surface but set the surface status to
- * CAIRO_STATUS_SURFACE_FINISHED.
+ * destroying it. Further drawing to the surface will not affect the
+ * surface but will instead trigger a CAIRO_STATUS_SURFACE_FINISHED
+ * error.
*
* When the last call to cairo_surface_destroy() decreases the
* reference count to zero, cairo will call cairo_surface_finish() if
* it hasn't been called already, before freeing the resources
* associated with the surface.
- *
- * Return value: CAIRO_STATUS_SUCCESS if the surface was finished
- * successfully, otherwise CAIRO_STATUS_NO_MEMORY or
- * CAIRO_STATUS_WRITE_ERROR.
**/
-cairo_status_t
+void
cairo_surface_finish (cairo_surface_t *surface)
{
cairo_status_t status;
- if (surface->finished)
- return CAIRO_STATUS_SURFACE_FINISHED;
+ if (surface->finished) {
+ _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
+ return;
+ }
- if (surface->backend->finish) {
- status = surface->backend->finish (surface);
- if (status)
- return status;
+ if (surface->backend->finish == NULL) {
+ surface->finished = TRUE;
+ return;
+ }
+
+ status = surface->backend->finish (surface);
+ if (status) {
+ _cairo_surface_set_error (surface, status);
+ return;
}
surface->finished = TRUE;
-
- return CAIRO_STATUS_SUCCESS;
}
/**
@@ -252,11 +362,37 @@ cairo_surface_set_user_data (cairo_surface_t *surface,
void *user_data,
cairo_destroy_func_t destroy)
{
+ if (surface->ref_count == -1)
+ return CAIRO_STATUS_NO_MEMORY;
+
return _cairo_user_data_array_set_data (&surface->user_data,
key, user_data, destroy);
}
/**
+ * cairo_surface_get_font_options:
+ * @surface: a #cairo_surface_t
+ * @options: a #cairo_font_options_t object into which to store
+ * the retrieved options. All existing values are overwritten
+ *
+ * Retrieves the default font rendering options for the surface.
+ * This allows display surfaces to report the correct subpixel order
+ * for rendering on them, print surfaces to disable hinting of
+ * metrics and so forth. The result can then be used with
+ * cairo_scaled_font_create().
+ **/
+void
+cairo_surface_get_font_options (cairo_surface_t *surface,
+ cairo_font_options_t *options)
+{
+ if (!surface->finished && surface->backend->get_font_options) {
+ surface->backend->get_font_options (surface, options);
+ } else {
+ _cairo_font_options_init_default (options);
+ }
+}
+
+/**
* cairo_surface_set_device_offset:
* @surface: a #cairo_surface_t
* @x_offset: the offset in the X direction, in device units
@@ -279,6 +415,16 @@ cairo_surface_set_device_offset (cairo_surface_t *surface,
double x_offset,
double y_offset)
{
+ if (surface->status) {
+ _cairo_surface_set_error (surface, surface->status);
+ return;
+ }
+
+ if (surface->finished) {
+ _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
+ return;
+ }
+
surface->device_x_offset = x_offset;
surface->device_y_offset = y_offset;
}
@@ -453,7 +599,17 @@ typedef struct {
void *image_extra;
} fallback_state_t;
-static cairo_status_t
+/**
+ * _fallback_init:
+ *
+ * Acquire destination image surface needed for an image-based
+ * fallback.
+ *
+ * Return value: CAIRO_INT_STATUS_NOTHING_TO_DO if the extents are not
+ * visible, CAIRO_STATUS_SUCCESS if some portion is visible and all
+ * went well, or some error status otherwise.
+ **/
+static cairo_int_status_t
_fallback_init (fallback_state_t *state,
cairo_surface_t *dst,
int x,
@@ -461,6 +617,8 @@ _fallback_init (fallback_state_t *state,
int width,
int height)
{
+ cairo_status_t status;
+
state->extents.x = x;
state->extents.y = y;
state->extents.width = width;
@@ -468,15 +626,29 @@ _fallback_init (fallback_state_t *state,
state->dst = dst;
- return _cairo_surface_acquire_dest_image (dst, &state->extents,
- &state->image, &state->image_rect, &state->image_extra);
+ status = _cairo_surface_acquire_dest_image (dst, &state->extents,
+ &state->image, &state->image_rect,
+ &state->image_extra);
+ if (status)
+ return status;
+
+ /* XXX: This NULL value tucked away in state->image is a rather
+ * ugly interface. Cleaner would be to push the
+ * CAIRO_INT_STATUS_NOTHING_TO_DO value down into
+ * _cairo_surface_acquire_dest_image and its backend
+ * counterparts. */
+ if (state->image == NULL)
+ return CAIRO_INT_STATUS_NOTHING_TO_DO;
+
+ return CAIRO_STATUS_SUCCESS;
}
static void
-_fallback_cleanup (fallback_state_t *state)
+_fallback_fini (fallback_state_t *state)
{
_cairo_surface_release_dest_image (state->dst, &state->extents,
- state->image, &state->image_rect, state->image_extra);
+ state->image, &state->image_rect,
+ state->image_extra);
}
static cairo_status_t
@@ -497,18 +669,20 @@ _fallback_composite (cairo_operator_t operator,
cairo_status_t status;
status = _fallback_init (&state, dst, dst_x, dst_y, width, height);
- if (status || !state.image)
+ if (status) {
+ if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
+ return CAIRO_STATUS_SUCCESS;
return status;
+ }
- state.image->base.backend->composite (operator, src, mask,
- &state.image->base,
- src_x, src_y, mask_x, mask_y,
- dst_x - state.image_rect.x,
- dst_y - state.image_rect.y,
- width, height);
+ status = state.image->base.backend->composite (operator, src, mask,
+ &state.image->base,
+ src_x, src_y, mask_x, mask_y,
+ dst_x - state.image_rect.x,
+ dst_y - state.image_rect.y,
+ width, height);
+ _fallback_fini (&state);
- _fallback_cleanup (&state);
-
return status;
}
@@ -528,6 +702,9 @@ _cairo_surface_composite (cairo_operator_t operator,
{
cairo_int_status_t status;
+ if (dst->status)
+ return dst->status;
+
if (dst->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
@@ -561,6 +738,9 @@ _cairo_surface_fill_rectangle (cairo_surface_t *surface,
{
cairo_rectangle_t rect;
+ if (surface->status)
+ return surface->status;
+
if (surface->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
@@ -609,16 +789,19 @@ _fallback_fill_rectangles (cairo_surface_t *surface,
}
status = _fallback_init (&state, surface, x1, y1, x2 - x1, y2 - y1);
- if (status || !state.image)
+ if (status) {
+ if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
+ return CAIRO_STATUS_SUCCESS;
return status;
+ }
/* If the fetched image isn't at 0,0, we need to offset the rectangles */
if (state.image_rect.x != 0 || state.image_rect.y != 0) {
offset_rects = malloc (sizeof (cairo_rectangle_t) * num_rects);
- if (!offset_rects) {
+ if (offset_rects == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
- goto FAIL;
+ goto DONE;
}
for (i = 0; i < num_rects; i++) {
@@ -631,15 +814,15 @@ _fallback_fill_rectangles (cairo_surface_t *surface,
rects = offset_rects;
}
- state.image->base.backend->fill_rectangles (&state.image->base, operator, color,
- rects, num_rects);
+ status = state.image->base.backend->fill_rectangles (&state.image->base,
+ operator, color,
+ rects, num_rects);
- if (offset_rects)
- free (offset_rects);
+ free (offset_rects);
+
+ DONE:
+ _fallback_fini (&state);
- FAIL:
- _fallback_cleanup (&state);
-
return status;
}
@@ -652,6 +835,9 @@ _cairo_surface_fill_rectangles (cairo_surface_t *surface,
{
cairo_int_status_t status;
+ if (surface->status)
+ return surface->status;
+
if (surface->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
@@ -678,11 +864,11 @@ _cairo_surface_fill_path (cairo_operator_t operator,
cairo_fill_rule_t fill_rule,
double tolerance)
{
- if (dst->backend->fill_path)
- return dst->backend->fill_path (operator, pattern, dst, path,
- fill_rule, tolerance);
- else
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ if (dst->backend->fill_path)
+ return dst->backend->fill_path (operator, pattern, dst, path,
+ fill_rule, tolerance);
+ else
+ return CAIRO_INT_STATUS_UNSUPPORTED;
}
@@ -705,8 +891,11 @@ _fallback_composite_trapezoids (cairo_operator_t operator,
int i;
status = _fallback_init (&state, dst, dst_x, dst_y, width, height);
- if (status || !state.image)
+ if (status) {
+ if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
+ return CAIRO_STATUS_SUCCESS;
return status;
+ }
/* If the destination image isn't at 0,0, we need to offset the trapezoids */
@@ -718,7 +907,7 @@ _fallback_composite_trapezoids (cairo_operator_t operator,
offset_traps = malloc (sizeof (cairo_trapezoid_t) * num_traps);
if (!offset_traps) {
status = CAIRO_STATUS_NO_MEMORY;
- goto FAIL;
+ goto DONE;
}
for (i = 0; i < num_traps; i++) {
@@ -746,13 +935,12 @@ _fallback_composite_trapezoids (cairo_operator_t operator,
if (offset_traps)
free (offset_traps);
- FAIL:
- _fallback_cleanup (&state);
+ DONE:
+ _fallback_fini (&state);
return status;
}
-
cairo_status_t
_cairo_surface_composite_trapezoids (cairo_operator_t operator,
cairo_pattern_t *pattern,
@@ -768,6 +956,9 @@ _cairo_surface_composite_trapezoids (cairo_operator_t operator,
{
cairo_int_status_t status;
+ if (dst->status)
+ return dst->status;
+
if (dst->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
@@ -782,16 +973,19 @@ _cairo_surface_composite_trapezoids (cairo_operator_t operator,
return status;
}
- return _fallback_composite_trapezoids (operator, pattern, dst,
- src_x, src_y,
- dst_x, dst_y,
- width, height,
- traps, num_traps);
+ return _fallback_composite_trapezoids (operator, pattern, dst,
+ src_x, src_y,
+ dst_x, dst_y,
+ width, height,
+ traps, num_traps);
}
cairo_status_t
_cairo_surface_copy_page (cairo_surface_t *surface)
{
+ if (surface->status)
+ return surface->status;
+
if (surface->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
@@ -799,12 +993,15 @@ _cairo_surface_copy_page (cairo_surface_t *surface)
if (surface->backend->copy_page == NULL)
return CAIRO_STATUS_SUCCESS;
- return surface->backend->copy_page (surface);
+ return surface->backend->copy_page (surface);
}
cairo_status_t
_cairo_surface_show_page (cairo_surface_t *surface)
{
+ if (surface->status)
+ return surface->status;
+
if (surface->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
@@ -834,15 +1031,19 @@ _cairo_surface_get_current_clip_serial (cairo_surface_t *surface)
* _cairo_surface_allocate_clip_serial:
* @surface: the #cairo_surface_t to allocate a serial number from
*
- * Each surface has a separate set of clipping serial numbers,
- * and this function allocates one from the specified surface.
- * As zero is reserved for the special no-clipping case,
- * this function will not return that.
+ * Each surface has a separate set of clipping serial numbers, and
+ * this function allocates one from the specified surface. As zero is
+ * reserved for the special no-clipping case, this function will not
+ * return that except for an in-error surface, (ie. surface->status !=
+ * CAIRO_STATUS_SUCCESS).
*/
unsigned int
_cairo_surface_allocate_clip_serial (cairo_surface_t *surface)
{
unsigned int serial;
+
+ if (surface->status)
+ return 0;
if ((serial = ++(surface->next_clip_serial)) == 0)
serial = ++(surface->next_clip_serial);
@@ -863,6 +1064,9 @@ _cairo_surface_reset_clip (cairo_surface_t *surface)
{
cairo_status_t status;
+ if (surface->status)
+ return surface->status;
+
if (surface->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
@@ -882,6 +1086,7 @@ _cairo_surface_reset_clip (cairo_surface_t *surface)
if (status)
return status;
}
+
return CAIRO_STATUS_SUCCESS;
}
@@ -900,12 +1105,16 @@ _cairo_surface_set_clip_region (cairo_surface_t *surface,
pixman_region16_t *region,
unsigned int serial)
{
+ if (surface->status)
+ return surface->status;
+
if (surface->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
assert (surface->backend->set_clip_region != NULL);
surface->current_clip_serial = serial;
+
return surface->backend->set_clip_region (surface, region);
}
@@ -915,6 +1124,9 @@ _cairo_surface_intersect_clip_path (cairo_surface_t *surface,
cairo_fill_rule_t fill_rule,
double tolerance)
{
+ if (surface->status)
+ return surface->status;
+
if (surface->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
@@ -945,7 +1157,6 @@ _cairo_surface_set_clip_path_recursive (cairo_surface_t *surface,
clip_path->tolerance);
}
-
/**
* _cairo_surface_set_clip_path:
* @surface: the #cairo_surface_t to reset the clip on
@@ -964,6 +1175,9 @@ _cairo_surface_set_clip_path (cairo_surface_t *surface,
{
cairo_status_t status;
+ if (surface->status)
+ return surface->status;
+
if (surface->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
@@ -1004,6 +1218,9 @@ cairo_status_t
_cairo_surface_get_extents (cairo_surface_t *surface,
cairo_rectangle_t *rectangle)
{
+ if (surface->status)
+ return surface->status;
+
if (surface->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
@@ -1026,6 +1243,9 @@ _cairo_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
{
cairo_status_t status;
+ if (dst->status)
+ return dst->status;
+
if (dst->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 385297ee2..15dd96b3d 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -46,6 +46,9 @@
#ifndef CLEARTYPE_QUALITY
#define CLEARTYPE_QUALITY 5
#endif
+#ifndef TT_PRIM_CSPLINE
+#define TT_PRIM_CSPLINE 3
+#endif
const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend;
@@ -55,6 +58,7 @@ typedef struct {
cairo_scaled_font_t base;
LOGFONTW logfont;
+ cairo_font_options_t options;
BYTE quality;
@@ -162,35 +166,41 @@ _compute_transform (cairo_win32_scaled_font_t *scaled_font,
cairo_matrix_init_identity (&scaled_font->device_to_logical);
}
+static cairo_bool_t
+_have_cleartype_quality (void)
+{
+ OSVERSIONINFO version_info;
+
+ version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
+
+ if (!GetVersionEx (&version_info)) {
+ _cairo_win32_print_gdi_error ("_have_cleartype_quality");
+ return FALSE;
+ }
+
+ return (version_info.dwMajorVersion > 5 ||
+ (version_info.dwMajorVersion == 5 &&
+ version_info.dwMinorVersion >= 1)); /* XP or newer */
+}
+
+
static BYTE
_get_system_quality (void)
{
BOOL font_smoothing;
+ UINT smoothing_type;
if (!SystemParametersInfo (SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0)) {
_cairo_win32_print_gdi_error ("_get_system_quality");
- return FALSE;
+ return DEFAULT_QUALITY;
}
if (font_smoothing) {
- OSVERSIONINFO version_info;
-
- version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
-
- if (!GetVersionEx (&version_info)) {
- _cairo_win32_print_gdi_error ("_get_system_quality");
- return FALSE;
- }
-
- if (version_info.dwMajorVersion > 5 ||
- (version_info.dwMajorVersion == 5 &&
- version_info.dwMinorVersion >= 1)) { /* XP or newer */
- UINT smoothing_type;
-
+ if (_have_cleartype_quality ()) {
if (!SystemParametersInfo (SPI_GETFONTSMOOTHINGTYPE,
0, &smoothing_type, 0)) {
_cairo_win32_print_gdi_error ("_get_system_quality");
- return FALSE;
+ return DEFAULT_QUALITY;
}
if (smoothing_type == FE_FONTSMOOTHINGCLEARTYPE)
@@ -204,19 +214,48 @@ _get_system_quality (void)
}
static cairo_scaled_font_t *
-_win32_scaled_font_create (LOGFONTW *logfont,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm)
+_win32_scaled_font_create (LOGFONTW *logfont,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ const cairo_font_options_t *options)
{
cairo_win32_scaled_font_t *f;
cairo_matrix_t scale;
f = malloc (sizeof(cairo_win32_scaled_font_t));
- if (f == NULL)
- return NULL;
+ if (f == NULL)
+ return NULL;
f->logfont = *logfont;
- f->quality = _get_system_quality ();
+ 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
+ * cairo_font_options_t. We use the 'antialias' field to set
+ * the 'quality'.
+ *
+ * XXX: The other option we could pay attention to, but don't
+ * here is the hint_metrics options.
+ */
+ if (options->antialias == CAIRO_ANTIALIAS_DEFAULT)
+ f->quality = _get_system_quality ();
+ else {
+ switch (options->antialias) {
+ case CAIRO_ANTIALIAS_NONE:
+ f->quality = NONANTIALIASED_QUALITY;
+ break;
+ case CAIRO_ANTIALIAS_GRAY:
+ f->quality = ANTIALIASED_QUALITY;
+ break;
+ case CAIRO_ANTIALIAS_SUBPIXEL:
+ if (_have_cleartype_quality ())
+ f->quality = CLEARTYPE_QUALITY;
+ else
+ f->quality = ANTIALIASED_QUALITY;
+ break;
+ }
+ }
+
f->em_square = 0;
f->scaled_hfont = NULL;
f->unscaled_hfont = NULL;
@@ -390,12 +429,13 @@ _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,
- cairo_scaled_font_t **scaled_font_out)
+_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)
{
LOGFONTW logfont;
cairo_scaled_font_t *scaled_font;
@@ -456,7 +496,7 @@ _cairo_win32_scaled_font_create (const char *family,
if (!logfont.lfFaceName)
return CAIRO_STATUS_NO_MEMORY;
- scaled_font = _win32_scaled_font_create (&logfont, font_matrix, ctm);
+ scaled_font = _win32_scaled_font_create (&logfont, font_matrix, ctm, options);
if (!scaled_font)
return CAIRO_STATUS_NO_MEMORY;
@@ -918,7 +958,7 @@ _draw_glyphs_on_surface (cairo_win32_surface_t *surface,
_finish_glyphs (&state);
cairo_win32_scaled_font_done_font (&scaled_font->base);
FAIL1:
- RestoreDC (surface->dc, 1);
+ RestoreDC (surface->dc, -1);
return status;
}
@@ -969,7 +1009,7 @@ _compute_a8_mask (cairo_win32_surface_t *mask_surface)
image8 = (cairo_image_surface_t *)cairo_image_surface_create (CAIRO_FORMAT_A8,
image24->width, image24->height);
- if (!image8)
+ if (image8->base.status)
return NULL;
for (i = 0; i < image24->height; i++) {
@@ -1042,7 +1082,7 @@ _cairo_win32_scaled_font_show_glyphs (void *abstract_font,
RECT r;
tmp_surface = (cairo_win32_surface_t *)_cairo_win32_surface_create_dib (CAIRO_FORMAT_ARGB32, width, height);
- if (!tmp_surface)
+ if (tmp_surface->base.status)
return CAIRO_STATUS_NO_MEMORY;
r.left = 0;
@@ -1262,15 +1302,16 @@ _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,
- cairo_scaled_font_t **font)
+_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_t *font_face = abstract_face;
*font = _win32_scaled_font_create (&font_face->logfont,
- font_matrix, ctm);
+ font_matrix, ctm, options);
if (*font)
return CAIRO_STATUS_SUCCESS;
else
@@ -1303,8 +1344,10 @@ cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont)
cairo_win32_font_face_t *font_face;
font_face = malloc (sizeof (cairo_win32_font_face_t));
- if (!font_face)
- return NULL;
+ if (!font_face) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_font_face_t *)&_cairo_font_face_nil;
+ }
font_face->logfont = *logfont;
@@ -1346,6 +1389,11 @@ cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font,
HFONT old_hfont = NULL;
int old_mode;
+ if (scaled_font->status) {
+ _cairo_scaled_font_set_error (scaled_font, scaled_font->status);
+ return scaled_font->status;
+ }
+
hfont = _win32_scaled_font_get_scaled_hfont ((cairo_win32_scaled_font_t *)scaled_font);
if (!hfont)
return CAIRO_STATUS_NO_MEMORY;
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 148d22bcd..f92012451 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -243,23 +243,29 @@ _cairo_win32_surface_create_for_dc (HDC original_dc,
int width,
int height)
{
+ cairo_status_t status;
cairo_win32_surface_t *surface;
char *bits;
int rowstride;
surface = malloc (sizeof (cairo_win32_surface_t));
- if (!surface)
- return NULL;
+ if (surface == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return &_cairo_surface_nil;
+ }
- if (_create_dc_and_bitmap (surface, original_dc, format,
- width, height,
- &bits, &rowstride) != CAIRO_STATUS_SUCCESS)
+ status = _create_dc_and_bitmap (surface, original_dc, format,
+ width, height,
+ &bits, &rowstride);
+ if (status)
goto FAIL;
surface->image = cairo_image_surface_create_for_data (bits, format,
width, height, rowstride);
- if (!surface->image)
+ if (surface->image->status) {
+ status = CAIRO_STATUS_NO_MEMORY;
goto FAIL;
+ }
surface->format = format;
@@ -283,9 +289,14 @@ _cairo_win32_surface_create_for_dc (HDC original_dc,
}
if (surface)
free (surface);
-
- return NULL;
-
+
+ if (status == CAIRO_STATUS_NO_MEMORY) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return &_cairo_surface_nil;
+ } else {
+ _cairo_error (status);
+ return &_cairo_surface_nil;
+ }
}
static cairo_surface_t *
@@ -359,7 +370,7 @@ _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface,
content,
width,
height);
- if (!local)
+ if (local->base.status)
return CAIRO_STATUS_NO_MEMORY;
if (!BitBlt (local->dc,
@@ -892,12 +903,16 @@ cairo_win32_surface_create (HDC hdc)
*/
if (GetClipBox (hdc, &rect) == ERROR) {
_cairo_win32_print_gdi_error ("cairo_win32_surface_create");
- return NULL;
+ /* XXX: Can we make a more reasonable guess at the error cause here? */
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return &_cairo_surface_nil;
}
surface = malloc (sizeof (cairo_win32_surface_t));
- if (!surface)
- return NULL;
+ if (surface == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return &_cairo_surface_nil;
+ }
surface->image = NULL;
surface->format = CAIRO_FORMAT_RGB24;
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 1b0e2aaee..b743cf4d8 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -256,6 +256,10 @@ _cairo_xcb_surface_create_similar (void *abstract_src,
cairo_xcb_surface_create_with_xrender_format (dpy, d,
&xrender_format,
width, height);
+ if (surface->base.status) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
surface->owns_pixmap = TRUE;
@@ -477,10 +481,10 @@ _get_image_surface (cairo_xcb_surface_t *surface,
masks.blue_mask = surface->visual->blue_mask;
} else if (surface->has_format) {
masks.bpp = bpp;
- masks.red_mask = surface->format.direct.red_mask << surface->format.direct.red_shift;
- masks.green_mask = surface->format.direct.green_mask << surface->format.direct.green_shift;
- masks.blue_mask = surface->format.direct.blue_mask << surface->format.direct.blue_shift;
- masks.alpha_mask = surface->format.direct.alpha_mask << surface->format.direct.alpha_shift;
+ masks.red_mask = (unsigned long)surface->format.direct.red_mask << surface->format.direct.red_shift;
+ masks.green_mask = (unsigned long)surface->format.direct.green_mask << surface->format.direct.green_shift;
+ masks.blue_mask = (unsigned long)surface->format.direct.blue_mask << surface->format.direct.blue_shift;
+ masks.alpha_mask = (unsigned long)surface->format.direct.alpha_mask << surface->format.direct.alpha_shift;
} else {
masks.bpp = bpp;
masks.red_mask = 0;
@@ -503,6 +507,8 @@ _get_image_surface (cairo_xcb_surface_t *surface,
x2 - x1,
y2 - y1,
bytes_per_line);
+ if (image->base.status)
+ goto FAIL;
} else {
/*
* XXX This can't work. We must convert the data to one of the
@@ -510,12 +516,14 @@ _get_image_surface (cairo_xcb_surface_t *surface,
* which takes data in an arbitrary format and converts it
* to something supported by that library.
*/
- image = _cairo_image_surface_create_with_masks (data,
- &masks,
- x2 - x1,
- y2 - y1,
- bytes_per_line);
-
+ image = (cairo_image_surface_t *)
+ _cairo_image_surface_create_with_masks (data,
+ &masks,
+ x2 - x1,
+ y2 - y1,
+ bytes_per_line);
+ if (image->base.status)
+ goto FAIL;
}
/* Let the surface take ownership of the data */
@@ -523,6 +531,10 @@ _get_image_surface (cairo_xcb_surface_t *surface,
*image_out = image;
return CAIRO_STATUS_SUCCESS;
+
+ FAIL:
+ free (data);
+ return CAIRO_STATUS_NO_MEMORY;
}
static void
@@ -570,6 +582,7 @@ _cairo_xcb_surface_acquire_source_image (void *abstract_surfa
return status;
*image_out = image;
+ *image_extra = NULL;
return CAIRO_STATUS_SUCCESS;
}
@@ -598,6 +611,7 @@ _cairo_xcb_surface_acquire_dest_image (void *abstract_surface
return status;
*image_out = image;
+ *image_extra = NULL;
return CAIRO_STATUS_SUCCESS;
}
@@ -637,11 +651,14 @@ _cairo_xcb_surface_clone_similar (void *abstract_surface,
} else if (_cairo_surface_is_image (src)) {
cairo_image_surface_t *image_src = (cairo_image_surface_t *)src;
cairo_content_t content = _cairo_content_from_format (image_src->format);
+
+ if (surface->base.status)
+ return surface->base.status;
clone = (cairo_xcb_surface_t *)
_cairo_xcb_surface_create_similar (surface, content,
image_src->width, image_src->height);
- if (clone == NULL)
+ if (clone->base.status)
return CAIRO_STATUS_NO_MEMORY;
_draw_image_surface (clone, image_src, 0, 0);
@@ -888,9 +905,9 @@ _cairo_xcb_surface_composite (cairo_operator_t operator,
}
if (mask)
- _cairo_pattern_release_surface (&dst->base, &mask->base, &mask_attr);
+ _cairo_pattern_release_surface (mask_pattern, &mask->base, &mask_attr);
- _cairo_pattern_release_surface (&dst->base, &src->base, &src_attr);
+ _cairo_pattern_release_surface (src_pattern, &src->base, &src_attr);
return status;
}
@@ -977,7 +994,7 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t operator,
render_src_y + attributes.y_offset,
num_traps, (XCBRenderTRAP *) traps);
- _cairo_pattern_release_surface (&dst->base, &src->base, &attributes);
+ _cairo_pattern_release_surface (pattern, &src->base, &attributes);
return status;
}
@@ -1062,8 +1079,10 @@ _cairo_xcb_surface_create_internal (XCBConnection *dpy,
cairo_xcb_surface_t *surface;
surface = malloc (sizeof (cairo_xcb_surface_t));
- if (surface == NULL)
- return NULL;
+ if (surface == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
_cairo_surface_init (&surface->base, &cairo_xcb_surface_backend);
diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h
new file mode 100644
index 000000000..966a08d18
--- /dev/null
+++ b/src/cairo-xlib-private.h
@@ -0,0 +1,54 @@
+/* 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.
+ */
+
+#ifndef CAIRO_XLIB_PRIVATE_H
+#define CAIRO_XLIB_PRIVATE_H
+
+#include "cairoint.h"
+#include "cairo-xlib.h"
+
+typedef struct _cairo_xlib_screen_info cairo_xlib_screen_info_t;
+
+struct _cairo_xlib_screen_info {
+ cairo_xlib_screen_info_t *next;
+
+ Display *display;
+ Screen *screen;
+ cairo_bool_t has_render;
+
+ cairo_font_options_t font_options;
+};
+
+cairo_private cairo_xlib_screen_info_t *
+_cairo_xlib_screen_info_get (Display *display, Screen *screen);
+
+#endif /* CAIRO_XLIB_PRIVATE_H */
diff --git a/src/cairo-xlib-screen.c b/src/cairo-xlib-screen.c
new file mode 100644
index 000000000..6a4efdbd4
--- /dev/null
+++ b/src/cairo-xlib-screen.c
@@ -0,0 +1,346 @@
+/* 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.
+ *
+ * Partially on code from xftdpy.c
+ *
+ * Copyright © 2000 Keith Packard
+ *
+ * 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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.
+ */
+#include <stdlib.h>
+#include <string.h>
+
+#include "cairo-xlib-private.h"
+
+#include <fontconfig/fontconfig.h>
+
+#include <X11/Xlibint.h> /* For XESetCloseDisplay */
+#include <X11/extensions/Xrender.h>
+
+static int
+parse_boolean (const char *v)
+{
+ char c0, c1;
+
+ c0 = *v;
+ if (c0 == 't' || c0 == 'T' || c0 == 'y' || c0 == 'Y' || c0 == '1')
+ return 1;
+ if (c0 == 'f' || c0 == 'F' || c0 == 'n' || c0 == 'N' || c0 == '0')
+ return 0;
+ if (c0 == 'o')
+ {
+ c1 = v[1];
+ if (c1 == 'n' || c1 == 'N')
+ return 1;
+ if (c1 == 'f' || c1 == 'F')
+ return 0;
+ }
+
+ return -1;
+}
+
+static cairo_bool_t
+get_boolean_default (Display *dpy,
+ const char *option,
+ cairo_bool_t *value)
+{
+ char *v;
+ int i;
+
+ v = XGetDefault (dpy, "Xft", option);
+ if (v) {
+ i = parse_boolean (v);
+ if (i >= 0) {
+ *value = i;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static cairo_bool_t
+get_integer_default (Display *dpy,
+ const char *option,
+ int *value)
+{
+ int i;
+ char *v, *e;
+
+ v = XGetDefault (dpy, "Xft", option);
+ if (v) {
+ if (FcNameConstant ((FcChar8 *) v, value))
+ return TRUE;
+
+ i = strtol (v, &e, 0);
+ if (e != v)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* Old versions of fontconfig didn't have these options */
+#ifndef FC_HINT_NONE
+#define FC_HINT_NONE 0
+#define FC_HINT_SLIGHT 1
+#define FC_HINT_MEDIUM 2
+#define FC_HINT_FULL 3
+#endif
+
+static void
+_cairo_xlib_init_screen_font_options (cairo_xlib_screen_info_t *info)
+{
+ cairo_bool_t xft_hinting;
+ cairo_bool_t xft_antialias;
+ int xft_hintstyle;
+ int xft_rgba;
+ cairo_antialias_t antialias;
+ cairo_subpixel_order_t subpixel_order;
+ cairo_hint_style_t hint_style;
+
+ if (!get_boolean_default (info->display, "antialias", &xft_antialias))
+ xft_antialias = TRUE;
+
+ if (!get_boolean_default (info->display, "hinting", &xft_hinting))
+ xft_hinting = TRUE;
+
+ if (!get_integer_default (info->display, "hintstyle", &xft_hintstyle))
+ xft_hintstyle = FC_HINT_FULL;
+
+ if (!get_integer_default (info->display, "rgba", &xft_rgba))
+ {
+ xft_rgba = FC_RGBA_UNKNOWN;
+
+#if RENDER_MAJOR > 0 || RENDER_MINOR >= 6
+ if (info->has_render)
+ {
+ int render_order = XRenderQuerySubpixelOrder (info->display,
+ XScreenNumberOfScreen (info->screen));
+
+ switch (render_order)
+ {
+ default:
+ case SubPixelUnknown:
+ xft_rgba = FC_RGBA_UNKNOWN;
+ break;
+ case SubPixelHorizontalRGB:
+ xft_rgba = FC_RGBA_RGB;
+ break;
+ case SubPixelHorizontalBGR:
+ xft_rgba = FC_RGBA_BGR;
+ break;
+ case SubPixelVerticalRGB:
+ xft_rgba = FC_RGBA_VRGB;
+ break;
+ case SubPixelVerticalBGR:
+ xft_rgba = FC_RGBA_VBGR;
+ break;
+ case SubPixelNone:
+ xft_rgba = FC_RGBA_NONE;
+ break;
+ }
+ }
+#endif
+ }
+
+ if (xft_hinting) {
+ switch (xft_hintstyle) {
+ case FC_HINT_NONE:
+ hint_style = CAIRO_HINT_STYLE_NONE;
+ break;
+ case FC_HINT_SLIGHT:
+ hint_style = CAIRO_HINT_STYLE_SLIGHT;
+ break;
+ case FC_HINT_MEDIUM:
+ hint_style = CAIRO_HINT_STYLE_MEDIUM;
+ break;
+ case FC_HINT_FULL:
+ hint_style = CAIRO_HINT_STYLE_FULL;
+ break;
+ default:
+ hint_style = CAIRO_HINT_STYLE_DEFAULT;
+ }
+ } else {
+ hint_style = CAIRO_HINT_STYLE_NONE;
+ }
+
+ switch (xft_rgba) {
+ case FC_RGBA_RGB:
+ subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
+ break;
+ case FC_RGBA_BGR:
+ subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
+ break;
+ case FC_RGBA_VRGB:
+ subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
+ break;
+ case FC_RGBA_VBGR:
+ subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
+ break;
+ case FC_RGBA_UNKNOWN:
+ case FC_RGBA_NONE:
+ default:
+ subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
+ }
+
+ if (xft_antialias) {
+ if (subpixel_order == CAIRO_SUBPIXEL_ORDER_DEFAULT)
+ antialias = CAIRO_ANTIALIAS_GRAY;
+ else
+ antialias = CAIRO_ANTIALIAS_SUBPIXEL;
+ } else {
+ antialias = CAIRO_ANTIALIAS_NONE;
+ }
+
+ _cairo_font_options_init_default (&info->font_options);
+ cairo_font_options_set_hint_style (&info->font_options, hint_style);
+ cairo_font_options_set_antialias (&info->font_options, antialias);
+ cairo_font_options_set_subpixel_order (&info->font_options, subpixel_order);
+}
+
+CAIRO_MUTEX_DECLARE(_xlib_screen_mutex);
+
+static cairo_xlib_screen_info_t *_cairo_xlib_screen_list;
+
+static int
+_cairo_xlib_close_display (Display *dpy, XExtCodes *codes)
+{
+ cairo_xlib_screen_info_t *info;
+ cairo_xlib_screen_info_t **prev;
+
+ /*
+ * Unhook from the global list
+ */
+ CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
+
+ for (prev = &_cairo_xlib_screen_list; (info = *prev); prev = &(*prev)->next) {
+ if (info->display == dpy) {
+ *prev = info->next;
+ free (info);
+ if (!*prev)
+ break;
+ }
+ }
+ CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
+
+ return 0;
+}
+
+
+cairo_private cairo_xlib_screen_info_t *
+_cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
+{
+ cairo_xlib_screen_info_t *info;
+ cairo_xlib_screen_info_t **prev;
+ int event_base, error_base;
+ XExtCodes *codes;
+ cairo_bool_t seen_display = FALSE;
+
+ /* There is an apparent deadlock between this mutex and the
+ * mutex for the display, but it's actually safe. For the
+ * app to call XCloseDisplay() while any other thread is
+ * inside this function would be an error in the logic
+ * app, and the CloseDisplay hook is the only other place we
+ * acquire this mutex.
+ */
+ CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
+
+ for (prev = &_cairo_xlib_screen_list; (info = *prev); prev = &(*prev)->next)
+ {
+ if (info->display == dpy) {
+ seen_display = TRUE;
+ if (info->screen == screen)
+ {
+ /*
+ * MRU the list
+ */
+ if (prev != &_cairo_xlib_screen_list)
+ {
+ *prev = info->next;
+ info->next = _cairo_xlib_screen_list;
+ _cairo_xlib_screen_list = info;
+ }
+ break;
+ }
+ }
+ }
+
+ if (info)
+ goto out;
+
+ info = malloc (sizeof (cairo_xlib_screen_info_t));
+ if (!info)
+ goto out;
+
+ if (!seen_display) {
+ codes = XAddExtension (dpy);
+ if (!codes) {
+ free (info);
+ info = NULL;
+ goto out;
+ }
+
+ XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display);
+ }
+
+ info->display = dpy;
+ info->screen = screen;
+ info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
+ (XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0));
+
+ _cairo_xlib_init_screen_font_options (info);
+
+ info->next = _cairo_xlib_screen_list;
+ _cairo_xlib_screen_list = info;
+
+ out:
+ CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
+
+ return info;
+}
+
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index caec2b9dd..5f26a2f49 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1,6 +1,7 @@
/* 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
@@ -38,6 +39,7 @@
#include "cairo-xlib.h"
#include "cairo-xlib-xrender.h"
#include "cairo-xlib-test.h"
+#include "cairo-xlib-private.h"
#include <X11/extensions/Xrender.h>
/* Xlib doesn't define a typedef, so define one ourselves */
@@ -70,8 +72,11 @@ struct _cairo_xlib_surface {
cairo_surface_t base;
Display *dpy;
+ cairo_xlib_screen_info_t *screen_info;
+
GC gc;
Drawable drawable;
+ Screen *screen;
cairo_bool_t owns_pixmap;
Visual *visual;
@@ -186,7 +191,6 @@ _cairo_xlib_surface_create_similar (void *abstract_src,
{
cairo_xlib_surface_t *src = abstract_src;
Display *dpy = src->dpy;
- int scr;
Pixmap pix;
cairo_xlib_surface_t *surface;
cairo_format_t format = _cairo_format_from_content (content);
@@ -201,16 +205,18 @@ _cairo_xlib_surface_create_similar (void *abstract_src,
return cairo_image_surface_create (format, width, height);
}
- scr = DefaultScreen (dpy);
-
- pix = XCreatePixmap (dpy, DefaultRootWindow (dpy),
+ pix = XCreatePixmap (dpy, RootWindowOfScreen (src->screen),
width <= 0 ? 1 : width, height <= 0 ? 1 : height,
depth);
surface = (cairo_xlib_surface_t *)
- cairo_xlib_surface_create_with_xrender_format (dpy, pix,
+ cairo_xlib_surface_create_with_xrender_format (dpy, pix, src->screen,
xrender_format,
width, height);
+ if (surface->base.status) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
surface->owns_pixmap = TRUE;
@@ -407,10 +413,10 @@ _get_image_surface (cairo_xlib_surface_t *surface,
masks.blue_mask = surface->visual->blue_mask;
} else if (surface->format) {
masks.bpp = ximage->bits_per_pixel;
- masks.red_mask = surface->format->direct.redMask << surface->format->direct.red;
- masks.green_mask = surface->format->direct.greenMask << surface->format->direct.green;
- masks.blue_mask = surface->format->direct.blueMask << surface->format->direct.blue;
- masks.alpha_mask = surface->format->direct.alphaMask << surface->format->direct.alpha;
+ masks.red_mask = (unsigned long)surface->format->direct.redMask << surface->format->direct.red;
+ masks.green_mask = (unsigned long)surface->format->direct.greenMask << surface->format->direct.green;
+ masks.blue_mask = (unsigned long)surface->format->direct.blueMask << surface->format->direct.blue;
+ masks.alpha_mask = (unsigned long)surface->format->direct.alphaMask << surface->format->direct.alpha;
} else {
masks.bpp = ximage->bits_per_pixel;
masks.red_mask = 0;
@@ -428,11 +434,14 @@ _get_image_surface (cairo_xlib_surface_t *surface,
*/
if (_CAIRO_MASK_FORMAT (&masks, &format))
{
- image = (cairo_image_surface_t *) cairo_image_surface_create_for_data ((unsigned char *) ximage->data,
- format,
- ximage->width,
- ximage->height,
- ximage->bytes_per_line);
+ image = (cairo_image_surface_t*)
+ cairo_image_surface_create_for_data ((unsigned char *) ximage->data,
+ format,
+ ximage->width,
+ ximage->height,
+ ximage->bytes_per_line);
+ if (image->base.status)
+ goto FAIL;
}
else
{
@@ -442,11 +451,14 @@ _get_image_surface (cairo_xlib_surface_t *surface,
* which takes data in an arbitrary format and converts it
* to something supported by that library.
*/
- image = _cairo_image_surface_create_with_masks ((unsigned char *) ximage->data,
- &masks,
- ximage->width,
- ximage->height,
- ximage->bytes_per_line);
+ image = (cairo_image_surface_t*)
+ _cairo_image_surface_create_with_masks ((unsigned char *) ximage->data,
+ &masks,
+ ximage->width,
+ ximage->height,
+ ximage->bytes_per_line);
+ if (image->base.status)
+ goto FAIL;
}
/* Let the surface take ownership of the data */
@@ -456,6 +468,10 @@ _get_image_surface (cairo_xlib_surface_t *surface,
*image_out = image;
return CAIRO_STATUS_SUCCESS;
+
+ FAIL:
+ XDestroyImage (ximage);
+ return CAIRO_STATUS_NO_MEMORY;
}
static void
@@ -573,6 +589,7 @@ _cairo_xlib_surface_acquire_source_image (void *abstract_surf
return status;
*image_out = image;
+ *image_extra = NULL;
return CAIRO_STATUS_SUCCESS;
}
@@ -601,7 +618,8 @@ _cairo_xlib_surface_acquire_dest_image (void *abstract_surfac
return status;
*image_out = image;
-
+ *image_extra = NULL;
+
return CAIRO_STATUS_SUCCESS;
}
@@ -620,6 +638,18 @@ _cairo_xlib_surface_release_dest_image (void *abstract_surface
cairo_surface_destroy (&image->base);
}
+/*
+ * Return whether two xlib surfaces share the same
+ * screen. Both core and Render drawing require this
+ * when using multiple drawables in an operation.
+ */
+static cairo_bool_t
+_cairo_xlib_surface_same_screen (cairo_xlib_surface_t *dst,
+ cairo_xlib_surface_t *src)
+{
+ return dst->dpy == src->dpy && dst->screen == src->screen;
+}
+
static cairo_status_t
_cairo_xlib_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
@@ -631,7 +661,7 @@ _cairo_xlib_surface_clone_similar (void *abstract_surface,
if (src->backend == surface->base.backend ) {
cairo_xlib_surface_t *xlib_src = (cairo_xlib_surface_t *)src;
- if (xlib_src->dpy == surface->dpy) {
+ if (_cairo_xlib_surface_same_screen (surface, xlib_src)) {
*clone_out = src;
cairo_surface_reference (src);
@@ -644,7 +674,7 @@ _cairo_xlib_surface_clone_similar (void *abstract_surface,
clone = (cairo_xlib_surface_t *)
_cairo_xlib_surface_create_similar (surface, content,
image_src->width, image_src->height);
- if (clone == NULL)
+ if (clone->base.status)
return CAIRO_STATUS_NO_MEMORY;
_draw_image_surface (clone, image_src, 0, 0);
@@ -793,24 +823,26 @@ _cairo_xlib_surface_set_attributes (cairo_xlib_surface_t *surface,
* a tile in a GC.
*/
static cairo_bool_t
-_surfaces_compatible (cairo_xlib_surface_t *src,
- cairo_xlib_surface_t *dst)
+_surfaces_compatible (cairo_xlib_surface_t *dst,
+ cairo_xlib_surface_t *src)
{
-
- if (src->dpy != dst->dpy)
+ /* same screen */
+ if (!_cairo_xlib_surface_same_screen (dst, src))
return FALSE;
- /* We must not only match depth and format/visual, we must also
- * match screen. We don't have that information, and rather than
- * asking for it round-trip, we'll just return FALSE if we have
- * more than one screen on the display.
- */
- if (ScreenCount (dst->dpy) > 1)
+ /* same depth (for core) */
+ if (src->depth != dst->depth)
return FALSE;
+
+ /* if Render is supported, match picture formats */
+ if (src->format != NULL && src->format == dst->format)
+ return TRUE;
- return (src->depth == dst->depth &&
- ((src->format != NULL && src->format == dst->format) ||
- (src->visual != NULL && src->visual == dst->visual)));
+ /* Without Render, match visuals instead */
+ if (src->visual == dst->visual)
+ return TRUE;
+
+ return FALSE;
}
static cairo_bool_t
@@ -880,7 +912,7 @@ _categorize_composite_operation (cairo_xlib_surface_t *dst,
{
if (!dst->buggy_repeat)
return DO_RENDER;
-
+
if (src_pattern->type == CAIRO_PATTERN_SURFACE)
{
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *)src_pattern;
@@ -901,7 +933,12 @@ _categorize_composite_operation (cairo_xlib_surface_t *dst,
if (operator == CAIRO_OPERATOR_OVER && _surface_has_alpha (src))
return DO_UNSUPPORTED;
- if (src->dpy == dst->dpy && !_surfaces_compatible (src, dst))
+ /* If these are on the same screen but otherwise incompatible,
+ * make a copy as core drawing can't cross depths and doesn't
+ * work rightacross visuals of the same depth
+ */
+ if (_cairo_xlib_surface_same_screen (dst, src) &&
+ !_surfaces_compatible (dst, src))
return DO_UNSUPPORTED;
}
}
@@ -1304,6 +1341,18 @@ _cairo_xlib_surface_get_extents (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
+static void
+_cairo_xlib_surface_get_font_options (void *abstract_surface,
+ cairo_font_options_t *options)
+{
+ cairo_xlib_surface_t *surface = abstract_surface;
+
+ *options = surface->screen_info->font_options;
+
+ if (_surface_has_alpha (surface) && options->antialias == CAIRO_ANTIALIAS_SUBPIXEL)
+ options->antialias = CAIRO_ANTIALIAS_GRAY;
+}
+
static cairo_int_status_t
_cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
@@ -1334,7 +1383,9 @@ static const cairo_surface_backend_t cairo_xlib_surface_backend = {
_cairo_xlib_surface_set_clip_region,
NULL, /* intersect_clip_path */
_cairo_xlib_surface_get_extents,
- _cairo_xlib_surface_show_glyphs
+ _cairo_xlib_surface_show_glyphs,
+ NULL, /* fill_path */
+ _cairo_xlib_surface_get_font_options
};
/**
@@ -1354,6 +1405,7 @@ _cairo_surface_is_xlib (cairo_surface_t *surface)
static cairo_surface_t *
_cairo_xlib_surface_create_internal (Display *dpy,
Drawable drawable,
+ Screen *screen,
Visual *visual,
XRenderPictFormat *format,
int width,
@@ -1361,17 +1413,28 @@ _cairo_xlib_surface_create_internal (Display *dpy,
int depth)
{
cairo_xlib_surface_t *surface;
+ cairo_xlib_screen_info_t *screen_info;
+
+ screen_info = _cairo_xlib_screen_info_get (dpy, screen);
+ if (screen_info == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
surface = malloc (sizeof (cairo_xlib_surface_t));
- if (surface == NULL)
- return NULL;
+ if (surface == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
_cairo_surface_init (&surface->base, &cairo_xlib_surface_backend);
surface->dpy = dpy;
+ surface->screen_info = screen_info;
surface->gc = NULL;
surface->drawable = drawable;
+ surface->screen = screen;
surface->owns_pixmap = FALSE;
surface->use_pixmap = 0;
surface->width = width;
@@ -1380,20 +1443,17 @@ _cairo_xlib_surface_create_internal (Display *dpy,
if (format) {
depth = format->depth;
} else if (visual) {
- int i, j, k;
+ int j, k;
/* This is ugly, but we have to walk over all visuals
* for the display to find the depth.
*/
- for (i = 0; i < ScreenCount (dpy); i++) {
- Screen *screen = ScreenOfDisplay (dpy, i);
- for (j = 0; j < screen->ndepths; j++) {
- Depth *d = &screen->depths[j];
- for (k = 0; k < d->nvisuals; k++) {
- if (&d->visuals[k] == visual) {
- depth = d->depth;
- goto found;
- }
+ for (j = 0; j < screen->ndepths; j++) {
+ Depth *d = &screen->depths[j];
+ for (k = 0; k < d->nvisuals; k++) {
+ if (&d->visuals[k] == visual) {
+ depth = d->depth;
+ goto found;
}
}
}
@@ -1441,6 +1501,29 @@ _cairo_xlib_surface_create_internal (Display *dpy,
return (cairo_surface_t *) surface;
}
+static Screen *
+_cairo_xlib_screen_from_visual (Display *dpy, Visual *visual)
+{
+ int s;
+ int d;
+ int v;
+ Screen *screen;
+ Depth *depth;
+
+ for (s = 0; s < ScreenCount (dpy); s++) {
+ screen = ScreenOfDisplay (dpy, s);
+ if (visual == DefaultVisualOfScreen (screen))
+ return screen;
+ for (d = 0; d < screen->ndepths; d++) {
+ depth = &screen->depths[d];
+ for (v = 0; v < depth->nvisuals; v++)
+ if (visual == &depth->visuals[v])
+ return screen;
+ }
+ }
+ return NULL;
+}
+
/**
* cairo_xlib_surface_create:
* @dpy: an X Display
@@ -1468,7 +1551,14 @@ cairo_xlib_surface_create (Display *dpy,
int width,
int height)
{
- return _cairo_xlib_surface_create_internal (dpy, drawable,
+ Screen *screen = _cairo_xlib_screen_from_visual (dpy, visual);
+
+ if (screen == NULL) {
+ _cairo_error (CAIRO_STATUS_INVALID_VISUAL);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
+
+ return _cairo_xlib_surface_create_internal (dpy, drawable, screen,
visual, NULL, width, height, 0);
}
@@ -1476,6 +1566,7 @@ cairo_xlib_surface_create (Display *dpy,
* cairo_xlib_surface_create_for_bitmap:
* @dpy: an X Display
* @bitmap: an X Drawable, (a depth-1 Pixmap)
+ * @screen: the X Screen associated with @bitmap
* @width: the current width of @bitmap.
* @height: the current height of @bitmap.
*
@@ -1487,10 +1578,11 @@ cairo_xlib_surface_create (Display *dpy,
cairo_surface_t *
cairo_xlib_surface_create_for_bitmap (Display *dpy,
Pixmap bitmap,
+ Screen *screen,
int width,
int height)
{
- return _cairo_xlib_surface_create_internal (dpy, bitmap,
+ return _cairo_xlib_surface_create_internal (dpy, bitmap, screen,
NULL, NULL, width, height, 1);
}
@@ -1498,6 +1590,7 @@ cairo_xlib_surface_create_for_bitmap (Display *dpy,
* cairo_xlib_surface_create_with_xrender_format:
* @dpy: an X Display
* @drawable: an X Drawable, (a Pixmap or a Window)
+ * @screen: the X Screen associated with @drawable
* @format: the picture format to use for drawing to @drawable. The depth
* of @format must match the depth of the drawable.
* @width: the current width of @drawable.
@@ -1516,11 +1609,12 @@ cairo_xlib_surface_create_for_bitmap (Display *dpy,
cairo_surface_t *
cairo_xlib_surface_create_with_xrender_format (Display *dpy,
Drawable drawable,
+ Screen *screen,
XRenderPictFormat *format,
int width,
int height)
{
- return _cairo_xlib_surface_create_internal (dpy, drawable,
+ return _cairo_xlib_surface_create_internal (dpy, drawable, screen,
NULL, format, width, height, 0);
}
@@ -1554,20 +1648,73 @@ cairo_xlib_surface_set_size (cairo_surface_t *surface,
xlib_surface->width = width;
xlib_surface->height = height;
}
+/**
+ * cairo_xlib_surface_set_drawable:
+ * @surface: a #cairo_surface_t for the XLib backend
+ * @drawable: the new drawable for the surface
+ *
+ * Informs cairo of a new X Drawable underlying the
+ * surface. The drawable must match the display, screen
+ * and format of the existing drawable or the application
+ * will get X protocol errors and will probably terminate.
+ * No checks are done by this function to ensure this
+ * compatibility.
+ **/
+void
+cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface,
+ Drawable drawable,
+ int width,
+ int height)
+{
+ cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *)abstract_surface;
+
+ /* XXX: How do we want to handle this error case? */
+ if (! _cairo_surface_is_xlib (abstract_surface))
+ return;
+
+ /* XXX: and what about this case? */
+ if (surface->owns_pixmap)
+ return;
+
+ if (surface->drawable != drawable) {
+ if (surface->dst_picture)
+ XRenderFreePicture (surface->dpy, surface->dst_picture);
+
+ if (surface->src_picture)
+ XRenderFreePicture (surface->dpy, surface->src_picture);
+
+ surface->dst_picture = None;
+ surface->src_picture = None;
+
+ surface->drawable = drawable;
+ }
+ surface->width = width;
+ surface->height = height;
+}
/* RENDER glyphset cache code */
typedef struct glyphset_cache {
cairo_cache_t base;
- struct glyphset_cache *next;
+
Display *display;
- XRenderPictFormat *a8_pict_format;
- GlyphSet glyphset;
Glyph counter;
+
+ XRenderPictFormat *a1_pict_format;
+ GlyphSet a1_glyphset;
+
+ XRenderPictFormat *a8_pict_format;
+ GlyphSet a8_glyphset;
+
+ XRenderPictFormat *argb32_pict_format;
+ GlyphSet argb32_glyphset;
+
+ struct glyphset_cache *next;
} glyphset_cache_t;
typedef struct {
cairo_glyph_cache_key_t key;
+ GlyphSet glyphset;
Glyph glyph;
} glyphset_cache_entry_t;
@@ -1577,6 +1724,14 @@ _next_xlib_glyph (glyphset_cache_t *cache)
return ++(cache->counter);
}
+static cairo_bool_t
+_native_byte_order_lsb (void)
+{
+ int x = 1;
+
+ return *((char *) &x) == 1;
+}
+
static cairo_status_t
_xlib_glyphset_cache_create_entry (void *abstract_cache,
void *abstract_key,
@@ -1586,6 +1741,7 @@ _xlib_glyphset_cache_create_entry (void *abstract_cache,
cairo_glyph_cache_key_t *key = abstract_key;
glyphset_cache_entry_t *entry;
XGlyphInfo glyph_info;
+ unsigned char *data;
cairo_status_t status;
@@ -1610,9 +1766,19 @@ _xlib_glyphset_cache_create_entry (void *abstract_cache,
entry->key = *key;
_cairo_unscaled_font_reference (entry->key.unscaled);
+ if (!im->image) {
+ entry->glyph = None;
+ entry->glyphset = None;
+ entry->key.base.memory = 0;
+
+ goto out;
+ }
+
entry->glyph = _next_xlib_glyph (cache);
- glyph_info.width = im->image ? im->image->stride : im->size.width;
+ data = im->image->data;
+
+ glyph_info.width = im->size.width;
glyph_info.height = im->size.height;
/*
@@ -1656,14 +1822,83 @@ _xlib_glyphset_cache_create_entry (void *abstract_cache,
glyph_info.xOff = 0;
glyph_info.yOff = 0;
- XRenderAddGlyphs (cache->display, cache->glyphset,
+ switch (im->image->format) {
+ case CAIRO_FORMAT_A1:
+ /* local bitmaps are always stored with bit == byte */
+ if (_native_byte_order_lsb() !=
+ (BitmapBitOrder (cache->display) == LSBFirst))
+ {
+ int c = im->image->stride * im->size.height;
+ unsigned char *d;
+ unsigned char *new, *n;
+
+ new = malloc (c);
+ if (!new)
+ return CAIRO_STATUS_NO_MEMORY;
+ n = new;
+ d = data;
+ while (c--)
+ {
+ char b = *d++;
+ b = ((b << 1) & 0xaa) | ((b >> 1) & 0x55);
+ b = ((b << 2) & 0xcc) | ((b >> 2) & 0x33);
+ b = ((b << 4) & 0xf0) | ((b >> 4) & 0x0f);
+ *n++ = b;
+ }
+ data = new;
+ }
+ entry->glyphset = cache->a1_glyphset;
+ break;
+ case CAIRO_FORMAT_A8:
+ entry->glyphset = cache->a8_glyphset;
+ break;
+ case CAIRO_FORMAT_ARGB32:
+ if (_native_byte_order_lsb() !=
+ (ImageByteOrder (cache->display) == LSBFirst))
+ {
+ int c = im->image->stride * im->size.height;
+ unsigned char *d;
+ unsigned char *new, *n;
+
+ new = malloc (c);
+ if (!new)
+ return CAIRO_STATUS_NO_MEMORY;
+ n = new;
+ d = data;
+ while ((c -= 4) >= 0)
+ {
+ n[3] = d[0];
+ n[2] = d[1];
+ n[1] = d[2];
+ n[0] = d[3];
+ d += 4;
+ n += 4;
+ }
+ data = new;
+ }
+ entry->glyphset = cache->argb32_glyphset;
+ break;
+ case CAIRO_FORMAT_RGB24:
+ default:
+ ASSERT_NOT_REACHED;
+ break;
+ }
+ /* XXX assume X server wants pixman padding. Xft assumes this as well */
+
+ XRenderAddGlyphs (cache->display, entry->glyphset,
&(entry->glyph), &(glyph_info), 1,
- im->image ? (char *) im->image->data : NULL,
- im->image ? glyph_info.height * glyph_info.width : 0);
+ (char *) data,
+ im->image->stride * glyph_info.height);
+
+ if (data != im->image->data)
+ free (data);
+
+ entry->key.base.memory = im->image->height * im->image->stride;
- entry->key.base.memory = im->image ? im->image->width * im->image->stride : 0;
+ out:
*return_entry = entry;
_cairo_unlock_global_image_glyph_cache ();
+
return CAIRO_STATUS_SUCCESS;
}
@@ -1681,7 +1916,8 @@ _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, cache->glyphset, &(entry->glyph), 1);
+ XRenderFreeGlyphs (cache->display, entry->glyphset,
+ &(entry->glyph), 1);
free (entry);
}
@@ -1719,9 +1955,10 @@ _get_glyphset_cache (Display *d)
* There should usually only be one, or a very small number, of
* displays. So we just do a linear scan.
*/
-
glyphset_cache_t *cache;
+ /* XXX: This is not thread-safe. Xft has example code to get
+ * per-display data via Xlib extension mechanisms. */
for (cache = _xlib_glyphset_caches; cache != NULL; cache = cache->next) {
if (cache->display == d)
return cache;
@@ -1738,8 +1975,14 @@ _get_glyphset_cache (Display *d)
cache->display = d;
cache->counter = 0;
+ cache->a1_pict_format = XRenderFindStandardFormat (d, PictStandardA1);
+ cache->a1_glyphset = XRenderCreateGlyphSet (d, cache->a1_pict_format);
+
cache->a8_pict_format = XRenderFindStandardFormat (d, PictStandardA8);
- cache->glyphset = XRenderCreateGlyphSet (d, cache->a8_pict_format);
+ cache->a8_glyphset = XRenderCreateGlyphSet (d, cache->a8_pict_format);
+
+ cache->argb32_pict_format = XRenderFindStandardFormat (d, PictStandardARGB32);
+ cache->argb32_glyphset = XRenderCreateGlyphSet (d, cache->argb32_pict_format);;
cache->next = _xlib_glyphset_caches;
_xlib_glyphset_caches = cache;
@@ -1755,6 +1998,28 @@ _get_glyphset_cache (Display *d)
#define N_STACK_BUF 1024
+static XRenderPictFormat *
+_select_text_mask_format (glyphset_cache_t *cache,
+ cairo_bool_t have_a1_glyphs,
+ cairo_bool_t have_a8_glyphs,
+ cairo_bool_t have_argb32_glyphs)
+{
+ if (have_a8_glyphs)
+ return cache->a8_pict_format;
+
+ if (have_a1_glyphs && have_argb32_glyphs)
+ return cache->a8_pict_format;
+
+ if (have_a1_glyphs)
+ return cache->a1_pict_format;
+
+ if (have_argb32_glyphs)
+ return cache->argb32_pict_format;
+
+ /* when there are no glyphs to draw, just pick something */
+ return cache->a8_pict_format;
+}
+
static cairo_status_t
_cairo_xlib_surface_show_glyphs32 (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
@@ -1774,10 +2039,13 @@ _cairo_xlib_surface_show_glyphs32 (cairo_scaled_font_t *scaled_font,
unsigned int *chars = NULL;
unsigned int stack_chars [N_STACK_BUF];
- int i;
+ int i, count;
int thisX, thisY;
int lastX = 0, lastY = 0;
+ cairo_bool_t have_a1, have_a8, have_argb32;
+ XRenderPictFormat *mask_format;
+
/* Acquire arrays of suitable sizes. */
if (num_glyphs < N_STACK_BUF) {
elts = stack_elts;
@@ -1794,19 +2062,42 @@ _cairo_xlib_surface_show_glyphs32 (cairo_scaled_font_t *scaled_font,
}
+ have_a1 = FALSE;
+ have_a8 = FALSE;
+ have_argb32 = FALSE;
+ count = 0;
+
for (i = 0; i < num_glyphs; ++i) {
- chars[i] = entries[i]->glyph;
- elts[i].chars = &(chars[i]);
- elts[i].nchars = 1;
- elts[i].glyphset = cache->glyphset;
+ GlyphSet glyphset;
+
+ if (!entries[i]->glyph)
+ continue;
+
+ glyphset = entries[i]->glyphset;
+
+ if (glyphset == cache->a1_glyphset)
+ have_a1 = TRUE;
+ else if (glyphset == cache->a8_glyphset)
+ have_a8 = TRUE;
+ else if (glyphset == cache->argb32_glyphset)
+ have_argb32 = TRUE;
+
+ chars[count] = entries[i]->glyph;
+ elts[count].chars = &(chars[count]);
+ elts[count].nchars = 1;
+ elts[count].glyphset = glyphset;
thisX = (int) floor (glyphs[i].x + 0.5);
thisY = (int) floor (glyphs[i].y + 0.5);
- elts[i].xOff = thisX - lastX;
- elts[i].yOff = thisY - lastY;
+ elts[count].xOff = thisX - lastX;
+ elts[count].yOff = thisY - lastY;
lastX = thisX;
lastY = thisY;
+ count++;
}
+ mask_format = _select_text_mask_format (cache,
+ have_a1, have_a8, have_argb32);
+
XRenderCompositeText32 (self->dpy,
_render_operator (operator),
src->src_picture,
@@ -1814,7 +2105,7 @@ _cairo_xlib_surface_show_glyphs32 (cairo_scaled_font_t *scaled_font,
cache->a8_pict_format,
source_x, source_y,
0, 0,
- elts, num_glyphs);
+ elts, count);
if (num_glyphs >= N_STACK_BUF) {
free (chars);
@@ -1851,10 +2142,13 @@ _cairo_xlib_surface_show_glyphs16 (cairo_scaled_font_t *scaled_font,
unsigned short *chars = NULL;
unsigned short stack_chars [N_STACK_BUF];
- int i;
+ int i, count;
int thisX, thisY;
int lastX = 0, lastY = 0;
+ cairo_bool_t have_a1, have_a8, have_argb32;
+ XRenderPictFormat *mask_format;
+
/* Acquire arrays of suitable sizes. */
if (num_glyphs < N_STACK_BUF) {
elts = stack_elts;
@@ -1871,27 +2165,50 @@ _cairo_xlib_surface_show_glyphs16 (cairo_scaled_font_t *scaled_font,
}
+ have_a1 = FALSE;
+ have_a8 = FALSE;
+ have_argb32 = FALSE;
+ count = 0;
+
for (i = 0; i < num_glyphs; ++i) {
- chars[i] = entries[i]->glyph;
- elts[i].chars = &(chars[i]);
- elts[i].nchars = 1;
- elts[i].glyphset = cache->glyphset;
+ GlyphSet glyphset;
+
+ if (!entries[i]->glyph)
+ continue;
+
+ glyphset = entries[i]->glyphset;
+
+ if (glyphset == cache->a1_glyphset)
+ have_a1 = TRUE;
+ else if (glyphset == cache->a8_glyphset)
+ have_a8 = TRUE;
+ else if (glyphset == cache->argb32_glyphset)
+ have_argb32 = TRUE;
+
+ chars[count] = entries[i]->glyph;
+ elts[count].chars = &(chars[count]);
+ elts[count].nchars = 1;
+ elts[count].glyphset = glyphset;
thisX = (int) floor (glyphs[i].x + 0.5);
thisY = (int) floor (glyphs[i].y + 0.5);
- elts[i].xOff = thisX - lastX;
- elts[i].yOff = thisY - lastY;
+ elts[count].xOff = thisX - lastX;
+ elts[count].yOff = thisY - lastY;
lastX = thisX;
lastY = thisY;
+ count++;
}
+ mask_format = _select_text_mask_format (cache,
+ have_a1, have_a8, have_argb32);
+
XRenderCompositeText16 (self->dpy,
_render_operator (operator),
src->src_picture,
self->dst_picture,
- cache->a8_pict_format,
+ mask_format,
source_x, source_y,
0, 0,
- elts, num_glyphs);
+ elts, count);
if (num_glyphs >= N_STACK_BUF) {
free (chars);
@@ -1927,10 +2244,16 @@ _cairo_xlib_surface_show_glyphs8 (cairo_scaled_font_t *scaled_font,
char *chars = NULL;
char stack_chars [N_STACK_BUF];
- int i;
+ int i, count;
int thisX, thisY;
int lastX = 0, lastY = 0;
+ cairo_bool_t have_a1, have_a8, have_argb32;
+ XRenderPictFormat *mask_format;
+
+ if (num_glyphs == 0)
+ return CAIRO_STATUS_SUCCESS;
+
/* Acquire arrays of suitable sizes. */
if (num_glyphs < N_STACK_BUF) {
elts = stack_elts;
@@ -1947,27 +2270,50 @@ _cairo_xlib_surface_show_glyphs8 (cairo_scaled_font_t *scaled_font,
}
+ have_a1 = FALSE;
+ have_a8 = FALSE;
+ have_argb32 = FALSE;
+ count = 0;
+
for (i = 0; i < num_glyphs; ++i) {
- chars[i] = entries[i]->glyph;
- elts[i].chars = &(chars[i]);
- elts[i].nchars = 1;
- elts[i].glyphset = cache->glyphset;
+ GlyphSet glyphset;
+
+ if (!entries[i]->glyph)
+ continue;
+
+ glyphset = entries[i]->glyphset;
+
+ if (glyphset == cache->a1_glyphset)
+ have_a1 = TRUE;
+ else if (glyphset == cache->a8_glyphset)
+ have_a8 = TRUE;
+ else if (glyphset == cache->argb32_glyphset)
+ have_argb32 = TRUE;
+
+ chars[count] = entries[i]->glyph;
+ elts[count].chars = &(chars[count]);
+ elts[count].nchars = 1;
+ elts[count].glyphset = glyphset;
thisX = (int) floor (glyphs[i].x + 0.5);
thisY = (int) floor (glyphs[i].y + 0.5);
- elts[i].xOff = thisX - lastX;
- elts[i].yOff = thisY - lastY;
+ elts[count].xOff = thisX - lastX;
+ elts[count].yOff = thisY - lastY;
lastX = thisX;
lastY = thisY;
+ count++;
}
+ mask_format = _select_text_mask_format (cache,
+ have_a1, have_a8, have_argb32);
+
XRenderCompositeText8 (self->dpy,
_render_operator (operator),
src->src_picture,
self->dst_picture,
- cache->a8_pict_format,
+ mask_format,
source_x, source_y,
0, 0,
- elts, num_glyphs);
+ elts, count);
if (num_glyphs >= N_STACK_BUF) {
free (chars);
@@ -2052,7 +2398,9 @@ _cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
/* Work out the index size to use. */
elt_size = 8;
- _cairo_scaled_font_get_glyph_cache_key (scaled_font, &key);
+ status = _cairo_scaled_font_get_glyph_cache_key (scaled_font, &key);
+ if (status)
+ goto UNLOCK;
for (i = 0; i < num_glyphs; ++i) {
key.index = glyphs[i].index;
diff --git a/src/cairo-xlib-xrender.h b/src/cairo-xlib-xrender.h
index 08a8624e2..71b239772 100644
--- a/src/cairo-xlib-xrender.h
+++ b/src/cairo-xlib-xrender.h
@@ -48,6 +48,7 @@ CAIRO_BEGIN_DECLS
cairo_surface_t *
cairo_xlib_surface_create_with_xrender_format (Display *dpy,
Drawable drawable,
+ Screen *screen,
XRenderPictFormat *format,
int width,
int height);
diff --git a/src/cairo-xlib.h b/src/cairo-xlib.h
index 3fe285fdb..5cdf1378b 100644
--- a/src/cairo-xlib.h
+++ b/src/cairo-xlib.h
@@ -55,6 +55,7 @@ cairo_xlib_surface_create (Display *dpy,
cairo_surface_t *
cairo_xlib_surface_create_for_bitmap (Display *dpy,
Pixmap bitmap,
+ Screen *screen,
int width,
int height);
@@ -63,6 +64,12 @@ cairo_xlib_surface_set_size (cairo_surface_t *surface,
int width,
int height);
+void
+cairo_xlib_surface_set_drawable (cairo_surface_t *surface,
+ Drawable drawable,
+ int width,
+ int height);
+
CAIRO_END_DECLS
#else /* CAIRO_HAS_XLIB_SURFACE */
diff --git a/src/cairo.c b/src/cairo.c
index 56da06eaa..b4fc5464f 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -62,34 +62,52 @@ static const cairo_t cairo_nil = {
* a bit of a pain, but it should be easy to always catch as long as
* one adds a new test case to test a trigger of the new status value.
*/
-#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_PATTERN_TYPE_MISMATCH
+#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_FILE_NOT_FOUND
/**
* _cairo_error:
+ * @status: a status value indicating an error, (eg. not
+ * CAIRO_STATUS_SUCCESS)
+ *
+ * Checks that status is an error status, but does nothing else.
+ *
+ * All assignments of an error status to any user-visible object
+ * within the cairo application should result in a call to
+ * _cairo_error().
+ *
+ * The purpose of this function is to allow the user to set a
+ * breakpoint in _cairo_error() to generate a stack trace for when the
+ * user causes cairo to detect an error.
+ **/
+void
+_cairo_error (cairo_status_t status)
+{
+ assert (status > CAIRO_STATUS_SUCCESS &&
+ status <= CAIRO_STATUS_LAST_STATUS);
+}
+
+/**
+ * _cairo_set_error:
* @cr: a cairo context
* @status: a status value indicating an error, (eg. not
* CAIRO_STATUS_SUCCESS)
*
- * Sets cr->status to @status.
+ * Sets cr->status to @status and calls _cairo_error;
*
* All assignments of an error status to cr->status should happen
- * either inside of _cairo_error(), or else _cairo_error() should be
+ * through _cairo_set_error() or else _cairo_error() should be
* called immediately after the assignment.
*
* The purpose of this function is to allow the user to set a
* breakpoint in _cairo_error() to generate a stack trace for when the
* user causes cairo to detect an error.
- *
- * _cairo_error also calls the error notify callback function that the
- * user may have set with cairo_set_error_notify.
**/
static void
-_cairo_error (cairo_t *cr, cairo_status_t status)
+_cairo_set_error (cairo_t *cr, cairo_status_t status)
{
- assert (status > CAIRO_STATUS_SUCCESS &&
- status <= CAIRO_STATUS_LAST_STATUS);
-
cr->status = status;
+
+ _cairo_error (status);
}
/**
@@ -142,13 +160,13 @@ cairo_create (cairo_surface_t *target)
if (target == NULL) {
cr->gstate = NULL;
- _cairo_error (cr, CAIRO_STATUS_NULL_POINTER);
+ _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
return cr;
}
cr->gstate = _cairo_gstate_create (target);
if (cr->gstate == NULL)
- _cairo_error (cr, CAIRO_STATUS_NO_MEMORY);
+ _cairo_set_error (cr, CAIRO_STATUS_NO_MEMORY);
return cr;
}
@@ -222,14 +240,14 @@ cairo_save (cairo_t *cr)
cairo_gstate_t *top;
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
top = _cairo_gstate_clone (cr->gstate);
if (top == NULL) {
- _cairo_error (cr, CAIRO_STATUS_NO_MEMORY);
+ _cairo_set_error (cr, CAIRO_STATUS_NO_MEMORY);
return;
}
@@ -252,7 +270,7 @@ cairo_restore (cairo_t *cr)
cairo_gstate_t *top;
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -262,7 +280,7 @@ cairo_restore (cairo_t *cr)
_cairo_gstate_destroy (top);
if (cr->gstate == NULL)
- _cairo_error (cr, CAIRO_STATUS_INVALID_RESTORE);
+ _cairo_set_error (cr, CAIRO_STATUS_INVALID_RESTORE);
}
slim_hidden_def(cairo_restore);
@@ -311,13 +329,13 @@ void
cairo_set_operator (cairo_t *cr, cairo_operator_t op)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_set_operator (cr->gstate, op);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -341,7 +359,7 @@ cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue)
cairo_pattern_t *pattern;
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -374,7 +392,7 @@ cairo_set_source_rgba (cairo_t *cr,
cairo_pattern_t *pattern;
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -416,7 +434,7 @@ cairo_set_source_surface (cairo_t *cr,
cairo_matrix_t matrix;
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -447,23 +465,23 @@ void
cairo_set_source (cairo_t *cr, cairo_pattern_t *source)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
if (source == NULL) {
- _cairo_error (cr, CAIRO_STATUS_NULL_POINTER);
+ _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
return;
}
if (source->status) {
- _cairo_error (cr, source->status);
+ _cairo_set_error (cr, source->status);
return;
}
cr->status = _cairo_gstate_set_source (cr->gstate, source);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -479,12 +497,8 @@ cairo_set_source (cairo_t *cr, cairo_pattern_t *source)
cairo_pattern_t *
cairo_get_source (cairo_t *cr)
{
- if (cr->status) {
- cairo_pattern_t *pattern;
- pattern = _cairo_pattern_create_in_error (cr->status);
- _cairo_error (cr, cr->status);
- return pattern;
- }
+ if (cr->status)
+ return (cairo_pattern_t*) &cairo_solid_pattern_nil.base;
return _cairo_gstate_get_source (cr->gstate);
}
@@ -506,7 +520,7 @@ void
cairo_set_tolerance (cairo_t *cr, double tolerance)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -514,7 +528,7 @@ cairo_set_tolerance (cairo_t *cr, double tolerance)
cr->status = _cairo_gstate_set_tolerance (cr->gstate, tolerance);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -532,13 +546,13 @@ void
cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_set_fill_rule (cr->gstate, fill_rule);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -559,7 +573,7 @@ void
cairo_set_line_width (cairo_t *cr, double width)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -567,7 +581,7 @@ cairo_set_line_width (cairo_t *cr, double width)
cr->status = _cairo_gstate_set_line_width (cr->gstate, width);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -588,13 +602,13 @@ void
cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_set_line_cap (cr->gstate, line_cap);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -615,39 +629,39 @@ void
cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_set_line_join (cr->gstate, line_join);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
void
cairo_set_dash (cairo_t *cr, double *dashes, int ndash, double offset)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_set_dash (cr->gstate, dashes, ndash, offset);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
void
cairo_set_miter_limit (cairo_t *cr, double limit)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_set_miter_limit (cr->gstate, limit);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
@@ -667,13 +681,13 @@ void
cairo_translate (cairo_t *cr, double tx, double ty)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_translate (cr->gstate, tx, ty);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -691,13 +705,13 @@ void
cairo_scale (cairo_t *cr, double sx, double sy)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_scale (cr->gstate, sx, sy);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
@@ -717,13 +731,13 @@ void
cairo_rotate (cairo_t *cr, double angle)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_rotate (cr->gstate, angle);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -740,13 +754,13 @@ cairo_transform (cairo_t *cr,
const cairo_matrix_t *matrix)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_transform (cr->gstate, matrix);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -762,13 +776,13 @@ cairo_set_matrix (cairo_t *cr,
const cairo_matrix_t *matrix)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_set_matrix (cr->gstate, matrix);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -784,13 +798,13 @@ void
cairo_identity_matrix (cairo_t *cr)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_identity_matrix (cr->gstate);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -807,13 +821,13 @@ void
cairo_user_to_device (cairo_t *cr, double *x, double *y)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_user_to_device (cr->gstate, x, y);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -831,13 +845,13 @@ void
cairo_user_to_device_distance (cairo_t *cr, double *dx, double *dy)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_user_to_device_distance (cr->gstate, dx, dy);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -854,13 +868,13 @@ void
cairo_device_to_user (cairo_t *cr, double *x, double *y)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_device_to_user (cr->gstate, x, y);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -878,20 +892,20 @@ void
cairo_device_to_user_distance (cairo_t *cr, double *dx, double *dy)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_device_to_user_distance (cr->gstate, dx, dy);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
void
cairo_new_path (cairo_t *cr)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -905,7 +919,7 @@ cairo_move_to (cairo_t *cr, double x, double y)
cairo_fixed_t x_fixed, y_fixed;
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -915,7 +929,7 @@ cairo_move_to (cairo_t *cr, double x, double y)
cr->status = _cairo_path_fixed_move_to (&cr->path, x_fixed, y_fixed);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
slim_hidden_def(cairo_move_to);
@@ -925,7 +939,7 @@ cairo_line_to (cairo_t *cr, double x, double y)
cairo_fixed_t x_fixed, y_fixed;
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -935,7 +949,7 @@ cairo_line_to (cairo_t *cr, double x, double y)
cr->status = _cairo_path_fixed_line_to (&cr->path, x_fixed, y_fixed);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
void
@@ -949,7 +963,7 @@ cairo_curve_to (cairo_t *cr,
cairo_fixed_t x3_fixed, y3_fixed;
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -971,7 +985,7 @@ cairo_curve_to (cairo_t *cr,
x2_fixed, y2_fixed,
x3_fixed, y3_fixed);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -1014,7 +1028,7 @@ cairo_arc (cairo_t *cr,
double angle1, double angle2)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -1054,7 +1068,7 @@ cairo_arc_negative (cairo_t *cr,
double angle1, double angle2)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -1096,7 +1110,7 @@ cairo_rel_move_to (cairo_t *cr, double dx, double dy)
cairo_fixed_t dx_fixed, dy_fixed;
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -1106,7 +1120,7 @@ cairo_rel_move_to (cairo_t *cr, double dx, double dy)
cr->status = _cairo_path_fixed_rel_move_to (&cr->path, dx_fixed, dy_fixed);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
void
@@ -1115,7 +1129,7 @@ cairo_rel_line_to (cairo_t *cr, double dx, double dy)
cairo_fixed_t dx_fixed, dy_fixed;
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -1125,7 +1139,7 @@ cairo_rel_line_to (cairo_t *cr, double dx, double dy)
cr->status = _cairo_path_fixed_rel_line_to (&cr->path, dx_fixed, dy_fixed);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
slim_hidden_def(cairo_rel_line_to);
@@ -1140,7 +1154,7 @@ cairo_rel_curve_to (cairo_t *cr,
cairo_fixed_t dx3_fixed, dy3_fixed;
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -1162,7 +1176,7 @@ cairo_rel_curve_to (cairo_t *cr,
dx2_fixed, dy2_fixed,
dx3_fixed, dy3_fixed);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
void
@@ -1171,7 +1185,7 @@ cairo_rectangle (cairo_t *cr,
double width, double height)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -1191,7 +1205,7 @@ cairo_stroke_to_path (cairo_t *cr)
cr->status = _cairo_gstate_stroke_path (cr->gstate);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
*/
@@ -1199,13 +1213,13 @@ void
cairo_close_path (cairo_t *cr)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_path_fixed_close_path (&cr->path);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
slim_hidden_def(cairo_close_path);
@@ -1220,13 +1234,13 @@ void
cairo_paint (cairo_t *cr)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_paint (cr->gstate);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -1247,7 +1261,7 @@ cairo_paint_with_alpha (cairo_t *cr,
cairo_pattern_union_t pattern;
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -1261,7 +1275,7 @@ cairo_paint_with_alpha (cairo_t *cr,
cr->status = _cairo_gstate_mask (cr->gstate, &pattern.base);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
_cairo_pattern_fini (&pattern.base);
}
@@ -1281,23 +1295,23 @@ cairo_mask (cairo_t *cr,
cairo_pattern_t *pattern)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
if (pattern == NULL) {
- _cairo_error (cr, CAIRO_STATUS_NULL_POINTER);
+ _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
return;
}
if (pattern->status) {
- _cairo_error (cr, pattern->status);
+ _cairo_set_error (cr, pattern->status);
return;
}
cr->status = _cairo_gstate_mask (cr->gstate, pattern);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -1322,7 +1336,7 @@ cairo_mask_surface (cairo_t *cr,
cairo_matrix_t matrix;
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -1372,13 +1386,13 @@ void
cairo_stroke_preserve (cairo_t *cr)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_stroke (cr->gstate, &cr->path);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
slim_hidden_def(cairo_stroke_preserve);
@@ -1413,13 +1427,13 @@ void
cairo_fill_preserve (cairo_t *cr)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_fill (cr->gstate, &cr->path);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
slim_hidden_def(cairo_fill_preserve);
@@ -1427,26 +1441,26 @@ void
cairo_copy_page (cairo_t *cr)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_copy_page (cr->gstate);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
void
cairo_show_page (cairo_t *cr)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_show_page (cr->gstate);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
cairo_bool_t
@@ -1455,7 +1469,7 @@ cairo_in_stroke (cairo_t *cr, double x, double y)
int inside;
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return 0;
}
@@ -1463,20 +1477,20 @@ cairo_in_stroke (cairo_t *cr, double x, double y)
&cr->path,
x, y, &inside);
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return 0;
}
return inside;
}
-int
+cairo_bool_t
cairo_in_fill (cairo_t *cr, double x, double y)
{
int inside;
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return 0;
}
@@ -1484,7 +1498,7 @@ cairo_in_fill (cairo_t *cr, double x, double y)
&cr->path,
x, y, &inside);
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return 0;
}
@@ -1496,7 +1510,7 @@ cairo_stroke_extents (cairo_t *cr,
double *x1, double *y1, double *x2, double *y2)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -1504,7 +1518,7 @@ cairo_stroke_extents (cairo_t *cr,
&cr->path,
x1, y1, x2, y2);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
void
@@ -1512,7 +1526,7 @@ cairo_fill_extents (cairo_t *cr,
double *x1, double *y1, double *x2, double *y2)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -1520,7 +1534,7 @@ cairo_fill_extents (cairo_t *cr,
&cr->path,
x1, y1, x2, y2);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -1579,13 +1593,13 @@ void
cairo_clip_preserve (cairo_t *cr)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_clip (cr->gstate, &cr->path);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
slim_hidden_def(cairo_clip_preserve);
@@ -1609,13 +1623,13 @@ void
cairo_reset_clip (cairo_t *cr)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_reset_clip (cr->gstate);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -1640,13 +1654,13 @@ cairo_select_font_face (cairo_t *cr,
cairo_font_weight_t weight)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_select_font_face (cr->gstate, family, slant, weight);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -1666,15 +1680,15 @@ cairo_get_font_face (cairo_t *cr)
cairo_font_face_t *font_face;
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return NULL;
}
cr->status = _cairo_gstate_get_font_face (cr->gstate, &font_face);
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
/* XXX: When available:
- return _cairo_font_face_create_in_error (cr->status);
+ return _cairo_font_face_nil;
*/
return NULL;
}
@@ -1695,13 +1709,13 @@ cairo_font_extents (cairo_t *cr,
cairo_font_extents_t *extents)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_get_font_extents (cr->gstate, extents);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -1718,13 +1732,13 @@ cairo_set_font_face (cairo_t *cr,
cairo_font_face_t *font_face)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_set_font_face (cr->gstate, font_face);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -1742,13 +1756,13 @@ void
cairo_set_font_size (cairo_t *cr, double size)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_set_font_size (cr->gstate, size);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -1769,13 +1783,13 @@ cairo_set_font_matrix (cairo_t *cr,
const cairo_matrix_t *matrix)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_set_font_matrix (cr->gstate, matrix);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -1793,6 +1807,49 @@ cairo_get_font_matrix (cairo_t *cr, cairo_matrix_t *matrix)
}
/**
+ * cairo_set_font_options:
+ * @cr: a #cairo_t
+ * @options: font options to use
+ *
+ * Sets a set of custom font rendering options for the #cairo_t.
+ * Rendering options are derived by merging these options with the
+ * options derived from underlying surface; if the value in @options
+ * has a default value (like %CAIRO_ANTIALIAS_DEFAULT), then the value
+ * from the surface is used.
+ **/
+void
+cairo_set_font_options (cairo_t *cr,
+ const cairo_font_options_t *options)
+{
+ if (cr->status) {
+ _cairo_set_error (cr, cr->status);
+ return;
+ }
+
+ cr->status = _cairo_gstate_set_font_options (cr->gstate, options);
+ if (cr->status)
+ _cairo_set_error (cr, cr->status);
+}
+
+/**
+ * cairo_get_font_options:
+ * @cr: a #cairo_t
+ * @options: a #cairo_font_options_t object into which to store
+ * the retrieved options. All existing values are overwritten
+ *
+ * Retrieves font rendering options set via #cairo_set_font_options.
+ * Note that the returned options do not include any options derived
+ * from the underlying surface; they are literally the options
+ * passed to cairo_set_font_options().
+ **/
+void
+cairo_get_font_options (cairo_t *cr,
+ cairo_font_options_t *options)
+{
+ _cairo_gstate_get_font_options (cr->gstate, options);
+}
+
+/**
* cairo_text_extents:
* @cr: a #cairo_t
* @utf8: a string of text, encoded in utf-8
@@ -1822,7 +1879,7 @@ cairo_text_extents (cairo_t *cr,
double x, y;
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -1845,7 +1902,7 @@ cairo_text_extents (cairo_t *cr,
if (cr->status) {
if (glyphs)
free (glyphs);
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -1854,7 +1911,7 @@ cairo_text_extents (cairo_t *cr,
free (glyphs);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -1882,14 +1939,14 @@ cairo_glyph_extents (cairo_t *cr,
cairo_text_extents_t *extents)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_glyph_extents (cr->gstate, glyphs, num_glyphs,
extents);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
void
@@ -1900,7 +1957,7 @@ cairo_show_text (cairo_t *cr, const char *utf8)
double x, y;
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -1916,7 +1973,7 @@ cairo_show_text (cairo_t *cr, const char *utf8)
if (cr->status) {
if (glyphs)
free (glyphs);
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -1926,20 +1983,20 @@ cairo_show_text (cairo_t *cr, const char *utf8)
free (glyphs);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
void
cairo_show_glyphs (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_show_glyphs (cr->gstate, glyphs, num_glyphs);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
void
@@ -1950,7 +2007,7 @@ cairo_text_path (cairo_t *cr, const char *utf8)
double x, y;
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -1963,7 +2020,7 @@ cairo_text_path (cairo_t *cr, const char *utf8)
if (cr->status) {
if (glyphs)
free (glyphs);
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -1974,7 +2031,7 @@ cairo_text_path (cairo_t *cr, const char *utf8)
free (glyphs);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
@@ -1982,7 +2039,7 @@ void
cairo_glyph_path (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
@@ -1990,7 +2047,7 @@ cairo_glyph_path (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs)
glyphs, num_glyphs,
&cr->path);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
/**
@@ -2156,20 +2213,19 @@ cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix)
* Gets the target surface for the cairo context as passed to
* cairo_create().
*
- * Return value: the target surface, (or NULL if @cr is in an error
- * state). This object is owned by cairo. To keep a reference to it,
- * you must call cairo_surface_reference().
+ * Return value: the target surface. This object is owned by cairo. To
+ * keep a reference to it, you must call cairo_surface_reference().
+ *
+ * This function will always return a valid pointer, but the result
+ * can be a "nil" surface if @cr is already in an error state,
+ * (ie. cairo_status(cr) != CAIRO_STATUS_SUCCESS). A nil surface is
+ * indicated by cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS.
**/
cairo_surface_t *
cairo_get_target (cairo_t *cr)
{
- if (cr->status) {
- _cairo_error (cr, cr->status);
- /* XXX: Should be as follows when available:
- return _cairo_surface_create_in_error ();
- */
- return NULL;
- }
+ if (cr->status)
+ return (cairo_surface_t*) &_cairo_surface_nil;
return _cairo_gstate_get_target (cr->gstate);
}
@@ -2190,20 +2246,18 @@ cairo_get_target (cairo_t *cr)
* will have no data, (data==NULL and num_data==0), if either of the
* following conditions hold:
*
- * 1) If there is insufficient memory to copy the path. In this case
- * path->status will be set to CAIRO_STATUS_NO_MEMORY.
+ * 1) If there is insufficient memory to copy the path.
*
- * 2) If @cr is already in an error state. In this case path->status
- * will contain the same status that would be returned by
- * cairo_status(cr).
+ * 2) If @cr is already in an error state.
+ *
+ * In either case, path->status will be set to CAIRO_STATUS_NO_MEMORY,
+ * (regardless of what the error status in @cr might have been).
**/
cairo_path_t *
cairo_copy_path (cairo_t *cr)
{
- if (cr->status) {
- _cairo_error (cr, cr->status);
- return _cairo_path_data_create_in_error (cr->status);
- }
+ if (cr->status)
+ return &cairo_path_nil;
return _cairo_path_data_create (&cr->path, cr->gstate);
}
@@ -2242,7 +2296,7 @@ cairo_path_t *
cairo_copy_path_flat (cairo_t *cr)
{
if (cr->status)
- return _cairo_path_data_create_in_error (cr->status);
+ return &cairo_path_nil;
else
return _cairo_path_data_create_flat (&cr->path, cr->gstate);
}
@@ -2264,31 +2318,31 @@ cairo_append_path (cairo_t *cr,
cairo_path_t *path)
{
if (cr->status) {
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
return;
}
if (path == NULL) {
- _cairo_error (cr, CAIRO_STATUS_NULL_POINTER);
+ _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
return;
}
if (path->status) {
if (path->status <= CAIRO_STATUS_LAST_STATUS)
- _cairo_error (cr, path->status);
+ _cairo_set_error (cr, path->status);
else
- _cairo_error (cr, CAIRO_STATUS_INVALID_STATUS);
+ _cairo_set_error (cr, CAIRO_STATUS_INVALID_STATUS);
return;
}
if (path->data == NULL) {
- _cairo_error (cr, CAIRO_STATUS_NULL_POINTER);
+ _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
return;
}
cr->status = _cairo_path_data_append_to_context (path, cr);
if (cr->status)
- _cairo_error (cr, cr->status);
+ _cairo_set_error (cr, cr->status);
}
cairo_status_t
@@ -2314,7 +2368,7 @@ cairo_status_to_string (cairo_status_t status)
case CAIRO_STATUS_INVALID_MATRIX:
return "invalid matrix (not invertible)";
case CAIRO_STATUS_INVALID_STATUS:
- return " invalid value for an input cairo_status_t";
+ return "invalid value for an input cairo_status_t";
case CAIRO_STATUS_NULL_POINTER:
return "NULL pointer";
case CAIRO_STATUS_INVALID_STRING:
@@ -2331,6 +2385,14 @@ cairo_status_to_string (cairo_status_t status)
return "the surface type is not appropriate for the operation";
case CAIRO_STATUS_PATTERN_TYPE_MISMATCH:
return "the pattern type is not appropriate for the operation";
+ case CAIRO_STATUS_INVALID_CONTENT:
+ return "invalid value for an input cairo_content_t";
+ case CAIRO_STATUS_INVALID_FORMAT:
+ return "invalid value for an input cairo_format_t";
+ case CAIRO_STATUS_INVALID_VISUAL:
+ return "invalid value for an input Visual*";
+ case CAIRO_STATUS_FILE_NOT_FOUND:
+ return "file not found";
}
return "<unknown error status>";
diff --git a/src/cairo.h b/src/cairo.h
index 41ae83ce7..ba8999810 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -90,9 +90,20 @@ typedef struct _cairo_surface cairo_surface_t;
/**
* cairo_matrix_t:
+ * @xx: xx component of the affine transformation
+ * @yx: yx component of the affine transformation
+ * @xy: xy component of the affine transformation
+ * @yy: yy component of the affine transformation
+ * @x0: X translation component of the affine transformation
+ * @y0: Y translation component of the affine transformation
*
* A #cairo_matrix_t holds an affine transformation, such as a scale,
- * rotation, or shear, or a combination of those.
+ * rotation, or shear, or a combination of those. The transformation is given
+ * by:
+ * <programlisting>
+ * x_new = xx * x + xy * y + x0;
+ * y_new = yx * x + yy * y + y0;
+ * </programlisting>
**/
typedef struct _cairo_matrix {
double xx; double yx;
@@ -103,7 +114,8 @@ typedef struct _cairo_matrix {
typedef struct _cairo_pattern cairo_pattern_t;
/**
- * cairo_destroy_func_t
+ * cairo_destroy_func_t:
+ * @data: The data element being destroyed.
*
* #cairo_destroy_func_t the type of function which is called when a
* data element is destroyed. It is passed the pointer to the data
@@ -112,7 +124,8 @@ typedef struct _cairo_pattern cairo_pattern_t;
typedef void (*cairo_destroy_func_t) (void *data);
/**
- * cairo_user_data_key_t
+ * cairo_user_data_key_t:
+ * @unused: not used; ignore.
*
* #cairo_user_data_key_t is used for attaching user data to cairo
* data structures. The actual contents of the struct is never used,
@@ -129,7 +142,7 @@ typedef struct _cairo_user_data_key {
* @CAIRO_STATUS_SUCCESS: no error has occurred
* @CAIRO_STATUS_NO_MEMORY: out of memory
* @CAIRO_STATUS_INVALID_RESTORE: cairo_restore without matching cairo_save
- * @CAIRO_STATUS_INVALID_POP_GROUP:
+ * @CAIRO_STATUS_INVALID_POP_GROUP: no saved group to pop
* @CAIRO_STATUS_NO_CURRENT_POINT: no current point defined
* @CAIRO_STATUS_INVALID_MATRIX: invalid matrix (not invertible)
* @CAIRO_STATUS_INVALID_STATUS: invalid value for an input cairo_status_t
@@ -141,6 +154,10 @@ typedef struct _cairo_user_data_key {
* @CAIRO_STATUS_SURFACE_FINISHED: target surface has been finished
* @CAIRO_STATUS_SURFACE_TYPE_MISMATCH: the surface type is not appropriate for the operation
* @CAIRO_STATUS_PATTERN_TYPE_MISMATCH: the pattern type is not appropriate for the operation
+ * @CAIRO_STATUS_INVALID_CONTENT: invalid value for an input cairo_content_t
+ * @CAIRO_STATUS_INVALID_FORMAT: invalid value for an input cairo_format_t
+ * @CAIRO_STATUS_INVALID_VISUAL: invalid value for an input Visual*
+ * @CAIRO_STATUS_FILE_NOT_FOUND: file not found
*
* #cairo_status_t is used to indicate errors that can occur when
* using Cairo. In some cases it is returned directly by functions.
@@ -162,11 +179,18 @@ typedef enum _cairo_status {
CAIRO_STATUS_WRITE_ERROR,
CAIRO_STATUS_SURFACE_FINISHED,
CAIRO_STATUS_SURFACE_TYPE_MISMATCH,
- CAIRO_STATUS_PATTERN_TYPE_MISMATCH
+ CAIRO_STATUS_PATTERN_TYPE_MISMATCH,
+ CAIRO_STATUS_INVALID_CONTENT,
+ CAIRO_STATUS_INVALID_FORMAT,
+ CAIRO_STATUS_INVALID_VISUAL,
+ CAIRO_STATUS_FILE_NOT_FOUND
} cairo_status_t;
/**
- * cairo_write_func_t
+ * cairo_write_func_t:
+ * @closure: the output closure
+ * @data: the buffer containing the data to write
+ * @length: the amount of data to write
*
* #cairo_write_func_t is the type of function which is called when a
* backend needs to write data to an output stream. It is passed the
@@ -175,21 +199,28 @@ typedef enum _cairo_status {
* data in bytes. The write function should return
* CAIRO_STATUS_SUCCESS if all the data was successfully written,
* CAIRO_STATUS_WRITE_ERROR otherwise.
+ *
+ * Returns: the status code of the write operation
*/
typedef cairo_status_t (*cairo_write_func_t) (void *closure,
const unsigned char *data,
unsigned int length);
/**
- * cairo_read_func_t
+ * cairo_read_func_t:
+ * @closure: the input closure
+ * @data: the buffer into which to read the data
+ * @length: the amount of data to read
*
* #cairo_read_func_t is the type of function which is called when a
* backend needs to read data from an intput stream. It is passed the
* closure which was specified by the user at the time the read
* function was registered, the buffer to read the data into and the
* length of the data in bytes. The read function should return
- * CAIRO_STATUS_SUCCESS if all the data was successfully written,
+ * CAIRO_STATUS_SUCCESS if all the data was successfully read,
* CAIRO_STATUS_READ_ERROR otherwise.
+ *
+ * Returns: the status code of the read operation
*/
typedef cairo_status_t (*cairo_read_func_t) (void *closure,
unsigned char *data,
@@ -635,7 +666,148 @@ typedef enum _cairo_font_weight {
CAIRO_FONT_WEIGHT_NORMAL,
CAIRO_FONT_WEIGHT_BOLD
} 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
+ * @CAIRO_SUBPIXEL_ORDER_RGB: Subpixel elements are arranged horizontally
+ * with red at the left
+ * @CAIRO_SUBPIXEL_ORDER_BGR: Subpixel elements are arranged horizontally
+ * with blue at the left
+ * @CAIRO_SUBPIXEL_ORDER_VRGB: Subpixel elements are arranged vertically
+ * with red at the top
+ * @CAIRO_SUBPIXEL_ORDER_VBGR: Subpixel elements are arranged vertically
+ * with blue at the top
+ *
+ * The subpixel order specifies the order of color elements within
+ * each pixel on the display device when rendering with an
+ * antialiasing mode of %CAIRO_ANTIALIAS_SUBPIXEL.
+ **/
+typedef enum _cairo_subpixel_order {
+ CAIRO_SUBPIXEL_ORDER_DEFAULT,
+ CAIRO_SUBPIXEL_ORDER_RGB,
+ CAIRO_SUBPIXEL_ORDER_BGR,
+ CAIRO_SUBPIXEL_ORDER_VRGB,
+ CAIRO_SUBPIXEL_ORDER_VBGR
+} cairo_subpixel_order_t;
+
+/**
+ * cairo_hint_style_t:
+ * @CAIRO_HINT_STYLE_DEFAULT: Use the default hint style for
+ * for font backend and target device
+ * @CAIRO_HINT_STYLE_NONE: Do not hint outlines
+ * @CAIRO_HINT_STYLE_SLIGHT: Hint outlines slightly to improve
+ * contrast while retaining good fidelity to the original
+ * shapes.
+ * @CAIRO_HINT_STYLE_MEDIUM: Hint outlines with medium strength
+ * giving a compromise between fidelity to the original shapes
+ * and contrast
+ * @CAIRO_HINT_STYLE_FULL: Hint outlines to maximize contrast
+ *
+ * Specifies the type of hinting to do on font outlines. Hinting
+ * is the process of fitting outlines to the pixel grid in order
+ * to improve the appearance of the result. Since hinting outlines
+ * involves distorting them, it also reduces the faithfulness
+ * to the original outline shapes. Not all of the outline hinting
+ * styles are supported by all font backends.
+ */
+typedef enum _cairo_hint_style {
+ CAIRO_HINT_STYLE_DEFAULT,
+ CAIRO_HINT_STYLE_NONE,
+ CAIRO_HINT_STYLE_SLIGHT,
+ CAIRO_HINT_STYLE_MEDIUM,
+ CAIRO_HINT_STYLE_FULL
+} cairo_hint_style_t;
+
+/**
+ * cairo_hint_metrics_t:
+ * @CAIRO_HINT_METRICS_DEFAULT: Hint metrics in the default
+ * manner for the font backend and target device
+ * @CAIRO_HINT_METRICS_OFF: Do not hint font metrics
+ * @CAIRO_HINT_METRICS_ON: Hint font metrics
+ *
+ * Specifies whether to hint font metrics; hinting font metrics
+ * means quantizing them so that they are integer values in
+ * device space. Doing this improves the consistency of
+ * letter and line spacing, however it also means that text
+ * will be laid out differently at different zoom factors.
+ */
+typedef enum _cairo_hint_metrics {
+ CAIRO_HINT_METRICS_DEFAULT,
+ CAIRO_HINT_METRICS_OFF,
+ CAIRO_HINT_METRICS_ON
+} cairo_hint_metrics_t;
+
+typedef struct _cairo_font_options cairo_font_options_t;
+
+cairo_font_options_t *
+cairo_font_options_create (void);
+
+cairo_font_options_t *
+cairo_font_options_copy (const cairo_font_options_t *original);
+
+void
+cairo_font_options_destroy (cairo_font_options_t *options);
+
+cairo_status_t
+cairo_font_options_status (cairo_font_options_t *options);
+
+void
+cairo_font_options_merge (cairo_font_options_t *options,
+ const cairo_font_options_t *other);
+cairo_bool_t
+cairo_font_options_equal (const cairo_font_options_t *options,
+ const cairo_font_options_t *other);
+
+unsigned long
+cairo_font_options_hash (const cairo_font_options_t *options);
+
+void
+cairo_font_options_set_antialias (cairo_font_options_t *options,
+ cairo_antialias_t antialias);
+cairo_antialias_t
+cairo_font_options_get_antialias (const cairo_font_options_t *options);
+
+void
+cairo_font_options_set_subpixel_order (cairo_font_options_t *options,
+ cairo_subpixel_order_t subpixel_order);
+cairo_subpixel_order_t
+cairo_font_options_get_subpixel_order (const cairo_font_options_t *options);
+
+void
+cairo_font_options_set_hint_style (cairo_font_options_t *options,
+ cairo_hint_style_t hint_style);
+cairo_hint_style_t
+cairo_font_options_get_hint_style (const cairo_font_options_t *options);
+
+void
+cairo_font_options_set_hint_metrics (cairo_font_options_t *options,
+ cairo_hint_metrics_t hint_metrics);
+cairo_hint_metrics_t
+cairo_font_options_get_hint_metrics (const cairo_font_options_t *options);
+
+
/* This interface is for dealing with text as text, not caring about the
font object inside the the cairo_t. */
@@ -657,6 +829,14 @@ cairo_get_font_matrix (cairo_t *cr,
cairo_matrix_t *matrix);
void
+cairo_set_font_options (cairo_t *cr,
+ const cairo_font_options_t *options);
+
+void
+cairo_get_font_options (cairo_t *cr,
+ cairo_font_options_t *options);
+
+void
cairo_show_text (cairo_t *cr, const char *utf8);
void
@@ -697,6 +877,9 @@ cairo_font_face_reference (cairo_font_face_t *font_face);
void
cairo_font_face_destroy (cairo_font_face_t *font_face);
+cairo_status_t
+cairo_font_face_status (cairo_font_face_t *font_face);
+
void *
cairo_font_face_get_user_data (cairo_font_face_t *font_face,
const cairo_user_data_key_t *key);
@@ -710,9 +893,10 @@ cairo_font_face_set_user_data (cairo_font_face_t *font_face,
/* Portable interface to general font features. */
cairo_scaled_font_t *
-cairo_scaled_font_create (cairo_font_face_t *font_face,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm);
+cairo_scaled_font_create (cairo_font_face_t *font_face,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ const cairo_font_options_t *options);
void
cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font);
@@ -721,6 +905,9 @@ void
cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font);
cairo_status_t
+cairo_scaled_font_status (cairo_scaled_font_t *scaled_font);
+
+void
cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font,
cairo_font_extents_t *extents);
@@ -844,6 +1031,9 @@ typedef union {
/**
* cairo_path_t:
+ * @status: the current error status
+ * @data: the elements in the path
+ * @num_data: the number of elements in the data array
*
* A data structure for holding a path. This data structure serves as
* the return value for cairo_copy_path_data() and
@@ -907,9 +1097,11 @@ typedef enum _cairo_content {
CAIRO_CONTENT_COLOR_ALPHA = 0x3000
} cairo_content_t;
-#define CAIRO_CONTENT_VALID(content) (((content) & ~(CAIRO_CONTENT_COLOR | \
- CAIRO_CONTENT_ALPHA | \
- CAIRO_CONTENT_COLOR_ALPHA)) == 0)
+#define CAIRO_CONTENT_VALID(content) ((content) && \
+ (((content) & ~(CAIRO_CONTENT_COLOR | \
+ CAIRO_CONTENT_ALPHA | \
+ CAIRO_CONTENT_COLOR_ALPHA))\
+ == 0))
cairo_surface_t *
cairo_surface_create_similar (cairo_surface_t *other,
@@ -924,6 +1116,9 @@ void
cairo_surface_destroy (cairo_surface_t *surface);
cairo_status_t
+cairo_surface_status (cairo_surface_t *surface);
+
+void
cairo_surface_finish (cairo_surface_t *surface);
#if CAIRO_HAS_PNG_FUNCTIONS
@@ -950,6 +1145,10 @@ cairo_surface_set_user_data (cairo_surface_t *surface,
cairo_destroy_func_t destroy);
void
+cairo_surface_get_font_options (cairo_surface_t *surface,
+ cairo_font_options_t *options);
+
+void
cairo_surface_set_device_offset (cairo_surface_t *surface,
double x_offset,
double y_offset);
diff --git a/src/cairoint.h b/src/cairoint.h
index bd8072c5d..457478388 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -36,7 +36,7 @@
*/
/*
- * These definitions are solely for use by the implementation of Cairo
+ * These definitions are solely for use by the implementation of cairo
* and constitute no kind of standard. If you need any of these
* functions, please drop me a note. Either the library needs new
* functionality, or there's a way to do what you need using the
@@ -55,10 +55,6 @@
#include <string.h>
#include <stdarg.h>
-#if HAVE_PTHREAD_H
-#include <pthread.h>
-#endif
-
#ifdef _MSC_VER
#define _USE_MATH_DEFINES
#endif
@@ -233,7 +229,8 @@ typedef struct _cairo_rectangle {
offset */
typedef enum cairo_int_status {
CAIRO_INT_STATUS_DEGENERATE = 1000,
- CAIRO_INT_STATUS_UNSUPPORTED
+ CAIRO_INT_STATUS_UNSUPPORTED,
+ CAIRO_INT_STATUS_NOTHING_TO_DO
} cairo_int_status_t;
typedef enum cairo_direction {
@@ -457,12 +454,13 @@ typedef struct _cairo_font_face_backend cairo_font_face_backend_t;
* glyph cache.
*/
struct _cairo_unscaled_font {
- int refcount;
+ int ref_count;
const cairo_unscaled_font_backend_t *backend;
};
struct _cairo_scaled_font {
- int refcount;
+ cairo_status_t status;
+ int ref_count;
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 */
@@ -471,11 +469,19 @@ struct _cairo_scaled_font {
};
struct _cairo_font_face {
- int refcount;
+ cairo_status_t status;
+ int ref_count;
cairo_user_data_array_t user_data;
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],
@@ -534,6 +540,7 @@ struct _cairo_scaled_font_backend {
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);
@@ -585,6 +592,7 @@ struct _cairo_font_face_backend {
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);
};
@@ -766,6 +774,9 @@ typedef struct _cairo_surface_backend {
cairo_fill_rule_t fill_rule,
double tolerance);
+ void
+ (*get_font_options) (void *surface,
+ cairo_font_options_t *options);
} cairo_surface_backend_t;
typedef struct _cairo_format_masks {
@@ -786,6 +797,7 @@ struct _cairo_surface {
const cairo_surface_backend_t *backend;
unsigned int ref_count;
+ cairo_status_t status;
cairo_bool_t finished;
cairo_user_data_array_t user_data;
@@ -825,6 +837,8 @@ struct _cairo_image_surface {
pixman_image_t *pixman_image;
};
+extern const cairo_surface_backend_t cairo_image_surface_backend;
+
/* XXX: Right now, the cairo_color structure puts unpremultiplied
color in the doubles and premultiplied color in the shorts. Yes,
this is crazy insane, (but at least we don't export this
@@ -878,6 +892,8 @@ typedef struct _cairo_solid_pattern {
cairo_color_t color;
} cairo_solid_pattern_t;
+extern const cairo_solid_pattern_t cairo_solid_pattern_nil;
+
typedef struct _cairo_surface_pattern {
cairo_pattern_t base;
@@ -1199,6 +1215,14 @@ cairo_private cairo_status_t
_cairo_gstate_set_font_matrix (cairo_gstate_t *gstate,
const cairo_matrix_t *matrix);
+void
+_cairo_gstate_get_font_options (cairo_gstate_t *gstate,
+ cairo_font_options_t *options);
+
+cairo_private cairo_status_t
+_cairo_gstate_set_font_options (cairo_gstate_t *gstate,
+ const cairo_font_options_t *options);
+
cairo_private cairo_status_t
_cairo_gstate_get_font_face (cairo_gstate_t *gstate,
cairo_font_face_t **font_face);
@@ -1278,6 +1302,12 @@ _cairo_color_get_rgba_premultiplied (cairo_color_t *color,
/* cairo-font.c */
cairo_private void
+_cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font,
+ cairo_status_t status);
+
+extern const cairo_font_face_t _cairo_font_face_nil;
+
+cairo_private void
_cairo_font_face_init (cairo_font_face_t *font_face,
const cairo_font_face_backend_t *backend);
@@ -1344,10 +1374,15 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
int num_glyphs,
cairo_path_fixed_t *path);
-cairo_private void
+cairo_private cairo_status_t
_cairo_scaled_font_get_glyph_cache_key (cairo_scaled_font_t *scaled_font,
cairo_glyph_cache_key_t *key);
+/* cairo-font-options.c */
+
+cairo_private void
+_cairo_font_options_init_default (cairo_font_options_t *options);
+
/* cairo_hull.c */
cairo_private cairo_status_t
_cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices);
@@ -1447,6 +1482,11 @@ _cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
cairo_traps_t *traps);
/* cairo-surface.c */
+
+extern const cairo_surface_t _cairo_surface_nil;
+extern const cairo_surface_t _cairo_surface_nil_read_error;
+extern const cairo_surface_t _cairo_surface_nil_file_not_found;
+
cairo_private cairo_surface_t *
_cairo_surface_create_similar_scratch (cairo_surface_t *other,
cairo_content_t content,
@@ -1606,7 +1646,7 @@ _cairo_format_from_content (cairo_content_t content);
cairo_private cairo_content_t
_cairo_content_from_format (cairo_format_t format);
-cairo_private cairo_image_surface_t *
+cairo_private cairo_surface_t *
_cairo_image_surface_create_with_masks (unsigned char *data,
cairo_format_masks_t *format,
int width,
@@ -1620,7 +1660,7 @@ cairo_private cairo_int_status_t
_cairo_image_surface_set_clip_region (cairo_image_surface_t *surface,
pixman_region16_t *region);
-cairo_private int
+cairo_private cairo_bool_t
_cairo_surface_is_image (cairo_surface_t *surface);
/* cairo_pen.c */
@@ -1796,9 +1836,6 @@ _cairo_pattern_fini (cairo_pattern_t *pattern);
cairo_private cairo_pattern_t *
_cairo_pattern_create_solid (const cairo_color_t *color);
-cairo_pattern_t *
-_cairo_pattern_create_in_error (cairo_status_t status);
-
cairo_private void
_cairo_pattern_transform (cairo_pattern_t *pattern,
const cairo_matrix_t *ctm_inverse);
@@ -1888,6 +1925,9 @@ _cairo_output_stream_get_status (cairo_output_stream_t *stream);
cairo_output_stream_t *
_cairo_output_stream_create_for_file (const char *filename);
+cairo_private void
+_cairo_error (cairo_status_t status);
+
/* Avoid unnecessary PLT entries. */
slim_hidden_proto(cairo_get_current_point)
diff --git a/test/.cvsignore b/test/.cvsignore
index 00ed2feca..1d037fa05 100644
--- a/test/.cvsignore
+++ b/test/.cvsignore
@@ -9,6 +9,7 @@ composite-integer-translate-over
composite-integer-translate-over-repeat
coverage
create-from-png
+create-from-png-stream
fill-and-stroke
fill-rule
filter-nearest-offset
@@ -40,6 +41,9 @@ source-clip
source-surface-scale-paint
surface-finish-twice
surface-pattern
+text-antialias-gray
+text-antialias-none
+text-antialias-subpixel
text-cache-crash
text-rotate
transforms
diff --git a/test/.valgrind-suppressions b/test/.valgrind-suppressions
new file mode 100644
index 000000000..1b1832fa3
--- /dev/null
+++ b/test/.valgrind-suppressions
@@ -0,0 +1,26 @@
+{
+ cairo's write_png triggers apparent bugs in libpng/libz
+ Memcheck:Cond
+ obj:/usr/lib/libz.so.1.2.2.2
+ obj:/usr/lib/libz.so.1.2.2.2
+ fun:deflate
+ fun:png_write_finish_row
+ fun:png_write_filtered_row
+ fun:png_write_find_filter
+ fun:png_write_row
+ fun:png_write_image
+ fun:write_png
+ }
+{
+ cairo's write_png_argb32 triggers apparent bugs in libpng/libz
+ Memcheck:Cond
+ obj:/usr/lib/libz.so.1.2.2.2
+ obj:/usr/lib/libz.so.1.2.2.2
+ fun:deflate
+ fun:png_write_finish_row
+ fun:png_write_filtered_row
+ fun:png_write_find_filter
+ fun:png_write_row
+ fun:png_write_image
+ fun:write_png_argb32
+ }
diff --git a/test/Makefile.am b/test/Makefile.am
index ee8d1b98d..649c4012b 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -6,6 +6,7 @@ composite-integer-translate-source \
composite-integer-translate-over \
composite-integer-translate-over-repeat \
create-from-png \
+create-from-png-stream \
fill-and-stroke \
fill-rule \
filter-nearest-offset \
@@ -29,6 +30,9 @@ source-clip \
source-surface-scale-paint \
surface-finish-twice \
surface-pattern \
+text-antialias-gray \
+text-antialias-none \
+text-antialias-subpixel \
text-cache-crash \
text-rotate \
transforms \
@@ -59,6 +63,7 @@ composite-integer-translate-source-ref.png \
composite-integer-translate-over-ref.png \
composite-integer-translate-over-repeat-ref.png \
create-from-png-ref.png \
+create-from-png-stream-ref.png \
fill-and-stroke-ref.png \
fill-rule-ref.png \
filter-nearest-offset-ref.png \
@@ -80,6 +85,8 @@ set-source-ref.png \
source-clip-ref.png \
source-surface-scale-paint-ref.png \
surface-pattern-ref.png \
+text-antialias-gray-ref.png \
+text-antialias-none-ref.png \
transforms-ref.png \
translate-show-surface-ref.png \
trap-clip-ref.png \
@@ -103,6 +110,7 @@ filter-nearest-offset \
pixman-rotate \
self-intersecting \
source-surface-scale-paint \
+text-antialias-subpixel \
text-rotate
check_PROGRAMS = $(TESTS)
@@ -143,6 +151,7 @@ composite_integer_translate_source_LDADD = $(LDADDS)
composite_integer_translate_over_LDADD = $(LDADDS)
composite_integer_translate_over_repeat_LDADD = $(LDADDS)
create_from_png_LDADD = $(LDADDS)
+create_from_png_stream_LDADD = $(LDADDS)
fill_and_stroke_LDADD = $(LDADDS)
fill_rule_LDADD = $(LDADDS)
filter_nearest_offset_LDADD = $(LDADDS)
@@ -169,6 +178,9 @@ source_clip_LDADD = $(LDADDS)
source_surface_scale_paint_LDADD = $(LDADDS)
surface_finish_twice_LDADD = $(LDADDS)
surface_pattern_LDADD = $(LDADDS)
+text_antialias_gray_LDADD = $(LDADDS)
+text_antialias_none_LDADD = $(LDADDS)
+text_antialias_subpixel_LDADD = $(LDADDS)
text_cache_crash_LDADD = $(LDADDS)
text_rotate_LDADD = $(LDADDS)
transforms_LDADD = $(LDADDS)
@@ -190,4 +202,4 @@ CLEANFILES = \
pdf-clip.pdf
check-valgrind:
- TESTS_ENVIRONMENT="libtool --mode=execute valgrind --tool=memcheck --leak-check=yes --show-reachable=yes" $(MAKE) check
+ TESTS_ENVIRONMENT="libtool --mode=execute valgrind --tool=memcheck --suppressions=./.valgrind-suppressions --leak-check=yes --show-reachable=yes" $(MAKE) check 2>&1 | tee valgrind.log
diff --git a/test/cairo-test.c b/test/cairo-test.c
index 77cf48fd0..456d7d85a 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -377,6 +377,7 @@ create_xlib_surface (int width, int height, void **closure)
width, height, xrender_format->depth);
surface = cairo_xlib_surface_create_with_xrender_format (dpy, xtc->pixmap,
+ DefaultScreenOfDisplay (dpy),
xrender_format,
width, height);
return surface;
@@ -582,14 +583,17 @@ cairo_test_create_surface_from_png (const char *filename)
char *srcdir = getenv ("srcdir");
image = cairo_image_surface_create_from_png (filename);
- if (image == NULL) {
+ if (cairo_surface_status(image)) {
+ /* expect not found when running with srcdir != builddir
+ * such as when 'make distcheck' is run
+ */
if (srcdir) {
char *srcdir_filename;
xasprintf (&srcdir_filename, "%s/%s", srcdir, filename);
image = cairo_image_surface_create_from_png (srcdir_filename);
free (srcdir_filename);
}
- if (image == NULL)
+ if (cairo_surface_status(image))
return NULL;
}
diff --git a/test/create-from-png-stream-ref.png b/test/create-from-png-stream-ref.png
new file mode 100644
index 000000000..765adc4a4
--- /dev/null
+++ b/test/create-from-png-stream-ref.png
Binary files differ
diff --git a/test/create-from-png-stream.c b/test/create-from-png-stream.c
new file mode 100644
index 000000000..75c70a563
--- /dev/null
+++ b/test/create-from-png-stream.c
@@ -0,0 +1,95 @@
+/*
+ * 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 Worth <cworth@cworth.org>
+ */
+
+#include "cairo-test.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#define WIDTH 2
+#define HEIGHT 2
+
+cairo_test_t test = {
+ "create-from-png",
+ "Tests the creation of an image surface from a PNG file",
+ WIDTH, HEIGHT
+};
+
+static cairo_status_t
+read_png_from_file (void *closure, unsigned char *data, unsigned int length)
+{
+ FILE *file = closure;
+ size_t bytes_read;
+
+ bytes_read = fread (data, 1, length, file);
+ if (bytes_read != length)
+ return CAIRO_STATUS_READ_ERROR;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ char *srcdir = getenv ("srcdir");
+ char *filename;
+ FILE *file;
+ cairo_surface_t *surface;
+
+ xasprintf (&filename, "%s/%s", srcdir ? srcdir : ".",
+ "create-from-png-stream-ref.png");
+
+ file = fopen (filename, "r");
+ if (file == NULL) {
+ cairo_test_log ("Error: failed to open file: %s\n", filename);
+ return CAIRO_TEST_FAILURE;
+ }
+
+ surface = cairo_image_surface_create_from_png_stream (read_png_from_file,
+ file);
+
+ fclose (file);
+
+ if (surface == NULL) {
+ cairo_test_log ("Error: failed to create surface from PNG: %s\n", filename);
+ free (filename);
+ return CAIRO_TEST_FAILURE;
+ }
+
+ free (filename);
+
+ cairo_set_source_surface (cr, surface, 0, 0);
+ cairo_paint (cr);
+
+ cairo_surface_destroy (surface);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+ return cairo_test (&test, draw);
+}
diff --git a/test/create-from-png.c b/test/create-from-png.c
index f4fd1b934..a7937bf2b 100644
--- a/test/create-from-png.c
+++ b/test/create-from-png.c
@@ -43,17 +43,28 @@ draw (cairo_t *cr, int width, int height)
char *filename;
cairo_surface_t *surface;
+ surface = cairo_image_surface_create_from_png ("___THIS_FILE_DOES_NOT_EXIST___");
+ if (cairo_surface_status (surface) != CAIRO_STATUS_FILE_NOT_FOUND) {
+ cairo_test_log ("Error: expected \"file not found\", but got: %s\n",
+ cairo_status_to_string (cairo_surface_status (surface)));
+ return CAIRO_TEST_FAILURE;
+ }
+
xasprintf (&filename, "%s/%s", srcdir ? srcdir : ".",
"create-from-png-ref.png");
surface = cairo_image_surface_create_from_png (filename);
- free (filename);
- if (surface == NULL) {
- cairo_test_log ("Error: failed to open file %s\n", filename);
+ if (cairo_surface_status (surface)) {
+ cairo_test_log ("Error reading PNG image %s: %s\n",
+ filename,
+ cairo_status_to_string (cairo_surface_status (surface)));
+ free (filename);
return CAIRO_TEST_FAILURE;
}
+ free (filename);
+
cairo_set_source_surface (cr, surface, 0, 0);
cairo_paint (cr);
diff --git a/test/surface-finish-twice.c b/test/surface-finish-twice.c
index 68d49c928..ce4f06595 100644
--- a/test/surface-finish-twice.c
+++ b/test/surface-finish-twice.c
@@ -55,12 +55,13 @@ draw (cairo_t *cr, int width, int height)
cairo_status_t status;
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
- status = cairo_surface_finish (surface);
- if (status != CAIRO_STATUS_SUCCESS)
+
+ cairo_surface_finish (surface);
+ if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
return CAIRO_TEST_FAILURE;
- status = cairo_surface_finish (surface);
- if (status != CAIRO_STATUS_SURFACE_FINISHED)
+ cairo_surface_finish (surface);
+ if (cairo_surface_status (surface) != CAIRO_STATUS_SURFACE_FINISHED)
return CAIRO_TEST_FAILURE;
cairo_surface_destroy (surface);
diff --git a/test/text-antialias-gray-ref.png b/test/text-antialias-gray-ref.png
new file mode 100644
index 000000000..1367ea9ef
--- /dev/null
+++ b/test/text-antialias-gray-ref.png
Binary files differ
diff --git a/test/text-antialias-gray.c b/test/text-antialias-gray.c
new file mode 100644
index 000000000..caa260ade
--- /dev/null
+++ b/test/text-antialias-gray.c
@@ -0,0 +1,77 @@
+/*
+ * 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"
+
+#define WIDTH 31
+#define HEIGHT 20
+#define TEXT_SIZE 12
+
+cairo_test_t test = {
+ "text-antialias-gray",
+ "Tests text rendering with grayscale antialiasing",
+ WIDTH, HEIGHT
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ cairo_text_extents_t extents;
+ cairo_font_options_t *font_options;
+ static char black[] = "black", blue[] = "blue";
+
+ cairo_select_font_face (cr, "Bitstream Vera Sans",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_NORMAL);
+ cairo_set_font_size (cr, TEXT_SIZE);
+
+ font_options = cairo_font_options_create ();
+
+ cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
+ cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF);
+ cairo_font_options_set_antialias (font_options, CAIRO_ANTIALIAS_GRAY);
+
+ cairo_set_font_options (cr, font_options);
+ cairo_font_options_destroy (font_options);
+
+ cairo_set_source_rgb (cr, 0, 0, 0); /* black */
+ cairo_text_extents (cr, black, &extents);
+ cairo_move_to (cr, -extents.x_bearing, -extents.y_bearing);
+ cairo_show_text (cr, black);
+ cairo_translate (cr, 0, -extents.y_bearing + 1);
+
+ cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
+ cairo_text_extents (cr, blue, &extents);
+ cairo_move_to (cr, -extents.x_bearing, -extents.y_bearing);
+ cairo_show_text (cr, blue);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+ return cairo_test (&test, draw);
+}
diff --git a/test/text-antialias-none-ref.png b/test/text-antialias-none-ref.png
new file mode 100644
index 000000000..c0281938c
--- /dev/null
+++ b/test/text-antialias-none-ref.png
Binary files differ
diff --git a/test/text-antialias-none.c b/test/text-antialias-none.c
new file mode 100644
index 000000000..411de0d92
--- /dev/null
+++ b/test/text-antialias-none.c
@@ -0,0 +1,77 @@
+/*
+ * 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"
+
+#define WIDTH 31
+#define HEIGHT 20
+#define TEXT_SIZE 12
+
+cairo_test_t test = {
+ "text-antialias-none",
+ "Tests text rendering with no antialiasing",
+ WIDTH, HEIGHT
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ cairo_text_extents_t extents;
+ cairo_font_options_t *font_options;
+ static char black[] = "black", blue[] = "blue";
+
+ cairo_select_font_face (cr, "Bitstream Vera Sans",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_NORMAL);
+ cairo_set_font_size (cr, TEXT_SIZE);
+
+ font_options = cairo_font_options_create ();
+
+ cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
+ cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF);
+ cairo_font_options_set_antialias (font_options, CAIRO_ANTIALIAS_NONE);
+
+ cairo_set_font_options (cr, font_options);
+ cairo_font_options_destroy (font_options);
+
+ cairo_set_source_rgb (cr, 0, 0, 0); /* black */
+ cairo_text_extents (cr, black, &extents);
+ cairo_move_to (cr, -extents.x_bearing, -extents.y_bearing);
+ cairo_show_text (cr, black);
+ cairo_translate (cr, 0, -extents.y_bearing + 1);
+
+ cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
+ cairo_text_extents (cr, blue, &extents);
+ cairo_move_to (cr, -extents.x_bearing, -extents.y_bearing);
+ cairo_show_text (cr, blue);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+ return cairo_test (&test, draw);
+}
diff --git a/test/text-antialias-subpixel.c b/test/text-antialias-subpixel.c
new file mode 100644
index 000000000..c72a71285
--- /dev/null
+++ b/test/text-antialias-subpixel.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"
+
+#define WIDTH 31
+#define HEIGHT 20
+#define TEXT_SIZE 12
+
+cairo_test_t test = {
+ "text-antialias-subpixel",
+ "Tests text rendering with subpixel antialiasing",
+ WIDTH, HEIGHT
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ cairo_text_extents_t extents;
+ cairo_font_options_t *font_options;
+ static char black[] = "black", blue[] = "blue";
+
+ cairo_select_font_face (cr, "Bitstream Vera Sans",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_NORMAL);
+ cairo_set_font_size (cr, TEXT_SIZE);
+
+ /* Sub-pixel antialiasing with unhinted glyphs can be pretty ugly
+ * (bad color fringing). The reason we turn off hints here is to
+ * try to get repeatable glyph shapes on multiple systems, not for
+ * any aesthetic reason. */
+ font_options = cairo_font_options_create ();
+
+ cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
+ cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF);
+ cairo_font_options_set_antialias (font_options, CAIRO_ANTIALIAS_SUBPIXEL);
+ cairo_font_options_set_subpixel_order (font_options, CAIRO_SUBPIXEL_ORDER_RGB);
+ cairo_set_font_options (cr, font_options);
+ cairo_font_options_destroy (font_options);
+
+ cairo_set_source_rgb (cr, 0, 0, 0); /* black */
+ cairo_text_extents (cr, black, &extents);
+ cairo_move_to (cr, -extents.x_bearing, -extents.y_bearing);
+ cairo_show_text (cr, black);
+ cairo_translate (cr, 0, -extents.y_bearing + 1);
+
+ cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
+ cairo_text_extents (cr, blue, &extents);
+ cairo_move_to (cr, -extents.x_bearing, -extents.y_bearing);
+ cairo_show_text (cr, blue);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+ return cairo_test_expect_failure (&test, draw,
+ "Bugs in subpixel-antialiased text rendering");
+}