[cairo-commit] 13 commits - src/cairo-win32-font.c

Jeff Muizelaar jrmuizel at kemper.freedesktop.org
Thu Dec 18 14:30:49 PST 2008


 src/cairo-win32-font.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

New commits:
commit b4e0d489bb0317fdd935ad2d29830e48b5ce4f6c
Merge: 813cbf1... f60da9a...
Author: Jeff Muizelaar <jmuizelaar at mozilla.com>
Date:   Thu Dec 18 17:25:17 2008 -0500

    Merge branch '1.8'
    
    Conflicts:
    	NEWS
    	build/Makefile.am.changelog
    	cairo-version.h
    	src/cairo-gstate.c

commit f60da9a379890a3a4cd74cdad48e73c22cb74160
Author: Jeff Muizelaar <jmuizelaar at mozilla.com>
Date:   Thu Dec 18 17:07:25 2008 -0500

    Fix _compute_transform to check for nearly degenerate matrices
    
    If a matrix was something like [0 .000001 0, .000001 0 0] the old code would
    assume that xx and yy were greater than 0 and turn the nearly degenerate matrix
    into an actual degenerate one. This caused things to blow up later on. Now we
    check that our nearly rectangular matrices are not nearly degenerate, and let
    the nearly degenerate ones fall through to the non-rectangular path.
    
    Note: I'm not sure why NEARLY_ZERO(d) is fabs(d) < 1/65536 instead of some
    other value.  Hopefully, it's a useful definition.
    
    This problem was found by a test case attached to:
    https://bugzilla.mozilla.org/show_bug.cgi?id=467423

diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 879cfac..b4f125e 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -158,7 +158,8 @@ _compute_transform (cairo_win32_scaled_font_t *scaled_font,
 {
     cairo_status_t status;
 
-    if (NEARLY_ZERO (sc->yx) && NEARLY_ZERO (sc->xy)) {
+    if (NEARLY_ZERO (sc->yx) && NEARLY_ZERO (sc->xy) &&
+	    !NEARLY_ZERO(sc->xx) && !NEARLY_ZERO(sc->yy)) {
 	scaled_font->preserve_axes = TRUE;
 	scaled_font->x_scale = sc->xx;
 	scaled_font->swap_x = (sc->xx < 0);
@@ -166,7 +167,8 @@ _compute_transform (cairo_win32_scaled_font_t *scaled_font,
 	scaled_font->swap_y = (sc->yy < 0);
 	scaled_font->swap_axes = FALSE;
 
-    } else if (NEARLY_ZERO (sc->xx) && NEARLY_ZERO (sc->yy)) {
+    } else if (NEARLY_ZERO (sc->xx) && NEARLY_ZERO (sc->yy) &&
+	    !NEARLY_ZERO(sc->yx) && !NEARLY_ZERO(sc->xy)) {
 	scaled_font->preserve_axes = TRUE;
 	scaled_font->x_scale = sc->yx;
 	scaled_font->swap_x = (sc->yx < 0);
commit 0137b9bd320783264d865a397392b0ee14fd69b3
Author: Karl Tomlinson <karlt+ at karlt.net>
Date:   Wed Dec 17 16:40:12 2008 -0500

    [ft] Don't call FT_Done_Face() on faces we did not create

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index cd11253..3675db6 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -528,7 +528,7 @@ _has_unlocked_face (void *entry)
 {
     cairo_ft_unscaled_font_t *unscaled = entry;
 
-    return (unscaled->lock_count == 0 && unscaled->face);
+    return (!unscaled->from_face && unscaled->lock_count == 0 && unscaled->face);
 }
 
 /* Ensures that an unscaled font has a face object. If we exceed
commit 9485cd947f982ecd1e4f8d948786af3265d6eb74
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Dec 14 16:35:14 2008 +0000

    Increment version to 1.8.7 after the 1.8.6 release.

diff --git a/cairo-version.h b/cairo-version.h
index 4e2458e..c814964 100644
--- a/cairo-version.h
+++ b/cairo-version.h
@@ -3,6 +3,6 @@
 
 #define CAIRO_VERSION_MAJOR 1
 #define CAIRO_VERSION_MINOR 8
-#define CAIRO_VERSION_MICRO 6
+#define CAIRO_VERSION_MICRO 7
 
 #endif
commit e2a2eddcfb8fc73f3decdb91c00e8e6d5282e09c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Dec 14 14:07:11 2008 +0000

    Increment version to 1.8.6
    
    In preparation for the next stable release.

diff --git a/cairo-version.h b/cairo-version.h
index e389760..4e2458e 100644
--- a/cairo-version.h
+++ b/cairo-version.h
@@ -3,6 +3,6 @@
 
 #define CAIRO_VERSION_MAJOR 1
 #define CAIRO_VERSION_MINOR 8
-#define CAIRO_VERSION_MICRO 5
+#define CAIRO_VERSION_MICRO 6
 
 #endif
commit ef7c42a7d390064b2a5b08e14d5f65b8ea4628e3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Dec 14 14:06:07 2008 +0000

    [NEWS] Add notes for 1.8.6
    
    Add the historical blurb for 1.8.6.

diff --git a/NEWS b/NEWS
index 5be426c..8c80c61 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,53 @@
+Release 1.8.6 (2008-12-13 Chris Wilson <chris at chris-wilson.co.uk>)
+=========================================================
+The cairo community is pleased to announce the 1.8.6 release of the
+cairo graphics library. This is the third update to cairo's stable
+1.8 series and contains a small number of bug fixes (in particular a
+few fixes for failures of cairo 1.8.4 on Quartz and PDF, and build fixes for
+a couple of backends). This is being released just under a month after
+cairo 1.8.4.
+
+We recommend that everyone using cairo upgrade to 1.8.6.
+
+-Chris
+
+Build fixes
+-----------
+Fix build of DirectFB backend with debugging enabled:
+
+   Bug in _cairo_directfb_surface_release_source_image function
+   http://bugs.freedesktop.org/show_bug.cgi?id=18322
+
+Fix build on OS/2.
+
+Bug fixes
+---------
+Workaround a mis-compilation of cairo_matrix_invert() that generated invalid
+matrices and triggered assertion failures later. The issue was reported by
+Peter Hercek.
+
+Invalid computation of the modulus:
+
+   https://bugzilla.mozilla.org/show_bug.cgi?id=466258
+
+Invalid referencing of patterns in the Quartz backend:
+
+   Failed assertion `CAIRO_REFERENCE_COUNT_HAS_REFERENCE
+   (&pattern->ref_count)' when using cairo quartz backend
+   http://bugs.freedesktop.org/show_bug.cgi?id=18632
+
+Invalid references to glyphs after early culling, causing segmentation faults
+in the PDF backend:
+
+   http://lists.cairographics.org/archives/cairo/2008-December/015976.html
+
+Check for XRender in the XCB backend, or else we may attempt an invalid memory
+access:
+
+    XCB backend fails with missing render.
+    https://bugs.freedesktop.org/show_bug.cgi?id=18588
+
+
 Release 1.8.4 (2008-11-14 Carl Worth <cworth at cworth.org>)
 =========================================================
 The cairo community is pleased to announce the 1.8.4 release of the
commit ce91e6ac360e1dbe57a4e729b68d84499603e9ae
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Dec 14 14:53:27 2008 +0000

    [perf] Fix for git-1.6
    
    git-1.6 moved all the subcommands out of the PATH so update our usage.

diff --git a/perf/cairo-perf-graph b/perf/cairo-perf-graph
index 4d25953..aa05bf1 100755
--- a/perf/cairo-perf-graph
+++ b/perf/cairo-perf-graph
@@ -79,7 +79,7 @@ fi
 
 git_setup() {
     SUBDIRECTORY_OK='Yes'
-    . git-sh-setup
+    . "$(git --exec-path)/git-sh-setup"
     CAIRO_DIR=`dirname $GIT_DIR`
     if [ "$CAIRO_DIR" = "." ]; then
 	CAIRO_DIR=`pwd`
commit f8372509aff662e9cbabeb99560b01019395c15e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Dec 14 13:05:01 2008 +0000

    [RELEASING] Update Makefile for git-1.6
    
    Git moved all the subcommands out of the PATH, so we need to update our
    usage.

diff --git a/build/Makefile.am.changelog b/build/Makefile.am.changelog
index b9fbdcf..8c7c3e4 100644
--- a/build/Makefile.am.changelog
+++ b/build/Makefile.am.changelog
@@ -37,7 +37,7 @@ $(srcdir)/ChangeLog:
 	@if test -d "$(srcdir)/.git"; then \
 		version=$(CURR_CHANGELOG_VERSION); \
 		prev=$(PREV_CHANGELOG_VERSION).0; \
-		nearest_tag=`git-describe | sed 's/-.*//'`; \
+		nearest_tag=`git describe | sed 's/-.*//'`; \
 		before=$(srcdir)/ChangeLog.cache-$$prev..$$nearest_tag; \
 		after=$(srcdir)/ChangeLog.cache-$$nearest_tag..; \
 		$(MAKE) $(AM_MAKEFLAGS) $$before $$after && \
@@ -71,7 +71,7 @@ $(srcdir)/ChangeLog.cache-% $(srcdir)/ChangeLog.pre-%:
 		test "x$$from" = xinitial || from=$$from.0; \
 		spec=$$from..$$to; \
 	  fi; \
-	  $(srcdir)/build/missing --run git-log --stat "$$spec") > $@.tmp \
+	  $(srcdir)/build/missing --run git log --stat "$$spec") > $@.tmp \
 	  && mv -f $@.tmp $@ \
 	  || ($(RM) $@.tmp; \
 	      echo Failed to generate $@, your $@ may be outdated >&2); \
diff --git a/build/Makefile.am.releasing b/build/Makefile.am.releasing
index 4f6f8ab..08cab67 100644
--- a/build/Makefile.am.releasing
+++ b/build/Makefile.am.releasing
@@ -19,7 +19,7 @@ dist-clear-sticky-bits:
 
 snapshot:
 	distdir="$(distdir)-`date '+%Y%m%d'`"; \
-	test -d "$(srcdir)/.git" && distdir=$$distdir-`cd "$(srcdir)" && git-rev-parse HEAD | cut -c 1-6`; \
+	test -d "$(srcdir)/.git" && distdir=$$distdir-`cd "$(srcdir)" && git rev-parse HEAD | cut -c 1-6`; \
 	TAR_OPTIONS="$(TAR_OPTIONS)" $(MAKE) $(AM_MAKEFLAGS) distdir="$$distdir" snapshot-dist
 
 snapshot-dist: dist
@@ -99,7 +99,7 @@ release-upload: $(tar_file) $(sha1_file) $(gpg_file)
 	scp $(tar_file) $(sha1_file) $(gpg_file) $(RELEASE_UPLOAD_HOST):$(RELEASE_UPLOAD_DIR)
 	mv $(tar_file) $(sha1_file) $(gpg_file) releases
 	ssh $(RELEASE_UPLOAD_HOST) "rm -f $(RELEASE_UPLOAD_DIR)/LATEST-$(PACKAGE)-[0-9]* && ln -s $(tar_file) $(RELEASE_UPLOAD_DIR)/LATEST-$(PACKAGE)-$(VERSION)"
-	git-tag -s  -m "cairo $(CAIRO_VERSION_MAJOR).$(CAIRO_VERSION_MINOR).$(CAIRO_VERSION_MICRO) release" $(CAIRO_VERSION_MAJOR).$(CAIRO_VERSION_MINOR).$(CAIRO_VERSION_MICRO)
+	git tag -s  -m "cairo $(CAIRO_VERSION_MAJOR).$(CAIRO_VERSION_MINOR).$(CAIRO_VERSION_MICRO) release" $(CAIRO_VERSION_MAJOR).$(CAIRO_VERSION_MINOR).$(CAIRO_VERSION_MICRO)
 
 release-publish-message: releases/$(sha1_file)
 	@echo "Please follow the instructions in RELEASING to push stuff out and"
commit 9faa9a214994fe27a0cb27a298881f23c2050bbe
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Dec 14 11:40:12 2008 +0000

    [RELEASING] Correct a few minor typos.
    
    As I was reading through the instructions, take the opportunity to fix a
    few spelling mistakes.

diff --git a/RELEASING b/RELEASING
index ae70ae6..c3d5ae9 100644
--- a/RELEASING
+++ b/RELEASING
@@ -1,13 +1,13 @@
 Here are the steps to follow to create a new cairo release:
 
-1) Ensure that there are no local, uncommitted/unspushed
+1) Ensure that there are no local, uncommitted/unpushed
    modifications. You're probably in a good state if both "git diff
    HEAD" and "git log master..origin/master" give no output.
 
 2) Verify that the code passes "make distcheck"
 
 	First, make sure you have 'nm' and 'readelf' commands in PATH.
-	this should be Ok with any Linux distro.
+	this should be OK with any Linux distro.
 
 	Running "make distcheck" should result in no warnings or
 	errors and end with a message of the form:
@@ -43,7 +43,7 @@ Here are the steps to follow to create a new cairo release:
 3) Fill out an entry in the NEWS file
 
 	Sift through the logs since the last release. This is most
-	easily done with a comand such as:
+	easily done with a command such as:
 
 		git log --stat X.Y.Z..
 
@@ -72,7 +72,7 @@ Here are the steps to follow to create a new cairo release:
 	and reset cairo_version_micro to 0. NOTE: The minor version is
 	only incremented for releases, not for snapshots.
 
-	Otherwise, (ie. there are only bug fixes), increment
+	Otherwise, (i.e. there are only bug fixes), increment
 	cairo_version_micro to the next larger (even) number.
 
 5) Commit the changes to NEWS and cairo-version.h
@@ -121,7 +121,7 @@ Here are the steps to follow to create a new cairo release:
     using the text provided from "make release-publish", adding the excerpt
     from NEWS, your signature, followed by the standard "What is cairo" and
     "Where to get more information about cairo" blurbs from README, and
-    inally the shortlog of all changes since last release, generated by:
+    finally the shortlog of all changes since last release, generated by:
 
 	git shortlog X.Y.Z...
 
commit b1be4196513263bdbf58944ea6ac87708a399c5f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Dec 14 11:26:56 2008 +0000

    [doc] Fix erroneous doc comment.
    
    A normal comment was marked as a gtk-doc entry and thus causing gtk-doc to
    complain.

diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c
index 9086119..a915ada 100644
--- a/src/cairo-path-fixed.c
+++ b/src/cairo-path-fixed.c
@@ -797,7 +797,7 @@ _cairo_path_fixed_is_empty (cairo_path_fixed_t *path)
     return FALSE;
 }
 
-/**
+/*
  * Check whether the given path contains a single rectangle.
  */
 cairo_bool_t
commit 79bd32a6ccb1a882ddd2b1585ab155f568bf5ec7
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Dec 6 13:32:37 2008 +0200

    [perf-diff] Fix cairo-perf-diff for git 1.6
    
    Since git 1.6 the plumbing commands aren't installed in the user's
    path by default.  This patch fixes cairo-perf-diff to find the
    git-sh-setup command from git's lib dir.
    (cherry picked from commit 0c0f4862c52d68776024f125b003ade455044b27)

diff --git a/perf/cairo-perf-diff b/perf/cairo-perf-diff
index 50cd1f2..718cdc5 100755
--- a/perf/cairo-perf-diff
+++ b/perf/cairo-perf-diff
@@ -89,7 +89,7 @@ fi
 
 git_setup() {
     SUBDIRECTORY_OK='Yes'
-    . git-sh-setup
+    . "$(git --exec-path)/git-sh-setup"
     CAIRO_DIR=`dirname $GIT_DIR`
     if [ "$CAIRO_DIR" = "." ]; then
 	CAIRO_DIR=`pwd`
commit 97b5240beeb9206f4dbda6ffce33b51aa16eec2f
Author: Julien Danjou <julien at danjou.info>
Date:   Tue Nov 18 10:01:49 2008 +0100

    [xcb] check for render extension presence
    
    Otherwise this may leads to an invalid memory access to r.
    
    Fixes: Bug 18588 - XCB backend fails with missing render.
    https://bugs.freedesktop.org/show_bug.cgi?id=18588
    
    Signed-off-by: Julien Danjou <julien at danjou.info>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
    (cherry picked from commit 834f1d7b7097dcc3a32f6c65d21e87fd272d924a)

diff --git a/AUTHORS b/AUTHORS
index 488f4c0..289fecb 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -16,6 +16,7 @@ Steve Chaplin <stevech1097 at yahoo.com.au> Bug fixes for PNG reading
 Tomasz Cholewo <cholewo at ieee-cis.org> Bug fixes
 Manu Cornet <manu at manucornet.net> SVG build fix
 Frederic Crozat <fcrozat at mandriva.com> Fix test suite for OPD platforms (IA64 or PPC64)
+Julien Danjou <julien at danjou.info> XCB fixes
 Radek Doulík <rodo at novell.com> Bug report and test case
 John Ehresman <jpe at wingide.com> Build fixes for win32
 John Ellson <ellson at research.att.com> First font/glyph extents functions
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 9b7eb4b..c63e851 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -1732,7 +1732,8 @@ _cairo_xcb_surface_create_internal (xcb_connection_t	     *dpy,
 				    int			      depth)
 {
     cairo_xcb_surface_t *surface;
-    const xcb_render_query_version_reply_t *r;
+    const xcb_query_extension_reply_t *er;
+    const xcb_render_query_version_reply_t *r = NULL;
 
     surface = malloc (sizeof (cairo_xcb_surface_t));
     if (surface == NULL)
@@ -1764,7 +1765,10 @@ _cairo_xcb_surface_create_internal (xcb_connection_t	     *dpy,
 	;
     }
 
-    r = xcb_render_util_query_version(dpy);
+    er = xcb_get_extension_data(dpy, &xcb_render_id);
+    if(er && er->present) {
+	r = xcb_render_util_query_version(dpy);
+    }
     if (r) {
 	surface->render_major = r->major_version;
 	surface->render_minor = r->minor_version;
commit 6fed98c0d3b0708ad5171654179a482fa7d88805
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Dec 5 21:14:45 2008 +0000

    [gstate] Remove culled glyphs from clusters.
    
    Sascha Steinbiss reported a bug where the PDF backend was reading beyond
    the end of the glyph array:
    http://lists.cairographics.org/archives/cairo/2008-December/015976.html.
    
    It transpires that in the early glyph culling in the gstate we were
    not updating the clusters to skip culled glyphs.

diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index fe8d279..28a9538 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -64,8 +64,12 @@ static cairo_status_t
 _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t      *gstate,
                                            const cairo_glyph_t *glyphs,
                                            int                  num_glyphs,
+					   const cairo_text_cluster_t	*clusters,
+					   int			 num_clusters,
+					   cairo_text_cluster_flags_t cluster_flags,
                                            cairo_glyph_t       *transformed_glyphs,
-					   int		       *num_transformed_glyphs);
+					   int			*num_transformed_glyphs,
+					   cairo_text_cluster_t *transformed_clusters);
 
 cairo_status_t
 _cairo_gstate_init (cairo_gstate_t  *gstate,
@@ -1581,10 +1585,12 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
 				int			    num_clusters,
 				cairo_text_cluster_flags_t  cluster_flags)
 {
-    cairo_status_t status;
     cairo_pattern_union_t source_pattern;
-    cairo_glyph_t *transformed_glyphs;
     cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
+    cairo_glyph_t *transformed_glyphs;
+    cairo_text_cluster_t stack_transformed_clusters[CAIRO_STACK_ARRAY_LENGTH (cairo_text_cluster_t)];
+    cairo_text_cluster_t *transformed_clusters;
+    cairo_status_t status;
 
     if (gstate->source->status)
 	return gstate->source->status;
@@ -1597,18 +1603,37 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
     if (status)
 	return status;
 
-    if (num_glyphs <= ARRAY_LENGTH (stack_transformed_glyphs)) {
-	transformed_glyphs = stack_transformed_glyphs;
-    } else {
+    transformed_glyphs = stack_transformed_glyphs;
+    transformed_clusters = stack_transformed_clusters;
+
+    if (num_glyphs > ARRAY_LENGTH (stack_transformed_glyphs)) {
 	transformed_glyphs = cairo_glyph_allocate (num_glyphs);
-	if (transformed_glyphs == NULL)
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	if (transformed_glyphs == NULL) {
+	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    goto CLEANUP_GLYPHS;
+	}
+    }
+
+    /* Just in case */
+    if (!clusters)
+	num_clusters = 0;
+
+    if (num_clusters > ARRAY_LENGTH (stack_transformed_clusters)) {
+	transformed_clusters = cairo_text_cluster_allocate (num_clusters);
+	if (transformed_clusters == NULL) {
+	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    goto CLEANUP_GLYPHS;
+	}
     }
 
     status = _cairo_gstate_transform_glyphs_to_backend (gstate,
 							glyphs, num_glyphs,
+							clusters,
+							num_clusters,
+							cluster_flags,
 							transformed_glyphs,
-							&num_glyphs);
+							&num_glyphs,
+							transformed_clusters);
 
     if (status || num_glyphs == 0)
 	goto CLEANUP_GLYPHS;
@@ -1617,10 +1642,6 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
     if (status)
 	goto CLEANUP_GLYPHS;
 
-    /* Just in case */
-    if (!clusters)
-	num_clusters = 0;
-
     /* For really huge font sizes, we can just do path;fill instead of
      * show_glyphs, as show_glyphs would put excess pressure on the cache,
      * and moreover, not all components below us correctly handle huge font
@@ -1638,7 +1659,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
 						  &source_pattern.base,
 						  utf8, utf8_len,
 						  transformed_glyphs, num_glyphs,
-						  clusters, num_clusters,
+						  transformed_clusters, num_clusters,
 						  cluster_flags,
 						  gstate->scaled_font);
     } else {
@@ -1667,6 +1688,8 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
 CLEANUP_GLYPHS:
     if (transformed_glyphs != stack_transformed_glyphs)
       cairo_glyph_free (transformed_glyphs);
+    if (transformed_clusters != stack_transformed_clusters)
+      cairo_text_cluster_free (transformed_clusters);
 
     return status;
 }
@@ -1694,8 +1717,9 @@ _cairo_gstate_glyph_path (cairo_gstate_t      *gstate,
 
     status = _cairo_gstate_transform_glyphs_to_backend (gstate,
 							glyphs, num_glyphs,
+							NULL, 0, 0,
 							transformed_glyphs,
-							NULL);
+							NULL, NULL);
     if (status)
 	goto CLEANUP_GLYPHS;
 
@@ -1744,13 +1768,17 @@ _cairo_gstate_get_antialias (cairo_gstate_t *gstate)
  * cull/drop glyphs that will not be visible.
  **/
 static cairo_status_t
-_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t      *gstate,
-                                           const cairo_glyph_t *glyphs,
-                                           int                  num_glyphs,
-                                           cairo_glyph_t       *transformed_glyphs,
-					   int		       *num_transformed_glyphs)
-{
-    int i, j;
+_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t	*gstate,
+                                           const cairo_glyph_t	*glyphs,
+                                           int			 num_glyphs,
+					   const cairo_text_cluster_t	*clusters,
+					   int			 num_clusters,
+					   cairo_text_cluster_flags_t cluster_flags,
+                                           cairo_glyph_t	*transformed_glyphs,
+					   int			*num_transformed_glyphs,
+					   cairo_text_cluster_t *transformed_clusters)
+{
+    int i, j, k;
     cairo_matrix_t *ctm = &gstate->ctm;
     cairo_matrix_t *font_matrix = &gstate->font_matrix;
     cairo_matrix_t *device_transform = &gstate->target->device_transform;
@@ -1796,22 +1824,52 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t      *gstate,
 
 #define KEEP_GLYPH(glyph) (x1 <= glyph.x && glyph.x <= x2 && y1 <= glyph.y && glyph.y <= y2)
 
+    j = 0;
     if (_cairo_matrix_is_identity (ctm) &&
         _cairo_matrix_is_identity (device_transform) &&
 	font_matrix->x0 == 0 && font_matrix->y0 == 0)
     {
-	if (!drop)
-	    memcpy (transformed_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t));
-	else {
-	    for (j = 0, i = 0; i < num_glyphs; i++)
-	    {
+	if (! drop) {
+	    memcpy (transformed_glyphs, glyphs,
+		    num_glyphs * sizeof (cairo_glyph_t));
+	} else if (num_clusters == 0) {
+	    for (i = 0; i < num_glyphs; i++) {
 		transformed_glyphs[j].index = glyphs[i].index;
 		transformed_glyphs[j].x = glyphs[i].x;
 		transformed_glyphs[j].y = glyphs[i].y;
 		if (KEEP_GLYPH (transformed_glyphs[j]))
 		    j++;
 	    }
-	    *num_transformed_glyphs = j;
+	} else {
+	    const cairo_glyph_t *cur_glyph;
+
+	    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
+		cur_glyph = glyphs + num_glyphs - 1;
+	    else
+		cur_glyph = glyphs;
+
+	    for (i = 0; i < num_clusters; i++) {
+		cairo_bool_t cluster_visible = FALSE;
+
+		for (k = 0; k < clusters[i].num_glyphs; k++) {
+		    transformed_glyphs[j+k].index = cur_glyph->index;
+		    transformed_glyphs[j+k].x = cur_glyph->x;
+		    transformed_glyphs[j+k].y = cur_glyph->y;
+		    if (KEEP_GLYPH (transformed_glyphs[j+k]))
+			cluster_visible = TRUE;
+
+		    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
+			cur_glyph--;
+		    else
+			cur_glyph++;
+		}
+
+		transformed_clusters[i] = clusters[i];
+		if (cluster_visible)
+		    j += k;
+		else
+		    transformed_clusters[i].num_glyphs = 0;
+	    }
 	}
     }
     else if (_cairo_matrix_is_translation (ctm) &&
@@ -1820,15 +1878,45 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t      *gstate,
         double tx = font_matrix->x0 + ctm->x0 + device_transform->x0;
         double ty = font_matrix->y0 + ctm->y0 + device_transform->y0;
 
-        for (j = 0, i = 0; i < num_glyphs; i++)
-        {
-            transformed_glyphs[j].index = glyphs[i].index;
-            transformed_glyphs[j].x = glyphs[i].x + tx;
-            transformed_glyphs[j].y = glyphs[i].y + ty;
-	    if (!drop || KEEP_GLYPH (transformed_glyphs[j]))
-		j++;
-        }
-	*num_transformed_glyphs = j;
+	if (! drop || num_clusters == 0) {
+	    for (i = 0; i < num_glyphs; i++) {
+		transformed_glyphs[j].index = glyphs[i].index;
+		transformed_glyphs[j].x = glyphs[i].x + tx;
+		transformed_glyphs[j].y = glyphs[i].y + ty;
+		if (!drop || KEEP_GLYPH (transformed_glyphs[j]))
+		    j++;
+	    }
+	} else {
+	    const cairo_glyph_t *cur_glyph;
+
+	    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
+		cur_glyph = glyphs + num_glyphs - 1;
+	    else
+		cur_glyph = glyphs;
+
+	    for (i = 0; i < num_clusters; i++) {
+		cairo_bool_t cluster_visible = FALSE;
+
+		for (k = 0; k < clusters[i].num_glyphs; k++) {
+		    transformed_glyphs[j+k].index = cur_glyph->index;
+		    transformed_glyphs[j+k].x = cur_glyph->x + tx;
+		    transformed_glyphs[j+k].y = cur_glyph->y + ty;
+		    if (KEEP_GLYPH (transformed_glyphs[j+k]))
+			cluster_visible = TRUE;
+
+		    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
+			cur_glyph--;
+		    else
+			cur_glyph++;
+		}
+
+		transformed_clusters[i] = clusters[i];
+		if (cluster_visible)
+		    j += k;
+		else
+		    transformed_clusters[i].num_glyphs = 0;
+	    }
+	}
     }
     else
     {
@@ -1842,16 +1930,57 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t      *gstate,
         cairo_matrix_multiply (&aggregate_transform,
                                &aggregate_transform, device_transform);
 
-        for (j = 0, i = 0; i < num_glyphs; i++)
-        {
-            transformed_glyphs[j] = glyphs[i];
-            cairo_matrix_transform_point (&aggregate_transform,
-                                          &transformed_glyphs[j].x,
-                                          &transformed_glyphs[j].y);
-	    if (!drop || KEEP_GLYPH (transformed_glyphs[j]))
-		j++;
-        }
-	*num_transformed_glyphs = j;
+	if (! drop || num_clusters == 0) {
+	    for (i = 0; i < num_glyphs; i++) {
+		transformed_glyphs[j] = glyphs[i];
+		cairo_matrix_transform_point (&aggregate_transform,
+					      &transformed_glyphs[j].x,
+					      &transformed_glyphs[j].y);
+		if (! drop || KEEP_GLYPH (transformed_glyphs[j]))
+		    j++;
+	    }
+	} else {
+	    const cairo_glyph_t *cur_glyph;
+
+	    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
+		cur_glyph = glyphs + num_glyphs - 1;
+	    else
+		cur_glyph = glyphs;
+
+	    for (i = 0; i < num_clusters; i++) {
+		cairo_bool_t cluster_visible = FALSE;
+		for (k = 0; k < clusters[i].num_glyphs; k++) {
+		    transformed_glyphs[j+k] = *cur_glyph;
+		    cairo_matrix_transform_point (&aggregate_transform,
+						  &transformed_glyphs[j+k].x,
+						  &transformed_glyphs[j+k].y);
+		    if (KEEP_GLYPH (transformed_glyphs[j+k]))
+			cluster_visible = TRUE;
+
+		    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
+			cur_glyph--;
+		    else
+			cur_glyph++;
+		}
+
+		transformed_clusters[i] = clusters[i];
+		if (cluster_visible)
+		    j += k;
+		else
+		    transformed_clusters[i].num_glyphs = 0;
+	    }
+	}
+    }
+    *num_transformed_glyphs = j;
+
+    if (num_clusters != 0 && cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD) {
+	for (i = 0; i < --j; i++) {
+	    cairo_glyph_t tmp;
+
+	    tmp = transformed_glyphs[i];
+	    transformed_glyphs[i] = transformed_glyphs[j];
+	    transformed_glyphs[j] = tmp;
+	}
     }
 
     return CAIRO_STATUS_SUCCESS;


More information about the cairo-commit mailing list