diff options
author | Carl Worth <cworth@cworth.org> | 2006-02-13 16:47:41 -0800 |
---|---|---|
committer | Carl Worth <cworth@cworth.org> | 2006-02-13 16:47:41 -0800 |
commit | 73c2eada0d0c80763f0a953cce7fc144f7931fa1 (patch) | |
tree | d455caf8febf6e9eb1eed134e5fc80acd26b2f6f | |
parent | 01dd527ef3cb3205e33ffec90a11fda11f0e281a (diff) | |
parent | b9861b3e877776c5fe5b8b30fe76ced8ff846923 (diff) |
Remove pixman from SNAPSHOT_0_6_0SNAPSHOT_0_6_0
87 files changed, 8391 insertions, 1034 deletions
@@ -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 \ @@ -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 @@ -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 Binary files differnew file mode 100644 index 000000000..a08e1193a --- /dev/null +++ b/doc/tutorial/slides/circle-cairo-large.png diff --git a/doc/tutorial/slides/circle-cairo.png b/doc/tutorial/slides/circle-cairo.png Binary files differnew file mode 100644 index 000000000..f5d8cd438 --- /dev/null +++ b/doc/tutorial/slides/circle-cairo.png diff --git a/doc/tutorial/slides/circle-ooo-large.png b/doc/tutorial/slides/circle-ooo-large.png Binary files differnew file mode 100644 index 000000000..dfa40997f --- /dev/null +++ b/doc/tutorial/slides/circle-ooo-large.png diff --git a/doc/tutorial/slides/circle-ooo.png b/doc/tutorial/slides/circle-ooo.png Binary files differnew file mode 100644 index 000000000..eb90666e6 --- /dev/null +++ b/doc/tutorial/slides/circle-ooo.png diff --git a/doc/tutorial/slides/expander-fuzzy-large.png b/doc/tutorial/slides/expander-fuzzy-large.png Binary files differnew file mode 100644 index 000000000..3a485da6a --- /dev/null +++ b/doc/tutorial/slides/expander-fuzzy-large.png diff --git a/doc/tutorial/slides/expander-fuzzy.png b/doc/tutorial/slides/expander-fuzzy.png Binary files differnew file mode 100644 index 000000000..b01fd636e --- /dev/null +++ b/doc/tutorial/slides/expander-fuzzy.png diff --git a/doc/tutorial/slides/expander-sharp-large.png b/doc/tutorial/slides/expander-sharp-large.png Binary files differnew file mode 100644 index 000000000..f97fa06a4 --- /dev/null +++ b/doc/tutorial/slides/expander-sharp-large.png diff --git a/doc/tutorial/slides/expander-sharp.png b/doc/tutorial/slides/expander-sharp.png Binary files differnew file mode 100644 index 000000000..40759aef7 --- /dev/null +++ b/doc/tutorial/slides/expander-sharp.png 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 <cairo.h></lc> + <lc>#include <cairo-xlib.h></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, &ev) == 0)</lc> + <lc> if (ev.type == Expose && !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 <gtk/gtk.h></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 (&argc, &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 <cairo.h></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 <cairo.h></lc> + <lc>#include <cairo-pdf.h></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 Binary files differnew file mode 100644 index 000000000..765adc4a4 --- /dev/null +++ b/test/create-from-png-stream-ref.png 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 Binary files differnew file mode 100644 index 000000000..1367ea9ef --- /dev/null +++ b/test/text-antialias-gray-ref.png 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 Binary files differnew file mode 100644 index 000000000..c0281938c --- /dev/null +++ b/test/text-antialias-none-ref.png 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"); +} |