summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Worth <cworth@cworth.org>2006-02-13 16:47:13 -0800
committerCarl Worth <cworth@cworth.org>2006-02-13 16:47:13 -0800
commit5de154bcdb659618d723bcec14e0315630c62c7e (patch)
tree462e5c5d5a444c9388da1d33de1399e2fa98c9ed
parent6c38e238e5daab5df4c11027d28e48e62bbd4bc8 (diff)
parentf030aec810d74a60a44c35bf7815b9e94743cd65 (diff)
Remove pixman from SNAPSHOT_0_5_0SNAPSHOT_0_5_0
-rw-r--r--ChangeLog2241
-rw-r--r--NEWS304
-rw-r--r--PORTING_GUIDE257
-rw-r--r--RELEASING14
-rw-r--r--ROADMAP80
-rw-r--r--TODO105
-rwxr-xr-xautogen.sh2
-rw-r--r--configure.in154
-rw-r--r--doc/public/Makefile.am17
-rw-r--r--doc/public/cairo-docs.xml12
-rw-r--r--doc/public/cairo-sections.txt196
-rw-r--r--doc/public/language-bindings.xml726
-rw-r--r--doc/public/tmpl/cairo-atsui.sgml3
-rw-r--r--doc/public/tmpl/cairo-font.sgml148
-rw-r--r--doc/public/tmpl/cairo-ft.sgml26
-rw-r--r--doc/public/tmpl/cairo-glitz.sgml8
-rw-r--r--doc/public/tmpl/cairo-matrix.sgml69
-rw-r--r--doc/public/tmpl/cairo-pattern.sgml18
-rw-r--r--doc/public/tmpl/cairo-pdf.sgml20
-rw-r--r--doc/public/tmpl/cairo-png.sgml41
-rw-r--r--doc/public/tmpl/cairo-ps.sgml12
-rw-r--r--doc/public/tmpl/cairo-quartz.sgml10
-rw-r--r--doc/public/tmpl/cairo-surface.sgml72
-rw-r--r--doc/public/tmpl/cairo-xcb.sgml7
-rw-r--r--doc/public/tmpl/cairo-xlib.sgml25
-rw-r--r--doc/public/tmpl/cairo.sgml363
-rw-r--r--src/Makefile.am85
-rw-r--r--src/cairo-arc-private.h57
-rw-r--r--src/cairo-arc.c296
-rw-r--r--src/cairo-array.c139
-rw-r--r--src/cairo-atsui-font.c1215
-rw-r--r--src/cairo-atsui.h8
-rw-r--r--src/cairo-cache.c11
-rw-r--r--src/cairo-color.c120
-rw-r--r--src/cairo-features.h.in24
-rw-r--r--src/cairo-font.c954
-rw-r--r--src/cairo-ft-font.c962
-rw-r--r--src/cairo-ft-private.h4
-rw-r--r--src/cairo-ft.h24
-rw-r--r--src/cairo-glitz-surface.c1106
-rw-r--r--src/cairo-glitz.h9
-rw-r--r--src/cairo-gstate-private.h80
-rw-r--r--src/cairo-gstate.c2118
-rw-r--r--src/cairo-hash.c11
-rw-r--r--src/cairo-image-surface.c142
-rw-r--r--src/cairo-matrix.c461
-rw-r--r--src/cairo-output-stream.c285
-rw-r--r--src/cairo-path-bounds.c16
-rw-r--r--src/cairo-path-data-private.h55
-rw-r--r--src/cairo-path-data.c422
-rw-r--r--src/cairo-path-fill.c20
-rw-r--r--src/cairo-path-fixed-private.h74
-rw-r--r--src/cairo-path-stroke.c34
-rw-r--r--src/cairo-path.c389
-rw-r--r--src/cairo-pattern.c449
-rw-r--r--src/cairo-pdf-surface.c1139
-rw-r--r--src/cairo-pdf.h33
-rw-r--r--src/cairo-pen.c6
-rw-r--r--src/cairo-png.c465
-rw-r--r--src/cairo-private.h51
-rw-r--r--src/cairo-ps-surface.c323
-rw-r--r--src/cairo-ps.h32
-rw-r--r--src/cairo-quartz-surface.c403
-rw-r--r--src/cairo-quartz.h11
-rw-r--r--src/cairo-surface.c589
-rw-r--r--src/cairo-traps.c99
-rw-r--r--src/cairo-unicode.c28
-rw-r--r--src/cairo-wideint.h12
-rw-r--r--src/cairo-win32-font.c602
-rw-r--r--src/cairo-win32-surface.c239
-rw-r--r--src/cairo-win32.h26
-rw-r--r--src/cairo-xcb-surface.c613
-rw-r--r--src/cairo-xcb-xrender.h (renamed from src/cairo_fixed.c)67
-rw-r--r--src/cairo-xcb.h27
-rw-r--r--src/cairo-xlib-surface.c770
-rw-r--r--src/cairo-xlib-test.h (renamed from src/cairo-png.h)27
-rw-r--r--src/cairo-xlib-xrender.h (renamed from src/cairo_color.c)69
-rw-r--r--src/cairo-xlib.h43
-rw-r--r--src/cairo.c1426
-rw-r--r--src/cairo.h862
-rw-r--r--src/cairo_array.c134
-rw-r--r--src/cairo_atsui_font.c807
-rw-r--r--src/cairo_cache.c518
-rw-r--r--src/cairo_font.c476
-rw-r--r--src/cairo_ft_font.c1538
-rw-r--r--src/cairo_glitz_surface.c1317
-rw-r--r--src/cairo_gstate.c2566
-rw-r--r--src/cairo_hull.c202
-rw-r--r--src/cairo_image_surface.c675
-rw-r--r--src/cairo_matrix.c645
-rw-r--r--src/cairo_path.c495
-rw-r--r--src/cairo_path_bounds.c182
-rw-r--r--src/cairo_path_fill.c206
-rw-r--r--src/cairo_path_stroke.c848
-rw-r--r--src/cairo_pattern.c1325
-rw-r--r--src/cairo_pdf_surface.c2222
-rw-r--r--src/cairo_pen.c587
-rw-r--r--src/cairo_png_surface.c425
-rw-r--r--src/cairo_polygon.c172
-rw-r--r--src/cairo_ps_surface.c443
-rw-r--r--src/cairo_quartz_surface.c392
-rw-r--r--src/cairo_slope.c103
-rw-r--r--src/cairo_spline.c288
-rw-r--r--src/cairo_surface.c708
-rw-r--r--src/cairo_traps.c740
-rw-r--r--src/cairo_unicode.c340
-rw-r--r--src/cairo_wideint.c1024
-rw-r--r--src/cairo_win32_font.c1252
-rw-r--r--src/cairo_win32_surface.c931
-rw-r--r--src/cairo_xcb_surface.c978
-rw-r--r--src/cairo_xlib_surface.c1530
-rw-r--r--src/cairoint.h1054
-rw-r--r--test/.cvsignore54
-rw-r--r--test/Makefile.am205
-rw-r--r--test/buffer-diff.c105
-rw-r--r--test/buffer-diff.h22
-rw-r--r--test/buffer_diff.c73
-rw-r--r--test/buffer_diff.h38
-rw-r--r--test/cairo-test.c533
-rw-r--r--test/cairo-test.h12
-rw-r--r--test/cairo_test.c247
-rw-r--r--test/clip-nesting-ref.pngbin0 -> 1050 bytes
-rw-r--r--test/clip-nesting.c98
-rw-r--r--test/clip-twice.c11
-rw-r--r--test/clip_twice-ref.pngbin751 -> 0 bytes
-rw-r--r--test/coverage-ref.pngbin44324 -> 0 bytes
-rw-r--r--test/create-for-png-ref.png (renamed from test/move_to_show_surface-ref.png)bin100 -> 100 bytes
-rw-r--r--test/create-for-png.c69
-rw-r--r--test/create-from-png-ref.pngbin0 -> 100 bytes
-rw-r--r--test/create-from-png.c69
-rw-r--r--test/fill-and-stroke-ref.pngbin0 -> 279 bytes
-rw-r--r--test/fill-and-stroke.c63
-rw-r--r--test/fill-rule.c10
-rw-r--r--test/fill_rule-ref.pngbin1979 -> 0 bytes
-rw-r--r--test/fill_rule.c130
-rw-r--r--test/filter-nearest-offset-ref.pngbin0 -> 254 bytes
-rw-r--r--test/filter-nearest-offset.c107
-rw-r--r--test/get-and-set.c142
-rw-r--r--test/gradient-alpha-ref.pngbin0 -> 153 bytes
-rw-r--r--test/gradient-alpha.c (renamed from test/cairo_test.h)68
-rw-r--r--test/imagediff.c8
-rw-r--r--test/leaky-polygon.c8
-rw-r--r--test/leaky_polygon-ref.pngbin255 -> 0 bytes
-rw-r--r--test/line-width.c10
-rw-r--r--test/line_width-ref.pngbin171 -> 0 bytes
-rw-r--r--test/linear-gradient.c42
-rw-r--r--test/linear_gradient-ref.pngbin12724 -> 0 bytes
-rw-r--r--test/linear_gradient.c141
-rw-r--r--test/mask-ref.pngbin0 -> 87846 bytes
-rw-r--r--test/mask.c246
-rw-r--r--test/move-to-show-surface.c30
-rw-r--r--test/paint-ref.pngbin0 -> 116 bytes
-rw-r--r--test/paint-with-alpha-ref.pngbin0 -> 164 bytes
-rw-r--r--test/paint-with-alpha.c (renamed from test/move_to_show_surface.c)53
-rw-r--r--test/paint.c (renamed from test/line_width.c)36
-rw-r--r--test/path-data-ref.pngbin0 -> 387 bytes
-rw-r--r--test/path-data.c184
-rw-r--r--test/pdf-surface.c115
-rw-r--r--test/pixman-rotate.c56
-rw-r--r--test/pixman_rotate-ref.pngbin260 -> 0 bytes
-rw-r--r--test/pixman_rotate.c78
-rw-r--r--test/ps-surface.c115
-rw-r--r--test/read-png.c35
-rw-r--r--test/read_png.c166
-rw-r--r--test/read_png.h45
-rw-r--r--test/rel-path-ref.pngbin0 -> 212 bytes
-rw-r--r--test/rel-path.c56
-rw-r--r--test/scale-source-surface-paint-ref.pngbin0 -> 147 bytes
-rw-r--r--test/scale-source-surface-paint.c64
-rw-r--r--test/select-font-no-show-text.c64
-rw-r--r--test/self-copy-ref.pngbin0 -> 291 bytes
-rw-r--r--test/self-copy.c90
-rw-r--r--test/set-source-ref.pngbin0 -> 120 bytes
-rw-r--r--test/set-source.c87
-rw-r--r--test/source-clip-ref.pngbin0 -> 180 bytes
-rw-r--r--test/source-clip.c84
-rw-r--r--test/source-surface-scale-paint-ref.pngbin0 -> 147 bytes
-rw-r--r--test/source-surface-scale-paint.c64
-rw-r--r--test/surface-finish-twice.c74
-rw-r--r--test/surface-pattern-ref.pngbin0 -> 194 bytes
-rw-r--r--test/surface-pattern.c (renamed from test/clip_twice.c)64
-rwxr-xr-xtest/testsvg4
-rw-r--r--test/text-cache-crash.c26
-rw-r--r--test/text-rotate.c25
-rw-r--r--test/text_cache_crash.c133
-rw-r--r--test/text_rotate.c117
-rw-r--r--test/transforms-ref.pngbin0 -> 302 bytes
-rw-r--r--test/transforms.c111
-rw-r--r--test/translate-show-surface-ref.pngbin0 -> 100 bytes
-rw-r--r--test/translate-show-surface.c (renamed from test/leaky_polygon.c)69
-rw-r--r--test/trap-clip-ref.pngbin0 -> 71701 bytes
-rw-r--r--test/trap-clip.c (renamed from test/coverage.c)158
-rw-r--r--test/user-data.c82
-rw-r--r--test/write-png.c4
-rw-r--r--test/write-png.h2
-rw-r--r--test/write_png.c99
-rw-r--r--test/write_png.h35
-rw-r--r--test/xlib-surface.c269
-rw-r--r--test/xmalloc.c5
-rw-r--r--test/xmalloc.h2
-rwxr-xr-xutil/cairo-api-update60
201 files changed, 19669 insertions, 33188 deletions
diff --git a/ChangeLog b/ChangeLog
index abf671a09..55cb2b9e9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,2244 @@
+2005-05-17 Carl Worth <cworth@cworth.org>
+
+ * PORTING_GUIDE: Added porting guide to help with transition to
+ cairo 0.5 API.
+
+ * NEWS: Added notes for snapshot 0.5.0
+
+ * configure.in: Increment CAIRO_VERSION to 0.5.0
+
+2005-05-17 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-xcb-surface.c: (_get_image_surface),
+ (_cairo_xcb_surface_create_internal): Bring up to date with
+ Keith's latest improvements to cairo-xlib-surface.c: Add some
+ comments about how and why masks are computed. Generalize
+ overflow detection in mask computation. Expand on pixman format
+ conversion comment. Fix the broken visual->format case.
+
+2005-05-17 Carl Worth <cworth@cworth.org>
+
+ Two fixes from Kristian Høgsberg:
+
+ * src/cairo-output-stream.c: (_cairo_output_stream_create),
+ (_cairo_output_stream_destroy),
+ (_cairo_output_stream_create_for_file): Fix to close the file if
+ we opened it.
+
+ * src/cairo-pdf-surface.c: (_cairo_pdf_document_finish): Grab the
+ status from out of the stream _before_ we destroy the stream.
+
+2005-05-17 Keith Packard <keithp@keithp.com>
+
+ * src/cairo-xlib-surface.c: (_get_image_surface):
+ Add some comments about how and why masks are computed.
+ Generalize overflow detection in mask computation.
+ Expand on pixman format conversion comment.
+
+2005-05-17 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-xcb-surface.c:
+ * src/cairo-xlib-surface.c: Fix documentation to not mention
+ set_size for the _for_bitmap functions.
+
+2005-05-17 Carl Worth <cworth@cworth.org>
+
+ * util/cairo-api-update: Remove #ifdef munging since we once again
+ support either #if or #ifdef.
+
+2005-05-17 Carl Worth <cworth@cworth.org>
+
+ * RELEASING: Update instructions to match output of 'make
+ distcheck'
+
+ * src/Makefile.am:
+ * test/Makefile.am: Add private headers and flesh out CLEANFILES
+ so that 'make distcheck' actually passes.
+
+2005-05-17 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.h: Add a few more REPLACED_BY and DEPRECATED_BY
+ definitions.
+
+ * util/cairo-api-update: Add some helpful warnings.
+
+2005-05-17 Carl Worth <cworth@cworth.org>
+
+ * src/Makefile.am (libcairo_xlib_headers): Add
+ cairo-xlib-xrender.h which was missed from an earlier commit.
+
+2005-05-17 Carl Worth <cworth@cworth.org>
+
+ * src/Makefile.am:
+ * src/cairo-xcb.h:
+ * src/cairo-xcb-xrender.h:
+ * src/cairo-xcb-surface.c:
+ (cairo_xcb_surface_create),
+ (cairo_xcb_surface_create_for_bitmap),
+ (cairo_xcb_surface_create_with_xrender_format): Update cairo-xcb.h
+ to provide the same style of interface as cairo-xlib.h.
+
+ * test/cairo-test.c: Update to match new cairo_xcb_surface_t
+ create functions.
+
+2005-05-17 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-xlib-surface.c (_get_image_surface): Avoid shifting
+ 32-bit quanity by 32 bits, which is undefined behavior.
+
+2005-05-17 Carl Worth <cworth@cworth.org>
+
+ Rework of cairo_xlib_surface create functions by Keith Packard:
+
+ * src/cairo-xlib-xrender.h:
+ Add cairo_xlib_surface_create_with_render_format.
+
+ * src/cairo-xlib.h:
+ * src/cairo-xlib-surface.c:
+ (cairo_xlib_surface_create),
+ (cairo_xlib_surface_create_for_bitmap): Reduce Xlib constructors
+ down to two simple forms. Add width, height to constructors and
+ eliminate any synchronous size queries from the implementation.
+
+ * test/cairo-test.c: (create_xlib_surface):
+ * test/xlib-surface.c: (do_test): Update to match new
+ cairo_xlib_surface_t create functions.
+
+2005-05-17 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h:
+ * src/cairo-output-stream.c: Remove destroy_closure from
+ cairo_output_stream_t interface.
+
+ * src/cairo-pdf.h:
+ * src/cairo-pdf-surface.c: Remove destroy_closure argument from
+ cairo_pdf_surface_create_for_stream. Rename width,height to
+ width_in_points, height_in_points for better clarity.
+
+ * src/cairo-ps.h:
+ * src/cairo-ps-surface.c: Brush a bunch of dust off of the PS
+ backend and bring it up to date with the latest API conventions
+ from the PDF backend. These include: accepting a filename rather
+ than a FILE in the primary constructor, providing a stream-based
+ interface for more flexibility, and accepting a surface size in
+ device-space units (points) rather than inches.
+
+ * test/pdf-surface.c: (main): Make it a little more clear that the
+ width and height being passed around are in units of points.
+
+ * test/ps-surface.c: (main): Update to the latest cairo-ps.h
+ changes as described above. Notice how much more sane things
+ become now that the surface size is described in device-space
+ units.
+
+2005-05-17 Carl Worth <cworth@cworth.org>
+
+ * test/.cvsignore:
+ * test/Makefile.am:
+ * test/ps-surface.c: (draw), (main): Add simple test for ps
+ surface backend (modeled after pdf-surface.c).
+
+ * test/pdf-surface.c: (main): Add print message telling user to
+ examine resulting file.
+
+2005-05-17 Carl Worth <cworth@cworth.org>
+
+ * test/pdf-surface.c: (draw), (main): Update PDF test case to make
+ sure we're actually getting the right paper size, image scaling
+ etc. And it should now be easier to see if cairo is happy by manually
+ viewing the resulting PDF file.
+
+2005-05-17 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-xlib-test.h: Fix to include cairo-xlib.h, (which also
+ fixes test/xlib-surface.c).
+
+2005-05-17 Carl Worth <cworth@cworth.org>
+
+ * test/pdf-surface.c: (main): Update to the latest PDF surface API
+ changes: use filename not FILE* and use surface dimension in
+ points, not inches.
+
+2005-05-16 Keith Packard <keithp@keithp.com>
+
+ * src/cairo-pattern.c: (_cairo_pattern_shader_init):
+ Initialize op->stops[0].scale = 0.
+
+ This scale value is used only when computing gradient values
+ before the defined range, in which case stop 0 is used for both
+ ends of the interpolation, making the value of 'scale' not
+ actually matter, except that valgrind notices we're using
+ an undefined value.
+
+2005-05-16 Carl Worth <cworth@cworth.org>
+
+ * test/.cvsignore:
+ * test/Makefile.am: Remove quarter-over test name accidentally
+ added to Makefile.
+
+2005-05-16 Kristian Høgsberg <krh@redhat.com>
+
+ * src/cairo-pdf-surface.c (cairo_pdf_surface_create):
+ * src/cairo-output-stream.c
+ (_cairo_output_stream_create_for_file): Take a filename instead of
+ a FILE pointer.
+
+2005-05-14 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-xcb.h:
+ * src/cairo-xcb-surface.c: (_cairo_xcb_surface_create_similar),
+ (_cairo_xcb_surface_finish), (_cairo_xcb_surface_get_size),
+ (_bits_per_pixel), (_bytes_per_line), (_get_image_surface),
+ (_draw_image_surface), (_cairo_xcb_surface_get_extents),
+ (_cairo_surface_is_xcb), (_cairo_xcb_surface_create_internal),
+ (cairo_xcb_surface_create_for_pixmap),
+ (cairo_xcb_surface_create_for_pixmap_with_visual),
+ (cairo_xcb_surface_create_for_window_with_visual),
+ (cairo_xcb_surface_set_size):
+ Brush the dust off the XCB backend and get it compiling and
+ working again. This patch makes the XCB surface API match that of
+ the Xlib surface API as of yesterday. But, it's already stale as
+ the Xlib API changed again. So we'll need one more revision of the
+ XCB backend before the next snapshot.
+
+ * test/.cvsignore:
+ * test/Makefile.am:
+ * test/cairo-test.c: (create_xcb_surface), (cleanup_xcb):
+ * test/cairo-test.h: Add support for testing of the xcb backend as
+ well.
+
+2005-05-14 Carl Worth <cworth@cworth.org>
+
+ * test/cairo-test.c: (cairo_test_real):
+ * test/pdf-surface.c: (main):
+ * test/xlib-surface.c: (do_test), (main): Cleanup output a bit,
+ move verbose messages to test-specific log file.
+
+2005-05-14 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-xlib-surface.c: (cairo_xlib_surface_create_with_visual):
+ Fix the last commit so it actually compiles now.
+
+2005-05-14 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-xlib-surface.c: (cairo_test_xlib_disable_render),
+ (cairo_xlib_surface_create_with_visual)
+
+ * test/.cvsignore: Fix a few documentation typos in the recent
+ xlib surface rework.
+
+2005-05-14 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-atsui.h:
+ * src/cairo-ft.h:
+ * src/cairo-glitz.h:
+ * src/cairo-pdf.h:
+ * src/cairo-ps.h:
+ * src/cairo-quartz.h:
+ * src/cairo-win32.h:
+ * src/cairo-xcb.h:
+ * src/cairo-xlib.h: Add an #error if cairo-foo.h is included when
+ cairo was compiled without support for the foo backend.
+
+2005-05-14 Carl Worth <cworth@cworth.org>
+
+ * test/pdf-surface.c (main): Update for change in
+ cairo_pdf_surface_create which no longer accepts DPI values.
+
+2005-05-13 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-xlib-surface.c src/cairo-xlib.h
+ doc/public/cairo-sections.txt: Drop the _for_pixmap() and
+ _for_window() out of the create functions and use some lazy
+ cleverness to sniff the information out as needed.
+
+ * src/cairo-xlib-surface.c src/cairo-xlib-test.h Makefile.am:
+ add cairo_test_xlib_disable_render() to turn off RENDER
+ for tests.
+
+ * test/xlib-surface.c: Test various different types of
+ Xlib surface creation.
+
+ * src/cairo-xlib.h: Remove left-over include of Xrender.h.
+
+2005-05-13 Kristian Høgsberg <krh@redhat.com>
+
+ * src/cairo-pdf-surface.c (_cairo_pdf_document_open_stream): Make
+ this a varg function and use the new
+ _cairo_output_stream_vprintf() function to format extra dict
+ contents.
+
+ * src/cairo-output-stream.c (_cairo_output_stream_vprintf):
+ Reimplement the printf logic so we can special case formatting of
+ doubles to be locale independent and trim trailing zeros.
+
+ * src/cairo-pdf-surface.c: Rename
+ cairo_pdf_surface_create_for_callback() to
+ cairo_pdf_surface_create_for_stream(), and change PDF constructors
+ to take width and height as points and move PPI setting to
+ cairo_pdf_surface_set_ppi()
+
+2005-05-13 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-xlib-surface.c (_cairo_xlib_surface_create_internal): Fix
+ misplaced goto.
+
+2005-05-12 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h:
+ * src/cairo-image-surface.c: (_cairo_image_surface_create_with_masks):
+ Fix image->data to be unsigned
+
+ * src/cairo-glitz-surface.c: (_cairo_glitz_surface_get_image):
+ * src/cairo-image-surface.c:
+ (_cairo_image_surface_create_for_pixman_image),
+ * src/cairo-xlib-surface.c: (_get_image_surface),
+ (_draw_image_surface), (_xlib_glyphset_cache_create_entry):
+ Track change in signedness of data member/parameter.
+
+2005-05-12 Carl Worth <cworth@cworth.org>
+
+ Update xcb backend to compile after recent API changes:
+
+ * src/cairo-xcb-surface.c: (_cairo_xcb_surface_finish):
+ Fix missing return value.
+ (_cairo_xcb_surface_acquire_source_image): Remove calls to
+ non-existent cairo_surface functions.
+ (_cairo_xcb_surface_set_matrix): Update for new matrix member names.
+ (_cairo_xcb_surface_get_extents): Fix typo.
+
+2005-05-12 Carl Worth <cworth@cworth.org>
+
+ * test/.cvsignore:
+ * test/Makefile.am:
+ * test/paint-with-alpha-ref.png:
+ * test/paint-with-alpha.c: (draw), (main): Add new test for bug in
+ cairo_paint_with_alpha not transforming the source.
+
+ * src/cairo-gstate.c: (_cairo_gstate_mask): Use a transformed copy
+ of the source just like we do in all the other calls to
+ cairo_surface_composite. Fixes the bug tested by
+ test/paint-with-alpha.
+
+2005-05-12 Keith Packard <keithp@keithp.com>
+
+ reviewed by: otaylor
+
+ * src/cairo-gstate.c: (_get_mask_extents):
+ _get_mask_extents creates a pixman region but
+ neglects to destroy it.
+
+2005-05-11 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-win32-surface.c (categorize_solid_dest_operator):
+ Handle more cases by assuming no-super-luminescent colors.
+
+2005-05-11 T Rowley <tim.rowley@gmail.com>
+
+ * src/cairo-atsui-font.c:
+ * src/cairo-atsui.h:
+ * src/cairo-quartz-surface.c: Revive quartz backend.
+
+2005-05-11 David Reveman <davidr@novell.com>
+
+ * src/cairo-glitz-surface.c (_cairo_glitz_surface_fill_rectangles):
+ Set fill type repeat on source surface.
+ (_cairo_glitz_surface_show_glyphs): Add missing cairo operator to
+ glitz operator conversion.
+ (_cairo_glitz_surface_show_glyphs): Only render glyphs with non zero
+ size.
+
+2005-05-11 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-surface.c (_fallback_fill_rectangles):
+ Fix bounding box computation.
+
+ * src/cairo-win32-surface.c: Patch from Tor Lillqvist
+ to make things compile and work again.
+
+ * test/cairo-test.c (create_win32_surface): Don't
+ #error because there is no win32 test, it isn't useful.
+ Just skip it.
+
+ * src/cairo-win32-font.c: Fix up matrix constness.
+
+ * test/Makefile.am (TESTS): Skip the pdf-surface test
+ if we don't have the PDF backend.
+
+ * src/cairo-win32-surface.c (categorize_solid_dest_operator):
+ Optimize fill_rectangles for all cases where the destination
+ ends up a solid color.
+
+2005-05-11 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-xlib-surface.c src/cairo-xlib.h: Remove leftover
+ cairo_xlib_surface_create().
+
+2005-05-10 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo.c src/cairo-path-data.c src/cairo-path-data-private.h:
+ Pass the gstate to _cairo_path_data_create[_flat] and use
+ _cairo_gstate_backend_to_user() so as to properly handle
+ the surface device offset.
+
+2005-05-10 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-arc.c (_cairo_arc_path_negative): Don't use return
+ when calling a void function (thanks to Damien Carbery
+ <damien.carbery@sun.com>). Closes bug #3134.
+
+2005-05-10 Carl Worth <cworth@cworth.org>
+
+ * test/cairo-test.c:
+ * test/cairo-test.h: Removing mucking around with stderr and add a
+ cairo_test_log function instead.
+
+ * test/buffer-diff.c:
+ * test/create-for-png.c:
+ * test/pdf-surface.c:
+ * test/read-png.c:
+ * test/trap-clip.c:
+ * test/xmalloc.c: Switch all error messages from
+ fprintf(stderr,...) to cairo_test_log(...).
+
+2005-05-10 Carl Worth <cworth@cworth.org>
+
+ * configure.in: Fix URLs for glitz and xlibs, (thanks to Jason
+ Dorje Short <jdorje@users.sf.net>).
+
+2005-05-10 Carl Worth <cworth@cworth.org>
+
+ * configure.in: Update to current canonical URL for XCB.
+
+2005-05-10 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-wideint.h: Don't guess and make our own definitions
+ for uint8_t, etc. Just error out if we can't find a suitable
+ header file.
+
+ * src/cairo-png.c: (unpremultiply_data), (premultiply_data):
+ * test/read-png.c: (premultiply_data): Fix to use fixed-size type
+ so that this code works when sizeof(unsigned long) != 32. Thanks
+ to Manish Singh.
+
+2005-05-10 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-gstate.c: (_cairo_gstate_get_font_matrix):
+ * src/cairo.c: (cairo_get_font_matrix):
+ * src/cairo.h:
+ * src/cairoint.h: Fix cairo_get_font_matrix to actually use its
+ out-parameter. And change the return type to void.
+
+2005-05-09 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-ft-font.c (_cairo_ft_unscaled_font_create_glyph):
+ Get the glyphslot point *after* we get the FT_Face. (Robert O'Callahan)
+
+2005-05-09 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.h (cairo_current_target_surface): Fix deprecation
+ macro to point to the right function, (thanks to John Ellson).
+
+2005-05-09 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-font.c: (_cairo_simple_font_face_create_font),
+ (cairo_scaled_font_create), (_cairo_scaled_font_init):
+ * src/cairo-ft-font.c: (_ft_scaled_font_create),
+ (_cairo_ft_scaled_font_create), (_ft_font_face_create_font):
+ * src/cairo-gstate.c: (_cairo_gstate_transform),
+ (_cairo_gstate_set_matrix), (_cairo_gstate_set_font_matrix):
+ * src/cairo-image-surface.c: (_cairo_image_surface_set_matrix):
+ * src/cairo-matrix.c: (_cairo_matrix_get_affine),
+ (cairo_matrix_transform_distance), (cairo_matrix_transform_point),
+ (_cairo_matrix_transform_bounding_box),
+ (_cairo_matrix_compute_determinant),
+ (_cairo_matrix_compute_eigen_values),
+ (_cairo_matrix_compute_scale_factors),
+ (_cairo_matrix_is_integer_translation):
+ * src/cairo-pattern.c: (cairo_pattern_set_matrix),
+ (_cairo_pattern_transform):
+ * src/cairo.c: (cairo_transform), (cairo_set_matrix),
+ (cairo_set_font_matrix):
+ * src/cairo.h:
+ * src/cairoint.h: Push cairo_matrix_t const-correctness down
+ through the entire implmentation, (expanding on preliminary work
+ by Robert O'Callahan <rocallahan@novell.com>)
+
+2005-05-09 Carl Worth <cworth@cworth.org>
+
+ * configure.in:
+ * src/cairo-features.h.in: Change cairo-features again so that
+ either #if or #ifdef will work to test any feature.
+
+2005-05-07 Owen Taylor <otaylor@redhat.com>
+
+ * doc/public/language-bindings.xml doc/public/cairo-doc.xml
+ doc/public/Makefile.am: Document suggested conventions and
+ techniques for many aspects of creating a language binding
+ for Cairo.
+
+2005-05-07 Owen Taylor <otaylor@redhat.com>
+
+ * doc/public/cairo-sections.txt: Update.
+
+2005-05-07 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.h (cairo_set_alpha): Point to both
+ cairo_set_source_rgba and cairo_paint_with_alpha in deprecation of
+ cairo_set_alpha.
+
+2005-05-07 Carl Worth <cworth@cworth.org>
+
+ * util/cairo-api-update: Make idempotent substitutions that extend
+ old names:
+
+ cairo_select_font -> cairo_select_font_face
+ cairo_pattern_add_color_stop -> cairo_pattern_add_color_stop_rgba
+
+ by only substituting if the old name is not immediately followed
+ by an underscore.
+
+ Tweak the substitution slightly to allow the script to be run on
+ the cairo source itself, (eg. avoid changing the REPLACED_BY and
+ DEPRECATED_BY macros that must mention the old names).
+
+2005-05-07 Carl Worth <cworth@cworth.org>
+
+ * configure.in:
+
+ * src/cairo-features.h.in: Change definitions of everything in
+ cairo-features.h to prefer #if over #ifdef.
+
+ * src/cairo-atsui.h:
+ * src/cairo-cache.c:
+ * src/cairo-ft-private.h:
+ * src/cairo-ft.h:
+ * src/cairo-glitz.h:
+ * src/cairo-pdf.h:
+ * src/cairo-ps.h:
+ * src/cairo-quartz.h:
+ * src/cairo-win32.h:
+ * src/cairo-xcb.h:
+ * src/cairo-xlib.h:
+ * src/cairo.c:
+ * src/cairo.h:
+ * src/cairoint.h:
+ * test/cairo-test.c: Track #ifdef -> #if changes.
+
+ * util/cairo-api-update: Add support to automatically change all
+ #ifdef CAIRO_HAS to #if CAIRO_HAS.
+
+2005-05-07 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-gstate.c:
+ * src/cairo-pattern.c:
+ * src/cairo.c:
+ * src/cairo.h:
+ * src/cairoint.h: Remove deprecated cairo_get_rgb_color that was
+ accidentally missed in the recent purge of deprecated functions.
+
+2005-05-07 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-xcb-surface.c (_render_operator):
+ * src/cairo-win32-surface.c (_cairo_win32_surface_composite)
+ (_cairo_win32_surface_fill_rectangles): Update to track new
+ CAIRO_OPERATOR names.
+
+ * test/select-font-no-show-text.c:
+ * src/cairo-surface.c (cairo_surface_set_user_data): Fix
+ documentation to refer to functions by their current names.
+
+ * src/cairo-gstate.c (_cairo_gstate_begin_group): Update to track
+ latest API (in currently unused function).
+
+2005-05-06 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-glitz-surface.c (_cairo_glitz_surface_show_glyphs):
+ Fix return type from cairo_status_t to cairo_int_status_t.
+
+2005-05-06 Carl Worth <cworth@cworth.org>
+
+ * ROADMAP: Note that cairo_mask, and "just eliminate a bunch of
+ functions are now done".
+
+ * TODO: Note that all backwards-compatible and
+ backwards-incompatible cahnges for the API Shakeup are now
+ done. Sort "new functionality" of API Shakeup into its own
+ category.
+
+2005-05-06 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.c:
+ * src/cairo.h: Eliminate the following deprecated functions from
+ cairo's interface:
+
+ cairo_copy
+ cairo_get_path
+ cairo_get_path_flat
+ cairo_matrix_create
+ cairo_matrix_destroy
+ cairo_matrix_copy
+ cairo_matrix_get_affine
+ cairo_surface_set_repeat
+ cairo_surface_set_matrix
+ cairo_surface_get_matrix
+ cairo_surface_set_filter
+ cairo_surface_get_filter
+
+ Also, eliminate all support for compiling against, or running with
+ old, deprecated names for functions.
+
+ * src/cairo-ft-font.c: (_compute_transform):
+ * src/cairo-gstate.c:
+ * src/cairo-image-surface.c: (cairo_image_surface_create_for_data):
+ * src/cairo-matrix.c: (_cairo_matrix_get_affine),
+ (_cairo_matrix_compute_adjoint),
+ (_cairo_matrix_is_integer_translation):
+ * src/cairo-pattern.c: (cairo_pattern_add_color_stop_rgba),
+ (cairo_pattern_set_matrix), (cairo_pattern_get_matrix),
+ (_cairo_image_data_set_linear), (_cairo_linear_pattern_classify),
+ (_cairo_image_data_set_radial):
+ * src/cairo-pdf-surface.c: (_cairo_pdf_surface_composite_image),
+ (_cairo_pdf_surface_composite_pdf), (emit_surface_pattern),
+ (emit_linear_pattern), (emit_radial_pattern):
+ * src/cairo-surface.c:
+ * src/cairo-xlib-surface.c:
+ (_cairo_xlib_surface_acquire_source_image),
+ (cairo_xlib_surface_create):
+ * src/cairo.c: (cairo_set_source_rgba), (cairo_set_source),
+ (cairo_get_source), (cairo_transform), (cairo_identity_matrix),
+ (cairo_user_to_device), (cairo_user_to_device_distance),
+ (cairo_device_to_user), (cairo_device_to_user_distance),
+ (cairo_reset_clip), (cairo_select_font_face), (cairo_font_extents),
+ (cairo_set_font_size), (cairo_get_operator), (cairo_get_rgb_color),
+ (cairo_get_tolerance), (cairo_get_fill_rule),
+ (cairo_get_line_width), (cairo_get_line_cap),
+ (cairo_get_line_join), (cairo_get_miter_limit), (cairo_get_matrix),
+ (cairo_get_target), (cairo_status), (cairo_status_string):
+ * src/cairoint.h:
+ * test/cairo-test.c: (cairo_test_create_png_pattern):
+ * test/gradient-alpha.c: (draw):
+ * test/mask.c: (set_gradient_pattern), (set_image_pattern):
+ * test/move-to-show-surface.c: (draw):
+ * test/select-font-no-show-text.c: (draw):
+ * test/set-source.c: (draw):
+ * test/text-cache-crash.c: (draw):
+ * test/text-rotate.c: (draw):
+ * test/transforms.c: (draw_L_shape):
+ * test/translate-show-surface.c: (draw):
+ * test/trap-clip.c: (set_gradient_pattern), (set_image_pattern):
+ * util/cairo-api-update:
+
+ Deal with all of the removals.
+
+2005-05-06 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-glitz-surface.c: (_glitz_operator),
+ (_cairo_glitz_surface_fill_rectangles):
+ * src/cairo-gstate.c: (_cairo_gstate_mask):
+ * src/cairo-image-surface.c: (_pixman_operator),
+ (_cairo_image_surface_composite_trapezoids):
+ * src/cairo-ps-surface.c: (_cairo_ps_surface_erase),
+ (_cairo_ps_surface_copy_page):
+ * src/cairo-surface.c: (_cairo_surface_create_similar_solid):
+ * src/cairo-xlib-surface.c: (_render_operator):
+ * src/cairo.h:
+ * test/cairo-test.c: (cairo_test_for_target):
+ * test/mask.c: (mask_polygon), (draw):
+
+ Rename and re-order the cairo_operator_t enum to names that
+ abbreviate less and are easier to understand,
+ (eg. CAIRO_OPERATOR_DEST_OVER instead of
+ CAIRO_OPEERATOR_OVER_REVERSE).
+
+2005-05-06 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.c: (cairo_create), (cairo_save), (cairo_get_target):
+ * src/cairo.h:
+ * src/cairoint.h:
+ * src/cairo-gstate.c: (_cairo_gstate_create), (_cairo_gstate_init),
+ (_cairo_gstate_get_target):
+ * src/cairo-glitz.h:
+ * src/cairo-pdf.h:
+ * src/cairo-ps.h:
+ * src/cairo-quartz-surface.c:
+ * src/cairo-quartz.h:
+ * src/cairo-surface.c: (_cairo_surface_begin):
+ * src/cairo-win32.h:
+ * src/cairo-xcb.h:
+ * src/cairo-xlib.h: Remove cairo_set_target_surface and all other
+ backend-specific cairo_set_target functions. Require a
+ cairo_surface_t* to call cairo_create.
+
+ * test/cairo-test.c: (create_image_surface), (cleanup_image),
+ (create_glitz_surface), (cleanup_glitz), (create_quartz_surface),
+ (cleanup_quartz), (create_win32_surface), (cleanup_win32),
+ (create_xcb_surface), (cleanup_xcb), (create_xlib_surface),
+ (cleanup_xlib), (cairo_test_for_target), (cairo_test_real):
+
+ Port to use new cairo_create interface.
+
+ * test/clip-nesting.c: (draw):
+ * test/mask.c: (mask_polygon), (draw):
+ * test/path-data.c: (main):
+ * test/pdf-surface.c: (main):
+ * test/pixman-rotate.c: (draw):
+ * test/scale-source-surface-paint.c: (draw):
+ * test/self-copy.c: (draw):
+ * test/source-clip.c: (draw):
+ * test/source-surface-scale-paint.c: (draw):
+ * test/surface-pattern.c: (draw):
+
+ Rewrite all tests that were using cairo_set_target_surface to
+ instead create a temporary cairo_t, (eventually to be replaced
+ with cairo_begin_group).
+
+2005-05-05 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo.[ch] doc/public/cairo-sections.txt: Add
+ cairo_paint_with_alpha().
+
+ * src/cairo-pattern.c (_cairo_pattern_acquire_surfaces): Fix
+ segfault when mask == NULL.
+
+ * test/mask.c test/mask-ref.png: Add testing of cairo_paint_with_alpha().
+
+ * test/coverage.c test/coverage-ref.png: Remove ... it's not testing
+ anything that mask doesn't test better.
+
+2005-05-04 David Reveman <davidr@novell.com>
+
+ * src/cairo-glitz-surface.c: Add glyph caching to glitz backend.
+
+2005-05-03 Kristian Høgsberg <krh@redhat.com>
+
+ Fills as paths patch originally by Owen Taylor.
+
+ * src/cairo-path.c: (_cairo_path_fixed_rel_move_to),
+ (_cairo_path_fixed_line_to), (_cairo_path_fixed_rel_line_to),
+ (_cairo_path_fixed_curve_to), (_cairo_path_fixed_rel_curve_to):
+ Make sure we have a current point for the relative path operators.
+
+ * src/cairoint.h:
+ * src/cairo-gstate.c: (_cairo_gstate_fill):
+ * src/cairo-surface.c: (_cairo_surface_fill_path): Add fill_path
+ backend method.
+
+ * src/cairo-pdf-surface.c: (_cairo_pdf_document_close_stream),
+ (emit_image_data), (emit_surface_pattern),
+ (_cairo_pdf_path_move_to), (_cairo_pdf_path_line_to),
+ (_cairo_pdf_path_curve_to), (_cairo_pdf_path_close_path),
+ (_cairo_pdf_surface_fill_path): Implement fill_path in the PDF
+ backend.
+
+2005-05-03 Carl Worth <cworth@cworth.org>
+
+ Originally 2005-04-20 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.h:
+ * src/cairo.c: Remove cairo_show_surface. Add new
+ cairo_set_source_surface.
+
+ * src/cairo-gstate.c: Remove _cairo_gstate_show_surface.
+
+ * test/create-for-png.c: (draw):
+ * test/pixman-rotate.c: (draw):
+ * test/move-to-show-surface.c: (draw):
+ * test/translate-show-surface.c: (draw): Replace calls to
+ cairo_show_surface with cairo_set_source_surface; cairo_paint.
+
+ * test/cairo-test.c: (cairo_test_real): Fix messages to prefer -
+ over _.
+
+ * src/cairo-png.c: (cairo_surface_write_to_png): Fix
+ documentation.
+
+ * test/filter-nearest-offset-ref.png:
+ * test/filter-nearest-offset.c:
+ * test/scale-source-surface-paint-ref.png:
+ * test/scale-source-surface-paint.c:
+ * test/source-surface-scale-paint-ref.png:
+ * test/source-surface-scale-paint.c: Three new tests to exercise
+ set_source_surface more completely, (two of these are expected
+ failures dues to outstanding bugs).
+
+2005-05-03 Carl Worth <cworth@cworth.org>
+
+ * TODO: Add suggestion for copy-on-write regions to fix clip
+ region problems.
+
+ * src/Makefile.am (install-data-local): Fix check for old headers
+ to respect DESTDIR, (to work better when cross-compiling, etc.).
+ Thanks to Luke-Jr <luke-jr@utopios.org>.
+
+2005-05-02 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-ft-font.c (_cairo_ft_scaled_font_font_extents): Changes the
+ sign of extents->descent to match win32 backend and the conventional
+ convention.
+
+ * src/cairo.h: Document cairo_font_extents_t.
+
+2005-04-28 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-surface.c src/cairoint.h: Add _cairo_surface_begin/end
+ to save and restore the clip state of a surface. Copy and store
+ clip regions set on a surface so that we can save and restore them.
+
+ * src/cairo.[ch]: Add a CAIRO_STATUS_BAD_NESTING error
+ for interleaved use of two cairo_t's on the same surface. Also,
+ add a skeleton doc comment for cairo_status_t.
+
+ * src/cairo.c src/cairo-gstate.c src/cairoint.h: Use
+ _cairo_surface_begin/end to replace
+ _cairo_gstate_restore_external_state.
+
+ * src/cairo-gstate.c: Use _cairo_surface_begin/end to save the
+ state of a surface when we start drawing at it and restore it
+ at the end. Check that the save level of the surface is what
+ we expect on drawing operations and fail with CAIRO_STATUS_BAD_NESTING
+ otherwise.
+
+ * src/cairo-pattern.c src/cairoint.h (_cairo_pattern_acquire_surface_for_surface)
+ (_cairo_pattern_release_surface): Surround use of pattern->surface
+ with _cairo_surface->begin/end so we don't clip surfaces used as
+ sources.
+
+ * test/clip-nesting.c test/Makefile.am: Test of destinatin
+ clipping with the nested creation of cairo_t's for the same
+ context.
+
+ * test/source-clip.c test/Makefile.am: Test that clipping on
+ a source as a destination doesn't affect use of it as a source.
+
+ * test/self-copy.c: XFAIL test for copying from a surface as
+ a source to itself as a destination with a clip.
+
+2005-05-02 Keith Packard <keithp@keithp.com>
+
+ reviewed by: cworth
+
+ * src/cairo-path.c: (_cairo_path_fixed_rel_curve_to):
+ Use correct arguments to compute absolute positions.
+
+ * test/Makefile.am:
+ * test/rel-path-ref.png:
+ * test/rel-path.c: (draw), (main):
+ Test cairo_rel_move_to, cairo_rel_line_to and cairo_rel_curve_to
+
+2005-05-02 Owen Taylor <otaylor@redhat.com>
+
+ * test/Makefile.am (EXTRA_DIST): mask-ref.png, not
+ mask.png. (Pointed out by Carl)
+
+2005-05-02 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo.[ch] src/cairo-gstate.c: Add cairo_mask()
+ and cairo_mask_surface().
+
+ * test/maks.c tests/Makefile.am tests/mask-ref.png: Add a
+ comprehensive tests for cairo_mask().
+
+ * docs/public/cairo-sections.txt: Updated
+
+2005-05-02 Kristian Høgsberg <krh@redhat.com>
+
+ * src/cairo-gstate.c (_cairo_gstate_glyph_path): Also call
+ _cairo_gstate_ensure_font() for this function.
+
+2005-04-28 Owen Taylor <otaylor@redhat.com>
+
+ * TODO, ROADMAP: Add a item about reworking cairo_format_t.
+
+2005-04-28 Carl Worth <cworth@cworth.org>
+
+ * test/.cvsignore:
+ * test/cairo-test.c: (cairo_test_for_target): Replace annoying _
+ in output image filenames with - for better consistency.
+
+2005-04-27 Carl Worth <cworth@cworth.org>
+
+ * test/cairo-test.c: (set_xlib_target), (cleanup_xlib_target):
+ Use 1 instead of 0 for width and height to avoid BadValue errors
+ from XCreatePixmap.
+
+2005-04-27 Carl Worth <cworth@cworth.org>
+
+ * test/.cvsignore:
+ * test/buffer-diff.c: (xunlink), (buffer_diff), (image_diff):
+ * test/buffer-diff.h:
+ * test/cairo-test.c: (set_image_target), (cleanup_image_target),
+ (set_glitz_target), (cleanup_glitz_target), (set_quartz_target),
+ (cleanup_quartz_target), (set_win32_target),
+ (cleanup_win32_target), (set_xcb_target), (cleanup_xcb_target),
+ (set_xlib_target), (cleanup_xlib_target), (cairo_test_for_target),
+ (cairo_test_real), (cairo_test_expect_failure), (cairo_test):
+ * test/cairo-test.h:
+ * test/read-png.c: (read_png_argb32):
+ * test/xmalloc.h: Add support for testing multiple backends,
+ courtesy of cairo_surface_write_to_png. Currently, only image and
+ xlib backends are fullk hooked-up, but other backends should be
+ quite easy to add for anyone skilled in the appropriate art.
+
+2005-04-27 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-traps.c src/cairoint.h (_cairo_traps_init_box):
+ New function to create a single trapezoid box.
+
+ * src/cairo.c src/cairo-gstate.c src/cairoint.h: Move
+ the implementation of cairo_paint() into cairo-gstate.c
+ for a better fix for the problem with backend/user coordinate
+ confusion. Also no longer clear the current path on
+ cairo_paint().
+
+2005-04-26 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.c (cairo_paint): Build rectangle with an identity
+ matrix in place so that the entire target surface will be filled
+ even when there is a transformation in place.
+
+2005-04-26 Owen Taylor <otaylor@redhat.com>
+
+ * doc/public/cairo-sections.txt: Updated.
+
+ * src/cairo-png.c src/cairo.h: Fix up some doc build issues.
+
+2005-04-26 Carl Worth <cworth@cworth.org>
+
+ * test/.cvsignore:
+ * test/Makefile.am:
+ * test/paint-ref.png:
+ * test/paint.c: (draw), (main): Add test to demonstrate bug in
+ cairo_paint when under a non-identity transformation.
+
+2005-04-26 Carl Worth <cworth@cworth.org>
+
+ * ROADMAP:
+ * TODO: Note that cairo_paint and cairo_clip/fill/stroke_preserve
+ are all done now.
+
+2005-04-26 Carl Worth <cworth@cworth.org>
+
+ Originally: 2005-04-19 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.h: Add cairo_stroke_preserve, cairo_fill_preserve,
+ and cairo_clip_preserve.
+
+ * src/cairoint.h:
+ * src/cairo-gstate-private.h:
+ * src/cairo-gstate.c: Rip the path out of cairo_gstate_t.
+
+ * src/cairo-private.h: Add path to cairo_t.
+
+ * src/cairo.c: Bring in most of the path code that used to live in
+ cairo-gstate.c
+
+ * src/Makefile.am:
+ * src/cairo-arc-private.h:
+ * src/cairo-arc.c: Move arc generation code into its own file.
+
+ * src/cairo-path-data-private.h:
+ * src/cairo-path-data.c: Accept path+ctm_inverse+tolerance instead
+ of gstate. Absorb flattening and device space->user space
+ conversion that used to be in _cairo_gstate_intepret_path.
+
+ * src/cairo-path.c: Prefer cairo_fixed_t parameters over
+ ciaro_point_t for cross-file interfaces.
+
+ * src/cairo-ft-font.c: Track changes in _cairo_path_fixed
+ interfaces.
+
+ * test/fill-and-stroke.c: (draw): Port to use cairo_fill_preserve
+ rather than cairo_save/cairo_restore which no longer work for
+ saving the path.
+
+ * test/get-and-set.c: (settings_set), (settings_get),
+ (settings_equal): Remove get and set of current point since it is
+ no longer affected by cairo_save and cairo_restore. Add get and
+ set testing for cairo_matrix_t.
+
+2005-04-26 Carl Worth <cworth@cworth.org>
+
+ * test/.cvsignore:
+ * test/Makefile.am:
+ * test/cairo-test.h:
+ * test/pdf-surface.c: (main): Add very simple test to generate PDF
+ output, (no automated verification yet).
+
+ * test/cairo-test.c: (cairo_test):
+ * test/create-for-png.c: (draw):
+ * test/pixman-rotate.c: Track PNG interface changes, (no more
+ include of cairo-png.h, cairo_surface_write_png renamed to
+ cairo_surface_write_to_png).
+
+2005-04-26 Kristian Høgsberg <krh@redhat.com>
+
+ * src/cairo-png.h: Prototypes moved to cairo.h, this file removed.
+
+ * src/cairo-png.c (cairo_surface_write_to_png_stream): Renamed
+ from cairo_surface_write_png_to_stream() for consistency.
+ (cairo_surface_write_to_png): Renamed from
+ cairo_surface_write_png() for consistency.
+
+2005-04-25 Kristian Høgsberg <krh@redhat.com>
+
+ * src/cairo-png.c (cairo_surface_write_png): Factor out bulk of
+ the code into a new callback based function, write_png(). Call it
+ with a stdio write callback.
+ (cairo_surface_write_png_to_stream): New function to write a
+ surface to a PNG stream.
+ (cairo_image_surface_create_from_png): Likewise, move most of the
+ code to read_png(), clean up error handling and reduce this
+ function to calling read_png() with a stdio based read function.
+ (cairo_image_surface_create_from_png_stream): New function to
+ create an image surface from a PNG stream.
+
+ * src/cairo-image-surface.c (cairo_image_surface_get_width)
+ (cairo_image_surface_get_height): New functions to get widht and
+ height of an image surface.
+
+ * src/cairo.h: Add new prototype and error codes.
+
+ * test/create-for-png.c (draw): Adjust to new PNG API.
+
+2005-04-25 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-win32-surface.c (cairo_win32_surface_create): Initialize
+ the saved_dc_bitmap field here as well ... not strictly needed,
+ but cleaner. (Reported by Peter Arsoff)
+
+2005-04-23 Kristian Høgsberg <krh@redhat.com>
+
+ * src/cairo-gstate.c (_composite_trap_region): Finalize the
+ correct pattern.
+
+2005-04-22 Kristian Høgsberg <krh@redhat.com>
+
+ * src/cairo-png.c (cairo_image_surface_create_for_png): Only check
+ PNG signature if we read all the bytes. Don't fclose() the FILE
+ argument (Steve Chaplin <stevech1097@yahoo.com.au>).
+
+ Rename to cairo_image_surface_create_for_png() to
+ cairo_image_surface_create_from_png() and change FILE arguments
+ for this function and cairo_surface_write_png() to be a filename
+ argument instead.
+
+2005-04-21 Kristian Høgsberg <krh@redhat.com>
+
+ * src/cairo-surface.c (_cairo_surface_set_clip_region): Handle
+ backends that don't have a set_clip_region implementation (PDF).
+
+2005-04-19 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.c: (cairo_paint):
+ * src/cairo.h: Add new cairo_paint function.
+
+ * src/cairoint.h: Add new get_extents function to the surface
+ backend interface.
+
+ * src/cairo-gstate.c: (_cairo_gstate_get_clip_extents): Add
+ function to query current clip_extents.
+
+ * src/cairo-glitz-surface.c: (_cairo_glitz_surface_get_extents):
+ * src/cairo-image-surface.c: (_cairo_image_surface_get_extents),
+ (_cairo_image_abstract_surface_get_extents):
+ * src/cairo-pdf-surface.c: (_cairo_pdf_surface_get_extents):
+ * src/cairo-ps-surface.c: (_cairo_ps_surface_get_extents):
+ * src/cairo-quartz-surface.c: (_cairo_quartz_surface_get_extents):
+ * src/cairo-win32-surface.c: (_cairo_win32_get_extents):
+ * src/cairo-xcb-surface.c: (_cairo_xcb_surface_get_extents):
+ * src/cairo-xlib-surface.c: (_cairo_xlib_surface_get_extents):
+ Implement the new get_extents function for each backend.
+
+ * src/cairo-surface.c: (_cairo_surface_init),
+ (_cairo_surface_set_clip_region),
+ (_cairo_surface_get_clip_extents): Save the clip extents from
+ set_clip_region and implement _cairo_surface_get_clip_extents.
+
+ * src/cairo-xlib-surface.c: (_cairo_xlib_surface_get_size),
+ (_get_image_surface): Abstract away the evil XGetGeometry
+ roundtrip in _cairo_xlib_surface_get_size.
+
+ * test/gradient-alpha.c: (draw):
+ * test/linear-gradient.c: (draw): Rewrite a couple of tests to
+ call cairo_paint.
+
+2005-04-19 Carl Worth <cworth@cworth.org>
+
+ * TODO: Update API Shakeup chart to indicate that cairo_paint and
+ cairo_fill_preserve patches have been sent.
+
+2005-04-19 Carl Worth <cworth@cworth.org>
+
+ * test/.cvsignore:
+ * test/Makefile.am:
+ * test/surface-pattern-ref.png:
+ * test/surface-pattern.c: (draw), (main): Add a test of a
+ repeating surface pattern.
+
+2005-04-18 Carl Worth <cworth@cworth.org>
+
+ * ROADMAP: Mark a couple of items that are now complete.
+
+ * test/.cvsignore:
+ * test/Makefile.am:
+ * test/fill-and-stroke-ref.png:
+ * test/fill-and-stroke.c: (draw), (main): Add test case that fills
+ and strokes the same shapes, (in preparation for testing
+ cairo_fill_preserve patch).
+
+2005-04-14 Carl Worth <cworth@cworth.org>
+
+ * TODO: Update API Shakeup chart to indicate that cairo_set_source
+ is done.
+
+2005-04-14 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.h:
+ * src/cairo.c: Rename, add, and delete:
+
+ cairo_set_pattern -> cairo_set_source
+ cairo_get_pattern -> cairo_get_source
+ cairo_set_rgb_color -> cairo_set_source_rgb
+ -> cairo_set_source_rgba
+ cairo_set_alpha ->
+ cairo_get_alpha ->
+
+ Note that we'll likely want to add cairo_set_source_surface.
+
+ * src/cairo-color.c: Add _cairo_stock_color helper function.
+ Improve some interfaces:
+
+ _cairo_color_init _cairo_color_init_rgb
+ _cairo_color_set_rgb -> _cairo_color_init_rgba
+ _cairo_color_set_alpha _cairo_color_multiply_alpha
+
+ _cairo_color_get_rgb -> _cairo_color_get_rbga
+ _cairo_color_get_rgba_premultiplied
+
+ * src/cairoint.h: Add cairo_stock_t and some helper macros:
+
+ CAIRO_COLOR_WHITE
+ CAIRO_COLOR_BLACK
+ CAIRO_COLOR_TRANSPARENT
+
+ Fix cairo_pattern_t by eliminating pattern->alpha.
+ Fix cairo_solid_pattern_t to use cairo_color_t rather than three
+ doubles.
+
+ * src/cairo-glitz-surface.c:
+ (_cairo_glitz_pattern_acquire_surface),
+ (_cairo_glitz_pattern_acquire_surfaces),
+ (_cairo_glitz_surface_composite_trapezoids): Track removal of
+ pattern->alpha, simplifying the code considerably
+
+ * src/cairo-gstate-private.h:
+
+ * src/cairo-gstate.c: Track _cairo_color interface changes. Remove
+ gstate->alpha. Propagate down set_source renamings.
+
+ * src/cairo.h:
+ * src/cairo-pattern.c: Rename:
+
+ cairo_pattern_add_color_stop -> cairo_pattern_add_color_stop_rgba
+
+ and add:
+
+ cairo_pattern_add_color_stop_rgb
+
+ Remove pattern->alpha, simplifying the code considerably.
+
+ * src/cairo-pdf-surface.c:
+ * src/cairo-ps-surface.c: Track pattern and color interface
+ changes.
+
+ * src/cairo-surface.c: Add const where appropriate on
+ cairo_color_t*.
+
+ * src/cairo-xlib-surface.c: (_cairo_surface_is_xlib): Add private
+ type inspection predicate.
+ (cairo_xlib_surface_set_size): Add check for surface type
+ mismatch, (no useful error reporting yet, though).
+
+ * test/Makefile.am: Note coverage as en expected failure.
+
+ * test/cairo-test.c: (cairo_test_expect_failure): Improve line
+ wrap on expected failure messages.
+
+ * test/clip-twice.c:
+ * test/coverage.c:
+ * test/fill-rule.c:
+ * test/line-width.c:
+ * test/linear-gradient.c:
+ * test/pixman-rotate.c:
+ * test/set-source.c:
+ * test/text-rotate.c:
+ * test/trap-clip.c: Port all tests to new cairo_set_source
+ interfaces.
+
+2005-04-14 Carl Worth <cworth@cworth.org>
+
+ * test/gradient-alpha-ref.png:
+ * test/gradient-alpha.c: (draw): Make gradient change color in
+ addition to just changing alpha in order to highlight distinction
+ between interpolating in premultiplied vs. non-premultiplied
+ space.
+
+2005-04-14 Carl Worth <cworth@cworth.org>
+
+ * test/Makefile.am: Improve instructions for when to add a test to
+ the XFAIL list.
+
+ * test/cairo-test.c: (cairo_test_expect_failure):
+ * test/cairo-test.h:
+ * test/pixman-rotate.c: (main):
+ * test/text-rotate.c: (main): Print explanations for expected
+ failures.
+
+2005-04-14 Carl Worth <cworth@cworth.org>
+
+ * test/.cvsignore:
+ * test/Makefile.am:
+ * test/gradient-alpha-ref.png:
+ * test/gradient-alpha.c: (draw), (main): Add gradient-alpha test
+ in preparation for upcoming cairo_set_source patch.
+
+2005-04-14 Carl Worth <cworth@cworth.org>
+
+ * test/.cvsignore:
+ * test/Makefile.am:
+ * test/set-source-ref.png:
+ * test/set-source.c: (draw), (main): Add set-source test in
+ preparation for upcoming cairo_set_source patch.
+
+2005-04-14 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-font.c (_cairo_simple_font_face_destroy): Remove
+ a stray free() (#3029, Carl Worth)
+
+ * test/select-font-no-show-text.c: Note that the bug is fixed.
+
+2005-04-13 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-image-surface.c:
+ (_cairo_image_abstract_surface_finish): Set freed pointer to NULL.
+
+ * src/cairo-surface.c: (cairo_surface_finish): Fix to actually set
+ surface->finished when done. Closes bug #2950 as documented in
+ test/surface-finish-twice.c.
+
+ * test/surface-finish-twice.c: Note that this bug is fixed.
+
+2005-04-13 Carl Worth <cworth@cworth.org>
+
+ * test/.cvsignore:
+ * test/Makefile.am:
+ * test/surface-finish-twice.c: (draw), (main): Add new test to
+ exercise crash when calling cairo_surface_finish twice on the same
+ surface.
+
+2005-04-13 Carl Worth <cworth@cworth.org>
+
+ * test/.cvsignore:
+ * test/Makefile.am:
+ * test/select-font-no-show-text.c: (draw), (main): Add new
+ set-surface-no-show-text test.
+
+ * test/cairo-test.c: (cairo_test): Be sure to call cairo_destroy
+ even if the image size is 0,0 so that we can test bugs triggered
+ during cleanup.
+
+2005-04-13 Carl Worth <cworth@cworth.org>
+
+ * test/coverage-ref.png:
+ * test/coverage.c: (draw_funcs), (draw): Temporarily remove all
+ text from this test case until we come up with an approach for
+ drawing the same text with different freetype configurations.
+
+2005-04-13 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-traps.c (_cairo_traps_extract_region): Work around
+ a pair of bugs elsewhere (denegerate trapezoids from tesellator,
+ pixman_region_union_rect() failing on width/height zero rectangles)
+
+2005-04-13 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairoint.h src/cairo-traps.c: Add _cairo_traps_extract_region
+ for converting trapezoids into a pixman region.
+
+ * src/cairo-gstate.c (cairo_clip): Represent all rectangular
+ pixel-aligned regions as regions, not just single rectangles.
+
+ * src/cairo-gstate.c (_cairo_gstate_clip_and_composite_trapezoid):
+ Split into manageable pieces, optimize rectangular pixel-
+ aligned regions by using _cairo_surface_fill_rectangles()
+ or _cairo_surface_set_clip_region() as appropriate.
+
+ * tests/trap-clip.c tests/trap-clip-ref.png tests/Makefile.am:
+ Add a test for trapezoids clipping.
+
+ * doc/public/cairo-docs.xml: Add an index.
+
+2005-04-12 Carl Worth <cworth@cworth.org>
+
+ * test/translate-show-surface.c: Note that bug is now fixed.
+
+2005-04-12 Carl Worth <cworth@cworth.org>
+
+ * autogen.sh: Replace errant use of aclocal with $ACLOCAL, as
+ reported by Martin Hedenfalk. Closes bug #3000.
+
+2005-04-12 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-pattern.c:
+ * src/cairo-surface.c: (_cairo_surface_init): Default to
+ CAIRO_FILTER_GOOD rather than CAIRO_FILTER_BEST.
+
+ * src/cairo-pattern.c:
+ (_cairo_pattern_acquire_surface_for_surface): Optimize to use
+ CAIRO_FILTER_NEAREST when the pattern matrix is an integer
+ translation.
+
+2005-04-12 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-pattern.c:
+ (_cairo_pattern_acquire_surface_for_surface):
+ * src/cairo-surface.c: (_cairo_surface_init): Use
+ CAIRO_FILTER_BEST by default rather than CAIRO_FILTER_NEAREST.
+
+2005-04-12 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-gstate.c (_cairo_gstate_show_surface): Offset the src
+ pattern by (0,0)->CTM. This fixes test/translate-show-surface.
+
+ * src/cairo-glitz-surface.c
+ (_cairo_glitz_surface_composite_trapezoids): Use unsigned cahr* to
+ match new prototype for cairo_image_surface_create_for_data.
+
+2005-04-11 Carl Worth <cworth@cworth.org>
+
+ * test/.cvsignore:
+ * test/Makefile.am:
+ * test/translate-show-surface-ref.png:
+ * test/translate-show-surface.c: (draw), (main): Add new test
+ demonstrating bug in the sequence: cairo_translate;
+ cairo_show_surface.
+
+2005-04-11 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.c (cairo_select_font_face): Add deprecation alias from
+ cairo_scale_font to cairo_set_font_size.
+
+2005-04-11 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.c (cairo_select_font_face): Add deprecation alias from
+ cairo_select_font to cairo_select_font_face.
+
+2005-04-11 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo.h doc/public/cairo-sections.txt
+ src/cairo-matrix.c: Update.
+
+ * doc/public/cairo-docs.xml: Include cairo-font.xml
+
+2005-04-08 Carl Worth <cworth@cworth.org>
+
+ * src/cairoint.h:
+ * src/cairo.h: Move include of pixman.h from cairo.h to cairoint.h
+ since libpixman isn't part of cairo's public interface.
+
+ * test/move-to-show-surface.c (draw): Use unsigned long rather
+ than uint32_t since we no longer have pixman.h setting that type
+ up for us.
+
+ * src/cairo-font.c (cairo_font_face_destroy): Remove unused
+ variable user_data_copy.
+
+2005-04-08 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo.h src/cairo-font.c src/cairoint.h
+ doc/public/cairo-sections.txt:
+ Add cairo_font_face_set/get_user_data().
+
+ * src/cairo-array.c src/cairoint.h src/cairo-surface.c:
+ Refactor user data code from cairo-surface.c into
+ cairo_user_data_array_t.
+
+ * src/cairo-font.c (cairo_font_face_destroy,
+ (cairo_scaled_font_destroy, _cairo_unscaled_font_destroy):
+ Switch these types to be like cairo_surface_t where the
+ generic code frees the wrapper object.
+
+ * src/cairo-atsui-font.c src/cairo-ft-font.c
+ src/cairo-win32-font.c: Fix up for the above changes.
+
+ * src/cairo-ft-font.c (_cairo_ft_unscaled_font_destroy,
+ _ft_font_face_destroy): Implement a complicated mutual-referencing
+ scheme to make sure that a face from cairo_ft_font_face_create_for_ft_face()
+ is freed only when the FT_Face is no longer needed.
+
+ * src/cairo-ft-font.c (cairo_ft_font_face_create_for_ft_face):
+ Update the docs to describe how to figure out when the FT_Face
+ can be freed.
+
+ * src/cairo-ft-font.c: Fix refcount leaks when creating fonts.
+
+ * src/cairo-pdf-surface.c (cairo_pdf_ft_font_create): Remove
+ excess call to _cairo_unscaled_font_reference().
+
+ * src/cairo-gstate.c (_cairo_gstate_set_font_face): Remove
+ stray initialization of font matrix to the identity.
+
+ * src/cairo-array.c (_cairo_user_data_array_set_data) test/user-data.c:
+ Fix a bug when setting/unsetting a key with a free key slot before it,
+ add that to the test case.
+
+ * src/cairo-array.c (_cairo_user_data_array_set_data):
+ Don't append an element when user_data is NULL.
+
+2005-04-08 Dave Beckett <Dave.Beckett@bristol.ac.uk>
+
+ * src/cairo-glitz-surface.c (_cairo_glitz_surface_set_matrix):
+ Update to track changes to cairo_matrix_t interface.
+
+2005-04-08 Carl Worth <cworth@cworth.org>
+
+ * ROADMAP: Add ROADMAP file with an initial stab at 1.0 items.
+
+2005-04-08 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-gstate.c:
+ (_cairo_gstate_transform), (_cairo_gstate_set_matrix),
+ (_cairo_gstate_interpret_path): Eliminate internal use of
+ deprecated cairo_matrix_copy.
+
+ * src/cairo-gstate.c: (_cairo_gstate_get_matrix),
+ * src/cairo-matrix.c: (cairo_matrix_copy):
+ * src/cairo.c: (cairo_get_matrix):
+ * src/cairo.h:
+ * src/cairoint.h: Change cairo_get_matrix to accept a pointer to
+ the return value cairo_matrix_t rather than returning the value
+ directly.
+
+2005-04-08 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-matrix.c (cairo_matrix_init_identity): Don't try to
+ return a value (even a void value) from a void function. Closes
+ bug #2931.
+
+2005-04-07 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-wideint.h: Remove broken code for defining
+ uint64_t.
+
+2005-04-07 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-surface.c: (_cairo_surface_release_source_image),
+ (_cairo_surface_release_dest_image),
+ (_cairo_surface_clone_similar), (_cairo_surface_composite),
+ (_cairo_surface_fill_rectangles),
+ (_cairo_surface_composite_trapezoids), (_cairo_surface_copy_page),
+ (_cairo_surface_show_page), (_cairo_surface_show_glyphs):
+
+ Change to allow NULL backend function pointers to indicate
+ unsupported functions.
+
+ * src/cairo-glitz-surface.c:
+ * src/cairo-image-surface.c:
+ * src/cairo-pdf-surface.c:
+ * src/cairo-ps-surface.c:
+ * src/cairo-quartz-surface.c:
+ * src/cairo-win32-surface.c:
+ * src/cairo-xcb-surface.c:
+ * src/cairo-xlib-surface.c: Eliminate stub functions and replace
+ with NULL in surface backend table.
+
+2005-04-07 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo.[ch] src/cairoint.h src/cairo-gstate.c
+ docs/public/cairo-sections.txt:
+ cairo_select_font() => cairo_select_font_face()
+ cairo_scale_font() => cairo_set_font_size()
+ cairo_transform_font() => cairo_set_font_matrix()
+ Add cairo_get_font_matrix(). Make cairo_set_font_face()
+ not reset the font matrix. Default the font matrix
+ to SCALE(10). Document cairo_select_font_face().
+
+ * test/coverage.c (draw) test/text-cache-crash.c (draw)
+ test/text-rotate.c (draw): Use cairo_set_font_size().
+
+ * src/cairo-font.c src/cairo.h: Fix up some parameter
+ names for docs.
+
+2005-04-07 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-win32-font.c: Fix various compilation errors.
+
+2005-04-07 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-gstate.c:
+ * src/cairo-png.c:
+ * src/cairo-win32-font.c:
+ * src/cairo-win32-surface.c:
+ * src/cairo-win32.h:
+ * src/cairoint.h: Minor changes to header file inclusion
+ recommended by Oleg Smolsky for better portability to MSVC.
+
+2005-04-07 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-png.c (PNG_SIG_SIZE): Use a preprocessor macro to get
+ a literal value in the array size declaration, (for better
+ portability to lame compilers that can't deal with a const int
+ variable for the array size). Reported by Oleg Smolsky.
+ (PNG_SIG_SIZE): Fix typo.
+
+2005-04-07 Carl Worth <cworth@cworth.org>
+
+ * configure.in:
+ * src/cairo-wideint.h:
+ * src/cairoint.h: Use configure-time checks for stdint.h
+ vs. inttypes.h vs. sys/int_types.h rather than ad-hoc
+ system-specific macros. Also define these types manually none of
+ these header are available. (Thanks to Jason Dorje Short
+ <jdorje@users.sf.net>).
+
+2005-04-07 Carl Worth <cworth@cworth.org>
+
+ * test/imagediff.c (main): Fix to return non-zero status on error.
+
+2005-04-06 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo.h src/cairo-gstate.c src/cairo-font.c: Add
+ a cairo_font_face_t type to hold a description of a font
+ face. Replace cairo_set_font() with cairo_set_font_face().
+
+ * src/cairoint.h src/cairo-font.c src/cairo-gstate.c: Add
+ "cairo_simple_font_face" for family/weight/slant and use
+ it to implement font naming for the toy API.
+
+ * src/cairo-ft.h src/cairo-ft-font.c cairo-win32.h
+ cairo-win32-font.c: Switch the FreeType and Win32 backends
+ over to using cairo_font_face_t.
+
+ * src/cairo.h src/cairo-font.c src/cairo-ft-font.c
+ src/cairo-win32-font.c: Pass in font matrix and CTM separately
+ rather than as a composite scale when creating fonts; allows
+ removing font_matrix argument to metrics functions.
+
+ * src/cairoint.h src/cairo-font.c src/cairo-ft-font.c
+ src/cairo-win32-font.c: Remove cairo_font_scale_t type,
+ just use cairo_matrix_t and ignore translations.
+
+ * src/cairo-ft.h src/cairo-ft-font.c: Remove
+ cairo_ft_font_get_pattern() -- it can't work for all FreeType
+ backend fonts and doesn't seem particularly useful.
+
+ * src/cairo.[ch]: Rename cairo_font_get_extents() to
+ cairo_font_extents()
+
+ * doc/public/cairo-sections.txt: Update, split font functions
+ into a separate section.
+
+ * src/cairo-ft-font.c (_ft_unscaled_font_get_for_pattern): Fix
+ locking order problem.
+
+ * src/cairo-font.c: Add caches for simple font faces and from
+ cairo_font_face_t to cairo_scaled_font_t.
+
+ * src/cairo.h src/cairoint.h src/cairo-font.c src/cairo-win32-font.c
+ src/cairo-ft-font.c src/cairo-gstate.c src/cairo-gstate-private.h:
+ Rename cairo_font_t to cairo_scaled_font_t.
+
+2005-04-06 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.h: Rework the cairo_matrix_t interface in several ways.
+ Expose a struct for cairo_matrix_t.
+
+ Add new function to return current matrix:
+ cairo_get_matrix
+
+ Deprecate the following functions (in documentation):
+ cairo_matrix_create
+ cairo_matrix_destroy
+ cairo_matrix_get_affine
+
+ Rename:
+ cairo_matrix_set_affine -> cairo_matrix_init
+ cairo_matrix_set_identity -> cairo_matrix_init_identity
+
+ Add other new matrix initialization functions:
+ cairo_matrix_init_translate
+ cairo_matrix_init_scale
+ cairo_matrix_init_rotate
+
+ Change return type of almost all cairo_matrix functions from
+ cairo_status_t to void.
+
+ * src/cairo-atsui-font.c:
+ * src/cairo-ft-font.c:
+ * src/cairo-gstate.c:
+ * src/cairo-image-surface.c:
+ * src/cairo-matrix.c:
+ * src/cairo-pattern.c:
+ * src/cairo-pdf-surface.c:
+ * src/cairo-pen.c:
+ * src/cairo-surface.c:
+ * src/cairo-win32-font.c:
+ * src/cairo-xlib-surface.c:
+ * src/cairo.c:
+ * src/cairoint.h: Track changes to cairo_matrix_t interface.
+
+ * test/.cvsignore:
+ * test/Makefile.am:
+ * test/transforms-ref.png:
+ * test/transforms.c: Add a test case showing the same path drawn
+ under various transforms, (including skews set directly by
+ initializing a cairo_matrix_t).
+
+2005-04-06 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.h: Make handling of unsigned char* vs. char*
+ consistent. Change all parameters that are actual string data from
+ unsigned char* to char* (cairo_text_extents, cairo_show_text,
+ cairo_text_path). Change all data buffers from char* to unsigned
+ char* (cairo_write_func_t).
+
+ * src/cairo-gstate.c: (_cairo_gstate_text_to_glyphs):
+ * src/cairo-ft-font.c: (_cairo_ft_font_text_to_glyphs):
+ * src/cairo-font.c: (_cairo_font_text_to_glyphs):
+ * src/cairo-atsui-font.c: (_cairo_atsui_font_text_to_glyphs):
+ * src/cairoint.h:
+ * src/cairo.c: (cairo_text_extents), (cairo_show_text),
+ (cairo_text_path): Track changes from unsigned char* to
+ char*. Convert to unsigned only at the internal interface to
+ unicode processing.
+
+ * test/move-to-show-surface.c: (draw):
+ * src/cairo-output-stream.c: (_cairo_output_stream_printf),
+ (stdio_write): Track change from char* to unsigned char*.
+
+2005-04-06 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-cache.c (_cairo_cache_init): Fix reversed arguments in
+ call to calloc.
+
+2005-04-04 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.h (cairo_set_target_image,
+ cairo_image_surface_create_for_data):
+ * src/cairo.c: (cairo_set_target_image): Change type of data
+ parameter from char* to unsigned char*.
+
+ * src/cairo-ft-font.c: (_cairo_ft_font_create_glyph):
+ * src/cairo-image-surface.c: (cairo_image_surface_create_for_data):
+ * src/cairo-pattern.c:
+ (_cairo_pattern_acquire_surface_for_gradient):
+ * test/buffer-diff.c: (buffer_diff):
+ * test/buffer-diff.h:
+ * test/write-png.c: (write_png_argb32):
+ * test/write-png.h: Propagate the unsigned char* change down the
+ stack.
+
+ * src/cairo-xlib-surface.c: (_get_image_surface): Add cast since
+ XImage uses char* rather than unsigned char*.
+
+ * src/cairo-png.c: (cairo_image_surface_create_for_png): Fix
+ memory leak of image data.
+
+ * test/cairo-test.c: (cairo_test), (cairo_test_create_png_pattern):
+ * test/cairo-test.h: Switch to use cairo_surface_write_png rather
+ than a custom write_png_argb32.
+
+ * test/.cvsignore:
+ * test/Makefile.am:
+ * test/create-for-png-ref.png:
+ * test/create-for-png.c: (draw), (main): Add test to exercise the
+ cairo_image_surface_create_for_png function.
+
+2005-04-04 Carl Worth <cworth@cworth.org>
+
+ * TODO: Remove items for PNG backend removal and trapezoid
+ reasterization re-implementation since they have been completed.
+
+2005-04-04 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.c:
+ * src/cairo.h: Drop cairo_default_matrix since it is now always
+ identical to cairo_identity_matrix.
+
+ * src/cairo-gstate-private.h:
+ * src/cairo-gstate.c: (_cairo_gstate_init),
+ (_cairo_gstate_set_target_surface): Remove gstate->pixels_per
+ inch. Change default matrix to always be the identity matrix.
+
+ * src/cairo-glitz-surface.c:
+ * src/cairo-image-surface.c:
+ * src/cairo-pdf-surface.c:
+ * src/cairo-ps-surface.c:
+ * src/cairo-quartz-surface.c:
+ * src/cairo-surface.c:
+ * src/cairo-win32-surface.c:
+ * src/cairo-xcb-surface.c:
+ * src/cairo-xlib-surface.c:
+ * src/cairoint.h: Drop pixels_per_inch function from surface
+ backend interface as it is no longer needed.
+
+2005-04-02 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-gstate.c: (_cairo_gstate_show_surface): Use the
+ current point to offset just the destination, not the source and
+ destination. With this fix, cairo_show_surface should work with
+ the current point at places other than the origin.
+
+ * test/Makefile.am: Move move-to-show-surface off the expected
+ failure list.
+
+ * test/move-to-show-surface.c: Add comment indicating that bug is
+ resolved.
+
+ * test/testsvg: Don't use diff to compare images, just imagediff.
+
+2005-04-02 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.h:
+ * src/cairo.c: (cairo_set_target_image), (cairo_text_extents),
+ (cairo_show_text), (cairo_text_path):
+ * src/cairo-image-surface.c: (cairo_image_surface_create_for_data):
+ * src/cairo-gstate.c: (_cairo_gstate_text_to_glyphs):
+ * src/cairo-font.c: (_cairo_font_create): Style and indentation
+ fixes.
+
+ * src/cairo-ft-font.c: (_cairo_ft_font_create): Add (unsigned
+ char*) cast to quiet new gcc-4 warnings.
+
+ * src/cairo-ft-font.c: (_cairo_ft_font_glyph_extents): Initialize
+ variables to quiet new gcc-4 warnings.
+
+ * src/cairo-pdf-surface.c: (cairo_pdf_ft_font_write_generic_table),
+ (cairo_pdf_ft_font_write_glyf_table):
+ * src/cairo-png.c: (cairo_surface_write_png),
+ (cairo_image_surface_create_for_png):
+ * src/cairo-xlib-surface.c: (_get_image_surface):
+ * src/cairo-ps-surface.c: (_cairo_ps_surface_copy_page):
+ Use unsigned char* as expected by freetype, libpng, Xlib, and zlib.
+
+ * src/cairoint.h:
+ * src/cairo-unicode.c: (_utf8_get_char), (_utf8_get_char_extended),
+ (_cairo_utf8_to_ucs4), (_cairo_utf8_to_utf16): Propagate unsigned
+ char* down from cairo_text_extents.
+
+2005-04-01 Carl Worth <cworth@cworth.org>
+
+ * TODO: Update API shakeup chart.
+
+ * src/cairo.h:
+ * src/cairo.c: (cairo_set_target_image_no_data): Add a standin for
+ the function that should be cairo_set_target_image which should
+ then have some other name. We can straighten that mess out when we
+ eliminate the set_target functions. Add deprecation alias for
+ cairo_current_pattern.
+
+ * src/cairoint.h:
+ * src/cairo-image-surface.c:
+ * src/cairo-surface.c: Deprecate cairo_surface_create_for_image in
+ favor of cairo_image_surface_create_for_data.
+
+2005-03-31 Kristian Høgsberg <krh@redhat.com>
+
+ * src/cairo.c (cairo_set_target_png): Remove this function now
+ that the PNG backend is gone.
+
+2005-03-30 Carl Worth <cworth@cworth.org>
+
+ * configure.in: Fix typo I had introduced into Jason's patch that
+ made configure fail.
+
+2005-03-30 Carl Worth <cworth@cworth.org>
+
+ A few fixes courtesy of Jason Dorje Short <jdorje@users.sf.net>:
+
+ * configure.in: Disable PS backend if zlib is not found.
+
+ * src/cairo-win32-font.c: (_cairo_win32_font_glyph_path): Fix
+ mistyped parameter.
+
+ * src/cairo-win32-surface.c: (_cairo_win32_surface_finish): Fix
+ missing return value.
+
+2005-03-30 T Rowley <tim.rowley@gmail.com>
+
+ * src/cairo-gstate.c (_cairo_gstate_stroke_extents): call
+ _cairo_pen_init so that the result takes into account the caps.
+
+2005-03-29 T Rowley <tim.rowley@gmail.com>
+
+ * src/cairo-xlib.h: include Xlib.h to fix solaris build bustage.
+
+2005-03-29 T Rowley <tim.rowley@gmail.com>
+
+ * src/cairo-wideint.h: add preprocessor tests for stdint.h/inttypes.h
+
+ * src/cairoint.h: add preprocessor tests for stdint.h/inttypes.h
+
+2005-03-29 T Rowley <tim.rowley@gmail.com>
+
+ * configure.in: re-enable quartz backend
+
+ * src/cairo-quartz-surface.c: update to compilable/workable version
+
+ * src/cairo-atsui-font.c: update to compilable/workable version
+
+2005-03-29 Carl Worth <cworth@cworth.org>
+
+ * test/Makefile.am:
+ * test/*_*.c: More _/- renames in the test directory.
+
+2005-03-28 Carl Worth <cworth@cworth.org>
+
+ * src/Makefile.am:
+ * src/cairo_*.c: Renamed a bunch of files to use - rather than _
+ as a separator. Copy happened in the master repository to preserve
+ history, so this is just a big remove.
+
+2005-03-28 Carl Worth <cworth@cworth.org>
+
+ * TODO: Sorted API shakeup chart.
+
+2005-03-28 Kristian Høgsberg <krh@redhat.com>
+
+ * src/cairo-png.c (cairo_image_surface_write_png)
+ (cairo_image_surface_create_from_png): New PNG utility functions.
+
+ * src/cairo_pdf_surface.c, src/cairo-pdf.h: Reverse the naming of
+ the pdf constructors so the callback based ones have the long
+ names.
+
+2005-03-25 Jamey Sharp <jamey@minilop.net>
+
+ * src/cairo-xcb.h:
+ * src/cairo_xcb_surface.c:
+ Fix "implicit declaration" warning in cairo.c by moving
+ cairo_xcb_surface_create prototype into cairo-xcb.h.
+
+2005-03-23 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-path-fixed-private.h:
+ * src/cairo_path.c: Clean up names of cairo_path internals.
+
+2005-03-23 Carl Worth <cworth@cworth.org>
+
+ * src/cairo_path_fill.c:
+ * src/cairo_path_stroke.c: Remove unneeded includes of
+ cairo-path-fixed-private.h.
+
+ * src/cairo_ft_font.c (_cairo_ft_font_glyph_path): Fix
+ indentation.
+
+2005-03-23 Carl Worth <cworth@cworth.org>
+
+ * TODO: More updates to the API Shakeup chart.
+
+2005-03-23 Carl Worth <cworth@cworth.org>
+
+ * src/cairo_path.c: (_cairo_path_fixed_init),
+ (_cairo_path_fixed_init_copy), (_cairo_path_fixed_fini),
+ (_cairo_path_fixed_move_to), (_cairo_path_fixed_rel_move_to),
+ (_cairo_path_fixed_line_to), (_cairo_path_fixed_rel_line_to),
+ (_cairo_path_fixed_curve_to), (_cairo_path_fixed_rel_curve_to),
+ (_cairo_path_fixed_close_path),
+ (_cairo_path_fixed_get_current_point), (_cairo_path_add),
+ (_cairo_path_add_op_buf), (_cairo_path_new_op_buf),
+ (_cairo_path_add_arg_buf), (_cairo_path_new_arg_buf),
+ (_cairo_path_fixed_interpret):
+ * src/cairo_path_bounds.c: (_cairo_path_fixed_bounds):
+ * src/cairo_path_fill.c: (_cairo_path_fixed_fill_to_traps):
+ * src/cairo_path_stroke.c: (_cairo_path_fixed_stroke_to_traps):
+ * src/cairoint.h: Rename cairo_path_real_t to cairo_path_fixed_t
+ and fix all _cairo_path functions to be named as _cairo_path_fixed
+ functions.
+
+ * src/cairo-gstate-private.h:
+ * src/cairo-path-fixed-private.h:
+ * src/cairo_font.c: (_cairo_font_glyph_path):
+ * src/cairo_ft_font.c: (_move_to), (_line_to), (_conic_to),
+ (_cubic_to), (_cairo_ft_font_glyph_path):
+ * src/cairo_gstate.c: (_cairo_gstate_init),
+ (_cairo_gstate_init_copy), (_cairo_gstate_fini),
+ (_cairo_gstate_new_path), (_cairo_gstate_move_to),
+ (_cairo_gstate_line_to), (_cairo_gstate_curve_to),
+ (_cairo_gstate_rel_move_to), (_cairo_gstate_rel_line_to),
+ (_cairo_gstate_rel_curve_to), (_cairo_gstate_close_path),
+ (_cairo_gstate_get_current_point), (_cairo_gstate_interpret_path),
+ (_cairo_gstate_stroke), (_cairo_gstate_in_stroke),
+ (_cairo_gstate_fill), (_cairo_gstate_in_fill),
+ (_cairo_gstate_stroke_extents), (_cairo_gstate_fill_extents),
+ (_cairo_gstate_clip), (_cairo_gstate_text_to_glyphs): Track name
+ change of cairo_path_real_t and _cairo_path_fixed functions.
+
+2005-03-23 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-path-data-private.h: Remove CAIRO_BEGIN_DECLS and
+ CAIRO_END_DECLS as they are not needed for private headers.
+
+ * src/cairoint.h: Add ASSERT_NOT_REACHED macro.
+
+ * src/cairo.c: (cairo_get_path), (cairo_get_path_flat): Rewrite in
+ terms of cairo_copt_path and cairo_copy_path_flat in preparation
+ for removing cairo_gstate_interpret_path.
+
+2005-03-23 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-gstate-private.h:
+ * src/cairo-path-fixed-private.h:
+ * src/cairo-private.h:
+ * src/cairoint.h: Begin the process of breaking up cairoint.h,
+ moving structure definitions of cairo_t, cairo_gstate_t, and
+ cairo_path_real_t into their own header files.
+
+ * src/cairo.c:
+ * src/cairo_gstate.c:
+ * src/cairo_path.c:
+ * src/cairo_path_fill.c:
+ * src/cairo_path_stroke.c:
+ * src/cairo_pen.c: Track changes to header files, reaching into
+ the new private headers where necessary.
+
+2005-03-23 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.c: (cairo_set_target_glitz), (cairo_set_target_pdf),
+ (cairo_set_target_pdf_as_file), (cairo_set_target_png),
+ (cairo_set_target_ps), (cairo_set_target_win32),
+ (cairo_set_target_xcb), (cairo_set_target_drawable): Move
+ surface-specific cairo_t functions to cairo.c.
+
+ * src/cairo_glitz_surface.c:
+ * src/cairo_pdf_surface.c:
+ * src/cairo_png_surface.c:
+ * src/cairo_ps_surface.c:
+ * src/cairo_win32_surface.c:
+ * src/cairo_xcb_surface.c:
+ * src/cairo_xlib_surface.c: Remove functions that have now moved
+ to cairo.c.
+
+ * test/.cvsignore: A few new files to ignore now with new
+ compilation mode using a libtool helper library.
+
+2005-03-23 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.h: Add backwards-compatibility for recently renamed
+ functions.
+
+2005-03-21 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.c:
+ * src/cairo_gstate.c: (_cairo_gstate_transform),
+ (_cairo_gstate_user_to_device),
+ (_cairo_gstate_user_to_device_distance),
+ (_cairo_gstate_device_to_user),
+ (_cairo_gstate_device_to_user_distance),
+ (_cairo_gstate_reset_clip):
+ * src/cairo_matrix.c:
+ * src/cairoint.h:
+ * src/cairo.h: Rename functions to eliminate abbreviations:
+ cairo_concat_matrix -> cairo_transform
+ cairo_transform_point -> cairo_user_to_device
+ cairo_transform_distance -> cairo_user_to_device_distance
+ cairo_inverse_transform_point -> cairo_device_to_user
+ cairo_inverse_transform_distance-> cairo_device_to_user_distance
+ cairo_init_clip -> cairo_reset_clip
+
+2005-03-18 Carl Worth <cworth@cworth.org>
+
+ * TODO: Update API shakeup chart.
+
+2005-03-18 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-path-data-private.h: * src/cairo.c: (cairo_copy_path),
+ (cairo_copy_path_flat),
+ (cairo_append_path): Rename cairo_copy_path_data,
+ cairop_copy_path_data_flat, and cairo_append_path_data to
+ cairo_copy_path, cairo_copy_path_flat, and cairo_append_path.
+
+ * src/cairo.h: Add new cairo_path_t, containing a
+ cairo_path_data_t array and an explicit length. Remove
+ CAIRO_PATH_END_PATH terminator from cairo_path_data_t.
+
+ * src/cairo_atsui_font.c: (_cairo_atsui_font_glyph_path):
+ * src/cairo_font.c: (_cairo_font_glyph_path):
+ * src/cairo_ft_font.c: (_move_to), (_line_to), (_conic_to),
+ (_cubic_to), (_cairo_ft_font_glyph_path):
+ * src/cairo_gstate.c: (_cairo_gstate_interpret_path):
+ * src/cairo_path.c: (_cairo_path_init), (_cairo_path_init_copy),
+ (_cairo_path_fini), (_cairo_path_move_to),
+ (_cairo_path_rel_move_to), (_cairo_path_line_to),
+ (_cairo_path_rel_line_to), (_cairo_path_curve_to),
+ (_cairo_path_rel_curve_to), (_cairo_path_close_path),
+ (_cairo_path_get_current_point), (_cairo_path_add),
+ (_cairo_path_add_op_buf), (_cairo_path_new_op_buf),
+ (_cairo_path_add_arg_buf), (_cairo_path_new_arg_buf),
+ (_cairo_path_interpret):
+ * src/cairo_path_bounds.c: (_cairo_path_bounds):
+ * src/cairo_path_data.c: (_cairo_path_data_count),
+ (_cairo_path_data_populate), (_cairo_path_data_create_real),
+ (cairo_path_destroy), (_cairo_path_data_append_to_context):
+ * src/cairo_path_fill.c: (_cairo_path_fill_to_traps):
+ * src/cairo_path_stroke.c: (_cairo_path_stroke_to_traps):
+ * src/cairoint.h:
+ * test/path_data.c: (munge_and_set_path), (draw), (main): Rename
+ the internal path object from cairo_path_t to cairo_path_real_t.
+
+2005-03-18 Kristian Høgsberg <krh@redhat.com>
+
+ * src/cairo_pdf_surface.c (cairo_set_target_pdf_as_file)
+ (cairo_set_target_pdf): Remove return statements from these
+ functions (bug #2137).
+
+2005-03-18 Carl Worth <cworth@cworth.org>
+
+ * src/Makefile.am (libcairo_la_SOURCES): Remove unused
+ libcairo_freetype_sources (thanks to Damien Carbery). Closes bug
+ #2673.
+
+2005-03-17 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo_matrix.c (cairo_matrix_rotate): doc fix -
+ 90 degrees is MI_PI/2 radians.
+
+ * src/cairo.c src/cairo_matrix.c src/cairo_ft_font.c
+ src/cairo_ps_surface.c src/cairo_quartz_surface.c
+ src/cairo_win32_font.c src/cairo_win32_surface.c
+ src/cairo_xlib_surface.c: Cairo is only capitalized
+ at the beginning of sentences.
+
+2005-03-17 Kristian Høgsberg <krh@redhat.com>
+
+ From Tor Lillqvist <tml@novell.com>:
+
+ * test/cairo_test.c (cairo_test): Open output PNG files in binary
+ mode.
+
+2005-03-17 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo.h src/cairo_surface.c src/cairo-xlib.h
+ src/cairo_xlib_surface.c: Move cairo_xlib_surface_set_device_offset()
+ to a generic cairo_surface_set_device_offset().
+
+ * src/cairo_gstate.c: Take the surface's device offset into
+ account.
+
+ * doc/public/cairo-sections.txt: Update.
+
+2005-03-17 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo_matrix.c: Fix the docs to to correctly describe
+ the order of transformation for muliply/scale/rotate/translate.
+ (cairo_matrix_translate): Fix translate/rotate typo in the
+ parameter descriptions.
+
+2005-03-17 Kristian Høgsberg <krh@redhat.com>
+
+ * src/cairo_output_stream.c: Forgot to add this file.
+
+2005-03-16 Kristian Høgsberg <krh@redhat.com>
+
+ * src/cairo_surface.c (_destroy_user_data)
+ (cairo_surface_set_user_data): Dont call user data destroy
+ function if it's NULL.
+
+ * test/user_data.c: (main): Add test case for user data with NULL
+ destroy function.
+
+2005-03-16 Kristian Høgsberg <krh@redhat.com>
+
+ * src/Makefile.am: Add cairo_output_stream.c
+
+ * src/cairo.h: Add new errors, CAIRO_STATUS_WRITE_ERROR and
+ CAIRO_STATUS_SURFACE_FINISHED, add cairo_surface_finish()
+ prototype, add cairo_write_func_t.
+
+ * src/cairo.c: Add strings for new errors, documentation fix.
+
+ * src/cairo_win32_surface.c:
+ * src/cairo_xcb_surface.c:
+ * src/cairo_xlib_surface.c:
+ * src/cairo_glitz_surface.c:
+ * src/cairo_image_surface.c:
+ * src/cairo_png_surface.c:
+ * src/cairo_ps_surface.c: Rename surface destroy functions to
+ finish and change them to not free the surface.
+
+ * src/cairo-pdf.h:
+ * src/cairo_pdf_surface.c: Change PDF surface constructors to take
+ a write function in the general case and add stdio convenience
+ constructors. Change destroy function to finish for
+ cairo_pdf_surface. Change implementation to use
+ cairo_output_stream_t functions for output.
+
+ * src/cairo_font.c: (_cairo_font_show_glyphs): Use
+ _cairo_surface_show_glyphs instead of calling function pointer
+ directly.
+
+ * src/cairoint.h: Add prototypes for cairo output stream
+ functions, rename destroy to finish in cairo_surface_backend_t and
+ add finished flag to cairo_surface_t.
+
+ * src/cairo_surface.c: Add cairo_surface_finish() and call it from
+ cairo_surface_destroy(). Check the finished flag in
+ cairo_surface_t in functions that change the surface.
+
+2005-03-15 Owen Taylor <otaylor@redhat.com>
+
+ * src/cairo-xlib.h src/cairo_xlib_surface.c: Rework set
+ of contructors for XLib surfaces. Add
+ cairo_xlib_surface_set_size().
+
+ * src/cairo-xlib.h src/cairo_xlib_surface.c: Add
+ cairo_xlib_surface_set_device_offset().
+
+ * src/cairo_xlib_surface.c (cairo_xlib_surface_set_clip_region):
+ Rewrite for clarity and efficiency.
+
+ * src/cairo_xlib_surface.c (_get_image_surface): Use a
+ temporary pixmap to avoid possible BadMatch when fetch
+ from windows.
+
+ * src/cairo.[ch] src/cairo-xlib.h: Fix some parameter names
+ for the docs.
+
+ * doc/public/cairo-sections.txt: Update
+
+2005-03-14 Carl Worth <cworth@cworth.org>
+
+ * test/path_data-ref.png: Add reference image.
+
+2005-03-14 Carl Worth <cworth@cworth.org>
+
+ * test/Makefile.am: Fixes to force tests to run against locally
+ compiled version (thanks to Manish Singh).
+
+2005-03-11 Carl Worth <cworth@cworth.org>
+
+ * doc/public/cairo-sections.txt:
+ * doc/public/tmpl/cairo-surface.sgml:
+ * doc/public/tmpl/cairo.sgml: Added some documentation, so we get
+ some churn here.
+
+ * src/cairo.c:
+ * src/cairo.h: New functions: cairo_copy_path_data,
+ cairo_copy_path_data_flat, and cairo_append_path_data.
+
+ * src/Makefile.am:
+ * src/cairo-path-data-private.h:
+ * src/cairo_path_data.c: Add new implementation for
+ cairo_copy_path_data and cairo_append_path_data.
+
+ * test/Makefile.am:
+ * test/path_data.c: New test for new path_data functions.
+
+2005-03-10 Kristian Høgsberg <krh@redhat.com>
+
+ * src/cairo_surface.c (_destroy_user_data): Add this function and
+ call it on surface destruction.
+
+2005-03-10 Kristian Høgsberg <krh@redhat.com>
+
+ * test/user_data.c (main): Fix assert()'s using = instead of ==.
+
+ * test/cairo_test.c (cairo_test): Move xunlink call below the
+ xasprintf that builds the filename to unlink.
+
+2005-03-10 Carl Worth <cworth@cworth.org>
+
+ * TODO: API Shakeup status update.
+
+2005-03-10 Carl Worth <cworth@cworth.org>
+
+ Originally: 2005-02-24 Carl Worth <cworth@cworth.org>
+
+ * src/cairo_surface.c (cairo_surface_set_user_data)
+ (cairo_surface_get_user_data):
+ * src/cairo.h: Add const qualifier to cairo_user_data_key_t
+ arguments.
+
+ Originally: 2005-02-15 Kristian Høgsberg <krh@redhat.com>
+
+ * src/cairo_surface.c (cairo_surface_get_data, cairo_surface_set_data):
+ Add these two functions to set and get user data on an surface.
+
+ * src/cairo.h: Function prototypes for new functions.
+
+ * test/user_data.c: Test case for user data functions.
+
+2005-03-09 Carl Worth <cworth@cworth.org>
+
+ * test/cairo_test.c (cairo_test): Move filename initialization up
+ to before first use.
+
+ * test/get_and_set.c:
+ * test/Makefile.am: Add test for the most trivial cairo_get and
+ cairo_set functions.
+
+2005-03-09 Carl Worth <cworth@cworth.org>
+
+ * test/cairo_test.c: (cairo_test):
+ * test/cairo_test.h:
+ * test/clip_twice.c: (draw):
+ * test/coverage.c: (draw):
+ * test/fill_rule.c: (draw):
+ * test/leaky_polygon.c: (draw):
+ * test/line_width.c: (draw):
+ * test/linear_gradient.c: (draw):
+ * test/move_to_show_surface.c: (draw):
+ * test/pixman_rotate.c: (draw):
+ * test/text_cache_crash.c: (draw):
+ * test/text_rotate.c: (draw): Change the draw function under test
+ to return a cairo_test_status_t so that it can indicate test
+ failure even if there is no result image.
+
+2005-03-09 Carl Worth <cworth@cworth.org>
+
+ * TODO: Update API Shakeup planning chart.
+ fix typos.
+
+2005-03-09 Carl Worth <cworth@cworth.org>
+
+ * doc/public/cairo-sections.txt:
+ * src/cairo.c: (cairo_get_pattern), (cairo_get_font),
+ (cairo_get_font_extents), (cairo_get_operator),
+ (cairo_get_rgb_color), (cairo_get_alpha), (cairo_get_tolerance),
+ (cairo_get_current_point), (cairo_get_fill_rule),
+ (cairo_get_line_width), (cairo_get_line_cap),
+ (cairo_get_line_join), (cairo_get_miter_limit), (cairo_get_matrix),
+ (cairo_get_target_surface), (cairo_get_path),
+ (cairo_get_path_flat):
+ * src/cairo.h:
+ * src/cairo_ft_font.c: (_conic_to):
+ * src/cairo_gstate.c: (_cairo_gstate_get_target_surface),
+ (_cairo_gstate_get_pattern), (_cairo_gstate_get_operator),
+ (_cairo_gstate_get_rgb_color), (_cairo_gstate_get_tolerance),
+ (_cairo_gstate_get_alpha), (_cairo_gstate_get_fill_rule),
+ (_cairo_gstate_get_line_width), (_cairo_gstate_get_line_cap),
+ (_cairo_gstate_get_line_join), (_cairo_gstate_get_miter_limit),
+ (_cairo_gstate_get_matrix), (_cairo_gstate_get_current_point),
+ (_cairo_gstate_show_surface), (_cairo_gstate_get_font),
+ (_cairo_gstate_get_font_transform), (_cairo_gstate_get_font_scale),
+ (_cairo_gstate_ensure_font), (_cairo_gstate_get_font_extents),
+ (_cairo_gstate_text_to_glyphs):
+ * src/cairo_path.c: (_cairo_path_get_current_point):
+ * src/cairoint.h:
+ * test/pixman_rotate.c: (draw):Rename all the cairo_current
+ functions to cairo_get functions instead. Add documentation for
+ all of these functions (and a few others as well).
+
+ Add support so that old binarys should still run and old source
+ should still compile, (though we'll rip that out again on the API
+ Shakeup flag day).
+
+2005-03-08 Carl Worth <cworth@cworth.org>
+
+ * configure.in: Add -head to CAIRO_VERSION after tagging with
+ SNAPSHOT_0_4_0.
+
2005-03-08 Carl Worth <cworth@cworth.org>
* gtk-doc.make (dist-check-gtkdoc): Commit workaround to prevent
diff --git a/NEWS b/NEWS
index 62a1b1829..447583c45 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,307 @@
+Snapshot 0.5.0 (2005-05-17 Carl Worth <cworth@cworth.org>)
+==========================================================
+This is a pretty big, and fairly significant snapshot. It represents
+between 2 and 3 months of solid work from a lot of people on improving
+the API as much as possible. I'd like to express my appreciation and
+congratulations to everyone who has worked on the big API Shakeup,
+(whether in email battles over names, or fixing my silly bugs).
+
+This snapshot will require some effort on the part of users, since
+there are a _lot_ of API changes (ie. no cairo program ever written is
+safe --- they're all broken now in at least one way). But, in spite of
+that, we do encourage everyone to move their code to this snapshot as
+soon as possible. And we're doing everything we can think of to make
+the transition as smooth as possible.
+
+The idea behind 0.5 is that we've tried to make every good API change
+we could want now, and get them all done with. That is, between now
+and the 1.0 release of cairo, we expect very few new API changes,
+(though some will certainly sneak in). We will have some significant
+additions, but the pain of moving code from cairo 0.4 to cairo 0.5
+should be a one time experience, and things should be much smoother as
+we continue to move toward cairo 1.0.
+
+And with so many changes coming out for the first time in this 0.5
+release, we really do need a lot of people trying this out to make
+sure the ideas are solid before we freeze the API in preparation for
+the 1.0 release.
+
+OK, enough introduction. Here is a (not-quite-complete) description of
+the API removals, changes and additions in this snapshot, (compared to
+0.4.0)
+
+API removals
+============
+The following public functions have been removed:
+
+- cairo_set_target_*
+
+ This is a big change. See the description of cairo_create in
+ the API changes section for how to deal with this.
+
+- cairo_set_alpha
+
+ Alpha blending hasn't gone away; there's just a much more
+ unified rendering model now. Almost all uses of
+ cairo_set_alpha will be trivially replaced with
+ cairo_set_source_rgba and a few others will be replaced just
+ as easily with cairo_paint_with_alpha.
+
+- cairo_show_surface
+
+ Another useful function that we realized was muddling up the
+ rendering model. The replacement is quite easy:
+ cairo_set_source_surface and cairo_paint.
+
+- cairo_matrix_create
+- cairo_matrix_destroy
+- cairo_matrix_copy
+- cairo_matrix_get_affine
+
+ These functions supported an opaque cairo_matrix_t. We now
+ have an exposed cairo_matrix_t structure, so these can be
+ dropped.
+
+- cairo_surface_set_repeat
+- cairo_surface_set_matrix
+- cairo_surface_set_filter
+
+ These properties don't belong on surfaces. If you were using
+ them, you'll just want to instead use
+ cairo_pattern_create_for_surface and then set these properties
+ on the pattern.
+
+- cairo_copy
+
+ This was a confusing function and hopefully nobody will miss
+ it. But if you really don't find cairo_save/restore adequate,
+ let us know and we have another idea for a potential
+ replacement.
+
+And while we're on the subject of removals, we carefully tightened up
+the cairo header files so they no longer gratuitously include header
+files that are not strictly necessary, (stdio.h, stdint.h, pixman.h,
+Xrender.h, etc. and their dependencies). This may lead to some
+surprising errors, so keep your eyes open for that.
+
+API changes
+===========
+Here are some of the API changes that have occurred:
+
+~ cairo_create(void) -> cairo_create(cairo_surface_t *)
+
+ This is the big change that breaks every program. The ability
+ to re-target a cairo_t was not particularly useful, but it did
+ introduce a lot of muddy semantic questions. To eliminate
+ that, cairo_create now requires its target surface to be
+ passed in at creation time. This isn't too hard to cope with
+ as the typical first operation after cairo_create was often
+ cairo_set_target_foo. So the order of those two swap and the
+ application instead has cairo_foo_surface_create, then
+ cairo_create.
+
+~ cairo_current_* -> cairo_get_*
+
+ We had a strange mixture of cairo_get and cairo_current
+ functions. They've all been standardized on cairo_get, (though
+ note one is cairo_get_current_point).
+
+~ CAIRO_OPERATOR_SRC -> CAIRO_OPERATOR_SOURCE
+~ CAIRO_OPERATOR_OVER_REVERSE -> CAIRO_OPERATOR_DEST_OVER
+
+ Many of the cairo_operator_t symbolic values were renamed to
+ reduce the amount of abbreviation. The confusing "OP_REVERSE"
+ naming was also changed to use "DEST_OP" instead which is
+ easier to read and has wider acceptance in other
+ libraries/languages.
+
+~ cairo_set_pattern -> cairo_set_source
+~ cairo_set_rgb_color -> cairo_set_source_rgb
+
+ All of the various functions that changed the source
+ color/pattern were unified to use cairo_set_source names to
+ make the relation more clear.
+
+~ cairo_transform_point -> cairo_user_to_device
+~ cairo_transform_distance -> cairo_user_to_device_distance
+~ cairo_inverse_transform_point -> cairo_device_to_user
+~ cairo_inverse_transform_distance -> cairo_device_to_user_distance
+
+ These names just seemed a lot more clear.
+
+~ cairo_init_clip -> cairo_reset_clip
+~ cairo_concat_matrix -> cairo_transform
+
+ More abbreviation elimination
+
+~ cairo_current_path -> cairo_copy_path
+~ cairo_current_path_flat -> cairo_copy_path_flat
+
+ The former mechanism for examining the current path was a
+ function that required 3 or 4 callbacks. This was more
+ complexity than warranted in most situations. The new
+ cairo_copy_path function copies the current path into an
+ exposed data structure, and the documentation provides a
+ convenient idiom for navigating the path data.
+
+API additions
+-------------
++ cairo_paint
+
+ A generalized version of the painting operators cairo_stroke
+ and cairo_fill. The cairo_paint call applies the source paint
+ everywhere within the current clip region. Very useful for
+ clearing a surface to a solid color, or painting an image,
+ (see cairo_set_source_surface).
+
++ cairo_paint_with_alpha
+
+ Like cairo_paint but applying some alpha to the source,
+ (making the source paint translucent, eg. to blend an image on
+ top of another).
+
++ cairo_mask
+
+ A more generalized version of cairo_paint_with_alpha which
+ allows a pattern to specify the amount of translucence at each
+ point rather than using a constant value everywhere.
+
++ cairo_mask_surface
+
+ A convenience function on cairo_mask for when the mask pattern
+ is already contained within a surface.
+
++ cairo_surface_set_user_data
++ cairo_surface_get_user_data
++ cairo_font_face_set_user_data
++ cairo_font_face_get_user_data
+
+ Associate arbitrary data with a surface or font face for later
+ retrieval. Get notified when a surface or font face object is
+ destroyed.
+
++ cairo_surface_finish
+
+ Allows the user to instruct cairo to finish all of its
+ operations for a given surface. This provides a safe point for
+ doing things such as flushing and closing files that the
+ surface may have had open for writing.
+
++ cairo_fill_preserve
++ cairo_stroke_preserve
++ cairo_clip_preserve
+
+ One interesting change in cairo is that the path is no longer
+ part of the graphics state managed by
+ cairo_save/restore. This allows functions to construct paths
+ without interfering with the graphics state. But it prevents
+ the traditional idiom for fill-and-stroke:
+
+ cairo_save; cairo_fill; cairo_restore; cairo_stroke
+
+ Instead we know have alternate versions cairo cairo_fill,
+ cairo_stroke, and cairo_clip that preserve the current path
+ rather than consuming it. So the idiom now becomes simply:
+
+ cairo_fill_preserve; cairo_stroke
+
++ cairo_surface_write_to_png
++ cairo_surface_write_to_png_stream
+
+ In place of a single PNG backend, now a surface created
+ through any backend (except PDF currently) can be written out
+ to a PNG image.
+
++ cairo_image_surface_create_from_png
++ cairo_image_surface_create_from_png_stream
+
+ And its just as easy to load a PNG image into a surface as well.
+
++ cairo_append_path
+
+ With the new, exposed path data structure, it's now possible
+ to append bulk path data to the current path, (rather than
+ issuing a long sequence of cairo_move_to/line_to/curve_to
+ function calls).
+
+Xlib and XCB backends
+---------------------
+
+Any cairo_format_t and Colormap arguments have been dropped from
+cairo_xlib_surface_create. There are also two new
+cairo_xlib|xcb_surface_create functions:
+
+ cairo_xlib|xcb_surface_create_for_bitmap
+ (Particular for creating A1 surfaces)
+ cairo_xlib|xcb_surface_create_with_xrender_format
+ (For any other surface types, not described by a Visual*)
+
+All of these surface create functions now accept width and height. In
+addition, there are new cairo_xlib|xcb_surface_set_size functions
+which must be called each time a window that is underlying a surface
+changes size.
+
+Print backends (PS and PDF)
+---------------------------
+The old FILE* based interfaces have been eliminated. In their place we
+have two different functions. One accepts a simple const char
+*filename. The other is a more general function which accepts a
+callback write function and a void* closure. This should allow the
+flexibility needed to hook up with various stream object in many
+languages.
+
+In addition, when specifying the surface size during construction, the
+units are now device-space units (ie. points) rather than inches. This
+provides consistency with all the other surface types and also makes
+it much easier to reason about the size of the surface when drawing to
+it with the default identity matrix.
+
+Finally, the DPI parameters, which are only needed to control the
+quality of fallbacks, have been made optional. Nothing is required
+during surface_create (300 DPI is assumed) and
+cairo_ps|pdf_surface_set_dpi can be used to set alternate values if
+needed.
+
+Font system
+-----------
+Owen very graciously listened to feedback after the big font rework he
+had done for 0.4, and came up with way to improve it even more. In 0.4
+there was a cairo_font_t that was always pre-scaled. Now, there is an
+unscaled cairo_font_face_t which is easier to construct, (eg. no
+scaling matrix required) and work with, (it can be scaled and
+transformed after being set on the graphics state). And the font size
+manipulation functions are much easier. You can set an explicit size
+and read/modify/write the font matrix with:
+
+ cairo_set_font_size
+ cairo_get_font_matrix
+ cairo_set_font_matrix
+
+(Previously you could only multiply in a scale factor or a matrix.) A
+pleasant side effect is that we can (and do) now have a default font
+size that is reasonable, as opposed to the old default height of one
+device-space unit which was useless until scaled.
+
+Of course, the old pre-scaled font had allowed some performance
+benefits when getting many metrics for a font. Those benefits are
+still made available through the new cairo_scaled_font_t. And a
+cairo_font_face_t can be "promoted" to a cairo_scaled_font_t by
+suppling a font_matrix and the desired CTM.
+
+Quartz backend
+--------------
+Tim Rowley put in the work to bring the Quartz backend back after it
+had been disabled in the 0.4.0 snapshot. He was not able to bring back
+the function that allows one to create a cairo_font_t from an ATSUI
+style:
+
+ cairo_font_t *
+ cairo_atsui_font_create (ATSUStyle style);
+
+because he didn't have a test case for it. If you care about this
+function, please provide a fairly minimal test and we'll try to bring
+it back in an upcoming snapshot.
+
Snapshot 0.4.0 (2005-03-08 Carl Worth <cworth@cworth.org>)
==========================================================
New documentation
diff --git a/PORTING_GUIDE b/PORTING_GUIDE
new file mode 100644
index 000000000..b8bdd37b6
--- /dev/null
+++ b/PORTING_GUIDE
@@ -0,0 +1,257 @@
+ ...-----=======-----...
+ Cairo 0.5 Porting Guide
+ ...-----=======-----...
+
+Here are some notes on more easily porting cairo_code from cairo 0.4
+to cairo 0.5. It is sorted roughly in order of importance, (the items
+near the top are expected to affect the most people).
+
+Automated API renamings
+=======================
+There have been a lot of simple renamings where the functionality is
+the same but the name of the symbol is different. We have provided a
+script to automate the conversion of these symbols. It can be found
+within the cairo distribution in:
+
+ util/cairo-api-update
+
+This script is used by installing it somewhere on your PATH, and the
+running it and providing the names of your source files on the command
+line. For example:
+
+ cairo-api-update *.[ch]
+
+The script will first save backup copies of each file (renamed with a
+.bak extension) and then will perform all of the simple renamings.
+
+For your benefit, the script also produces messages giving filenames
+and line numbers for several of the manual API updates that you will
+need to perform as described below.
+
+
+Manual API changes
+==================
+This section of the porting guide describes changes you will have to
+manually make to your source code. In addition to the information in
+this guide, the cairo-api-update script will notify you of some of
+these issues as described above.
+
+Cairo's deprecation warnings
+----------------------------
+Also, if your compiler provides warnings for implicit declarations of
+functions, (eg. "gcc -Wall"), then simply attempting to compile your
+program will cause cairo to generate messages intended to guide you
+through the porting process.
+
+For example, if you neglect to update an old call to
+cairo_set_target_drawable, you might see an error message as follows:
+
+ foo.c:10: warning: implicit declaration of function
+ ‘cairo_set_target_drawable_DEPRECATED_BY_cairo_xlib_surface_create’
+
+This message is indicating to you that the deprecatd function
+cairo_set_target_drawable appears in your program foo.c on line 10,
+and you should rewrite your program to call cairo_xlib_surface_create
+instead.
+
+The remainder of this porting guide is arranged as a set of common
+code patterns that appear in old (cairo-0.4) code and how it should be
+transformed to new (cairo-0.5) code.
+
+cairo_create
+------------
+Was: cr = cairo_create ();
+ cairo_set_target_foo (cr, args);
+ /* draw */
+ cairo_destroy (cr);
+
+Now: cairo_surface_t *surface;
+
+ surface = cairo_foo_surface_create (args);
+ cr = cairo_create (surface);
+ /* draw */
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
+
+Or: cairo_surface_t *surface;
+
+ surface = cairo_foo_surface_create (args);
+ cr = cairo_create (surface);
+ cairo_surface_destroy (surface);
+ /* draw */
+ cairo_destroy (cr);
+
+NOTE: Many of the cairo_foo_surface_create functions accept the
+ identical arguments as the the old cairo_set_target_foo
+ functions, (minus the cairo_t*), making this transformation
+ quite easy. One notable exception is cairo_set_target_drawable
+ which, when it becomes cairo_xlib_surface_create must pickup new
+ arguments for the Visual*, the width, and the height.
+
+cairo_set_alpha (1)
+-------------------
+Was: cairo_set_rgb_color (cr, red, green, blue);
+ cairo_set_alpha (cr, alpha);
+
+Now: cairo_set_source_rgba (cr, red, green, blue, alpha);
+
+cairo_show_surface
+------------------
+Was: cairo_show_surface (cr, surface, width, height);
+
+Now: cairo_set_source_surface (cr, surface, x, y);
+ cairo_paint (cr);
+
+NOTE: The type signatures of cairo_show_surface and cairo_set_source
+ are the same, but pay attention that cairo_show_surface required
+ the width and height, while cairo_set_source_surface requires
+ the X,Y location to where the surface will be placed.
+
+cairo_set_alpha (2)
+-------------------
+Was: cairo_set_alpha (cr, alpha);
+ cairo_show_surface (cr, surface, width, height);
+
+Now: cairo_set_source_surface (cr, surface, x, y);
+ cairo_paint_with_alpha (cr, alpha);
+
+filling and stroking
+--------------------
+Was: cairo_save (cr);
+ /* set fill color */
+ cairo_fiill (cr);
+ cairo_restore (cr);
+ /* set stroke color */
+ cairo_stroke (cr);
+
+Now: /* set fill color */
+ cairo_fill_preserve (cr);
+ /* set stroke color */
+ cairo_stroke (cr);
+
+NOTE: The current path is no longer saved/restored by
+ cairo_save/cairo_restore. This can lead to some subtle
+ surprises, so look out.
+
+cairo_matrix_t
+--------------
+Was: cairo_matrix_t *matrix;
+
+ matrix = cairo_matrix_create ();
+ /* Do stuff with matrix */
+ cairo_matrix_destroy (matrix);
+
+Now: cairo_matrix_t matrix;
+ cairo_matrix_init_identity (&matrix);
+ /* Do stuff with &matrix */
+
+NOTE: If you are really lazy, you can still use a cairo_matrix_t* and
+ avoid putting the &matrix all over by just replacing
+ cairo_matrix_create() with malloc() and cairo_matrix_destroy()
+ with free(). That's not as nice, and you still need to be
+ careful to see if you need to initialize it to an identity
+ matrix as cairo_matrix_create() did for you.
+
+Rendering to a temporary surface
+--------------------------------
+Was: cairo_save (cr);
+ {
+ cairo_set_target_surface (cr, temporary);
+ /* draw through cr onto temporary */
+ }
+ cairo_restore (cr);
+ /* use temporary as source on cr */
+
+Now: {
+ cr2 = cairo_create (temporary);
+ /* draw through cr2 onto temporary */
+ cairo_destory (cr2);
+ }
+ /* use temporary as source on cr */
+
+NOTE: Having to create another cairo_t is a bit annoying, but having
+ to invent a new name for it is just awful, (imagine a deeply
+ nested version of this code). Fortunately, the style above is
+ just a stop-gap measure until the new group API comes along.
+
+Iterating over a path
+---------------------
+Was: cairo_current_path (cr,
+ my_move_to,
+ my_line_to,
+ my_curve_to,
+ my_close_path,
+ closure);
+
+Now: int i;
+ cairo_path_t *path;
+ cairo_path_data_t *data;
+
+ path = cairo_copy_path (cr);
+
+ for (i=0; i < path->num_data; i += path->data[i].header.length) {
+ data = &path->data[i];
+ switch (data->header.type) {
+ case CAIRO_PATH_MOVE_TO:
+ my_move_to (closure, data[1].point.x, data[1].point.y);
+ break;
+ case CAIRO_PATH_LINE_TO:
+ my_line_to (closure, data[1].point.x, data[1].point.y);
+ break;
+ case CAIRO_PATH_CURVE_TO:
+ my_curve_to (closure, data[1].point.x, data[1].point.y,
+ data[2].point.x, data[2].point.y,
+ data[3].point.x, data[3].point.y);
+ break;
+ case CAIRO_PATH_CLOSE_PATH:
+ my_close_path (closure);
+ break;
+ }
+ }
+ cairo_path_destroy (path);
+
+NOTE: This version makes it looks like the new form is a _lot_ more
+ verbose than the old version. But realize that the old version
+ required the support of 4 additional functions. The new approach
+ allows great flexibility including the ability to inline the
+ entire operation within the switch statement when appropriate.
+
+Erasing a surface to transparent
+--------------------------------
+Was: cairo_set_rgb_color (cr, 0., 0., 0.);
+ cairo_set_alpha (cr, 0.)
+ cairo_set_operator (cr, CAIRO_OPERATOR_SRC);
+ cairo_rectangle (cr, 0., 0., surface_width, surface_height);
+ cairo_fill (cr);
+
+Now: cairo_set_source_rgba (cr, 0., 0., 0., 0.);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint (cr);
+
+NOTE: Using cairo_rectanlgle and fill would still work just fine. It's
+ just a lot more convenient to use cairo_paint now, (particularly
+ as it doesn't require you to even know what the bounds of the
+ target surface are).
+
+Drawing to a PNG file
+---------------------
+Was: file = fopen (filename, "w");
+ cr = cairo_create ();
+ cairo_set_target_png (cr, file, format, width, height);
+ /* draw image */
+ cairo_destroy (cr);
+ fclose (file);
+
+Now: surface = cairo_image_surface_create (format, width, height);
+ cr = cairo_create (surface);
+ /* draw image */
+ cairo_surface_write_to_png (surface, filename);
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
+
+NOTE: The png backend is gone. So there is no cairo_png_surface_create
+ to take the place of cairo_set_target_png. And notice that we
+ used an image surface here, but it is just as easy to use
+ cairo_surface_write_to_png with an xlib or other surface, (but
+ not PDF at the moment). This is one of the big advantages of
+ this approach as opposed to a PNG surface.
diff --git a/RELEASING b/RELEASING
index 57f289dfc..c6513f451 100644
--- a/RELEASING
+++ b/RELEASING
@@ -18,9 +18,10 @@ fixes are committed. Here are the steps to follow:
Running "make distcheck" should result in no warnings or
errors and end with a message of the form:
- ================================================
- cairo-X.Y.Z.tar.gz is ready for distribution
- ================================================
+ ==================================================
+ cairo-X.Y.Z-head archives ready for distribution:
+ caioo-X.Y.Z-head.tar.gz
+ ==================================================
(But the tar file isn't actually ready yet, as we still have
some more steps to follow).
@@ -31,11 +32,14 @@ fixes are committed. Here are the steps to follow:
snapshot. Summarize major changes briefly in a style similar
to other entries in NEWS. Take special care to note any
incompatible changes in the API. These should be easy to find
- by looking for cairo.h in the ChangeLog. Additionally, the
+ by looking for cairo*.h in the ChangeLog. Additionally, the
output of the following command should be examined using the
previous snapshot tag:
- cvs diff -r SNAPSHOT_X_Y_Z src/cairo.h
+ cvs diff -r SNAPSHOT_X_Y_Z src/*.h
+
+ [Hmm, it would be nice to have a pattern for that command that
+ would exclude private header files.]
4) Increment CAIRO_VERSION in configure.in
diff --git a/ROADMAP b/ROADMAP
new file mode 100644
index 000000000..4a47c4964
--- /dev/null
+++ b/ROADMAP
@@ -0,0 +1,80 @@
+Here are some quick notes as far as a cairo roadmap goes.
+
+See also the TODO file for a different view, (less organized, but
+often in more detail, particularly for the API Shakeup work in
+progress).
+
+cairo 1.0 release requirements
+==============================
+
+Implementation work
+-------------------
+ I1. Fix clipping to be sane
+ Dificulty: moderate
+ Status: cworth has started looking at this
+
+ I2. Real PostScript/PDF fallbacks (cairo_meta_surface_t)
+ Difficulty: hard
+ Status: otaylor has drafted a plan or two on the list
+
+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
+
+✓A2. Add cairo_mask
+ Difficulty: moderate
+ Status: Done
+
+ A3. Add cairo_begin/end/get_group
+ Difficulty: easy to hard (depending on how sophisticated an
+ implementation is acceptable, and whether the
+ cairo_meta_surface_t mentioned in [I2] is done)
+ Status: cworth sent API proposal to the list
+ (still some unresolved API issues)
+
+✓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_format_t:
+ Difficulty: moderate. It's just going through and examining
+ each use of cairo_format_t, but there are a lot
+ of them.
+ Status: not started, there is a rough plan in TODO
+
+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
diff --git a/TODO b/TODO
index f0edbc309..ea44263ed 100644
--- a/TODO
+++ b/TODO
@@ -1,29 +1,42 @@
-API Shakeup work
-----------------
-Patch? Reviewed?
-yes yes user data (was Re: [cairo] Patch improving fallbacks)
- cairo_paint
-yes yes setters and getters
- cairo_current_matrix
- Renaming the terms of the rendering equation
- Making set_source consistent
- Eliminating cairo_show_surface
- cairo_mask
- cairo_begin_group, cairo_end_group, cairo_get_group
-yes yes cairo_output_stream_t and cairo_surface_finish()
- cairo_create and eliminating cairo_set_target_surface
- cairo_fill_preserve, cairo_stroke_preserve, cairo_clip_preserve
- default matrix
- cairo_current_path -> cairo_copy_path_data
- cairo_surface_finish, cairo_surface_flush
- cairo_<device>_surface_mark_dirty
- Eliminating cairo_copy
- Eliminating cairo_surface_set_repeat/matrix/filter
- A hidden offset for the xlib backend
- cairo_stroke_path -> cairo_stroke_to_path
- Simplifying the operator set
- Abbreviation hunt: cairo_init_clip and cairo_concat_matrix
- Consistent error handling for all objects
+API Shakeup planning
+--------------------
+ Patch submitted to mailing list?
+/ Documentation included in patch?
+|/ Review of patch completed?
+||/ Test case included?
+|||/ Committed.
+||||/
+New functionality (more-or-less)
+--------------------------------
+ cairo_begin_group, cairo_end_group, cairo_get_group
+ cairo_<device>_surface_mark_dirty
+ Consistent error handling for all objects
+
+Somewhat backwards-compatible changes
+-----------------------------------
+PDRTC user data (was Re: [cairo] Patch improving fallbacks)
+PDRTC setters and getters
+PDRTC cairo_output_stream_t and cairo_surface_finish()
+PDRTC cairo_current_path -> cairo_copy_path_data
+PDR C cairo_surface_finish, cairo_surface_flush
+PDRTC Abbreviation hunt: cairo_init_clip and cairo_concat_matrix
+PDRTC Renaming the terms of the rendering equation
+PDRTC default matrix
+PDRTC cairo_paint
+PDRTC Making set_source consistent
+PDRTC cairo_stroke_path -> cairo_stroke_to_path
+PDRTC cairo_current_matrix
+PDRTC cairo_mask
+PDRTC cairo_fill_preserve, cairo_stroke_preserve, cairo_clip_preserve
+PDR C A hidden offset for the xlib backend
+
+Backwards incompatible
+----------------------
+PDRTC Simplifying the operator set
+PDRTC cairo_create and eliminating cairo_set_target_surface
+PDRTC Eliminating cairo_copy
+PDRTC Eliminating cairo_surface_set_repeat/matrix/filter
+PDRTC Eliminating cairo_show_surface
* Add support for non-antialiased rendering. API ?
@@ -37,8 +50,37 @@ yes yes cairo_output_stream_t and cairo_surface_finish()
((src Op dest) In clip) Add (dest Out clip)
-* Replace PNG backend with an image_surface function to save a PNG
- image.
+* Split cairo_format_t into two things:
+
+ - An enumeration that determines the "capabilities" of a surface -
+ A vs. ARGB. vs. RGB
+ - An enumeration that determines a specific in-memory representation
+ of data. (A1/A8/ARGB32/etc.. Could be extensible to things like
+ RGBA32_BYTES_NONPREMULTIPLIED. Some consistent naming convention would
+ be be good.)
+
+ One issue here is that some interfaces, like cairo_surface_create_similar()
+ might be useful with either one. We might want to create an A1 surface
+ compatible with the backend (are there examples other than A1? Should
+ bilevel just be another "capability"?), or we might want to just create
+ an alpha surface without caring about the depth.
+
+ If we want to support this, we could do something like:
+
+ typedef enum cairo_pixel_format_t {
+ CAIRO_PIXEL_FORMAT_A8 = CAIRO_FORMAT_ALPHA,
+ CAIRO_PIXEL_FORMAT_RGB24 = CAIRO_FORMAT_RGB,
+ CAIRO_PIXEL_FORMAT_A1,
+ };
+
+ To allow passing either in.
+
+ (I don't particularly like this idea for create_similar() because then you
+ aren't really saying ALPHA-dont-care, you are saying ALPHA-8. I think it
+ would be better to have a separate path for create_similar_with_pixel_format()
+ if we need that. But it might be useful for cairo_image_surface_create() ...
+ people are going to screw up and pass CAIRO_FORMAT_RGB into that, and if it
+ "just worked" that would save people trouble....)
* Clean up the API in preparation for freezing and release.
@@ -83,9 +125,6 @@ do gradients the Right Way).
* Implement cairo_arc_to.
-* Re-implement the trapezoid rasterization algorithm according to the
- new "specification".
-
* Stroking closed, degenerate paths should still draw caps. Round
caps are easy; square should probably draw an axis-aligned square.
@@ -128,3 +167,7 @@ do gradients the Right Way).
* Verification, profiling, optimization.
centi_unfinished.svg may provide a good test case.
+
+* Implement copy-on-write regions in pixman as a more complete
+ solution than the BAD_NESTING stuff to Owen's "Clip region problems"
+ thread.
diff --git a/autogen.sh b/autogen.sh
index f834cfed1..ae8acc606 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -93,7 +93,7 @@ else
fi
if test -z "$ACLOCAL_FLAGS"; then
- acdir=`aclocal --print-ac-dir`
+ acdir=`$ACLOCAL --print-ac-dir`
if [ ! -f $acdir/pkg.m4 ]; then
echo "$ARGV0: Error: Could not find pkg-config macros."
echo " (Looked in $acdir/pkg.m4)"
diff --git a/configure.in b/configure.in
index 5ee585e73..070b0ef64 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.4.0
+CAIRO_VERSION=0.5.0
# libtool shared library version
@@ -60,18 +60,15 @@ if test "x$use_xlib" = "xyes"; then
AC_PATH_XTRA
XRENDER_LIBS="$X_LIBS -lXrender -lXext -lX11 $X_EXTRA_LIBS"
use_xlib=yes], [
- use_xlib="no (requires Xrender http://freedesktop.org/software/xlibs)"])])
+ use_xlib="no (requires Xrender http://freedesktop.org/Software/xlibs)"])])
fi
-if test "x$use_xlib" != "xyes"; then
- XLIB_SURFACE_FEATURE=CAIRO_HAS_NO_XLIB_SURFACE
- AM_CONDITIONAL(CAIRO_HAS_XLIB_SURFACE, false)
-else
- XLIB_SURFACE_FEATURE=CAIRO_HAS_XLIB_SURFACE
- AM_CONDITIONAL(CAIRO_HAS_XLIB_SURFACE, true)
+AM_CONDITIONAL(CAIRO_HAS_XLIB_SURFACE, test "x$use_xlib" = "xyes")
+if test "x$use_xlib" = "xyes"; then
+ XLIB_SURFACE_FEATURE="#define CAIRO_HAS_XLIB_SURFACE 1"
fi
-
AC_SUBST(XLIB_SURFACE_FEATURE)
+
AC_SUBST(XRENDER_REQUIRES)
CAIRO_CFLAGS="$CAIRO_CFLAGS $XRENDER_CFLAGS"
@@ -79,22 +76,18 @@ CAIRO_LIBS="$CAIRO_LIBS $XRENDER_LIBS"
AC_ARG_ENABLE(quartz,
[ --disable-quartz Disable cairo's quartz backend],
- [use_quartz=$enableval], [use_quartz="no (temporarily disabled while code is out of sync)"])
+ [use_quartz=$enableval], [use_quartz=yes])
if test "x$use_quartz" = "xyes"; then
dnl There is no pkgconfig for quartz; lets do a header check
AC_CHECK_HEADER(Carbon/Carbon.h, [use_quartz=yes], [use_quartz=no])
fi
-if test "x$use_quartz" != "xyes"; then
- QUARTZ_SURFACE_FEATURE=CAIRO_HAS_NO_QUARTZ_SURFACE
- AM_CONDITIONAL(CAIRO_HAS_QUARTZ_SURFACE, false)
-else
- QUARTZ_SURFACE_FEATURE=CAIRO_HAS_QUARTZ_SURFACE
+AM_CONDITIONAL(CAIRO_HAS_QUARTZ_SURFACE, test "x$use_quartz" = "xyes")
+if test "x$use_quartz" = "xyes"; then
+ QUARTZ_SURFACE_FEATURE="#define CAIRO_HAS_QUARTZ_SURFACE 1"
QUARTZ_LIBS="-Xlinker -framework -Xlinker Carbon"
- AM_CONDITIONAL(CAIRO_HAS_QUARTZ_SURFACE, true)
fi
-
AC_SUBST(QUARTZ_SURFACE_FEATURE)
CAIRO_LIBS="$CAIRO_LIBS $QUARTZ_LIBS"
@@ -106,21 +99,18 @@ AC_ARG_ENABLE(xcb,
if test "x$use_xcb" = "xyes"; then
PKG_CHECK_MODULES(XCB, xcb, [use_xcb=yes], [
- use_xcb="no (requires XCB http://freedesktop.org/software/xcb)"])
+ use_xcb="no (requires XCB http://xcb.freedesktop.org)"])
fi
-if test "x$use_xcb" != "xyes"; then
- XCB_SURFACE_FEATURE=CAIRO_HAS_NO_XCB_SURFACE
- AM_CONDITIONAL(CAIRO_HAS_XCB_SURFACE, false)
-else
- XCB_SURFACE_FEATURE=CAIRO_HAS_XCB_SURFACE
- AM_CONDITIONAL(CAIRO_HAS_XCB_SURFACE, true)
+AM_CONDITIONAL(CAIRO_HAS_XCB_SURFACE, test "x$use_xcb" = "xyes")
+if test "x$use_xcb" = "xyes"; then
+ XCB_SURFACE_FEATURE="#define CAIRO_HAS_XCB_SURFACE 1"
fi
+AC_SUBST(XCB_SURFACE_FEATURE)
CAIRO_CFLAGS="$CAIRO_CFLAGS $XCB_CFLAGS"
CAIRO_LIBS="$CAIRO_LIBS $XCB_LIBS"
-AC_SUBST(XCB_SURFACE_FEATURE)
dnl ===========================================================================
@@ -147,23 +137,16 @@ if test "x$use_win32" = "xyes"; then
CAIRO_LIBS="$CAIRO_LIBS -lgdi32 -lmsimg32"
fi
-if test "x$use_win32" != "xyes"; then
- WIN32_SURFACE_FEATURE=CAIRO_HAS_NO_WIN32_SURFACE
- AM_CONDITIONAL(CAIRO_HAS_WIN32_SURFACE, false)
-else
- WIN32_SURFACE_FEATURE=CAIRO_HAS_WIN32_SURFACE
- AM_CONDITIONAL(CAIRO_HAS_WIN32_SURFACE, true)
+AM_CONDITIONAL(CAIRO_HAS_WIN32_SURFACE, test "x$use_win32" = "xyes")
+if test "x$use_win32" = "xyes"; then
+ WIN32_SURFACE_FEATURE="#define CAIRO_HAS_WIN32_SURFACE 1"
fi
+AC_SUBST(WIN32_SURFACE_FEATURE)
-if test "x$use_win32" != "xyes"; then
- WIN32_FONT_FEATURE=CAIRO_HAS_NO_WIN32_FONT
- AM_CONDITIONAL(CAIRO_HAS_WIN32_FONT, false)
-else
- WIN32_FONT_FEATURE=CAIRO_HAS_WIN32_FONT
- AM_CONDITIONAL(CAIRO_HAS_WIN32_FONT, true)
+AM_CONDITIONAL(CAIRO_HAS_WIN32_FONT, test "x$use_win32" = "xyes")
+if test "x$use_win32" = "xyes"; then
+ WIN32_FONT_FEATURE="#define CAIRO_HAS_WIN32_FONT 1"
fi
-
-AC_SUBST(WIN32_SURFACE_FEATURE)
AC_SUBST(WIN32_FONT_FEATURE)
dnl ===========================================================================
@@ -172,24 +155,27 @@ AC_ARG_ENABLE(ps,
[ --disable-ps Disable cairo's PostScript backend],
[use_ps=$enableval], [use_ps=yes])
-if test "x$use_ps" != "xyes"; then
- PS_SURFACE_FEATURE=CAIRO_HAS_NO_PS_SURFACE
- AM_CONDITIONAL(CAIRO_HAS_PS_SURFACE, false)
-else
- PS_SURFACE_FEATURE=CAIRO_HAS_PS_SURFACE
+# 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
- AM_CONDITIONAL(CAIRO_HAS_PS_SURFACE, true)
fi
+AC_SUBST(PS_SURFACE_FEATURE)
CAIRO_LIBS="$CAIRO_LIBS $PS_LIBS"
-AC_SUBST(PS_SURFACE_FEATURE)
AC_SUBST(PS_LIBS)
dnl ===========================================================================
AC_ARG_ENABLE(png,
- [ --disable-png Disable cairo's PNG backend],
+ [ --disable-png Disable cairo's PNG functions],
[use_png=$enableval], [use_png=yes])
if test "x$use_png" = "xyes"; then
@@ -211,18 +197,15 @@ if test "x$use_png" = "xyes"; then
fi
fi
-if test "x$use_png" != "xyes"; then
- PNG_SURFACE_FEATURE=CAIRO_HAS_NO_PNG_SURFACE
- AM_CONDITIONAL(CAIRO_HAS_PNG_SURFACE, false)
-else
- PNG_SURFACE_FEATURE=CAIRO_HAS_PNG_SURFACE
- AM_CONDITIONAL(CAIRO_HAS_PNG_SURFACE, true)
+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"
fi
+AC_SUBST(PNG_FUNCTIONS_FEATURE)
CAIRO_CFLAGS="$CAIRO_CFLAGS $PNG_CFLAGS"
CAIRO_LIBS="$CAIRO_LIBS $PNG_LIBS"
-AC_SUBST(PNG_SURFACE_FEATURE)
AC_SUBST(PNG_REQUIRES)
dnl ===========================================================================
@@ -234,39 +217,22 @@ AC_ARG_ENABLE(glitz,
if test "x$use_glitz" = "xyes"; then
PKG_CHECK_MODULES(GLITZ, glitz >= 0.4.0, [
GLITZ_REQUIRES=glitz
- use_glitz=yes], [use_glitz="no (requires glitz http://freedesktop.org/software/glitz)"])
+ use_glitz=yes], [use_glitz="no (requires glitz http://freedesktop.org/Software/glitz)"])
fi
-if test "x$use_glitz" != "xyes"; then
- GLITZ_SURFACE_FEATURE=CAIRO_HAS_NO_GLITZ_SURFACE
- AM_CONDITIONAL(CAIRO_HAS_GLITZ_SURFACE, false)
-else
- GLITZ_SURFACE_FEATURE=CAIRO_HAS_GLITZ_SURFACE
- AM_CONDITIONAL(CAIRO_HAS_GLITZ_SURFACE, true)
+AM_CONDITIONAL(CAIRO_HAS_GLITZ_SURFACE, test "x$use_glitz" = "xyes")
+if test "x$use_glitz" = "xyes"; then
+ GLITZ_SURFACE_FEATURE="#define CAIRO_HAS_GLITZ_SURFACE 1"
fi
+AC_SUBST(GLITZ_SURFACE_FEATURE)
CAIRO_CFLAGS="$CAIRO_CFLAGS $GLITZ_CFLAGS"
CAIRO_LIBS="$CAIRO_LIBS $GLITZ_LIBS"
-AC_SUBST(GLITZ_SURFACE_FEATURE)
AC_SUBST(GLITZ_REQUIRES)
dnl ===========================================================================
-AC_ARG_ENABLE(sanity-checking,
- [ --disable-sanity Disable cairo's sanity checking routines],
- [check_sanity=$enableval], [check_sanity=yes])
-
-if test "x$check_sanity" != "xyes"; then
- SANITY_CHECKING_FEATURE=CAIRO_NO_SANITY_CHECKING
-else
- SANITY_CHECKING_FEATURE=CAIRO_DO_SANITY_CHECKING
-fi
-
-AC_SUBST(SANITY_CHECKING_FEATURE)
-
-dnl ===========================================================================
-
PKG_CHECK_MODULES(PIXMAN, libpixman >= 0.1.4)
CAIRO_CFLAGS="$CAIRO_CFLAGS $PIXMAN_CFLAGS"
CAIRO_LIBS="$CAIRO_LIBS $PIXMAN_LIBS"
@@ -333,12 +299,9 @@ fi
CAIRO_CFLAGS="$CAIRO_CFLAGS $FREETYPE_CFLAGS"
CAIRO_LIBS="$CAIRO_LIBS $FREETYPE_LIBS"
-if test "x$use_freetype" != "xyes"; then
- FT_FONT_FEATURE=CAIRO_HAS_NO_FT_FONT
- AM_CONDITIONAL(CAIRO_HAS_FT_FONT, false)
-else
- FT_FONT_FEATURE=CAIRO_HAS_FT_FONT
- AM_CONDITIONAL(CAIRO_HAS_FT_FONT, true)
+AM_CONDITIONAL(CAIRO_HAS_FT_FONT, test "x$use_freetype" = "xyes")
+if test "x$use_freetype" = "xyes"; then
+ FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
fi
AC_SUBST(FT_FONT_FEATURE)
@@ -353,18 +316,15 @@ if test x"$use_freetype" != "xyes" ; then
use_pdf=no
fi
-if test "x$use_pdf" != "xyes"; then
- PDF_SURFACE_FEATURE=CAIRO_HAS_NO_PDF_SURFACE
- AM_CONDITIONAL(CAIRO_HAS_PDF_SURFACE, false)
-else
- PDF_SURFACE_FEATURE=CAIRO_HAS_PDF_SURFACE
+AM_CONDITIONAL(CAIRO_HAS_PDF_SURFACE, test "x$use_pdf" = "xyes")
+if test "x$use_pdf" = "xyes"; then
+ PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
PDF_LIBS=-lz
- AM_CONDITIONAL(CAIRO_HAS_PDF_SURFACE, true)
fi
+AC_SUBST(PDF_SURFACE_FEATURE)
CAIRO_LIBS="$CAIRO_LIBS $PDF_LIBS"
-AC_SUBST(PDF_SURFACE_FEATURE)
AC_SUBST(PDF_LIBS)
dnl ===========================================================================
@@ -381,17 +341,15 @@ if test "x$use_atsui" = "xyes"; then
AC_CHECK_HEADER(Carbon/Carbon.h, [use_atsui=yes], [use_atsui=no])
fi
-if test "x$use_atsui" != "xyes"; then
- ATSUI_FONT_FEATURE=CAIRO_HAS_NO_ATSUI_FONT
- AM_CONDITIONAL(CAIRO_HAS_ATSUI_FONT, false)
-else
- ATSUI_FONT_FEATURE=CAIRO_HAS_ATSUI_FONT
- AM_CONDITIONAL(CAIRO_HAS_ATSUI_FONT, true)
+AM_CONDITIONAL(CAIRO_HAS_ATSUI_FONT, test "x$use_atsui" = "xyes")
+if test "x$use_atsui" = "xyes"; then
+ ATSUI_FONT_FEATURE="#define CAIRO_HAS_ATSUI_FONT 1"
fi
AC_SUBST(ATSUI_FONT_FEATURE)
dnl ===========================================================================
dnl Checks for precise integer types
+AC_CHECK_HEADERS([stdint.h inttypes.h sys/int_types.h])
AC_CHECK_TYPES([uint64_t, uint128_t])
dnl Use lots of warning flags with GCC
@@ -435,14 +393,15 @@ echo " XCB: $use_xcb"
echo " Win32: $use_win32"
echo " PostScript: $use_ps"
echo " PDF: $use_pdf"
-echo " PNG: $use_png"
echo " glitz: $use_glitz"
echo ""
-echo "and the following font backends:"
+echo "the following font backends:"
echo " FreeType: $use_freetype"
echo " Win32: $use_win32"
echo " ATSUI: $use_atsui"
echo ""
+echo "and the following features:"
+echo " PNG functions: $use_png"
if test x"$use_freetype" != "xyes" && \
test x"$use_win32" != "xyes" && \
@@ -453,4 +412,3 @@ if test x"$use_freetype" != "xyes" && \
http://freetype.org/ http://fontconfig.org/
])
fi
-
diff --git a/doc/public/Makefile.am b/doc/public/Makefile.am
index b993bb978..f058d36aa 100644
--- a/doc/public/Makefile.am
+++ b/doc/public/Makefile.am
@@ -19,11 +19,15 @@ HFILE_GLOB=$(top_srcdir)/src/*.h
CFILE_GLOB=$(top_srcdir)/src/*.c $(top_srcdir)/src/*.h
# Headers to ignore
-IGNORE_HFILES= \
- cairo-features.h \
- cairo-ft-private.h \
- cairo-win32-private.h \
- cairoint.h \
+IGNORE_HFILES= \
+ cairo-features.h \
+ cairo-ft-private.h \
+ cairo-gstate-private.h \
+ cairo-path-fixed-private.h \
+ cairo-private.h \
+ cairo-win32-private.h \
+ cairo-xlib-test.h \
+ cairoint.h \
cairo-wideint.h
# CFLAGS and LDFLAGS for compiling scan program. Only needed
@@ -35,7 +39,8 @@ GTKDOC_LIBS =
MKDB_OPTIONS=--sgml-mode --output-format=xml
# Non-autogenerated SGML files to be included in $(DOC_MAIN_SGML_FILE)
-content_files =
+content_files = \
+ language-bindings.xml
# Images to copy into HTML directory
HTML_IMAGES =
diff --git a/doc/public/cairo-docs.xml b/doc/public/cairo-docs.xml
index 2a4cdae8a..729738aac 100644
--- a/doc/public/cairo-docs.xml
+++ b/doc/public/cairo-docs.xml
@@ -12,6 +12,7 @@
<xi:include href="xml/cairo-surface.xml"/>
<xi:include href="xml/cairo-pattern.xml"/>
<xi:include href="xml/cairo-matrix.xml"/>
+ <xi:include href="xml/cairo-font.xml"/>
<xi:include href="xml/cairo-atsui.xml"/>
<xi:include href="xml/cairo-ft.xml"/>
<xi:include href="xml/cairo-glitz.xml"/>
@@ -22,10 +23,9 @@
<xi:include href="xml/cairo-win32.xml"/>
<xi:include href="xml/cairo-xcb.xml"/>
<xi:include href="xml/cairo-xlib.xml"/>
- </part>
+ </part>
+ <index>
+ <title>Index</title>
+ </index>
+ <xi:include href="language-bindings.xml"/>
</book>
-
-
-
-
-
diff --git a/doc/public/cairo-sections.txt b/doc/public/cairo-sections.txt
index 3da0fa801..b462436b8 100644
--- a/doc/public/cairo-sections.txt
+++ b/doc/public/cairo-sections.txt
@@ -7,70 +7,68 @@ cairo_atsui_font_create
<SECTION>
<FILE>cairo-ft</FILE>
<TITLE>FreeType Fonts</TITLE>
-cairo_ft_font_create
-cairo_ft_font_create_for_ft_face
-cairo_ft_font_lock_face
-cairo_ft_font_unlock_face
-cairo_ft_font_get_pattern
+cairo_ft_font_face_create_for_pattern
+cairo_ft_font_face_create_for_ft_face
+cairo_ft_scaled_font_lock_face
+cairo_ft_scaled_font_unlock_face
</SECTION>
<SECTION>
<FILE>cairo-glitz</FILE>
<TITLE>Glitz backend</TITLE>
-cairo_set_target_glitz
cairo_glitz_surface_create
</SECTION>
<SECTION>
<FILE>cairo-pdf</FILE>
<TITLE>PDF Backend</TITLE>
-cairo_set_target_pdf
cairo_pdf_surface_create
+cairo_pdf_surface_create_for_callback
</SECTION>
<SECTION>
<FILE>cairo-png</FILE>
<TITLE>PNG Backend</TITLE>
-cairo_set_target_png
-cairo_png_surface_create
+cairo_image_surface_create_from_png
+cairo_image_surface_create_from_png_stream
+cairo_surface_write_to_png
+cairo_surface_write_to_png_stream
</SECTION>
<SECTION>
<FILE>cairo-ps</FILE>
<TITLE>PS Backend</TITLE>
-cairo_set_target_ps
cairo_ps_surface_create
</SECTION>
<SECTION>
<FILE>cairo-quartz</FILE>
<TITLE>Quartz Backend</TITLE>
-cairo_set_target_quartz_context
cairo_quartz_surface_create
</SECTION>
<SECTION>
<FILE>cairo-win32</FILE>
<TITLE>Microsoft Windows Backend</TITLE>
-cairo_set_target_win32
cairo_win32_surface_create
-cairo_win32_font_create_for_logfontw
-cairo_win32_font_select_font
-cairo_win32_font_done_font
-cairo_win32_font_get_scale_factor
+cairo_win32_font_face_create_for_logfontw
+cairo_win32_scaled_font_select_font
+cairo_win32_scaled_font_done_font
+cairo_win32_scaled_font_get_metrics_factor
</SECTION>
<SECTION>
<FILE>cairo-xcb</FILE>
<TITLE>XCB Backend</TITLE>
-cairo_set_target_xcb
+cairo_xcb_surface_create
</SECTION>
<SECTION>
<FILE>cairo-xlib</FILE>
<TITLE>XLib Backend</TITLE>
-cairo_set_target_drawable
cairo_xlib_surface_create
+cairo_xlib_surface_create_with_visual
+cairo_xlib_surface_set_size
</SECTION>
<SECTION>
@@ -81,11 +79,15 @@ cairo_surface_create_for_image
cairo_surface_create_similar
cairo_surface_reference
cairo_surface_destroy
+cairo_surface_finish
cairo_surface_set_repeat
cairo_surface_set_matrix
cairo_surface_get_matrix
cairo_surface_set_filter
cairo_surface_get_filter
+cairo_surface_set_user_data
+cairo_surface_get_user_data
+cairo_surface_set_device_offset
</SECTION>
<SECTION>
@@ -97,7 +99,8 @@ cairo_pattern_create_linear
cairo_pattern_create_radial
cairo_pattern_reference
cairo_pattern_destroy
-cairo_pattern_add_color_stop
+cairo_pattern_add_color_stop_rgb
+cairo_pattern_add_color_stop_rgba
cairo_pattern_set_matrix
cairo_pattern_get_matrix
cairo_extend_t
@@ -105,18 +108,19 @@ cairo_pattern_set_extend
cairo_pattern_get_extend
cairo_pattern_set_filter
cairo_pattern_get_filter
+<SUBSECTION Private>
+cairo_pattern_add_color_stop
</SECTION>
<SECTION>
<FILE>cairo-matrix</FILE>
<TITLE>cairo_matrix_t</TITLE>
cairo_matrix_t
-cairo_matrix_create
-cairo_matrix_destroy
-cairo_matrix_copy
-cairo_matrix_set_identity
-cairo_matrix_set_affine
-cairo_matrix_get_affine
+cairo_matrix_init
+cairo_matrix_init_identity
+cairo_matrix_init_translate
+cairo_matrix_init_scale
+cairo_matrix_init_rotate
cairo_matrix_translate
cairo_matrix_scale
cairo_matrix_rotate
@@ -124,6 +128,31 @@ cairo_matrix_invert
cairo_matrix_multiply
cairo_matrix_transform_distance
cairo_matrix_transform_point
+<SUBSECTION Private>
+cairo_matrix_create
+cairo_matrix_destroy
+cairo_matrix_copy
+cairo_matrix_set_identity
+cairo_matrix_set_affine
+cairo_matrix_get_affine
+</SECTION>
+
+<SECTION>
+<FILE>cairo-font</FILE>
+<TITLE>Fonts</TITLE>
+cairo_font_face_t
+cairo_scaled_font_t
+cairo_font_face_reference
+cairo_font_face_destroy
+cairo_font_face_get_user_data
+cairo_font_face_set_user_data
+cairo_scaled_font_create
+cairo_scaled_font_reference
+cairo_scaled_font_destroy
+cairo_font_extents_t
+cairo_scaled_font_extents
+cairo_text_extents_t
+cairo_scaled_font_glyph_extents
</SECTION>
<SECTION>
@@ -136,13 +165,13 @@ cairo_destroy
cairo_save
cairo_restore
cairo_copy
-cairo_set_target_surface
cairo_format_t
-cairo_set_target_image
cairo_operator_t
cairo_set_operator
-cairo_set_rgb_color
-cairo_set_pattern
+cairo_set_source_rgb
+cairo_set_source_rgba
+cairo_set_source
+cairo_set_source_surface
cairo_set_alpha
cairo_set_tolerance
cairo_fill_rule_t
@@ -157,14 +186,14 @@ cairo_set_miter_limit
cairo_translate
cairo_scale
cairo_rotate
-cairo_concat_matrix
+cairo_transform
cairo_set_matrix
cairo_default_matrix
cairo_identity_matrix
-cairo_transform_point
-cairo_transform_distance
-cairo_inverse_transform_point
-cairo_inverse_transform_distance
+cairo_user_to_device
+cairo_user_to_device_distance
+cairo_device_to_user
+cairo_device_to_user_distance
cairo_new_path
cairo_move_to
cairo_line_to
@@ -176,8 +205,14 @@ cairo_rel_line_to
cairo_rel_curve_to
cairo_rectangle
cairo_close_path
+cairo_paint
+cairo_paint_with_alpha
+cairo_mask
+cairo_mask_surface
cairo_stroke
+cairo_stroke_preserve
cairo_fill
+cairo_fill_preserve
cairo_copy_page
cairo_show_page
cairo_in_stroke
@@ -185,35 +220,61 @@ cairo_in_fill
cairo_bool_t
cairo_stroke_extents
cairo_fill_extents
-cairo_init_clip
cairo_clip
-cairo_font_t
+cairo_clip_preserve
+cairo_reset_clip
cairo_glyph_t
-cairo_text_extents_t
-cairo_font_extents_t
cairo_font_slant_t
cairo_font_weight_t
-cairo_select_font
-cairo_scale_font
-cairo_transform_font
+cairo_select_font_face
+cairo_set_font_size
+cairo_set_font_matrix
+cairo_get_font_matrix
cairo_show_text
cairo_show_glyphs
-cairo_current_font
-cairo_current_font_extents
-cairo_set_font
+cairo_get_font_face
+cairo_font_extents
+cairo_set_font_face
cairo_text_extents
cairo_glyph_extents
cairo_text_path
cairo_glyph_path
-cairo_font_reference
-cairo_font_destroy
-cairo_font_extents
-cairo_font_glyph_extents
cairo_show_surface
+cairo_get_operator
+cairo_get_source
+cairo_get_tolerance
+cairo_get_current_point
+cairo_get_fill_rule
+cairo_get_line_width
+cairo_get_line_cap
+cairo_get_line_join
+cairo_get_miter_limit
+cairo_get_matrix
+cairo_get_target
+cairo_get_path
+cairo_get_path_flat
+cairo_copy_path
+cairo_copy_path_flat
+cairo_append_path
+cairo_path_t
+cairo_path_destroy
+cairo_status_t
+cairo_status
+cairo_status_string
+cairo_filter_t
+cairo_image_surface_create
+cairo_image_surface_create_for_data
+cairo_image_surface_get_width
+cairo_image_surface_get_height
+cairo_destroy_func_t
+cairo_user_data_key_t
+cairo_read_func_t
+cairo_write_func_t
+<SUBSECTION Private>
+CAIRO_BEGIN_DECLS
+CAIRO_END_DECLS
+cairo_concat_matrix
cairo_current_operator
-cairo_current_rgb_color
-cairo_current_pattern
-cairo_current_alpha
cairo_current_tolerance
cairo_current_point
cairo_current_fill_rule
@@ -225,27 +286,18 @@ cairo_current_matrix
cairo_current_target_surface
cairo_current_path
cairo_current_path_flat
-cairo_status_t
-cairo_status
-cairo_status_string
-cairo_filter_t
-cairo_image_surface_create
-cairo_image_surface_create_for_data
-<SUBSECTION Private>
-CAIRO_BEGIN_DECLS
-CAIRO_END_DECLS
-cairo_get_operator
-cairo_get_rgb_color
-cairo_get_alpha
-cairo_get_tolerance
-cairo_get_current_point
-cairo_get_fill_rule
-cairo_get_line_width
-cairo_get_line_cap
-cairo_get_line_join
-cairo_get_miter_limit
-cairo_get_matrix
-cairo_get_target_surface
+cairo_current_font_extents
+cairo_init_clip
+cairo_inverse_transform_point
+cairo_inverse_transform_distance
+cairo_scale_font
+cairo_select_font
+cairo_set_pattern
+cairo_set_rgb_color
+cairo_transform_font
+cairo_get_font_extents
cairo_get_status
cairo_get_status_string
+cairo_transform_point
+cairo_transform_distance
</SECTION>
diff --git a/doc/public/language-bindings.xml b/doc/public/language-bindings.xml
new file mode 100644
index 000000000..1b999d82f
--- /dev/null
+++ b/doc/public/language-bindings.xml
@@ -0,0 +1,726 @@
+<appendix id="language-bindings">
+ <title>Creating a language binding for cairo</title>
+ <para>
+ While cairo is implemented and C, and has a C API, it is expected
+ that many users of cairo will be using it from languages other
+ than C. The glue that connects the core cairo library to another
+ language is known as a <firstterm>language
+ binding</firstterm>. This appendix attempts to collect together
+ issues that come up when creating a language bindings for cairo
+ and present standardized solutions to promote consistency among
+ the different language bindings.
+ </para>
+ <sect1 id="bindings-general">
+ <title>General considerations</title>
+ <para>
+ The naming of the central <link
+ linkend="cairo-t"><type>cairo_t</type></link> type is a
+ special exception. The object is “a cairo context” not “a
+ cairo”, and names such as <type>cairo_t</type> rather than
+ <type>cairo_context_t</type> and
+ <function>cairo_set_source()</function> rather than
+ <function>cairo_context_set_source()</function> are simply
+ abbreviations to make the C API more palatable. In languages
+ which have object-oriented syntax, this abbreviation is much
+ less useful. In fact, if ‘Cairo’ is used as a namespace, then
+ in many languages, you'd end up with a ridiculous type name
+ like ‘Cairo.Cairo’. For this reason, and for inter-language
+ consistency all object-oriented languages should name this
+ type as if it were <type>cairo_context_t</type>.
+ </para>
+ <para>
+ The punctuation and casing of the type names and
+ method names of cairo should be changed to match the general
+ convention of the language. In Java, where type names are written
+ in StudlyCaps and method names in javaCaps, cairo_font_extents_t
+ will become FontExtents and
+ <literal>cairo_set_source(cr,source)</literal>,
+ <literal>cr.setSource(source)</literal>.
+ As compared to changing the punctuation, and casing, much
+ more reluctance should be used in changing the method names
+ themselves. Even if get is usually omitted from getters in
+ your language, you shouldn't bind cairo_get_source() as
+ cr.source().
+ </para>
+ </sect1>
+ <sect1 id="bindings-memory">
+ <title>Memory Management</title>
+ <para>
+ The objects in cairo can roughly be divided into two types:
+ refcounted opaque types like
+ <link
+ linkend="cairo-surface-t"><type>cairo_surface_t</type></link>
+ and plain structures like
+ <link
+ linkend="cairo-glyph-t"><type>cairo_glyph_t</type></link>.
+ <link
+ linkend="cairo-path-t"><type>cairo_path_t</type></link>
+ and
+ <link
+ linkend="cairo-path-data-t"><type>cairo_path_data_t</type></link>
+ are special cases and are treated separately in this appendix.
+ </para>
+ <para>
+ Refcounted opaque types all have a
+ <function>..._reference()</function>
+ function to increase the refcount by one and a
+ <function>..._destroy()</function> to decrease the refcount
+ by one. These should not be exposed to the user of the language
+ binding, but rather used to implement memory management within
+ the language binding. The simplest way to do memory management
+ for a language binding is to treat the language binding object
+ as a simple handle to the cairo object. The language binding
+ object references the cairo object, and unreferences it when
+ finalized. This is the recommended method, though there are
+ a couple of caveats to be noted:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Equality won't work as expected. You can have two language
+ objects for the same cairo and they won't necessarily
+ compare equal. If the language allows customizing the
+ equality operation, then this is fixable by comparing
+ the underlying pointers. It also can be fixed by creating
+ at most one language object per cairo object, and
+ uniquifying via a <firstterm>pin table</firstterm> (a hash
+ table that goes from cairo object to language object).
+ For <type>cairo_surface_t</type> you can use also
+ <link
+ linkend="cairo-surface-set-user-data"><function>cairo_surface_set_user_data()</function></link>
+ instead of a separate pin table.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Derivation from the language object doesn't work because
+ you can lose the language object while keeping the Cairo
+ object. Code like:
+ </para>
+<programlisting>
+public class MySurface (ImageSurface) {
+ public MySurface (width, height) {
+ super (Format.ARGB32, width, height);
+ }
+ public int get42 () {
+ return 42;
+ }
+}
+
+ cr = Cairo(MySurface(width, height));
+ surface = cr.getTarget();
+</programlisting>
+ <para>
+ Can result in <varname>surface</varname> containing an
+ <classname>ImageSurface</classname> not a <classname>MySurface</classname>.
+ This is not easily fixable without creating memory leaks,
+ and it's probably best to simply forbid deriving from the
+ language objects.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ When a plain structure is used as a return value from cairo,
+ this is done by passing it as a “out parameter”.
+ </para>
+<programlisting>
+cairo_font_extents_t extents;
+
+cairo_font_extents (cr, &amp;extents);</programlisting>
+ <para>
+ In a language binding, this should typically be treated
+ as a return value:
+ </para>
+<programlisting>
+FontExtents extents = cr.fontExtents ();</programlisting>
+ <para>
+ A language binding has a choice in how it implements the
+ language objects for plain structures. It can use a pure
+ language object with fields corresponding to those of the C
+ structure, and convert from and to the C structure when calling
+ cairo functions or converting cairo return values. Or it
+ can keep a pointer to the C structure internally and wrap
+ it inside a language object much like occurs for refcounted
+ objects. The choice should be invisible to the user: they should
+ be able to imagine that it is implemented as a pure language
+ object.
+ </para>
+ </sect1>
+ <sect1 id="bindings-return-values">
+ <title>Multiple return values</title>
+ <para>
+ There are a number of functions in the cairo API that have
+ multiple <firstterm>out parameters</firstterm> or
+ <firstterm>in-out parameters</firstterm>. In some languages
+ these can be translated into multiple return values. In Python,
+ what is:
+ </para>
+ <programlisting>
+cairo_user_to_device (cr, &amp;x, &amp;y);</programlisting>
+ <para>
+ can by mapped to:
+ </para>
+ <programlisting>
+(x, y) = cr.user_to_device (cr, x, y);</programlisting>
+ <para>
+ but many languages don't have provisions for multiple return
+ values, so it is necessary to introduce auxiliary types.
+ Most of the functions that require the auxiliary types
+ require a type that would, in C, look like
+ </para>
+ <programlisting>
+typedef struct _cairo_point cairo_point_t;
+struct _cairo_point {
+ double x;
+ double y;
+}</programlisting>
+ <para>
+ The same type should be used both for functions that use a pair
+ of coordinates as an absolute position, and functions that use
+ a pair of coordinates as a displacement. While an argument could
+ be made that having a separate “distance” type is more correct,
+ it is more likely just to confuse users.
+ </para>
+ <programlisting>
+void
+cairo_user_to_device (cairo_t *cr, double *x, double *y);
+
+void
+cairo_user_to_device_distance (cairo_t *cr, double *dx, double *dy);
+
+void
+cairo_device_to_user (cairo_t *cr, double *x, double *y);
+
+void
+cairo_device_to_user_distance (cairo_t *cr, double *dx, double *dy);
+
+void
+cairo_matrix_transform_distance (cairo_matrix_t *matrix, double *dx, double *dy);
+
+void
+cairo_matrix_transform_point (cairo_matrix_t *matrix, double *x, double *y);
+
+void
+cairo_get_current_point (cairo_t *cr, double *x, double *y);
+ </programlisting>
+ <para>
+ There are also a couple of functions that return four values
+ representing a rectangle. These should be mapped to a
+ “rectangle” type that looks like:
+ </para>
+ <programlisting>
+typedef struct _cairo_rectangle cairo_rectangle_t;
+struct _cairo_rectangle {
+ double x;
+ double y;
+ double width;
+ double height;
+}</programlisting>
+ <para>
+ The C function returns the rectangle as a set of two points to
+ facilitate rounding to integral extents, but this isn't worth
+ adding a “box” type to go along with the more obvious
+ “rectangle” representation.
+ </para>
+ <remark>
+ Q: Would it make sense here to define a standard
+ <function>cairo_rectangle_round()</function> method
+ that language bindings should map?
+ </remark>
+ <programlisting>
+void
+cairo_stroke_extents (cairo_t *cr,
+ double *x1, double *y1,
+ double *x2, double *y2);
+
+void
+cairo_fill_extents (cairo_t *cr,
+ double *x1, double *y1,
+ double *x2, double *y2);
+ </programlisting>
+ </sect1>
+ <sect1 id="bindings-overloading">
+ <title>Overloading and optional arguments</title>
+ <para>
+ Function overloading (having a several variants of a function
+ with the same name and different arguments) is a language
+ feature available in many languages but not in C.
+ </para>
+ <para>
+ In general, language binding authors should use restraint in
+ combining functions in the cairo API via function
+ overloading. What may seem like an obvious overload now may
+ turn out to be strange with future additions to cairo.
+ It might seem logical to make
+ <link
+ linkend="cairo-set-source-rgb"><function>cairo_set_source_rgb()</function></link>
+ an overload of <function>cairo_set_source()</function>, but future plans to add
+ <function>cairo_set_source_rgb_premultiplied()</function>,
+ which will also take three doubles make this a bad idea. For
+ this reason, only the following pairs of functions should
+ be combined via overloading
+ </para>
+ <programlisting>
+void
+cairo_set_source (cairo_t *cr, cairo_pattern_t *source);
+
+void
+cairo_set_source_surface (cairo_t *cr,
+ cairo_surface_t *source,
+ double surface_x,
+ double surface_y);
+
+void
+cairo_mask (cairo_t *cr,
+ cairo_pattern_t *pattern);
+
+void
+cairo_mask_surface (cairo_t *cr,
+ cairo_surface_t *surface,
+ double surface_x,
+ double surface_y);
+
+cairo_surface_t *
+cairo_image_surface_create (cairo_format_t format,
+ int width,
+ int height);
+cairo_surface_t *
+cairo_image_surface_create_for_data (unsigned char *data,
+ cairo_format_t format,
+ int width,
+ int height,
+ int stride);
+
+cairo_status_t
+cairo_surface_write_to_png (cairo_surface_t *surface,
+ const char *filename);
+
+cairo_status_t
+cairo_surface_write_to_png_stream (cairo_surface_t *surface,
+ cairo_write_func_t write_func,
+ void *closure);
+
+cairo_surface_t *
+cairo_image_surface_create_from_png (const char *filename);
+
+cairo_surface_t *
+cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func,
+ void *closure);
+ </programlisting>
+ <para>
+ Note that there are cases where all constructors for a type
+ aren't overloaded together. For example
+ <link
+ linkend="cairo-image-surface-create-from-png"><function>cairo_image_surface_create_from_png()</function></link>
+ should <emphasis>not</emphasis> be overloaded together with
+ <link
+ linkend="cairo-image-surface-create"><function>cairo_image_surface_create()</function></link>.
+ In such cases, the remaining constructors will typically need to
+ be bound as static methods. In Java, for example, we might have:
+ </para>
+<programlisting>
+Surface surface1 = ImageSurface(Format.RGB24, 100, 100);
+Surface surface2 = ImageSurface.createFromPNG("camera.png");</programlisting>
+ <para>
+ Some other overloads that add combinations not found in C may be
+ convenient for users for language bindings that provide
+ <type>cairo_point_t</type> and <type>cairo_rectangle_t</type>
+ types, for example:
+ </para>
+ <programlisting>
+void
+cairo_move_to (cairo_t *cr,
+ cairo_point_t *point);
+void
+cairo_rectangle (cairo_t *cr,
+ cairo_rectangle_t *rectangle);
+ </programlisting>
+ </sect1>
+ <sect1 id="bindings-streams">
+ <title>Streams and File I/O</title>
+ <para>
+ Various places in the cairo API deal with reading and writing
+ data, whether from and to files, or to other sources and
+ destinations. In these cases, what is typically provided in the
+ C API is a simple version that just takes a filename, and a
+ complex version that takes a callback function.
+ An example is the PNG handling functions:
+ </para>
+<programlisting>
+cairo_surface_t *
+cairo_image_surface_create_from_png (const char *filename);
+
+cairo_surface_t *
+cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func,
+ void *closure);
+
+cairo_status_t
+cairo_surface_write_to_png (cairo_surface_t *surface,
+ const char *filename);
+
+cairo_status_t
+cairo_surface_write_to_png_stream (cairo_surface_t *surface,
+ cairo_write_func_t write_func,
+ void *closure);</programlisting>
+ <para>
+ The expectation is that the filename version will be mapped
+ literally in the language binding, but the callback version
+ will be mapped to a version that takes a language stream
+ object. For example, in Java, the four functions above
+ might be mapped to:
+ </para>
+<programlisting>
+static public ImageSurface createFromPNG (String filename) throws IOException;
+static public ImageSurface createFromPNG (InputStream stream) throws IOException;
+public void writeToPNG (String filename) throws IOException;
+public void writeToPNG (OutputStream stream) throws IOException;
+</programlisting>
+ <para>
+ In many cases, it will be better to
+ implement the filename version internally
+ using the stream version, rather than building it on top of the
+ filename version in C. The reason for this is that will
+ naturally give a more standard handling of file errors for
+ the language, as seen in the above Java example, where
+ <methodname>createFromPNG()</methodname> is marked as raising
+ an exception. Propagating exceptions from inside the callback
+ function to the caller will pose a challenge to the language
+ binding implementor, since an exception must not propagate
+ through the Cairo code. A technique that will be useful in
+ some cases is to catch the exception in the callback,
+ store the exception object inside a structure pointed to by
+ <parameter>closure</parameter>, and then rethrow it once
+ the function returns.
+ </para>
+ <remark>
+ I'm not sure how to handle this for
+ <link
+ linkend="cairo-pdf-surface-create-for-callback"><function>cairo_pdf_surface_create_for_callback()</function></link>.
+ Other than keep a “exception to rethrow” thread-specific
+ variable
+ that is checked after <emphasis>every</emphasis> call to a Cairo
+ function.
+ </remark>
+ </sect1>
+ <sect1 id="bindings-errors">
+ <title>Error handling</title>
+ <para>
+ The error handling approach in C for Cairo has multiple
+ elements:
+ </para>
+ <itemizedlist>
+ <listitem><para>
+ When a method on an object fails, the object is put into
+ an error state. Subsequent operations on the object do
+ nothing. The status of the object can be queried with
+ a function like <link
+ linkend="cairo-status"><function>status()</function></link>.
+ </para></listitem>
+ <listitem><para>
+ Constructors, rather than
+ returning<constant>NULL</constant> on out-of-memory failure,
+ return a special singleton object on which all
+ operations do nothing. Retrieving the status of the
+ singleton object returns <constant>CAIRO_STATUS_NO_MEMORY</constant>
+ </para>
+ <remark>
+ Is this going to apply to
+ <type>cairo_surface_t</type> as well?
+ </remark>
+ <remark>
+ What about cairo_copy_path_data()? It's probably going to
+ have to return <constant>NULL</constant>.
+ </remark>
+ </listitem>
+ <listitem><para>
+ Errors propagate from object to object. Setting a pattern
+ in an out-of-memory state as the source of a
+ <type>cairo_t</type> puts the type into an error state.
+ </para></listitem>
+ </itemizedlist>
+ <remark>Much of the above is not yet implemented at the time of
+ this writing</remark>
+ <para>
+ A language binding could copy the C approach, and for a
+ language without exceptions, this is likely the right thing
+ to do. However, for a language with exceptions, exposing
+ a completely different style of error handling for cairo
+ would be strange. So, instead, status should be checked
+ after every call to cairo, and exceptions thrown as necessary.
+ </para>
+ <para>
+ One problem that can arise with this, in languages
+ where handling exceptions is mandatory (like Java), is that almost
+ every cairo function can result in a status being set,
+ usually because of an out-of-memory condition. This could make
+ cairo hard to use. To resolve this problem, let's classify then
+ cairo status codes:
+ </para>
+<programlisting>
+/* Memory */
+CAIRO_STATUS_NO_MEMORY,
+
+/* Programmer error */
+CAIRO_STATUS_INVALID_RESTORE
+CAIRO_STATUS_INVALID_POP_GROUP
+CAIRO_STATUS_NO_CURRENT_POINT
+CAIRO_STATUS_INVALID_MATRIX
+CAIRO_STATUS_NO_TARGET_SURFACE
+CAIRO_STATUS_INVALID_STRING
+CAIRO_STATUS_SURFACE_FINISHED
+CAIRO_STATUS_BAD_NESTING
+
+/* Language binding implementation */
+CAIRO_STATUS_NULL_POINTER
+CAIRO_STATUS_INVALID_PATH_DATA
+CAIRO_STATUS_SURFACE_TYPE_MISMATCH
+
+/* Other */
+CAIRO_STATUS_READ_ERROR
+CAIRO_STATUS_WRITE_ERROR
+</programlisting>
+ <para>
+ If we look at these, the
+ <constant>CAIRO_STATUS_NO_MEMORY</constant>
+ should map to the native out-of-memory exception, which could
+ happen at any point in any case. Most of the others indicate
+ programmer error, and handling them in user code would be
+ silly. These should be mapped into whatever the language uses
+ for assertion failures, rather than errors that are normally
+ handled. (In Java, a subclass of Error rather than Exception,
+ perhaps.) And <constant>CAIRO_STATUS_READ_ERROR</constant>,
+ and <constant>CAIRO_STATUS_WRITE_ERROR</constant> can occur
+ only in very specific places. (In fact, as described
+ in <xref linkend="bindings-streams"/>, these errors may be
+ mapped into the language's native I/O error types.)
+ So, there really aren't exceptions that the programmer must
+ handle at most points in the Cairo API.
+ </para>
+ </sect1>
+ <sect1 id="bindings-patterns">
+ <title>Patterns</title>
+ <para>
+ The cairo C API allows for creating a number of different types
+ of patterns. All of these different types of patterns map to
+ <link
+ linkend="cairo-pattern-t"><type>cairo_pattern_t</type></link>
+ in C, but in an object oriented language, there should instead
+ be a hierarchy of types. (The functions that should map to
+ constructors for the various types are listed after the type,
+ methods on that type are listed below)
+ </para>
+ <programlisting>
+cairo_pattern_t
+ <link linkend="cairo-pattern-set-matrix"><function>cairo_pattern_set_matrix()</function></link>
+ <link linkend="cairo-pattern-get-matrix"><function>cairo_pattern_get_matrix()</function></link>
+ cairo_solid_pattern_t
+ cairo_surface_pattern_t (<link linkend="cairo-pattern-create-for-surface"><function>cairo_pattern_create_for_surface()</function></link>)
+ <link linkend="cairo-pattern-set-extend"><function>cairo_pattern_set_extend()</function></link>
+ <link linkend="cairo-pattern-get-extend"><function>cairo_pattern_get_extend()</function></link>
+ <link linkend="cairo-pattern-set-filter"><function>cairo_pattern_set_filter()</function></link>
+ <link linkend="cairo-pattern-get-filter"><function>cairo_pattern_get_filter()</function></link>
+ cairo_gradient_t
+ <link linkend="cairo-pattern-add-color-stop-rgb"><function>cairo_pattern_add_color_stop_rgb()</function></link>
+ <link linkend="cairo-pattern-add-color-stop-rgba"><function>cairo_pattern_add_color_stop_rgba()</function></link>
+ cairo_linear_gradient_t (<link linkend="cairo-pattern-create-linear"><function>cairo_pattern_create_linear()</function></link>)
+ cairo_radial_gradient_t (<link linkend="cairo-pattern-create-radial"><function>cairo_pattern_create_radial()</function></link>)
+ </programlisting>
+ <para>
+ </para>
+ </sect1>
+ <sect1 id="bindings-surfaces">
+ <title>Surfaces</title>
+ <para>
+ Like patterns, surfaces, which use only the
+ <link
+ linkend="cairo-surface-t"><type>cairo_surface_t</type></link>
+ type in the C API should be broken up into a heirarchy of types
+ in a language binding.
+ </para>
+ <programlisting>
+cairo_surface_t
+ cairo_image_surface_t
+ cairo_atsui_surface_t
+ cairo_win32_surface_t
+ cairo_xlib_surface_t
+ </programlisting>
+ <para>
+ Unlike patterns, the constructors and methods on these types are
+ clearly named, and can be trivially associated with the
+ appropriate subtype. Many language bindings will want to avoid
+ binding the platform-specific subtypes at all, since the
+ methods on these types are not useful without passing in native
+ C types. Unless there is a language binding for Xlib available,
+ there is no way to represent a XLib <type>Display</type> * in
+ that language.
+ </para>
+ <para>
+ This doesn't mean that platform-specific surface types can't
+ be used in a language binding that doesn't bind the constructor.
+ A very common situation is to use a cairo language binding in
+ combination with a binding for a higher level system like
+ the <ulink url="http://www.gtk.org/">GTK+</ulink> widget
+ toolkit. In such a situation, the higher level toolkit provides
+ ways to get references to platform specific surfaces.
+ </para>
+ <para>
+ The <link
+ linkend="cairo-surface-set-user-data"><function>cairo_surface_set_user_data()</function></link>,
+ and <link
+ linkend="cairo-surface-get-user-data"><function>cairo_surface_get_user_data()</function></link>
+ methods are provided for use in language bindings, and should
+ not be directly exposed to applications. One example of the use
+ of these functions in a language binding is creating a binding for:
+ </para>
+<programlisting>
+cairo_surface_t *
+<link linkend="cairo-image-surface-create-for-data"><function>cairo_image_surface_create_for_data</function></link> (unsigned char *data,
+ cairo_format_t format,
+ int width,
+ int height,
+ int stride);
+</programlisting>
+ <para>
+ The memory block passed in for <parameter>data</parameter> must be
+ kept around until the surface is destroyed, so the language
+ binding must have some way of determining when that happens. The
+ way to do this is to use the <parameter>destroy</parameter>
+ argument to <function>cairo_surface_set_user_data()</function>.
+ </para>
+ <remark>
+ Some languages may not have a suitable “pointer to a block of
+ data” type to pass in for <parameter>data</parameter>. And even
+ where a language does have such a type, the user will be
+ frequently able to cause the backing store to be reallocated
+ to a different location or truncated. Should we recommend a
+ standard type name and binding for a buffer object here?
+ </remark>
+ </sect1>
+ <sect1 id="bindings-fonts">
+ <title>Fonts</title>
+ <para>
+ Fonts are once more an area where there is a hierarchy of types:
+ </para>
+<programlisting>
+cairo_font_face_t
+ cairo_ft_font_face_t
+ cairo_win32_font_face_t
+cairo_scaled_font_t
+ cairo_ft_scaled_font_t
+ cairo_win32_scaled_font_t
+</programlisting>
+ <para>
+ The methods on the subtypes are, however, not useful without
+ bindings for fontconfig and FreeType or for the Win32 GDI,
+ so most language bindings will choose not to bind these
+ types.
+ </para>
+ <para>
+ The <link
+ linkend="cairo-font-face-set-user-data"><function>cairo_font_face_set_user_data()</function></link>,
+ and <link
+ linkend="cairo-font-face-get-user-data"><function>cairo_font_face_get_user_data()</function></link>
+ methods are provided for use in language bindings, and should
+ not be directly exposed to applications.
+ </para>
+ </sect1>
+ <sect1 id="bindings-path">
+ <title>cairo_path_t</title>
+ <para>
+ The <link linkend="cairo-path-t"><type>cairo_path_t</type></link> type is one
+ area in which most language bindings will differ significantly
+ from the C API. The C API for <type>cairo_path_t</type> is
+ designed for efficiency and to avoid auxiliary objects that
+ would be have to be manually memory managed by the
+ application. However,
+ a language binding should not present <type>cairo_path_t</type> as an
+ array, but rather as an opaque that can be iterated
+ over. Different languages have quite different conventions for
+ how iterators work, so it is impossible to give an exact
+ specification for how this API should work, but the type names
+ and methods should be similar to the language's mapping of the following:
+ </para>
+ <programlisting>
+typedef struct cairo_path_iterator cairo_path_iterator_t;
+typedef struct cairo_path_element cairo_path_element_t;
+
+cairo_path_iterator_t *
+cairo_path_get_iterator (cairo_path_t *path);
+
+cairo_bool_t
+cairo_path_iterator_has_next (cairo_path_iterator_t *iterator);
+
+cairo_path_element_t *
+cairo_path_iterator_next (cairo_path_iterator_t *iterator);
+
+cairo_path_element_type_t
+cairo_path_element_get_type (cairo_path_element_t *element);
+
+void
+cairo_path_element_get_point (cairo_path_element_t *element,
+ int index,
+ double *x,
+ double *y);
+ </programlisting>
+ <para>
+ The above is written using the Java conventions for
+ iterators. To illustrate how the API for PathIterator might
+ depend on the native iteration conventions of the API, examine
+ three versions of the loop, first written in a hypothetical Java
+ binding:
+ </para>
+ <programlisting>
+PathIterator iter = cr.copyPath().iterator();
+while (cr.hasNext()) {
+ PathElement element = iter.next();
+ if (element.getType() == PathElementType.MOVE_TO) {
+ Point p = element.getPoint(0);
+ doMoveTo (p.x, p.y);
+ }
+}</programlisting>
+ <para>
+ And then in a hypothetical C++ binding:
+ </para>
+ <programlisting>
+Path path = cr.copyPath();
+for (PathIterator iter = path.begin(); iter != path.end(); iter++) {
+ PathElement element = *iter;
+ if (element.getType() == PathElementType.MOVE_TO) {
+ Point p = element.getPoint(0);
+ doMoveTo (p.x, p.y);
+ }
+}</programlisting>
+ <para>
+ And then finally in a Python binding:
+ </para>
+<programlisting>
+for element in cr.copy_path():
+ if element.getType == cairo.PATH_ELEMENT_MOVE_TO:
+ (x, y) = element.getPoint(0)
+ doMoveTo (x, y);</programlisting>
+ <para>
+ While many of the API elements stay the same in the three
+ examples, the exact iteration mechanism is quite different, to
+ match how users of the language would expect to iterate over
+ a container.
+ </para>
+ <para>
+ You should not present an API for mutating or for creating new
+ <type>cairo_path_t</type> objects. In the future, these
+ guidelines may be extended to present an API for creating a
+ <type>cairo_path_t</type> from scratch for use with
+ <link
+ linkend="cairo-append-path"><function>cairo_append_path()</function></link>
+ but the current expectation is that <function>cairo_append_path()</function> will
+ mostly be used with paths from
+ <link
+ linkend="cairo-append-path"><function>cairo_copy_path()</function></link>.
+ </para>
+ </sect1>
+</appendix>
+<!--
+Local variables:
+mode: sgml
+sgml-parent-document: ("cairo-docs.xml" "book" "book" "appendix")
+End:
+-->
diff --git a/doc/public/tmpl/cairo-atsui.sgml b/doc/public/tmpl/cairo-atsui.sgml
index 0d957ecdf..a47ee8c68 100644
--- a/doc/public/tmpl/cairo-atsui.sgml
+++ b/doc/public/tmpl/cairo-atsui.sgml
@@ -14,6 +14,9 @@ ATSUI Fonts
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### FUNCTION cairo_atsui_font_create ##### -->
<para>
diff --git a/doc/public/tmpl/cairo-font.sgml b/doc/public/tmpl/cairo-font.sgml
new file mode 100644
index 000000000..66502930e
--- /dev/null
+++ b/doc/public/tmpl/cairo-font.sgml
@@ -0,0 +1,148 @@
+<!-- ##### SECTION Title ##### -->
+Fonts
+
+<!-- ##### SECTION Short_Description ##### -->
+Font Handling
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### TYPEDEF cairo_font_face_t ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### TYPEDEF cairo_scaled_font_t ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION cairo_font_face_reference ##### -->
+<para>
+
+</para>
+
+@font_face:
+
+
+<!-- ##### FUNCTION cairo_font_face_destroy ##### -->
+<para>
+
+</para>
+
+@font_face:
+
+
+<!-- ##### FUNCTION cairo_font_face_get_user_data ##### -->
+<para>
+
+</para>
+
+@font_face:
+@key:
+@Returns:
+
+
+<!-- ##### FUNCTION cairo_font_face_set_user_data ##### -->
+<para>
+
+</para>
+
+@font_face:
+@key:
+@user_data:
+@destroy:
+@Returns:
+
+
+<!-- ##### FUNCTION cairo_scaled_font_create ##### -->
+<para>
+
+</para>
+
+@font_face:
+@font_matrix:
+@ctm:
+@Returns:
+
+
+<!-- ##### FUNCTION cairo_scaled_font_reference ##### -->
+<para>
+
+</para>
+
+@scaled_font:
+<!-- # Unused Parameters # -->
+@font:
+
+
+<!-- ##### FUNCTION cairo_scaled_font_destroy ##### -->
+<para>
+
+</para>
+
+@scaled_font:
+<!-- # Unused Parameters # -->
+@font:
+
+
+<!-- ##### STRUCT cairo_font_extents_t ##### -->
+<para>
+
+</para>
+
+@ascent:
+@descent:
+@height:
+@max_x_advance:
+@max_y_advance:
+
+<!-- ##### FUNCTION cairo_scaled_font_extents ##### -->
+<para>
+
+</para>
+
+@scaled_font:
+@extents:
+@Returns:
+<!-- # Unused Parameters # -->
+@font:
+
+
+<!-- ##### STRUCT cairo_text_extents_t ##### -->
+<para>
+
+</para>
+
+@x_bearing:
+@y_bearing:
+@width:
+@height:
+@x_advance:
+@y_advance:
+
+<!-- ##### FUNCTION cairo_scaled_font_glyph_extents ##### -->
+<para>
+
+</para>
+
+@scaled_font:
+@glyphs:
+@num_glyphs:
+@extents:
+<!-- # Unused Parameters # -->
+@font:
+
+
diff --git a/doc/public/tmpl/cairo-ft.sgml b/doc/public/tmpl/cairo-ft.sgml
index bcf52ac34..d9f7cbfc1 100644
--- a/doc/public/tmpl/cairo-ft.sgml
+++ b/doc/public/tmpl/cairo-ft.sgml
@@ -14,50 +14,42 @@ FreeType Fonts
</para>
-<!-- ##### FUNCTION cairo_ft_font_create ##### -->
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### FUNCTION cairo_ft_font_face_create_for_pattern ##### -->
<para>
</para>
@pattern:
-@scale:
@Returns:
-<!-- ##### FUNCTION cairo_ft_font_create_for_ft_face ##### -->
+<!-- ##### FUNCTION cairo_ft_font_face_create_for_ft_face ##### -->
<para>
</para>
@face:
@load_flags:
-@scale:
@Returns:
-<!-- ##### FUNCTION cairo_ft_font_lock_face ##### -->
+<!-- ##### FUNCTION cairo_ft_scaled_font_lock_face ##### -->
<para>
</para>
-@ft_font:
+@scaled_font:
@Returns:
-<!-- ##### FUNCTION cairo_ft_font_unlock_face ##### -->
+<!-- ##### FUNCTION cairo_ft_scaled_font_unlock_face ##### -->
<para>
</para>
-@ft_font:
-
-
-<!-- ##### FUNCTION cairo_ft_font_get_pattern ##### -->
-<para>
-
-</para>
-
-@ft_font:
-@Returns:
+@scaled_font:
diff --git a/doc/public/tmpl/cairo-glitz.sgml b/doc/public/tmpl/cairo-glitz.sgml
index 101eb9e3e..9594d87a5 100644
--- a/doc/public/tmpl/cairo-glitz.sgml
+++ b/doc/public/tmpl/cairo-glitz.sgml
@@ -14,13 +14,7 @@ Glitz backend
</para>
-<!-- ##### FUNCTION cairo_set_target_glitz ##### -->
-<para>
-
-</para>
-
-@cr:
-@surface:
+<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### FUNCTION cairo_glitz_surface_create ##### -->
diff --git a/doc/public/tmpl/cairo-matrix.sgml b/doc/public/tmpl/cairo-matrix.sgml
index dc24c5754..c58abe488 100644
--- a/doc/public/tmpl/cairo-matrix.sgml
+++ b/doc/public/tmpl/cairo-matrix.sgml
@@ -38,77 +38,78 @@ cairo_matrix_t
</para>
-<!-- ##### TYPEDEF cairo_matrix_t ##### -->
-<para>
-
-</para>
+<!-- ##### SECTION Stability_Level ##### -->
-<!-- ##### FUNCTION cairo_matrix_create ##### -->
+<!-- ##### STRUCT cairo_matrix_t ##### -->
<para>
</para>
-@Returns:
-
+@xx:
+@yx:
+@xy:
+@yy:
+@x0:
+@y0:
-<!-- ##### FUNCTION cairo_matrix_destroy ##### -->
+<!-- ##### FUNCTION cairo_matrix_init ##### -->
<para>
</para>
@matrix:
+@xx:
+@yx:
+@xy:
+@yy:
+@x0:
+@y0:
+<!-- # Unused Parameters # -->
+@Param7:
+@a:
+@b:
+@c:
+@d:
+@tx:
+@ty:
-<!-- ##### FUNCTION cairo_matrix_copy ##### -->
+<!-- ##### FUNCTION cairo_matrix_init_identity ##### -->
<para>
</para>
@matrix:
-@other:
-@Returns:
-<!-- ##### FUNCTION cairo_matrix_set_identity ##### -->
+<!-- ##### FUNCTION cairo_matrix_init_translate ##### -->
<para>
</para>
@matrix:
-@Returns:
+@tx:
+@ty:
-<!-- ##### FUNCTION cairo_matrix_set_affine ##### -->
+<!-- ##### FUNCTION cairo_matrix_init_scale ##### -->
<para>
</para>
@matrix:
-@a:
-@b:
-@c:
-@d:
-@tx:
-@ty:
-@Returns:
-<!-- # Unused Parameters # -->
-@cr:
+@sx:
+@sy:
-<!-- ##### FUNCTION cairo_matrix_get_affine ##### -->
+<!-- ##### FUNCTION cairo_matrix_init_rotate ##### -->
<para>
</para>
@matrix:
-@a:
-@b:
-@c:
-@d:
-@tx:
-@ty:
-@Returns:
+@radians:
<!-- ##### FUNCTION cairo_matrix_translate ##### -->
@@ -119,6 +120,7 @@ cairo_matrix_t
@matrix:
@tx:
@ty:
+<!-- # Unused Parameters # -->
@Returns:
@@ -130,6 +132,7 @@ cairo_matrix_t
@matrix:
@sx:
@sy:
+<!-- # Unused Parameters # -->
@Returns:
@@ -140,6 +143,7 @@ cairo_matrix_t
@matrix:
@radians:
+<!-- # Unused Parameters # -->
@Returns:
@@ -160,6 +164,7 @@ cairo_matrix_t
@result:
@a:
@b:
+<!-- # Unused Parameters # -->
@Returns:
@@ -171,6 +176,7 @@ cairo_matrix_t
@matrix:
@dx:
@dy:
+<!-- # Unused Parameters # -->
@Returns:
@@ -181,6 +187,7 @@ cairo_matrix_t
@matrix:
@x:
@y:
+<!-- # Unused Parameters # -->
@Returns:
<!--
diff --git a/doc/public/tmpl/cairo-pattern.sgml b/doc/public/tmpl/cairo-pattern.sgml
index 84728212b..30deec9b8 100644
--- a/doc/public/tmpl/cairo-pattern.sgml
+++ b/doc/public/tmpl/cairo-pattern.sgml
@@ -14,6 +14,9 @@ cairo_pattern_t
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### TYPEDEF cairo_pattern_t ##### -->
<para>
@@ -71,7 +74,20 @@ cairo_pattern_t
@pattern:
-<!-- ##### FUNCTION cairo_pattern_add_color_stop ##### -->
+<!-- ##### FUNCTION cairo_pattern_add_color_stop_rgb ##### -->
+<para>
+
+</para>
+
+@pattern:
+@offset:
+@red:
+@green:
+@blue:
+@Returns:
+
+
+<!-- ##### FUNCTION cairo_pattern_add_color_stop_rgba ##### -->
<para>
</para>
diff --git a/doc/public/tmpl/cairo-pdf.sgml b/doc/public/tmpl/cairo-pdf.sgml
index e627c236e..8ff0ea17e 100644
--- a/doc/public/tmpl/cairo-pdf.sgml
+++ b/doc/public/tmpl/cairo-pdf.sgml
@@ -14,25 +14,35 @@ PDF Backend
</para>
-<!-- ##### FUNCTION cairo_set_target_pdf ##### -->
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### FUNCTION cairo_pdf_surface_create ##### -->
<para>
</para>
-@cr:
-@file:
+@fp:
@width_inches:
@height_inches:
@x_pixels_per_inch:
@y_pixels_per_inch:
+@Returns:
+<!-- # Unused Parameters # -->
+@write_func:
+@destroy_closure_func:
+@closure:
+@file:
-<!-- ##### FUNCTION cairo_pdf_surface_create ##### -->
+<!-- ##### FUNCTION cairo_pdf_surface_create_for_callback ##### -->
<para>
</para>
-@file:
+@write_func:
+@destroy_closure_func:
+@closure:
@width_inches:
@height_inches:
@x_pixels_per_inch:
diff --git a/doc/public/tmpl/cairo-png.sgml b/doc/public/tmpl/cairo-png.sgml
index d4d5a66b5..dd4486c71 100644
--- a/doc/public/tmpl/cairo-png.sgml
+++ b/doc/public/tmpl/cairo-png.sgml
@@ -14,27 +14,46 @@ PNG Backend
</para>
-<!-- ##### FUNCTION cairo_set_target_png ##### -->
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### FUNCTION cairo_image_surface_create_from_png ##### -->
+<para>
+
+</para>
+
+@filename:
+@Returns:
+
+
+<!-- ##### FUNCTION cairo_image_surface_create_from_png_stream ##### -->
<para>
</para>
-@cr:
-@file:
-@format:
-@width:
-@height:
+@read_func:
+@closure:
+@Returns:
+
+
+<!-- ##### FUNCTION cairo_surface_write_to_png ##### -->
+<para>
+
+</para>
+
+@surface:
+@filename:
+@Returns:
-<!-- ##### FUNCTION cairo_png_surface_create ##### -->
+<!-- ##### FUNCTION cairo_surface_write_to_png_stream ##### -->
<para>
</para>
-@file:
-@format:
-@width:
-@height:
+@surface:
+@write_func:
+@closure:
@Returns:
diff --git a/doc/public/tmpl/cairo-ps.sgml b/doc/public/tmpl/cairo-ps.sgml
index 70b2e7e8f..4cb4a0268 100644
--- a/doc/public/tmpl/cairo-ps.sgml
+++ b/doc/public/tmpl/cairo-ps.sgml
@@ -14,17 +14,7 @@ PS Backend
</para>
-<!-- ##### FUNCTION cairo_set_target_ps ##### -->
-<para>
-
-</para>
-
-@cr:
-@file:
-@width_inches:
-@height_inches:
-@x_pixels_per_inch:
-@y_pixels_per_inch:
+<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### FUNCTION cairo_ps_surface_create ##### -->
diff --git a/doc/public/tmpl/cairo-quartz.sgml b/doc/public/tmpl/cairo-quartz.sgml
index 04c9bc61f..c83de6c77 100644
--- a/doc/public/tmpl/cairo-quartz.sgml
+++ b/doc/public/tmpl/cairo-quartz.sgml
@@ -14,15 +14,7 @@ Quartz Backend
</para>
-<!-- ##### FUNCTION cairo_set_target_quartz_context ##### -->
-<para>
-
-</para>
-
-@cr:
-@context:
-@width:
-@height:
+<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### FUNCTION cairo_quartz_surface_create ##### -->
diff --git a/doc/public/tmpl/cairo-surface.sgml b/doc/public/tmpl/cairo-surface.sgml
index 2f8ad470c..e92935a6c 100644
--- a/doc/public/tmpl/cairo-surface.sgml
+++ b/doc/public/tmpl/cairo-surface.sgml
@@ -14,23 +14,27 @@ cairo_surface_t
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### TYPEDEF cairo_surface_t ##### -->
<para>
</para>
-<!-- ##### FUNCTION cairo_surface_create_for_image ##### -->
+<!-- ##### MACRO cairo_surface_create_for_image ##### -->
<para>
</para>
+@Returns:
+<!-- # Unused Parameters # -->
@data:
@format:
@width:
@height:
@stride:
-@Returns:
<!-- ##### FUNCTION cairo_surface_create_similar ##### -->
@@ -61,52 +65,100 @@ cairo_surface_t
@surface:
-<!-- ##### FUNCTION cairo_surface_set_repeat ##### -->
+<!-- ##### FUNCTION cairo_surface_finish ##### -->
<para>
</para>
@surface:
-@repeat:
@Returns:
-<!-- ##### FUNCTION cairo_surface_set_matrix ##### -->
+<!-- ##### MACRO cairo_surface_set_repeat ##### -->
<para>
</para>
-@surface:
-@matrix:
@Returns:
+<!-- # Unused Parameters # -->
+@surface:
+@repeat:
-<!-- ##### FUNCTION cairo_surface_get_matrix ##### -->
+<!-- ##### MACRO cairo_surface_set_matrix ##### -->
<para>
</para>
+@Returns:
+<!-- # Unused Parameters # -->
@surface:
@matrix:
+
+
+<!-- ##### MACRO cairo_surface_get_matrix ##### -->
+<para>
+
+</para>
+
@Returns:
+<!-- # Unused Parameters # -->
+@surface:
+@matrix:
-<!-- ##### FUNCTION cairo_surface_set_filter ##### -->
+<!-- ##### MACRO cairo_surface_set_filter ##### -->
<para>
</para>
+@Returns:
+<!-- # Unused Parameters # -->
@surface:
@filter:
+
+
+<!-- ##### MACRO cairo_surface_get_filter ##### -->
+<para>
+
+</para>
+
@Returns:
+<!-- # Unused Parameters # -->
+@surface:
-<!-- ##### FUNCTION cairo_surface_get_filter ##### -->
+<!-- ##### FUNCTION cairo_surface_set_user_data ##### -->
<para>
</para>
@surface:
+@key:
+@user_data:
+@destroy:
@Returns:
+<!-- # Unused Parameters # -->
+@data:
+
+
+<!-- ##### FUNCTION cairo_surface_get_user_data ##### -->
+<para>
+
+</para>
+
+@surface:
+@key:
+@Returns:
+
+
+<!-- ##### FUNCTION cairo_surface_set_device_offset ##### -->
+<para>
+
+</para>
+
+@surface:
+@x_offset:
+@y_offset:
diff --git a/doc/public/tmpl/cairo-xcb.sgml b/doc/public/tmpl/cairo-xcb.sgml
index e5e1ee912..416d71638 100644
--- a/doc/public/tmpl/cairo-xcb.sgml
+++ b/doc/public/tmpl/cairo-xcb.sgml
@@ -14,15 +14,18 @@ XCB Backend
</para>
-<!-- ##### FUNCTION cairo_set_target_xcb ##### -->
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### FUNCTION cairo_xcb_surface_create ##### -->
<para>
</para>
-@cr:
@dpy:
@drawable:
@visual:
@format:
+@Returns:
diff --git a/doc/public/tmpl/cairo-xlib.sgml b/doc/public/tmpl/cairo-xlib.sgml
index b18e76aae..30282b226 100644
--- a/doc/public/tmpl/cairo-xlib.sgml
+++ b/doc/public/tmpl/cairo-xlib.sgml
@@ -14,17 +14,24 @@ XLib Backend
</para>
-<!-- ##### FUNCTION cairo_set_target_drawable ##### -->
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### FUNCTION cairo_xlib_surface_create ##### -->
<para>
</para>
-@cr:
@dpy:
@drawable:
+@format:
+@Returns:
+<!-- # Unused Parameters # -->
+@visual:
+@colormap:
-<!-- ##### FUNCTION cairo_xlib_surface_create ##### -->
+<!-- ##### FUNCTION cairo_xlib_surface_create_with_visual ##### -->
<para>
</para>
@@ -32,8 +39,16 @@ XLib Backend
@dpy:
@drawable:
@visual:
-@format:
-@colormap:
@Returns:
+<!-- ##### FUNCTION cairo_xlib_surface_set_size ##### -->
+<para>
+
+</para>
+
+@surface:
+@width:
+@height:
+
+
diff --git a/doc/public/tmpl/cairo.sgml b/doc/public/tmpl/cairo.sgml
index a9e195c73..06a5fba6d 100644
--- a/doc/public/tmpl/cairo.sgml
+++ b/doc/public/tmpl/cairo.sgml
@@ -24,6 +24,9 @@ Drawing contexts.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### TYPEDEF cairo_t ##### -->
<para>
@@ -35,6 +38,7 @@ Drawing contexts.
</para>
+@target:
@Returns:
@@ -70,24 +74,16 @@ Drawing contexts.
@cr:
-<!-- ##### FUNCTION cairo_copy ##### -->
+<!-- ##### MACRO cairo_copy ##### -->
<para>
</para>
+<!-- # Unused Parameters # -->
@dest:
@src:
-<!-- ##### FUNCTION cairo_set_target_surface ##### -->
-<para>
-
-</para>
-
-@cr:
-@surface:
-
-
<!-- ##### ENUM cairo_format_t ##### -->
<para>
@@ -98,35 +94,22 @@ Drawing contexts.
@CAIRO_FORMAT_A8:
@CAIRO_FORMAT_A1:
-<!-- ##### FUNCTION cairo_set_target_image ##### -->
-<para>
-
-</para>
-
-@cr:
-@data:
-@format:
-@width:
-@height:
-@stride:
-
-
<!-- ##### ENUM cairo_operator_t ##### -->
<para>
</para>
@CAIRO_OPERATOR_CLEAR:
-@CAIRO_OPERATOR_SRC:
-@CAIRO_OPERATOR_DST:
+@CAIRO_OPERATOR_SOURCE:
@CAIRO_OPERATOR_OVER:
-@CAIRO_OPERATOR_OVER_REVERSE:
@CAIRO_OPERATOR_IN:
-@CAIRO_OPERATOR_IN_REVERSE:
@CAIRO_OPERATOR_OUT:
-@CAIRO_OPERATOR_OUT_REVERSE:
@CAIRO_OPERATOR_ATOP:
-@CAIRO_OPERATOR_ATOP_REVERSE:
+@CAIRO_OPERATOR_DEST:
+@CAIRO_OPERATOR_DEST_OVER:
+@CAIRO_OPERATOR_DEST_IN:
+@CAIRO_OPERATOR_DEST_OUT:
+@CAIRO_OPERATOR_DEST_ATOP:
@CAIRO_OPERATOR_XOR:
@CAIRO_OPERATOR_ADD:
@CAIRO_OPERATOR_SATURATE:
@@ -140,7 +123,18 @@ Drawing contexts.
@op:
-<!-- ##### FUNCTION cairo_set_rgb_color ##### -->
+<!-- ##### FUNCTION cairo_set_source_rgb ##### -->
+<para>
+
+</para>
+
+@cr:
+@red:
+@green:
+@blue:
+
+
+<!-- ##### FUNCTION cairo_set_source_rgba ##### -->
<para>
</para>
@@ -149,22 +143,37 @@ Drawing contexts.
@red:
@green:
@blue:
+@alpha:
-<!-- ##### FUNCTION cairo_set_pattern ##### -->
+<!-- ##### FUNCTION cairo_set_source ##### -->
<para>
</para>
@cr:
+@source:
+<!-- # Unused Parameters # -->
@pattern:
-<!-- ##### FUNCTION cairo_set_alpha ##### -->
+<!-- ##### FUNCTION cairo_set_source_surface ##### -->
+<para>
+
+</para>
+
+@cr:
+@surface:
+@x:
+@y:
+
+
+<!-- ##### MACRO cairo_set_alpha ##### -->
<para>
</para>
+<!-- # Unused Parameters # -->
@cr:
@alpha:
@@ -289,7 +298,7 @@ Drawing contexts.
@angle:
-<!-- ##### FUNCTION cairo_concat_matrix ##### -->
+<!-- ##### FUNCTION cairo_transform ##### -->
<para>
</para>
@@ -307,11 +316,12 @@ Drawing contexts.
@matrix:
-<!-- ##### FUNCTION cairo_default_matrix ##### -->
+<!-- ##### MACRO cairo_default_matrix ##### -->
<para>
</para>
+<!-- # Unused Parameters # -->
@cr:
@@ -323,7 +333,7 @@ Drawing contexts.
@cr:
-<!-- ##### FUNCTION cairo_transform_point ##### -->
+<!-- ##### FUNCTION cairo_user_to_device ##### -->
<para>
</para>
@@ -333,7 +343,7 @@ Drawing contexts.
@y:
-<!-- ##### FUNCTION cairo_transform_distance ##### -->
+<!-- ##### FUNCTION cairo_user_to_device_distance ##### -->
<para>
</para>
@@ -343,7 +353,7 @@ Drawing contexts.
@dy:
-<!-- ##### FUNCTION cairo_inverse_transform_point ##### -->
+<!-- ##### FUNCTION cairo_device_to_user ##### -->
<para>
</para>
@@ -353,7 +363,7 @@ Drawing contexts.
@y:
-<!-- ##### FUNCTION cairo_inverse_transform_distance ##### -->
+<!-- ##### FUNCTION cairo_device_to_user_distance ##### -->
<para>
</para>
@@ -485,6 +495,43 @@ Drawing contexts.
@cr:
+<!-- ##### FUNCTION cairo_paint ##### -->
+<para>
+
+</para>
+
+@cr:
+
+
+<!-- ##### FUNCTION cairo_paint_with_alpha ##### -->
+<para>
+
+</para>
+
+@cr:
+@alpha:
+
+
+<!-- ##### FUNCTION cairo_mask ##### -->
+<para>
+
+</para>
+
+@cr:
+@pattern:
+
+
+<!-- ##### FUNCTION cairo_mask_surface ##### -->
+<para>
+
+</para>
+
+@cr:
+@surface:
+@surface_x:
+@surface_y:
+
+
<!-- ##### FUNCTION cairo_stroke ##### -->
<para>
@@ -493,6 +540,14 @@ Drawing contexts.
@cr:
+<!-- ##### FUNCTION cairo_stroke_preserve ##### -->
+<para>
+
+</para>
+
+@cr:
+
+
<!-- ##### FUNCTION cairo_fill ##### -->
<para>
@@ -501,6 +556,14 @@ Drawing contexts.
@cr:
+<!-- ##### FUNCTION cairo_fill_preserve ##### -->
+<para>
+
+</para>
+
+@cr:
+
+
<!-- ##### FUNCTION cairo_copy_page ##### -->
<para>
@@ -569,7 +632,7 @@ Drawing contexts.
@y2:
-<!-- ##### FUNCTION cairo_init_clip ##### -->
+<!-- ##### FUNCTION cairo_clip ##### -->
<para>
</para>
@@ -577,7 +640,7 @@ Drawing contexts.
@cr:
-<!-- ##### FUNCTION cairo_clip ##### -->
+<!-- ##### FUNCTION cairo_clip_preserve ##### -->
<para>
</para>
@@ -585,11 +648,13 @@ Drawing contexts.
@cr:
-<!-- ##### TYPEDEF cairo_font_t ##### -->
+<!-- ##### FUNCTION cairo_reset_clip ##### -->
<para>
</para>
+@cr:
+
<!-- ##### STRUCT cairo_glyph_t ##### -->
<para>
@@ -600,29 +665,6 @@ Drawing contexts.
@x:
@y:
-<!-- ##### STRUCT cairo_text_extents_t ##### -->
-<para>
-
-</para>
-
-@x_bearing:
-@y_bearing:
-@width:
-@height:
-@x_advance:
-@y_advance:
-
-<!-- ##### STRUCT cairo_font_extents_t ##### -->
-<para>
-
-</para>
-
-@ascent:
-@descent:
-@height:
-@max_x_advance:
-@max_y_advance:
-
<!-- ##### ENUM cairo_font_slant_t ##### -->
<para>
@@ -640,7 +682,7 @@ Drawing contexts.
@CAIRO_FONT_WEIGHT_NORMAL:
@CAIRO_FONT_WEIGHT_BOLD:
-<!-- ##### FUNCTION cairo_select_font ##### -->
+<!-- ##### FUNCTION cairo_select_font_face ##### -->
<para>
</para>
@@ -651,16 +693,16 @@ Drawing contexts.
@weight:
-<!-- ##### FUNCTION cairo_scale_font ##### -->
+<!-- ##### FUNCTION cairo_set_font_size ##### -->
<para>
</para>
@cr:
-@scale:
+@size:
-<!-- ##### FUNCTION cairo_transform_font ##### -->
+<!-- ##### FUNCTION cairo_set_font_matrix ##### -->
<para>
</para>
@@ -669,6 +711,16 @@ Drawing contexts.
@matrix:
+<!-- ##### FUNCTION cairo_get_font_matrix ##### -->
+<para>
+
+</para>
+
+@cr:
+@matrix:
+@Returns:
+
+
<!-- ##### FUNCTION cairo_show_text ##### -->
<para>
@@ -688,7 +740,7 @@ Drawing contexts.
@num_glyphs:
-<!-- ##### FUNCTION cairo_current_font ##### -->
+<!-- ##### FUNCTION cairo_get_font_face ##### -->
<para>
</para>
@@ -697,22 +749,26 @@ Drawing contexts.
@Returns:
-<!-- ##### FUNCTION cairo_current_font_extents ##### -->
+<!-- ##### FUNCTION cairo_font_extents ##### -->
<para>
</para>
@cr:
@extents:
+<!-- # Unused Parameters # -->
+@font:
+@Returns:
+@font_matrix:
-<!-- ##### FUNCTION cairo_set_font ##### -->
+<!-- ##### FUNCTION cairo_set_font_face ##### -->
<para>
</para>
@cr:
-@font:
+@font_face:
<!-- ##### FUNCTION cairo_text_extents ##### -->
@@ -755,66 +811,65 @@ Drawing contexts.
@num_glyphs:
-<!-- ##### FUNCTION cairo_font_reference ##### -->
+<!-- ##### MACRO cairo_show_surface ##### -->
<para>
</para>
-@font:
+<!-- # Unused Parameters # -->
+@cr:
+@surface:
+@width:
+@height:
-<!-- ##### FUNCTION cairo_font_destroy ##### -->
+<!-- ##### FUNCTION cairo_get_operator ##### -->
<para>
</para>
-@font:
+@cr:
+@Returns:
-<!-- ##### FUNCTION cairo_font_glyph_extents ##### -->
+<!-- ##### FUNCTION cairo_get_source ##### -->
<para>
</para>
-@font:
-@font_matrix:
-@glyphs:
-@num_glyphs:
-@extents:
+@cr:
+@Returns:
-<!-- ##### FUNCTION cairo_show_surface ##### -->
+<!-- ##### FUNCTION cairo_get_tolerance ##### -->
<para>
</para>
@cr:
-@surface:
-@width:
-@height:
+@Returns:
-<!-- ##### FUNCTION cairo_current_operator ##### -->
+<!-- ##### FUNCTION cairo_get_current_point ##### -->
<para>
</para>
@cr:
-@Returns:
+@x:
+@y:
-<!-- ##### FUNCTION cairo_current_rgb_color ##### -->
+<!-- ##### FUNCTION cairo_get_fill_rule ##### -->
<para>
</para>
@cr:
-@red:
-@green:
-@blue:
+@Returns:
-<!-- ##### FUNCTION cairo_current_pattern ##### -->
+<!-- ##### FUNCTION cairo_get_line_width ##### -->
<para>
</para>
@@ -823,7 +878,7 @@ Drawing contexts.
@Returns:
-<!-- ##### FUNCTION cairo_current_alpha ##### -->
+<!-- ##### FUNCTION cairo_get_line_cap ##### -->
<para>
</para>
@@ -832,7 +887,7 @@ Drawing contexts.
@Returns:
-<!-- ##### FUNCTION cairo_current_tolerance ##### -->
+<!-- ##### FUNCTION cairo_get_line_join ##### -->
<para>
</para>
@@ -841,26 +896,27 @@ Drawing contexts.
@Returns:
-<!-- ##### FUNCTION cairo_current_point ##### -->
+<!-- ##### FUNCTION cairo_get_miter_limit ##### -->
<para>
</para>
@cr:
-@x:
-@y:
+@Returns:
-<!-- ##### FUNCTION cairo_current_fill_rule ##### -->
+<!-- ##### FUNCTION cairo_get_matrix ##### -->
<para>
</para>
@cr:
+@matrix:
+<!-- # Unused Parameters # -->
@Returns:
-<!-- ##### FUNCTION cairo_current_line_width ##### -->
+<!-- ##### FUNCTION cairo_get_target ##### -->
<para>
</para>
@@ -869,25 +925,34 @@ Drawing contexts.
@Returns:
-<!-- ##### FUNCTION cairo_current_line_cap ##### -->
+<!-- ##### MACRO cairo_get_path ##### -->
<para>
</para>
+<!-- # Unused Parameters # -->
@cr:
-@Returns:
+@move_to:
+@line_to:
+@curve_to:
+@close_path:
+@closure:
-<!-- ##### FUNCTION cairo_current_line_join ##### -->
+<!-- ##### MACRO cairo_get_path_flat ##### -->
<para>
</para>
+<!-- # Unused Parameters # -->
@cr:
-@Returns:
+@move_to:
+@line_to:
+@close_path:
+@closure:
-<!-- ##### FUNCTION cairo_current_miter_limit ##### -->
+<!-- ##### FUNCTION cairo_copy_path ##### -->
<para>
</para>
@@ -896,47 +961,38 @@ Drawing contexts.
@Returns:
-<!-- ##### FUNCTION cairo_current_matrix ##### -->
+<!-- ##### FUNCTION cairo_copy_path_flat ##### -->
<para>
</para>
@cr:
-@matrix:
+@Returns:
-<!-- ##### FUNCTION cairo_current_target_surface ##### -->
+<!-- ##### FUNCTION cairo_append_path ##### -->
<para>
</para>
@cr:
-@Returns:
+@path:
-<!-- ##### FUNCTION cairo_current_path ##### -->
+<!-- ##### STRUCT cairo_path_t ##### -->
<para>
</para>
-@cr:
-@move_to:
-@line_to:
-@curve_to:
-@close_path:
-@closure:
-
+@data:
+@num_data:
-<!-- ##### FUNCTION cairo_current_path_flat ##### -->
+<!-- ##### FUNCTION cairo_path_destroy ##### -->
<para>
</para>
-@cr:
-@move_to:
-@line_to:
-@close_path:
-@closure:
+@path:
<!-- ##### ENUM cairo_status_t ##### -->
@@ -953,6 +1009,12 @@ Drawing contexts.
@CAIRO_STATUS_NO_TARGET_SURFACE:
@CAIRO_STATUS_NULL_POINTER:
@CAIRO_STATUS_INVALID_STRING:
+@CAIRO_STATUS_INVALID_PATH_DATA:
+@CAIRO_STATUS_READ_ERROR:
+@CAIRO_STATUS_WRITE_ERROR:
+@CAIRO_STATUS_SURFACE_FINISHED:
+@CAIRO_STATUS_SURFACE_TYPE_MISMATCH:
+@CAIRO_STATUS_BAD_NESTING:
<!-- ##### FUNCTION cairo_status ##### -->
<para>
@@ -1017,3 +1079,58 @@ End:
-->
+<!-- ##### FUNCTION cairo_image_surface_get_width ##### -->
+<para>
+
+</para>
+
+@surface:
+@Returns:
+
+
+<!-- ##### FUNCTION cairo_image_surface_get_height ##### -->
+<para>
+
+</para>
+
+@surface:
+@Returns:
+
+
+<!-- ##### USER_FUNCTION cairo_destroy_func_t ##### -->
+<para>
+
+</para>
+
+@data:
+
+
+<!-- ##### STRUCT cairo_user_data_key_t ##### -->
+<para>
+
+</para>
+
+@unused:
+
+<!-- ##### USER_FUNCTION cairo_read_func_t ##### -->
+<para>
+
+</para>
+
+@closure:
+@data:
+@length:
+@Returns:
+
+
+<!-- ##### USER_FUNCTION cairo_write_func_t ##### -->
+<para>
+
+</para>
+
+@closure:
+@data:
+@length:
+@Returns:
+
+
diff --git a/src/Makefile.am b/src/Makefile.am
index 3f76d2726..8c624f247 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,56 +1,55 @@
if CAIRO_HAS_PS_SURFACE
libcairo_ps_headers = cairo-ps.h
-libcairo_ps_sources = cairo_ps_surface.c
+libcairo_ps_sources = cairo-ps-surface.c
endif
if CAIRO_HAS_PDF_SURFACE
libcairo_pdf_headers = cairo-pdf.h
-libcairo_pdf_sources = cairo_pdf_surface.c
+libcairo_pdf_sources = cairo-pdf-surface.c
endif
-if CAIRO_HAS_PNG_SURFACE
-libcairo_png_headers = cairo-png.h
-libcairo_png_sources = cairo_png_surface.c
+if CAIRO_HAS_PNG_FUNCTIONS
+libcairo_png_sources = cairo-png.c
endif
if CAIRO_HAS_XLIB_SURFACE
-libcairo_xlib_headers = cairo-xlib.h
-libcairo_xlib_sources = cairo_xlib_surface.c
+libcairo_xlib_headers = cairo-xlib.h cairo-xlib-xrender.h
+libcairo_xlib_sources = cairo-xlib-surface.c cairo-xlib-test.h
endif
if CAIRO_HAS_QUARTZ_SURFACE
libcairo_quartz_headers = cairo-quartz.h
-libcairo_quartz_sources = cairo_quartz_surface.c
+libcairo_quartz_sources = cairo-quartz-surface.c
endif
if CAIRO_HAS_XCB_SURFACE
-libcairo_xcb_headers = cairo-xcb.h
-libcairo_xcb_sources = cairo_xcb_surface.c
+libcairo_xcb_headers = cairo-xcb.h cairo-xcb-xrender.h
+libcairo_xcb_sources = cairo-xcb-surface.c
endif
libcairo_win32_sources =
if CAIRO_HAS_WIN32_SURFACE
libcairo_win32_headers = cairo-win32.h
-libcairo_win32_sources += cairo_win32_surface.c cairo-win32-private.h
+libcairo_win32_sources += cairo-win32-surface.c cairo-win32-private.h
endif
if CAIRO_HAS_WIN32_FONT
-libcairo_win32_sources += cairo_win32_font.c
+libcairo_win32_sources += cairo-win32-font.c
endif
if CAIRO_HAS_GLITZ_SURFACE
libcairo_glitz_headers = cairo-glitz.h
-libcairo_glitz_sources = cairo_glitz_surface.c
+libcairo_glitz_sources = cairo-glitz-surface.c
endif
if CAIRO_HAS_ATSUI_FONT
libcairo_atsui_headers = cairo-atsui.h
-libcairo_atsui_sources = cairo_atsui_font.c
+libcairo_atsui_sources = cairo-atsui-font.c
endif
if CAIRO_HAS_FT_FONT
libcairo_ft_headers = cairo-ft.h
-libcairo_ft_sources = cairo_ft_font.c cairo-ft-private.h
+libcairo_ft_sources = cairo-ft-font.c cairo-ft-private.h
endif
# These names match automake style variable definition conventions so
@@ -68,7 +67,6 @@ cairoinclude_HEADERS = \
$(libcairo_ft_headers) \
$(libcairo_glitz_headers) \
$(libcairo_pdf_headers) \
- $(libcairo_png_headers) \
$(libcairo_ps_headers) \
$(libcairo_quartz_headers) \
$(libcairo_win32_headers) \
@@ -80,28 +78,36 @@ lib_LTLIBRARIES = libcairo.la
libcairo_la_SOURCES = \
cairo.c \
cairo.h \
- cairo_array.c \
- cairo_cache.c \
- cairo_color.c \
- cairo_fixed.c \
- cairo_font.c \
- cairo_gstate.c \
- cairo_hull.c \
- cairo_image_surface.c \
- cairo_matrix.c \
- cairo_path.c \
- cairo_path_bounds.c \
- cairo_path_fill.c \
- cairo_path_stroke.c \
- cairo_pen.c \
- cairo_polygon.c \
- cairo_slope.c \
- cairo_spline.c \
- cairo_surface.c \
- cairo_traps.c \
- cairo_pattern.c \
- cairo_unicode.c \
- cairo_wideint.c \
+ cairo-private.h \
+ cairo-arc.c \
+ cairo-arc-private.h \
+ cairo-array.c \
+ cairo-cache.c \
+ cairo-color.c \
+ cairo-fixed.c \
+ cairo-font.c \
+ cairo-gstate.c \
+ cairo-gstate-private.h \
+ cairo-hull.c \
+ cairo-image-surface.c \
+ cairo-matrix.c \
+ cairo-path.c \
+ cairo-path-bounds.c \
+ cairo-path-data.c \
+ cairo-path-data-private.h \
+ cairo-path-fill.c \
+ cairo-path-fixed-private.h \
+ cairo-path-stroke.c \
+ cairo-pen.c \
+ cairo-polygon.c \
+ cairo-slope.c \
+ cairo-spline.c \
+ cairo-surface.c \
+ cairo-traps.c \
+ cairo-pattern.c \
+ cairo-unicode.c \
+ cairo-output-stream.c \
+ cairo-wideint.c \
cairo-wideint.h \
$(libcairo_atsui_sources)\
$(libcairo_ft_sources)\
@@ -113,7 +119,6 @@ libcairo_la_SOURCES = \
$(libcairo_xcb_sources) \
$(libcairo_glitz_sources)\
$(libcairo_win32_sources)\
- $(libcairo_freetype_sources) \
cairoint.h
libcairo_la_LDFLAGS = -version-info @VERSION_INFO@ -no-undefined
@@ -123,7 +128,7 @@ INCLUDES = -I$(srcdir) $(CAIRO_CFLAGS)
libcairo_la_LIBADD = $(CAIRO_LIBS)
install-data-local:
- @if test -f $(includedir)/cairo.h || test -f $(includedir)/cairo-features.h ; then \
+ @if test -f "$(DESTDIR)$(includedir)/cairo.h" || test -f "$(DESTDIR)$(includedir)/cairo-features.h" ; then \
echo "****************************************************************" ; \
echo "*** Error: Old headers found. You should remove the following" ; \
echo "*** files and then type 'make install' again." ; \
diff --git a/src/cairo-arc-private.h b/src/cairo-arc-private.h
new file mode 100644
index 000000000..1cd41cc15
--- /dev/null
+++ b/src/cairo-arc-private.h
@@ -0,0 +1,57 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ * Carl D. Worth <cworth@redhat.com>
+ */
+
+#ifndef CAIRO_ARC_PRIVATE_H
+#define CAIRO_ARC_PRIVATE_H
+
+#include "cairoint.h"
+
+void
+_cairo_arc_path (cairo_t *cr,
+ double xc,
+ double yc,
+ double radius,
+ double angle1,
+ double angle2);
+
+void
+_cairo_arc_path_negative (cairo_t *cr,
+ double xc,
+ double yc,
+ double radius,
+ double angle1,
+ double angle2);
+
+#endif /* CAIRO_ARC_PRIVATE_H */
diff --git a/src/cairo-arc.c b/src/cairo-arc.c
new file mode 100644
index 000000000..d3302cdd5
--- /dev/null
+++ b/src/cairo-arc.c
@@ -0,0 +1,296 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2002 University of Southern California
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ * Carl D. Worth <cworth@cworth.org>
+ */
+
+#include <math.h>
+
+#include "cairo-arc-private.h"
+
+/* Spline deviation from the circle in radius would be given by:
+
+ error = sqrt (x**2 + y**2) - 1
+
+ A simpler error function to work with is:
+
+ e = x**2 + y**2 - 1
+
+ From "Good approximation of circles by curvature-continuous Bezier
+ curves", Tor Dokken and Morten Daehlen, Computer Aided Geometric
+ Design 8 (1990) 22-41, we learn:
+
+ abs (max(e)) = 4/27 * sin**6(angle/4) / cos**2(angle/4)
+
+ and
+ abs (error) =~ 1/2 * e
+
+ Of course, this error value applies only for the particular spline
+ approximation that is used in _cairo_gstate_arc_segment.
+*/
+static double
+_arc_error_normalized (double angle)
+{
+ return 2.0/27.0 * pow (sin (angle / 4), 6) / pow (cos (angle / 4), 2);
+}
+
+static double
+_arc_max_angle_for_tolerance_normalized (double tolerance)
+{
+ double angle, error;
+ int i;
+
+ /* Use table lookup to reduce search time in most cases. */
+ struct {
+ double angle;
+ double error;
+ } table[] = {
+ { M_PI / 1.0, 0.0185185185185185036127 },
+ { M_PI / 2.0, 0.000272567143730179811158 },
+ { M_PI / 3.0, 2.38647043651461047433e-05 },
+ { M_PI / 4.0, 4.2455377443222443279e-06 },
+ { M_PI / 5.0, 1.11281001494389081528e-06 },
+ { M_PI / 6.0, 3.72662000942734705475e-07 },
+ { M_PI / 7.0, 1.47783685574284411325e-07 },
+ { M_PI / 8.0, 6.63240432022601149057e-08 },
+ { M_PI / 9.0, 3.2715520137536980553e-08 },
+ { M_PI / 10.0, 1.73863223499021216974e-08 },
+ { M_PI / 11.0, 9.81410988043554039085e-09 },
+ };
+ int table_size = (sizeof (table) / sizeof (table[0]));
+
+ for (i = 0; i < table_size; i++)
+ if (table[i].error < tolerance)
+ return table[i].angle;
+
+ ++i;
+ do {
+ angle = M_PI / i++;
+ error = _arc_error_normalized (angle);
+ } while (error > tolerance);
+
+ return angle;
+}
+
+static int
+_arc_segments_needed (double angle,
+ double radius,
+ cairo_matrix_t *ctm,
+ double tolerance)
+{
+ double l1, l2, lmax;
+ double max_angle;
+
+ _cairo_matrix_compute_eigen_values (ctm, &l1, &l2);
+
+ l1 = fabs (l1);
+ l2 = fabs (l2);
+ if (l1 > l2)
+ lmax = l1;
+ else
+ lmax = l2;
+
+ max_angle = _arc_max_angle_for_tolerance_normalized (tolerance / (radius * lmax));
+
+ return (int) ceil (angle / max_angle);
+}
+
+/* We want to draw a single spline approximating a circular arc radius
+ R from angle A to angle B. Since we want a symmetric spline that
+ matches the endpoints of the arc in position and slope, we know
+ that the spline control points must be:
+
+ (R * cos(A), R * sin(A))
+ (R * cos(A) - h * sin(A), R * sin(A) + h * cos (A))
+ (R * cos(B) + h * sin(B), R * sin(B) - h * cos (B))
+ (R * cos(B), R * sin(B))
+
+ for some value of h.
+
+ "Approximation of circular arcs by cubic poynomials", Michael
+ Goldapp, Computer Aided Geometric Design 8 (1991) 227-238, provides
+ various values of h along with error analysis for each.
+
+ From that paper, a very practical value of h is:
+
+ h = 4/3 * tan(angle/4)
+
+ This value does not give the spline with minimal error, but it does
+ provide a very good approximation, (6th-order convergence), and the
+ error expression is quite simple, (see the comment for
+ _arc_error_normalized).
+*/
+static void
+_cairo_arc_segment (cairo_t *cr,
+ double xc,
+ double yc,
+ double radius,
+ double angle_A,
+ double angle_B)
+{
+ double r_sin_A, r_cos_A;
+ double r_sin_B, r_cos_B;
+ double h;
+
+ r_sin_A = radius * sin (angle_A);
+ r_cos_A = radius * cos (angle_A);
+ r_sin_B = radius * sin (angle_B);
+ r_cos_B = radius * cos (angle_B);
+
+ h = 4.0/3.0 * tan ((angle_B - angle_A) / 4.0);
+
+ cairo_curve_to (cr,
+ xc + r_cos_A - h * r_sin_A,
+ yc + r_sin_A + h * r_cos_A,
+ xc + r_cos_B + h * r_sin_B,
+ yc + r_sin_B - h * r_cos_B,
+ xc + r_cos_B,
+ yc + r_sin_B);
+}
+
+static void
+_cairo_arc_in_direction (cairo_t *cr,
+ double xc,
+ double yc,
+ double radius,
+ double angle_min,
+ double angle_max,
+ cairo_direction_t dir)
+{
+ while (angle_max - angle_min > 4 * M_PI)
+ angle_max -= 2 * M_PI;
+
+ /* Recurse if drawing arc larger than pi */
+ if (angle_max - angle_min > M_PI) {
+ double angle_mid = angle_min + (angle_max - angle_min) / 2.0;
+ /* XXX: Something tells me this block could be condensed. */
+ if (dir == CAIRO_DIRECTION_FORWARD) {
+ _cairo_arc_in_direction (cr, xc, yc, radius,
+ angle_min, angle_mid,
+ dir);
+
+ _cairo_arc_in_direction (cr, xc, yc, radius,
+ angle_mid, angle_max,
+ dir);
+ } else {
+ _cairo_arc_in_direction (cr, xc, yc, radius,
+ angle_mid, angle_max,
+ dir);
+
+ _cairo_arc_in_direction (cr, xc, yc, radius,
+ angle_min, angle_mid,
+ dir);
+ }
+ } else {
+ cairo_matrix_t ctm;
+ int i, segments;
+ double angle, angle_step;
+
+ cairo_get_matrix (cr, &ctm);
+ segments = _arc_segments_needed (angle_max - angle_min,
+ radius, &ctm,
+ cairo_get_tolerance (cr));
+ angle_step = (angle_max - angle_min) / (double) segments;
+
+ if (dir == CAIRO_DIRECTION_FORWARD) {
+ angle = angle_min;
+ } else {
+ angle = angle_max;
+ angle_step = - angle_step;
+ }
+
+ for (i = 0; i < segments; i++, angle += angle_step) {
+ _cairo_arc_segment (cr, xc, yc,
+ radius,
+ angle,
+ angle + angle_step);
+ }
+ }
+}
+
+/**
+ * _cairo_arc_path_negative:
+ * @cr: a cairo context
+ * @xc: X position of the center of the arc
+ * @yc: Y position of the center of the arc
+ * @radius: the radius of the arc
+ * @angle1: the start angle, in radians
+ * @angle2: the end angle, in radians
+ *
+ * Compute a path for the given arc and append it onto the current
+ * path within @cr. The arc will be accurate within the current
+ * tolerance and given the current transformation.
+ **/
+void
+_cairo_arc_path (cairo_t *cr,
+ double xc,
+ double yc,
+ double radius,
+ double angle1,
+ double angle2)
+{
+ _cairo_arc_in_direction (cr, xc, yc,
+ radius,
+ angle1, angle2,
+ CAIRO_DIRECTION_FORWARD);
+}
+
+/**
+ * _cairo_arc_path_negative:
+ * @xc: X position of the center of the arc
+ * @yc: Y position of the center of the arc
+ * @radius: the radius of the arc
+ * @angle1: the start angle, in radians
+ * @angle2: the end angle, in radians
+ * @ctm: the current transformation matrix
+ * @tolerance: the current tolerance value
+ * @path: the path onto which th earc will be appended
+ *
+ * Compute a path for the given arc (defined in the negative
+ * direction) and append it onto the current path within @cr. The arc
+ * will be accurate within the current tolerance and given the current
+ * transformation.
+ **/
+void
+_cairo_arc_path_negative (cairo_t *cr,
+ double xc,
+ double yc,
+ double radius,
+ double angle1,
+ double angle2)
+{
+ _cairo_arc_in_direction (cr, xc, yc,
+ radius,
+ angle2, angle1,
+ CAIRO_DIRECTION_REVERSE);
+}
diff --git a/src/cairo-array.c b/src/cairo-array.c
index 2b1cf9d61..a37ea9af5 100644
--- a/src/cairo-array.c
+++ b/src/cairo-array.c
@@ -132,3 +132,142 @@ _cairo_array_num_elements (cairo_array_t *array)
{
return array->num_elements;
}
+
+/* cairo_user_data_array_t */
+
+typedef struct {
+ const cairo_user_data_key_t *key;
+ void *user_data;
+ cairo_destroy_func_t destroy;
+} cairo_user_data_slot_t;
+
+/**
+ * _cairo_user_data_array_init:
+ * @array: a #cairo_user_data_array_t
+ *
+ * Initializes a #cairo_user_data_array_t structure for future
+ * use. After initialization, the array has no keys. Call
+ * _cairo_user_data_array_destroy() to free any allocated memory
+ * when done using the array.
+ **/
+void
+_cairo_user_data_array_init (cairo_user_data_array_t *array)
+{
+ _cairo_array_init (array, sizeof (cairo_user_data_slot_t));
+}
+
+/**
+ * _cairo_user_data_array_destroy:
+ * @array: a #cairo_user_data_array_t
+ *
+ * Destroys all current keys in the user data array and deallocates
+ * any memory allocated for the array itself.
+ **/
+void
+_cairo_user_data_array_destroy (cairo_user_data_array_t *array)
+{
+ int i, num_slots;
+ cairo_user_data_slot_t *slots;
+
+ num_slots = array->num_elements;
+ slots = (cairo_user_data_slot_t *) array->elements;
+ for (i = 0; i < num_slots; i++) {
+ if (slots[i].user_data != NULL && slots[i].destroy != NULL)
+ slots[i].destroy (slots[i].user_data);
+ }
+
+ _cairo_array_fini (array);
+}
+
+/**
+ * _cairo_user_data_array_get_data:
+ * @array: a #cairo_user_data_array_t
+ * @key: the address of the #cairo_user_data_key_t the user data was
+ * attached to
+ *
+ * Returns user data previously attached using the specified
+ * key. If no user data has been attached with the given key this
+ * function returns %NULL.
+ *
+ * Return value: the user data previously attached or %NULL.
+ **/
+void *
+_cairo_user_data_array_get_data (cairo_user_data_array_t *array,
+ const cairo_user_data_key_t *key)
+{
+ int i, num_slots;
+ cairo_user_data_slot_t *slots;
+
+ num_slots = array->num_elements;
+ slots = (cairo_user_data_slot_t *) array->elements;
+ for (i = 0; i < num_slots; i++) {
+ if (slots[i].key == key)
+ return slots[i].user_data;
+ }
+
+ return NULL;
+}
+
+/**
+ * _cairo_user_data_array_set_data:
+ * @array: a #cairo_user_data_array_t
+ * @key: the address of a #cairo_user_data_key_t to attach the user data to
+ * @user_data: the user data to attach
+ * @destroy: a #cairo_destroy_func_t which will be called when the
+ * user data array is destroyed or when new user data is attached using the
+ * same key.
+ *
+ * Attaches user data to a user data array. To remove user data,
+ * call this function with the key that was used to set it and %NULL
+ * for @data.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
+ * slot could not be allocated for the user data.
+ **/
+cairo_status_t
+_cairo_user_data_array_set_data (cairo_user_data_array_t *array,
+ const cairo_user_data_key_t *key,
+ void *user_data,
+ cairo_destroy_func_t destroy)
+{
+ int i, num_slots;
+ cairo_user_data_slot_t *slots, *s;
+
+ s = NULL;
+ num_slots = array->num_elements;
+ slots = (cairo_user_data_slot_t *) array->elements;
+ for (i = 0; i < num_slots; i++) {
+ if (slots[i].key == key) {
+ if (slots[i].user_data != NULL && slots[i].destroy != NULL)
+ slots[i].destroy (slots[i].user_data);
+ s = &slots[i];
+ break;
+ }
+ if (user_data && slots[i].user_data == NULL) {
+ s = &slots[i]; /* Have to keep searching for an exact match */
+ }
+ }
+
+ if (user_data == NULL) {
+ if (s != NULL) {
+ s->key = NULL;
+ s->user_data = NULL;
+ s->destroy = NULL;
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+
+ } else {
+ if (s == NULL)
+ s = _cairo_array_append (array, NULL, 1);
+ if (s == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ s->key = key;
+ s->user_data = user_data;
+ s->destroy = destroy;
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index cb4b1c5d7..a279956df 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -30,778 +30,661 @@
* The Initial Developer of the Original Code is Calum Robinson
*
* Contributor(s):
- * Calum Robinson <calumr@mac.com>
+ * Calum Robinson <calumr@mac.com>
*/
#include <stdlib.h>
#include <math.h>
-
#include "cairo-atsui.h"
#include "cairoint.h"
+#include "cairo.h"
+#include <iconv.h>
+typedef struct {
+ cairo_scaled_font_t base;
+ cairo_matrix_t scale;
+ ATSUStyle style;
+ ATSUStyle unscaled_style;
+ ATSUFontID fontID;
+} cairo_atsui_font_t;
+typedef struct cairo_ATSUI_glyph_path_callback_info_t {
+ cairo_path_fixed_t *path;
+ cairo_matrix_t scale;
+} cairo_ATSUI_glyph_path_callback_info_t;
+const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend;
-#pragma mark Types
+static CGAffineTransform
+CGAffineTransformMakeWithCairoFontScale(cairo_matrix_t *scale)
+{
+ return CGAffineTransformMake(scale->xx, scale->yx,
+ scale->xy, scale->yy,
+ 0, 0);
+}
+static ATSUStyle
+CreateSizedCopyOfStyle(ATSUStyle inStyle, cairo_matrix_t *scale)
+{
+ ATSUStyle style;
+ OSStatus err;
-typedef struct {
- cairo_unscaled_font_t base;
-
- ATSUStyle style;
- ATSUFontID fontID;
-} cairo_atsui_font_t;
+ // Set the style's size
+ CGAffineTransform theTransform =
+ CGAffineTransformMakeWithCairoFontScale(scale);
+ Fixed theSize =
+ FloatToFixed(CGSizeApplyAffineTransform
+ (CGSizeMake(1.0, 1.0), theTransform).height);
+ const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag };
+ const ByteCount theFontStyleSizes[] = { sizeof(Fixed) };
+ ATSUAttributeValuePtr theFontStyleValues[] = { &theSize };
+ err = ATSUCreateAndCopyStyle(inStyle, &style);
-typedef struct cairo_ATSUI_glyph_path_callback_info_t {
- cairo_path_t *path;
- cairo_matrix_t scale;
-} cairo_ATSUI_glyph_path_callback_info_t;
+ err = ATSUSetAttributes(style,
+ sizeof(theFontStyleTags) /
+ sizeof(ATSUAttributeTag), theFontStyleTags,
+ theFontStyleSizes, theFontStyleValues);
+ return style;
+}
+static cairo_status_t
+_cairo_atsui_font_create(const char *family,
+ cairo_font_slant_t slant,
+ cairo_font_weight_t weight,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ cairo_scaled_font_t **font_out)
+{
+ cairo_atsui_font_t *font = NULL;
+ ATSUStyle style;
+ ATSUFontID fontID;
+ OSStatus err;
+ Boolean isItalic, isBold;
+ cairo_matrix_t scale;
+
+ err = ATSUCreateStyle(&style);
+
+
+ switch (weight) {
+ case CAIRO_FONT_WEIGHT_BOLD:
+ isBold = true;
+ break;
+ case CAIRO_FONT_WEIGHT_NORMAL:
+ default:
+ isBold = false;
+ break;
+ }
+
+ switch (slant) {
+ case CAIRO_FONT_SLANT_ITALIC:
+ isItalic = true;
+ break;
+ case CAIRO_FONT_SLANT_OBLIQUE:
+ isItalic = false;
+ break;
+ case CAIRO_FONT_SLANT_NORMAL:
+ default:
+ isItalic = false;
+ break;
+ }
+
+ err = ATSUFindFontFromName(family, strlen(family),
+ kFontFamilyName,
+ kFontNoPlatformCode,
+ kFontRomanScript,
+ kFontNoLanguageCode, &fontID);
+
+ if (err != noErr) {
+ // couldn't get the font - remap css names and try again
+
+ if (!strcmp(family, "serif"))
+ family = "Times";
+ else if (!strcmp(family, "sans-serif"))
+ family = "Helvetica";
+ else if (!strcmp(family, "cursive"))
+ family = "Apple Chancery";
+ else if (!strcmp(family, "fantasy"))
+ family = "Gadget";
+ else if (!strcmp(family, "monospace"))
+ family = "Courier";
+ else // anything else - return error instead?
+ family = "Courier";
+
+ err = ATSUFindFontFromName(family, strlen(family),
+ kFontFamilyName,
+ kFontNoPlatformCode,
+ kFontRomanScript,
+ kFontNoLanguageCode, &fontID);
+ }
+
+
+ ATSUAttributeTag styleTags[] =
+ { kATSUQDItalicTag, kATSUQDBoldfaceTag, kATSUFontTag };
+ ATSUAttributeValuePtr styleValues[] = { &isItalic, &isBold, &fontID };
+ ByteCount styleSizes[] =
+ { sizeof(Boolean), sizeof(Boolean), sizeof(ATSUFontID) };
+
+
+ err = ATSUSetAttributes(style,
+ sizeof(styleTags) / sizeof(styleTags[0]),
+ styleTags, styleSizes, styleValues);
+
+ font = malloc(sizeof(cairo_atsui_font_t));
+
+ _cairo_scaled_font_init(&font->base, font_matrix, ctm,
+ &cairo_atsui_scaled_font_backend);
+
+ cairo_matrix_multiply(&scale, font_matrix, ctm);
+ font->style = CreateSizedCopyOfStyle(style, &scale);
+
+ Fixed theSize = FloatToFixed(1.0);
+ const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag };
+ const ByteCount theFontStyleSizes[] = { sizeof(Fixed) };
+ ATSUAttributeValuePtr theFontStyleValues[] = { &theSize };
+ err = ATSUSetAttributes(style,
+ sizeof(theFontStyleTags) /
+ sizeof(ATSUAttributeTag), theFontStyleTags,
+ theFontStyleSizes, theFontStyleValues);
+
+ font->unscaled_style = style;
+
+ font->fontID = fontID;
+ font->scale = scale;
+
+ *font_out = &font->base;
+
+ return CAIRO_STATUS_SUCCESS;
+}
-#pragma mark Private Functions
+static void
+_cairo_atsui_font_destroy_font(void *abstract_font)
+{
+ cairo_atsui_font_t *font = abstract_font;
+ if (font == NULL)
+ return;
+ if (font->style)
+ ATSUDisposeStyle(font->style);
+ if (font->unscaled_style)
+ ATSUDisposeStyle(font->unscaled_style);
+}
-static CGAffineTransform CGAffineTransformMakeWithCairoFontScale(cairo_font_scale_t scale)
+static void
+_cairo_atsui_font_get_glyph_cache_key(void *abstract_font,
+ cairo_glyph_cache_key_t *key)
{
- return CGAffineTransformMake( scale.matrix[0][0], scale.matrix[0][1],
- scale.matrix[1][0], scale.matrix[1][1],
- 0, 0);
}
-static ATSUStyle CreateSizedCopyOfStyle(ATSUStyle inStyle, cairo_font_scale_t *scale)
+static cairo_status_t
+_cairo_atsui_font_text_to_glyphs(void *abstract_font,
+ const char *utf8,
+ cairo_glyph_t **glyphs,
+ int *num_glyphs)
{
- ATSUStyle style;
- OSStatus err;
-
-
- // Set the style's size
- CGAffineTransform theTransform = CGAffineTransformMakeWithCairoFontScale(*scale);
- Fixed theSize = FloatToFixed(CGSizeApplyAffineTransform(CGSizeMake(1.0, 1.0), theTransform).height);
- const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag };
- const ByteCount theFontStyleSizes[] = { sizeof(Fixed) };
- ATSUAttributeValuePtr theFontStyleValues[] = { &theSize };
-
- err = ATSUCreateAndCopyStyle(inStyle, &style);
-
- err = ATSUSetAttributes( style,
- sizeof(theFontStyleTags) / sizeof(ATSUAttributeTag),
- theFontStyleTags, theFontStyleSizes, theFontStyleValues);
-
-
- return style;
-}
+ cairo_atsui_font_t *font = abstract_font;
+ size_t i;
+ OSStatus err;
+ ATSUTextLayout textLayout;
+ ATSLayoutRecord *layoutRecords;
+ ItemCount glyphCount, charCount;
+ UniChar *theText;
+ err = ATSUCreateTextLayout(&textLayout);
+#if 1
+ charCount = strlen(utf8);
+ // Set the text in the text layout object, so we can measure it
+ theText = (UniChar *) malloc(charCount * sizeof(UniChar));
+ for (i = 0; i < charCount; i++) {
+ theText[i] = utf8[i];
+ }
+#endif
-#pragma mark Public Functions
+#if 0
+ // Set the text in the text layout object, so we can measure it
+ charCount = strlen(utf8);
+ theText = (UniChar *) malloc(charCount * sizeof(UniChar));
+ size_t inBytes = charCount, outBytes = charCount;
+ iconv_t converter = iconv_open("UTF-8", "UTF-16");
+ charCount = iconv(converter, utf8, &inBytes, theText, &outBytes);
+#endif
+ err = ATSUSetTextPointerLocation(textLayout,
+ theText, 0, charCount, charCount);
+ // Set the style for all of the text
+ err = ATSUSetRunStyle(textLayout,
+ font->unscaled_style, kATSUFromTextBeginning, kATSUToTextEnd);
-static cairo_unscaled_font_t *
-_cairo_atsui_font_create( const char *family,
- cairo_font_slant_t slant,
- cairo_font_weight_t weight)
-{
- cairo_atsui_font_t *font = NULL;
- ATSUStyle style;
- ATSUFontID fontID;
- OSStatus err;
- Boolean isItalic, isBold;
-
-
- err = ATSUCreateStyle(&style);
-
-
- switch (weight)
- {
- case CAIRO_FONT_WEIGHT_BOLD:
- isBold = true;
- break;
- case CAIRO_FONT_WEIGHT_NORMAL:
- default:
- isBold = false;
- break;
- }
-
- switch (slant)
- {
- case CAIRO_FONT_SLANT_ITALIC:
- isItalic = true;
- break;
- case CAIRO_FONT_SLANT_OBLIQUE:
- isItalic = false;
- break;
- case CAIRO_FONT_SLANT_NORMAL:
- default:
- isItalic = false;
- break;
- }
-
- err = ATSUFindFontFromName( family, strlen(family),
- kFontFamilyName,
- kFontNoPlatformCode,
- kFontRomanScript,
- kFontNoLanguageCode,
- &fontID);
-
-
- ATSUAttributeTag styleTags[] = {kATSUQDItalicTag, kATSUQDBoldfaceTag, kATSUFontTag};
- ATSUAttributeValuePtr styleValues[] = {&isItalic, &isBold, &fontID};
- ByteCount styleSizes[] = {sizeof(Boolean), sizeof(Boolean), sizeof(ATSUFontID)};
-
-
- err = ATSUSetAttributes( style,
- sizeof(styleTags) / sizeof(styleTags[0]),
- styleTags,
- styleSizes,
- styleValues);
-
-
-
- font = malloc(sizeof(cairo_atsui_font_t));
-
- if (_cairo_unscaled_font_init(&font->base, &cairo_atsui_font_backend) == CAIRO_STATUS_SUCCESS)
- {
- font->style = style;
- font->fontID = fontID;
-
-
- return &font->base;
- }
-
-
- free(font);
-
- return NULL;
-}
+ // Get the glyphs from the text layout object
+ err = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(textLayout,
+ 0,
+ kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
+ (void *)
+ &layoutRecords,
+ &glyphCount);
+ *num_glyphs = glyphCount - 1;
-static void
-_cairo_atsui_font_destroy(void *abstract_font)
-{
- cairo_atsui_font_t *font = abstract_font;
-
-
- if (font == NULL)
- return;
-
- if (font->style)
- ATSUDisposeStyle(font->style);
-
- free(font);
-}
+ *glyphs =
+ (cairo_glyph_t *) malloc(*num_glyphs * (sizeof(cairo_glyph_t)));
+ if (*glyphs == NULL) {
+ return CAIRO_STATUS_NO_MEMORY;
+ }
-static cairo_status_t
-_cairo_atsui_font_text_to_glyphs( void *abstract_font,
- cairo_font_scale_t *sc,
- const unsigned char *utf8,
- cairo_glyph_t **glyphs,
- int *nglyphs)
-{
- cairo_atsui_font_t *font = abstract_font;
- size_t i;
- OSStatus err;
- ATSUTextLayout textLayout;
- ATSLayoutRecord *layoutRecords;
- ItemCount glyphCount, charCount;
- UniChar *theText;
- ATSUStyle style;
-
-
- charCount = strlen(utf8);
-
-
- err = ATSUCreateTextLayout(&textLayout);
-
-
- // Set the text in the text layout object, so we can measure it
- theText = (UniChar *)malloc(charCount * sizeof(UniChar));
-
- for (i = 0; i < charCount; i++)
- {
- theText[i] = utf8[i];
- }
-
- err = ATSUSetTextPointerLocation( textLayout,
- theText,
- 0,
- charCount,
- charCount);
-
-
- style = CreateSizedCopyOfStyle(font->style, sc);
-
-
- // Set the style for all of the text
- err = ATSUSetRunStyle( textLayout,
- style,
- kATSUFromTextBeginning,
- kATSUToTextEnd);
-
-
-
- // Get the glyphs from the text layout object
- err = ATSUDirectGetLayoutDataArrayPtrFromTextLayout( textLayout,
- 0,
- kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
- (void *)&layoutRecords,
- &glyphCount);
-
- *nglyphs = glyphCount;
-
-
- *glyphs = (cairo_glyph_t *)malloc(glyphCount * (sizeof(cairo_glyph_t)));
- if (*glyphs == NULL)
- {
- return CAIRO_STATUS_NO_MEMORY;
- }
-
- for (i = 0; i < glyphCount; i++)
- {
- (*glyphs)[i].index = layoutRecords[i].glyphID;
- (*glyphs)[i].x = FixedToFloat(layoutRecords[i].realPos);
- (*glyphs)[i].y = 0;
- }
-
-
- free(theText);
-
- ATSUDirectReleaseLayoutDataArrayPtr( NULL,
- kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
- (void *)&layoutRecords);
-
- ATSUDisposeTextLayout(textLayout);
-
- ATSUDisposeStyle(style);
-
-
- return CAIRO_STATUS_SUCCESS;
+ for (i = 0; i < *num_glyphs; i++) {
+ (*glyphs)[i].index = layoutRecords[i].glyphID;
+ (*glyphs)[i].x = FixedToFloat(layoutRecords[i].realPos);
+ (*glyphs)[i].y = 0;
+ }
+
+
+ free(theText);
+
+ ATSUDirectReleaseLayoutDataArrayPtr(NULL,
+ kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
+ (void *) &layoutRecords);
+
+ ATSUDisposeTextLayout(textLayout);
+
+ return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
-_cairo_atsui_font_font_extents( void *abstract_font,
- cairo_font_scale_t *sc,
- cairo_font_extents_t *extents)
+static cairo_status_t
+_cairo_atsui_font_font_extents(void *abstract_font,
+ cairo_font_extents_t * extents)
{
- cairo_atsui_font_t *font = abstract_font;
- ATSFontRef atsFont;
- ATSFontMetrics metrics;
- OSStatus err;
-
-
- // TODO - test this
-
- atsFont = FMGetATSFontRefFromFont(font->fontID);
-
- if (atsFont)
- {
- err = ATSFontGetHorizontalMetrics(atsFont, kATSOptionFlagsDefault, &metrics);
-
- if (err == noErr)
- {
- extents->ascent = metrics.ascent;
- extents->descent = metrics.descent;
- extents->height = metrics.capHeight;
- extents->max_x_advance = metrics.maxAdvanceWidth;
-
- // The FT backend doesn't handle max_y_advance either, so we'll ignore it for now.
- extents->max_y_advance = 0.0;
-
-
- return CAIRO_STATUS_SUCCESS;
- }
- }
-
-
- return CAIRO_STATUS_NULL_POINTER;
+ cairo_atsui_font_t *font = abstract_font;
+ ATSFontRef atsFont;
+ ATSFontMetrics metrics;
+ OSStatus err;
+
+ // TODO - test this
+
+ atsFont = FMGetATSFontRefFromFont(font->fontID);
+
+ if (atsFont) {
+ err =
+ ATSFontGetHorizontalMetrics(atsFont, kATSOptionFlagsDefault,
+ &metrics);
+
+ if (err == noErr) {
+ extents->ascent = metrics.ascent;
+ extents->descent = metrics.descent;
+ extents->height = metrics.capHeight;
+ extents->max_x_advance = metrics.maxAdvanceWidth;
+
+ // The FT backend doesn't handle max_y_advance either, so we'll ignore it for now.
+ extents->max_y_advance = 0.0;
+
+ return CAIRO_STATUS_SUCCESS;
+ }
+ }
+
+
+ return CAIRO_STATUS_NULL_POINTER;
}
-static cairo_status_t
-_cairo_atsui_font_glyph_extents( void *abstract_font,
- cairo_font_scale_t *sc,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_text_extents_t *extents)
+static cairo_status_t
+_cairo_atsui_font_glyph_extents(void *abstract_font,
+ cairo_glyph_t * glyphs,
+ int num_glyphs,
+ cairo_text_extents_t * extents)
{
- cairo_atsui_font_t *font = abstract_font;
- cairo_point_double_t origin;
- cairo_point_double_t glyph_min, glyph_max;
- cairo_point_double_t total_min, total_max;
- OSStatus err;
- ATSUStyle style;
- int i;
-
-
- if (num_glyphs == 0)
- {
- extents->x_bearing = 0.0;
- extents->y_bearing = 0.0;
- extents->width = 0.0;
- extents->height = 0.0;
- extents->x_advance = 0.0;
- extents->y_advance = 0.0;
-
- return CAIRO_STATUS_SUCCESS;
- }
-
- origin.x = glyphs[0].x;
- origin.y = glyphs[0].y;
-
-
- style = CreateSizedCopyOfStyle(font->style, sc);
-
-
- for (i = 0; i < num_glyphs; i++)
- {
- GlyphID theGlyph = glyphs[i].index;
- double minX, maxX, ascent, descent;
- ATSGlyphIdealMetrics metricsH, metricsV;
-
-
- err = ATSUGlyphGetIdealMetrics( style,
- 1,
- &theGlyph,
- 0,
- &metricsH);
-
-
- ATSUVerticalCharacterType verticalType = kATSUStronglyVertical;
- ATSUAttributeTag theTag = kATSUVerticalCharacterTag;
- ByteCount theSize = sizeof(ATSUVerticalCharacterType);
-
- err = ATSUSetAttributes(style, 1, &theTag, &theSize, (ATSUAttributeValuePtr)&verticalType);
-
- err = ATSUGlyphGetIdealMetrics( style,
- 1,
- &theGlyph,
- 0,
- &metricsV);
-
- minX = metricsH.otherSideBearing.x;
- maxX = metricsH.advance.x;
-
- ascent = metricsV.advance.x;
- descent = metricsV.otherSideBearing.x;
-
- glyph_min.x = glyphs[i].x + minX;
- glyph_min.y = glyphs[i].y + descent;
- glyph_max.x = glyphs[i].x + maxX;
- glyph_max.y = glyphs[i].y + ascent;
-
- if (i==0)
- {
- total_min = glyph_min;
- total_max = glyph_max;
- }
- else
- {
- if (glyph_min.x < total_min.x)
- total_min.x = glyph_min.x;
- if (glyph_min.y < total_min.y)
- total_min.y = glyph_min.y;
-
- if (glyph_max.x > total_max.x)
- total_max.x = glyph_max.x;
- if (glyph_max.y > total_max.y)
- total_max.y = glyph_max.y;
- }
- }
-
-
- extents->x_bearing = total_min.x - origin.x;
- extents->y_bearing = total_min.y - origin.y;
- extents->width = total_max.x - total_min.x;
- extents->height = total_max.y - total_min.y;
- extents->x_advance = glyphs[i-1].x - origin.x;
- extents->y_advance = glyphs[i-1].y - origin.y;
-
-
- return CAIRO_STATUS_SUCCESS;
+ cairo_atsui_font_t *font = abstract_font;
+ OSStatus err;
+
+ assert(num_glyphs == 1);
+
+ GlyphID theGlyph = glyphs[0].index;
+
+ ATSGlyphIdealMetrics metricsH, metricsV;
+ ATSUStyle style;
+
+ ATSUCreateAndCopyStyle(font->unscaled_style, &style);
+
+ err = ATSUGlyphGetIdealMetrics(style,
+ 1, &theGlyph, 0, &metricsH);
+
+ ATSUVerticalCharacterType verticalType = kATSUStronglyVertical;
+ const ATSUAttributeTag theTag[] = { kATSUVerticalCharacterTag };
+ const ByteCount theSizes[] = { sizeof(verticalType) };
+ ATSUAttributeValuePtr theValues[] = { &verticalType };
+
+ err = ATSUSetAttributes(style, 1, theTag, theSizes, theValues);
+
+ err = ATSUGlyphGetIdealMetrics(style,
+ 1, &theGlyph, 0, &metricsV);
+
+ extents->x_bearing = metricsH.sideBearing.x;
+ extents->y_bearing = metricsV.advance.y;
+ extents->width =
+ metricsH.advance.x - metricsH.sideBearing.x - metricsH.otherSideBearing.x;
+ extents->height =
+ -metricsV.advance.y - metricsV.sideBearing.y - metricsV.otherSideBearing.y;
+ extents->x_advance = metricsH.advance.x;
+ extents->y_advance = 0;
+
+ ATSUDisposeStyle(style);
+
+ return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
-_cairo_atsui_font_glyph_bbox( void *abstract_font,
- cairo_font_scale_t *sc,
- const cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_box_t *bbox)
+static cairo_status_t
+_cairo_atsui_font_glyph_bbox(void *abstract_font,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs, cairo_box_t *bbox)
{
- cairo_atsui_font_t *font = abstract_font;
- cairo_fixed_t x1, y1, x2, y2;
- int i;
- OSStatus err;
- ATSUStyle style;
-
-
- bbox->p1.x = bbox->p1.y = CAIRO_MAXSHORT << 16;
- bbox->p2.x = bbox->p2.y = CAIRO_MINSHORT << 16;
-
-
- style = CreateSizedCopyOfStyle(font->style, sc);
-
-
- for (i = 0; i < num_glyphs; i++)
- {
- GlyphID theGlyph = glyphs[i].index;
- ATSGlyphIdealMetrics metrics;
-
-
- err = ATSUGlyphGetIdealMetrics( style,
- 1,
- &theGlyph,
- 0,
- &metrics);
-
- x1 = _cairo_fixed_from_double(glyphs[i].x);
- y1 = _cairo_fixed_from_double(glyphs[i].y);
- x2 = x1 + _cairo_fixed_from_double(metrics.advance.x);
- y2 = y1 + _cairo_fixed_from_double(metrics.advance.y);
-
- if (x1 < bbox->p1.x)
- bbox->p1.x = x1;
-
- if (y1 < bbox->p1.y)
- bbox->p1.y = y1;
-
- if (x2 > bbox->p2.x)
- bbox->p2.x = x2;
-
- if (y2 > bbox->p2.y)
- bbox->p2.y = y2;
- }
-
-
- ATSUDisposeStyle(style);
-
-
- return CAIRO_STATUS_SUCCESS;
+ cairo_atsui_font_t *font = abstract_font;
+ cairo_fixed_t x1, y1, x2, y2;
+ int i;
+
+ bbox->p1.x = bbox->p1.y = CAIRO_MAXSHORT << 16;
+ bbox->p2.x = bbox->p2.y = CAIRO_MINSHORT << 16;
+
+
+ for (i = 0; i < num_glyphs; i++) {
+ GlyphID theGlyph = glyphs[i].index;
+
+ ATSGlyphScreenMetrics metrics;
+ ATSUGlyphGetScreenMetrics(font->style,
+ 1, &theGlyph, 0, true, true, &metrics);
+
+ x1 = _cairo_fixed_from_double(glyphs[i].x + metrics.topLeft.x);
+ y1 = _cairo_fixed_from_double(glyphs[i].y - metrics.topLeft.y);
+ x2 = x1 + _cairo_fixed_from_double(metrics.height);
+ y2 = y1 + _cairo_fixed_from_double(metrics.width);
+
+ if (x1 < bbox->p1.x)
+ bbox->p1.x = x1;
+
+ if (y1 < bbox->p1.y)
+ bbox->p1.y = y1;
+
+ if (x2 > bbox->p2.x)
+ bbox->p2.x = x2;
+
+ if (y2 > bbox->p2.y)
+ bbox->p2.y = y2;
+ }
+
+ return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
-_cairo_atsui_font_show_glyphs( void *abstract_font,
- cairo_font_scale_t *sc,
- cairo_operator_t operator,
- cairo_surface_t *source,
- cairo_surface_t *surface,
- int source_x,
- int source_y,
- const cairo_glyph_t *glyphs,
- int num_glyphs)
+static cairo_status_t
+_cairo_atsui_font_show_glyphs(void *abstract_font,
+ cairo_operator_t operator,
+ cairo_pattern_t *pattern,
+ cairo_surface_t *generic_surface,
+ int source_x,
+ int source_y,
+ int dest_x,
+ int dest_y,
+ unsigned int width,
+ unsigned int height,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs)
{
- cairo_atsui_font_t *font = abstract_font;
- CGContextRef myBitmapContext;
- CGColorSpaceRef colorSpace;
- cairo_image_surface_t *destImageSurface;
- int i;
-
-
- destImageSurface = _cairo_surface_get_image(surface);
-
-
- // Create a CGBitmapContext for the dest surface for drawing into
+ cairo_atsui_font_t *font = abstract_font;
+ CGContextRef myBitmapContext;
+ CGColorSpaceRef colorSpace;
+ cairo_image_surface_t *destImageSurface;
+ int i;
+
+ cairo_rectangle_t rect = {dest_x, dest_y, width, height};
+ _cairo_surface_acquire_dest_image(generic_surface,
+ &rect,
+ &destImageSurface,
+ &rect,
+ NULL);
+
+ // Create a CGBitmapContext for the dest surface for drawing into
colorSpace = CGColorSpaceCreateDeviceRGB();
-
- myBitmapContext = CGBitmapContextCreate( destImageSurface->data,
- destImageSurface->width,
- destImageSurface->height,
- destImageSurface->depth / 4,
- destImageSurface->stride,
- colorSpace,
- kCGImageAlphaPremultipliedFirst);
-
-
- ATSFontRef atsFont = FMGetATSFontRefFromFont(font->fontID);
- CGFontRef cgFont = CGFontCreateWithPlatformFont(&atsFont);
-
- CGContextSetFont(myBitmapContext, cgFont);
-
-
- CGAffineTransform textTransform = CGAffineTransformMakeWithCairoFontScale(*sc);
- CGSize textSize = CGSizeMake(1.0, 1.0);
-
- textSize = CGSizeApplyAffineTransform(textSize, textTransform);
-
- CGContextSetFontSize(myBitmapContext, textSize.width);
-
-
- // TODO - bold and italic text
- //
- // We could draw the text using ATSUI and get bold, italics
- // etc. for free, but ATSUI does a lot of text layout work
- // that we don't really need...
-
-
- for (i = 0; i < num_glyphs; i++)
- {
- CGGlyph theGlyph = glyphs[i].index;
-
- CGContextShowGlyphsAtPoint(myBitmapContext, source_x + glyphs[i].x, destImageSurface->height - (source_y + glyphs[i].y), &theGlyph, 1);
- }
-
-
- CGColorSpaceRelease(colorSpace);
- CGContextRelease(myBitmapContext);
-
-
- return CAIRO_STATUS_SUCCESS;
-}
+ myBitmapContext = CGBitmapContextCreate(destImageSurface->data,
+ destImageSurface->width,
+ destImageSurface->height,
+ destImageSurface->depth / 4,
+ destImageSurface->stride,
+ colorSpace,
+ kCGImageAlphaPremultipliedFirst);
+ CGContextTranslateCTM(myBitmapContext, 0, destImageSurface->height);
+ CGContextScaleCTM(myBitmapContext, 1.0f, -1.0f);
+
+ ATSFontRef atsFont = FMGetATSFontRefFromFont(font->fontID);
+ CGFontRef cgFont = CGFontCreateWithPlatformFont(&atsFont);
+
+ CGContextSetFont(myBitmapContext, cgFont);
+
+ CGAffineTransform textTransform =
+ CGAffineTransformMakeWithCairoFontScale(&font->scale);
+
+ textTransform = CGAffineTransformScale(textTransform, 1.0f, -1.0f);
+
+ CGContextSetFontSize(myBitmapContext, 1.0);
+ CGContextSetTextMatrix(myBitmapContext, textTransform);
+
+ if (pattern->type == CAIRO_PATTERN_SOLID &&
+ _cairo_pattern_is_opaque_solid(pattern)) {
+ cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *)pattern;
+ CGContextSetRGBFillColor(myBitmapContext,
+ solid->color.red,
+ solid->color.green,
+ solid->color.blue, 1.0f);
+ } else
+ CGContextSetRGBFillColor(myBitmapContext, 0.0f, 0.0f, 0.0f, 0.0f);
+
+ // TODO - bold and italic text
+ //
+ // We could draw the text using ATSUI and get bold, italics
+ // etc. for free, but ATSUI does a lot of text layout work
+ // that we don't really need...
+
+
+ for (i = 0; i < num_glyphs; i++) {
+ CGGlyph theGlyph = glyphs[i].index;
+
+ CGContextShowGlyphsAtPoint(myBitmapContext,
+ glyphs[i].x,
+ glyphs[i].y,
+ &theGlyph, 1);
+ }
+
+
+ CGColorSpaceRelease(colorSpace);
+ CGContextRelease(myBitmapContext);
-#pragma mark -
+ _cairo_surface_release_dest_image(generic_surface,
+ &rect,
+ destImageSurface,
+ &rect,
+ NULL);
+
+ return CAIRO_STATUS_SUCCESS;
+}
-static OSStatus MyATSCubicMoveToCallback(const Float32Point *pt, void *callBackDataPtr)
+static OSStatus MyATSCubicMoveToCallback(const Float32Point * pt,
+ void *callBackDataPtr)
{
- cairo_ATSUI_glyph_path_callback_info_t *info = callBackDataPtr;
- double scaledPt[2];
- cairo_point_t point;
-
-
- scaledPt[0] = pt->x;
- scaledPt[1] = pt->y;
-
- cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]);
-
- point.x = _cairo_fixed_from_double(scaledPt[0]);
- point.y = _cairo_fixed_from_double(scaledPt[1]);
-
- _cairo_path_move_to(info->path, &point);
-
-
+ cairo_ATSUI_glyph_path_callback_info_t *info = callBackDataPtr;
+ double scaledPt[2];
+ cairo_fixed_t x, y;
+
+ scaledPt[0] = pt->x;
+ scaledPt[1] = pt->y;
+
+ cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]);
+
+ x = _cairo_fixed_from_double(scaledPt[0]);
+ y = _cairo_fixed_from_double(scaledPt[1]);
+
+ _cairo_path_fixed_close_path(info->path);
+ _cairo_path_fixed_move_to(info->path, x, y);
+
return noErr;
}
-static OSStatus MyATSCubicLineToCallback(const Float32Point *pt, void *callBackDataPtr)
+static OSStatus MyATSCubicLineToCallback(const Float32Point * pt,
+ void *callBackDataPtr)
{
- cairo_ATSUI_glyph_path_callback_info_t *info = callBackDataPtr;
- cairo_point_t point;
- double scaledPt[2];
-
-
- scaledPt[0] = pt->x;
- scaledPt[1] = pt->y;
-
- cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]);
-
- point.x = _cairo_fixed_from_double(scaledPt[0]);
- point.y = _cairo_fixed_from_double(scaledPt[1]);
-
- _cairo_path_line_to(info->path, &point);
-
-
- return noErr;
+ cairo_ATSUI_glyph_path_callback_info_t *info = callBackDataPtr;
+ double scaledPt[2];
+ cairo_fixed_t x, y;
+
+ scaledPt[0] = pt->x;
+ scaledPt[1] = pt->y;
+
+ cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]);
+
+ x = _cairo_fixed_from_double(scaledPt[0]);
+ y = _cairo_fixed_from_double(scaledPt[1]);
+
+ _cairo_path_fixed_line_to(info->path, x, y);
+
+
+ return noErr;
}
-static OSStatus MyATSCubicCurveToCallback( const Float32Point *pt1,
- const Float32Point *pt2,
- const Float32Point *pt3,
- void *callBackDataPtr)
+static OSStatus MyATSCubicCurveToCallback(const Float32Point * pt1,
+ const Float32Point * pt2,
+ const Float32Point * pt3,
+ void *callBackDataPtr)
{
- cairo_ATSUI_glyph_path_callback_info_t *info = callBackDataPtr;
- cairo_point_t p0, p1, p2;
- double scaledPt[2];
-
-
- scaledPt[0] = pt1->x;
- scaledPt[1] = pt1->y;
-
- cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]);
-
- p0.x = _cairo_fixed_from_double(scaledPt[0]);
- p0.y = _cairo_fixed_from_double(scaledPt[1]);
-
+ cairo_ATSUI_glyph_path_callback_info_t *info = callBackDataPtr;
+ double scaledPt[2];
+ cairo_fixed_t x0, y0;
+ cairo_fixed_t x1, y1;
+ cairo_fixed_t x2, y2;
+
+
+ scaledPt[0] = pt1->x;
+ scaledPt[1] = pt1->y;
+
+ cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]);
+
+ x0 = _cairo_fixed_from_double(scaledPt[0]);
+ y0 = _cairo_fixed_from_double(scaledPt[1]);
+
scaledPt[0] = pt2->x;
- scaledPt[1] = pt2->y;
-
- cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]);
+ scaledPt[1] = pt2->y;
+
+ cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]);
+
+ x1 = _cairo_fixed_from_double(scaledPt[0]);
+ y1 = _cairo_fixed_from_double(scaledPt[1]);
- p1.x = _cairo_fixed_from_double(scaledPt[0]);
- p1.y = _cairo_fixed_from_double(scaledPt[1]);
-
scaledPt[0] = pt3->x;
- scaledPt[1] = pt3->y;
-
- cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]);
+ scaledPt[1] = pt3->y;
- p2.x = _cairo_fixed_from_double(scaledPt[0]);
- p2.y = _cairo_fixed_from_double(scaledPt[1]);
-
+ cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]);
- _cairo_path_curve_to(info->path, &p0, &p1, &p2);
-
-
- return noErr;
-}
+ x2 = _cairo_fixed_from_double(scaledPt[0]);
+ y2 = _cairo_fixed_from_double(scaledPt[1]);
-static OSStatus MyCubicClosePathProc(void * callBackDataPtr)
-{
- cairo_ATSUI_glyph_path_callback_info_t *info = callBackDataPtr;
-
-
- _cairo_path_close_path(info->path);
-
-
- return noErr;
+ _cairo_path_fixed_curve_to(info->path, x0, y0, x1, y1, x2, y2);
+
+
+ return noErr;
}
-static cairo_status_t
-_cairo_atsui_font_glyph_path( void *abstract_font,
- cairo_font_scale_t *sc,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_path_t *path)
+static OSStatus MyCubicClosePathProc(void *callBackDataPtr)
{
- int i;
- cairo_atsui_font_t *font = abstract_font;
- OSStatus err;
- cairo_ATSUI_glyph_path_callback_info_t info;
- ATSUStyle style;
-
-
- static ATSCubicMoveToUPP moveProc = NULL;
- static ATSCubicLineToUPP lineProc = NULL;
- static ATSCubicCurveToUPP curveProc = NULL;
- static ATSCubicClosePathUPP closePathProc = NULL;
-
-
- if (moveProc == NULL)
- {
- moveProc = NewATSCubicMoveToUPP(MyATSCubicMoveToCallback);
- lineProc = NewATSCubicLineToUPP(MyATSCubicLineToCallback);
- curveProc = NewATSCubicCurveToUPP(MyATSCubicCurveToCallback);
- closePathProc = NewATSCubicClosePathUPP(MyCubicClosePathProc);
- }
-
-
- info.path = path;
-
-
- style = CreateSizedCopyOfStyle(font->style, sc);
-
-
- for (i = 0; i < num_glyphs; i++)
- {
- GlyphID theGlyph = glyphs[i].index;
-
-
- cairo_matrix_set_affine( &info.scale,
- 1.0, 0.0,
- 0.0, 1.0,
- glyphs[i].x, glyphs[i].y);
-
-
- err = ATSUGlyphGetCubicPaths( style,
- theGlyph,
- moveProc,
- lineProc,
- curveProc,
- closePathProc,
- (void *)&info,
- &err);
- }
-
-
- err = ATSUDisposeStyle(style);
-
-
- return CAIRO_STATUS_SUCCESS;
-}
+ cairo_ATSUI_glyph_path_callback_info_t *info = callBackDataPtr;
-#pragma mark -
+ _cairo_path_fixed_close_path(info->path);
-static cairo_status_t
-_cairo_atsui_font_create_glyph(cairo_image_glyph_cache_entry_t *val)
-{
- // TODO
- printf("_cairo_atsui_font_create_glyph is unimplemented\n");
-
- // I'm not sure if we need this, given that the ATSUI backend does no caching(?)
-
-
- return CAIRO_STATUS_SUCCESS;
+ return noErr;
}
-cairo_font_t *
-cairo_atsui_font_create(ATSUStyle style)
-{
- cairo_font_scale_t scale;
- cairo_font_t *scaled;
- cairo_atsui_font_t *f = NULL;
-
-
- scaled = malloc(sizeof(cairo_font_t));
- if (scaled == NULL)
- return NULL;
-
-
- f = malloc(sizeof(cairo_atsui_font_t));
- if (f)
- {
- if (_cairo_unscaled_font_init(&f->base, &cairo_atsui_font_backend) == CAIRO_STATUS_SUCCESS)
- {
- f->style = style;
-
- _cairo_font_init(scaled, &scale, &f->base);
-
- return scaled;
- }
- }
-
-
- free(scaled);
-
-
- return NULL;
-}
+static cairo_status_t
+_cairo_atsui_font_glyph_path(void *abstract_font,
+ cairo_glyph_t *glyphs, int num_glyphs,
+ cairo_path_fixed_t *path)
+{
+ int i;
+ cairo_atsui_font_t *font = abstract_font;
+ OSStatus err;
+ cairo_ATSUI_glyph_path_callback_info_t info;
+ static ATSCubicMoveToUPP moveProc = NULL;
+ static ATSCubicLineToUPP lineProc = NULL;
+ static ATSCubicCurveToUPP curveProc = NULL;
+ static ATSCubicClosePathUPP closePathProc = NULL;
+ if (moveProc == NULL) {
+ moveProc = NewATSCubicMoveToUPP(MyATSCubicMoveToCallback);
+ lineProc = NewATSCubicLineToUPP(MyATSCubicLineToCallback);
+ curveProc = NewATSCubicCurveToUPP(MyATSCubicCurveToCallback);
+ closePathProc = NewATSCubicClosePathUPP(MyCubicClosePathProc);
+ }
-#pragma mark Backend
+ info.path = path;
+ for (i = 0; i < num_glyphs; i++) {
+ GlyphID theGlyph = glyphs[i].index;
-const cairo_font_backend_t cairo_atsui_font_backend = {
- _cairo_atsui_font_create,
- _cairo_atsui_font_destroy,
- _cairo_atsui_font_font_extents,
- _cairo_atsui_font_text_to_glyphs,
- _cairo_atsui_font_glyph_extents,
- _cairo_atsui_font_glyph_bbox,
- _cairo_atsui_font_show_glyphs,
- _cairo_atsui_font_glyph_path,
- _cairo_atsui_font_create_glyph
+ cairo_matrix_init(&info.scale,
+ 1.0, 0.0,
+ 0.0, 1.0, glyphs[i].x, glyphs[i].y);
+
+
+ err = ATSUGlyphGetCubicPaths(font->style,
+ theGlyph,
+ moveProc,
+ lineProc,
+ curveProc,
+ closePathProc, (void *) &info, &err);
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+
+const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend = {
+ _cairo_atsui_font_create,
+ _cairo_atsui_font_destroy_font,
+ _cairo_atsui_font_font_extents,
+ _cairo_atsui_font_text_to_glyphs,
+ _cairo_atsui_font_glyph_extents,
+ _cairo_atsui_font_glyph_bbox,
+ _cairo_atsui_font_show_glyphs,
+ _cairo_atsui_font_glyph_path,
+ _cairo_atsui_font_get_glyph_cache_key,
};
+
diff --git a/src/cairo-atsui.h b/src/cairo-atsui.h
index a5b7308f8..72e2d6d15 100644
--- a/src/cairo-atsui.h
+++ b/src/cairo-atsui.h
@@ -38,7 +38,7 @@
#include <cairo.h>
-#ifdef CAIRO_HAS_ATSUI_FONT
+#if CAIRO_HAS_ATSUI_FONT
/* ATSUI platform-specific font interface */
@@ -46,10 +46,10 @@
CAIRO_BEGIN_DECLS
-cairo_font_t *
-cairo_atsui_font_create(ATSUStyle style);
-
CAIRO_END_DECLS
+#else /* CAIRO_HAS_ATSUI_FONT */
+# error Cairo was not compiled with support for the atsui font backend
#endif /* CAIRO_HAS_ATSUI_FONT */
+
#endif /* CAIRO_ATSUI_H */
diff --git a/src/cairo-cache.c b/src/cairo-cache.c
index d1ad5a4e2..e95894960 100644
--- a/src/cairo-cache.c
+++ b/src/cairo-cache.c
@@ -113,7 +113,9 @@ static const cairo_cache_arrangement_t cache_arrangements [] = {
#define LIVE_ENTRY_P(cache, i) \
(!((NULL_ENTRY_P((cache),(i))) || (DEAD_ENTRY_P((cache),(i)))))
-#ifdef CAIRO_DO_SANITY_CHECKING
+#ifdef NDEBUG
+#define _cache_sane_state(c)
+#else
static void
_cache_sane_state (cairo_cache_t *cache)
{
@@ -125,8 +127,6 @@ _cache_sane_state (cairo_cache_t *cache)
/* assert (cache->used_memory <= cache->max_memory); */
assert (cache->live_entries <= cache->arrangement->size);
}
-#else
-#define _cache_sane_state(c)
#endif
static void
@@ -351,8 +351,9 @@ _cairo_cache_init (cairo_cache_t *cache,
#endif
cache->backend = backend;
- cache->entries = calloc (sizeof(cairo_cache_entry_base_t *),
- cache->arrangement->size);
+ cache->entries = calloc (cache->arrangement->size,
+ sizeof(cairo_cache_entry_base_t *));
+
if (cache->entries == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
diff --git a/src/cairo-color.c b/src/cairo-color.c
index f203d96cc..beb4a3474 100644
--- a/src/cairo-color.c
+++ b/src/cairo-color.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
@@ -36,62 +37,127 @@
#include "cairoint.h"
-static cairo_color_t const CAIRO_COLOR_WHITE = {
- 1.0, 1.0, 1.0, 1.0,
+static cairo_color_t const cairo_color_white = {
+ 1.0, 1.0, 1.0, 1.0,
0xffff, 0xffff, 0xffff, 0xffff
};
-static void
-_cairo_color_compute_shorts (cairo_color_t *color);
+static cairo_color_t const cairo_color_black = {
+ 0.0, 0.0, 0.0, 1.0,
+ 0x0, 0x0, 0x0, 0xffff
+};
+
+static cairo_color_t const cairo_color_transparent = {
+ 0.0, 0.0, 0.0, 0.0,
+ 0x0, 0x0, 0x0, 0x0
+};
+
+static cairo_color_t const cairo_color_magenta = {
+ 1.0, 0.0, 1.0, 1.0,
+ 0xffff, 0x0, 0xffff, 0xffff
+};
+
+const cairo_color_t *
+_cairo_stock_color (cairo_stock_t stock)
+{
+ switch (stock) {
+ case CAIRO_STOCK_WHITE:
+ return &cairo_color_white;
+ case CAIRO_STOCK_BLACK:
+ return &cairo_color_black;
+ case CAIRO_STOCK_TRANSPARENT:
+ return &cairo_color_transparent;
+ }
+
+ ASSERT_NOT_REACHED;
+
+ /* If the user can get here somehow, give a color that indicates a
+ * problem. */
+ return &cairo_color_magenta;
+}
void
_cairo_color_init (cairo_color_t *color)
{
- *color = CAIRO_COLOR_WHITE;
+ *color = cairo_color_white;
}
void
-_cairo_color_fini (cairo_color_t *color)
+_cairo_color_init_rgb (cairo_color_t *color,
+ double red, double green, double blue)
{
- /* Nothing to do here */
+ _cairo_color_init_rgba (color, red, green, blue, 1.0);
+}
+
+
+/* XXX: The calculation of:
+
+ channel * 0xffff
+
+ isn't really what we want since:
+
+ (1.0 - epsilon) * 0xffff = 0xfffe
+
+ In other words, given an input range of [0.0, 1.0], we have an
+ infinitely small range tha maps to the output value 0xffff,
+ (while having large, uniformly sized input ranges for all
+ other output values). This is undesirable, particularly when
+ we want to do optimizations for "opaque" colors specfied as
+ floating-point.
+*/
+static void
+_cairo_color_compute_shorts (cairo_color_t *color)
+{
+ color->red_short = color->red * color->alpha * 0xffff;
+ color->green_short = color->green * color->alpha * 0xffff;
+ color->blue_short = color->blue * color->alpha * 0xffff;
+ color->alpha_short = color->alpha * 0xffff;
}
void
-_cairo_color_set_rgb (cairo_color_t *color, double red, double green, double blue)
+_cairo_color_init_rgba (cairo_color_t *color,
+ double red, double green, double blue,
+ double alpha)
{
color->red = red;
color->green = green;
color->blue = blue;
+ color->alpha = alpha;
_cairo_color_compute_shorts (color);
}
void
-_cairo_color_get_rgb (const cairo_color_t *color,
- double *red, double *green, double *blue)
+_cairo_color_multiply_alpha (cairo_color_t *color,
+ double alpha)
{
- if (red)
- *red = color->red;
- if (green)
- *green = color->green;
- if (blue)
- *blue = color->blue;
+ color->alpha *= alpha;
+
+ _cairo_color_compute_shorts (color);
}
void
-_cairo_color_set_alpha (cairo_color_t *color, double alpha)
+_cairo_color_get_rgba (cairo_color_t *color,
+ double *red,
+ double *green,
+ double *blue,
+ double *alpha)
{
- color->alpha = alpha;
-
- _cairo_color_compute_shorts (color);
+ *red = color->red;
+ *green = color->green;
+ *blue = color->blue;
+ *alpha = color->alpha;
}
-static void
-_cairo_color_compute_shorts (cairo_color_t *color)
+void
+_cairo_color_get_rgba_premultiplied (cairo_color_t *color,
+ double *red,
+ double *green,
+ double *blue,
+ double *alpha)
{
- color->red_short = (color->red * color->alpha) * 0xffff;
- color->green_short = (color->green * color->alpha) * 0xffff;
- color->blue_short = (color->blue * color->alpha) * 0xffff;
- color->alpha_short = color->alpha * 0xffff;
+ *red = color->red * color->alpha;
+ *green = color->green * color->alpha;
+ *blue = color->blue * color->alpha;
+ *alpha = color->alpha;
}
-
diff --git a/src/cairo-features.h.in b/src/cairo-features.h.in
index a13250d97..8065be352 100644
--- a/src/cairo-features.h.in
+++ b/src/cairo-features.h.in
@@ -37,28 +37,26 @@
#ifndef CAIRO_FEATURES_H
#define CAIRO_FEATURES_H
-#define @PS_SURFACE_FEATURE@
+@PS_SURFACE_FEATURE@
-#define @PDF_SURFACE_FEATURE@
+@PDF_SURFACE_FEATURE@
-#define @PNG_SURFACE_FEATURE@
+@XLIB_SURFACE_FEATURE@
-#define @XLIB_SURFACE_FEATURE@
+@QUARTZ_SURFACE_FEATURE@
-#define @QUARTZ_SURFACE_FEATURE@
+@XCB_SURFACE_FEATURE@
-#define @XCB_SURFACE_FEATURE@
+@WIN32_SURFACE_FEATURE@
-#define @WIN32_SURFACE_FEATURE@
+@GLITZ_SURFACE_FEATURE@
-#define @GLITZ_SURFACE_FEATURE@
+@FT_FONT_FEATURE@
-#define @FT_FONT_FEATURE@
+@WIN32_FONT_FEATURE@
-#define @WIN32_FONT_FEATURE@
+@ATSUI_FONT_FEATURE@
-#define @ATSUI_FONT_FEATURE@
-
-#define @SANITY_CHECKING_FEATURE@
+@PNG_FUNCTIONS_FEATURE@
#endif
diff --git a/src/cairo-font.c b/src/cairo-font.c
index 529c1c7c3..3bd1e0318 100644
--- a/src/cairo-font.c
+++ b/src/cairo-font.c
@@ -39,185 +39,906 @@
#include "cairoint.h"
-/* Now the internal "unscaled + scale" font API */
+/* cairo_font_face_t */
-cairo_private cairo_status_t
-_cairo_font_create (const char *family,
- cairo_font_slant_t slant,
- cairo_font_weight_t weight,
- cairo_font_scale_t *sc,
- cairo_font_t **font)
+void
+_cairo_font_face_init (cairo_font_face_t *font_face,
+ const cairo_font_face_backend_t *backend)
{
- const cairo_font_backend_t *backend = CAIRO_FONT_BACKEND_DEFAULT;
+ font_face->refcount = 1;
+ font_face->backend = backend;
- return backend->create (family, slant, weight, sc, font);
+ _cairo_user_data_array_init (&font_face->user_data);
}
+/**
+ * cairo_font_face_reference:
+ * @font_face: a #cairo_font_face_t
+ *
+ * Increases the reference count on @font_face by one. This prevents
+ * @font_face from being destroyed until a matching call to cairo_font_face_destroy()
+ * is made.
+ **/
void
-_cairo_font_init (cairo_font_t *font,
- cairo_font_scale_t *scale,
- const cairo_font_backend_t *backend)
+cairo_font_face_reference (cairo_font_face_t *font_face)
{
- font->scale = *scale;
- font->refcount = 1;
- font->backend = backend;
+ font_face->refcount++;
}
+/**
+ * cairo_font_face_destroy:
+ * @font_face: a #cairo_font_face_t
+ *
+ * Decreases the reference count on @font_face by one. If the result
+ * is zero, then @font_face and all associated resources are freed.
+ * See cairo_font_face_reference().
+ **/
void
-_cairo_unscaled_font_init (cairo_unscaled_font_t *font,
- const cairo_font_backend_t *backend)
+cairo_font_face_destroy (cairo_font_face_t *font_face)
{
- font->refcount = 1;
- font->backend = backend;
+ if (--(font_face->refcount) > 0)
+ return;
+
+ font_face->backend->destroy (font_face);
+
+ /* We allow resurrection to deal with some memory management for the
+ * 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)
+ return;
+
+ _cairo_user_data_array_destroy (&font_face->user_data);
+
+ free (font_face);
}
+/**
+ * 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
+ * attached to
+ *
+ * Return user data previously attached to @font_face using the specified
+ * key. If no user data has been attached with the given key this
+ * function returns %NULL.
+ *
+ * Return value: the user data previously attached or %NULL.
+ **/
+void *
+cairo_font_face_get_user_data (cairo_font_face_t *font_face,
+ const cairo_user_data_key_t *key)
+{
+ return _cairo_user_data_array_get_data (&font_face->user_data,
+ key);
+}
+
+/**
+ * cairo_font_face_set_user_data:
+ * @font_face: a #cairo_font_face_t
+ * @key: the address of a #cairo_user_data_key_t to attach the user data to
+ * @user_data: the user data to attach to the font face
+ * @destroy: a #cairo_destroy_func_t which will be called when the
+ * font face is destroyed or when new user data is attached using the
+ * same key.
+ *
+ * Attach user data to @font_face. To remove user data from a font face,
+ * call this function with the key that was used to set it and %NULL
+ * for @data.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
+ * slot could not be allocated for the user data.
+ **/
cairo_status_t
-_cairo_font_text_to_glyphs (cairo_font_t *font,
- const unsigned char *utf8,
- cairo_glyph_t **glyphs,
- int *num_glyphs)
+cairo_font_face_set_user_data (cairo_font_face_t *font_face,
+ const cairo_user_data_key_t *key,
+ void *user_data,
+ cairo_destroy_func_t destroy)
+{
+ return _cairo_user_data_array_set_data (&font_face->user_data,
+ key, user_data, destroy);
+}
+
+/* cairo_simple_font_face_t - simple family/slant/weight font faces used for
+ * the built-in font API
+ */
+
+typedef struct _cairo_simple_font_face cairo_simple_font_face_t;
+
+struct _cairo_simple_font_face {
+ cairo_font_face_t base;
+ char *family;
+ cairo_font_slant_t slant;
+ cairo_font_weight_t weight;
+};
+
+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
+ * cairo_font_face_t => cairo_scaled_font_t works. For this reason, we don't need
+ * this cache to keep font faces alive; we just add them to the cache and
+ * remove them again when freed.
+ */
+
+typedef struct {
+ cairo_cache_entry_base_t base;
+ const char *family;
+ cairo_font_slant_t slant;
+ cairo_font_weight_t weight;
+} cairo_simple_cache_key_t;
+
+typedef struct {
+ cairo_simple_cache_key_t key;
+ cairo_simple_font_face_t *font_face;
+} cairo_simple_cache_entry_t;
+
+static const cairo_cache_backend_t _cairo_simple_font_cache_backend;
+
+static void
+_lock_global_simple_cache (void)
+{
+ /* FIXME: Perform locking here. */
+}
+
+static void
+_unlock_global_simple_cache (void)
{
- return font->backend->text_to_glyphs (font, utf8, glyphs, num_glyphs);
+ /* FIXME: Perform locking here. */
+}
+
+static cairo_cache_t *
+_get_global_simple_cache (void)
+{
+ static cairo_cache_t *global_simple_cache = NULL;
+
+ if (global_simple_cache == NULL)
+ {
+ global_simple_cache = malloc (sizeof (cairo_cache_t));
+ if (!global_simple_cache)
+ goto FAIL;
+
+ if (_cairo_cache_init (global_simple_cache,
+ &_cairo_simple_font_cache_backend,
+ 0)) /* No memory limit */
+ goto FAIL;
+ }
+ return global_simple_cache;
+
+ FAIL:
+ if (global_simple_cache)
+ free (global_simple_cache);
+ global_simple_cache = NULL;
+ return NULL;
+}
+
+static unsigned long
+_cairo_simple_font_cache_hash (void *cache, void *key)
+{
+ cairo_simple_cache_key_t *k = (cairo_simple_cache_key_t *) key;
+ unsigned long hash;
+
+ /* 1607 and 1451 are just a couple random primes. */
+ hash = _cairo_hash_string (k->family);
+ hash += ((unsigned long) k->slant) * 1607;
+ hash += ((unsigned long) k->weight) * 1451;
+
+ return hash;
+}
+
+static int
+_cairo_simple_font_cache_keys_equal (void *cache,
+ void *k1,
+ void *k2)
+{
+ cairo_simple_cache_key_t *a;
+ cairo_simple_cache_key_t *b;
+ a = (cairo_simple_cache_key_t *) k1;
+ b = (cairo_simple_cache_key_t *) k2;
+
+ return strcmp (a->family, b->family) == 0 &&
+ a->slant == b->slant &&
+ a->weight == b->weight;
+}
+
+static cairo_simple_font_face_t *
+_cairo_simple_font_face_create_from_cache_key (cairo_simple_cache_key_t *key)
+{
+ cairo_simple_font_face_t *simple_face;
+
+ simple_face = malloc (sizeof (cairo_simple_font_face_t));
+ if (!simple_face)
+ return NULL;
+
+ simple_face->family = strdup (key->family);
+ if (!simple_face->family) {
+ free (simple_face);
+ return NULL;
+ }
+
+ simple_face->slant = key->slant;
+ simple_face->weight = key->weight;
+
+ _cairo_font_face_init (&simple_face->base, &_cairo_simple_font_face_backend);
+
+ return simple_face;
+}
+
+static cairo_status_t
+_cairo_simple_font_cache_create_entry (void *cache,
+ void *key,
+ void **return_entry)
+{
+ cairo_simple_cache_key_t *k = (cairo_simple_cache_key_t *) key;
+ cairo_simple_cache_entry_t *entry;
+
+ entry = malloc (sizeof (cairo_simple_cache_entry_t));
+ if (entry == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ entry->font_face = _cairo_simple_font_face_create_from_cache_key (k);
+ if (!entry->font_face) {
+ free (entry);
+ return CAIRO_STATUS_NO_MEMORY;
+ }
+
+ entry->key.base.memory = 0;
+ entry->key.family = entry->font_face->family;
+ entry->key.slant = entry->font_face->slant;
+ entry->key.weight = entry->font_face->weight;
+
+ *return_entry = entry;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+/* Entries are never spontaneously destroyed; but only when
+ * we remove them from the cache specifically. We free entry->font_face
+ * in the code that removes the entry from the cache
+ */
+static void
+_cairo_simple_font_cache_destroy_entry (void *cache,
+ void *entry)
+{
+ cairo_simple_cache_entry_t *e = (cairo_simple_cache_entry_t *) entry;
+
+ free (e);
+}
+
+static void
+_cairo_simple_font_cache_destroy_cache (void *cache)
+{
+ free (cache);
+}
+
+static const cairo_cache_backend_t _cairo_simple_font_cache_backend = {
+ _cairo_simple_font_cache_hash,
+ _cairo_simple_font_cache_keys_equal,
+ _cairo_simple_font_cache_create_entry,
+ _cairo_simple_font_cache_destroy_entry,
+ _cairo_simple_font_cache_destroy_cache
+};
+
+static void
+_cairo_simple_font_face_destroy (void *abstract_face)
+{
+ cairo_simple_font_face_t *simple_face = abstract_face;
+ cairo_cache_t *cache;
+ cairo_simple_cache_key_t key;
+
+ _lock_global_simple_cache ();
+ cache = _get_global_simple_cache ();
+ assert (cache);
+
+ key.family = simple_face->family;
+ key.slant = simple_face->slant;
+ key.weight = simple_face->weight;
+
+ _cairo_cache_remove (cache, &key);
+
+ _unlock_global_simple_cache ();
+
+ free (simple_face->family);
+}
+
+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)
+{
+ const cairo_scaled_font_backend_t *backend = CAIRO_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);
+}
+
+static const cairo_font_face_backend_t _cairo_simple_font_face_backend = {
+ _cairo_simple_font_face_destroy,
+ _cairo_simple_font_face_create_font,
+};
+
+/**
+ * _cairo_simple_font_face_create:
+ * @family: a font family name, encoded in UTF-8
+ * @slant: the slant for the font
+ * @weight: the weight for the font
+ *
+ * Creates a font face from a triplet of family, slant, and weight.
+ * These font faces are used in implementation of the the #cairo_t "toy"
+ * font API.
+ *
+ * Return value: a newly created #cairo_font_face_t, destroy with
+ * cairo_font_face_destroy()
+ **/
+cairo_private cairo_font_face_t *
+_cairo_simple_font_face_create (const char *family,
+ cairo_font_slant_t slant,
+ cairo_font_weight_t weight)
+{
+ cairo_simple_cache_entry_t *entry;
+ cairo_simple_cache_key_t key;
+ cairo_cache_t *cache;
+ cairo_status_t status;
+ cairo_bool_t created_entry;
+
+ key.family = family;
+ key.slant = slant;
+ key.weight = weight;
+
+ _lock_global_simple_cache ();
+ cache = _get_global_simple_cache ();
+ if (cache == NULL) {
+ _unlock_global_simple_cache ();
+ return NULL;
+ }
+ status = _cairo_cache_lookup (cache, &key, (void **) &entry, &created_entry);
+ if (CAIRO_OK (status) && !created_entry)
+ cairo_font_face_reference (&entry->font_face->base);
+
+ _unlock_global_simple_cache ();
+ if (status)
+ return NULL;
+
+ return &entry->font_face->base;
+}
+
+/* cairo_scaled_font_t */
+
+/* Here we keep a cache from cairo_font_face_t/matrix/ctm => cairo_scaled_font_t.
+ *
+ * The implementation is messy because we want
+ *
+ * - All otherwise referenced cairo_scaled_font_t's to be in the cache
+ * - Some number of not otherwise referenced cairo_scaled_font_t's
+ *
+ * For this reason, we actually use *two* caches ... a finite size
+ * cache that references the cairo_scaled_font_t as a first level (the outer
+ * cache), then an infinite size cache as the second level (the inner
+ * cache). A single cache could be used at the cost of complicating
+ * cairo-cache.c
+ */
+
+/* This defines the size of the outer cache ... that is, the number
+ * of scaled fonts we keep around even when not otherwise referenced
+ */
+#define MAX_CACHED_FONTS 24
+
+typedef struct {
+ cairo_cache_entry_base_t base;
+ cairo_font_face_t *font_face;
+ const cairo_matrix_t *font_matrix;
+ const cairo_matrix_t *ctm;
+} cairo_font_cache_key_t;
+
+typedef struct {
+ cairo_font_cache_key_t key;
+ cairo_scaled_font_t *scaled_font;
+} cairo_font_cache_entry_t;
+
+static const cairo_cache_backend_t _cairo_outer_font_cache_backend;
+static const cairo_cache_backend_t _cairo_inner_font_cache_backend;
+
+static void
+_lock_global_font_cache (void)
+{
+ /* FIXME: Perform locking here. */
+}
+
+static void
+_unlock_global_font_cache (void)
+{
+ /* FIXME: Perform locking here. */
+}
+
+static cairo_cache_t *
+_get_outer_font_cache (void)
+{
+ static cairo_cache_t *outer_font_cache = NULL;
+
+ if (outer_font_cache == NULL)
+ {
+ outer_font_cache = malloc (sizeof (cairo_cache_t));
+ if (!outer_font_cache)
+ goto FAIL;
+
+ if (_cairo_cache_init (outer_font_cache,
+ &_cairo_outer_font_cache_backend,
+ MAX_CACHED_FONTS))
+ goto FAIL;
+ }
+ return outer_font_cache;
+
+ FAIL:
+ if (outer_font_cache)
+ free (outer_font_cache);
+ outer_font_cache = NULL;
+ return NULL;
+}
+
+static cairo_cache_t *
+_get_inner_font_cache (void)
+{
+ static cairo_cache_t *inner_font_cache = NULL;
+
+ if (inner_font_cache == NULL)
+ {
+ inner_font_cache = malloc (sizeof (cairo_cache_t));
+ if (!inner_font_cache)
+ goto FAIL;
+
+ if (_cairo_cache_init (inner_font_cache,
+ &_cairo_inner_font_cache_backend,
+ MAX_CACHED_FONTS))
+ goto FAIL;
+ }
+ return inner_font_cache;
+
+ FAIL:
+ if (inner_font_cache)
+ free (inner_font_cache);
+ inner_font_cache = NULL;
+ return NULL;
+}
+
+
+/* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/)
+ *
+ * Not necessarily better than a lot of other hashes, but should be OK, and
+ * well tested with binary data.
+ */
+
+#define FNV_32_PRIME ((uint32_t)0x01000193)
+#define FNV1_32_INIT ((uint32_t)0x811c9dc5)
+
+static uint32_t
+_hash_bytes_fnv (unsigned char *buffer,
+ int len,
+ uint32_t hval)
+{
+ while (len--) {
+ hval *= FNV_32_PRIME;
+ hval ^= *buffer++;
+ }
+
+ return hval;
+}
+static unsigned long
+_cairo_font_cache_hash (void *cache, void *key)
+{
+ cairo_font_cache_key_t *k = (cairo_font_cache_key_t *) key;
+ uint32_t hash = FNV1_32_INIT;
+
+ /* We do a bytewise hash on the font matrices */
+ hash = _hash_bytes_fnv ((unsigned char *)(&k->font_matrix->xx),
+ sizeof(double) * 4,
+ hash);
+ hash = _hash_bytes_fnv ((unsigned char *)(&k->ctm->xx),
+ sizeof(double) * 4,
+ hash);
+
+ return hash ^ (unsigned long)k->font_face;
+}
+
+static int
+_cairo_font_cache_keys_equal (void *cache,
+ void *k1,
+ void *k2)
+{
+ cairo_font_cache_key_t *a;
+ cairo_font_cache_key_t *b;
+ a = (cairo_font_cache_key_t *) k1;
+ b = (cairo_font_cache_key_t *) k2;
+
+ return (a->font_face == b->font_face &&
+ memcmp ((unsigned char *)(&a->font_matrix->xx),
+ (unsigned char *)(&b->font_matrix->xx),
+ sizeof(double) * 4) == 0 &&
+ memcmp ((unsigned char *)(&a->ctm->xx),
+ (unsigned char *)(&b->ctm->xx),
+ sizeof(double) * 4) == 0);
+}
+
+/* The cache lookup failed in the outer cache, so we pull
+ * the font from the inner cache (if that in turns fails,
+ * it will create the font
+ */
+static cairo_status_t
+_cairo_outer_font_cache_create_entry (void *cache,
+ void *key,
+ void **return_entry)
+{
+ cairo_font_cache_entry_t *entry;
+ cairo_font_cache_entry_t *inner_entry;
+ cairo_bool_t created_entry;
+ cairo_status_t status;
+
+ entry = malloc (sizeof (cairo_font_cache_entry_t));
+ if (entry == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ cache = _get_inner_font_cache ();
+ if (cache == NULL) {
+ _unlock_global_font_cache ();
+ return CAIRO_STATUS_NO_MEMORY;
+ }
+
+ status = _cairo_cache_lookup (cache, key, (void **) &inner_entry, &created_entry);
+ if (!CAIRO_OK (status)) {
+ free (entry);
+ return status;
+ }
+
+ entry->scaled_font = inner_entry->scaled_font;
+ if (!created_entry)
+ cairo_scaled_font_reference (entry->scaled_font);
+
+ entry->key.base.memory = 1;
+ 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;
+
+ *return_entry = entry;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_outer_font_cache_destroy_entry (void *cache,
+ void *entry)
+{
+ cairo_font_cache_entry_t *e = (cairo_font_cache_entry_t *) entry;
+
+ cairo_scaled_font_destroy (e->scaled_font);
+
+ free (e);
+}
+
+/* Called when the lookup fails in the inner cache as well; there
+ * is no existing font, so we have to create one.
+ */
+static cairo_status_t
+_cairo_inner_font_cache_create_entry (void *cache,
+ void *key,
+ void **return_entry)
+{
+ cairo_font_cache_key_t *k = (cairo_font_cache_key_t *) key;
+ cairo_font_cache_entry_t *entry;
+ cairo_status_t status;
+
+ entry = malloc (sizeof (cairo_font_cache_entry_t));
+ if (entry == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ status = k->font_face->backend->create_font (k->font_face,
+ k->font_matrix,
+ k->ctm,
+ &entry->scaled_font);
+ if (!CAIRO_OK (status)) {
+ free (entry);
+ return status;
+ }
+
+ entry->scaled_font->font_face = k->font_face;
+ cairo_font_face_reference (k->font_face);
+
+ entry->key.base.memory = 0;
+ entry->key.font_face = k->font_face;
+ entry->key.font_matrix = &entry->scaled_font->font_matrix;
+ entry->key.ctm = &entry->scaled_font->ctm;
+
+ *return_entry = entry;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+/* Entries in the inner font cache are never spontaneously destroyed;
+ * but only when we remove them from the cache specifically. We free
+ * entry->scaled_font in the code that removes the entry from the cache
+ */
+static void
+_cairo_inner_font_cache_destroy_entry (void *cache,
+ void *entry)
+{
+ free (entry);
+}
+
+static void
+_cairo_font_cache_destroy_cache (void *cache)
+{
+ free (cache);
+}
+
+static const cairo_cache_backend_t _cairo_outer_font_cache_backend = {
+ _cairo_font_cache_hash,
+ _cairo_font_cache_keys_equal,
+ _cairo_outer_font_cache_create_entry,
+ _cairo_outer_font_cache_destroy_entry,
+ _cairo_font_cache_destroy_cache
+};
+
+static const cairo_cache_backend_t _cairo_inner_font_cache_backend = {
+ _cairo_font_cache_hash,
+ _cairo_font_cache_keys_equal,
+ _cairo_inner_font_cache_create_entry,
+ _cairo_inner_font_cache_destroy_entry,
+ _cairo_font_cache_destroy_cache
+};
+
+/**
+ * cairo_scaled_font_create:
+ * @font_face: a #cairo_font_face_t
+ * @font_matrix: font space to user space transformation matrix for the
+ * font. In the simplest case of a N point font, this matrix is
+ * just a scale by N, but it can also be used to shear the font
+ * or stretch it unequally along the two axes. See
+ * cairo_set_font_matrix().
+ * @ctm: user to device transformation matrix with which the font will
+ * be used.
+ *
+ * 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
+ * be used.
+ *
+ * Return value: a newly created #cairo_scaled_font_t. Destroy with
+ * 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_font_cache_entry_t *entry;
+ cairo_font_cache_key_t key;
+ cairo_cache_t *cache;
+ cairo_status_t status;
+
+ key.font_face = font_face;
+ key.font_matrix = font_matrix;
+ key.ctm = ctm;
+
+ _lock_global_font_cache ();
+ cache = _get_outer_font_cache ();
+ if (cache == NULL) {
+ _unlock_global_font_cache ();
+ return NULL;
+ }
+
+ status = _cairo_cache_lookup (cache, &key, (void **) &entry, NULL);
+ if (CAIRO_OK (status))
+ cairo_scaled_font_reference (entry->scaled_font);
+
+ _unlock_global_font_cache ();
+ if (!CAIRO_OK (status))
+ return NULL;
+
+ return entry->scaled_font;
+}
+
+void
+_cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ const cairo_scaled_font_backend_t *backend)
+{
+ 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->backend = backend;
}
cairo_status_t
-_cairo_font_glyph_extents (cairo_font_t *font,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_text_extents_t *extents)
+_cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
+ const char *utf8,
+ cairo_glyph_t **glyphs,
+ int *num_glyphs)
{
- return font->backend->glyph_extents(font, glyphs, num_glyphs, extents);
+ return scaled_font->backend->text_to_glyphs (scaled_font, utf8, glyphs, num_glyphs);
+}
+
+cairo_status_t
+_cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_text_extents_t *extents)
+{
+ return scaled_font->backend->glyph_extents (scaled_font, glyphs, num_glyphs, extents);
}
cairo_status_t
-_cairo_font_glyph_bbox (cairo_font_t *font,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_box_t *bbox)
+_cairo_scaled_font_glyph_bbox (cairo_scaled_font_t *scaled_font,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_box_t *bbox)
{
- return font->backend->glyph_bbox (font, glyphs, num_glyphs, bbox);
+ return scaled_font->backend->glyph_bbox (scaled_font, glyphs, num_glyphs, bbox);
}
cairo_status_t
-_cairo_font_show_glyphs (cairo_font_t *font,
- cairo_operator_t operator,
- cairo_pattern_t *pattern,
- cairo_surface_t *surface,
- int source_x,
- int source_y,
- int dest_x,
- int dest_y,
- unsigned int width,
- unsigned int height,
- cairo_glyph_t *glyphs,
- int num_glyphs)
+_cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
+ cairo_operator_t operator,
+ cairo_pattern_t *pattern,
+ cairo_surface_t *surface,
+ int source_x,
+ int source_y,
+ int dest_x,
+ int dest_y,
+ unsigned int width,
+ unsigned int height,
+ cairo_glyph_t *glyphs,
+ int num_glyphs)
{
cairo_status_t status;
- if (surface->backend->show_glyphs != NULL) {
- status = surface->backend->show_glyphs (font, operator, pattern,
- surface,
- source_x, source_y,
- dest_x, dest_y,
- width, height,
- glyphs, num_glyphs);
- if (status == CAIRO_STATUS_SUCCESS)
- return status;
- }
+
+ status = _cairo_surface_show_glyphs (scaled_font, operator, pattern,
+ surface,
+ source_x, source_y,
+ dest_x, dest_y,
+ width, height,
+ glyphs, num_glyphs);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
/* Surface display routine either does not exist or failed. */
- return font->backend->show_glyphs (font, operator, pattern,
- surface,
- source_x, source_y,
- dest_x, dest_y,
- width, height,
- glyphs, num_glyphs);
+ return scaled_font->backend->show_glyphs (scaled_font, operator, pattern,
+ surface,
+ source_x, source_y,
+ dest_x, dest_y,
+ width, height,
+ glyphs, num_glyphs);
}
cairo_status_t
-_cairo_font_glyph_path (cairo_font_t *font,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_path_t *path)
+_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_path_fixed_t *path)
{
- return font->backend->glyph_path (font, glyphs, num_glyphs, path);
+ return scaled_font->backend->glyph_path (scaled_font, glyphs, num_glyphs, path);
}
void
-_cairo_font_get_glyph_cache_key (cairo_font_t *font,
- cairo_glyph_cache_key_t *key)
+_cairo_scaled_font_get_glyph_cache_key (cairo_scaled_font_t *scaled_font,
+ cairo_glyph_cache_key_t *key)
{
- font->backend->get_glyph_cache_key (font, key);
+ scaled_font->backend->get_glyph_cache_key (scaled_font, key);
}
cairo_status_t
-_cairo_font_font_extents (cairo_font_t *font,
- cairo_font_extents_t *extents)
+_cairo_scaled_font_font_extents (cairo_scaled_font_t *scaled_font,
+ cairo_font_extents_t *extents)
{
- return font->backend->font_extents (font, extents);
+ return scaled_font->backend->font_extents (scaled_font, extents);
}
void
-_cairo_unscaled_font_reference (cairo_unscaled_font_t *font)
+_cairo_unscaled_font_init (cairo_unscaled_font_t *unscaled_font,
+ const cairo_unscaled_font_backend_t *backend)
{
- font->refcount++;
+ unscaled_font->refcount = 1;
+ unscaled_font->backend = backend;
}
void
-_cairo_unscaled_font_destroy (cairo_unscaled_font_t *font)
+_cairo_unscaled_font_reference (cairo_unscaled_font_t *unscaled_font)
+{
+ unscaled_font->refcount++;
+}
+
+void
+_cairo_unscaled_font_destroy (cairo_unscaled_font_t *unscaled_font)
{
- if (--(font->refcount) > 0)
+ if (--(unscaled_font->refcount) > 0)
return;
- font->backend->destroy_unscaled_font (font);
+ unscaled_font->backend->destroy (unscaled_font);
+
+ free (unscaled_font);
}
/* Public font API follows. */
+/**
+ * cairo_scaled_font_reference:
+ * @scaled_font: a #cairo_scaled_font_t
+ *
+ * Increases the reference count on @scaled_font by one. This prevents
+ * @scaled_font from being destroyed until a matching call to
+ * cairo_scaled_font_destroy() is made.
+ **/
void
-cairo_font_reference (cairo_font_t *font)
+cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font)
{
- font->refcount++;
+ scaled_font->refcount++;
}
+/**
+ * cairo_scaled_font_destroy:
+ * @scaled_font: a #cairo_scaled_font_t
+ *
+ * Decreases the reference count on @font by one. If the result
+ * is zero, then @font and all associated resources are freed.
+ * See cairo_scaled_font_reference().
+ **/
void
-cairo_font_destroy (cairo_font_t *font)
+cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
{
- if (--(font->refcount) > 0)
+ cairo_font_cache_key_t key;
+ cairo_cache_t *cache;
+
+ if (--(scaled_font->refcount) > 0)
return;
- font->backend->destroy_font (font);
+ if (scaled_font->font_face) {
+ _lock_global_font_cache ();
+ cache = _get_inner_font_cache ();
+ assert (cache);
+
+ key.font_face = scaled_font->font_face;
+ key.font_matrix = &scaled_font->font_matrix;
+ key.ctm = &scaled_font->ctm;
+
+ _cairo_cache_remove (cache, &key);
+ _unlock_global_font_cache ();
+
+ cairo_font_face_destroy (scaled_font->font_face);
+ }
+
+ scaled_font->backend->destroy (scaled_font);
+
+ free (scaled_font);
}
/**
- * cairo_font_extents:
- * @font: a #cairo_font_t
- * @font_matrix: the font transformation for which this font was
- * created. (See cairo_transform_font()). This is needed
- * properly convert the metrics from the font into user space.
+ * cairo_scaled_font_extents:
+ * @scaled_font: a #cairo_scaled_font_t
* @extents: a #cairo_font_extents_t which to store the retrieved extents.
*
- * Gets the metrics for a #cairo_font_t.
+ * Gets the metrics for a #cairo_scaled_font_t.
*
* Return value: %CAIRO_STATUS_SUCCESS on success. Otherwise, an
* error such as %CAIRO_STATUS_NO_MEMORY.
**/
cairo_status_t
-cairo_font_extents (cairo_font_t *font,
- cairo_matrix_t *font_matrix,
- cairo_font_extents_t *extents)
+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;
- status = _cairo_font_font_extents (font, extents);
+ status = _cairo_scaled_font_font_extents (scaled_font, extents);
if (!CAIRO_OK (status))
return status;
- _cairo_matrix_compute_scale_factors (font_matrix,
+ _cairo_matrix_compute_scale_factors (&scaled_font->font_matrix,
&font_scale_x, &font_scale_y,
/* XXX */ 1);
@@ -237,10 +958,7 @@ cairo_font_extents (cairo_font_t *font,
/**
* cairo_font_glyph_extents:
- * @font: a #cairo_font_t
- * @font_matrix: the font transformation for which this font was
- * created. (See cairo_transform_font()). This is needed
- * properly convert the metrics from the font into user space.
+ * @scaled_font: a #cairo_scaled_font_t
* @glyphs: an array of glyph IDs with X and Y offsets.
* @num_glyphs: the number of glyphs in the @glyphs array
* @extents: a #cairo_text_extents_t which to store the retrieved extents.
@@ -249,11 +967,10 @@ cairo_font_extents (cairo_font_t *font,
* glyphs. The X and Y offsets in @glyphs are taken from an origin of 0,0.
**/
void
-cairo_font_glyph_extents (cairo_font_t *font,
- cairo_matrix_t *font_matrix,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_text_extents_t *extents)
+cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_text_extents_t *extents)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_glyph_t origin_glyph;
@@ -283,9 +1000,9 @@ cairo_font_glyph_extents (cairo_font_t *font,
origin_glyph = glyphs[i];
origin_glyph.x = 0.0;
origin_glyph.y = 0.0;
- status = _cairo_font_glyph_extents (font,
- &origin_glyph, 1,
- &origin_extents);
+ status = _cairo_scaled_font_glyph_extents (scaled_font,
+ &origin_glyph, 1,
+ &origin_extents);
/*
* Transform font space metrics into user space metrics
@@ -294,7 +1011,7 @@ cairo_font_glyph_extents (cairo_font_t *font,
*/
x = origin_extents.x_bearing;
y = origin_extents.y_bearing;
- cairo_matrix_transform_point (font_matrix,
+ cairo_matrix_transform_point (&scaled_font->font_matrix,
&x, &y);
for (hm = 0.0; hm <= 1.0; hm += 1.0)
@@ -302,7 +1019,7 @@ cairo_font_glyph_extents (cairo_font_t *font,
{
x = origin_extents.x_bearing + origin_extents.width * wm;
y = origin_extents.y_bearing + origin_extents.height * hm;
- cairo_matrix_transform_point (font_matrix,
+ cairo_matrix_transform_point (&scaled_font->font_matrix,
&x, &y);
x += glyphs[i].x;
y += glyphs[i].y;
@@ -323,7 +1040,7 @@ cairo_font_glyph_extents (cairo_font_t *font,
x = origin_extents.x_advance;
y = origin_extents.y_advance;
- cairo_matrix_transform_point (font_matrix,
+ cairo_matrix_transform_point (&scaled_font->font_matrix,
&x, &y);
x_pos = glyphs[i].x + x;
y_pos = glyphs[i].y + y;
@@ -348,10 +1065,10 @@ _cairo_glyph_cache_hash (void *cache, void *key)
in = (cairo_glyph_cache_key_t *) key;
return
((unsigned long) in->unscaled)
- ^ ((unsigned long) in->scale.matrix[0][0])
- ^ ((unsigned long) in->scale.matrix[0][1])
- ^ ((unsigned long) in->scale.matrix[1][0])
- ^ ((unsigned long) in->scale.matrix[1][1])
+ ^ ((unsigned long) in->scale.xx)
+ ^ ((unsigned long) in->scale.yx)
+ ^ ((unsigned long) in->scale.xy)
+ ^ ((unsigned long) in->scale.yy)
^ (in->flags * 1451) /* 1451 is just an abitrary prime */
^ in->index;
}
@@ -367,10 +1084,10 @@ _cairo_glyph_cache_keys_equal (void *cache,
return (a->index == b->index)
&& (a->unscaled == b->unscaled)
&& (a->flags == b->flags)
- && (a->scale.matrix[0][0] == b->scale.matrix[0][0])
- && (a->scale.matrix[0][1] == b->scale.matrix[0][1])
- && (a->scale.matrix[1][0] == b->scale.matrix[1][0])
- && (a->scale.matrix[1][1] == b->scale.matrix[1][1]);
+ && (a->scale.xx == b->scale.xx)
+ && (a->scale.yx == b->scale.yx)
+ && (a->scale.xy == b->scale.xy)
+ && (a->scale.yy == b->scale.yy);
}
@@ -388,7 +1105,8 @@ _image_glyph_cache_create_entry (void *cache,
return CAIRO_STATUS_NO_MEMORY;
im->key = *k;
- status = im->key.unscaled->backend->create_glyph (im);
+ status = im->key.unscaled->backend->create_glyph (im->key.unscaled,
+ im);
if (status != CAIRO_STATUS_SUCCESS) {
free (im);
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 44e1b0e84..c02cd61e5 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -66,31 +66,42 @@ typedef struct {
/*
* We create an object that corresponds to a single font on the disk;
* (identified by a filename/id pair) these are shared between all
- * fonts using that file. For cairo_ft_font_create_for_ft_face(), we
+ * fonts using that file. For cairo_ft_scaled_font_create_for_ft_face(), we
* just create a one-off version with a permanent face value.
*/
+
+typedef struct _ft_font_face ft_font_face_t;
+
typedef struct {
cairo_unscaled_font_t base;
- int from_face; /* from cairo_ft_font_create_for_ft_face()? */
- FT_Face face; /* provided or cached face */
+ cairo_bool_t from_face; /* from cairo_ft_scaled_font_create_for_ft_face()? */
+ FT_Face face; /* provided or cached face */
/* only set if from_face is false */
- FT_Library library;
char *filename;
int id;
/* We temporarily scale the unscaled font as neede */
int have_scale;
- cairo_font_scale_t current_scale;
+ cairo_matrix_t current_scale;
double x_scale; /* Extracted X scale factor */
double y_scale; /* Extracted Y scale factor */
int lock; /* count of how many times this font has been locked */
+
+ ft_font_face_t *faces; /* Linked list of faces for this font */
} ft_unscaled_font_t;
-const cairo_font_backend_t cairo_ft_font_backend;
+struct _ft_font_face {
+ cairo_font_face_t base;
+ ft_unscaled_font_t *unscaled;
+ int load_flags;
+ ft_font_face_t *next_face;
+};
+
+const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend;
static ft_unscaled_font_t *
_ft_unscaled_font_create_from_face (FT_Face face)
@@ -102,21 +113,21 @@ _ft_unscaled_font_create_from_face (FT_Face face)
unscaled->from_face = 1;
unscaled->face = face;
- unscaled->library = NULL;
unscaled->filename = NULL;
unscaled->id = 0;
unscaled->have_scale = 0;
unscaled->lock = 0;
- _cairo_unscaled_font_init ((cairo_unscaled_font_t *)unscaled,
- &cairo_ft_font_backend);
+ unscaled->faces = NULL;
+
+ _cairo_unscaled_font_init (&unscaled->base,
+ &cairo_ft_unscaled_font_backend);
return unscaled;
}
static ft_unscaled_font_t *
-_ft_unscaled_font_create_from_filename (FT_Library library,
- const char *filename,
+_ft_unscaled_font_create_from_filename (const char *filename,
int id)
{
ft_unscaled_font_t *unscaled;
@@ -135,15 +146,16 @@ _ft_unscaled_font_create_from_filename (FT_Library library,
unscaled->from_face = 0;
unscaled->face = NULL;
- unscaled->library = library;
unscaled->filename = new_filename;
unscaled->id = id;
unscaled->have_scale = 0;
unscaled->lock = 0;
- _cairo_unscaled_font_init ((cairo_unscaled_font_t *)unscaled,
- &cairo_ft_font_backend);
+ unscaled->faces = NULL;
+
+ _cairo_unscaled_font_init (&unscaled->base,
+ &cairo_ft_unscaled_font_backend);
return unscaled;
}
@@ -204,7 +216,6 @@ _ft_font_cache_create_entry (void *cache,
void *key,
void **return_entry)
{
- ft_cache_t *ftcache = (ft_cache_t *) cache;
cairo_ft_cache_key_t *k = (cairo_ft_cache_key_t *) key;
cairo_ft_cache_entry_t *entry;
@@ -212,8 +223,7 @@ _ft_font_cache_create_entry (void *cache,
if (entry == NULL)
return CAIRO_STATUS_NO_MEMORY;
- entry->unscaled = _ft_unscaled_font_create_from_filename (ftcache->lib,
- k->filename,
+ entry->unscaled = _ft_unscaled_font_create_from_filename (k->filename,
k->id);
if (!entry->unscaled) {
free (entry);
@@ -327,13 +337,13 @@ _ft_unscaled_font_get_for_pattern (FcPattern *pattern)
}
status = _cairo_cache_lookup (cache, &key, (void **) &entry, &created_entry);
+ if (CAIRO_OK (status) && !created_entry)
+ _cairo_unscaled_font_reference (&entry->unscaled->base);
+
_unlock_global_ft_cache ();
- if (status)
+ if (!CAIRO_OK (status))
return NULL;
- if (!created_entry)
- _cairo_unscaled_font_reference ((cairo_unscaled_font_t *)entry->unscaled);
-
return entry->unscaled;
}
@@ -406,9 +416,9 @@ _ft_unscaled_font_unlock_face (ft_unscaled_font_t *unscaled)
static void
_compute_transform (ft_font_transform_t *sf,
- cairo_font_scale_t *sc)
+ cairo_matrix_t *scale)
{
- cairo_matrix_t normalized;
+ cairo_matrix_t normalized = *scale;
double tx, ty;
/* The font matrix has x and y "scale" components which we extract and
@@ -418,21 +428,14 @@ _compute_transform (ft_font_transform_t *sf,
* freetype's transformation.
*/
- cairo_matrix_set_affine (&normalized,
- sc->matrix[0][0],
- sc->matrix[0][1],
- sc->matrix[1][0],
- sc->matrix[1][1],
- 0, 0);
-
_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);
+ _cairo_matrix_get_affine (&normalized,
+ &sf->shape[0][0], &sf->shape[0][1],
+ &sf->shape[1][0], &sf->shape[1][1],
+ &tx, &ty);
}
/* Temporarily scales an unscaled font to the give scale. We catch
@@ -440,7 +443,7 @@ _compute_transform (ft_font_transform_t *sf,
*/
static void
_ft_unscaled_font_set_scale (ft_unscaled_font_t *unscaled,
- cairo_font_scale_t *scale)
+ cairo_matrix_t *scale)
{
ft_font_transform_t sf;
FT_Matrix mat;
@@ -448,10 +451,10 @@ _ft_unscaled_font_set_scale (ft_unscaled_font_t *unscaled,
assert (unscaled->face != NULL);
if (unscaled->have_scale &&
- scale->matrix[0][0] == unscaled->current_scale.matrix[0][0] &&
- scale->matrix[0][1] == unscaled->current_scale.matrix[0][1] &&
- scale->matrix[1][0] == unscaled->current_scale.matrix[1][0] &&
- scale->matrix[1][1] == unscaled->current_scale.matrix[1][1])
+ scale->xx == unscaled->current_scale.xx &&
+ scale->yx == unscaled->current_scale.yx &&
+ scale->xy == unscaled->current_scale.xy &&
+ scale->yy == unscaled->current_scale.yy)
return;
unscaled->have_scale = 1;
@@ -474,14 +477,172 @@ _ft_unscaled_font_set_scale (ft_unscaled_font_t *unscaled,
(FT_UInt) sf.y_scale);
}
-/* implement the font backend interface */
+static void
+_cairo_ft_unscaled_font_destroy (void *abstract_font)
+{
+ ft_unscaled_font_t *unscaled = abstract_font;
+
+ if (unscaled->from_face) {
+ /* See comments in _ft_font_face_destroy about the "zombie" state
+ * for a _ft_font_face.
+ */
+ if (unscaled->faces && !unscaled->faces->unscaled)
+ cairo_font_face_destroy (&unscaled->faces->base);
+ } else {
+ cairo_cache_t *cache;
+ cairo_ft_cache_key_t key;
+
+ _lock_global_ft_cache ();
+ cache = _get_global_ft_cache ();
+ assert (cache);
+
+ key.filename = unscaled->filename;
+ key.id = unscaled->id;
+
+ _cairo_cache_remove (cache, &key);
+
+ _unlock_global_ft_cache ();
+
+ if (unscaled->filename)
+ free (unscaled->filename);
+
+ if (unscaled->face)
+ FT_Done_Face (unscaled->face);
+ }
+}
+
+static cairo_status_t
+_cairo_ft_unscaled_font_create_glyph (void *abstract_font,
+ cairo_image_glyph_cache_entry_t *val)
+{
+ ft_unscaled_font_t *unscaled = abstract_font;
+ FT_GlyphSlot glyphslot;
+ unsigned int width, height, stride;
+ FT_Face face;
+ FT_Outline *outline;
+ FT_BBox cbox;
+ FT_Bitmap bitmap;
+ FT_Glyph_Metrics *metrics;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+ face = _ft_unscaled_font_lock_face (unscaled);
+ if (!face)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ glyphslot = face->glyph;
+ metrics = &glyphslot->metrics;
+
+ _ft_unscaled_font_set_scale (unscaled, &val->key.scale);
+
+ if (FT_Load_Glyph (face, val->key.index, val->key.flags) != 0) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto FAIL;
+ }
+
+ /*
+ * 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
+ */
+
+ 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;
+
+ outline = &glyphslot->outline;
+
+ FT_Outline_Get_CBox (outline, &cbox);
+
+ cbox.xMin &= -64;
+ 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;
+
+ if (width * height == 0)
+ val->image = NULL;
+ else
+ {
+
+ bitmap.pixel_mode = ft_pixel_mode_grays;
+ bitmap.num_grays = 256;
+ bitmap.width = width;
+ bitmap.rows = height;
+ bitmap.pitch = stride;
+ bitmap.buffer = calloc (1, stride * height);
+
+ if (bitmap.buffer == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto FAIL;
+ }
+
+ FT_Outline_Translate (outline, -cbox.xMin, -cbox.yMin);
+
+ if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
+ free (bitmap.buffer);
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto FAIL;
+ }
+
+ 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);
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto FAIL;
+ }
+
+ _cairo_image_surface_assume_ownership_of_data (val->image);
+ }
+
+ /*
+ * Note: the font's coordinate system is upside down from ours, so the
+ * 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);
+
+ FAIL:
+ _ft_unscaled_font_unlock_face (unscaled);
+
+ return status;
+}
+
+const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend = {
+ _cairo_ft_unscaled_font_destroy,
+ _cairo_ft_unscaled_font_create_glyph
+};
+
+/* cairo_ft_scaled_font_t */
typedef struct {
- cairo_font_t base;
- FcPattern *pattern;
+ cairo_scaled_font_t base;
int load_flags;
ft_unscaled_font_t *unscaled;
-} cairo_ft_font_t;
+} 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
@@ -547,51 +708,43 @@ _get_load_flags (FcPattern *pattern)
return load_flags;
}
-/* Like the public cairo_ft_font_create, but takes a cairo_font_scale_t,
- * rather than a cairo_font_t
- */
-static cairo_font_t *
-_ft_font_create (FcPattern *pattern,
- cairo_font_scale_t *scale)
+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)
{
- cairo_ft_font_t *f = NULL;
- ft_unscaled_font_t *unscaled = NULL;
+ cairo_ft_scaled_font_t *f = NULL;
- unscaled = _ft_unscaled_font_get_for_pattern (pattern);
- if (unscaled == NULL)
- return NULL;
-
- f = malloc (sizeof(cairo_ft_font_t));
+ f = malloc (sizeof(cairo_ft_scaled_font_t));
if (f == NULL)
- goto FREE_UNSCALED;
+ return NULL;
f->unscaled = unscaled;
- f->pattern = pattern;
- FcPatternReference (pattern);
- f->load_flags = _get_load_flags (pattern);
-
- _cairo_font_init ((cairo_font_t *)f, scale, &cairo_ft_font_backend);
-
- return (cairo_font_t *)f;
+ _cairo_unscaled_font_reference (&unscaled->base);
+
+ f->load_flags = load_flags;
- FREE_UNSCALED:
- _cairo_unscaled_font_destroy ((cairo_unscaled_font_t *)unscaled);
+ _cairo_scaled_font_init (&f->base, font_matrix, ctm, &cairo_ft_scaled_font_backend);
- return NULL;
+ return (cairo_scaled_font_t *)f;
}
static cairo_status_t
-_cairo_ft_font_create (const char *family,
- cairo_font_slant_t slant,
- cairo_font_weight_t weight,
- cairo_font_scale_t *scale,
- cairo_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,
+ cairo_scaled_font_t **font)
{
FcPattern *pattern, *resolved;
- cairo_font_t *new_font;
+ ft_unscaled_font_t *unscaled;
+ cairo_scaled_font_t *new_font;
FcResult result;
int fcslant;
int fcweight;
+ cairo_matrix_t scale;
ft_font_transform_t sf;
pattern = FcPatternCreate ();
@@ -623,14 +776,15 @@ _cairo_ft_font_create (const char *family,
break;
}
- if (!FcPatternAddString (pattern, FC_FAMILY, family))
+ if (!FcPatternAddString (pattern, FC_FAMILY, (unsigned char *) family))
goto FREE_PATTERN;
if (!FcPatternAddInteger (pattern, FC_SLANT, fcslant))
goto FREE_PATTERN;
if (!FcPatternAddInteger (pattern, FC_WEIGHT, fcweight))
goto FREE_PATTERN;
- _compute_transform (&sf, scale);
+ cairo_matrix_multiply (&scale, font_matrix, ctm);
+ _compute_transform (&sf, &scale);
FcPatternAddInteger (pattern, FC_PIXEL_SIZE, sf.y_scale);
@@ -641,7 +795,13 @@ _cairo_ft_font_create (const char *family,
if (!resolved)
goto FREE_PATTERN;
- new_font = _ft_font_create (resolved, scale);
+ unscaled = _ft_unscaled_font_get_for_pattern (resolved);
+ if (!unscaled)
+ goto FREE_RESOLVED;
+
+ new_font = _ft_scaled_font_create (unscaled, _get_load_flags (pattern),
+ font_matrix, ctm);
+ _cairo_unscaled_font_destroy (&unscaled->base);
FcPatternDestroy (resolved);
FcPatternDestroy (pattern);
@@ -653,6 +813,9 @@ _cairo_ft_font_create (const char *family,
return CAIRO_STATUS_NO_MEMORY; /* A guess */
}
+ FREE_RESOLVED:
+ FcPatternDestroy (resolved);
+
FREE_PATTERN:
FcPatternDestroy (pattern);
@@ -660,88 +823,50 @@ _cairo_ft_font_create (const char *family,
}
static void
-_cairo_ft_font_destroy_font (void *abstract_font)
+_cairo_ft_scaled_font_destroy (void *abstract_font)
{
- cairo_ft_font_t * font = abstract_font;
+ cairo_ft_scaled_font_t *scaled_font = abstract_font;
- if (font == NULL)
+ if (scaled_font == NULL)
return;
- if (font->pattern != NULL)
- FcPatternDestroy (font->pattern);
-
- _cairo_unscaled_font_destroy ((cairo_unscaled_font_t *)font->unscaled);
-
- free (font);
-}
-
-static void
-_cairo_ft_font_destroy_unscaled_font (void *abstract_font)
-{
- ft_unscaled_font_t *unscaled = abstract_font;
-
- if (!unscaled->from_face) {
- cairo_cache_t *cache;
- cairo_ft_cache_key_t key;
-
- _lock_global_ft_cache ();
- cache = _get_global_ft_cache ();
- assert (cache);
-
- key.filename = unscaled->filename;
- key.id = unscaled->id;
-
- _cairo_cache_remove (cache, &key);
-
- _unlock_global_ft_cache ();
- }
-
- if (unscaled == NULL)
- return;
-
- if (!unscaled->from_face && unscaled->face)
- FT_Done_Face (unscaled->face);
-
- if (unscaled->filename)
- free (unscaled->filename);
-
- free (unscaled);
+ _cairo_unscaled_font_destroy (&scaled_font->unscaled->base);
}
static void
-_cairo_ft_font_get_glyph_cache_key (void *abstract_font,
- cairo_glyph_cache_key_t *key)
+_cairo_ft_scaled_font_get_glyph_cache_key (void *abstract_font,
+ cairo_glyph_cache_key_t *key)
{
- cairo_ft_font_t *font = abstract_font;
+ cairo_ft_scaled_font_t *scaled_font = abstract_font;
- key->unscaled = (cairo_unscaled_font_t *)font->unscaled;
- key->scale = font->base.scale;
- key->flags = font->load_flags;
+ key->unscaled = &scaled_font->unscaled->base;
+ key->scale = scaled_font->base.scale;
+ key->flags = scaled_font->load_flags;
}
static cairo_status_t
-_cairo_ft_font_text_to_glyphs (void *abstract_font,
- const unsigned char *utf8,
- cairo_glyph_t **glyphs,
- int *nglyphs)
+_cairo_ft_scaled_font_text_to_glyphs (void *abstract_font,
+ const char *utf8,
+ cairo_glyph_t **glyphs,
+ int *num_glyphs)
{
double x = 0., y = 0.;
size_t i;
uint32_t *ucs4 = NULL;
- cairo_ft_font_t *font = abstract_font;
+ cairo_ft_scaled_font_t *scaled_font = abstract_font;
FT_Face face;
cairo_glyph_cache_key_t key;
cairo_image_glyph_cache_entry_t *val;
cairo_cache_t *cache = NULL;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
- _cairo_ft_font_get_glyph_cache_key (font, &key);
+ _cairo_ft_scaled_font_get_glyph_cache_key (scaled_font, &key);
- status = _cairo_utf8_to_ucs4 (utf8, -1, &ucs4, nglyphs);
+ status = _cairo_utf8_to_ucs4 ((unsigned char*)utf8, -1, &ucs4, num_glyphs);
if (!CAIRO_OK (status))
return status;
- face = cairo_ft_font_lock_face ((cairo_font_t *)font);
+ face = cairo_ft_scaled_font_lock_face (&scaled_font->base);
if (!face) {
status = CAIRO_STATUS_NO_MEMORY;
goto FAIL1;
@@ -754,13 +879,13 @@ _cairo_ft_font_text_to_glyphs (void *abstract_font,
goto FAIL2;
}
- *glyphs = (cairo_glyph_t *) malloc ((*nglyphs) * (sizeof (cairo_glyph_t)));
+ *glyphs = (cairo_glyph_t *) malloc ((*num_glyphs) * (sizeof (cairo_glyph_t)));
if (*glyphs == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto FAIL2;
}
- for (i = 0; i < *nglyphs; i++)
+ for (i = 0; i < *num_glyphs; i++)
{
(*glyphs)[i].index = FT_Get_Char_Index (face, ucs4[i]);
(*glyphs)[i].x = x;
@@ -781,7 +906,7 @@ _cairo_ft_font_text_to_glyphs (void *abstract_font,
if (cache)
_cairo_unlock_global_image_glyph_cache ();
- cairo_ft_font_unlock_face ((cairo_font_t *)font);
+ cairo_ft_scaled_font_unlock_face (&scaled_font->base);
FAIL1:
free (ucs4);
@@ -791,49 +916,50 @@ _cairo_ft_font_text_to_glyphs (void *abstract_font,
static cairo_status_t
-_cairo_ft_font_font_extents (void *abstract_font,
- cairo_font_extents_t *extents)
+_cairo_ft_scaled_font_font_extents (void *abstract_font,
+ cairo_font_extents_t *extents)
{
- cairo_ft_font_t *font = abstract_font;
+ cairo_ft_scaled_font_t *scaled_font = abstract_font;
FT_Face face;
FT_Size_Metrics *metrics;
- face = _ft_unscaled_font_lock_face (font->unscaled);
+ face = _ft_unscaled_font_lock_face (scaled_font->unscaled);
if (!face)
return CAIRO_STATUS_NO_MEMORY;
metrics = &face->size->metrics;
- _ft_unscaled_font_set_scale (font->unscaled, &font->base.scale);
+ _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) / font->unscaled->y_scale;
- extents->descent = DOUBLE_FROM_26_6(metrics->descender) / font->unscaled->y_scale;
- extents->height = DOUBLE_FROM_26_6(metrics->height) / font->unscaled->y_scale;
- extents->max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance) / font->unscaled->x_scale;
+ 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;
/* FIXME: this doesn't do vertical layout atm. */
extents->max_y_advance = 0.0;
- _ft_unscaled_font_unlock_face (font->unscaled);
+ _ft_unscaled_font_unlock_face (scaled_font->unscaled);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
-_cairo_ft_font_glyph_extents (void *abstract_font,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_text_extents_t *extents)
+_cairo_ft_scaled_font_glyph_extents (void *abstract_font,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_text_extents_t *extents)
{
int i;
- cairo_ft_font_t *font = abstract_font;
+ cairo_ft_scaled_font_t *scaled_font = abstract_font;
cairo_point_double_t origin;
cairo_point_double_t glyph_min, glyph_max;
- cairo_point_double_t total_min, total_max;
+ /* Initialize just to squelch anti-helpful compiler warning. */
+ cairo_point_double_t total_min = { 0, 0}, total_max = {0,0};
cairo_image_glyph_cache_entry_t *img = NULL;
cairo_cache_t *cache;
@@ -861,7 +987,7 @@ _cairo_ft_font_glyph_extents (void *abstract_font,
return CAIRO_STATUS_NO_MEMORY;
}
- _cairo_ft_font_get_glyph_cache_key (font, &key);
+ _cairo_ft_scaled_font_get_glyph_cache_key (scaled_font, &key);
for (i = 0; i < num_glyphs; i++)
{
@@ -874,7 +1000,7 @@ _cairo_ft_font_glyph_extents (void *abstract_font,
/* XXX: Need to add code here to check the font's FcPattern
for FC_VERTICAL_LAYOUT and if set get vertBearingX/Y
instead. This will require that
- cairo_ft_font_create_for_ft_face accept an
+ cairo_ft_scaled_font_create_for_ft_face accept an
FcPattern. */
glyph_min.x = glyphs[i].x + img->extents.x_bearing;
glyph_min.y = glyphs[i].y + img->extents.y_bearing;
@@ -910,15 +1036,15 @@ _cairo_ft_font_glyph_extents (void *abstract_font,
static cairo_status_t
-_cairo_ft_font_glyph_bbox (void *abstract_font,
- const cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_box_t *bbox)
+_cairo_ft_scaled_font_glyph_bbox (void *abstract_font,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_box_t *bbox)
{
cairo_image_glyph_cache_entry_t *img;
cairo_cache_t *cache;
cairo_glyph_cache_key_t key;
- cairo_ft_font_t *font = abstract_font;
+ cairo_ft_scaled_font_t *scaled_font = abstract_font;
cairo_fixed_t x1, y1, x2, y2;
int i;
@@ -930,13 +1056,13 @@ _cairo_ft_font_glyph_bbox (void *abstract_font,
cache = _cairo_get_global_image_glyph_cache();
if (cache == NULL
- || font == NULL
+ || scaled_font == NULL
|| glyphs == NULL) {
_cairo_unlock_global_image_glyph_cache ();
return CAIRO_STATUS_NO_MEMORY;
}
- _cairo_ft_font_get_glyph_cache_key (font, &key);
+ _cairo_ft_scaled_font_get_glyph_cache_key (scaled_font, &key);
for (i = 0; i < num_glyphs; i++)
{
@@ -972,23 +1098,23 @@ _cairo_ft_font_glyph_bbox (void *abstract_font,
static cairo_status_t
-_cairo_ft_font_show_glyphs (void *abstract_font,
- cairo_operator_t operator,
- cairo_pattern_t *pattern,
- cairo_surface_t *surface,
- int source_x,
- int source_y,
- int dest_x,
- int dest_y,
- unsigned int width,
- unsigned int height,
- const cairo_glyph_t *glyphs,
- int num_glyphs)
+_cairo_ft_scaled_font_show_glyphs (void *abstract_font,
+ cairo_operator_t operator,
+ cairo_pattern_t *pattern,
+ cairo_surface_t *surface,
+ int source_x,
+ int source_y,
+ int dest_x,
+ int dest_y,
+ unsigned int width,
+ unsigned int height,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs)
{
cairo_image_glyph_cache_entry_t *img;
cairo_cache_t *cache;
cairo_glyph_cache_key_t key;
- cairo_ft_font_t *font = abstract_font;
+ cairo_ft_scaled_font_t *scaled_font = abstract_font;
cairo_surface_pattern_t glyph_pattern;
cairo_status_t status;
int x, y;
@@ -998,7 +1124,7 @@ _cairo_ft_font_show_glyphs (void *abstract_font,
cache = _cairo_get_global_image_glyph_cache();
if (cache == NULL
- || font == NULL
+ || scaled_font == NULL
|| pattern == NULL
|| surface == NULL
|| glyphs == NULL) {
@@ -1006,9 +1132,9 @@ _cairo_ft_font_show_glyphs (void *abstract_font,
return CAIRO_STATUS_NO_MEMORY;
}
- key.unscaled = (cairo_unscaled_font_t *)font->unscaled;
- key.scale = font->base.scale;
- key.flags = font->load_flags;
+ key.unscaled = &scaled_font->unscaled->base;
+ key.scale = scaled_font->base.scale;
+ key.flags = scaled_font->load_flags;
for (i = 0; i < num_glyphs; i++)
{
@@ -1054,14 +1180,14 @@ _cairo_ft_font_show_glyphs (void *abstract_font,
static int
_move_to (FT_Vector *to, void *closure)
{
- cairo_path_t *path = closure;
- cairo_point_t point;
+ cairo_path_fixed_t *path = closure;
+ cairo_fixed_t x, y;
- point.x = _cairo_fixed_from_26_6 (to->x);
- point.y = _cairo_fixed_from_26_6 (to->y);
+ x = _cairo_fixed_from_26_6 (to->x);
+ y = _cairo_fixed_from_26_6 (to->y);
- _cairo_path_close_path (path);
- _cairo_path_move_to (path, &point);
+ _cairo_path_fixed_close_path (path);
+ _cairo_path_fixed_move_to (path, x, y);
return 0;
}
@@ -1069,13 +1195,13 @@ _move_to (FT_Vector *to, void *closure)
static int
_line_to (FT_Vector *to, void *closure)
{
- cairo_path_t *path = closure;
- cairo_point_t point;
+ cairo_path_fixed_t *path = closure;
+ cairo_fixed_t x, y;
- point.x = _cairo_fixed_from_26_6 (to->x);
- point.y = _cairo_fixed_from_26_6 (to->y);
+ x = _cairo_fixed_from_26_6 (to->x);
+ y = _cairo_fixed_from_26_6 (to->y);
- _cairo_path_line_to (path, &point);
+ _cairo_path_fixed_line_to (path, x, y);
return 0;
}
@@ -1083,27 +1209,32 @@ _line_to (FT_Vector *to, void *closure)
static int
_conic_to (FT_Vector *control, FT_Vector *to, void *closure)
{
- cairo_path_t *path = closure;
+ cairo_path_fixed_t *path = closure;
- cairo_point_t p0, p1, p2, p3;
+ cairo_fixed_t x0, y0;
+ cairo_fixed_t x1, y1;
+ cairo_fixed_t x2, y2;
+ cairo_fixed_t x3, y3;
cairo_point_t conic;
- _cairo_path_current_point (path, &p0);
+ _cairo_path_fixed_get_current_point (path, &x0, &y0);
conic.x = _cairo_fixed_from_26_6 (control->x);
conic.y = _cairo_fixed_from_26_6 (control->y);
- p3.x = _cairo_fixed_from_26_6 (to->x);
- p3.y = _cairo_fixed_from_26_6 (to->y);
+ x3 = _cairo_fixed_from_26_6 (to->x);
+ y3 = _cairo_fixed_from_26_6 (to->y);
- p1.x = p0.x + 2.0/3.0 * (conic.x - p0.x);
- p1.y = p0.y + 2.0/3.0 * (conic.y - p0.y);
+ x1 = x0 + 2.0/3.0 * (conic.x - x0);
+ y1 = y0 + 2.0/3.0 * (conic.y - y0);
- p2.x = p3.x + 2.0/3.0 * (conic.x - p3.x);
- p2.y = p3.y + 2.0/3.0 * (conic.y - p3.y);
+ x2 = x3 + 2.0/3.0 * (conic.x - x3);
+ y2 = y3 + 2.0/3.0 * (conic.y - y3);
- _cairo_path_curve_to (path,
- &p1, &p2, &p3);
+ _cairo_path_fixed_curve_to (path,
+ x1, y1,
+ x2, y2,
+ x3, y3);
return 0;
}
@@ -1111,31 +1242,36 @@ _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)
{
- cairo_path_t *path = closure;
- cairo_point_t p0, p1, p2;
+ cairo_path_fixed_t *path = closure;
+ cairo_fixed_t x0, y0;
+ cairo_fixed_t x1, y1;
+ cairo_fixed_t x2, y2;
- p0.x = _cairo_fixed_from_26_6 (control1->x);
- p0.y = _cairo_fixed_from_26_6 (control1->y);
+ x0 = _cairo_fixed_from_26_6 (control1->x);
+ y0 = _cairo_fixed_from_26_6 (control1->y);
- p1.x = _cairo_fixed_from_26_6 (control2->x);
- p1.y = _cairo_fixed_from_26_6 (control2->y);
+ x1 = _cairo_fixed_from_26_6 (control2->x);
+ y1 = _cairo_fixed_from_26_6 (control2->y);
- p2.x = _cairo_fixed_from_26_6 (to->x);
- p2.y = _cairo_fixed_from_26_6 (to->y);
+ x2 = _cairo_fixed_from_26_6 (to->x);
+ y2 = _cairo_fixed_from_26_6 (to->y);
- _cairo_path_curve_to (path, &p0, &p1, &p2);
+ _cairo_path_fixed_curve_to (path,
+ x0, y0,
+ x1, y1,
+ x2, y2);
return 0;
}
static cairo_status_t
-_cairo_ft_font_glyph_path (void *abstract_font,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_path_t *path)
+_cairo_ft_scaled_font_glyph_path (void *abstract_font,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_path_fixed_t *path)
{
int i;
- cairo_ft_font_t *font = abstract_font;
+ cairo_ft_scaled_font_t *scaled_font = abstract_font;
FT_GlyphSlot glyph;
FT_Face face;
FT_Error error;
@@ -1148,7 +1284,7 @@ _cairo_ft_font_glyph_path (void *abstract_font,
0, /* delta */
};
- face = cairo_ft_font_lock_face (abstract_font);
+ face = cairo_ft_scaled_font_lock_face (abstract_font);
if (!face)
return CAIRO_STATUS_NO_MEMORY;
@@ -1161,7 +1297,7 @@ _cairo_ft_font_glyph_path (void *abstract_font,
0, DOUBLE_TO_16_16 (-1.0),
};
- error = FT_Load_Glyph (font->unscaled->face, glyphs[i].index, font->load_flags | FT_LOAD_NO_BITMAP);
+ error = FT_Load_Glyph (scaled_font->unscaled->face, glyphs[i].index, scaled_font->load_flags | FT_LOAD_NO_BITMAP);
/* XXX: What to do in this error case? */
if (error)
continue;
@@ -1176,148 +1312,136 @@ _cairo_ft_font_glyph_path (void *abstract_font,
DOUBLE_TO_26_6(glyphs[i].y));
FT_Outline_Decompose (&glyph->outline, &outline_funcs, path);
}
- _cairo_path_close_path (path);
+ _cairo_path_fixed_close_path (path);
- cairo_ft_font_unlock_face (abstract_font);
+ cairo_ft_scaled_font_unlock_face (abstract_font);
return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
-_cairo_ft_font_create_glyph (cairo_image_glyph_cache_entry_t *val)
-{
- ft_unscaled_font_t *unscaled = (ft_unscaled_font_t *)val->key.unscaled;
- FT_GlyphSlot glyphslot;
- unsigned int width, height, stride;
- FT_Face face;
- FT_Outline *outline;
- FT_BBox cbox;
- FT_Bitmap bitmap;
- FT_Glyph_Metrics *metrics;
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
-
- glyphslot = unscaled->face->glyph;
- metrics = &glyphslot->metrics;
+const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = {
+ _cairo_ft_scaled_font_create,
+ _cairo_ft_scaled_font_destroy,
+ _cairo_ft_scaled_font_font_extents,
+ _cairo_ft_scaled_font_text_to_glyphs,
+ _cairo_ft_scaled_font_glyph_extents,
+ _cairo_ft_scaled_font_glyph_bbox,
+ _cairo_ft_scaled_font_show_glyphs,
+ _cairo_ft_scaled_font_glyph_path,
+ _cairo_ft_scaled_font_get_glyph_cache_key,
+};
- face = _ft_unscaled_font_lock_face (unscaled);
- if (!face)
- return CAIRO_STATUS_NO_MEMORY;
+/* ft_font_face_t */
- _ft_unscaled_font_set_scale (unscaled, &val->key.scale);
-
- if (FT_Load_Glyph (face, val->key.index, val->key.flags) != 0) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto FAIL;
- }
+static void
+_ft_font_face_destroy (void *abstract_face)
+{
+ ft_font_face_t *font_face = abstract_face;
+
+ ft_font_face_t *tmp_face = NULL;
+ ft_font_face_t *last_face = NULL;
- /*
- * Note: the font's coordinate system is upside down from ours, so the
- * Y coordinates of the bearing and advance need to be negated.
+ /* When destroying the face created by cairo_ft_font_face_create_for_ft_face,
+ * we have a special "zombie" state for the face when the unscaled font
+ * is still alive but there are no public references to the font face.
*
- * Scale metrics back to glyph space from the scaled glyph space returned
- * by FreeType
+ * We go from:
+ *
+ * font_face ------> unscaled
+ * <-....weak....../
+ *
+ * To:
+ *
+ * font_face <------- unscaled
*/
- 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;
+ if (font_face->unscaled &&
+ font_face->unscaled->from_face &&
+ font_face->unscaled->base.refcount > 1) {
+ cairo_font_face_reference (&font_face->base);
+
+ _cairo_unscaled_font_destroy (&font_face->unscaled->base);
+ font_face->unscaled = NULL;
+
+ return;
+ }
+
+ if (font_face->unscaled) {
+ /* Remove face from linked list */
+ for (tmp_face = font_face->unscaled->faces; tmp_face; tmp_face = tmp_face->next_face) {
+ if (tmp_face == font_face) {
+ if (last_face)
+ last_face->next_face = tmp_face->next_face;
+ else
+ font_face->unscaled->faces = tmp_face->next_face;
+ }
+
+ last_face = tmp_face;
+ }
- val->extents.width = DOUBLE_FROM_26_6 (metrics->width) / unscaled->x_scale;
- val->extents.height = DOUBLE_FROM_26_6 (metrics->height) / unscaled->y_scale;
+ _cairo_unscaled_font_destroy (&font_face->unscaled->base);
+ font_face->unscaled = NULL;
+ }
+}
- /*
- * use untransformed advance values
- * XXX uses horizontal advance only at present;
- should provide FT_LOAD_VERTICAL_LAYOUT
- */
+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_t *font_face = abstract_face;
- val->extents.x_advance = DOUBLE_FROM_26_6 (face->glyph->metrics.horiAdvance) / unscaled->x_scale;
- val->extents.y_advance = 0 / unscaled->y_scale;
-
- outline = &glyphslot->outline;
+ *scaled_font = _ft_scaled_font_create (font_face->unscaled,
+ font_face->load_flags,
+ font_matrix, ctm);
+ if (*scaled_font)
+ return CAIRO_STATUS_SUCCESS;
+ else
+ return CAIRO_STATUS_NO_MEMORY;
+}
- FT_Outline_Get_CBox (outline, &cbox);
+static const cairo_font_face_backend_t _ft_font_face_backend = {
+ _ft_font_face_destroy,
+ _ft_font_face_create_font,
+};
- cbox.xMin &= -64;
- 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;
-
- if (width * height == 0)
- val->image = NULL;
- else
- {
+static cairo_font_face_t *
+_ft_font_face_create (ft_unscaled_font_t *unscaled,
+ int load_flags)
+{
+ ft_font_face_t *font_face;
- bitmap.pixel_mode = ft_pixel_mode_grays;
- bitmap.num_grays = 256;
- bitmap.width = width;
- bitmap.rows = height;
- bitmap.pitch = stride;
- bitmap.buffer = calloc (1, stride * height);
-
- if (bitmap.buffer == NULL) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto FAIL;
+ /* Looked for an existing matching font face */
+ for (font_face = unscaled->faces; font_face; font_face = font_face->next_face) {
+ if (font_face->load_flags == load_flags) {
+ cairo_font_face_reference (&font_face->base);
+ return &font_face->base;
}
-
- FT_Outline_Translate (outline, -cbox.xMin, -cbox.yMin);
-
- if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
- free (bitmap.buffer);
- status = CAIRO_STATUS_NO_MEMORY;
- goto FAIL;
- }
-
- val->image = (cairo_image_surface_t *)
- cairo_image_surface_create_for_data ((char *) bitmap.buffer,
- CAIRO_FORMAT_A8,
- width, height, stride);
- if (val->image == NULL) {
- free (bitmap.buffer);
- status = CAIRO_STATUS_NO_MEMORY;
- goto FAIL;
- }
-
- _cairo_image_surface_assume_ownership_of_data (val->image);
}
- /*
- * Note: the font's coordinate system is upside down from ours, so the
- * 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);
+ /* No match found, create a new one */
+ font_face = malloc (sizeof (ft_font_face_t));
+ if (!font_face)
+ return NULL;
- FAIL:
- _ft_unscaled_font_unlock_face (unscaled);
+ font_face->unscaled = unscaled;
+ _cairo_unscaled_font_reference (&unscaled->base);
- return status;
-}
+ font_face->load_flags = load_flags;
-const cairo_font_backend_t cairo_ft_font_backend = {
- _cairo_ft_font_create,
- _cairo_ft_font_destroy_font,
- _cairo_ft_font_destroy_unscaled_font,
- _cairo_ft_font_font_extents,
- _cairo_ft_font_text_to_glyphs,
- _cairo_ft_font_glyph_extents,
- _cairo_ft_font_glyph_bbox,
- _cairo_ft_font_show_glyphs,
- _cairo_ft_font_glyph_path,
- _cairo_ft_font_get_glyph_cache_key,
- _cairo_ft_font_create_glyph
-};
+ font_face->next_face = unscaled->faces;
+ unscaled->faces = font_face;
+
+ _cairo_font_face_init (&font_face->base, &_ft_font_face_backend);
+
+ return &font_face->base;
+}
/* implement the platform-specific interface */
/**
- * cairo_ft_font_create:
+ * cairo_ft_font_face_create_for_pattern:
* @pattern: A fully resolved fontconfig
* pattern. A pattern can be resolved, by, among other things, calling
* FcConfigSubstitute(), FcDefaultSubstitute(), then
@@ -1325,112 +1449,83 @@ const cairo_font_backend_t cairo_ft_font_backend = {
* pattern, so you should not further modify the pattern, but you can
* release your reference to the pattern with FcPatternDestroy() if
* you no longer need to access it.
- * @scale: The scale at which this font will be used. The
- * scale is given by multiplying the font matrix (see
- * cairo_transform_font()) by the current transformation matrix.
- * The translation elements of the resulting matrix are ignored.
*
- * Creates a new font for the FreeType font backend based on a
+ * Creates a new font face for the FreeType font backend based on a
* fontconfig pattern. This font can then be used with
- * cairo_set_font(), cairo_font_glyph_extents(), or FreeType backend
- * specific functions like cairo_ft_font_lock_face().
+ * cairo_set_font_face() or cairo_font_create(). The #cairo_scaled_font_t
+ * returned from cairo_font_create() is also for the FreeType backend
+ * and can be used with functions such as cairo_ft_font_lock_face().
*
- * Return value: a newly created #cairo_font_t. Free with
- * cairo_font_destroy() when you are done using it.
+ * Return value: a newly created #cairo_font_face_t. Free with
+ * cairo_font_face_destroy() when you are done using it.
**/
-cairo_font_t *
-cairo_ft_font_create (FcPattern *pattern,
- cairo_matrix_t *scale)
-{
- cairo_font_scale_t sc;
- double tx, ty;
+cairo_font_face_t *
+cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
+{
+ ft_unscaled_font_t *unscaled;
+ cairo_font_face_t *font_face;
- cairo_matrix_get_affine (scale,
- &sc.matrix[0][0], &sc.matrix[0][1],
- &sc.matrix[1][0], &sc.matrix[1][1],
- &tx, &ty);
+ unscaled = _ft_unscaled_font_get_for_pattern (pattern);
+ if (unscaled == NULL)
+ return NULL;
- return _ft_font_create (pattern, &sc);
+ font_face = _ft_font_face_create (unscaled, _get_load_flags (pattern));
+ _cairo_unscaled_font_destroy (&unscaled->base);
+
+ return font_face;
}
/**
* cairo_ft_font_create_for_ft_face:
* @face: A FreeType face object, already opened. This must
- * be kept around until the font object's refcount drops to
- * zero and it is freed. The font object can be kept alive by
- * internal caching, so it's safest to keep the face object
- * around forever.
+ * be kept around until the face's refcount 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.
- * @scale: The scale at which this font will be used. The
- * scale is given by multiplying the font matrix (see
- * cairo_transform_font()) by the current transformation matrix.
- * The translation elements of the resulting matrix are ignored.
*
- * Creates a new font forthe FreeType font backend from a pre-opened
- * FreeType face. This font can then be used with cairo_set_font(),
- * cairo_font_glyph_extents(), or FreeType backend specific
- * functions like cairo_ft_font_lock_face() Cairo will determine the
- * pixel size and transformation from the @scale parameter and call
- * FT_Set_Transform() and FT_Set_Pixel_Sizes().
+ * Creates a new font face for the FreeType font backend from a pre-opened
+ * FreeType face. This font can then be used with
+ * cairo_set_font_face() or cairo_font_create(). The #cairo_scaled_font_t
+ * returned from cairo_font_create() is also for the FreeType backend
+ * and can be used with functions such as cairo_ft_font_lock_face().
*
- * Return value: a newly created #cairo_font_t. Free with
- * cairo_font_destroy() when you are done using it.
+ * Return value: a newly created #cairo_font_face_t. Free with
+ * cairo_font_face_destroy() when you are done using it.
**/
-cairo_font_t *
-cairo_ft_font_create_for_ft_face (FT_Face face,
- int load_flags,
- cairo_matrix_t *scale)
+cairo_font_face_t *
+cairo_ft_font_face_create_for_ft_face (FT_Face face,
+ int load_flags)
{
- cairo_ft_font_t *f = NULL;
- ft_unscaled_font_t *unscaled = NULL;
- cairo_font_scale_t sc;
- double tx, ty;
+ ft_unscaled_font_t *unscaled;
+ cairo_font_face_t *font_face;
unscaled = _ft_unscaled_font_create_from_face (face);
if (unscaled == NULL)
return NULL;
- f = malloc (sizeof(cairo_ft_font_t));
- if (f == NULL)
- goto FREE_UNSCALED;
-
- f->unscaled = unscaled;
- f->pattern = NULL;
- f->load_flags = load_flags;
-
- cairo_matrix_get_affine (scale,
- &sc.matrix[0][0], &sc.matrix[0][1],
- &sc.matrix[1][0], &sc.matrix[1][1],
- &tx, &ty);
-
- _cairo_font_init ((cairo_font_t *)f, &sc, &cairo_ft_font_backend);
-
- return (cairo_font_t *)f;
-
- FREE_UNSCALED:
- _cairo_unscaled_font_destroy ((cairo_unscaled_font_t *)unscaled);
+ font_face = _ft_font_face_create (unscaled, load_flags);
+ _cairo_unscaled_font_destroy (&unscaled->base);
- return NULL;
+ return font_face;
}
-
/**
- * cairo_ft_font_lock_face:
- * @ft_font: A #cairo_font_t from the FreeType font backend. Such an
- * object can be created with cairo_ft_font_create() or
- * cairo_ft_font_create_for_ft_face(). On some platforms the font from
- * cairo_current_font() will also be a FreeType font, but using this
- * functionality with fonts you don't create yourself is not
- * recommended.
+ * cairo_ft_scaled_font_lock_face:
+ * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
+ * object can be created by calling cairo_scaled_font_create() on a
+ * FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
+ * cairo_ft_font_face_create_for_face()).
*
* cairo_ft_font_lock_face() gets the #FT_Face object from a FreeType
* backend font and scales it appropriately for the font. You must
* release the face with cairo_ft_font_unlock_face()
* when you are done using it. Since the #FT_Face object can be
- * shared between multiple #cairo_font_t objects, you must not
+ * shared between multiple #cairo_scaled_font_t objects, you must not
* lock any other font objects until you unlock this one. A count is
* kept of the number of times cairo_ft_font_lock_face() is
* called. cairo_ft_font_unlock_face() must be called the same number
@@ -1447,67 +1542,36 @@ cairo_ft_font_create_for_ft_face (FT_Face face,
* Return value: The #FT_Face object for @font, scaled appropriately.
**/
FT_Face
-cairo_ft_font_lock_face (cairo_font_t *abstract_font)
+cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
{
- cairo_ft_font_t *font = (cairo_ft_font_t *) abstract_font;
+ cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
FT_Face face;
- face = _ft_unscaled_font_lock_face (font->unscaled);
+ face = _ft_unscaled_font_lock_face (scaled_font->unscaled);
if (!face)
return NULL;
- _ft_unscaled_font_set_scale (font->unscaled, &font->base.scale);
+ _ft_unscaled_font_set_scale (scaled_font->unscaled, &scaled_font->base.scale);
return face;
}
/**
- * cairo_ft_font_unlock_face:
- * @ft_font: A #cairo_font_t from the FreeType font backend. Such an
- * object can be created with cairo_ft_font_create() or
- * cairo_ft_font_create_for_ft_face(). On some platforms the font from
- * cairo_current_font() will also be a FreeType font, but using this
- * functionality with fonts you don't create yourself is not
- * recommended.
+ * cairo_ft_scaled_font_unlock_face:
+ * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
+ * object can be created by calling cairo_scaled_font_create() on a
+ * FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
+ * cairo_ft_font_face_create_for_face()).
*
* Releases a face obtained with cairo_ft_font_lock_face(). See the
* documentation for that function for full details.
**/
void
-cairo_ft_font_unlock_face (cairo_font_t *abstract_font)
-{
- cairo_ft_font_t *font = (cairo_ft_font_t *) abstract_font;
-
- _ft_unscaled_font_unlock_face (font->unscaled);
-}
-
-/**
- * cairo_ft_font_get_pattern:
- * @ft_font: A #cairo_font_t from the FreeType font backend. Such an
- * object can be created with cairo_ft_font_create() or
- * cairo_ft_font_create_for_ft_face(). On some platforms the font from
- * cairo_current_font() will also be a FreeType font, but using this
- * functionality with fonts you don't create yourself is not
- * recommended.
- *
- * cairo_ft_font_get_pattern() gets the #FcPattern for a FreeType
- * backend font.
-
- * Return value: The #FcPattenr for @font. The return value is owned
- * by the font, so you must not modify it, and must call
- * FcPatternReference() to keep a persistant reference to the
- * pattern. If the font was created with cairo_ft_font_create_for_ft_face()
- * returns %NULL.
- **/
-FcPattern *
-cairo_ft_font_get_pattern (cairo_font_t *abstract_font)
+cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font)
{
- cairo_ft_font_t *font = (cairo_ft_font_t *) abstract_font;
-
- if (font == NULL)
- return NULL;
+ cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
- return font->pattern;
+ _ft_unscaled_font_unlock_face (scaled_font->unscaled);
}
/* We expose our unscaled font implementation internally for the the
@@ -1515,11 +1579,11 @@ cairo_ft_font_get_pattern (cairo_font_t *abstract_font)
* fonts-on-disk used by a document, so it can embed them.
*/
cairo_unscaled_font_t *
-_cairo_ft_font_get_unscaled_font (cairo_font_t *abstract_font)
+_cairo_ft_scaled_font_get_unscaled_font (cairo_scaled_font_t *abstract_font)
{
- cairo_ft_font_t *font = (cairo_ft_font_t *) abstract_font;
+ cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
- return (cairo_unscaled_font_t *)font->unscaled;
+ return &scaled_font->unscaled->base;
}
/* This differs from _cairo_ft_scaled_font_lock_face in that it doesn't
diff --git a/src/cairo-ft-private.h b/src/cairo-ft-private.h
index 37a6feecc..494d8369a 100644
--- a/src/cairo-ft-private.h
+++ b/src/cairo-ft-private.h
@@ -40,7 +40,7 @@
#include <cairo-ft.h>
#include <cairoint.h>
-#ifdef CAIRO_HAS_FT_FONT
+#if CAIRO_HAS_FT_FONT
CAIRO_BEGIN_DECLS
@@ -48,7 +48,7 @@ CAIRO_BEGIN_DECLS
* the different fonts-on-disk used by a document, so it can embed them
*/
cairo_private cairo_unscaled_font_t *
-_cairo_ft_font_get_unscaled_font (cairo_font_t *font);
+_cairo_ft_scaled_font_get_unscaled_font (cairo_scaled_font_t *scaled_font);
cairo_private FT_Face
_cairo_ft_unscaled_font_lock_face (cairo_unscaled_font_t *unscaled_font);
diff --git a/src/cairo-ft.h b/src/cairo-ft.h
index f10c67d80..4e8b8bcdb 100644
--- a/src/cairo-ft.h
+++ b/src/cairo-ft.h
@@ -39,7 +39,7 @@
#include <cairo.h>
-#ifdef CAIRO_HAS_FT_FONT
+#if CAIRO_HAS_FT_FONT
/* Fontconfig/Freetype platform-specific font interface */
@@ -49,25 +49,23 @@
CAIRO_BEGIN_DECLS
-cairo_font_t *
-cairo_ft_font_create (FcPattern *pattern,
- cairo_matrix_t *scale);
+cairo_font_face_t *
+cairo_ft_font_face_create_for_pattern (FcPattern *pattern);
-cairo_font_t *
-cairo_ft_font_create_for_ft_face (FT_Face face,
- int load_flags,
- cairo_matrix_t *scale);
+cairo_font_face_t *
+cairo_ft_font_face_create_for_ft_face (FT_Face face,
+ int load_flags);
FT_Face
-cairo_ft_font_lock_face (cairo_font_t *ft_font);
+cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *scaled_font);
void
-cairo_ft_font_unlock_face (cairo_font_t *ft_font);
-
-FcPattern *
-cairo_ft_font_get_pattern (cairo_font_t *ft_font);
+cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *scaled_font);
CAIRO_END_DECLS
+#else /* CAIRO_HAS_FT_FONT */
+# error Cairo was not compiled with support for the freetype font backend
#endif /* CAIRO_HAS_FT_FONT */
+
#endif /* CAIRO_FT_H */
diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c
index ee664e1cc..673b972c3 100644
--- a/src/cairo-glitz-surface.c
+++ b/src/cairo-glitz-surface.c
@@ -27,25 +27,6 @@
#include "cairoint.h"
#include "cairo-glitz.h"
-void
-cairo_set_target_glitz (cairo_t *cr, glitz_surface_t *surface)
-{
- cairo_surface_t *crsurface;
-
- if (cr->status && cr->status != CAIRO_STATUS_NO_TARGET_SURFACE)
- return;
-
- crsurface = cairo_glitz_surface_create (surface);
- if (crsurface == NULL) {
- cr->status = CAIRO_STATUS_NO_MEMORY;
- return;
- }
-
- cairo_set_target_surface (cr, crsurface);
-
- cairo_surface_destroy (crsurface);
-}
-
typedef struct _cairo_glitz_surface {
cairo_surface_t base;
@@ -54,8 +35,8 @@ typedef struct _cairo_glitz_surface {
pixman_region16_t *clip;
} cairo_glitz_surface_t;
-static void
-_cairo_glitz_surface_destroy (void *abstract_surface)
+static cairo_status_t
+_cairo_glitz_surface_finish (void *abstract_surface)
{
cairo_glitz_surface_t *surface = abstract_surface;
@@ -66,7 +47,8 @@ _cairo_glitz_surface_destroy (void *abstract_surface)
}
glitz_surface_destroy (surface->surface);
- free (surface);
+
+ return CAIRO_STATUS_SUCCESS;
}
static glitz_format_name_t
@@ -115,12 +97,6 @@ _cairo_glitz_surface_create_similar (void *abstract_src,
return crsurface;
}
-static double
-_cairo_glitz_surface_pixels_per_inch (void *abstract_surface)
-{
- return 96.0;
-}
-
static cairo_status_t
_cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
cairo_rectangle_t *interest,
@@ -130,7 +106,7 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
cairo_image_surface_t *image;
int x1, y1, x2, y2;
int width, height;
- char *pixels;
+ unsigned char *pixels;
cairo_format_masks_t format;
glitz_buffer_t *buffer;
glitz_pixel_format_t pf;
@@ -402,17 +378,17 @@ _cairo_glitz_surface_set_matrix (cairo_glitz_surface_t *surface,
{
glitz_transform_t transform;
- transform.matrix[0][0] = _cairo_fixed_from_double (matrix->m[0][0]);
- transform.matrix[0][1] = _cairo_fixed_from_double (matrix->m[1][0]);
- transform.matrix[0][2] = _cairo_fixed_from_double (matrix->m[2][0]);
+ transform.matrix[0][0] = _cairo_fixed_from_double (matrix->xx);
+ transform.matrix[0][1] = _cairo_fixed_from_double (matrix->xy);
+ transform.matrix[0][2] = _cairo_fixed_from_double (matrix->x0);
- transform.matrix[1][0] = _cairo_fixed_from_double (matrix->m[0][1]);
- transform.matrix[1][1] = _cairo_fixed_from_double (matrix->m[1][1]);
- transform.matrix[1][2] = _cairo_fixed_from_double (matrix->m[2][1]);
+ transform.matrix[1][0] = _cairo_fixed_from_double (matrix->yx);
+ transform.matrix[1][1] = _cairo_fixed_from_double (matrix->yy);
+ transform.matrix[1][2] = _cairo_fixed_from_double (matrix->y0);
transform.matrix[2][0] = 0;
transform.matrix[2][1] = 0;
- transform.matrix[2][2] = 1 << 16;
+ transform.matrix[2][2] = _cairo_fixed_from_double (1);
glitz_surface_set_transform (surface->surface, &transform);
}
@@ -423,32 +399,49 @@ _glitz_operator (cairo_operator_t op)
switch (op) {
case CAIRO_OPERATOR_CLEAR:
return GLITZ_OPERATOR_CLEAR;
- case CAIRO_OPERATOR_SRC:
+
+ case CAIRO_OPERATOR_SOURCE:
return GLITZ_OPERATOR_SRC;
- case CAIRO_OPERATOR_DST:
- return GLITZ_OPERATOR_DST;
- case CAIRO_OPERATOR_OVER_REVERSE:
- return GLITZ_OPERATOR_OVER_REVERSE;
+ case CAIRO_OPERATOR_OVER:
+ return GLITZ_OPERATOR_OVER;
case CAIRO_OPERATOR_IN:
return GLITZ_OPERATOR_IN;
- case CAIRO_OPERATOR_IN_REVERSE:
- return GLITZ_OPERATOR_IN_REVERSE;
case CAIRO_OPERATOR_OUT:
return GLITZ_OPERATOR_OUT;
- case CAIRO_OPERATOR_OUT_REVERSE:
- return GLITZ_OPERATOR_OUT_REVERSE;
case CAIRO_OPERATOR_ATOP:
return GLITZ_OPERATOR_ATOP;
- case CAIRO_OPERATOR_ATOP_REVERSE:
+
+ case CAIRO_OPERATOR_DEST:
+ return GLITZ_OPERATOR_DST;
+ case CAIRO_OPERATOR_DEST_OVER:
+ return GLITZ_OPERATOR_OVER_REVERSE;
+ case CAIRO_OPERATOR_DEST_IN:
+ return GLITZ_OPERATOR_IN_REVERSE;
+ case CAIRO_OPERATOR_DEST_OUT:
+ return GLITZ_OPERATOR_OUT_REVERSE;
+ case CAIRO_OPERATOR_DEST_ATOP:
return GLITZ_OPERATOR_ATOP_REVERSE;
+
case CAIRO_OPERATOR_XOR:
return GLITZ_OPERATOR_XOR;
case CAIRO_OPERATOR_ADD:
return GLITZ_OPERATOR_ADD;
- case CAIRO_OPERATOR_OVER:
- default:
+ case CAIRO_OPERATOR_SATURATE:
+ /* XXX: OVER is definitely not the right thing here, (but it
+ * is what the original glitz backend code has always
+ * done). Cairo's SATURATE operator is the native GL
+ * compositing mode, (from my understanding). So why isn't
+ * there a GLITZ_OPERATOR_SATURATE for us to use here? */
return GLITZ_OPERATOR_OVER;
}
+
+ ASSERT_NOT_REACHED;
+
+ /* Something's very broken if this line of code can be reached, so
+ we want to return something that would give a noticeably
+ incorrect result. The XOR operator seems so rearely desired
+ that it should fit the bill here. */
+ return CAIRO_OPERATOR_XOR;
}
static glitz_status_t
@@ -586,12 +579,12 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
pattern->filter != CAIRO_FILTER_BEST)
break;
- alpha = (gradient->stops[0].color.alpha * pattern->alpha) * 0xffff;
+ alpha = (gradient->stops[0].color.alpha) * 0xffff;
for (i = 1; i < gradient->n_stops; i++)
{
unsigned short a;
- a = (gradient->stops[i].color.alpha * pattern->alpha) * 0xffff;
+ a = (gradient->stops[i].color.alpha) * 0xffff;
if (a != alpha)
break;
}
@@ -733,7 +726,7 @@ _cairo_glitz_pattern_release_surface (cairo_glitz_surface_t *dst,
_cairo_pattern_release_surface (&dst->base, &surface->base,
&attr->base);
else
- _cairo_glitz_surface_destroy (surface);
+ cairo_surface_destroy (&surface->base);
}
static cairo_int_status_t
@@ -753,50 +746,30 @@ _cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src,
{
cairo_int_status_t status;
cairo_pattern_union_t tmp;
- cairo_bool_t src_opaque, mask_opaque;
- double src_alpha, mask_alpha;
- src_opaque = _cairo_pattern_is_opaque (src);
- mask_opaque = !mask || _cairo_pattern_is_opaque (mask);
-
- /* For surface patterns, we move any translucency from src->alpha
- * to mask->alpha so we can use the source unchanged. Otherwise we
- * move the translucency from mask->alpha to src->alpha so that
- * we can drop the mask if possible.
- */
- if (src->type == CAIRO_PATTERN_SURFACE)
- {
- if (mask) {
- mask_opaque = mask_opaque && src_opaque;
- mask_alpha = mask->alpha * src->alpha;
- } else {
- mask_opaque = src_opaque;
- mask_alpha = src->alpha;
- }
-
- src_alpha = 1.0;
- src_opaque = TRUE;
- }
- else
+ /* If src and mask are both solid, then the mask alpha can be
+ * combined into src and mask can be ignored. */
+
+ /* XXX: This optimization assumes that there is no color
+ * information in mask, so this will need to change when we
+ * support RENDER-style 4-channel masks. */
+
+ if (src->type == CAIRO_PATTERN_SOLID &&
+ mask->type == CAIRO_PATTERN_SOLID)
{
- if (mask)
- {
- src_opaque = mask_opaque && src_opaque;
- src_alpha = mask->alpha * src->alpha;
- /* FIXME: This needs changing when we support RENDER
- * style 4-channel masks.
- */
- if (mask->type == CAIRO_PATTERN_SOLID)
- mask = NULL;
- } else
- src_alpha = src->alpha;
+ cairo_color_t combined;
+ cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src;
+ cairo_solid_pattern_t *mask_solid = (cairo_solid_pattern_t *) mask;
- mask_alpha = 1.0;
- mask_opaque = TRUE;
- }
+ combined = src_solid->color;
+ _cairo_color_multiply_alpha (&combined, mask_solid->color.alpha);
- _cairo_pattern_init_copy (&tmp.base, src);
- _cairo_pattern_set_alpha (&tmp.base, src_alpha);
+ _cairo_pattern_init_solid (&tmp.solid, &combined);
+
+ mask = NULL;
+ } else {
+ _cairo_pattern_init_copy (&tmp.base, src);
+ }
status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst,
src_x, src_y,
@@ -808,14 +781,9 @@ _cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src,
if (status)
return status;
- if (mask || !mask_opaque)
+ if (mask)
{
- if (mask)
- _cairo_pattern_init_copy (&tmp.base, mask);
- else
- _cairo_pattern_init_solid (&tmp.solid, 0.0, 0.0, 0.0);
-
- _cairo_pattern_set_alpha (&tmp.base, mask_alpha);
+ _cairo_pattern_init_copy (&tmp.base, mask);
status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst,
mask_x, mask_y,
@@ -937,7 +905,7 @@ _cairo_glitz_surface_fill_rectangles (void *abstract_dst,
{
cairo_glitz_surface_t *dst = abstract_dst;
- if (op == CAIRO_OPERATOR_SRC)
+ if (op == CAIRO_OPERATOR_SOURCE)
{
glitz_color_t glitz_color;
@@ -969,6 +937,8 @@ _cairo_glitz_surface_fill_rectangles (void *abstract_dst,
(cairo_color_t *) color);
if (!src)
return CAIRO_STATUS_NO_MEMORY;
+
+ glitz_surface_set_fill (src->surface, GLITZ_FILL_REPEAT);
while (n_rects--)
{
@@ -1025,7 +995,6 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
cairo_pattern_union_t tmp;
_cairo_pattern_init_copy (&tmp.base, pattern);
- _cairo_pattern_set_alpha (&tmp.base, 1.0);
status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst,
src_x, src_y,
@@ -1033,8 +1002,6 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
&src, &attributes);
_cairo_pattern_fini (&tmp.base);
-
- alpha = pattern->alpha * 0xffff;
}
else
{
@@ -1042,8 +1009,8 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
src_x, src_y,
width, height,
&src, &attributes);
- alpha = 0xffff;
}
+ alpha = 0xffff;
if (status)
return status;
@@ -1076,7 +1043,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
return CAIRO_INT_STATUS_UNSUPPORTED;
}
- color.red = color.green = color.blue = color.alpha = alpha;
+ color.red = color.green = color.blue = color.alpha = 0xffff;
glitz_set_rectangle (mask->surface, &clear_black, 0, 0, 1, 1);
glitz_set_rectangle (mask->surface, &color, 1, 0, 1, 1);
@@ -1135,7 +1102,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
else
{
cairo_image_surface_t *image;
- char *ptr;
+ unsigned char *ptr;
int stride;
stride = (width + 3) & -4;
@@ -1149,7 +1116,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
memset (data, 0, stride * height);
/* using negative stride */
- ptr = (char *) data + stride * (height - 1);
+ ptr = (unsigned char *) data + stride * (height - 1);
image = (cairo_image_surface_t *)
cairo_image_surface_create_for_data (ptr,
@@ -1166,18 +1133,6 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
pixman_add_trapezoids (image->pixman_image, -dst_x, -dst_y,
(pixman_trapezoid_t *) traps, n_traps);
- if (alpha != 0xffff)
- {
- pixman_color_t color;
-
- color.red = color.green = color.blue = color.alpha = alpha;
-
- pixman_fill_rectangle (PIXMAN_OPERATOR_IN,
- image->pixman_image,
- &color,
- 0, 0, width, height);
- }
-
mask = (cairo_glitz_surface_t *)
_cairo_surface_create_similar_scratch (&dst->base,
CAIRO_FORMAT_A8, 0,
@@ -1228,18 +1183,6 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
}
static cairo_int_status_t
-_cairo_glitz_surface_copy_page (void *abstract_surface)
-{
- return CAIRO_INT_STATUS_UNSUPPORTED;
-}
-
-static cairo_int_status_t
-_cairo_glitz_surface_show_page (void *abstract_surface)
-{
- return CAIRO_INT_STATUS_UNSUPPORTED;
-}
-
-static cairo_int_status_t
_cairo_glitz_surface_set_clip_region (void *abstract_surface,
pixman_region16_t *region)
{
@@ -1275,10 +1218,902 @@ _cairo_glitz_surface_set_clip_region (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
+static cairo_int_status_t
+_cairo_glitz_surface_get_extents (void *abstract_surface,
+ cairo_rectangle_t *rectangle)
+{
+ cairo_glitz_surface_t *surface = abstract_surface;
+
+ rectangle->x = 0;
+ rectangle->y = 0;
+ rectangle->width = glitz_surface_get_width (surface->surface);
+ rectangle->height = glitz_surface_get_height (surface->surface);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+#define CAIRO_GLITZ_GLYPH_CACHE_MEMORY_DEFAULT 0x100000
+
+#define CAIRO_GLITZ_AREA_AVAILABLE 0
+#define CAIRO_GLITZ_AREA_DIVIDED 1
+#define CAIRO_GLITZ_AREA_OCCUPIED 2
+
+typedef struct _cairo_glitz_root_area cairo_glitz_root_area_t;
+
+typedef struct _cairo_glitz_area {
+ int state;
+ int level;
+ int x, y;
+ int width, height;
+ struct _cairo_glitz_area *area[4];
+ cairo_glitz_root_area_t *root;
+ void *closure;
+} cairo_glitz_area_t;
+
+static cairo_glitz_area_t _empty_area = {
+ 0, 0, 0, 0, 0, 0,
+ { NULL, NULL, NULL, NULL },
+ NULL,
+ NULL
+};
+
+typedef struct _cairo_glitz_area_funcs {
+ cairo_status_t (*move_in) (cairo_glitz_area_t *area,
+ void *closure);
+
+ void (*move_out) (cairo_glitz_area_t *area,
+ void *closure);
+
+ int (*compare_score) (cairo_glitz_area_t *area,
+ void *closure1,
+ void *closure2);
+} cairo_glitz_area_funcs_t;
+
+struct _cairo_glitz_root_area {
+ int max_level;
+ int width, height;
+ cairo_glitz_area_t *area;
+ const cairo_glitz_area_funcs_t *funcs;
+};
+
+static cairo_status_t
+_cairo_glitz_area_move_in (cairo_glitz_area_t *area,
+ void *closure)
+{
+ area->closure = closure;
+ area->state = CAIRO_GLITZ_AREA_OCCUPIED;
+
+ return (*area->root->funcs->move_in) (area, area->closure);
+}
+
+static void
+_cairo_glitz_area_move_out (cairo_glitz_area_t *area)
+{
+ (*area->root->funcs->move_out) (area, area->closure);
+
+ area->closure = NULL;
+ area->state = CAIRO_GLITZ_AREA_AVAILABLE;
+}
+
+static cairo_glitz_area_t *
+_cairo_glitz_area_create (cairo_glitz_root_area_t *root,
+ int level,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ cairo_glitz_area_t *area;
+ int n = 4;
+
+ area = malloc (sizeof (cairo_glitz_area_t));
+ if (!area)
+ return NULL;
+
+ area->level = level;
+ area->x = x;
+ area->y = y;
+ area->width = width;
+ area->height = height;
+ area->root = root;
+ area->closure = NULL;
+ area->state = CAIRO_GLITZ_AREA_AVAILABLE;
+
+ while (n--)
+ area->area[n] = NULL;
+
+ return area;
+}
+
+static void
+_cairo_glitz_area_destroy (cairo_glitz_area_t *area)
+{
+ if (!area)
+ return;
+
+ if (area->state == CAIRO_GLITZ_AREA_OCCUPIED)
+ {
+ _cairo_glitz_area_move_out (area);
+ }
+ else
+ {
+ int n = 4;
+
+ while (n--)
+ _cairo_glitz_area_destroy (area->area[n]);
+ }
+
+ free (area);
+}
+
+static cairo_glitz_area_t *
+_cairo_glitz_area_get_top_scored_sub_area (cairo_glitz_area_t *area)
+{
+ if (!area)
+ return NULL;
+
+ switch (area->state) {
+ case CAIRO_GLITZ_AREA_OCCUPIED:
+ return area;
+ case CAIRO_GLITZ_AREA_AVAILABLE:
+ break;
+ case CAIRO_GLITZ_AREA_DIVIDED: {
+ cairo_glitz_area_t *tmp, *top = NULL;
+ int i;
+
+ for (i = 0; i < 4; i++)
+ {
+ tmp = _cairo_glitz_area_get_top_scored_sub_area (area->area[i]);
+ if (tmp && top)
+ {
+ if ((*area->root->funcs->compare_score) (tmp,
+ tmp->closure,
+ top->closure) > 0)
+ top = tmp;
+ }
+ else if (tmp)
+ {
+ top = tmp;
+ }
+ }
+ return top;
+ }
+ }
+
+ return NULL;
+}
+
+static cairo_int_status_t
+_cairo_glitz_area_find (cairo_glitz_area_t *area,
+ int width,
+ int height,
+ cairo_bool_t kick_out,
+ void *closure)
+{
+ if (area->width < width || area->height < height)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ switch (area->state) {
+ case CAIRO_GLITZ_AREA_OCCUPIED:
+ if (kick_out)
+ {
+ if ((*area->root->funcs->compare_score) (area,
+ area->closure,
+ closure) >= 0)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ _cairo_glitz_area_move_out (area);
+ } else
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ /* fall-through */
+ case CAIRO_GLITZ_AREA_AVAILABLE: {
+ if (area->level == area->root->max_level ||
+ (area->width == width && area->height == height))
+ {
+ return _cairo_glitz_area_move_in (area, closure);
+ }
+ else
+ {
+ int dx[4], dy[4], w[4], h[4], i;
+
+ dx[0] = dx[2] = dy[0] = dy[1] = 0;
+
+ w[0] = w[2] = dx[1] = dx[3] = width;
+ h[0] = h[1] = dy[2] = dy[3] = height;
+
+ w[1] = w[3] = area->width - width;
+ h[2] = h[3] = area->height - height;
+
+ for (i = 0; i < 2; i++)
+ {
+ if (w[i])
+ area->area[i] =
+ _cairo_glitz_area_create (area->root,
+ area->level + 1,
+ area->x + dx[i],
+ area->y + dy[i],
+ w[i], h[i]);
+ }
+
+ for (; i < 4; i++)
+ {
+ if (w[i] && h[i])
+ area->area[i] =
+ _cairo_glitz_area_create (area->root,
+ area->level + 1,
+ area->x + dx[i],
+ area->y + dy[i],
+ w[i], h[i]);
+ }
+
+ area->state = CAIRO_GLITZ_AREA_DIVIDED;
+
+ if (CAIRO_OK (_cairo_glitz_area_find (area->area[0],
+ width, height,
+ kick_out, closure)))
+ return CAIRO_STATUS_SUCCESS;
+ }
+ } break;
+ case CAIRO_GLITZ_AREA_DIVIDED: {
+ cairo_glitz_area_t *to_area;
+ int i, rejected = FALSE;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (area->area[i])
+ {
+ if (area->area[i]->width >= width &&
+ area->area[i]->height >= height)
+ {
+ if (CAIRO_OK (_cairo_glitz_area_find (area->area[i],
+ width, height,
+ kick_out, closure)))
+ return CAIRO_STATUS_SUCCESS;
+
+ rejected = TRUE;
+ }
+ }
+ }
+
+ if (rejected)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ to_area = _cairo_glitz_area_get_top_scored_sub_area (area);
+ if (to_area)
+ {
+ if (kick_out)
+ {
+ if ((*area->root->funcs->compare_score) (to_area,
+ to_area->closure,
+ closure) >= 0)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ } else
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ _cairo_glitz_area_destroy (area->area[i]);
+ area->area[i] = NULL;
+ }
+
+ area->closure = NULL;
+ area->state = CAIRO_GLITZ_AREA_AVAILABLE;
+ if (CAIRO_OK (_cairo_glitz_area_find (area, width, height,
+ TRUE, closure)))
+ return CAIRO_STATUS_SUCCESS;
+
+ } break;
+ }
+
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+static cairo_status_t
+_cairo_glitz_root_area_init (cairo_glitz_root_area_t *root,
+ int max_level,
+ int width,
+ int height,
+ const cairo_glitz_area_funcs_t *funcs)
+{
+ root->max_level = max_level;
+ root->funcs = funcs;
+
+ root->area = _cairo_glitz_area_create (root, 0, 0, 0, width, height);
+ if (!root->area)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_glitz_root_area_fini (cairo_glitz_root_area_t *root)
+{
+ _cairo_glitz_area_destroy (root->area);
+}
+
+#define GLYPH_CACHE_TEXTURE_SIZE 512
+#define GLYPH_CACHE_MAX_LEVEL 64
+#define GLYPH_CACHE_MAX_HEIGHT 72
+#define GLYPH_CACHE_MAX_WIDTH 72
+
+#define WRITE_VEC2(ptr, _x, _y) \
+ *(ptr)++ = (_x); \
+ *(ptr)++ = (_y)
+
+#define WRITE_BOX(ptr, _vx1, _vy1, _vx2, _vy2, p1, p2) \
+ WRITE_VEC2 (ptr, _vx1, _vy1); \
+ WRITE_VEC2 (ptr, (p1)->x, (p2)->y); \
+ WRITE_VEC2 (ptr, _vx2, _vy1); \
+ WRITE_VEC2 (ptr, (p2)->x, (p2)->y); \
+ WRITE_VEC2 (ptr, _vx2, _vy2); \
+ WRITE_VEC2 (ptr, (p2)->x, (p1)->y); \
+ WRITE_VEC2 (ptr, _vx1, _vy2); \
+ WRITE_VEC2 (ptr, (p1)->x, (p1)->y)
+
+typedef struct _cairo_glitz_glyph_cache {
+ cairo_cache_t base;
+ cairo_glitz_root_area_t root;
+ glitz_surface_t *surface;
+} cairo_glitz_glyph_cache_t;
+
+typedef struct {
+ cairo_glyph_cache_key_t key;
+ int refcount;
+ cairo_glyph_size_t size;
+ cairo_glitz_area_t *area;
+ cairo_bool_t locked;
+ cairo_point_double_t p1, p2;
+} cairo_glitz_glyph_cache_entry_t;
+
+static cairo_status_t
+_cairo_glitz_glyph_move_in (cairo_glitz_area_t *area,
+ void *closure)
+{
+ cairo_glitz_glyph_cache_entry_t *entry = closure;
+
+ entry->area = area;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_glitz_glyph_move_out (cairo_glitz_area_t *area,
+ void *closure)
+{
+ cairo_glitz_glyph_cache_entry_t *entry = closure;
+
+ entry->area = NULL;
+}
+
+static int
+_cairo_glitz_glyph_compare (cairo_glitz_area_t *area,
+ void *closure1,
+ void *closure2)
+{
+ cairo_glitz_glyph_cache_entry_t *entry = closure1;
+
+ if (entry->locked)
+ return 1;
+
+ return -1;
+}
+
+static const cairo_glitz_area_funcs_t _cairo_glitz_area_funcs = {
+ _cairo_glitz_glyph_move_in,
+ _cairo_glitz_glyph_move_out,
+ _cairo_glitz_glyph_compare
+};
+
+static cairo_status_t
+_cairo_glitz_glyph_cache_entry_create (void *abstract_cache,
+ void *abstract_key,
+ void **return_entry)
+{
+ cairo_glitz_glyph_cache_entry_t *entry;
+ cairo_glyph_cache_key_t *key = abstract_key;
+
+ entry = malloc (sizeof (cairo_glitz_glyph_cache_entry_t));
+ if (!entry)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ entry->refcount = 1;
+ entry->key = *key;
+ entry->area = NULL;
+ entry->locked = FALSE;
+
+ _cairo_unscaled_font_reference (entry->key.unscaled);
+
+ *return_entry = entry;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_glitz_glyph_cache_entry_destroy (void *abstract_cache,
+ void *abstract_entry)
+{
+ cairo_glitz_glyph_cache_entry_t *entry = abstract_entry;
+
+ entry->refcount--;
+ if (entry->refcount)
+ return;
+
+ if (entry->area)
+ _cairo_glitz_area_move_out (entry->area);
+
+ _cairo_unscaled_font_destroy (entry->key.unscaled);
+
+ free (entry);
+}
+
+static void
+_cairo_glitz_glyph_cache_entry_reference (void *abstract_entry)
+{
+ cairo_glitz_glyph_cache_entry_t *entry = abstract_entry;
+
+ entry->refcount++;
+}
+
+static void
+_cairo_glitz_glyph_cache_destroy (void *abstract_cache)
+{
+ cairo_glitz_glyph_cache_t *cache = abstract_cache;
+
+ _cairo_glitz_root_area_fini (&cache->root);
+
+ glitz_surface_destroy (cache->surface);
+}
+
+static const cairo_cache_backend_t _cairo_glitz_glyph_cache_backend = {
+ _cairo_glyph_cache_hash,
+ _cairo_glyph_cache_keys_equal,
+ _cairo_glitz_glyph_cache_entry_create,
+ _cairo_glitz_glyph_cache_entry_destroy,
+ _cairo_glitz_glyph_cache_destroy
+};
+
+static cairo_glitz_glyph_cache_t *_cairo_glitz_glyph_caches = NULL;
+
+static cairo_glitz_glyph_cache_t *
+_cairo_glitz_get_glyph_cache (cairo_glitz_surface_t *surface)
+{
+ cairo_glitz_glyph_cache_t *cache;
+ glitz_drawable_t *drawable;
+ glitz_format_t *format;
+
+ /*
+ * FIXME: caches should be thread specific, display specific and screen
+ * specific.
+ */
+
+ if (_cairo_glitz_glyph_caches)
+ return _cairo_glitz_glyph_caches;
+
+ drawable = glitz_surface_get_drawable (surface->surface);
+
+ format = glitz_find_standard_format (drawable, GLITZ_STANDARD_A8);
+ if (!format)
+ return NULL;
+
+ cache = malloc (sizeof (cairo_glitz_glyph_cache_t));
+ if (!cache)
+ return NULL;
+
+ cache->surface =
+ glitz_surface_create (drawable, format,
+ GLYPH_CACHE_TEXTURE_SIZE,
+ GLYPH_CACHE_TEXTURE_SIZE,
+ 0, NULL);
+ if (!cache->surface)
+ {
+ free (cache);
+ return NULL;
+ }
+
+ if (_cairo_glitz_root_area_init (&cache->root,
+ GLYPH_CACHE_MAX_LEVEL,
+ GLYPH_CACHE_TEXTURE_SIZE,
+ GLYPH_CACHE_TEXTURE_SIZE,
+ &_cairo_glitz_area_funcs))
+ {
+ glitz_surface_destroy (cache->surface);
+ free (cache);
+ return NULL;
+ }
+
+ if (_cairo_cache_init (&cache->base,
+ &_cairo_glitz_glyph_cache_backend,
+ CAIRO_GLITZ_GLYPH_CACHE_MEMORY_DEFAULT))
+ {
+ _cairo_glitz_root_area_fini (&cache->root);
+ glitz_surface_destroy (cache->surface);
+ free (cache);
+ return NULL;
+ }
+
+ _cairo_glitz_glyph_caches = cache;
+
+ return cache;
+}
+
+#define FIXED_TO_FLOAT(f) (((glitz_float_t) (f)) / 65536)
+
+static cairo_status_t
+_cairo_glitz_cache_glyph (cairo_glitz_glyph_cache_t *cache,
+ cairo_glitz_glyph_cache_entry_t *entry,
+ cairo_image_glyph_cache_entry_t *image_entry)
+{
+ glitz_point_fixed_t p1, p2;
+ glitz_pixel_format_t pf;
+ glitz_buffer_t *buffer;
+ pixman_format_t *format;
+ int am, rm, gm, bm;
+
+ entry->size = image_entry->size;
+
+ if (entry->size.width > GLYPH_CACHE_MAX_WIDTH ||
+ entry->size.height > GLYPH_CACHE_MAX_HEIGHT)
+ return CAIRO_STATUS_SUCCESS;
+
+ if (!image_entry->image)
+ {
+ entry->area = &_empty_area;
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ format = pixman_image_get_format (image_entry->image->pixman_image);
+ if (!format)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ if (_cairo_glitz_area_find (cache->root.area,
+ entry->size.width,
+ entry->size.height,
+ FALSE, entry))
+ {
+ if (_cairo_glitz_area_find (cache->root.area,
+ entry->size.width,
+ entry->size.height,
+ TRUE, entry))
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ buffer = glitz_buffer_create_for_data (image_entry->image->data);
+ if (!buffer)
+ {
+ _cairo_glitz_area_move_out (entry->area);
+ return CAIRO_STATUS_NO_MEMORY;
+ }
+
+ pixman_format_get_masks (format, &pf.masks.bpp, &am, &rm, &gm, &bm);
+
+ pf.masks.alpha_mask = am;
+ pf.masks.red_mask = rm;
+ pf.masks.green_mask = gm;
+ pf.masks.blue_mask = bm;
+
+ pf.bytes_per_line = image_entry->image->stride;
+ pf.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP;
+ pf.xoffset = 0;
+ pf.skip_lines = 0;
+
+ glitz_set_pixels (cache->surface,
+ entry->area->x,
+ entry->area->y,
+ entry->size.width,
+ entry->size.height,
+ &pf, buffer);
+
+ glitz_buffer_destroy (buffer);
+
+ p1.x = entry->area->x << 16;
+ p1.y = entry->area->y << 16;
+ p2.x = (entry->area->x + entry->size.width) << 16;
+ p2.y = (entry->area->y + entry->size.height) << 16;
+
+ glitz_surface_translate_point (cache->surface, &p1, &p1);
+ glitz_surface_translate_point (cache->surface, &p2, &p2);
+
+ entry->p1.x = FIXED_TO_FLOAT (p1.x);
+ entry->p1.y = FIXED_TO_FLOAT (p1.y);
+ entry->p2.x = FIXED_TO_FLOAT (p2.x);
+ entry->p2.y = FIXED_TO_FLOAT (p2.y);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+#define N_STACK_BUF 256
+
+static cairo_int_status_t
+_cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
+ cairo_operator_t op,
+ cairo_pattern_t *pattern,
+ void *abstract_surface,
+ int src_x,
+ int src_y,
+ int dst_x,
+ int dst_y,
+ unsigned int width,
+ unsigned int height,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs)
+{
+ cairo_glitz_surface_attributes_t attributes;
+ cairo_glitz_surface_t *dst = abstract_surface;
+ cairo_glitz_surface_t *src;
+ cairo_glitz_glyph_cache_t *cache;
+ cairo_glitz_glyph_cache_entry_t *stack_entries[N_STACK_BUF];
+ cairo_glitz_glyph_cache_entry_t **entries;
+ cairo_glyph_cache_key_t key;
+ glitz_float_t stack_vertices[N_STACK_BUF * 16];
+ glitz_float_t *vertices;
+ glitz_buffer_t *buffer;
+ cairo_int_status_t status;
+ int i, cached_glyphs = 0;
+ int remaining_glyps = num_glyphs;
+ glitz_float_t x1, y1, x2, y2;
+ static glitz_vertex_format_t format = {
+ GLITZ_PRIMITIVE_QUADS,
+ GLITZ_DATA_TYPE_FLOAT,
+ sizeof (glitz_float_t) * 4,
+ GLITZ_VERTEX_ATTRIBUTE_MASK_COORD_MASK,
+ { 0 },
+ {
+ GLITZ_DATA_TYPE_FLOAT,
+ GLITZ_COORDINATE_SIZE_XY,
+ sizeof (glitz_float_t) * 2,
+ }
+ };
+
+ if (op == CAIRO_OPERATOR_SATURATE)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ if (_glitz_ensure_target (dst->surface))
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ status = _cairo_glitz_pattern_acquire_surface (pattern, dst,
+ src_x, src_y,
+ width, height,
+ &src, &attributes);
+ if (status)
+ return status;
+
+ _cairo_glitz_surface_set_attributes (src, &attributes);
+
+ if (num_glyphs > N_STACK_BUF)
+ {
+ char *data;
+
+ data = malloc (num_glyphs * sizeof (void *) +
+ num_glyphs * sizeof (glitz_float_t) * 16);
+ if (!data)
+ goto FAIL1;
+
+ entries = (cairo_glitz_glyph_cache_entry_t **) data;
+ vertices = (glitz_float_t *) (data + num_glyphs * sizeof (void *));
+ }
+ else
+ {
+ entries = stack_entries;
+ vertices = stack_vertices;
+ }
+
+ buffer = glitz_buffer_create_for_data (vertices);
+ if (!buffer)
+ goto FAIL2;
+
+ cache = _cairo_glitz_get_glyph_cache (dst);
+ if (!cache)
+ {
+ num_glyphs = 0;
+ goto UNLOCK;
+ }
+
+ _cairo_scaled_font_get_glyph_cache_key (scaled_font, &key);
+
+ for (i = 0; i < num_glyphs; i++)
+ {
+ key.index = glyphs[i].index;
+
+ status = _cairo_cache_lookup (&cache->base,
+ &key,
+ (void **) &entries[i],
+ NULL);
+ if (status)
+ {
+ num_glyphs = i;
+ goto UNLOCK;
+ }
+
+ _cairo_glitz_glyph_cache_entry_reference (entries[i]);
+
+ if (entries[i]->area)
+ {
+ remaining_glyps--;
+
+ if (entries[i]->area->width)
+ {
+ x1 = floor (glyphs[i].x + 0.5) + entries[i]->size.x;
+ y1 = floor (glyphs[i].y + 0.5) + entries[i]->size.y;
+ x2 = x1 + entries[i]->size.width;
+ y2 = y1 + entries[i]->size.height;
+
+ WRITE_BOX (vertices, x1, y1, x2, y2,
+ &entries[i]->p1, &entries[i]->p2);
+
+ entries[i]->locked = TRUE;
+ cached_glyphs++;
+ }
+ }
+ }
+
+ if (remaining_glyps)
+ {
+ cairo_cache_t *image_cache;
+ cairo_image_glyph_cache_entry_t *image_entry;
+ cairo_surface_t *image;
+ cairo_glitz_surface_t *clone;
+
+ _cairo_lock_global_image_glyph_cache ();
+
+ image_cache = _cairo_get_global_image_glyph_cache ();
+ if (!image_cache)
+ {
+ _cairo_unlock_global_image_glyph_cache ();
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto UNLOCK;
+ }
+
+ for (i = 0; i < num_glyphs; i++)
+ {
+ if (!entries[i]->area)
+ {
+ key.index = glyphs[i].index;
+
+ status = _cairo_cache_lookup (image_cache,
+ &key,
+ (void **) &image_entry,
+ NULL);
+ if (status)
+ {
+ _cairo_unlock_global_image_glyph_cache ();
+ goto UNLOCK;
+ }
+
+ status = _cairo_glitz_cache_glyph (cache,
+ entries[i],
+ image_entry);
+ if (status)
+ {
+ _cairo_unlock_global_image_glyph_cache ();
+ goto UNLOCK;
+ }
+ }
+
+ x1 = floor (glyphs[i].x + 0.5);
+ y1 = floor (glyphs[i].y + 0.5);
+
+ if (entries[i]->area)
+ {
+ if (entries[i]->area->width)
+ {
+ x1 += entries[i]->size.x;
+ y1 += entries[i]->size.y;
+ x2 = x1 + entries[i]->size.width;
+ y2 = y1 + entries[i]->size.height;
+
+ WRITE_BOX (vertices, x1, y1, x2, y2,
+ &entries[i]->p1, &entries[i]->p2);
+
+ entries[i]->locked = TRUE;
+ cached_glyphs++;
+ }
+ }
+ else
+ {
+ x1 += image_entry->size.x;
+ y1 += image_entry->size.y;
+
+ if (!image_entry->image)
+ continue;
+
+ image = &image_entry->image->base;
+ status =
+ _cairo_glitz_surface_clone_similar (abstract_surface,
+ image,
+ (cairo_surface_t **)
+ &clone);
+ if (status)
+ {
+ _cairo_unlock_global_image_glyph_cache ();
+ goto UNLOCK;
+ }
+
+ glitz_composite (_glitz_operator (op),
+ src->surface,
+ clone->surface,
+ dst->surface,
+ src_x + attributes.base.x_offset + x1,
+ src_y + attributes.base.y_offset + y1,
+ 0, 0,
+ x1, y1,
+ image_entry->size.width,
+ image_entry->size.height);
+
+ cairo_surface_destroy (&clone->base);
+
+ if (glitz_surface_get_status (dst->surface) ==
+ GLITZ_STATUS_NOT_SUPPORTED)
+ {
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
+ _cairo_unlock_global_image_glyph_cache ();
+ goto UNLOCK;
+ }
+ }
+ }
+
+ _cairo_unlock_global_image_glyph_cache ();
+ }
+
+ if (cached_glyphs)
+ {
+ glitz_set_geometry (dst->surface,
+ GLITZ_GEOMETRY_TYPE_VERTEX,
+ (glitz_geometry_format_t *) &format,
+ buffer);
+
+ glitz_set_array (dst->surface, 0, 4, cached_glyphs * 4, 0, 0);
+
+ glitz_composite (_glitz_operator (op),
+ src->surface,
+ cache->surface,
+ dst->surface,
+ src_x + attributes.base.x_offset,
+ src_y + attributes.base.y_offset,
+ 0, 0,
+ dst_x, dst_y,
+ width, height);
+
+ glitz_set_geometry (dst->surface,
+ GLITZ_GEOMETRY_TYPE_NONE,
+ NULL, NULL);
+ }
+
+UNLOCK:
+ if (cached_glyphs)
+ {
+ for (i = 0; i < num_glyphs; i++)
+ entries[i]->locked = FALSE;
+ }
+
+ for (i = 0; i < num_glyphs; i++)
+ _cairo_glitz_glyph_cache_entry_destroy (cache, entries[i]);
+
+ glitz_buffer_destroy (buffer);
+
+ FAIL2:
+ if (num_glyphs > N_STACK_BUF)
+ free (entries);
+
+ FAIL1:
+ if (attributes.n_params)
+ free (attributes.params);
+
+ _cairo_glitz_pattern_release_surface (dst, src, &attributes);
+
+ if (status)
+ return status;
+
+ if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
static const cairo_surface_backend_t cairo_glitz_surface_backend = {
_cairo_glitz_surface_create_similar,
- _cairo_glitz_surface_destroy,
- _cairo_glitz_surface_pixels_per_inch,
+ _cairo_glitz_surface_finish,
_cairo_glitz_surface_acquire_source_image,
_cairo_glitz_surface_release_source_image,
_cairo_glitz_surface_acquire_dest_image,
@@ -1287,10 +2122,11 @@ static const cairo_surface_backend_t cairo_glitz_surface_backend = {
_cairo_glitz_surface_composite,
_cairo_glitz_surface_fill_rectangles,
_cairo_glitz_surface_composite_trapezoids,
- _cairo_glitz_surface_copy_page,
- _cairo_glitz_surface_show_page,
+ NULL, /* copy_page */
+ NULL, /* show_page */
_cairo_glitz_surface_set_clip_region,
- NULL /* show_glyphs */
+ _cairo_glitz_surface_get_extents,
+ _cairo_glitz_surface_show_glyphs
};
cairo_surface_t *
diff --git a/src/cairo-glitz.h b/src/cairo-glitz.h
index f1917eb28..f5b4f2815 100644
--- a/src/cairo-glitz.h
+++ b/src/cairo-glitz.h
@@ -39,20 +39,19 @@
#include <cairo.h>
-#ifdef CAIRO_HAS_GLITZ_SURFACE
+#if CAIRO_HAS_GLITZ_SURFACE
#include <glitz.h>
CAIRO_BEGIN_DECLS
-void
-cairo_set_target_glitz (cairo_t *cr,
- glitz_surface_t *surface);
-
cairo_surface_t *
cairo_glitz_surface_create (glitz_surface_t *surface);
CAIRO_END_DECLS
+#else /* CAIRO_HAS_GLITZ_SURFACE */
+# error Cairo was not compiled with support for the glitz backend
#endif /* CAIRO_HAS_GLITZ_SURFACE */
+
#endif /* CAIRO_GLITZ_H */
diff --git a/src/cairo-gstate-private.h b/src/cairo-gstate-private.h
new file mode 100644
index 000000000..eeb35b83e
--- /dev/null
+++ b/src/cairo-gstate-private.h
@@ -0,0 +1,80 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ * Carl D. Worth <cworth@redhat.com>
+ */
+
+#ifndef CAIRO_GSTATE_PRIVATE_H
+#define CAIRO_GSTATE_PRIVATE_H
+
+struct _cairo_gstate {
+ cairo_operator_t operator;
+
+ double tolerance;
+
+ /* stroke style */
+ double line_width;
+ cairo_line_cap_t line_cap;
+ cairo_line_join_t line_join;
+ double miter_limit;
+
+ cairo_fill_rule_t fill_rule;
+
+ double *dash;
+ int num_dashes;
+ double dash_offset;
+
+ char *font_family; /* NULL means CAIRO_FONT_FAMILY_DEFAULT; */
+ cairo_font_slant_t font_slant;
+ cairo_font_weight_t font_weight;
+
+ cairo_font_face_t *font_face;
+ cairo_scaled_font_t *scaled_font; /* Specific to the current CTM */
+
+ cairo_surface_t *surface;
+ int surface_level; /* Used to detect bad nested use */
+
+ cairo_pattern_t *source;
+
+ cairo_clip_rec_t clip;
+
+ cairo_matrix_t font_matrix;
+
+ cairo_matrix_t ctm;
+ cairo_matrix_t ctm_inverse;
+
+ cairo_pen_t pen_regular;
+
+ struct _cairo_gstate *next;
+};
+
+#endif /* CAIRO_GSTATE_PRIVATE_H */
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index d6db560a3..45c729fc9 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.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
@@ -35,10 +36,15 @@
*/
#include <stdlib.h>
-#include <math.h>
#include "cairoint.h"
+#include "cairo-gstate-private.h"
+
+static cairo_status_t
+_cairo_gstate_set_target_surface (cairo_gstate_t *gstate,
+ cairo_surface_t *surface);
+
static cairo_status_t
_cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
cairo_pattern_t *src,
@@ -49,11 +55,14 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
static cairo_status_t
_cairo_gstate_ensure_font (cairo_gstate_t *gstate);
+static cairo_status_t
+_cairo_gstate_ensure_font_face (cairo_gstate_t *gstate);
+
static void
_cairo_gstate_unset_font (cairo_gstate_t *gstate);
cairo_gstate_t *
-_cairo_gstate_create ()
+_cairo_gstate_create (cairo_surface_t *target)
{
cairo_status_t status;
cairo_gstate_t *gstate;
@@ -62,7 +71,7 @@ _cairo_gstate_create ()
if (gstate)
{
- status = _cairo_gstate_init (gstate);
+ status = _cairo_gstate_init (gstate, target);
if (status) {
free (gstate);
return NULL;
@@ -73,8 +82,11 @@ _cairo_gstate_create ()
}
cairo_status_t
-_cairo_gstate_init (cairo_gstate_t *gstate)
+_cairo_gstate_init (cairo_gstate_t *gstate,
+ cairo_surface_t *target)
{
+ cairo_status_t status;
+
gstate->operator = CAIRO_GSTATE_OPERATOR_DEFAULT;
gstate->tolerance = CAIRO_GSTATE_TOLERANCE_DEFAULT;
@@ -90,32 +102,33 @@ _cairo_gstate_init (cairo_gstate_t *gstate)
gstate->num_dashes = 0;
gstate->dash_offset = 0.0;
- gstate->font_family = NULL;
- gstate->font_slant = CAIRO_FONT_SLANT_DEFAULT;
- gstate->font_weight = CAIRO_FONT_WEIGHT_DEFAULT;
-
- gstate->font = NULL;
+ gstate->scaled_font = NULL;
+ gstate->font_face = NULL;
+ cairo_matrix_init_scale (&gstate->font_matrix,
+ CAIRO_GSTATE_DEFAULT_FONT_SIZE,
+ CAIRO_GSTATE_DEFAULT_FONT_SIZE);
+
gstate->surface = NULL;
+ gstate->surface_level = 0;
gstate->clip.region = NULL;
gstate->clip.surface = NULL;
-
- gstate->pattern = _cairo_pattern_create_solid (0.0, 0.0, 0.0);
- if (!gstate->pattern)
- return CAIRO_STATUS_NO_MEMORY;
- gstate->alpha = 1.0;
-
- gstate->pixels_per_inch = CAIRO_GSTATE_PIXELS_PER_INCH_DEFAULT;
- _cairo_gstate_default_matrix (gstate);
+ gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
+ if (!gstate->source)
+ return CAIRO_STATUS_NO_MEMORY;
- _cairo_path_init (&gstate->path);
+ _cairo_gstate_identity_matrix (gstate);
_cairo_pen_init_empty (&gstate->pen_regular);
gstate->next = NULL;
+ status = _cairo_gstate_set_target_surface (gstate, target);
+ if (status)
+ return status;
+
return CAIRO_STATUS_SUCCESS;
}
@@ -138,51 +151,41 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
memcpy (gstate->dash, other->dash, other->num_dashes * sizeof (double));
}
- if (other->font_family) {
- gstate->font_family = strdup (other->font_family);
- if (!gstate->font_family)
- goto CLEANUP_DASH;
- }
-
- if (other->font) {
- gstate->font = other->font;
- cairo_font_reference (gstate->font);
- }
-
if (other->clip.region)
{
gstate->clip.region = pixman_region_create ();
pixman_region_copy (gstate->clip.region, other->clip.region);
}
+ if (gstate->font_face)
+ cairo_font_face_reference (gstate->font_face);
+
+ if (gstate->scaled_font)
+ cairo_scaled_font_reference (gstate->scaled_font);
+
cairo_surface_reference (gstate->surface);
cairo_surface_reference (gstate->clip.surface);
- cairo_pattern_reference (gstate->pattern);
+ cairo_pattern_reference (gstate->source);
- status = _cairo_path_init_copy (&gstate->path, &other->path);
+ status = _cairo_pen_init_copy (&gstate->pen_regular, &other->pen_regular);
if (status)
goto CLEANUP_FONT;
- status = _cairo_pen_init_copy (&gstate->pen_regular, &other->pen_regular);
+ status = _cairo_surface_begin (gstate->surface);
if (status)
- goto CLEANUP_PATH;
+ goto CLEANUP_PEN;
+ gstate->surface_level = gstate->surface->level;
return status;
- CLEANUP_PATH:
- _cairo_path_fini (&gstate->path);
+ CLEANUP_PEN:
+ _cairo_pen_fini (&gstate->pen_regular);
CLEANUP_FONT:
- cairo_font_destroy (gstate->font);
- gstate->font = NULL;
+ cairo_scaled_font_destroy (gstate->scaled_font);
+ gstate->scaled_font = NULL;
- if (gstate->font_family) {
- free (gstate->font_family);
- gstate->font_family = NULL;
- }
-
- CLEANUP_DASH:
free (gstate->dash);
gstate->dash = NULL;
@@ -192,15 +195,17 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
void
_cairo_gstate_fini (cairo_gstate_t *gstate)
{
- if (gstate->font_family)
- free (gstate->font_family);
+ if (gstate->font_face)
+ cairo_font_face_destroy (gstate->font_face);
- if (gstate->font)
- cairo_font_destroy (gstate->font);
+ if (gstate->scaled_font)
+ cairo_scaled_font_destroy (gstate->scaled_font);
- if (gstate->surface)
+ if (gstate->surface) {
+ _cairo_surface_end (gstate->surface);
cairo_surface_destroy (gstate->surface);
- gstate->surface = NULL;
+ gstate->surface = NULL;
+ }
if (gstate->clip.surface)
cairo_surface_destroy (gstate->clip.surface);
@@ -210,14 +215,7 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
pixman_region_destroy (gstate->clip.region);
gstate->clip.region = NULL;
- cairo_pattern_destroy (gstate->pattern);
-
- _cairo_matrix_fini (&gstate->font_matrix);
-
- _cairo_matrix_fini (&gstate->ctm);
- _cairo_matrix_fini (&gstate->ctm_inverse);
-
- _cairo_path_fini (&gstate->path);
+ cairo_pattern_destroy (gstate->source);
_cairo_pen_fini (&gstate->pen_regular);
@@ -253,28 +251,12 @@ _cairo_gstate_clone (cairo_gstate_t *gstate)
return clone;
}
-cairo_status_t
-_cairo_gstate_copy (cairo_gstate_t *dest, cairo_gstate_t *src)
-{
- cairo_status_t status;
- cairo_gstate_t *next;
-
- /* Preserve next pointer over fini/init */
- next = dest->next;
- _cairo_gstate_fini (dest);
- status = _cairo_gstate_init_copy (dest, src);
- dest->next = next;
-
- return status;
-}
-
/* Push rendering off to an off-screen group. */
/* XXX: Rethinking this API
cairo_status_t
_cairo_gstate_begin_group (cairo_gstate_t *gstate)
{
Pixmap pix;
- cairo_color_t clear;
unsigned int width, height;
gstate->parent_surface = gstate->surface;
@@ -295,12 +277,9 @@ _cairo_gstate_begin_group (cairo_gstate_t *gstate)
_cairo_surface_set_drawableWH (gstate->surface, pix, width, height);
- _cairo_color_init (&clear);
- _cairo_color_set_alpha (&clear, 0);
-
status = _cairo_surface_fill_rectangle (gstate->surface,
- CAIRO_OPERATOR_SRC,
- &clear,
+ CAIRO_OPERATOR_SOURCE,
+ &CAIRO_COLOR_TRANSPARENT,
0, 0,
_cairo_surface_get_width (gstate->surface),
_cairo_surface_get_height (gstate->surface));
@@ -325,7 +304,6 @@ _cairo_gstate_end_group (cairo_gstate_t *gstate)
_cairo_surface_init (&mask, gstate->dpy);
_cairo_color_init (&mask_color);
- _cairo_color_set_alpha (&mask_color, gstate->alpha);
_cairo_surface_set_solid_color (&mask, &mask_color);
@@ -355,73 +333,93 @@ _cairo_gstate_end_group (cairo_gstate_t *gstate)
}
*/
-cairo_status_t
+static cairo_status_t
_cairo_gstate_set_target_surface (cairo_gstate_t *gstate, cairo_surface_t *surface)
{
- double scale;
+ cairo_status_t status;
+
+ if (gstate->surface == surface)
+ return CAIRO_STATUS_SUCCESS;
+
+ if (surface) {
+ status = _cairo_surface_begin_reset_clip (surface);
+ if (!CAIRO_OK (status))
+ return status;
+ }
_cairo_gstate_unset_font (gstate);
- if (gstate->surface)
+ if (gstate->surface) {
+ _cairo_surface_end (gstate->surface);
cairo_surface_destroy (gstate->surface);
+ }
gstate->surface = surface;
/* Sometimes the user wants to return to having no target surface,
* (just like after cairo_create). This can be useful for forcing
* the old surface to be destroyed. */
- if (surface == NULL)
+ if (surface == NULL) {
+ gstate->surface_level = 0;
return CAIRO_STATUS_SUCCESS;
+ }
cairo_surface_reference (gstate->surface);
+ gstate->surface_level = surface->level;
- scale = _cairo_surface_pixels_per_inch (surface) / gstate->pixels_per_inch;
- _cairo_gstate_scale (gstate, scale, scale);
- gstate->pixels_per_inch = _cairo_surface_pixels_per_inch (surface);
+ _cairo_gstate_identity_matrix (gstate);
return CAIRO_STATUS_SUCCESS;
}
-/* XXX: Need to decide the memory mangement semantics of this
- function. Should it reference the surface again? */
cairo_surface_t *
-_cairo_gstate_current_target_surface (cairo_gstate_t *gstate)
+_cairo_gstate_get_target (cairo_gstate_t *gstate)
{
if (gstate == NULL)
return NULL;
-/* XXX: Do we want this?
- if (gstate->surface)
- _cairo_surface_reference (gstate->surface);
-*/
-
return gstate->surface;
}
cairo_status_t
-_cairo_gstate_set_pattern (cairo_gstate_t *gstate, cairo_pattern_t *pattern)
+_cairo_gstate_set_source (cairo_gstate_t *gstate,
+ cairo_pattern_t *source)
{
- if (pattern == NULL)
+ if (source == NULL)
return CAIRO_STATUS_NULL_POINTER;
- cairo_pattern_reference (pattern);
- cairo_pattern_destroy (gstate->pattern);
- gstate->pattern = pattern;
+ cairo_pattern_reference (source);
+ cairo_pattern_destroy (gstate->source);
+ gstate->source = source;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_gstate_set_source_solid (cairo_gstate_t *gstate,
+ const cairo_color_t *color)
+{
+ cairo_status_t status;
+ cairo_pattern_t *source;
+
+ source = _cairo_pattern_create_solid (color);
+ if (!source)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ status = _cairo_gstate_set_source (gstate, source);
+
+ cairo_pattern_destroy (source);
return CAIRO_STATUS_SUCCESS;
}
cairo_pattern_t *
-_cairo_gstate_current_pattern (cairo_gstate_t *gstate)
+_cairo_gstate_get_source (cairo_gstate_t *gstate)
{
if (gstate == NULL)
return NULL;
-/* XXX: Do we want this?
- cairo_pattern_reference (gstate->pattern);
-*/
-
- return gstate->pattern;
+ return gstate->source;
}
cairo_status_t
@@ -433,30 +431,12 @@ _cairo_gstate_set_operator (cairo_gstate_t *gstate, cairo_operator_t operator)
}
cairo_operator_t
-_cairo_gstate_current_operator (cairo_gstate_t *gstate)
+_cairo_gstate_get_operator (cairo_gstate_t *gstate)
{
return gstate->operator;
}
cairo_status_t
-_cairo_gstate_set_rgb_color (cairo_gstate_t *gstate, double red, double green, double blue)
-{
- cairo_pattern_destroy (gstate->pattern);
-
- gstate->pattern = _cairo_pattern_create_solid (red, green, blue);
- if (!gstate->pattern)
- return CAIRO_STATUS_NO_MEMORY;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
-_cairo_gstate_current_rgb_color (cairo_gstate_t *gstate, double *red, double *green, double *blue)
-{
- return _cairo_pattern_get_rgb (gstate->pattern, red, green, blue);
-}
-
-cairo_status_t
_cairo_gstate_set_tolerance (cairo_gstate_t *gstate, double tolerance)
{
gstate->tolerance = tolerance;
@@ -465,26 +445,12 @@ _cairo_gstate_set_tolerance (cairo_gstate_t *gstate, double tolerance)
}
double
-_cairo_gstate_current_tolerance (cairo_gstate_t *gstate)
+_cairo_gstate_get_tolerance (cairo_gstate_t *gstate)
{
return gstate->tolerance;
}
cairo_status_t
-_cairo_gstate_set_alpha (cairo_gstate_t *gstate, double alpha)
-{
- gstate->alpha = alpha;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-double
-_cairo_gstate_current_alpha (cairo_gstate_t *gstate)
-{
- return gstate->alpha;
-}
-
-cairo_status_t
_cairo_gstate_set_fill_rule (cairo_gstate_t *gstate, cairo_fill_rule_t fill_rule)
{
gstate->fill_rule = fill_rule;
@@ -493,7 +459,7 @@ _cairo_gstate_set_fill_rule (cairo_gstate_t *gstate, cairo_fill_rule_t fill_rule
}
cairo_fill_rule_t
-_cairo_gstate_current_fill_rule (cairo_gstate_t *gstate)
+_cairo_gstate_get_fill_rule (cairo_gstate_t *gstate)
{
return gstate->fill_rule;
}
@@ -507,7 +473,7 @@ _cairo_gstate_set_line_width (cairo_gstate_t *gstate, double width)
}
double
-_cairo_gstate_current_line_width (cairo_gstate_t *gstate)
+_cairo_gstate_get_line_width (cairo_gstate_t *gstate)
{
return gstate->line_width;
}
@@ -521,7 +487,7 @@ _cairo_gstate_set_line_cap (cairo_gstate_t *gstate, cairo_line_cap_t line_cap)
}
cairo_line_cap_t
-_cairo_gstate_current_line_cap (cairo_gstate_t *gstate)
+_cairo_gstate_get_line_cap (cairo_gstate_t *gstate)
{
return gstate->line_cap;
}
@@ -535,7 +501,7 @@ _cairo_gstate_set_line_join (cairo_gstate_t *gstate, cairo_line_join_t line_join
}
cairo_line_join_t
-_cairo_gstate_current_line_join (cairo_gstate_t *gstate)
+_cairo_gstate_get_line_join (cairo_gstate_t *gstate)
{
return gstate->line_join;
}
@@ -572,15 +538,15 @@ _cairo_gstate_set_miter_limit (cairo_gstate_t *gstate, double limit)
}
double
-_cairo_gstate_current_miter_limit (cairo_gstate_t *gstate)
+_cairo_gstate_get_miter_limit (cairo_gstate_t *gstate)
{
return gstate->miter_limit;
}
void
-_cairo_gstate_current_matrix (cairo_gstate_t *gstate, cairo_matrix_t *matrix)
+_cairo_gstate_get_matrix (cairo_gstate_t *gstate, cairo_matrix_t *matrix)
{
- cairo_matrix_copy (matrix, &gstate->ctm);
+ *matrix = gstate->ctm;
}
cairo_status_t
@@ -590,10 +556,10 @@ _cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty)
_cairo_gstate_unset_font (gstate);
- _cairo_matrix_set_translate (&tmp, tx, ty);
+ cairo_matrix_init_translate (&tmp, tx, ty);
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
- _cairo_matrix_set_translate (&tmp, -tx, -ty);
+ cairo_matrix_init_translate (&tmp, -tx, -ty);
cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
return CAIRO_STATUS_SUCCESS;
@@ -609,10 +575,10 @@ _cairo_gstate_scale (cairo_gstate_t *gstate, double sx, double sy)
_cairo_gstate_unset_font (gstate);
- _cairo_matrix_set_scale (&tmp, sx, sy);
+ cairo_matrix_init_scale (&tmp, sx, sy);
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
- _cairo_matrix_set_scale (&tmp, 1/sx, 1/sy);
+ cairo_matrix_init_scale (&tmp, 1/sx, 1/sy);
cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
return CAIRO_STATUS_SUCCESS;
@@ -625,24 +591,24 @@ _cairo_gstate_rotate (cairo_gstate_t *gstate, double angle)
_cairo_gstate_unset_font (gstate);
- _cairo_matrix_set_rotate (&tmp, angle);
+ cairo_matrix_init_rotate (&tmp, angle);
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
- _cairo_matrix_set_rotate (&tmp, -angle);
+ cairo_matrix_init_rotate (&tmp, -angle);
cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
-_cairo_gstate_concat_matrix (cairo_gstate_t *gstate,
- cairo_matrix_t *matrix)
+_cairo_gstate_transform (cairo_gstate_t *gstate,
+ const cairo_matrix_t *matrix)
{
cairo_matrix_t tmp;
_cairo_gstate_unset_font (gstate);
- cairo_matrix_copy (&tmp, matrix);
+ tmp = *matrix;
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
cairo_matrix_invert (&tmp);
@@ -652,16 +618,16 @@ _cairo_gstate_concat_matrix (cairo_gstate_t *gstate,
}
cairo_status_t
-_cairo_gstate_set_matrix (cairo_gstate_t *gstate,
- cairo_matrix_t *matrix)
+_cairo_gstate_set_matrix (cairo_gstate_t *gstate,
+ const cairo_matrix_t *matrix)
{
cairo_status_t status;
_cairo_gstate_unset_font (gstate);
- cairo_matrix_copy (&gstate->ctm, matrix);
+ gstate->ctm = *matrix;
- cairo_matrix_copy (&gstate->ctm_inverse, matrix);
+ gstate->ctm_inverse = *matrix;
status = cairo_matrix_invert (&gstate->ctm_inverse);
if (status)
return status;
@@ -670,37 +636,18 @@ _cairo_gstate_set_matrix (cairo_gstate_t *gstate,
}
cairo_status_t
-_cairo_gstate_default_matrix (cairo_gstate_t *gstate)
-{
- int scale = gstate->pixels_per_inch / CAIRO_GSTATE_PIXELS_PER_INCH_DEFAULT + 0.5;
- if (scale == 0)
- scale = 1;
-
- _cairo_gstate_unset_font (gstate);
-
- cairo_matrix_set_identity (&gstate->font_matrix);
-
- cairo_matrix_set_identity (&gstate->ctm);
- cairo_matrix_scale (&gstate->ctm, scale, scale);
- cairo_matrix_copy (&gstate->ctm_inverse, &gstate->ctm);
- cairo_matrix_invert (&gstate->ctm_inverse);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
_cairo_gstate_identity_matrix (cairo_gstate_t *gstate)
{
_cairo_gstate_unset_font (gstate);
- cairo_matrix_set_identity (&gstate->ctm);
- cairo_matrix_set_identity (&gstate->ctm_inverse);
+ cairo_matrix_init_identity (&gstate->ctm);
+ cairo_matrix_init_identity (&gstate->ctm_inverse);
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
-_cairo_gstate_transform_point (cairo_gstate_t *gstate, double *x, double *y)
+_cairo_gstate_user_to_device (cairo_gstate_t *gstate, double *x, double *y)
{
cairo_matrix_transform_point (&gstate->ctm, x, y);
@@ -708,7 +655,8 @@ _cairo_gstate_transform_point (cairo_gstate_t *gstate, double *x, double *y)
}
cairo_status_t
-_cairo_gstate_transform_distance (cairo_gstate_t *gstate, double *dx, double *dy)
+_cairo_gstate_user_to_device_distance (cairo_gstate_t *gstate,
+ double *dx, double *dy)
{
cairo_matrix_transform_distance (&gstate->ctm, dx, dy);
@@ -716,7 +664,7 @@ _cairo_gstate_transform_distance (cairo_gstate_t *gstate, double *dx, double *dy
}
cairo_status_t
-_cairo_gstate_inverse_transform_point (cairo_gstate_t *gstate, double *x, double *y)
+_cairo_gstate_device_to_user (cairo_gstate_t *gstate, double *x, double *y)
{
cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);
@@ -724,610 +672,297 @@ _cairo_gstate_inverse_transform_point (cairo_gstate_t *gstate, double *x, double
}
cairo_status_t
-_cairo_gstate_inverse_transform_distance (cairo_gstate_t *gstate, double *dx, double *dy)
+_cairo_gstate_device_to_user_distance (cairo_gstate_t *gstate,
+ double *dx, double *dy)
{
cairo_matrix_transform_distance (&gstate->ctm_inverse, dx, dy);
return CAIRO_STATUS_SUCCESS;
}
-cairo_status_t
-_cairo_gstate_new_path (cairo_gstate_t *gstate)
-{
- _cairo_path_fini (&gstate->path);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
-_cairo_gstate_move_to (cairo_gstate_t *gstate, double x, double y)
+void
+_cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y)
{
- cairo_point_t point;
-
- cairo_matrix_transform_point (&gstate->ctm, &x, &y);
-
- point.x = _cairo_fixed_from_double (x);
- point.y = _cairo_fixed_from_double (y);
-
- return _cairo_path_move_to (&gstate->path, &point);
+ cairo_matrix_transform_point (&gstate->ctm, x, y);
+ if (gstate->surface) {
+ *x += gstate->surface->device_x_offset;
+ *y += gstate->surface->device_y_offset;
+ }
}
-cairo_status_t
-_cairo_gstate_line_to (cairo_gstate_t *gstate, double x, double y)
+void
+_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y)
{
- cairo_point_t point;
-
- cairo_matrix_transform_point (&gstate->ctm, &x, &y);
-
- point.x = _cairo_fixed_from_double (x);
- point.y = _cairo_fixed_from_double (y);
-
- return _cairo_path_line_to (&gstate->path, &point);
+ if (gstate->surface) {
+ *x -= gstate->surface->device_x_offset;
+ *y -= gstate->surface->device_y_offset;
+ }
+ cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);
}
+/* XXX: NYI
cairo_status_t
-_cairo_gstate_curve_to (cairo_gstate_t *gstate,
- double x0, double y0,
- double x1, double y1,
- double x2, double y2)
-{
- cairo_point_t p0, p1, p2;
-
- cairo_matrix_transform_point (&gstate->ctm, &x0, &y0);
- cairo_matrix_transform_point (&gstate->ctm, &x1, &y1);
- cairo_matrix_transform_point (&gstate->ctm, &x2, &y2);
-
- p0.x = _cairo_fixed_from_double (x0);
- p0.y = _cairo_fixed_from_double (y0);
-
- p1.x = _cairo_fixed_from_double (x1);
- p1.y = _cairo_fixed_from_double (y1);
-
- p2.x = _cairo_fixed_from_double (x2);
- p2.y = _cairo_fixed_from_double (y2);
-
- return _cairo_path_curve_to (&gstate->path, &p0, &p1, &p2);
-}
-
-/* Spline deviation from the circle in radius would be given by:
-
- error = sqrt (x**2 + y**2) - 1
-
- A simpler error function to work with is:
-
- e = x**2 + y**2 - 1
-
- From "Good approximation of circles by curvature-continuous Bezier
- curves", Tor Dokken and Morten Daehlen, Computer Aided Geometric
- Design 8 (1990) 22-41, we learn:
-
- abs (max(e)) = 4/27 * sin**6(angle/4) / cos**2(angle/4)
-
- and
- abs (error) =~ 1/2 * e
-
- Of course, this error value applies only for the particular spline
- approximation that is used in _cairo_gstate_arc_segment.
-*/
-static double
-_arc_error_normalized (double angle)
-{
- return 2.0/27.0 * pow (sin (angle / 4), 6) / pow (cos (angle / 4), 2);
-}
-
-static double
-_arc_max_angle_for_tolerance_normalized (double tolerance)
-{
- double angle, error;
- int i;
-
- /* Use table lookup to reduce search time in most cases. */
- struct {
- double angle;
- double error;
- } table[] = {
- { M_PI / 1.0, 0.0185185185185185036127 },
- { M_PI / 2.0, 0.000272567143730179811158 },
- { M_PI / 3.0, 2.38647043651461047433e-05 },
- { M_PI / 4.0, 4.2455377443222443279e-06 },
- { M_PI / 5.0, 1.11281001494389081528e-06 },
- { M_PI / 6.0, 3.72662000942734705475e-07 },
- { M_PI / 7.0, 1.47783685574284411325e-07 },
- { M_PI / 8.0, 6.63240432022601149057e-08 },
- { M_PI / 9.0, 3.2715520137536980553e-08 },
- { M_PI / 10.0, 1.73863223499021216974e-08 },
- { M_PI / 11.0, 9.81410988043554039085e-09 },
- };
- int table_size = (sizeof (table) / sizeof (table[0]));
-
- for (i = 0; i < table_size; i++)
- if (table[i].error < tolerance)
- return table[i].angle;
-
- ++i;
- do {
- angle = M_PI / i++;
- error = _arc_error_normalized (angle);
- } while (error > tolerance);
-
- return angle;
-}
-
-static int
-_cairo_gstate_arc_segments_needed (cairo_gstate_t *gstate,
- double angle,
- double radius)
-{
- double l1, l2, lmax;
- double max_angle;
-
- _cairo_matrix_compute_eigen_values (&gstate->ctm, &l1, &l2);
-
- l1 = fabs (l1);
- l2 = fabs (l2);
- if (l1 > l2)
- lmax = l1;
- else
- lmax = l2;
-
- max_angle = _arc_max_angle_for_tolerance_normalized (gstate->tolerance / (radius * lmax));
-
- return (int) ceil (angle / max_angle);
-}
-
-/* We want to draw a single spline approximating a circular arc radius
- R from angle A to angle B. Since we want a symmetric spline that
- matches the endpoints of the arc in position and slope, we know
- that the spline control points must be:
-
- (R * cos(A), R * sin(A))
- (R * cos(A) - h * sin(A), R * sin(A) + h * cos (A))
- (R * cos(B) + h * sin(B), R * sin(B) - h * cos (B))
- (R * cos(B), R * sin(B))
-
- for some value of h.
-
- "Approximation of circular arcs by cubic poynomials", Michael
- Goldapp, Computer Aided Geometric Design 8 (1991) 227-238, provides
- various values of h along with error analysis for each.
-
- From that paper, a very practical value of h is:
-
- h = 4/3 * tan(angle/4)
-
- This value does not give the spline with minimal error, but it does
- provide a very good approximation, (6th-order convergence), and the
- error expression is quite simple, (see the comment for
- _arc_error_normalized).
-*/
-static cairo_status_t
-_cairo_gstate_arc_segment (cairo_gstate_t *gstate,
- double xc, double yc,
- double radius,
- double angle_A, double angle_B)
+_cairo_gstate_stroke_to_path (cairo_gstate_t *gstate)
{
cairo_status_t status;
- double r_sin_A, r_cos_A;
- double r_sin_B, r_cos_B;
- double h;
-
- r_sin_A = radius * sin (angle_A);
- r_cos_A = radius * cos (angle_A);
- r_sin_B = radius * sin (angle_B);
- r_cos_B = radius * cos (angle_B);
-
- h = 4.0/3.0 * tan ((angle_B - angle_A) / 4.0);
-
- status = _cairo_gstate_curve_to (gstate,
- xc + r_cos_A - h * r_sin_A, yc + r_sin_A + h * r_cos_A,
- xc + r_cos_B + h * r_sin_B, yc + r_sin_B - h * r_cos_B,
- xc + r_cos_B, yc + r_sin_B);
- if (status)
- return status;
+ _cairo_pen_init (&gstate);
return CAIRO_STATUS_SUCCESS;
}
+*/
-static cairo_status_t
-_cairo_gstate_arc_dir (cairo_gstate_t *gstate,
- double xc, double yc,
- double radius,
- double angle_min,
- double angle_max,
- cairo_direction_t dir)
+static void
+_cairo_gstate_pattern_transform (cairo_gstate_t *gstate,
+ cairo_pattern_t *pattern)
{
- cairo_status_t status;
-
- while (angle_max - angle_min > 4 * M_PI)
- angle_max -= 2 * M_PI;
-
- /* Recurse if drawing arc larger than pi */
- if (angle_max - angle_min > M_PI) {
- double angle_mid = angle_min + (angle_max - angle_min) / 2.0;
- /* XXX: Something tells me this block could be condensed. */
- if (dir == CAIRO_DIRECTION_FORWARD) {
- status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
- angle_min, angle_mid, dir);
- if (status)
- return status;
-
- status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
- angle_mid, angle_max, dir);
- if (status)
- return status;
- } else {
- status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
- angle_mid, angle_max, dir);
- if (status)
- return status;
-
- status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
- angle_min, angle_mid, dir);
- if (status)
- return status;
- }
- } else {
- int i, segments;
- double angle, angle_step;
-
- segments = _cairo_gstate_arc_segments_needed (gstate,
- angle_max - angle_min,
- radius);
- angle_step = (angle_max - angle_min) / (double) segments;
-
- if (dir == CAIRO_DIRECTION_FORWARD) {
- angle = angle_min;
- } else {
- angle = angle_max;
- angle_step = - angle_step;
- }
-
- for (i = 0; i < segments; i++, angle += angle_step) {
- _cairo_gstate_arc_segment (gstate,
- xc, yc,
- radius,
- angle,
- angle + angle_step);
- }
-
- }
+ cairo_matrix_t tmp_matrix = gstate->ctm_inverse;
+
+ if (gstate->surface)
+ cairo_matrix_translate (&tmp_matrix,
+ - gstate->surface->device_x_offset,
+ - gstate->surface->device_y_offset);
- return CAIRO_STATUS_SUCCESS;
+ _cairo_pattern_transform (pattern, &tmp_matrix);
}
cairo_status_t
-_cairo_gstate_arc (cairo_gstate_t *gstate,
- double xc, double yc,
- double radius,
- double angle1, double angle2)
+_cairo_gstate_paint (cairo_gstate_t *gstate)
{
+ cairo_rectangle_t rectangle;
cairo_status_t status;
+ cairo_box_t box;
+ cairo_traps_t traps;
- if (radius <= 0.0)
- return CAIRO_STATUS_SUCCESS;
-
- while (angle2 < angle1)
- angle2 += 2 * M_PI;
-
- status = _cairo_gstate_line_to (gstate,
- xc + radius * cos (angle1),
- yc + radius * sin (angle1));
- if (status)
- return status;
-
- status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
- angle1, angle2, CAIRO_DIRECTION_FORWARD);
- if (status)
+ if (gstate->surface->level != gstate->surface_level)
+ return CAIRO_STATUS_BAD_NESTING;
+
+ status = _cairo_surface_get_clip_extents (gstate->surface, &rectangle);
+ if (!CAIRO_OK (status))
return status;
- return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
-_cairo_gstate_arc_negative (cairo_gstate_t *gstate,
- double xc, double yc,
- double radius,
- double angle1, double angle2)
-{
- cairo_status_t status;
-
- if (radius <= 0.0)
- return CAIRO_STATUS_SUCCESS;
-
- while (angle2 > angle1)
- angle2 -= 2 * M_PI;
-
- status = _cairo_gstate_line_to (gstate,
- xc + radius * cos (angle1),
- yc + radius * sin (angle1));
- if (status)
+ box.p1.x = _cairo_fixed_from_int (rectangle.x);
+ box.p1.y = _cairo_fixed_from_int (rectangle.y);
+ box.p2.x = _cairo_fixed_from_int (rectangle.x + rectangle.width);
+ box.p2.y = _cairo_fixed_from_int (rectangle.y + rectangle.height);
+ status = _cairo_traps_init_box (&traps, &box);
+ if (!CAIRO_OK (status))
return status;
+
+ _cairo_gstate_clip_and_composite_trapezoids (gstate,
+ gstate->source,
+ gstate->operator,
+ gstate->surface,
+ &traps);
- status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
- angle2, angle1, CAIRO_DIRECTION_REVERSE);
- if (status)
- return status;
+ _cairo_traps_fini (&traps);
return CAIRO_STATUS_SUCCESS;
}
-/* XXX: NYI
-cairo_status_t
-_cairo_gstate_arc_to (cairo_gstate_t *gstate,
- double x1, double y1,
- double x2, double y2,
- double radius)
-{
-
-}
-*/
-
-cairo_status_t
-_cairo_gstate_rel_move_to (cairo_gstate_t *gstate, double dx, double dy)
-{
- cairo_distance_t distance;
-
- cairo_matrix_transform_distance (&gstate->ctm, &dx, &dy);
-
- distance.dx = _cairo_fixed_from_double (dx);
- distance.dy = _cairo_fixed_from_double (dy);
-
- return _cairo_path_rel_move_to (&gstate->path, &distance);
-}
-
-cairo_status_t
-_cairo_gstate_rel_line_to (cairo_gstate_t *gstate, double dx, double dy)
-{
- cairo_distance_t distance;
-
- cairo_matrix_transform_distance (&gstate->ctm, &dx, &dy);
-
- distance.dx = _cairo_fixed_from_double (dx);
- distance.dy = _cairo_fixed_from_double (dy);
-
- return _cairo_path_rel_line_to (&gstate->path, &distance);
-}
-
-cairo_status_t
-_cairo_gstate_rel_curve_to (cairo_gstate_t *gstate,
- double dx0, double dy0,
- double dx1, double dy1,
- double dx2, double dy2)
-{
- cairo_distance_t distance[3];
-
- cairo_matrix_transform_distance (&gstate->ctm, &dx0, &dy0);
- cairo_matrix_transform_distance (&gstate->ctm, &dx1, &dy1);
- cairo_matrix_transform_distance (&gstate->ctm, &dx2, &dy2);
-
- distance[0].dx = _cairo_fixed_from_double (dx0);
- distance[0].dy = _cairo_fixed_from_double (dy0);
-
- distance[1].dx = _cairo_fixed_from_double (dx1);
- distance[1].dy = _cairo_fixed_from_double (dy1);
-
- distance[2].dx = _cairo_fixed_from_double (dx2);
- distance[2].dy = _cairo_fixed_from_double (dy2);
-
- return _cairo_path_rel_curve_to (&gstate->path,
- &distance[0],
- &distance[1],
- &distance[2]);
-}
-
-/* XXX: NYI
-cairo_status_t
-_cairo_gstate_stroke_path (cairo_gstate_t *gstate)
+/* Combines @gstate->clip_surface using the IN operator with
+ * the given intermediate surface, which corresponds to the
+ * rectangle of the destination space given by @extents.
+ */
+static cairo_status_t
+_cairo_gstate_combine_clip_surface (cairo_gstate_t *gstate,
+ cairo_surface_t *intermediate,
+ cairo_rectangle_t *extents)
{
+ cairo_pattern_union_t pattern;
cairo_status_t status;
- _cairo_pen_init (&gstate);
- return CAIRO_STATUS_SUCCESS;
-}
-*/
+ _cairo_pattern_init_for_surface (&pattern.surface,
+ gstate->clip.surface);
+
+ status = _cairo_surface_composite (CAIRO_OPERATOR_IN,
+ &pattern.base,
+ NULL,
+ intermediate,
+ extents->x - gstate->clip.rect.x,
+ extents->y - gstate->clip.rect.y,
+ 0, 0,
+ 0, 0,
+ extents->width, extents->height);
+
+ _cairo_pattern_fini (&pattern.base);
-cairo_status_t
-_cairo_gstate_close_path (cairo_gstate_t *gstate)
-{
- return _cairo_path_close_path (&gstate->path);
+ return status;
}
-cairo_status_t
-_cairo_gstate_current_point (cairo_gstate_t *gstate, double *x_ret, double *y_ret)
-{
- cairo_status_t status;
- cairo_point_t point;
- double x, y;
-
- status = _cairo_path_current_point (&gstate->path, &point);
- if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
- x = 0.0;
- y = 0.0;
- } else {
- x = _cairo_fixed_to_double (point.x);
- y = _cairo_fixed_to_double (point.y);
- cairo_matrix_transform_point (&gstate->ctm_inverse, &x, &y);
+/* Creates a region from a cairo_rectangle_t */
+static cairo_status_t
+_region_new_from_rect (cairo_rectangle_t *rect,
+ pixman_region16_t **region)
+{
+ *region = pixman_region_create ();
+ if (pixman_region_union_rect (*region, *region,
+ rect->x, rect->y,
+ rect->width, rect->height) != PIXMAN_REGION_STATUS_SUCCESS) {
+ pixman_region_destroy (*region);
+ return CAIRO_STATUS_NO_MEMORY;
}
- if (x_ret)
- *x_ret = x;
- if (y_ret)
- *y_ret = y;
-
return CAIRO_STATUS_SUCCESS;
}
-typedef struct gstate_path_interpreter {
- cairo_matrix_t ctm_inverse;
- double tolerance;
- cairo_point_t current_point;
-
- cairo_move_to_func_t *move_to;
- cairo_line_to_func_t *line_to;
- cairo_curve_to_func_t *curve_to;
- cairo_close_path_func_t *close_path;
+/* Gets the bounding box of a region as a cairo_rectangle_t */
+static void
+_region_rect_extents (pixman_region16_t *region,
+ cairo_rectangle_t *rect)
+{
+ pixman_box16_t *region_extents = pixman_region_extents (region);
- void *closure;
-} gpi_t;
+ rect->x = region_extents->x1;
+ rect->y = region_extents->y1;
+ rect->width = region_extents->x2 - region_extents->x1;
+ rect->height = region_extents->y2 - region_extents->y1;
+}
+/* Intersects @region with the clipping bounds (both region
+ * and surface) of @gstate
+ */
static cairo_status_t
-_gpi_move_to (void *closure, cairo_point_t *point)
+_cairo_gstate_intersect_clip (cairo_gstate_t *gstate,
+ pixman_region16_t *region)
{
- gpi_t *gpi = closure;
- double x, y;
+ if (gstate->clip.region)
+ pixman_region_intersect (region, gstate->clip.region, region);
- x = _cairo_fixed_to_double (point->x);
- y = _cairo_fixed_to_double (point->y);
+ if (gstate->clip.surface) {
+ pixman_region16_t *clip_rect;
+ cairo_status_t status;
+
+ status = _region_new_from_rect (&gstate->clip.rect, &clip_rect);
+ if (!CAIRO_OK (status))
+ return status;
+
+ if (pixman_region_intersect (region,
+ clip_rect,
+ region) != PIXMAN_REGION_STATUS_SUCCESS)
+ status = CAIRO_STATUS_NO_MEMORY;
- cairo_matrix_transform_point (&gpi->ctm_inverse, &x, &y);
+ pixman_region_destroy (clip_rect);
- gpi->move_to (gpi->closure, x, y);
- gpi->current_point = *point;
+ if (!CAIRO_OK (status))
+ return status;
+ }
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
-_gpi_line_to (void *closure, cairo_point_t *point)
+_get_mask_extents (cairo_gstate_t *gstate,
+ cairo_pattern_t *mask,
+ cairo_rectangle_t *extents)
{
- gpi_t *gpi = closure;
- double x, y;
+ cairo_rectangle_t clip_rect;
+ pixman_region16_t *clip_region;
+ cairo_status_t status;
+
+ status = _cairo_surface_get_clip_extents (gstate->surface, &clip_rect);
+ if (!CAIRO_OK (status))
+ return status;
- x = _cairo_fixed_to_double (point->x);
- y = _cairo_fixed_to_double (point->y);
+ status = _region_new_from_rect (&clip_rect, &clip_region);
+ if (!CAIRO_OK (status))
+ return status;
+
+ status = _cairo_gstate_intersect_clip (gstate, clip_region);
+ if (!CAIRO_OK (status))
+ return status;
- cairo_matrix_transform_point (&gpi->ctm_inverse, &x, &y);
+ _region_rect_extents (clip_region, extents);
- gpi->line_to (gpi->closure, x, y);
- gpi->current_point = *point;
+ pixman_region_destroy (clip_region);
return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
-_gpi_curve_to (void *closure,
- cairo_point_t *p1,
- cairo_point_t *p2,
- cairo_point_t *p3)
+cairo_status_t
+_cairo_gstate_mask (cairo_gstate_t *gstate,
+ cairo_pattern_t *mask)
{
- gpi_t *gpi = closure;
+ cairo_rectangle_t extents;
+ cairo_pattern_union_t pattern;
+ cairo_surface_pattern_t intermediate_pattern;
+ cairo_pattern_t *effective_mask;
cairo_status_t status;
- cairo_spline_t spline;
- double x1, y1, x2, y2, x3, y3;
-
- if (gpi->curve_to) {
- x1 = _cairo_fixed_to_double (p1->x);
- y1 = _cairo_fixed_to_double (p1->y);
- cairo_matrix_transform_point (&gpi->ctm_inverse, &x1, &y1);
-
- x2 = _cairo_fixed_to_double (p2->x);
- y2 = _cairo_fixed_to_double (p2->y);
- cairo_matrix_transform_point (&gpi->ctm_inverse, &x2, &y2);
-
- x3 = _cairo_fixed_to_double (p3->x);
- y3 = _cairo_fixed_to_double (p3->y);
- cairo_matrix_transform_point (&gpi->ctm_inverse, &x3, &y3);
+ int mask_x, mask_y;
- gpi->curve_to (gpi->closure, x1, y1, x2, y2, x3, y3);
- } else {
- cairo_point_t *p0 = &gpi->current_point;
- int i;
- double x, y;
+ if (gstate->surface->level != gstate->surface_level)
+ return CAIRO_STATUS_BAD_NESTING;
+
+ _get_mask_extents (gstate, mask, &extents);
+
+ if (gstate->clip.surface) {
+ /* When there is clip surface, we'll need to create a
+ * temporary surface that combines the clip and mask
+ */
+ cairo_surface_t *intermediate;
- status = _cairo_spline_init (&spline, p0, p1, p2, p3);
- if (status == CAIRO_INT_STATUS_DEGENERATE)
- return CAIRO_STATUS_SUCCESS;
+ intermediate = cairo_surface_create_similar (gstate->clip.surface,
+ CAIRO_FORMAT_A8,
+ extents.width,
+ extents.height);
+ if (intermediate == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
- status = _cairo_spline_decompose (&spline, gpi->tolerance);
- if (status)
+ status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
+ mask, NULL, intermediate,
+ extents.x, extents.y,
+ 0, 0,
+ 0, 0,
+ extents.width, extents.height);
+ if (!CAIRO_OK (status)) {
+ cairo_surface_destroy (intermediate);
return status;
-
- for (i=1; i < spline.num_points; i++) {
- x = _cairo_fixed_to_double (spline.points[i].x);
- y = _cairo_fixed_to_double (spline.points[i].y);
-
- cairo_matrix_transform_point (&gpi->ctm_inverse, &x, &y);
-
- gpi->line_to (gpi->closure, x, y);
}
- }
-
- gpi->current_point = *p3;
-
- return CAIRO_STATUS_SUCCESS;
-}
+
+ status = _cairo_gstate_combine_clip_surface (gstate, intermediate, &extents);
+ if (!CAIRO_OK (status)) {
+ cairo_surface_destroy (intermediate);
+ return status;
+ }
+
+ _cairo_pattern_init_for_surface (&intermediate_pattern, intermediate);
+ cairo_surface_destroy (intermediate);
-static cairo_status_t
-_gpi_close_path (void *closure)
-{
- gpi_t *gpi = closure;
+ effective_mask = &intermediate_pattern.base;
+ mask_x = extents.x;
+ mask_y = extents.y;
+
+ } else {
+ effective_mask = mask;
+ mask_x = mask_y = 0;
+ }
- gpi->close_path (gpi->closure);
+ _cairo_pattern_init_copy (&pattern.base, gstate->source);
+ _cairo_gstate_pattern_transform (gstate, &pattern.base);
- gpi->current_point.x = 0;
- gpi->current_point.y = 0;
+ status = _cairo_surface_composite (gstate->operator,
+ &pattern.base,
+ effective_mask,
+ gstate->surface,
+ extents.x, extents.y,
+ extents.x - mask_x, extents.y - mask_y,
+ extents.x, extents.y,
+ extents.width, extents.height);
- return CAIRO_STATUS_SUCCESS;
-}
+ if (gstate->clip.surface)
+ _cairo_pattern_fini (&intermediate_pattern.base);
-/* It's OK for curve_path to be NULL. In that case, all curves in the
- path will be decomposed into one or more calls to the line_to
- function, (according to the current tolerance). */
-cairo_status_t
-_cairo_gstate_interpret_path (cairo_gstate_t *gstate,
- cairo_move_to_func_t *move_to,
- cairo_line_to_func_t *line_to,
- cairo_curve_to_func_t *curve_to,
- cairo_close_path_func_t *close_path,
- void *closure)
-{
- cairo_path_t path;
- gpi_t gpi;
-
- /* Anything we want from gstate must be copied. We must not retain
- pointers into gstate. */
- _cairo_path_init_copy (&path, &gstate->path);
-
- cairo_matrix_copy (&gpi.ctm_inverse, &gstate->ctm_inverse);
- gpi.tolerance = gstate->tolerance;
-
- gpi.move_to = move_to;
- gpi.line_to = line_to;
- gpi.curve_to = curve_to;
- gpi.close_path = close_path;
- gpi.closure = closure;
-
- gpi.current_point.x = 0;
- gpi.current_point.y = 0;
-
- return _cairo_path_interpret (&path,
- CAIRO_DIRECTION_FORWARD,
- _gpi_move_to,
- _gpi_line_to,
- _gpi_curve_to,
- _gpi_close_path,
- &gpi);
-}
-
-/* XXX: gstate->alpha will be going away before too long, and when it
- * does, it may make sense for this function to just disappear.
- */
-static void
-_cairo_gstate_pattern_init_copy (cairo_gstate_t *gstate,
- cairo_pattern_union_t *pattern,
- cairo_pattern_t *src)
-{
- _cairo_pattern_init_copy (&pattern->base, src);
- _cairo_pattern_transform (&pattern->base, &gstate->ctm_inverse);
- _cairo_pattern_set_alpha (&pattern->base, gstate->alpha);
+ return status;
}
cairo_status_t
-_cairo_gstate_stroke (cairo_gstate_t *gstate)
+_cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
{
cairo_status_t status;
cairo_traps_t traps;
+ if (gstate->surface->level != gstate->surface_level)
+ return CAIRO_STATUS_BAD_NESTING;
+
if (gstate->line_width <= 0.0)
return CAIRO_STATUS_SUCCESS;
@@ -1335,41 +970,40 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate)
_cairo_traps_init (&traps);
- status = _cairo_path_stroke_to_traps (&gstate->path, gstate, &traps);
+ status = _cairo_path_fixed_stroke_to_traps (path, gstate, &traps);
if (status) {
_cairo_traps_fini (&traps);
return status;
}
_cairo_gstate_clip_and_composite_trapezoids (gstate,
- gstate->pattern,
+ gstate->source,
gstate->operator,
gstate->surface,
&traps);
_cairo_traps_fini (&traps);
- _cairo_gstate_new_path (gstate);
-
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
-_cairo_gstate_in_stroke (cairo_gstate_t *gstate,
- double x,
- double y,
- cairo_bool_t *inside_ret)
+_cairo_gstate_in_stroke (cairo_gstate_t *gstate,
+ cairo_path_fixed_t *path,
+ double x,
+ double y,
+ cairo_bool_t *inside_ret)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_traps_t traps;
- cairo_matrix_transform_point (&gstate->ctm, &x, &y);
+ _cairo_gstate_user_to_backend (gstate, &x, &y);
_cairo_pen_init (&gstate->pen_regular, gstate->line_width / 2.0, gstate);
_cairo_traps_init (&traps);
- status = _cairo_path_stroke_to_traps (&gstate->path, gstate, &traps);
+ status = _cairo_path_fixed_stroke_to_traps (path, gstate, &traps);
if (status)
goto BAIL;
@@ -1433,6 +1067,119 @@ _cairo_rectangle_empty (cairo_rectangle_t *rect)
return rect->width == 0 || rect->height == 0;
}
+/* Given a region representing a set of trapezoids that will be
+ * drawn, clip the region according to the gstate and compute
+ * the overall extents.
+ */
+static cairo_status_t
+_clip_and_compute_extents_region (cairo_gstate_t *gstate,
+ pixman_region16_t *trap_region,
+ cairo_rectangle_t *extents)
+{
+ cairo_status_t status;
+
+ status = _cairo_gstate_intersect_clip (gstate, trap_region);
+ if (!CAIRO_OK (status))
+ return status;
+
+ _region_rect_extents (trap_region, extents);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+/* Given a a set of trapezoids to draw, find a bounding box (non-exact)
+ * of the trapezoids clipped by the gstate
+ */
+static cairo_status_t
+_clip_and_compute_extents_arbitrary (cairo_gstate_t *gstate,
+ cairo_traps_t *traps,
+ cairo_rectangle_t *extents)
+{
+ cairo_box_t trap_extents;
+
+ _cairo_traps_extents (traps, &trap_extents);
+ _cairo_box_round_to_rectangle (&trap_extents, extents);
+
+ if (gstate->clip.region) {
+ pixman_region16_t *intersection;
+ cairo_status_t status;
+
+ status = _region_new_from_rect (extents, &intersection);
+ if (!CAIRO_OK (status))
+ return status;
+
+ if (pixman_region_intersect (intersection,
+ gstate->clip.region,
+ intersection) == PIXMAN_REGION_STATUS_SUCCESS)
+ _region_rect_extents (intersection, extents);
+ else
+ status = CAIRO_STATUS_NO_MEMORY;
+
+ pixman_region_destroy (intersection);
+
+ if (!CAIRO_OK (status))
+ return status;
+ }
+
+ if (gstate->clip.surface)
+ _cairo_rectangle_intersect (extents, &gstate->clip.rect);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+/* Composites a region representing a set of trapezoids.
+ */
+static cairo_status_t
+_composite_trap_region (cairo_gstate_t *gstate,
+ cairo_pattern_t *src,
+ cairo_operator_t operator,
+ cairo_surface_t *dst,
+ pixman_region16_t *trap_region,
+ cairo_rectangle_t *extents)
+{
+ cairo_status_t status, tmp_status;
+ cairo_pattern_union_t pattern;
+ cairo_pattern_union_t mask;
+ int num_rects = pixman_region_num_rects (trap_region);
+
+ if (num_rects == 0)
+ return CAIRO_STATUS_SUCCESS;
+
+ if (num_rects > 1) {
+ status = _cairo_surface_set_clip_region (dst, trap_region);
+ if (!CAIRO_OK (status))
+ return status;
+ }
+
+ _cairo_pattern_init_copy (&pattern.base, src);
+ _cairo_gstate_pattern_transform (gstate, &pattern.base);
+
+ if (gstate->clip.surface)
+ _cairo_pattern_init_for_surface (&mask.surface, gstate->clip.surface);
+
+ status = _cairo_surface_composite (gstate->operator,
+ &pattern.base,
+ gstate->clip.surface ? &mask.base : NULL,
+ dst,
+ extents->x, extents->y,
+ extents->x - (gstate->clip.surface ? gstate->clip.rect.x : 0),
+ extents->y - (gstate->clip.surface ? gstate->clip.rect.y : 0),
+ extents->x, extents->y,
+ extents->width, extents->height);
+
+ _cairo_pattern_fini (&pattern.base);
+ if (gstate->clip.surface)
+ _cairo_pattern_fini (&mask.base);
+
+ if (num_rects > 1) {
+ tmp_status = _cairo_surface_set_clip_region (dst, gstate->clip.region);
+ if (!CAIRO_OK (tmp_status))
+ status = tmp_status;
+ }
+
+ return status;
+}
+
static void
translate_traps (cairo_traps_t *traps, int x, int y)
{
@@ -1462,6 +1209,145 @@ translate_traps (cairo_traps_t *traps, int x, int y)
}
}
+/* Composites a set of trapezoids in the case where we need to create
+ * an intermediate surface to handle gstate->clip.surface
+ *
+ * Warning: This call modifies the coordinates of traps
+ */
+static cairo_status_t
+_composite_traps_intermediate_surface (cairo_gstate_t *gstate,
+ cairo_pattern_t *src,
+ cairo_operator_t operator,
+ cairo_surface_t *dst,
+ cairo_traps_t *traps,
+ cairo_rectangle_t *extents)
+{
+ cairo_pattern_union_t pattern;
+ cairo_surface_t *intermediate;
+ cairo_surface_pattern_t intermediate_pattern;
+ cairo_status_t status;
+
+ translate_traps (traps, -extents->x, -extents->y);
+
+ intermediate = _cairo_surface_create_similar_solid (gstate->clip.surface,
+ CAIRO_FORMAT_A8,
+ extents->width,
+ extents->height,
+ CAIRO_COLOR_TRANSPARENT);
+ if (intermediate == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
+
+ status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_ADD,
+ &pattern.base,
+ intermediate,
+ extents->x, extents->y,
+ 0, 0,
+ extents->width,
+ extents->height,
+ traps->traps,
+ traps->num_traps);
+ _cairo_pattern_fini (&pattern.base);
+
+ if (!CAIRO_OK (status))
+ goto out;
+
+ status = _cairo_gstate_combine_clip_surface (gstate, intermediate, extents);
+ if (!CAIRO_OK (status))
+ goto out;
+
+ _cairo_pattern_init_for_surface (&intermediate_pattern, intermediate);
+ _cairo_pattern_init_copy (&pattern.base, src);
+ _cairo_gstate_pattern_transform (gstate, &pattern.base);
+
+ status = _cairo_surface_composite (operator,
+ &pattern.base,
+ &intermediate_pattern.base,
+ dst,
+ extents->x, extents->y,
+ 0, 0,
+ extents->x, extents->y,
+ extents->width, extents->height);
+
+ _cairo_pattern_fini (&pattern.base);
+ _cairo_pattern_fini (&intermediate_pattern.base);
+
+ out:
+ cairo_surface_destroy (intermediate);
+
+ return status;
+}
+
+/* Composites a region representing a set of trapezoids in the
+ * case of a solid source (so we can use
+ * _cairo_surface_fill_rectangles).
+ */
+static cairo_status_t
+_composite_trap_region_solid (cairo_gstate_t *gstate,
+ cairo_solid_pattern_t *src,
+ cairo_operator_t operator,
+ cairo_surface_t *dst,
+ pixman_region16_t *region)
+{
+ int num_rects = pixman_region_num_rects (region);
+ pixman_box16_t *boxes = pixman_region_rects (region);
+ cairo_rectangle_t *rects;
+ cairo_status_t status;
+ int i;
+
+ if (!num_rects)
+ return CAIRO_STATUS_SUCCESS;
+
+ rects = malloc (sizeof (pixman_rectangle_t) * num_rects);
+ if (!rects)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ for (i = 0; i < num_rects; i++) {
+ rects[i].x = boxes[i].x1;
+ rects[i].y = boxes[i].y1;
+ rects[i].width = boxes[i].x2 - boxes[i].x1;
+ rects[i].height = boxes[i].y2 - boxes[i].y1;
+ }
+
+ status = _cairo_surface_fill_rectangles (dst, operator,
+ &src->color, rects, num_rects);
+
+ free (rects);
+
+ return status;
+}
+
+/* Composites a set of trapezoids in the general case where
+ gstate->clip.surface == NULL
+ */
+static cairo_status_t
+_composite_traps (cairo_gstate_t *gstate,
+ cairo_pattern_t *src,
+ cairo_operator_t operator,
+ cairo_surface_t *dst,
+ cairo_traps_t *traps,
+ cairo_rectangle_t *extents)
+{
+ cairo_pattern_union_t pattern;
+ cairo_status_t status;
+
+ _cairo_pattern_init_copy (&pattern.base, src);
+ _cairo_gstate_pattern_transform (gstate, &pattern.base);
+
+ status = _cairo_surface_composite_trapezoids (gstate->operator,
+ &pattern.base, dst,
+ extents->x, extents->y,
+ extents->x, extents->y,
+ extents->width,
+ extents->height,
+ traps->traps,
+ traps->num_traps);
+
+ _cairo_pattern_fini (&pattern.base);
+
+ return status;
+}
/* Warning: This call modifies the coordinates of traps */
static cairo_status_t
@@ -1472,197 +1358,124 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
cairo_traps_t *traps)
{
cairo_status_t status;
- cairo_pattern_union_t pattern;
+ pixman_region16_t *trap_region;
cairo_rectangle_t extents;
- cairo_box_t trap_extents;
-
+
if (traps->num_traps == 0)
return CAIRO_STATUS_SUCCESS;
if (gstate->surface == NULL)
return CAIRO_STATUS_NO_TARGET_SURFACE;
- _cairo_traps_extents (traps, &trap_extents);
- _cairo_box_round_to_rectangle (&trap_extents, &extents);
-
- if (gstate->clip.surface) {
- cairo_surface_t *intermediate;
- cairo_surface_pattern_t intermediate_pattern;
- cairo_color_t empty_color;
-
- _cairo_rectangle_intersect (&extents, &gstate->clip.rect);
-
- if (_cairo_rectangle_empty (&extents)) {
- status = CAIRO_STATUS_SUCCESS;
- goto BAIL1;
- }
-
- translate_traps (traps, -extents.x, -extents.y);
+ status = _cairo_traps_extract_region (traps, &trap_region);
+ if (!CAIRO_OK (status))
+ return status;
- _cairo_color_init (&empty_color);
- _cairo_color_set_alpha (&empty_color, 0.);
- intermediate = _cairo_surface_create_similar_solid (gstate->clip.surface,
- CAIRO_FORMAT_A8,
- extents.width,
- extents.height,
- &empty_color);
- if (intermediate == NULL) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto BAIL1;
- }
+ if (trap_region)
+ status = _clip_and_compute_extents_region (gstate, trap_region, &extents);
+ else
+ status = _clip_and_compute_extents_arbitrary (gstate, traps, &extents);
- _cairo_pattern_init_solid (&pattern.solid, 1.0, 1.0, 1.0);
-
- status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_ADD,
- &pattern.base,
- intermediate,
- extents.x, extents.y,
- 0, 0,
- extents.width,
- extents.height,
- traps->traps,
- traps->num_traps);
- _cairo_pattern_fini (&pattern.base);
-
- if (status)
- goto BAIL2;
-
-
- _cairo_pattern_init_for_surface (&pattern.surface,
- gstate->clip.surface);
-
- status = _cairo_surface_composite (CAIRO_OPERATOR_IN,
- &pattern.base,
- NULL,
- intermediate,
- extents.x - gstate->clip.rect.x,
- extents.y - gstate->clip.rect.y,
- 0, 0,
- 0, 0,
- extents.width, extents.height);
- _cairo_pattern_fini (&pattern.base);
+ if (!CAIRO_OK (status))
+ goto out;
- if (status)
- goto BAIL2;
-
- _cairo_pattern_init_for_surface (&intermediate_pattern, intermediate);
- _cairo_gstate_pattern_init_copy (gstate, &pattern, src);
-
- status = _cairo_surface_composite (operator,
- &pattern.base,
- &intermediate_pattern.base,
- dst,
- extents.x, extents.y,
- 0, 0,
- extents.x, extents.y,
- extents.width, extents.height);
-
- _cairo_pattern_fini (&pattern.base);
- _cairo_pattern_fini (&intermediate_pattern.base);
-
- BAIL2:
- cairo_surface_destroy (intermediate);
- BAIL1:
+ if (_cairo_rectangle_empty (&extents))
+ /* Nothing to do */
+ goto out;
- if (status)
- return status;
+ if (gstate->clip.surface) {
+ if (trap_region) {
+ /* If we are compositing a set of rectangles, we can set them as the
+ * clip region for the destination surface and use the clip surface
+ * as the mask. A clip region might not be supported, in which case
+ * we fall through to the next method
+ */
+ status = _composite_trap_region (gstate, src, operator, dst,
+ trap_region, &extents);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ goto out;
+ }
+ /* Handle a clip surface by creating an intermediate surface. */
+ status = _composite_traps_intermediate_surface (gstate, src, operator,
+ dst, traps, &extents);
} else {
- if (gstate->clip.region) {
- pixman_box16_t box;
- pixman_box16_t *intersection_extents;
- pixman_region16_t *rect, *intersection;
-
- box.x1 = _cairo_fixed_integer_floor (trap_extents.p1.x);
- box.y1 = _cairo_fixed_integer_floor (trap_extents.p1.y);
- box.x2 = _cairo_fixed_integer_ceil (trap_extents.p2.x);
- box.y2 = _cairo_fixed_integer_ceil (trap_extents.p2.y);
-
- rect = pixman_region_create_simple (&box);
- if (rect == NULL)
- goto bail1;
- intersection = pixman_region_create();
- if (intersection == NULL)
- goto bail2;
-
- if (pixman_region_intersect (intersection, gstate->clip.region,
- rect) != PIXMAN_REGION_STATUS_SUCCESS)
- goto bail3;
- intersection_extents = pixman_region_extents (intersection);
-
- extents.x = intersection_extents->x1;
- extents.y = intersection_extents->y1;
- extents.width = intersection_extents->x2 - intersection_extents->x1;
- extents.height = intersection_extents->y2 - intersection_extents->y1;
- bail3:
- pixman_region_destroy (intersection);
- bail2:
- pixman_region_destroy (rect);
- bail1:
- ;
+ /* No clip surface */
+ if (trap_region && src->type == CAIRO_PATTERN_SOLID) {
+ /* Solid rectangles are handled specially */
+ status = _composite_trap_region_solid (gstate, (cairo_solid_pattern_t *)src,
+ operator, dst, trap_region);
+ } else if (trap_region && pixman_region_num_rects (trap_region) <= 1) {
+ /* For a simple rectangle, we can just use composite(), for more
+ * rectangles, we'd have to set a clip region. That might still
+ * be a win, but it's less obvious. (Depends on the backend)
+ */
+ status = _composite_trap_region (gstate, src, operator, dst,
+ trap_region, &extents);
+ } else {
+ status = _composite_traps (gstate, src, operator,
+ dst, traps, &extents);
}
-
- _cairo_gstate_pattern_init_copy (gstate, &pattern, src);
-
- status = _cairo_surface_composite_trapezoids (gstate->operator,
- &pattern.base, dst,
- extents.x, extents.y,
- extents.x, extents.y,
- extents.width,
- extents.height,
- traps->traps,
- traps->num_traps);
-
- _cairo_pattern_fini (&pattern.base);
-
- if (status)
- return status;
}
+
+ out:
+ if (trap_region)
+ pixman_region_destroy (trap_region);
- return CAIRO_STATUS_SUCCESS;
+ return status;
}
cairo_status_t
-_cairo_gstate_fill (cairo_gstate_t *gstate)
+_cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
{
cairo_status_t status;
cairo_traps_t traps;
+ if (gstate->surface->level != gstate->surface_level)
+ return CAIRO_STATUS_BAD_NESTING;
+
+ status = _cairo_surface_fill_path (gstate->operator,
+ gstate->source,
+ gstate->surface,
+ path);
+
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
+
_cairo_traps_init (&traps);
- status = _cairo_path_fill_to_traps (&gstate->path, gstate, &traps);
+ status = _cairo_path_fixed_fill_to_traps (path, gstate, &traps);
if (status) {
_cairo_traps_fini (&traps);
return status;
}
_cairo_gstate_clip_and_composite_trapezoids (gstate,
- gstate->pattern,
+ gstate->source,
gstate->operator,
gstate->surface,
&traps);
_cairo_traps_fini (&traps);
- _cairo_gstate_new_path (gstate);
-
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
-_cairo_gstate_in_fill (cairo_gstate_t *gstate,
- double x,
- double y,
- cairo_bool_t *inside_ret)
+_cairo_gstate_in_fill (cairo_gstate_t *gstate,
+ cairo_path_fixed_t *path,
+ double x,
+ double y,
+ cairo_bool_t *inside_ret)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_traps_t traps;
- cairo_matrix_transform_point (&gstate->ctm, &x, &y);
+ _cairo_gstate_user_to_backend (gstate, &x, &y);
_cairo_traps_init (&traps);
- status = _cairo_path_fill_to_traps (&gstate->path, gstate, &traps);
+ status = _cairo_path_fixed_fill_to_traps (path, gstate, &traps);
if (status)
goto BAIL;
@@ -1693,7 +1506,8 @@ _cairo_gstate_show_page (cairo_gstate_t *gstate)
}
cairo_status_t
-_cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
+_cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
+ cairo_path_fixed_t *path,
double *x1, double *y1,
double *x2, double *y2)
{
@@ -1701,9 +1515,11 @@ _cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
cairo_traps_t traps;
cairo_box_t extents;
+ _cairo_pen_init (&gstate->pen_regular, gstate->line_width / 2.0, gstate);
+
_cairo_traps_init (&traps);
- status = _cairo_path_stroke_to_traps (&gstate->path, gstate, &traps);
+ status = _cairo_path_fixed_stroke_to_traps (path, gstate, &traps);
if (status)
goto BAIL;
@@ -1714,8 +1530,8 @@ _cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
*x2 = _cairo_fixed_to_double (extents.p2.x);
*y2 = _cairo_fixed_to_double (extents.p2.y);
- cairo_matrix_transform_point (&gstate->ctm_inverse, x1, y1);
- cairo_matrix_transform_point (&gstate->ctm_inverse, x2, y2);
+ _cairo_gstate_backend_to_user (gstate, x1, y1);
+ _cairo_gstate_backend_to_user (gstate, x2, y2);
BAIL:
_cairo_traps_fini (&traps);
@@ -1724,7 +1540,8 @@ BAIL:
}
cairo_status_t
-_cairo_gstate_fill_extents (cairo_gstate_t *gstate,
+_cairo_gstate_fill_extents (cairo_gstate_t *gstate,
+ cairo_path_fixed_t *path,
double *x1, double *y1,
double *x2, double *y2)
{
@@ -1734,7 +1551,7 @@ _cairo_gstate_fill_extents (cairo_gstate_t *gstate,
_cairo_traps_init (&traps);
- status = _cairo_path_fill_to_traps (&gstate->path, gstate, &traps);
+ status = _cairo_path_fixed_fill_to_traps (path, gstate, &traps);
if (status)
goto BAIL;
@@ -1745,8 +1562,8 @@ _cairo_gstate_fill_extents (cairo_gstate_t *gstate,
*x2 = _cairo_fixed_to_double (extents.p2.x);
*y2 = _cairo_fixed_to_double (extents.p2.y);
- cairo_matrix_transform_point (&gstate->ctm_inverse, x1, y1);
- cairo_matrix_transform_point (&gstate->ctm_inverse, x2, y2);
+ _cairo_gstate_backend_to_user (gstate, x1, y1);
+ _cairo_gstate_backend_to_user (gstate, x2, y2);
BAIL:
_cairo_traps_fini (&traps);
@@ -1755,8 +1572,11 @@ BAIL:
}
cairo_status_t
-_cairo_gstate_init_clip (cairo_gstate_t *gstate)
+_cairo_gstate_reset_clip (cairo_gstate_t *gstate)
{
+ if (gstate->surface->level != gstate->surface_level)
+ return CAIRO_STATUS_BAD_NESTING;
+
/* destroy any existing clip-region artifacts */
if (gstate->clip.surface)
cairo_surface_destroy (gstate->clip.surface);
@@ -1774,113 +1594,57 @@ _cairo_gstate_init_clip (cairo_gstate_t *gstate)
return CAIRO_STATUS_SUCCESS;
}
-static int
-extract_transformed_rectangle(cairo_matrix_t *mat,
- cairo_traps_t *tr,
- pixman_box16_t *box)
-{
- double a, b, c, d, tx, ty;
- cairo_status_t st;
-
- st = cairo_matrix_get_affine (mat, &a, &b, &c, &d, &tx, &ty);
- if (!(st == CAIRO_STATUS_SUCCESS && b == 0. && c == 0.))
- return 0;
-
- if (tr->num_traps == 1
- && tr->traps[0].left.p1.x == tr->traps[0].left.p2.x
- && tr->traps[0].right.p1.x == tr->traps[0].right.p2.x
- && tr->traps[0].left.p1.y == tr->traps[0].right.p1.y
- && tr->traps[0].left.p2.y == tr->traps[0].right.p2.y
- && _cairo_fixed_is_integer(tr->traps[0].left.p1.x)
- && _cairo_fixed_is_integer(tr->traps[0].left.p1.y)
- && _cairo_fixed_is_integer(tr->traps[0].left.p2.x)
- && _cairo_fixed_is_integer(tr->traps[0].left.p2.y)
- && _cairo_fixed_is_integer(tr->traps[0].right.p1.x)
- && _cairo_fixed_is_integer(tr->traps[0].right.p1.y)
- && _cairo_fixed_is_integer(tr->traps[0].right.p2.x)
- && _cairo_fixed_is_integer(tr->traps[0].right.p2.y)) {
-
- box->x1 = (short) _cairo_fixed_integer_part(tr->traps[0].left.p1.x);
- box->x2 = (short) _cairo_fixed_integer_part(tr->traps[0].right.p1.x);
- box->y1 = (short) _cairo_fixed_integer_part(tr->traps[0].left.p1.y);
- box->y2 = (short) _cairo_fixed_integer_part(tr->traps[0].left.p2.y);
- return 1;
- }
- return 0;
-}
-
-/* Reset surface clip region to the one in the gstate */
-cairo_status_t
-_cairo_gstate_restore_external_state (cairo_gstate_t *gstate)
-{
- cairo_status_t status;
-
- status = CAIRO_STATUS_SUCCESS;
-
- if (gstate->surface)
- status = _cairo_surface_set_clip_region (gstate->surface,
- gstate->clip.region);
-
- /* If not supported we're already using surface clipping */
- if (status == CAIRO_INT_STATUS_UNSUPPORTED)
- status = CAIRO_STATUS_SUCCESS;
-
- return status;
-}
-
cairo_status_t
-_cairo_gstate_clip (cairo_gstate_t *gstate)
+_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
{
cairo_status_t status;
cairo_pattern_union_t pattern;
cairo_traps_t traps;
- cairo_color_t white_color;
cairo_box_t extents;
- pixman_box16_t box;
+ pixman_region16_t *region;
+ if (gstate->surface->level != gstate->surface_level)
+ return CAIRO_STATUS_BAD_NESTING;
+
/* Fill the clip region as traps. */
_cairo_traps_init (&traps);
- status = _cairo_path_fill_to_traps (&gstate->path, gstate, &traps);
- if (status) {
+ status = _cairo_path_fixed_fill_to_traps (path, gstate, &traps);
+ if (!CAIRO_OK (status)) {
_cairo_traps_fini (&traps);
return status;
}
/* Check to see if we can represent these traps as a PixRegion. */
- if (extract_transformed_rectangle (&gstate->ctm, &traps, &box)) {
-
- pixman_region16_t *rect = NULL;
- pixman_region16_t *intersection = NULL;
-
+ status = _cairo_traps_extract_region (&traps, &region);
+ if (!CAIRO_OK (status)) {
+ _cairo_traps_fini (&traps);
+ return status;
+ }
+
+ if (region) {
status = CAIRO_STATUS_SUCCESS;
- rect = pixman_region_create_simple (&box);
- if (rect == NULL) {
- status = CAIRO_STATUS_NO_MEMORY;
-
+ if (gstate->clip.region == NULL) {
+ gstate->clip.region = region;
} else {
-
- if (gstate->clip.region == NULL) {
- gstate->clip.region = rect;
- } else {
- intersection = pixman_region_create();
- if (pixman_region_intersect (intersection,
- gstate->clip.region, rect)
- == PIXMAN_REGION_STATUS_SUCCESS) {
- pixman_region_destroy (gstate->clip.region);
- gstate->clip.region = intersection;
- } else {
- status = CAIRO_STATUS_NO_MEMORY;
- }
- pixman_region_destroy (rect);
+ pixman_region16_t *intersection = pixman_region_create();
+
+ if (pixman_region_intersect (intersection,
+ gstate->clip.region, region)
+ == PIXMAN_REGION_STATUS_SUCCESS) {
+ pixman_region_destroy (gstate->clip.region);
+ gstate->clip.region = intersection;
+ } else {
+ status = CAIRO_STATUS_NO_MEMORY;
}
-
- if (!status)
- status = _cairo_surface_set_clip_region (gstate->surface,
- gstate->clip.region);
+ pixman_region_destroy (region);
}
+
+ if (CAIRO_OK (status))
+ status = _cairo_surface_set_clip_region (gstate->surface,
+ gstate->clip.region);
if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
_cairo_traps_fini (&traps);
@@ -1894,8 +1658,6 @@ _cairo_gstate_clip (cairo_gstate_t *gstate)
/* Otherwise represent the clip as a mask surface. */
- _cairo_color_init (&white_color);
-
if (gstate->clip.surface == NULL) {
_cairo_traps_extents (&traps, &extents);
_cairo_box_round_to_rectangle (&extents, &gstate->clip.rect);
@@ -1904,13 +1666,13 @@ _cairo_gstate_clip (cairo_gstate_t *gstate)
CAIRO_FORMAT_A8,
gstate->clip.rect.width,
gstate->clip.rect.height,
- &white_color);
+ CAIRO_COLOR_WHITE);
if (gstate->clip.surface == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
translate_traps (&traps, -gstate->clip.rect.x, -gstate->clip.rect.y);
- _cairo_pattern_init_solid (&pattern.solid, 1.0, 1.0, 1.0);
+ _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_IN,
&pattern.base,
@@ -1929,254 +1691,77 @@ _cairo_gstate_clip (cairo_gstate_t *gstate)
return CAIRO_STATUS_SUCCESS;
}
-cairo_status_t
-_cairo_gstate_show_surface (cairo_gstate_t *gstate,
- cairo_surface_t *surface,
- int width,
- int height)
-{
-
- /* We are dealing with 6 coordinate spaces in this function. this makes
- * it ugly.
- *
- * - "Image" space is the space of the surface we're reading pixels from.
- * it is the surface argument to this function. The surface has a
- * matrix attached to it which maps "user" space (see below) into
- * image space.
- *
- * - "Device" space is the space of the surface we're ultimately writing
- * pixels to. It is the current surface of the gstate argument to
- * this function.
- *
- * - "User" space is an arbitrary space defined by the user, defined
- * implicitly by the gstate's CTM. The CTM maps from user space to
- * device space. The CTM inverse (which is also kept at all times)
- * maps from device space to user space.
- *
- * - "Clip" space is the space of the surface being used to clip pixels
- * during compositing. Space-wise, it is a bounding box (offset+size)
- * within device space. This surface is usually smaller than the device
- * surface (and possibly the image surface too) and logically occupies
- * a bounding box around the "clip path", situated somewhere in device
- * space. The clip path is already painted on the clip surface.
- *
- * - "Intermediate" space is the subset of the Clip space that the
- * drawing will affect, and we allocate an intermediate surface
- * of this size so that we can paint in it.
- *
- * - "Pattern" space is another arbitrary space defined in the pattern
- * element of gstate. As pixels are read from image space, they are
- * combined with pixels being read from pattern space and pixels
- * already existing in device space. User coordinates are converted
- * to pattern space, similarly, using a matrix attached to the pattern.
- * (in fact, there is a 7th space in here, which is the space of the
- * surface acting as a source for the pattern)
- *
- * To composite these spaces, we temporarily change the image surface
- * so that it can be read and written in device coordinates; in a sense
- * this makes it "spatially compatible" with the clip and device spaces.
- *
- *
- * There is also some confusion about the interaction between a clip and
- * a pattern; it is assumed that in this "show surface" operation a pattern
- * is to be used as an auxiliary alpha mask. this might be wrong, but it's
- * what we're doing now.
- *
- * so, to follow the operations below, remember that in the compositing
- * model, each operation is always of the form ((src IN mask) OP dst).
- * that's the basic operation.
- *
- * so the compositing we are trying to do here, in general, involves 2
- * steps, going via a temporary surface:
- *
- * - combining clip and pattern pixels together into a mask channel.
- * this will be ((pattern IN clip) SRC temporary). it ignores the
- * pixels already in the temporary, overwriting it with the
- * pattern, clipped to the clip mask.
- *
- * - combining temporary and "image" pixels with "device" pixels,
- * with a user-provided porter/duff operator. this will be
- * ((image IN temporary) OP device).
- *
- * if there is no clip, the degenerate case is just the second step
- * with pattern standing in for temporary.
- *
- */
-
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
- cairo_matrix_t image_to_user, image_to_device;
- double device_x, device_y;
- double device_width, device_height;
- cairo_surface_pattern_t pattern;
- cairo_box_t pattern_extents;
- cairo_rectangle_t extents;
-
- cairo_surface_get_matrix (surface, &image_to_user);
- cairo_matrix_invert (&image_to_user);
- cairo_matrix_multiply (&image_to_device, &image_to_user, &gstate->ctm);
-
- _cairo_gstate_current_point (gstate, &device_x, &device_y);
- device_width = width;
- device_height = height;
- _cairo_matrix_transform_bounding_box (&image_to_device,
- &device_x, &device_y,
- &device_width, &device_height);
-
- _cairo_pattern_init_for_surface (&pattern, surface);
-
- /* inherit surface attributes while surface attribute functions still
- exist */
- pattern.base.matrix = surface->matrix;
- pattern.base.filter = surface->filter;
- if (surface->repeat)
- pattern.base.extend = CAIRO_EXTEND_REPEAT;
- else
- pattern.base.extend = CAIRO_EXTEND_NONE;
-
- _cairo_pattern_transform (&pattern.base, &gstate->ctm_inverse);
- _cairo_pattern_set_alpha (&pattern.base, gstate->alpha);
-
- pattern_extents.p1.x = _cairo_fixed_from_double (device_x);
- pattern_extents.p1.y = _cairo_fixed_from_double (device_y);
- pattern_extents.p2.x = _cairo_fixed_from_double (device_x + device_width);
- pattern_extents.p2.y = _cairo_fixed_from_double (device_y + device_height);
- _cairo_box_round_to_rectangle (&pattern_extents, &extents);
-
- if (gstate->clip.surface)
- {
- _cairo_rectangle_intersect (&extents, &gstate->clip.rect);
-
- /* We only need to composite if the rectangle is not empty. */
- if (!_cairo_rectangle_empty (&extents)) {
- cairo_surface_pattern_t clip_pattern;
-
- _cairo_pattern_init_for_surface (&clip_pattern,
- gstate->clip.surface);
-
- status = _cairo_surface_composite (gstate->operator,
- &pattern.base,
- &clip_pattern.base,
- gstate->surface,
- extents.x, extents.y,
- 0, 0,
- extents.x, extents.y,
- extents.width, extents.height);
-
- _cairo_pattern_fini (&clip_pattern.base);
- }
- }
- else
- {
- /* XXX: The rendered size is sometimes 1 or 2 pixels short
- * from what I expect. Need to fix this.
- * KRH: I'm guessing this was due to rounding error when
- * passing double coordinates for integer arguments. Using
- * the extents rectangle should fix this, since it's properly
- * rounded. Is this still the case?
- */
- status = _cairo_surface_composite (gstate->operator,
- &pattern.base,
- NULL,
- gstate->surface,
- extents.x, extents.y,
- 0, 0,
- extents.x, extents.y,
- extents.width, extents.height);
-
- }
-
- _cairo_pattern_fini (&pattern.base);
-
- return status;
-}
-
static void
_cairo_gstate_unset_font (cairo_gstate_t *gstate)
{
- if (gstate->font) {
- cairo_font_destroy (gstate->font);
- gstate->font = NULL;
+ if (gstate->scaled_font) {
+ cairo_scaled_font_destroy (gstate->scaled_font);
+ gstate->scaled_font = NULL;
}
}
cairo_status_t
-_cairo_gstate_select_font (cairo_gstate_t *gstate,
- const char *family,
- cairo_font_slant_t slant,
- cairo_font_weight_t weight)
+_cairo_gstate_select_font_face (cairo_gstate_t *gstate,
+ const char *family,
+ cairo_font_slant_t slant,
+ cairo_font_weight_t weight)
{
- char *new_family;
+ cairo_font_face_t *font_face;
- new_family = strdup (family);
- if (!new_family)
+ font_face = _cairo_simple_font_face_create (family, slant, weight);
+ if (!font_face)
return CAIRO_STATUS_NO_MEMORY;
-
- _cairo_gstate_unset_font (gstate);
-
- gstate->font_family = new_family;
- gstate->font_slant = slant;
- gstate->font_weight = weight;
- cairo_matrix_set_identity (&gstate->font_matrix);
-
+ _cairo_gstate_set_font_face (gstate, font_face);
+ cairo_font_face_destroy (font_face);
+
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
-_cairo_gstate_scale_font (cairo_gstate_t *gstate,
- double scale)
+_cairo_gstate_set_font_size (cairo_gstate_t *gstate,
+ double size)
{
_cairo_gstate_unset_font (gstate);
- return cairo_matrix_scale (&gstate->font_matrix, scale, scale);
+ cairo_matrix_init_scale (&gstate->font_matrix, size, size);
+
+ return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
-_cairo_gstate_transform_font (cairo_gstate_t *gstate,
- cairo_matrix_t *matrix)
+_cairo_gstate_set_font_matrix (cairo_gstate_t *gstate,
+ const cairo_matrix_t *matrix)
{
- cairo_matrix_t tmp;
- double a, b, c, d, tx, ty;
-
_cairo_gstate_unset_font (gstate);
- cairo_matrix_get_affine (matrix, &a, &b, &c, &d, &tx, &ty);
- cairo_matrix_set_affine (&tmp, a, b, c, d, 0, 0);
- return cairo_matrix_multiply (&gstate->font_matrix, &gstate->font_matrix, &tmp);
+ gstate->font_matrix = *matrix;
+
+ return CAIRO_STATUS_SUCCESS;
}
+void
+_cairo_gstate_get_font_matrix (cairo_gstate_t *gstate,
+ cairo_matrix_t *matrix)
+{
+ *matrix = gstate->font_matrix;
+}
cairo_status_t
-_cairo_gstate_current_font (cairo_gstate_t *gstate,
- cairo_font_t **font)
+_cairo_gstate_get_font_face (cairo_gstate_t *gstate,
+ cairo_font_face_t **font_face)
{
cairo_status_t status;
- status = _cairo_gstate_ensure_font (gstate);
+ status = _cairo_gstate_ensure_font_face (gstate);
if (status)
return status;
- *font = gstate->font;
+ *font_face = gstate->font_face;
return CAIRO_STATUS_SUCCESS;
}
-void
-_cairo_gstate_set_font_transform (cairo_gstate_t *gstate,
- cairo_matrix_t *matrix)
-{
- _cairo_gstate_unset_font (gstate);
-
- cairo_matrix_copy (&gstate->font_matrix, matrix);
-}
-
-void
-_cairo_gstate_current_font_transform (cairo_gstate_t *gstate,
- cairo_matrix_t *matrix)
-{
- cairo_matrix_copy (matrix, &gstate->font_matrix);
-}
-
/*
* Like everything else in this file, fonts involve Too Many Coordinate Spaces;
* it is easy to get confused about what's going on.
@@ -2191,11 +1776,10 @@ _cairo_gstate_current_font_transform (cairo_gstate_t *gstate,
* independently scale the user coordinate system *or* the font matrix, in
* order to adjust the rendered size of the font.
*
- * The only font type exposed to the user is cairo_font_t which is a
- * a font specialized to a particular scale matrix, CTM, and target
- * surface. The user is responsible for not using a cairo_font_t
- * after changing the parameters; doing so will produce garbled metrics.
- *
+ * Metrics are returned in user space, whether they are obtained from
+ * the currently selected font in a #cairo_t or from a #cairo_scaled_font_t
+ * which is aa font specialized to a particular scale matrix, CTM, and target
+ * surface.
*
* The font's view
* ---------------
@@ -2254,122 +1838,102 @@ _cairo_gstate_current_font_transform (cairo_gstate_t *gstate,
*
*/
-void
-_cairo_gstate_current_font_scale (cairo_gstate_t *gstate,
- cairo_font_scale_t *sc)
+static cairo_status_t
+_cairo_gstate_ensure_font_face (cairo_gstate_t *gstate)
{
- cairo_matrix_t tmp;
- double dummy;
- cairo_matrix_multiply (&tmp, &gstate->font_matrix, &gstate->ctm);
- cairo_matrix_get_affine (&tmp,
- &sc->matrix[0][0],
- &sc->matrix[0][1],
- &sc->matrix[1][0],
- &sc->matrix[1][1],
- &dummy, &dummy);
+ 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;
+ }
+
+ return CAIRO_STATUS_SUCCESS;
}
-
+
static cairo_status_t
_cairo_gstate_ensure_font (cairo_gstate_t *gstate)
{
- cairo_font_scale_t sc;
cairo_status_t status;
- const char *family;
- if (gstate->font)
+ if (gstate->scaled_font)
return CAIRO_STATUS_SUCCESS;
- _cairo_gstate_current_font_scale (gstate, &sc);
-
- if (gstate->font_family)
- family = gstate->font_family;
- else
- family = CAIRO_FONT_FAMILY_DEFAULT;
-
- status = _cairo_font_create (family,
- gstate->font_slant,
- gstate->font_weight,
- &sc,
- &gstate->font);
-
+ status = _cairo_gstate_ensure_font_face (gstate);
if (status)
return status;
+ gstate->scaled_font = cairo_scaled_font_create (gstate->font_face,
+ &gstate->font_matrix,
+ &gstate->ctm);
+
+ if (!gstate->scaled_font)
+ return CAIRO_STATUS_NO_MEMORY;
+
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
-_cairo_gstate_current_font_extents (cairo_gstate_t *gstate,
- cairo_font_extents_t *extents)
+_cairo_gstate_get_font_extents (cairo_gstate_t *gstate,
+ cairo_font_extents_t *extents)
{
cairo_status_t status = _cairo_gstate_ensure_font (gstate);
if (status)
return status;
- return cairo_font_extents (gstate->font,
- &gstate->font_matrix,
- extents);
+ return cairo_scaled_font_extents (gstate->scaled_font, extents);
}
cairo_status_t
_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
- const unsigned char *utf8,
+ const char *utf8,
+ double x,
+ double y,
cairo_glyph_t **glyphs,
- int *nglyphs)
+ int *num_glyphs)
{
cairo_status_t status;
-
- cairo_point_t point;
- double origin_x, origin_y;
int i;
status = _cairo_gstate_ensure_font (gstate);
if (status)
return status;
- status = _cairo_path_current_point (&gstate->path, &point);
- if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
- origin_x = 0.0;
- origin_y = 0.0;
- } else {
- origin_x = _cairo_fixed_to_double (point.x);
- origin_y = _cairo_fixed_to_double (point.y);
- cairo_matrix_transform_point (&gstate->ctm_inverse,
- &origin_x, &origin_y);
- }
-
- status = _cairo_font_text_to_glyphs (gstate->font,
- utf8, glyphs, nglyphs);
+ status = _cairo_scaled_font_text_to_glyphs (gstate->scaled_font,
+ utf8, glyphs, num_glyphs);
- if (status || !glyphs || !nglyphs || !(*glyphs) || !(nglyphs))
+ if (status || !glyphs || !num_glyphs || !(*glyphs) || !(num_glyphs))
return status;
/* The font responded in glyph space, starting from (0,0). Convert to
user space by applying the font transform, then add any current point
offset. */
- for (i = 0; i < *nglyphs; ++i) {
+ for (i = 0; i < *num_glyphs; ++i) {
cairo_matrix_transform_point (&gstate->font_matrix,
&((*glyphs)[i].x),
&((*glyphs)[i].y));
- (*glyphs)[i].x += origin_x;
- (*glyphs)[i].y += origin_y;
+ (*glyphs)[i].x += x;
+ (*glyphs)[i].y += y;
}
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
-_cairo_gstate_set_font (cairo_gstate_t *gstate,
- cairo_font_t *font)
-{
- if (font != gstate->font) {
- if (gstate->font)
- cairo_font_destroy (gstate->font);
- gstate->font = font;
- if (gstate->font)
- cairo_font_reference (gstate->font);
+_cairo_gstate_set_font_face (cairo_gstate_t *gstate,
+ cairo_font_face_t *font_face)
+{
+ if (font_face != gstate->font_face) {
+ if (gstate->font_face)
+ cairo_font_face_destroy (gstate->font_face);
+ gstate->font_face = font_face;
+ if (gstate->font_face)
+ cairo_font_face_reference (gstate->font_face);
}
+
+ _cairo_gstate_unset_font (gstate);
return CAIRO_STATUS_SUCCESS;
}
@@ -2386,10 +1950,9 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
if (status)
return status;
- cairo_font_glyph_extents (gstate->font,
- &gstate->font_matrix,
- glyphs, num_glyphs,
- extents);
+ cairo_scaled_font_glyph_extents (gstate->scaled_font,
+ glyphs, num_glyphs,
+ extents);
return CAIRO_STATUS_SUCCESS;
}
@@ -2406,6 +1969,9 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
cairo_box_t bbox;
cairo_rectangle_t extents;
+ if (gstate->surface->level != gstate->surface_level)
+ return CAIRO_STATUS_BAD_NESTING;
+
status = _cairo_gstate_ensure_font (gstate);
if (status)
return status;
@@ -2417,14 +1983,14 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
for (i = 0; i < num_glyphs; ++i)
{
transformed_glyphs[i] = glyphs[i];
- cairo_matrix_transform_point (&gstate->ctm,
- &transformed_glyphs[i].x,
- &transformed_glyphs[i].y);
+ _cairo_gstate_user_to_backend (gstate,
+ &transformed_glyphs[i].x,
+ &transformed_glyphs[i].y);
}
- status = _cairo_font_glyph_bbox (gstate->font,
- transformed_glyphs, num_glyphs,
- &bbox);
+ status = _cairo_scaled_font_glyph_bbox (gstate->scaled_font,
+ transformed_glyphs, num_glyphs,
+ &bbox);
_cairo_box_round_to_rectangle (&bbox, &extents);
if (status)
@@ -2434,7 +2000,6 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
{
cairo_surface_t *intermediate;
cairo_surface_pattern_t intermediate_pattern;
- cairo_color_t empty_color;
_cairo_rectangle_intersect (&extents, &gstate->clip.rect);
@@ -2444,13 +2009,11 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
goto BAIL1;
}
- _cairo_color_init (&empty_color);
- _cairo_color_set_alpha (&empty_color, .0);
intermediate = _cairo_surface_create_similar_solid (gstate->clip.surface,
CAIRO_FORMAT_A8,
extents.width,
extents.height,
- &empty_color);
+ CAIRO_COLOR_TRANSPARENT);
if (intermediate == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto BAIL1;
@@ -2463,15 +2026,15 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
transformed_glyphs[i].y -= extents.y;
}
- _cairo_pattern_init_solid (&pattern.solid, 1.0, 1.0, 1.0);
+ _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
- status = _cairo_font_show_glyphs (gstate->font,
- CAIRO_OPERATOR_ADD,
- &pattern.base, intermediate,
- extents.x, extents.y,
- 0, 0,
- extents.width, extents.height,
- transformed_glyphs, num_glyphs);
+ status = _cairo_scaled_font_show_glyphs (gstate->scaled_font,
+ CAIRO_OPERATOR_ADD,
+ &pattern.base, intermediate,
+ extents.x, extents.y,
+ 0, 0,
+ extents.width, extents.height,
+ transformed_glyphs, num_glyphs);
_cairo_pattern_fini (&pattern.base);
@@ -2497,7 +2060,8 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
goto BAIL2;
_cairo_pattern_init_for_surface (&intermediate_pattern, intermediate);
- _cairo_gstate_pattern_init_copy (gstate, &pattern, gstate->pattern);
+ _cairo_pattern_init_copy (&pattern.base, gstate->source);
+ _cairo_gstate_pattern_transform (gstate, &pattern.base);
status = _cairo_surface_composite (gstate->operator,
&pattern.base,
@@ -2517,15 +2081,16 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
}
else
{
- _cairo_gstate_pattern_init_copy (gstate, &pattern, gstate->pattern);
+ _cairo_pattern_init_copy (&pattern.base, gstate->source);
+ _cairo_gstate_pattern_transform (gstate, &pattern.base);
- status = _cairo_font_show_glyphs (gstate->font,
- gstate->operator, &pattern.base,
- gstate->surface,
- extents.x, extents.y,
- extents.x, extents.y,
- extents.width, extents.height,
- transformed_glyphs, num_glyphs);
+ status = _cairo_scaled_font_show_glyphs (gstate->scaled_font,
+ gstate->operator, &pattern.base,
+ gstate->surface,
+ extents.x, extents.y,
+ extents.x, extents.y,
+ extents.width, extents.height,
+ transformed_glyphs, num_glyphs);
_cairo_pattern_fini (&pattern.base);
}
@@ -2537,14 +2102,19 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
}
cairo_status_t
-_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
- cairo_glyph_t *glyphs,
- int num_glyphs)
+_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_path_fixed_t *path)
{
cairo_status_t status;
int i;
cairo_glyph_t *transformed_glyphs = NULL;
+ status = _cairo_gstate_ensure_font (gstate);
+ if (status)
+ return status;
+
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
if (transformed_glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;
@@ -2552,14 +2122,14 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
for (i = 0; i < num_glyphs; ++i)
{
transformed_glyphs[i] = glyphs[i];
- cairo_matrix_transform_point (&gstate->ctm,
- &(transformed_glyphs[i].x),
- &(transformed_glyphs[i].y));
+ _cairo_gstate_user_to_backend (gstate,
+ &(transformed_glyphs[i].x),
+ &(transformed_glyphs[i].y));
}
- status = _cairo_font_glyph_path (gstate->font,
- transformed_glyphs, num_glyphs,
- &gstate->path);
+ status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
+ transformed_glyphs, num_glyphs,
+ path);
free (transformed_glyphs);
return status;
diff --git a/src/cairo-hash.c b/src/cairo-hash.c
index d1ad5a4e2..e95894960 100644
--- a/src/cairo-hash.c
+++ b/src/cairo-hash.c
@@ -113,7 +113,9 @@ static const cairo_cache_arrangement_t cache_arrangements [] = {
#define LIVE_ENTRY_P(cache, i) \
(!((NULL_ENTRY_P((cache),(i))) || (DEAD_ENTRY_P((cache),(i)))))
-#ifdef CAIRO_DO_SANITY_CHECKING
+#ifdef NDEBUG
+#define _cache_sane_state(c)
+#else
static void
_cache_sane_state (cairo_cache_t *cache)
{
@@ -125,8 +127,6 @@ _cache_sane_state (cairo_cache_t *cache)
/* assert (cache->used_memory <= cache->max_memory); */
assert (cache->live_entries <= cache->arrangement->size);
}
-#else
-#define _cache_sane_state(c)
#endif
static void
@@ -351,8 +351,9 @@ _cairo_cache_init (cairo_cache_t *cache,
#endif
cache->backend = backend;
- cache->entries = calloc (sizeof(cairo_cache_entry_base_t *),
- cache->arrangement->size);
+ cache->entries = calloc (cache->arrangement->size,
+ sizeof(cairo_cache_entry_base_t *));
+
if (cache->entries == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 9745b3150..19dc7b611 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -68,7 +68,7 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
surface->pixman_image = pixman_image;
surface->format = format;
- surface->data = (char *) pixman_image_get_data (pixman_image);
+ surface->data = (unsigned char *) pixman_image_get_data (pixman_image);
surface->owns_data = 0;
surface->width = pixman_image_get_width (pixman_image);
@@ -80,8 +80,8 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
}
cairo_image_surface_t *
-_cairo_image_surface_create_with_masks (char *data,
- cairo_format_masks_t *format,
+_cairo_image_surface_create_with_masks (unsigned char *data,
+ cairo_format_masks_t *format,
int width,
int height,
int stride)
@@ -195,7 +195,7 @@ cairo_image_surface_create (cairo_format_t format,
* be created because of lack of memory
**/
cairo_surface_t *
-cairo_image_surface_create_for_data (char *data,
+cairo_image_surface_create_for_data (unsigned char *data,
cairo_format_t format,
int width,
int height,
@@ -224,6 +224,38 @@ cairo_image_surface_create_for_data (char *data,
return &surface->base;
}
+/**
+ * cairo_image_surface_get_width:
+ * @surface: a #cairo_image_surface_t
+ *
+ * Get the width of the image surface in pixels.
+ *
+ * Return value: the width of the surface in pixels.
+ **/
+int
+cairo_image_surface_get_width (cairo_surface_t *surface)
+{
+ cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
+
+ return image_surface->width;
+}
+
+/**
+ * cairo_image_surface_get_height:
+ * @surface: a #cairo_image_surface_t
+ *
+ * Get the height of the image surface in pixels.
+ *
+ * Return value: the height of the surface in pixels.
+ **/
+int
+cairo_image_surface_get_height (cairo_surface_t *surface)
+{
+ cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
+
+ return image_surface->height;
+}
+
static cairo_surface_t *
_cairo_image_surface_create_similar (void *abstract_src,
cairo_format_t format,
@@ -234,20 +266,22 @@ _cairo_image_surface_create_similar (void *abstract_src,
return cairo_image_surface_create (format, width, height);
}
-static void
-_cairo_image_abstract_surface_destroy (void *abstract_surface)
+static cairo_status_t
+_cairo_image_abstract_surface_finish (void *abstract_surface)
{
cairo_image_surface_t *surface = abstract_surface;
- if (surface->pixman_image)
+ if (surface->pixman_image) {
pixman_image_destroy (surface->pixman_image);
+ surface->pixman_image = NULL;
+ }
if (surface->owns_data) {
free (surface->data);
surface->data = NULL;
}
- free (surface);
+ return CAIRO_STATUS_SUCCESS;
}
void
@@ -256,13 +290,6 @@ _cairo_image_surface_assume_ownership_of_data (cairo_image_surface_t *surface)
surface->owns_data = 1;
}
-static double
-_cairo_image_surface_pixels_per_inch (void *abstract_surface)
-{
- /* XXX: We'll want a way to let the user set this. */
- return 96.0;
-}
-
static cairo_status_t
_cairo_image_surface_acquire_source_image (void *abstract_surface,
cairo_image_surface_t **image_out,
@@ -327,17 +354,17 @@ _cairo_image_surface_clone_similar (void *abstract_surface,
cairo_status_t
_cairo_image_surface_set_matrix (cairo_image_surface_t *surface,
- cairo_matrix_t *matrix)
+ const cairo_matrix_t *matrix)
{
pixman_transform_t pixman_transform;
- pixman_transform.matrix[0][0] = _cairo_fixed_from_double (matrix->m[0][0]);
- pixman_transform.matrix[0][1] = _cairo_fixed_from_double (matrix->m[1][0]);
- pixman_transform.matrix[0][2] = _cairo_fixed_from_double (matrix->m[2][0]);
+ pixman_transform.matrix[0][0] = _cairo_fixed_from_double (matrix->xx);
+ pixman_transform.matrix[0][1] = _cairo_fixed_from_double (matrix->xy);
+ pixman_transform.matrix[0][2] = _cairo_fixed_from_double (matrix->x0);
- pixman_transform.matrix[1][0] = _cairo_fixed_from_double (matrix->m[0][1]);
- pixman_transform.matrix[1][1] = _cairo_fixed_from_double (matrix->m[1][1]);
- pixman_transform.matrix[1][2] = _cairo_fixed_from_double (matrix->m[2][1]);
+ pixman_transform.matrix[1][0] = _cairo_fixed_from_double (matrix->yx);
+ pixman_transform.matrix[1][1] = _cairo_fixed_from_double (matrix->yy);
+ pixman_transform.matrix[1][2] = _cairo_fixed_from_double (matrix->y0);
pixman_transform.matrix[2][0] = 0;
pixman_transform.matrix[2][1] = 0;
@@ -414,32 +441,40 @@ _cairo_image_surface_set_attributes (cairo_image_surface_t *surface,
return status;
}
+/* XXX: I think we should fix pixman to match the names/order of the
+ * cairo operators, but that will likely be better done at the same
+ * time the X server is ported to pixman, (which will change a lot of
+ * things in pixman I think).
+ */
static pixman_operator_t
_pixman_operator (cairo_operator_t operator)
{
switch (operator) {
case CAIRO_OPERATOR_CLEAR:
return PIXMAN_OPERATOR_CLEAR;
- case CAIRO_OPERATOR_SRC:
+
+ case CAIRO_OPERATOR_SOURCE:
return PIXMAN_OPERATOR_SRC;
- case CAIRO_OPERATOR_DST:
- return PIXMAN_OPERATOR_DST;
case CAIRO_OPERATOR_OVER:
return PIXMAN_OPERATOR_OVER;
- case CAIRO_OPERATOR_OVER_REVERSE:
- return PIXMAN_OPERATOR_OVER_REVERSE;
case CAIRO_OPERATOR_IN:
return PIXMAN_OPERATOR_IN;
- case CAIRO_OPERATOR_IN_REVERSE:
- return PIXMAN_OPERATOR_IN_REVERSE;
case CAIRO_OPERATOR_OUT:
return PIXMAN_OPERATOR_OUT;
- case CAIRO_OPERATOR_OUT_REVERSE:
- return PIXMAN_OPERATOR_OUT_REVERSE;
case CAIRO_OPERATOR_ATOP:
return PIXMAN_OPERATOR_ATOP;
- case CAIRO_OPERATOR_ATOP_REVERSE:
+
+ case CAIRO_OPERATOR_DEST:
+ return PIXMAN_OPERATOR_DST;
+ case CAIRO_OPERATOR_DEST_OVER:
+ return PIXMAN_OPERATOR_OVER_REVERSE;
+ case CAIRO_OPERATOR_DEST_IN:
+ return PIXMAN_OPERATOR_IN_REVERSE;
+ case CAIRO_OPERATOR_DEST_OUT:
+ return PIXMAN_OPERATOR_OUT_REVERSE;
+ case CAIRO_OPERATOR_DEST_ATOP:
return PIXMAN_OPERATOR_ATOP_REVERSE;
+
case CAIRO_OPERATOR_XOR:
return PIXMAN_OPERATOR_XOR;
case CAIRO_OPERATOR_ADD:
@@ -587,7 +622,7 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t operator,
* somehow. */
status = _cairo_image_surface_set_attributes (src, &attributes);
if (CAIRO_OK (status))
- pixman_composite_trapezoids (operator,
+ pixman_composite_trapezoids (_pixman_operator (operator),
src->pixman_image,
dst->pixman_image,
render_src_x + attributes.x_offset,
@@ -600,18 +635,6 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t operator,
}
static cairo_int_status_t
-_cairo_image_surface_copy_page (void *abstract_surface)
-{
- return CAIRO_INT_STATUS_UNSUPPORTED;
-}
-
-static cairo_int_status_t
-_cairo_image_surface_show_page (void *abstract_surface)
-{
- return CAIRO_INT_STATUS_UNSUPPORTED;
-}
-
-static cairo_int_status_t
_cairo_image_abstract_surface_set_clip_region (void *abstract_surface,
pixman_region16_t *region)
{
@@ -642,6 +665,27 @@ _cairo_image_surface_set_clip_region (cairo_image_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
+static cairo_int_status_t
+_cairo_image_surface_get_extents (cairo_image_surface_t *surface,
+ cairo_rectangle_t *rectangle)
+{
+ rectangle->x = 0;
+ rectangle->y = 0;
+ rectangle->width = surface->width;
+ rectangle->height = surface->height;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_image_abstract_surface_get_extents (void *abstract_surface,
+ cairo_rectangle_t *rectangle)
+{
+ cairo_image_surface_t *surface = abstract_surface;
+
+ return _cairo_image_surface_get_extents (surface, rectangle);
+}
+
/**
* _cairo_surface_is_image:
* @surface: a #cairo_surface_t
@@ -658,8 +702,7 @@ _cairo_surface_is_image (cairo_surface_t *surface)
static const cairo_surface_backend_t cairo_image_surface_backend = {
_cairo_image_surface_create_similar,
- _cairo_image_abstract_surface_destroy,
- _cairo_image_surface_pixels_per_inch,
+ _cairo_image_abstract_surface_finish,
_cairo_image_surface_acquire_source_image,
_cairo_image_surface_release_source_image,
_cairo_image_surface_acquire_dest_image,
@@ -668,8 +711,9 @@ static const cairo_surface_backend_t cairo_image_surface_backend = {
_cairo_image_surface_composite,
_cairo_image_surface_fill_rectangles,
_cairo_image_surface_composite_trapezoids,
- _cairo_image_surface_copy_page,
- _cairo_image_surface_show_page,
+ NULL, /* copy_page */
+ NULL, /* show_page */
_cairo_image_abstract_surface_set_clip_region,
+ _cairo_image_abstract_surface_get_extents,
NULL /* show_glyphs */
};
diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c
index 88e536e8a..82ec0dbb7 100644
--- a/src/cairo-matrix.c
+++ b/src/cairo-matrix.c
@@ -40,14 +40,6 @@
#include "cairoint.h"
-static cairo_matrix_t const CAIRO_MATRIX_IDENTITY = {
- {
- {1, 0},
- {0, 1},
- {0, 0}
- }
-};
-
static void
_cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar);
@@ -55,228 +47,185 @@ static void
_cairo_matrix_compute_adjoint (cairo_matrix_t *matrix);
/**
- * cairo_matrix_create:
- *
- * Creates a new identity matrix.
- *
- * Return value: a newly created matrix; free with cairo_matrix_destroy(),
- * or %NULL if memory couldn't be allocated.
- **/
-cairo_matrix_t *
-cairo_matrix_create (void)
-{
- cairo_matrix_t *matrix;
-
- matrix = malloc (sizeof (cairo_matrix_t));
- if (matrix == NULL)
- return NULL;
-
- _cairo_matrix_init (matrix);
-
- return matrix;
-}
-
-void
-_cairo_matrix_init (cairo_matrix_t *matrix)
-{
- cairo_matrix_set_identity (matrix);
-}
-
-void
-_cairo_matrix_fini (cairo_matrix_t *matrix)
-{
- /* nothing to do here */
-}
-
-/**
- * cairo_matrix_destroy:
- * @matrix: a #cairo_matrix_t
- *
- * Frees a matrix created with cairo_matrix_create.
- **/
-void
-cairo_matrix_destroy (cairo_matrix_t *matrix)
-{
- _cairo_matrix_fini (matrix);
- free (matrix);
-}
-
-/**
- * cairo_matrix_copy:
- * @matrix: a #cairo_matrix_t
- * @other: another #cairo_
- *
- * Modifies @matrix to be identical to @other.
- *
- * Return value: %CAIRO_STATUS_SUCCESS, always.
- **/
-cairo_status_t
-cairo_matrix_copy (cairo_matrix_t *matrix, const cairo_matrix_t *other)
-{
- *matrix = *other;
-
- return CAIRO_STATUS_SUCCESS;
-}
-slim_hidden_def(cairo_matrix_copy);
-
-/**
- * cairo_matrix_set_identity:
+ * cairo_matrix_init_identity:
* @matrix: a #cairo_matrix_t
*
* Modifies @matrix to be an identity transformation.
- *
- * Return value: %CAIRO_STATUS_SUCCESS, always.
**/
-cairo_status_t
-cairo_matrix_set_identity (cairo_matrix_t *matrix)
+void
+cairo_matrix_init_identity (cairo_matrix_t *matrix)
{
- *matrix = CAIRO_MATRIX_IDENTITY;
-
- return CAIRO_STATUS_SUCCESS;
+ cairo_matrix_init (matrix,
+ 1, 0,
+ 0, 1,
+ 0, 0);
}
-slim_hidden_def(cairo_matrix_set_identity);
+slim_hidden_def(cairo_matrix_init_identity);
/**
- * cairo_matrix_set_affine:
+ * cairo_matrix_init:
* @matrix: a cairo_matrix_t
- * @a: a component of the affine transformation
- * @b: b component of the affine transformation
- * @c: c component of the affine transformation
- * @d: d component of the affine transformation
- * @tx: X translation component of the affine transformation
- * @ty: Y translation component of the affine transformation
+ * @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
*
* Sets @matrix to be the affine transformation given by
- * @a, b, @c, @d, @tx, @ty. The transformation is given
+ * @xx, @yx, @xy, @yy, @x0, @y0. The transformation is given
* by:
* <programlisting>
- * x_new = x * a + y * c + tx;
- * y_new = x * b + y * d + ty;
+ * x_new = xx * x + xy * y + x0;
+ * y_new = yx * x + yy * y + y0;
* </programlisting>
- *
- * Return value: %CAIRO_STATUS_SUCCESS, always.
**/
-cairo_status_t
-cairo_matrix_set_affine (cairo_matrix_t *matrix,
- double a, double b,
- double c, double d,
- double tx, double ty)
+void
+cairo_matrix_init (cairo_matrix_t *matrix,
+ double xx, double yx,
+ double xy, double yy,
+ double x0, double y0)
{
- matrix->m[0][0] = a; matrix->m[0][1] = b;
- matrix->m[1][0] = c; matrix->m[1][1] = d;
- matrix->m[2][0] = tx; matrix->m[2][1] = ty;
-
- return CAIRO_STATUS_SUCCESS;
+ matrix->xx = xx; matrix->yx = yx;
+ matrix->xy = xy; matrix->yy = yy;
+ matrix->x0 = x0; matrix->y0 = y0;
}
-slim_hidden_def(cairo_matrix_set_affine);
+slim_hidden_def(cairo_matrix_init);
/**
- * cairo_matrix_get_affine:
+ * _cairo_matrix_get_affine:
* @matrix: a @cairo_matrix_t
- * @a: location to store a component of affine transformation, or %NULL
- * @b: location to store b component of affine transformation, or %NULL
- * @c: location to store c component of affine transformation, or %NULL
- * @d: location to store d component of affine transformation, or %NULL
- * @tx: location to store X-translation component of affine transformation, or %NULL
- * @ty: location to store Y-translation component of affine transformation, or %NULL
+ * @xx: location to store xx component of matrix
+ * @yx: location to store yx component of matrix
+ * @xy: location to store xy component of matrix
+ * @yy: location to store yy component of matrix
+ * @x0: location to store x0 (X-translation component) of matrix, or %NULL
+ * @y0: location to store y0 (Y-translation component) of matrix, or %NULL
*
* Gets the matrix values for the affine tranformation that @matrix represents.
- * See cairo_matrix_set_affine().
- *
- * Return value: %CAIRO_STATUS_SUCCESS, always.
+ * See cairo_matrix_init().
+ *
+ *
+ * This function is a leftover from the old public API, but is still
+ * mildly useful as an internal means for getting at the matrix
+ * members in a positional way. For example, when reassigning to some
+ * external matrix type, or when renaming members to more meaningful
+ * names (such as a,b,c,d,e,f) for particular manipulations.
**/
-cairo_status_t
-cairo_matrix_get_affine (cairo_matrix_t *matrix,
- double *a, double *b,
- double *c, double *d,
- double *tx, double *ty)
+void
+_cairo_matrix_get_affine (const cairo_matrix_t *matrix,
+ double *xx, double *yx,
+ double *xy, double *yy,
+ double *x0, double *y0)
{
- if (a)
- *a = matrix->m[0][0];
- if (b)
- *b = matrix->m[0][1];
+ *xx = matrix->xx;
+ *yx = matrix->yx;
- if (c)
- *c = matrix->m[1][0];
- if (d)
- *d = matrix->m[1][1];
+ *xy = matrix->xy;
+ *yy = matrix->yy;
- if (tx)
- *tx = matrix->m[2][0];
- if (ty)
- *ty = matrix->m[2][1];
-
- return CAIRO_STATUS_SUCCESS;
+ if (x0)
+ *x0 = matrix->x0;
+ if (y0)
+ *y0 = matrix->y0;
}
-cairo_status_t
-_cairo_matrix_set_translate (cairo_matrix_t *matrix,
+/**
+ * cairo_matrix_init_translate:
+ * @matrix: a cairo_matrix_t
+ * @tx: amount to translate in the X direction
+ * @ty: amount to translate in the Y direction
+ *
+ * Initializes @matrix to a transformation that translates by @tx and
+ * @ty in the X and Y dimensions, respectively.
+ **/
+void
+cairo_matrix_init_translate (cairo_matrix_t *matrix,
double tx, double ty)
{
- return cairo_matrix_set_affine (matrix,
- 1, 0,
- 0, 1,
- tx, ty);
+ cairo_matrix_init (matrix,
+ 1, 0,
+ 0, 1,
+ tx, ty);
}
+slim_hidden_def(cairo_matrix_init_translate);
/**
* cairo_matrix_translate:
* @matrix: a cairo_matrix_t
- * @tx: amount to rotate in the X direction
- * @ty: amount to rotate in the Y direction
+ * @tx: amount to translate in the X direction
+ * @ty: amount to translate in the Y direction
*
* Applies a translation by @tx, @ty to the transformation in
- * @matrix. The new transformation is given by first translating by
- * @tx, @ty then applying the original transformation
- *
- * Return value: %CAIRO_STATUS_SUCCESS, always.
+ * @matrix. The effect of the new transformation is to first translate
+ * the coordinates by @tx and @ty, then apply the original transformation
+ * to the coordinates.
**/
-cairo_status_t
+void
cairo_matrix_translate (cairo_matrix_t *matrix, double tx, double ty)
{
cairo_matrix_t tmp;
- _cairo_matrix_set_translate (&tmp, tx, ty);
+ cairo_matrix_init_translate (&tmp, tx, ty);
- return cairo_matrix_multiply (matrix, &tmp, matrix);
+ cairo_matrix_multiply (matrix, &tmp, matrix);
}
-cairo_status_t
-_cairo_matrix_set_scale (cairo_matrix_t *matrix,
+/**
+ * cairo_matrix_init_scale:
+ * @matrix: a cairo_matrix_t
+ * @sx: scale factor in the X direction
+ * @sy: scale factor in the Y direction
+ *
+ * Initializes @matrix to a transformation that scales by @sx and @sy
+ * in the X and Y dimensions, respectively.
+ **/
+void
+cairo_matrix_init_scale (cairo_matrix_t *matrix,
double sx, double sy)
{
- return cairo_matrix_set_affine (matrix,
- sx, 0,
- 0, sy,
- 0, 0);
+ cairo_matrix_init (matrix,
+ sx, 0,
+ 0, sy,
+ 0, 0);
}
+slim_hidden_def(cairo_matrix_init_scale);
/**
* cairo_matrix_scale:
* @matrix: a #cairo_matrix_t
- * @sx: Scale factor in the X direction
- * @sy: Scale factor in the Y direction
+ * @sx: scale factor in the X direction
+ * @sy: scale factor in the Y direction
*
- * Applies scaling by @tx, @ty to the transformation in
- * @matrix. The new transformation is given by first scaling by @sx
- * and @sy then applying the original transformation
- *
- * Return value: %CAIRO_STATUS_SUCCESS, always.
+ * Applies scaling by @tx, @ty to the transformation in @matrix. The
+ * effect of the new transformation is to first scale the coordinates
+ * by @sx and @sy, then apply the original transformation to the coordinates.
**/
-cairo_status_t
+void
cairo_matrix_scale (cairo_matrix_t *matrix, double sx, double sy)
{
cairo_matrix_t tmp;
- _cairo_matrix_set_scale (&tmp, sx, sy);
+ cairo_matrix_init_scale (&tmp, sx, sy);
- return cairo_matrix_multiply (matrix, &tmp, matrix);
+ cairo_matrix_multiply (matrix, &tmp, matrix);
}
slim_hidden_def(cairo_matrix_scale);
-cairo_status_t
-_cairo_matrix_set_rotate (cairo_matrix_t *matrix,
- double radians)
+/**
+ * cairo_matrix_init_rotate:
+ * @matrix: a cairo_matrix_t
+ * @radians: angle of rotation, in radians. The direction of rotation
+ * is defined such that positive angles rotate in the direction from
+ * the positive X axis toward the positive Y axis. With the default
+ * axis orientation of cairo, positive angles rotate in a clockwise
+ * direction.
+ *
+ * Initialized @matrix to a transformation that rotates by @radians.
+ **/
+void
+cairo_matrix_init_rotate (cairo_matrix_t *matrix,
+ double radians)
{
double s;
double c;
@@ -286,35 +235,35 @@ _cairo_matrix_set_rotate (cairo_matrix_t *matrix,
s = sin (radians);
c = cos (radians);
#endif
- return cairo_matrix_set_affine (matrix,
- c, s,
- -s, c,
- 0, 0);
+ cairo_matrix_init (matrix,
+ c, s,
+ -s, c,
+ 0, 0);
}
+slim_hidden_def(cairo_matrix_init_rotate);
/**
* cairo_matrix_rotate:
* @matrix: a @cairo_matrix_t
- * @radians: angle of rotation, in radians. Angles are defined
- * so that an angle of 90 degrees (%M_PI radians) rotates the
- * positive X axis into the positive Y axis. With the default
- * Cairo choice of axis orientation, positive rotations are
- * clockwise.
+ * @radians: angle of rotation, in radians. The direction of rotation
+ * is defined such that positive angles rotate in the direction from
+ * the positive X axis toward the positive Y axis. With the default
+ * axis orientation of cairo, positive angles rotate in a clockwise
+ * direction.
*
* Applies rotation by @radians to the transformation in
- * @matrix. The new transformation is given by first rotating by
- * @radians then applying the original transformation
- *
- * Return value: %CAIRO_STATUS_SUCCESS, always.
+ * @matrix. The effect of the new transformation is to first rotate the
+ * coordinates by @radians, then apply the original transformation
+ * to the coordinates.
**/
-cairo_status_t
+void
cairo_matrix_rotate (cairo_matrix_t *matrix, double radians)
{
cairo_matrix_t tmp;
- _cairo_matrix_set_rotate (&tmp, radians);
+ cairo_matrix_init_rotate (&tmp, radians);
- return cairo_matrix_multiply (matrix, &tmp, matrix);
+ cairo_matrix_multiply (matrix, &tmp, matrix);
}
/**
@@ -324,46 +273,47 @@ cairo_matrix_rotate (cairo_matrix_t *matrix, double radians)
* @b: a @cairo_matrix_t
*
* Multiplies the affine transformations in @a and @b together
- * and stores the result in @result. The resulting transformation
- * is given by first applying the transformation in @b then
- * applying the transformation in @a.
- *
- * Return value: %CAIRO_STATUS_SUCCESS, always.
+ * and stores the result in @result. The effect of the resulting
+ * transformation is to first apply the transformation in @a to the
+ * coordinates and then apply the transformation in @b to the
+ * coordinates.
+ *
+ * It is allowable for @result to be identical to either @a or @b.
**/
-cairo_status_t
+/*
+ * XXX: The ordering of the arguments to this function corresponds
+ * to [row_vector]*A*B. If we want to use column vectors instead,
+ * then we need to switch the two arguments and fix up all
+ * uses.
+ */
+void
cairo_matrix_multiply (cairo_matrix_t *result, const cairo_matrix_t *a, const cairo_matrix_t *b)
{
cairo_matrix_t r;
- int row, col, n;
- double t;
-
- for (row = 0; row < 3; row++) {
- for (col = 0; col < 2; col++) {
- if (row == 2)
- t = b->m[2][col];
- else
- t = 0;
- for (n = 0; n < 2; n++) {
- t += a->m[row][n] * b->m[n][col];
- }
- r.m[row][col] = t;
- }
- }
- *result = r;
+ r.xx = a->xx * b->xx + a->yx * b->xy;
+ r.yx = a->xx * b->yx + a->yx * b->yy;
- return CAIRO_STATUS_SUCCESS;
+ r.xy = a->xy * b->xx + a->yy * b->xy;
+ r.yy = a->xy * b->yx + a->yy * b->yy;
+
+ r.x0 = a->x0 * b->xx + a->y0 * b->xy + b->x0;
+ r.y0 = a->x0 * b->yx + a->y0 * b->yy + b->y0;
+
+ *result = r;
}
slim_hidden_def(cairo_matrix_multiply);
/**
* cairo_matrix_transform_distance:
* @matrix: a @cairo_matrix_t
- * @dx: a distance in the X direction. An in/out parameter
- * @dy: a distance in the Y direction. An in/out parameter
+ * @dx: X component of a distance vector. An in/out parameter
+ * @dy: Y component of a distance vector. An in/out parameter
*
- * Transforms the vector (@dx,@dy) by @matrix. Translation is
- * ignored. In terms of the components of the affine transformation:
+ * Transforms the distance vector (@dx,@dy) by @matrix. This is
+ * similar to cairo_matrix_transform() except that the translation
+ * components of the transformation are ignored. The calculation of
+ * the returned vector is as follows:
*
* <programlisting>
* dx2 = dx1 * a + dy1 * c;
@@ -374,23 +324,17 @@ slim_hidden_def(cairo_matrix_multiply);
* always transforms to the same vector. If (@x1,@y1) transforms
* to (@x2,@y2) then (@x1+@dx1,@y1+@dy1) will transform to
* (@x1+@dx2,@y1+@dy2) for all values of @x1 and @x2.
- *
- * Return value: %CAIRO_STATUS_SUCCESS, always.
**/
-cairo_status_t
-cairo_matrix_transform_distance (cairo_matrix_t *matrix, double *dx, double *dy)
+void
+cairo_matrix_transform_distance (const cairo_matrix_t *matrix, double *dx, double *dy)
{
double new_x, new_y;
- new_x = (matrix->m[0][0] * *dx
- + matrix->m[1][0] * *dy);
- new_y = (matrix->m[0][1] * *dx
- + matrix->m[1][1] * *dy);
+ new_x = (matrix->xx * *dx + matrix->xy * *dy);
+ new_y = (matrix->yx * *dx + matrix->yy * *dy);
*dx = new_x;
*dy = new_y;
-
- return CAIRO_STATUS_SUCCESS;
}
slim_hidden_def(cairo_matrix_transform_distance);
@@ -401,23 +345,19 @@ slim_hidden_def(cairo_matrix_transform_distance);
* @y: Y position. An in/out parameter
*
* Transforms the point (@x, @y) by @matrix.
- *
- * Return value: %CAIRO_STATUS_SUCCESS, always.
**/
-cairo_status_t
-cairo_matrix_transform_point (cairo_matrix_t *matrix, double *x, double *y)
+void
+cairo_matrix_transform_point (const cairo_matrix_t *matrix, double *x, double *y)
{
cairo_matrix_transform_distance (matrix, x, y);
- *x += matrix->m[2][0];
- *y += matrix->m[2][1];
-
- return CAIRO_STATUS_SUCCESS;
+ *x += matrix->x0;
+ *y += matrix->y0;
}
slim_hidden_def(cairo_matrix_transform_point);
-cairo_status_t
-_cairo_matrix_transform_bounding_box (cairo_matrix_t *matrix,
+void
+_cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
double *x, double *y,
double *width, double *height)
{
@@ -466,18 +406,19 @@ _cairo_matrix_transform_bounding_box (cairo_matrix_t *matrix,
*y = min_y;
*width = max_x - min_x;
*height = max_y - min_y;
-
- return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar)
{
- int row, col;
+ matrix->xx *= scalar;
+ matrix->yx *= scalar;
+
+ matrix->xy *= scalar;
+ matrix->yy *= scalar;
- for (row = 0; row < 3; row++)
- for (col = 0; col < 2; col++)
- matrix->m[row][col] *= scalar;
+ matrix->x0 *= scalar;
+ matrix->y0 *= scalar;
}
/* This function isn't a correct adjoint in that the implicit 1 in the
@@ -490,14 +431,15 @@ _cairo_matrix_compute_adjoint (cairo_matrix_t *matrix)
/* adj (A) = transpose (C:cofactor (A,i,j)) */
double a, b, c, d, tx, ty;
- a = matrix->m[0][0]; b = matrix->m[0][1];
- c = matrix->m[1][0]; d = matrix->m[1][1];
- tx = matrix->m[2][0]; ty = matrix->m[2][1];
+ _cairo_matrix_get_affine (matrix,
+ &a, &b,
+ &c, &d,
+ &tx, &ty);
- cairo_matrix_set_affine (matrix,
- d, -b,
- -c, a,
- c*ty - d*tx, b*tx - a*ty);
+ cairo_matrix_init (matrix,
+ d, -b,
+ -c, a,
+ c*ty - d*tx, b*tx - a*ty);
}
/**
@@ -531,21 +473,21 @@ cairo_matrix_invert (cairo_matrix_t *matrix)
}
slim_hidden_def(cairo_matrix_invert);
-cairo_status_t
-_cairo_matrix_compute_determinant (cairo_matrix_t *matrix, double *det)
+void
+_cairo_matrix_compute_determinant (const cairo_matrix_t *matrix,
+ double *det)
{
double a, b, c, d;
- a = matrix->m[0][0]; b = matrix->m[0][1];
- c = matrix->m[1][0]; d = matrix->m[1][1];
+ a = matrix->xx; b = matrix->yx;
+ c = matrix->xy; d = matrix->yy;
*det = a*d - b*c;
-
- return CAIRO_STATUS_SUCCESS;
}
-cairo_status_t
-_cairo_matrix_compute_eigen_values (cairo_matrix_t *matrix, double *lambda1, double *lambda2)
+void
+_cairo_matrix_compute_eigen_values (const cairo_matrix_t *matrix,
+ double *lambda1, double *lambda2)
{
/* The eigenvalues of an NxN matrix M are found by solving the polynomial:
@@ -566,21 +508,18 @@ _cairo_matrix_compute_eigen_values (cairo_matrix_t *matrix, double *lambda1, dou
double a, b, c, d, rad;
- a = matrix->m[0][0];
- b = matrix->m[0][1];
- c = matrix->m[1][0];
- d = matrix->m[1][1];
+ a = matrix->xx; b = matrix->yx;
+ c = matrix->xy; d = matrix->yy;
rad = sqrt (a*a + 2*a*d + d*d - 4*(a*d - b*c));
*lambda1 = (a + d + rad) / 2.0;
*lambda2 = (a + d - rad) / 2.0;
-
- return CAIRO_STATUS_SUCCESS;
}
/* Compute the amount that each basis vector is scaled by. */
cairo_status_t
-_cairo_matrix_compute_scale_factors (cairo_matrix_t *matrix, double *sx, double *sy, int x_major)
+_cairo_matrix_compute_scale_factors (const cairo_matrix_t *matrix,
+ double *sx, double *sy, int x_major)
{
double det;
@@ -621,13 +560,13 @@ _cairo_matrix_compute_scale_factors (cairo_matrix_t *matrix, double *sx, double
}
cairo_bool_t
-_cairo_matrix_is_integer_translation(cairo_matrix_t *mat,
+_cairo_matrix_is_integer_translation(const cairo_matrix_t *mat,
int *itx, int *ity)
{
double a, b, c, d, tx, ty;
int ttx, tty;
int ok = 0;
- cairo_matrix_get_affine (mat, &a, &b, &c, &d, &tx, &ty);
+ _cairo_matrix_get_affine (mat, &a, &b, &c, &d, &tx, &ty);
ttx = _cairo_fixed_from_double (tx);
tty = _cairo_fixed_from_double (ty);
ok = ((a == 1.0)
diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c
new file mode 100644
index 000000000..14b4486a6
--- /dev/null
+++ b/src/cairo-output-stream.c
@@ -0,0 +1,285 @@
+/* cairo_output_stream.c: Output stream abstraction
+ *
+ * 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 cairo_output_stream.c as distributed with the
+ * cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Author(s):
+ * Kristian Høgsberg <krh@redhat.com>
+ */
+
+#include <stdio.h>
+#include <locale.h>
+#include <ctype.h>
+#include "cairoint.h"
+
+struct _cairo_output_stream {
+ cairo_write_func_t write_data;
+ void *closure;
+ cairo_bool_t owns_closure_is_file;
+ unsigned long position;
+ cairo_status_t status;
+};
+
+cairo_output_stream_t *
+_cairo_output_stream_create (cairo_write_func_t write_data,
+ void *closure)
+{
+ cairo_output_stream_t *stream;
+
+ stream = malloc (sizeof (cairo_output_stream_t));
+ if (stream == NULL)
+ return NULL;
+
+ stream->write_data = write_data;
+ stream->closure = closure;
+ stream->owns_closure_is_file = FALSE;
+ stream->position = 0;
+ stream->status = CAIRO_STATUS_SUCCESS;
+
+ return stream;
+}
+
+void
+_cairo_output_stream_destroy (cairo_output_stream_t *stream)
+{
+ if (stream->owns_closure_is_file) {
+ FILE *file = stream->closure;
+ fflush (file);
+ fclose (file);
+ }
+ free (stream);
+}
+
+cairo_status_t
+_cairo_output_stream_write (cairo_output_stream_t *stream,
+ const void *data, size_t length)
+{
+ if (length == 0)
+ return CAIRO_STATUS_SUCCESS;
+
+ stream->status = stream->write_data (stream->closure, data, length);
+ stream->position += length;
+
+ return stream->status;
+}
+
+/* Format a double in a locale independent way and trim trailing
+ * zeros. Based on code from Alex Larson <alexl@redhat.com>.
+ * http://mail.gnome.org/archives/gtk-devel-list/2001-October/msg00087.html
+ */
+
+static int
+dtostr (char *buffer, size_t size, double d)
+{
+ struct lconv *locale_data;
+ const char *decimal_point;
+ int decimal_point_len;
+ char *p;
+ int decimal_len;
+
+ snprintf (buffer, size, "%f", d);
+
+ locale_data = localeconv ();
+ decimal_point = locale_data->decimal_point;
+ decimal_point_len = strlen (decimal_point);
+
+ assert (decimal_point_len != 0);
+ p = buffer;
+
+ if (*p == '+' || *p == '-')
+ p++;
+
+ while (isdigit (*p))
+ p++;
+
+ if (strncmp (p, decimal_point, decimal_point_len) == 0) {
+ *p = '.';
+ decimal_len = strlen (p + decimal_point_len);
+ memmove (p + 1, p + decimal_point_len, decimal_len);
+ p[1 + decimal_len] = 0;
+
+ /* Remove trailing zeros and decimal point if possible. */
+ for (p = p + decimal_len; *p == '0'; p--)
+ *p = 0;
+
+ if (*p == '.') {
+ *p = 0;
+ p--;
+ }
+ }
+
+ return p + 1 - buffer;
+}
+
+
+enum {
+ LENGTH_MODIFIER_LONG = 0x100
+};
+
+/* Here's a limited reimplementation of printf. The reason for doing
+ * this is primarily to special case handling of doubles. We want
+ * locale independent formatting of doubles and we want to trim
+ * trailing zeros. This is handled by dtostr() above, and the code
+ * below handles everything else by calling snprintf() to do the
+ * formatting. This functionality is only for internal use and we
+ * only implement the formats we actually use.
+ */
+
+cairo_status_t
+_cairo_output_stream_vprintf (cairo_output_stream_t *stream,
+ const char *fmt, va_list ap)
+{
+ char buffer[512];
+ char *p;
+ const char *f;
+ int length_modifier;
+
+ f = fmt;
+ p = buffer;
+ while (*f != '\0') {
+ if (p == buffer + sizeof (buffer)) {
+ _cairo_output_stream_write (stream, buffer, sizeof (buffer));
+ p = buffer;
+ }
+
+ if (*f != '%') {
+ *p++ = *f++;
+ continue;
+ }
+
+ f++;
+
+ _cairo_output_stream_write (stream, buffer, p - buffer);
+ p = buffer;
+
+ length_modifier = 0;
+ if (*f == 'l') {
+ length_modifier = LENGTH_MODIFIER_LONG;
+ f++;
+ }
+
+ switch (*f | length_modifier) {
+ case '%':
+ p[0] = *f;
+ p[1] = 0;
+ break;
+ case 'd':
+ snprintf (buffer, sizeof buffer, "%d", va_arg (ap, int));
+ break;
+ case 'd' | LENGTH_MODIFIER_LONG:
+ snprintf (buffer, sizeof buffer, "%ld", va_arg (ap, long int));
+ break;
+ case 'u':
+ snprintf (buffer, sizeof buffer, "%u", va_arg (ap, unsigned int));
+ break;
+ case 'u' | LENGTH_MODIFIER_LONG:
+ snprintf (buffer, sizeof buffer, "%lu", va_arg (ap, long unsigned int));
+ break;
+ case 'o':
+ snprintf (buffer, sizeof buffer, "%o", va_arg (ap, int));
+ break;
+ case 's':
+ snprintf (buffer, sizeof buffer, "%s", va_arg (ap, const char *));
+ break;
+ case 'f':
+ dtostr (buffer, sizeof buffer, va_arg (ap, double));
+ break;
+ default:
+ ASSERT_NOT_REACHED;
+ }
+ p = buffer + strlen (buffer);
+ f++;
+ }
+
+ _cairo_output_stream_write (stream, buffer, p - buffer);
+
+ return stream->status;
+}
+
+cairo_status_t
+_cairo_output_stream_printf (cairo_output_stream_t *stream,
+ const char *fmt, ...)
+{
+ va_list ap;
+ cairo_status_t status;
+
+ va_start (ap, fmt);
+
+ status = _cairo_output_stream_vprintf (stream, fmt, ap);
+
+ va_end (ap);
+
+ return status;
+}
+
+long
+_cairo_output_stream_get_position (cairo_output_stream_t *stream)
+{
+ return stream->position;
+}
+
+cairo_status_t
+_cairo_output_stream_get_status (cairo_output_stream_t *stream)
+{
+ return stream->status;
+}
+
+
+/* Maybe this should be a configure time option, so embedded targets
+ * don't have to pull in stdio. */
+
+static cairo_status_t
+stdio_write (void *closure, const unsigned char *data, unsigned int length)
+{
+ FILE *fp = closure;
+
+ if (fwrite (data, 1, length, fp) == length)
+ return CAIRO_STATUS_SUCCESS;
+
+ return CAIRO_STATUS_WRITE_ERROR;
+}
+
+cairo_output_stream_t *
+_cairo_output_stream_create_for_file (const char *filename)
+{
+ FILE *fp;
+ cairo_output_stream_t *stream;
+
+ fp = fopen (filename, "wb");
+ if (fp == NULL)
+ return NULL;
+
+ stream = _cairo_output_stream_create (stdio_write, fp);
+ if (stream == NULL)
+ fclose (fp);
+ stream->owns_closure_is_file = TRUE;
+
+ return stream;
+}
diff --git a/src/cairo-path-bounds.c b/src/cairo-path-bounds.c
index 7c5772a82..670036cfd 100644
--- a/src/cairo-path-bounds.c
+++ b/src/cairo-path-bounds.c
@@ -151,7 +151,9 @@ _cairo_path_bounder_close_path (void *closure)
/* XXX: Perhaps this should compute a PixRegion rather than 4 doubles */
cairo_status_t
-_cairo_path_bounds (cairo_path_t *path, double *x1, double *y1, double *x2, double *y2)
+_cairo_path_fixed_bounds (cairo_path_fixed_t *path,
+ double *x1, double *y1,
+ double *x2, double *y2)
{
cairo_status_t status;
@@ -159,12 +161,12 @@ _cairo_path_bounds (cairo_path_t *path, double *x1, double *y1, double *x2, doub
_cairo_path_bounder_init (&bounder);
- status = _cairo_path_interpret (path, CAIRO_DIRECTION_FORWARD,
- _cairo_path_bounder_move_to,
- _cairo_path_bounder_line_to,
- _cairo_path_bounder_curve_to,
- _cairo_path_bounder_close_path,
- &bounder);
+ status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD,
+ _cairo_path_bounder_move_to,
+ _cairo_path_bounder_line_to,
+ _cairo_path_bounder_curve_to,
+ _cairo_path_bounder_close_path,
+ &bounder);
if (status) {
*x1 = *y1 = *x2 = *y2 = 0.0;
_cairo_path_bounder_fini (&bounder);
diff --git a/src/cairo-path-data-private.h b/src/cairo-path-data-private.h
new file mode 100644
index 000000000..e47eaaef9
--- /dev/null
+++ b/src/cairo-path-data-private.h
@@ -0,0 +1,55 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ * Carl D. Worth <cworth@redhat.com>
+ */
+
+#ifndef CAIRO_PATH_DATA_PRIVATE_H
+#define CAIRO_PATH_DATA_PRIVATE_H
+
+#include "cairoint.h"
+
+extern cairo_path_t _cairo_path_nil;
+
+cairo_path_t *
+_cairo_path_data_create (cairo_path_fixed_t *path,
+ cairo_gstate_t *gstate);
+
+cairo_path_t *
+_cairo_path_data_create_flat (cairo_path_fixed_t *path,
+ cairo_gstate_t *gstate);
+
+cairo_status_t
+_cairo_path_data_append_to_context (cairo_path_t *path,
+ cairo_t *cr);
+
+#endif /* CAIRO_PATH_DATA_PRIVATE_H */
diff --git a/src/cairo-path-data.c b/src/cairo-path-data.c
new file mode 100644
index 000000000..95fc3bb26
--- /dev/null
+++ b/src/cairo-path-data.c
@@ -0,0 +1,422 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ * Carl D. Worth <cworth@redhat.com>
+ */
+
+#include "cairo-path-data-private.h"
+#include "cairo-path-fixed-private.h"
+#include "cairo-gstate-private.h"
+
+cairo_path_t
+_cairo_path_nil = { NULL, 0 };
+
+/* Closure for path interpretation. */
+typedef struct cairo_path_data_count {
+ int count;
+ double tolerance;
+ cairo_point_t current_point;
+} cpdc_t;
+
+static cairo_status_t
+_cpdc_move_to (void *closure, cairo_point_t *point)
+{
+ cpdc_t *cpdc = closure;
+
+ cpdc->count += 2;
+
+ cpdc->current_point = *point;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cpdc_line_to (void *closure, cairo_point_t *point)
+{
+ cpdc_t *cpdc = closure;
+
+ cpdc->count += 2;
+
+ cpdc->current_point = *point;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cpdc_curve_to (void *closure,
+ cairo_point_t *p1,
+ cairo_point_t *p2,
+ cairo_point_t *p3)
+{
+ cpdc_t *cpdc = closure;
+
+ cpdc->count += 4;
+
+ cpdc->current_point = *p3;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cpdc_curve_to_flatten (void *closure,
+ cairo_point_t *p1,
+ cairo_point_t *p2,
+ cairo_point_t *p3)
+{
+ cpdc_t *cpdc = closure;
+ cairo_status_t status;
+ cairo_spline_t spline;
+ int i;
+
+ cairo_point_t *p0 = &cpdc->current_point;
+
+ status = _cairo_spline_init (&spline, p0, p1, p2, p3);
+ if (status == CAIRO_INT_STATUS_DEGENERATE)
+ return CAIRO_STATUS_SUCCESS;
+
+ status = _cairo_spline_decompose (&spline, cpdc->tolerance);
+ if (status)
+ return status;
+
+ for (i=1; i < spline.num_points; i++)
+ _cpdc_line_to (cpdc, &spline.points[i]);
+
+ cpdc->current_point = *p3;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cpdc_close_path (void *closure)
+{
+ cpdc_t *cpdc = closure;
+
+ cpdc->count += 1;
+
+ cpdc->current_point.x = 0;
+ cpdc->current_point.y = 0;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static int
+_cairo_path_data_count (cairo_path_t *path,
+ cairo_path_fixed_t *path_fixed,
+ double tolerance,
+ cairo_bool_t flatten)
+{
+ cpdc_t cpdc;
+
+ cpdc.count = 0;
+ cpdc.tolerance = tolerance;
+ cpdc.current_point.x = 0;
+ cpdc.current_point.y = 0;
+
+ _cairo_path_fixed_interpret (path_fixed,
+ CAIRO_DIRECTION_FORWARD,
+ _cpdc_move_to,
+ _cpdc_line_to,
+ flatten ?
+ _cpdc_curve_to_flatten :
+ _cpdc_curve_to,
+ _cpdc_close_path,
+ &cpdc);
+
+ return cpdc.count;
+}
+
+/* Closure for path interpretation. */
+typedef struct cairo_path_data_populate {
+ cairo_path_data_t *data;
+ cairo_gstate_t *gstate;
+ cairo_point_t current_point;
+} cpdp_t;
+
+static cairo_status_t
+_cpdp_move_to (void *closure, cairo_point_t *point)
+{
+ cpdp_t *cpdp = closure;
+ cairo_path_data_t *data = cpdp->data;
+ double x, y;
+
+ x = _cairo_fixed_to_double (point->x);
+ y = _cairo_fixed_to_double (point->y);
+
+ _cairo_gstate_backend_to_user (cpdp->gstate, &x, &y);
+
+ data->header.type = CAIRO_PATH_MOVE_TO;
+ data->header.length = 2;
+
+ /* We index from 1 to leave room for data->header */
+ data[1].point.x = x;
+ data[1].point.y = y;
+
+ cpdp->data += data->header.length;
+
+ cpdp->current_point = *point;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cpdp_line_to (void *closure, cairo_point_t *point)
+{
+ cpdp_t *cpdp = closure;
+ cairo_path_data_t *data = cpdp->data;
+ double x, y;
+
+ x = _cairo_fixed_to_double (point->x);
+ y = _cairo_fixed_to_double (point->y);
+
+ _cairo_gstate_backend_to_user (cpdp->gstate, &x, &y);
+
+ data->header.type = CAIRO_PATH_LINE_TO;
+ data->header.length = 2;
+
+ /* We index from 1 to leave room for data->header */
+ data[1].point.x = x;
+ data[1].point.y = y;
+
+ cpdp->data += data->header.length;
+
+ cpdp->current_point = *point;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cpdp_curve_to (void *closure,
+ cairo_point_t *p1,
+ cairo_point_t *p2,
+ cairo_point_t *p3)
+{
+ cpdp_t *cpdp = closure;
+ cairo_path_data_t *data = cpdp->data;
+ double x1, y1;
+ double x2, y2;
+ double x3, y3;
+
+ x1 = _cairo_fixed_to_double (p1->x);
+ y1 = _cairo_fixed_to_double (p1->y);
+ _cairo_gstate_backend_to_user (cpdp->gstate, &x1, &y1);
+
+ x2 = _cairo_fixed_to_double (p2->x);
+ y2 = _cairo_fixed_to_double (p2->y);
+ _cairo_gstate_backend_to_user (cpdp->gstate, &x2, &y2);
+
+ x3 = _cairo_fixed_to_double (p3->x);
+ y3 = _cairo_fixed_to_double (p3->y);
+ _cairo_gstate_backend_to_user (cpdp->gstate, &x3, &y3);
+
+ data->header.type = CAIRO_PATH_CURVE_TO;
+ data->header.length = 4;
+
+ /* We index from 1 to leave room for data->header */
+ data[1].point.x = x1;
+ data[1].point.y = y1;
+
+ data[2].point.x = x2;
+ data[2].point.y = y2;
+
+ data[3].point.x = x3;
+ data[3].point.y = y3;
+
+ cpdp->data += data->header.length;
+
+ cpdp->current_point = *p3;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cpdp_curve_to_flatten (void *closure,
+ cairo_point_t *p1,
+ cairo_point_t *p2,
+ cairo_point_t *p3)
+{
+ cpdp_t *cpdp = closure;
+ cairo_status_t status;
+ cairo_spline_t spline;
+ int i;
+
+ cairo_point_t *p0 = &cpdp->current_point;
+
+ status = _cairo_spline_init (&spline, p0, p1, p2, p3);
+ if (status == CAIRO_INT_STATUS_DEGENERATE)
+ return CAIRO_STATUS_SUCCESS;
+
+ status = _cairo_spline_decompose (&spline, cpdp->gstate->tolerance);
+ if (status)
+ return status;
+
+ for (i=1; i < spline.num_points; i++)
+ _cpdp_line_to (cpdp, &spline.points[i]);
+
+ cpdp->current_point = *p3;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cpdp_close_path (void *closure)
+{
+ cpdp_t *cpdp = closure;
+ cairo_path_data_t *data = cpdp->data;
+
+ data->header.type = CAIRO_PATH_CLOSE_PATH;
+ data->header.length = 1;
+
+ cpdp->data += data->header.length;
+
+ cpdp->current_point.x = 0;
+ cpdp->current_point.y = 0;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_path_data_populate (cairo_path_t *path,
+ cairo_path_fixed_t *path_fixed,
+ cairo_gstate_t *gstate,
+ cairo_bool_t flatten)
+{
+ cpdp_t cpdp;
+
+ cpdp.data = path->data;
+ cpdp.gstate = gstate;
+ cpdp.current_point.x = 0;
+ cpdp.current_point.y = 0;
+
+ _cairo_path_fixed_interpret (path_fixed,
+ CAIRO_DIRECTION_FORWARD,
+ _cpdp_move_to,
+ _cpdp_line_to,
+ flatten ?
+ _cpdp_curve_to_flatten :
+ _cpdp_curve_to,
+ _cpdp_close_path,
+ &cpdp);
+
+ /* Sanity check the count */
+ assert (cpdp.data - path->data == path->num_data);
+}
+
+static cairo_path_t *
+_cairo_path_data_create_real (cairo_path_fixed_t *path_fixed,
+ cairo_gstate_t *gstate,
+ cairo_bool_t flatten)
+{
+ cairo_path_t *path;
+
+ path = malloc (sizeof (cairo_path_t));
+ if (path == NULL)
+ return &_cairo_path_nil;
+
+ path->num_data = _cairo_path_data_count (path, path_fixed,
+ gstate->tolerance, flatten);
+
+ path->data = malloc (path->num_data * sizeof (cairo_path_data_t));
+ if (path->data == NULL) {
+ free (path);
+ return &_cairo_path_nil;
+ }
+
+ _cairo_path_data_populate (path, path_fixed,
+ gstate, flatten);
+
+ return path;
+}
+
+void
+cairo_path_destroy (cairo_path_t *path)
+{
+ free (path->data);
+ path->num_data = 0;
+ free (path);
+}
+
+cairo_path_t *
+_cairo_path_data_create (cairo_path_fixed_t *path,
+ cairo_gstate_t *gstate)
+{
+ return _cairo_path_data_create_real (path, gstate, FALSE);
+}
+
+cairo_path_t *
+_cairo_path_data_create_flat (cairo_path_fixed_t *path,
+ cairo_gstate_t *gstate)
+{
+ return _cairo_path_data_create_real (path, gstate, TRUE);
+}
+
+cairo_status_t
+_cairo_path_data_append_to_context (cairo_path_t *path,
+ cairo_t *cr)
+{
+ int i;
+ cairo_path_data_t *p;
+
+ for (i=0; i < path->num_data; i += path->data[i].header.length) {
+ p = &path->data[i];
+ switch (p->header.type) {
+ case CAIRO_PATH_MOVE_TO:
+ cairo_move_to (cr,
+ p[1].point.x, p[1].point.y);
+ if (p->header.length != 2)
+ return CAIRO_STATUS_INVALID_PATH_DATA;
+ break;
+ case CAIRO_PATH_LINE_TO:
+ cairo_line_to (cr,
+ p[1].point.x, p[1].point.y);
+ if (p->header.length != 2)
+ return CAIRO_STATUS_INVALID_PATH_DATA;
+ break;
+ case CAIRO_PATH_CURVE_TO:
+ cairo_curve_to (cr,
+ p[1].point.x, p[1].point.y,
+ p[2].point.x, p[2].point.y,
+ p[3].point.x, p[3].point.y);
+ if (p->header.length != 4)
+ return CAIRO_STATUS_INVALID_PATH_DATA;
+ break;
+ case CAIRO_PATH_CLOSE_PATH:
+ cairo_close_path (cr);
+ if (p->header.length != 1)
+ return CAIRO_STATUS_INVALID_PATH_DATA;
+ break;
+ default:
+ return CAIRO_STATUS_INVALID_PATH_DATA;
+ }
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
diff --git a/src/cairo-path-fill.c b/src/cairo-path-fill.c
index dc79b6b96..c0015fc96 100644
--- a/src/cairo-path-fill.c
+++ b/src/cairo-path-fill.c
@@ -36,6 +36,8 @@
#include "cairoint.h"
+#include "cairo-gstate-private.h"
+
typedef struct cairo_filler {
cairo_gstate_t *gstate;
cairo_traps_t *traps;
@@ -171,20 +173,22 @@ _cairo_filler_close_path (void *closure)
}
cairo_status_t
-_cairo_path_fill_to_traps (cairo_path_t *path, cairo_gstate_t *gstate, cairo_traps_t *traps)
+_cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,
+ cairo_gstate_t *gstate,
+ cairo_traps_t *traps)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_filler_t filler;
_cairo_filler_init (&filler, gstate, traps);
- status = _cairo_path_interpret (path,
- CAIRO_DIRECTION_FORWARD,
- _cairo_filler_move_to,
- _cairo_filler_line_to,
- _cairo_filler_curve_to,
- _cairo_filler_close_path,
- &filler);
+ status = _cairo_path_fixed_interpret (path,
+ CAIRO_DIRECTION_FORWARD,
+ _cairo_filler_move_to,
+ _cairo_filler_line_to,
+ _cairo_filler_curve_to,
+ _cairo_filler_close_path,
+ &filler);
if (status)
goto BAIL;
diff --git a/src/cairo-path-fixed-private.h b/src/cairo-path-fixed-private.h
new file mode 100644
index 000000000..e8e0df194
--- /dev/null
+++ b/src/cairo-path-fixed-private.h
@@ -0,0 +1,74 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ * Carl D. Worth <cworth@redhat.com>
+ */
+
+#ifndef CAIRO_PATH_FIXED_PRIVATE_H
+#define CAIRO_PATH_FIXED_PRIVATE_H
+
+typedef enum cairo_path_op {
+ CAIRO_PATH_OP_MOVE_TO = 0,
+ CAIRO_PATH_OP_LINE_TO = 1,
+ CAIRO_PATH_OP_CURVE_TO = 2,
+ CAIRO_PATH_OP_CLOSE_PATH = 3
+} __attribute__ ((packed)) cairo_path_op_t; /* Don't want 32 bits if we can avoid it. */
+
+#define CAIRO_PATH_BUF_SIZE 64
+
+typedef struct _cairo_path_op_buf {
+ int num_ops;
+ cairo_path_op_t op[CAIRO_PATH_BUF_SIZE];
+
+ struct _cairo_path_op_buf *next, *prev;
+} cairo_path_op_buf_t;
+
+typedef struct _cairo_path_arg_buf {
+ int num_points;
+ cairo_point_t points[CAIRO_PATH_BUF_SIZE];
+
+ struct _cairo_path_arg_buf *next, *prev;
+} cairo_path_arg_buf_t;
+
+struct _cairo_path_fixed {
+ cairo_path_op_buf_t *op_buf_head;
+ cairo_path_op_buf_t *op_buf_tail;
+
+ cairo_path_arg_buf_t *arg_buf_head;
+ cairo_path_arg_buf_t *arg_buf_tail;
+
+ cairo_point_t last_move_point;
+ cairo_point_t current_point;
+ int has_current_point;
+};
+
+#endif /* CAIRO_PATH_FIXED_PRIVATE_H */
diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index 08b380902..b81d862b9 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -36,6 +36,8 @@
#include "cairoint.h"
+#include "cairo-gstate-private.h"
+
typedef struct cairo_stroker {
cairo_gstate_t *gstate;
cairo_traps_t *traps;
@@ -794,7 +796,9 @@ _cairo_stroker_close_path (void *closure)
}
cairo_status_t
-_cairo_path_stroke_to_traps (cairo_path_t *path, cairo_gstate_t *gstate, cairo_traps_t *traps)
+_cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
+ cairo_gstate_t *gstate,
+ cairo_traps_t *traps)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_stroker_t stroker;
@@ -802,21 +806,21 @@ _cairo_path_stroke_to_traps (cairo_path_t *path, cairo_gstate_t *gstate, cairo_t
_cairo_stroker_init (&stroker, gstate, traps);
if (gstate->dash)
- status = _cairo_path_interpret (path,
- CAIRO_DIRECTION_FORWARD,
- _cairo_stroker_move_to,
- _cairo_stroker_line_to_dashed,
- _cairo_stroker_curve_to,
- _cairo_stroker_close_path,
- &stroker);
+ status = _cairo_path_fixed_interpret (path,
+ CAIRO_DIRECTION_FORWARD,
+ _cairo_stroker_move_to,
+ _cairo_stroker_line_to_dashed,
+ _cairo_stroker_curve_to,
+ _cairo_stroker_close_path,
+ &stroker);
else
- status = _cairo_path_interpret (path,
- CAIRO_DIRECTION_FORWARD,
- _cairo_stroker_move_to,
- _cairo_stroker_line_to,
- _cairo_stroker_curve_to,
- _cairo_stroker_close_path,
- &stroker);
+ status = _cairo_path_fixed_interpret (path,
+ CAIRO_DIRECTION_FORWARD,
+ _cairo_stroker_move_to,
+ _cairo_stroker_line_to,
+ _cairo_stroker_curve_to,
+ _cairo_stroker_close_path,
+ &stroker);
if (status)
goto BAIL;
diff --git a/src/cairo-path.c b/src/cairo-path.c
index 8314f601c..0940c4d1e 100644
--- a/src/cairo-path.c
+++ b/src/cairo-path.c
@@ -1,7 +1,8 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
- *
+ * Copyright © 2005 Red Hat, Inc.
+ *
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
@@ -37,48 +38,52 @@
#include <stdlib.h>
#include "cairoint.h"
+#include "cairo-path-fixed-private.h"
+
/* private functions */
static cairo_status_t
-_cairo_path_add (cairo_path_t *path, cairo_path_op_t op, cairo_point_t *points, int num_pts);
+_cairo_path_fixed_add (cairo_path_fixed_t *path,
+ cairo_path_op_t op,
+ cairo_point_t *points,
+ int num_points);
static void
-_cairo_path_add_op_buf (cairo_path_t *path, cairo_path_op_buf_t *op);
-
-static cairo_status_t
-_cairo_path_new_op_buf (cairo_path_t *path);
+_cairo_path_fixed_add_op_buf (cairo_path_fixed_t *path,
+ cairo_path_op_buf_t *op_buf);
static void
-_cairo_path_add_arg_buf (cairo_path_t *path, cairo_path_arg_buf_t *arg);
-
-static cairo_status_t
-_cairo_path_new_arg_buf (cairo_path_t *path);
+_cairo_path_fixed_add_arg_buf (cairo_path_fixed_t *path,
+ cairo_path_arg_buf_t *arg_buf);
static cairo_path_op_buf_t *
_cairo_path_op_buf_create (void);
static void
-_cairo_path_op_buf_destroy (cairo_path_op_buf_t *buf);
+_cairo_path_op_buf_destroy (cairo_path_op_buf_t *op_buf);
static void
-_cairo_path_op_buf_add (cairo_path_op_buf_t *op_buf, cairo_path_op_t op);
+_cairo_path_op_buf_add_op (cairo_path_op_buf_t *op_buf,
+ cairo_path_op_t op);
static cairo_path_arg_buf_t *
_cairo_path_arg_buf_create (void);
static void
-_cairo_path_arg_buf_destroy (cairo_path_arg_buf_t *buf);
+_cairo_path_arg_buf_destroy (cairo_path_arg_buf_t *arg_buf);
static void
-_cairo_path_arg_buf_add (cairo_path_arg_buf_t *arg, cairo_point_t *points, int num_points);
+_cairo_path_arg_buf_add_points (cairo_path_arg_buf_t *arg_buf,
+ cairo_point_t *points,
+ int num_points);
void
-_cairo_path_init (cairo_path_t *path)
+_cairo_path_fixed_init (cairo_path_fixed_t *path)
{
- path->op_head = NULL;
- path->op_tail = NULL;
+ path->op_buf_head = NULL;
+ path->op_buf_tail = NULL;
- path->arg_head = NULL;
- path->arg_tail = NULL;
+ path->arg_buf_head = NULL;
+ path->arg_buf_tail = NULL;
path->current_point.x = 0;
path->current_point.y = 0;
@@ -87,72 +92,85 @@ _cairo_path_init (cairo_path_t *path)
}
cairo_status_t
-_cairo_path_init_copy (cairo_path_t *path, cairo_path_t *other)
+_cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
+ cairo_path_fixed_t *other)
{
- cairo_path_op_buf_t *op, *other_op;
- cairo_path_arg_buf_t *arg, *other_arg;
+ cairo_path_op_buf_t *op_buf, *other_op_buf;
+ cairo_path_arg_buf_t *arg_buf, *other_arg_buf;
- _cairo_path_init (path);
+ _cairo_path_fixed_init (path);
path->current_point = other->current_point;
path->has_current_point = other->has_current_point;
path->last_move_point = other->last_move_point;
- for (other_op = other->op_head; other_op; other_op = other_op->next) {
- op = _cairo_path_op_buf_create ();
- if (op == NULL) {
- _cairo_path_fini(path);
+ for (other_op_buf = other->op_buf_head;
+ other_op_buf;
+ other_op_buf = other_op_buf->next)
+ {
+ op_buf = _cairo_path_op_buf_create ();
+ if (op_buf == NULL) {
+ _cairo_path_fixed_fini (path);
return CAIRO_STATUS_NO_MEMORY;
}
- *op = *other_op;
- _cairo_path_add_op_buf (path, op);
+ memcpy (op_buf, other_op_buf, sizeof (cairo_path_op_buf_t));
+ _cairo_path_fixed_add_op_buf (path, op_buf);
}
- for (other_arg = other->arg_head; other_arg; other_arg = other_arg->next) {
- arg = _cairo_path_arg_buf_create ();
- if (arg == NULL) {
- _cairo_path_fini(path);
+ for (other_arg_buf = other->arg_buf_head;
+ other_arg_buf;
+ other_arg_buf = other_arg_buf->next)
+ {
+ arg_buf = _cairo_path_arg_buf_create ();
+ if (arg_buf == NULL) {
+ _cairo_path_fixed_fini (path);
return CAIRO_STATUS_NO_MEMORY;
}
- *arg = *other_arg;
- _cairo_path_add_arg_buf (path, arg);
+ memcpy (arg_buf, other_arg_buf, sizeof (cairo_path_arg_buf_t));
+ _cairo_path_fixed_add_arg_buf (path, arg_buf);
}
return CAIRO_STATUS_SUCCESS;
}
void
-_cairo_path_fini (cairo_path_t *path)
+_cairo_path_fixed_fini (cairo_path_fixed_t *path)
{
- cairo_path_op_buf_t *op;
- cairo_path_arg_buf_t *arg;
+ cairo_path_op_buf_t *op_buf;
+ cairo_path_arg_buf_t *arg_buf;
- while (path->op_head) {
- op = path->op_head;
- path->op_head = op->next;
- _cairo_path_op_buf_destroy (op);
+ while (path->op_buf_head) {
+ op_buf = path->op_buf_head;
+ path->op_buf_head = op_buf->next;
+ _cairo_path_op_buf_destroy (op_buf);
}
- path->op_tail = NULL;
+ path->op_buf_tail = NULL;
- while (path->arg_head) {
- arg = path->arg_head;
- path->arg_head = arg->next;
- _cairo_path_arg_buf_destroy (arg);
+ while (path->arg_buf_head) {
+ arg_buf = path->arg_buf_head;
+ path->arg_buf_head = arg_buf->next;
+ _cairo_path_arg_buf_destroy (arg_buf);
}
- path->arg_tail = NULL;
+ path->arg_buf_tail = NULL;
path->has_current_point = 0;
}
cairo_status_t
-_cairo_path_move_to (cairo_path_t *path, cairo_point_t *point)
+_cairo_path_fixed_move_to (cairo_path_fixed_t *path,
+ cairo_fixed_t x,
+ cairo_fixed_t y)
{
cairo_status_t status;
+ cairo_point_t point;
+
+ point.x = x;
+ point.y = y;
- status = _cairo_path_add (path, CAIRO_PATH_OP_MOVE_TO, point, 1);
+ status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1);
if (status)
return status;
- path->current_point = *point;
+ path->current_point = point;
path->has_current_point = 1;
path->last_move_point = path->current_point;
@@ -160,91 +178,115 @@ _cairo_path_move_to (cairo_path_t *path, cairo_point_t *point)
}
cairo_status_t
-_cairo_path_rel_move_to (cairo_path_t *path, cairo_distance_t *distance)
+_cairo_path_fixed_rel_move_to (cairo_path_fixed_t *path,
+ cairo_fixed_t dx,
+ cairo_fixed_t dy)
{
- cairo_point_t point;
+ cairo_fixed_t x, y;
- point.x = path->current_point.x + distance->dx;
- point.y = path->current_point.y + distance->dy;
+ if (!path->has_current_point)
+ return CAIRO_STATUS_NO_CURRENT_POINT;
+
+ x = path->current_point.x + dx;
+ y = path->current_point.y + dy;
- return _cairo_path_move_to (path, &point);
+ return _cairo_path_fixed_move_to (path, x, y);
}
cairo_status_t
-_cairo_path_line_to (cairo_path_t *path, cairo_point_t *point)
+_cairo_path_fixed_line_to (cairo_path_fixed_t *path,
+ cairo_fixed_t x,
+ cairo_fixed_t y)
{
cairo_status_t status;
+ cairo_point_t point;
- status = _cairo_path_add (path, CAIRO_PATH_OP_LINE_TO, point, 1);
+ point.x = x;
+ point.y = y;
+
+ status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1);
if (status)
return status;
- path->current_point = *point;
+ path->current_point = point;
path->has_current_point = 1;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
-_cairo_path_rel_line_to (cairo_path_t *path, cairo_distance_t *distance)
+_cairo_path_fixed_rel_line_to (cairo_path_fixed_t *path,
+ cairo_fixed_t dx,
+ cairo_fixed_t dy)
{
- cairo_point_t point;
+ cairo_fixed_t x, y;
+
+ if (!path->has_current_point)
+ return CAIRO_STATUS_NO_CURRENT_POINT;
- point.x = path->current_point.x + distance->dx;
- point.y = path->current_point.y + distance->dy;
+ x = path->current_point.x + dx;
+ y = path->current_point.y + dy;
- return _cairo_path_line_to (path, &point);
+ return _cairo_path_fixed_line_to (path, x, y);
}
cairo_status_t
-_cairo_path_curve_to (cairo_path_t *path,
- cairo_point_t *p0,
- cairo_point_t *p1,
- cairo_point_t *p2)
+_cairo_path_fixed_curve_to (cairo_path_fixed_t *path,
+ cairo_fixed_t x0, cairo_fixed_t y0,
+ cairo_fixed_t x1, cairo_fixed_t y1,
+ cairo_fixed_t x2, cairo_fixed_t y2)
{
cairo_status_t status;
cairo_point_t point[3];
- point[0] = *p0;
- point[1] = *p1;
- point[2] = *p2;
+ point[0].x = x0; point[0].y = y0;
+ point[1].x = x1; point[1].y = y1;
+ point[2].x = x2; point[2].y = y2;
- status = _cairo_path_add (path, CAIRO_PATH_OP_CURVE_TO, point, 3);
+ status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CURVE_TO, point, 3);
if (status)
return status;
- path->current_point = *p2;
+ path->current_point = point[2];
path->has_current_point = 1;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
-_cairo_path_rel_curve_to (cairo_path_t *path,
- cairo_distance_t *d0,
- cairo_distance_t *d1,
- cairo_distance_t *d2)
+_cairo_path_fixed_rel_curve_to (cairo_path_fixed_t *path,
+ cairo_fixed_t dx0, cairo_fixed_t dy0,
+ cairo_fixed_t dx1, cairo_fixed_t dy1,
+ cairo_fixed_t dx2, cairo_fixed_t dy2)
{
- cairo_point_t p0, p1, p2;
+ cairo_fixed_t x0, y0;
+ cairo_fixed_t x1, y1;
+ cairo_fixed_t x2, y2;
+
+ if (!path->has_current_point)
+ return CAIRO_STATUS_NO_CURRENT_POINT;
- p0.x = path->current_point.x + d0->dx;
- p0.y = path->current_point.y + d0->dy;
+ x0 = path->current_point.x + dx0;
+ y0 = path->current_point.y + dy0;
- p1.x = path->current_point.x + d1->dx;
- p1.y = path->current_point.y + d1->dy;
+ x1 = path->current_point.x + dx1;
+ y1 = path->current_point.y + dy1;
- p2.x = path->current_point.x + d2->dx;
- p2.y = path->current_point.y + d2->dy;
+ x2 = path->current_point.x + dx2;
+ y2 = path->current_point.y + dy2;
- return _cairo_path_curve_to (path, &p0, &p1, &p2);
+ return _cairo_path_fixed_curve_to (path,
+ x0, y0,
+ x1, y1,
+ x2, y2);
}
cairo_status_t
-_cairo_path_close_path (cairo_path_t *path)
+_cairo_path_fixed_close_path (cairo_path_fixed_t *path)
{
cairo_status_t status;
- status = _cairo_path_add (path, CAIRO_PATH_OP_CLOSE_PATH, NULL, 0);
+ status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CLOSE_PATH, NULL, 0);
if (status)
return status;
@@ -256,120 +298,113 @@ _cairo_path_close_path (cairo_path_t *path)
}
cairo_status_t
-_cairo_path_current_point (cairo_path_t *path, cairo_point_t *point)
+_cairo_path_fixed_get_current_point (cairo_path_fixed_t *path,
+ cairo_fixed_t *x,
+ cairo_fixed_t *y)
{
if (! path->has_current_point)
return CAIRO_STATUS_NO_CURRENT_POINT;
- *point = path->current_point;
+ *x = path->current_point.x;
+ *y = path->current_point.y;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
-_cairo_path_add (cairo_path_t *path, cairo_path_op_t op, cairo_point_t *points, int num_points)
+_cairo_path_fixed_add (cairo_path_fixed_t *path,
+ cairo_path_op_t op,
+ cairo_point_t *points,
+ int num_points)
{
- cairo_status_t status;
+ if (path->op_buf_tail == NULL ||
+ path->op_buf_tail->num_ops + 1 > CAIRO_PATH_BUF_SIZE)
+ {
+ cairo_path_op_buf_t *op_buf;
- if (path->op_tail == NULL || path->op_tail->num_ops + 1 > CAIRO_PATH_BUF_SZ) {
- status = _cairo_path_new_op_buf (path);
- if (status)
- return status;
- }
- _cairo_path_op_buf_add (path->op_tail, op);
+ op_buf = _cairo_path_op_buf_create ();
+ if (op_buf == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
- if (path->arg_tail == NULL || path->arg_tail->num_points + num_points > CAIRO_PATH_BUF_SZ) {
- status = _cairo_path_new_arg_buf (path);
- if (status)
- return status;
+ _cairo_path_fixed_add_op_buf (path, op_buf);
}
- _cairo_path_arg_buf_add (path->arg_tail, points, num_points);
-
- return CAIRO_STATUS_SUCCESS;
-}
-static void
-_cairo_path_add_op_buf (cairo_path_t *path, cairo_path_op_buf_t *op)
-{
- op->next = NULL;
- op->prev = path->op_tail;
+ _cairo_path_op_buf_add_op (path->op_buf_tail, op);
- if (path->op_tail) {
- path->op_tail->next = op;
- } else {
- path->op_head = op;
- }
+ if (path->arg_buf_tail == NULL ||
+ path->arg_buf_tail->num_points + num_points > CAIRO_PATH_BUF_SIZE)
+ {
+ cairo_path_arg_buf_t *arg_buf;
- path->op_tail = op;
-}
+ arg_buf = _cairo_path_arg_buf_create ();
-static cairo_status_t
-_cairo_path_new_op_buf (cairo_path_t *path)
-{
- cairo_path_op_buf_t *op;
+ if (arg_buf == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
- op = _cairo_path_op_buf_create ();
- if (op == NULL)
- return CAIRO_STATUS_NO_MEMORY;
+ _cairo_path_fixed_add_arg_buf (path, arg_buf);
+ }
- _cairo_path_add_op_buf (path, op);
+ _cairo_path_arg_buf_add_points (path->arg_buf_tail, points, num_points);
return CAIRO_STATUS_SUCCESS;
}
static void
-_cairo_path_add_arg_buf (cairo_path_t *path, cairo_path_arg_buf_t *arg)
+_cairo_path_fixed_add_op_buf (cairo_path_fixed_t *path,
+ cairo_path_op_buf_t *op_buf)
{
- arg->next = NULL;
- arg->prev = path->arg_tail;
+ op_buf->next = NULL;
+ op_buf->prev = path->op_buf_tail;
- if (path->arg_tail) {
- path->arg_tail->next = arg;
+ if (path->op_buf_tail) {
+ path->op_buf_tail->next = op_buf;
} else {
- path->arg_head = arg;
+ path->op_buf_head = op_buf;
}
- path->arg_tail = arg;
+ path->op_buf_tail = op_buf;
}
-static cairo_status_t
-_cairo_path_new_arg_buf (cairo_path_t *path)
+static void
+_cairo_path_fixed_add_arg_buf (cairo_path_fixed_t *path,
+ cairo_path_arg_buf_t *arg_buf)
{
- cairo_path_arg_buf_t *arg;
-
- arg = _cairo_path_arg_buf_create ();
-
- if (arg == NULL)
- return CAIRO_STATUS_NO_MEMORY;
+ arg_buf->next = NULL;
+ arg_buf->prev = path->arg_buf_tail;
- _cairo_path_add_arg_buf (path, arg);
+ if (path->arg_buf_tail) {
+ path->arg_buf_tail->next = arg_buf;
+ } else {
+ path->arg_buf_head = arg_buf;
+ }
- return CAIRO_STATUS_SUCCESS;
+ path->arg_buf_tail = arg_buf;
}
static cairo_path_op_buf_t *
_cairo_path_op_buf_create (void)
{
- cairo_path_op_buf_t *op;
+ cairo_path_op_buf_t *op_buf;
- op = malloc (sizeof (cairo_path_op_buf_t));
+ op_buf = malloc (sizeof (cairo_path_op_buf_t));
- if (op) {
- op->num_ops = 0;
- op->next = NULL;
+ if (op_buf) {
+ op_buf->num_ops = 0;
+ op_buf->next = NULL;
}
- return op;
+ return op_buf;
}
static void
-_cairo_path_op_buf_destroy (cairo_path_op_buf_t *op)
+_cairo_path_op_buf_destroy (cairo_path_op_buf_t *op_buf)
{
- free (op);
+ free (op_buf);
}
static void
-_cairo_path_op_buf_add (cairo_path_op_buf_t *op_buf, cairo_path_op_t op)
+_cairo_path_op_buf_add_op (cairo_path_op_buf_t *op_buf,
+ cairo_path_op_t op)
{
op_buf->op[op_buf->num_ops++] = op;
}
@@ -377,31 +412,33 @@ _cairo_path_op_buf_add (cairo_path_op_buf_t *op_buf, cairo_path_op_t op)
static cairo_path_arg_buf_t *
_cairo_path_arg_buf_create (void)
{
- cairo_path_arg_buf_t *arg;
+ cairo_path_arg_buf_t *arg_buf;
- arg = malloc (sizeof (cairo_path_arg_buf_t));
+ arg_buf = malloc (sizeof (cairo_path_arg_buf_t));
- if (arg) {
- arg->num_points = 0;
- arg->next = NULL;
+ if (arg_buf) {
+ arg_buf->num_points = 0;
+ arg_buf->next = NULL;
}
- return arg;
+ return arg_buf;
}
static void
-_cairo_path_arg_buf_destroy (cairo_path_arg_buf_t *arg)
+_cairo_path_arg_buf_destroy (cairo_path_arg_buf_t *arg_buf)
{
- free (arg);
+ free (arg_buf);
}
static void
-_cairo_path_arg_buf_add (cairo_path_arg_buf_t *arg, cairo_point_t *points, int num_points)
+_cairo_path_arg_buf_add_points (cairo_path_arg_buf_t *arg_buf,
+ cairo_point_t *points,
+ int num_points)
{
int i;
for (i=0; i < num_points; i++) {
- arg->points[arg->num_points++] = points[i];
+ arg_buf->points[arg_buf->num_points++] = points[i];
}
}
@@ -416,29 +453,30 @@ static int const num_args[] =
};
cairo_status_t
-_cairo_path_interpret (cairo_path_t *path,
- cairo_direction_t dir,
- cairo_path_move_to_func_t *move_to,
- cairo_path_line_to_func_t *line_to,
- cairo_path_curve_to_func_t *curve_to,
- cairo_path_close_path_func_t *close_path,
- void *closure)
+_cairo_path_fixed_interpret (cairo_path_fixed_t *path,
+ cairo_direction_t dir,
+ cairo_path_fixed_move_to_func_t *move_to,
+ cairo_path_fixed_line_to_func_t *line_to,
+ cairo_path_fixed_curve_to_func_t *curve_to,
+ cairo_path_fixed_close_path_func_t *close_path,
+ void *closure)
{
cairo_status_t status;
int i, arg;
cairo_path_op_buf_t *op_buf;
cairo_path_op_t op;
- cairo_path_arg_buf_t *arg_buf = path->arg_head;
+ cairo_path_arg_buf_t *arg_buf = path->arg_buf_head;
int buf_i = 0;
cairo_point_t point[CAIRO_PATH_OP_MAX_ARGS];
- int step = (dir == CAIRO_DIRECTION_FORWARD) ? 1 : -1;
+ cairo_bool_t forward = (dir == CAIRO_DIRECTION_FORWARD);
+ int step = forward ? 1 : -1;
- for (op_buf = (dir == CAIRO_DIRECTION_FORWARD) ? path->op_head : path->op_tail;
+ for (op_buf = forward ? path->op_buf_head : path->op_buf_tail;
op_buf;
- op_buf = (dir == CAIRO_DIRECTION_FORWARD) ? op_buf->next : op_buf->prev)
+ op_buf = forward ? op_buf->next : op_buf->prev)
{
int start, stop;
- if (dir == CAIRO_DIRECTION_FORWARD) {
+ if (forward) {
start = 0;
stop = op_buf->num_ops;
} else {
@@ -449,7 +487,7 @@ _cairo_path_interpret (cairo_path_t *path,
for (i=start; i != stop; i += step) {
op = op_buf->op[i];
- if (dir == CAIRO_DIRECTION_REVERSE) {
+ if (! forward) {
if (buf_i == 0) {
arg_buf = arg_buf->prev;
buf_i = arg_buf->num_points;
@@ -466,7 +504,7 @@ _cairo_path_interpret (cairo_path_t *path,
}
}
- if (dir == CAIRO_DIRECTION_REVERSE) {
+ if (! forward) {
buf_i -= num_args[op];
}
@@ -492,4 +530,3 @@ _cairo_path_interpret (cairo_path_t *path,
return CAIRO_STATUS_SUCCESS;
}
-
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 283c36dbd..1746b6b2a 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1,6 +1,7 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2004 David Reveman
+ * 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
@@ -56,9 +57,8 @@ _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
pattern->ref_count = 1;
pattern->extend = CAIRO_EXTEND_DEFAULT;
pattern->filter = CAIRO_FILTER_DEFAULT;
- pattern->alpha = 1.0;
- _cairo_matrix_init (&pattern->matrix);
+ cairo_matrix_init_identity (&pattern->matrix);
}
static cairo_status_t
@@ -150,15 +150,10 @@ _cairo_pattern_fini (cairo_pattern_t *pattern)
void
_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
- double red,
- double green,
- double blue)
+ const cairo_color_t *color)
{
_cairo_pattern_init (&pattern->base, CAIRO_PATTERN_SOLID);
-
- pattern->red = red;
- pattern->green = green;
- pattern->blue = blue;
+ pattern->color = *color;
}
void
@@ -209,7 +204,7 @@ _cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
}
cairo_pattern_t *
-_cairo_pattern_create_solid (double red, double green, double blue)
+_cairo_pattern_create_solid (const cairo_color_t *color)
{
cairo_solid_pattern_t *pattern;
@@ -217,7 +212,7 @@ _cairo_pattern_create_solid (double red, double green, double blue)
if (pattern == NULL)
return NULL;
- _cairo_pattern_init_solid (pattern, red, green, blue);
+ _cairo_pattern_init_solid (pattern, color);
return &pattern->base;
}
@@ -296,11 +291,8 @@ cairo_pattern_destroy (cairo_pattern_t *pattern)
static cairo_status_t
_cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
- double offset,
- double red,
- double green,
- double blue,
- double alpha)
+ double offset,
+ cairo_color_t *color)
{
cairo_color_stop_t *stop;
@@ -316,22 +308,48 @@ _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
stop = &pattern->stops[pattern->n_stops - 1];
stop->offset = _cairo_fixed_from_double (offset);
-
- _cairo_color_init (&stop->color);
- _cairo_color_set_rgb (&stop->color, red, green, blue);
- _cairo_color_set_alpha (&stop->color, alpha);
+ stop->color = *color;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
-cairo_pattern_add_color_stop (cairo_pattern_t *pattern,
- double offset,
- double red,
- double green,
- double blue,
- double alpha)
+cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
+ double offset,
+ double red,
+ double green,
+ double blue)
{
+ cairo_color_t color;
+
+ if (pattern->type != CAIRO_PATTERN_LINEAR &&
+ pattern->type != CAIRO_PATTERN_RADIAL)
+ {
+ /* XXX: CAIRO_STATUS_INVALID_PATTERN? */
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ _cairo_restrict_value (&offset, 0.0, 1.0);
+ _cairo_restrict_value (&red, 0.0, 1.0);
+ _cairo_restrict_value (&green, 0.0, 1.0);
+ _cairo_restrict_value (&blue, 0.0, 1.0);
+
+ _cairo_color_init_rgb (&color, red, green, blue);
+ return _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
+ offset,
+ &color);
+}
+
+cairo_status_t
+cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
+ double offset,
+ double red,
+ double green,
+ double blue,
+ double alpha)
+{
+ cairo_color_t color;
+
if (pattern->type != CAIRO_PATTERN_LINEAR &&
pattern->type != CAIRO_PATTERN_RADIAL)
{
@@ -345,22 +363,27 @@ cairo_pattern_add_color_stop (cairo_pattern_t *pattern,
_cairo_restrict_value (&blue, 0.0, 1.0);
_cairo_restrict_value (&alpha, 0.0, 1.0);
+ _cairo_color_init_rgba (&color, red, green, blue, alpha);
return _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
offset,
- red, green, blue,
- alpha);
+ &color);
}
cairo_status_t
-cairo_pattern_set_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix)
+cairo_pattern_set_matrix (cairo_pattern_t *pattern,
+ const cairo_matrix_t *matrix)
{
- return cairo_matrix_copy (&pattern->matrix, matrix);
+ pattern->matrix = *matrix;
+
+ return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix)
{
- return cairo_matrix_copy (matrix, &pattern->matrix);
+ *matrix = pattern->matrix;
+
+ return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
@@ -391,35 +414,9 @@ cairo_pattern_get_extend (cairo_pattern_t *pattern)
return pattern->extend;
}
-cairo_status_t
-_cairo_pattern_get_rgb (cairo_pattern_t *pattern,
- double *red,
- double *green,
- double *blue)
-{
-
- if (pattern->type == CAIRO_PATTERN_SOLID)
- {
- cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
-
- *red = solid->red;
- *green = solid->green;
- *blue = solid->blue;
- } else
- *red = *green = *blue = 1.0;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-void
-_cairo_pattern_set_alpha (cairo_pattern_t *pattern, double alpha)
-{
- pattern->alpha = alpha;
-}
-
void
-_cairo_pattern_transform (cairo_pattern_t *pattern,
- cairo_matrix_t *ctm_inverse)
+_cairo_pattern_transform (cairo_pattern_t *pattern,
+ const cairo_matrix_t *ctm_inverse)
{
cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix);
}
@@ -506,8 +503,7 @@ _cairo_pattern_shader_init (cairo_gradient_pattern_t *pattern,
op->stops[i].color_char[0] = pattern->stops[i].color.red * 0xff;
op->stops[i].color_char[1] = pattern->stops[i].color.green * 0xff;
op->stops[i].color_char[2] = pattern->stops[i].color.blue * 0xff;
- op->stops[i].color_char[3] = pattern->stops[i].color.alpha *
- pattern->base.alpha * 0xff;
+ op->stops[i].color_char[3] = pattern->stops[i].color.alpha * 0xff;
op->stops[i].offset = pattern->stops[i].offset;
op->stops[i].id = i;
}