pixman: Branch 'master' - 5 commits

Søren Sandmann Pedersen sandmann at kemper.freedesktop.org
Thu Oct 20 06:31:06 PDT 2011


 Makefile.am                     |    4 
 pixman/pixman-gradient-walker.c |  175 +++++++++-------------------------------
 pixman/pixman-image.c           |   73 ++++++++++++++++
 pixman/pixman-private.h         |   16 +--
 4 files changed, 124 insertions(+), 144 deletions(-)

New commits:
commit 6131707e8fc39187d1d358481f7c57c57cfab206
Merge: 3d4d705... ec7c9c2...
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Thu Oct 20 09:13:12 2011 -0400

    Merge branch 'gradients'

commit ec7c9c2b6865b48b8bd14e4509538f8fcbe93463
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Oct 14 09:04:48 2011 -0400

    Simplify gradient_walker_reset()
    
    The code that searches for the closest color stop to the given
    position is duplicated across the various repeat modes. Replace the
    switch with two if/else constructions, and put the search code between
    them.

diff --git a/pixman/pixman-gradient-walker.c b/pixman/pixman-gradient-walker.c
index 3848247..048039e 100644
--- a/pixman/pixman-gradient-walker.c
+++ b/pixman/pixman-gradient-walker.c
@@ -56,57 +56,40 @@ gradient_walker_reset (pixman_gradient_walker_t *walker,
     int n, count = walker->num_stops;
     pixman_gradient_stop_t *stops = walker->stops;
 
-    switch (walker->repeat)
+    if (walker->repeat == PIXMAN_REPEAT_NORMAL)
     {
-    case PIXMAN_REPEAT_NORMAL:
-	x = (int32_t)pos & 0xFFFF;
-	for (n = 0; n < count; n++)
-	{
-	    if (x < stops[n].x)
-		break;
-	}
-
-	left_x =  stops[n - 1].x;
-	left_c = &stops[n - 1].color;
-
-	right_x =  stops[n].x;
-	right_c = &stops[n].color;
-
-	left_x  += (pos - x);
-	right_x += (pos - x);
-	break;
-
-    case PIXMAN_REPEAT_PAD:
-	for (n = 0; n < count; n++)
-	{
-	    if (pos < stops[n].x)
-		break;
-	}
-
-	left_x =  stops[n - 1].x;
-	left_c = &stops[n - 1].color;
-
-	right_x =  stops[n].x;
-	right_c = &stops[n].color;
-	break;
-
-    case PIXMAN_REPEAT_REFLECT:
-	x = (int32_t)pos & 0xFFFF;
+	x = (int32_t)pos & 0xffff;
+    }
+    else if (walker->repeat == PIXMAN_REPEAT_REFLECT)
+    {
+	x = (int32_t)pos & 0xffff;
 	if ((int32_t)pos & 0x10000)
 	    x = 0x10000 - x;
-
-	for (n = 0; n < count; n++)
-	{
-	    if (x < stops[n].x)
-		break;
-	}
-
-	left_x =  stops[n - 1].x;
-	left_c = &stops[n - 1].color;
-
-	right_x =  stops[n].x;
-	right_c = &stops[n].color;
-
+    }
+    else
+    {
+	x = pos;
+    }
+    
+    for (n = 0; n < count; n++)
+    {
+	if (x < stops[n].x)
+	    break;
+    }
+    
+    left_x =  stops[n - 1].x;
+    left_c = &stops[n - 1].color;
+    
+    right_x =  stops[n].x;
+    right_c = &stops[n].color;
+
+    if (walker->repeat == PIXMAN_REPEAT_NORMAL)
+    {
+	left_x  += (pos - x);
+	right_x += (pos - x);
+    }
+    else if (walker->repeat == PIXMAN_REPEAT_REFLECT)
+    {
 	if ((int32_t)pos & 0x10000)
 	{
 	    pixman_color_t  *tmp_c;
@@ -124,20 +107,6 @@ gradient_walker_reset (pixman_gradient_walker_t *walker,
 	}
 	left_x  += (pos - x);
 	right_x += (pos - x);
-	break;
-
-    default:  /* REPEAT_NONE */
-	for (n = 0; n < count; n++)
-	{
-	    if (pos < stops[n].x)
-		break;
-	}
-
-	left_x  =  stops[n - 1].x;
-	left_c  = &stops[n - 1].color;
-
-	right_x =  stops[n].x;
-	right_c = &stops[n].color;
     }
 
     walker->left_x   = left_x;
commit 2d0da8ab8d8fef60ed1bbb9d6b75f66577c3f85d
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Oct 14 09:02:14 2011 -0400

    Use sentinels instead of special casing first and last stops
    
    When storing the gradient stops internally, allocate two more stops,
    one before the beginning of the stop list and one after the
    end. Initialize those stops based on the repeat property of the
    gradient.
    
    This allows gradient_walker_reset() to be simplified because it can
    now simply pick the two closest stops to the position without special
    casing the first and last stops.

diff --git a/pixman/pixman-gradient-walker.c b/pixman/pixman-gradient-walker.c
index 53d0b30..3848247 100644
--- a/pixman/pixman-gradient-walker.c
+++ b/pixman/pixman-gradient-walker.c
@@ -56,8 +56,6 @@ gradient_walker_reset (pixman_gradient_walker_t *walker,
     int n, count = walker->num_stops;
     pixman_gradient_stop_t *stops = walker->stops;
 
-    static const pixman_color_t transparent_black = { 0, 0, 0, 0 };
-
     switch (walker->repeat)
     {
     case PIXMAN_REPEAT_NORMAL:
@@ -68,27 +66,12 @@ gradient_walker_reset (pixman_gradient_walker_t *walker,
 		break;
 	}
 
-	if (n == 0)
-	{
-	    left_x =  stops[count - 1].x - 0x10000;
-	    left_c = &stops[count - 1].color;
-	}
-	else
-	{
-	    left_x =  stops[n - 1].x;
-	    left_c = &stops[n - 1].color;
-	}
+	left_x =  stops[n - 1].x;
+	left_c = &stops[n - 1].color;
+
+	right_x =  stops[n].x;
+	right_c = &stops[n].color;
 
-	if (n == count)
-	{
-	    right_x =  stops[0].x + 0x10000;
-	    right_c = &stops[0].color;
-	}
-	else
-	{
-	    right_x =  stops[n].x;
-	    right_c = &stops[n].color;
-	}
 	left_x  += (pos - x);
 	right_x += (pos - x);
 	break;
@@ -100,27 +83,11 @@ gradient_walker_reset (pixman_gradient_walker_t *walker,
 		break;
 	}
 
-	if (n == 0)
-	{
-	    left_x =  INT32_MIN;
-	    left_c = &stops[0].color;
-	}
-	else
-	{
-	    left_x =  stops[n - 1].x;
-	    left_c = &stops[n - 1].color;
-	}
+	left_x =  stops[n - 1].x;
+	left_c = &stops[n - 1].color;
 
-	if (n == count)
-	{
-	    right_x =  INT32_MAX;
-	    right_c = &stops[n - 1].color;
-	}
-	else
-	{
-	    right_x =  stops[n].x;
-	    right_c = &stops[n].color;
-	}
+	right_x =  stops[n].x;
+	right_c = &stops[n].color;
 	break;
 
     case PIXMAN_REPEAT_REFLECT:
@@ -134,27 +101,11 @@ gradient_walker_reset (pixman_gradient_walker_t *walker,
 		break;
 	}
 
-	if (n == 0)
-	{
-	    left_x =  -stops[0].x;
-	    left_c = &stops[0].color;
-	}
-	else
-	{
-	    left_x =  stops[n - 1].x;
-	    left_c = &stops[n - 1].color;
-	}
+	left_x =  stops[n - 1].x;
+	left_c = &stops[n - 1].color;
 
-	if (n == count)
-	{
-	    right_x = 0x20000 - stops[n - 1].x;
-	    right_c = &stops[n - 1].color;
-	}
-	else
-	{
-	    right_x =  stops[n].x;
-	    right_c = &stops[n].color;
-	}
+	right_x =  stops[n].x;
+	right_c = &stops[n].color;
 
 	if ((int32_t)pos & 0x10000)
 	{
@@ -182,25 +133,11 @@ gradient_walker_reset (pixman_gradient_walker_t *walker,
 		break;
 	}
 
-	if (n == 0)
-	{
-	    left_x  =  INT32_MIN;
-	    right_x =  stops[0].x;
-	    left_c  = right_c = (pixman_color_t*) &transparent_black;
-	}
-	else if (n == count)
-	{
-	    left_x  = stops[n - 1].x;
-	    right_x = INT32_MAX;
-	    left_c  = right_c = (pixman_color_t*) &transparent_black;
-	}
-	else
-	{
-	    left_x  =  stops[n - 1].x;
-	    right_x =  stops[n].x;
-	    left_c  = &stops[n - 1].color;
-	    right_c = &stops[n].color;
-	}
+	left_x  =  stops[n - 1].x;
+	left_c  = &stops[n - 1].color;
+
+	right_x =  stops[n].x;
+	right_c = &stops[n].color;
     }
 
     walker->left_x   = left_x;
diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index afe587f..09d7cbc 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -31,6 +31,50 @@
 
 #include "pixman-private.h"
 
+static const pixman_color_t transparent_black = { 0, 0, 0, 0 };
+
+static void
+gradient_property_changed (pixman_image_t *image)
+{
+    gradient_t *gradient = &image->gradient;
+    int n = gradient->n_stops;
+    pixman_gradient_stop_t *stops = gradient->stops;
+    pixman_gradient_stop_t *begin = &(gradient->stops[-1]);
+    pixman_gradient_stop_t *end = &(gradient->stops[n]);
+
+    switch (gradient->common.repeat)
+    {
+    default:
+    case PIXMAN_REPEAT_NONE:
+	begin->x = INT32_MIN;
+	begin->color = transparent_black;
+	end->x = INT32_MAX;
+	end->color = transparent_black;
+	break;
+
+    case PIXMAN_REPEAT_NORMAL:
+	begin->x = stops[n - 1].x - pixman_fixed_1;
+	begin->color = stops[n - 1].color;
+	end->x = stops[0].x + pixman_fixed_1;
+	end->color = stops[0].color;
+	break;
+
+    case PIXMAN_REPEAT_REFLECT:
+	begin->x = - stops[0].x;
+	begin->color = stops[0].color;
+	end->x = pixman_int_to_fixed (2) - stops[n - 1].x;
+	end->color = stops[n - 1].color;
+	break;
+
+    case PIXMAN_REPEAT_PAD:
+	begin->x = INT32_MIN;
+	begin->color = stops[0].color;
+	end->x = INT32_MAX;
+	end->color = stops[n - 1].color;
+	break;
+    }
+}
+
 pixman_bool_t
 _pixman_init_gradient (gradient_t *                  gradient,
                        const pixman_gradient_stop_t *stops,
@@ -38,14 +82,27 @@ _pixman_init_gradient (gradient_t *                  gradient,
 {
     return_val_if_fail (n_stops > 0, FALSE);
 
-    gradient->stops = pixman_malloc_ab (n_stops, sizeof (pixman_gradient_stop_t));
+    /* We allocate two extra stops, one before the beginning of the stop list,
+     * and one after the end. These stops are initialized to whatever color
+     * would be used for positions outside the range of the stop list.
+     *
+     * This saves a bit of computation in the gradient walker.
+     *
+     * The pointer we store in the gradient_t struct still points to the
+     * first user-supplied struct, so when freeing, we will have to
+     * subtract one.
+     */
+    gradient->stops =
+	pixman_malloc_ab (n_stops + 2, sizeof (pixman_gradient_stop_t));
     if (!gradient->stops)
 	return FALSE;
 
+    gradient->stops += 1;
     memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t));
-
     gradient->n_stops = n_stops;
 
+    gradient->common.property_changed = gradient_property_changed;
+
     return TRUE;
 }
 
@@ -102,7 +159,17 @@ _pixman_image_fini (pixman_image_t *image)
 	    image->type == CONICAL)
 	{
 	    if (image->gradient.stops)
-		free (image->gradient.stops);
+	    {
+		/* See _pixman_init_gradient() for an explanation of the - 1 */
+		free (image->gradient.stops - 1);
+	    }
+
+	    /* This will trigger if someone adds a property_changed
+	     * method to the linear/radial/conical gradient overwriting
+	     * the general one.
+	     */
+	    assert (
+		image->common.property_changed == gradient_property_changed);
 	}
 
 	if (image->type == BITS && image->bits.free_me)
commit 84d6ca7c891601b019d4862a556ed98b7e6fe525
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Fri Oct 14 07:42:00 2011 -0400

    gradient walker: Correct types and fix formatting
    
    The type of pos in gradient_walker_reset() and gradient_walker_pixel()
    is pixman_fixed_48_16_t and not pixman_fixed_32_32. The types of the
    positions in the walker struct are pixman_fixed_t and not int32_t, and
    need_reset is a boolean, not an integer. The spread field should be
    called repeat and have the type pixman_repeat_t.
    
    Also fix some formatting issues, make gradient_walker_reset() static,
    and delete the pointless PIXMAN_GRADIENT_WALKER_NEED_RESET() macro.

diff --git a/pixman/pixman-gradient-walker.c b/pixman/pixman-gradient-walker.c
index dd666b4..53d0b30 100644
--- a/pixman/pixman-gradient-walker.c
+++ b/pixman/pixman-gradient-walker.c
@@ -31,7 +31,7 @@
 void
 _pixman_gradient_walker_init (pixman_gradient_walker_t *walker,
                               gradient_t *              gradient,
-                              unsigned int              spread)
+                              pixman_repeat_t		repeat)
 {
     walker->num_stops = gradient->n_stops;
     walker->stops     = gradient->stops;
@@ -42,29 +42,32 @@ _pixman_gradient_walker_init (pixman_gradient_walker_t *walker,
     walker->left_rb   = 0;
     walker->right_ag  = 0;
     walker->right_rb  = 0;
-    walker->spread    = spread;
+    walker->repeat    = repeat;
 
     walker->need_reset = TRUE;
 }
 
-void
-_pixman_gradient_walker_reset (pixman_gradient_walker_t *walker,
-                               pixman_fixed_32_32_t      pos)
+static void
+gradient_walker_reset (pixman_gradient_walker_t *walker,
+		       pixman_fixed_48_16_t      pos)
 {
     int32_t x, left_x, right_x;
-    pixman_color_t          *left_c, *right_c;
+    pixman_color_t *left_c, *right_c;
     int n, count = walker->num_stops;
-    pixman_gradient_stop_t *      stops = walker->stops;
+    pixman_gradient_stop_t *stops = walker->stops;
 
     static const pixman_color_t transparent_black = { 0, 0, 0, 0 };
 
-    switch (walker->spread)
+    switch (walker->repeat)
     {
     case PIXMAN_REPEAT_NORMAL:
 	x = (int32_t)pos & 0xFFFF;
 	for (n = 0; n < count; n++)
+	{
 	    if (x < stops[n].x)
 		break;
+	}
+
 	if (n == 0)
 	{
 	    left_x =  stops[count - 1].x - 0x10000;
@@ -92,8 +95,10 @@ _pixman_gradient_walker_reset (pixman_gradient_walker_t *walker,
 
     case PIXMAN_REPEAT_PAD:
 	for (n = 0; n < count; n++)
+	{
 	    if (pos < stops[n].x)
 		break;
+	}
 
 	if (n == 0)
 	{
@@ -122,9 +127,12 @@ _pixman_gradient_walker_reset (pixman_gradient_walker_t *walker,
 	x = (int32_t)pos & 0xFFFF;
 	if ((int32_t)pos & 0x10000)
 	    x = 0x10000 - x;
+
 	for (n = 0; n < count; n++)
+	{
 	    if (x < stops[n].x)
 		break;
+	}
 
 	if (n == 0)
 	{
@@ -169,8 +177,10 @@ _pixman_gradient_walker_reset (pixman_gradient_walker_t *walker,
 
     default:  /* REPEAT_NONE */
 	for (n = 0; n < count; n++)
+	{
 	    if (pos < stops[n].x)
 		break;
+	}
 
 	if (n == 0)
 	{
@@ -201,8 +211,8 @@ _pixman_gradient_walker_reset (pixman_gradient_walker_t *walker,
     walker->right_rb = ((right_c->red & 0xff00) << 8) | (right_c->blue >> 8);
 
     if (walker->left_x == walker->right_x                ||
-        ( walker->left_ag == walker->right_ag &&
-          walker->left_rb == walker->right_rb )   )
+        (walker->left_ag == walker->right_ag &&
+	 walker->left_rb == walker->right_rb))
     {
 	walker->stepper = 0;
     }
@@ -215,20 +225,15 @@ _pixman_gradient_walker_reset (pixman_gradient_walker_t *walker,
     walker->need_reset = FALSE;
 }
 
-#define  PIXMAN_GRADIENT_WALKER_NEED_RESET(w, x)                         \
-    ( (w)->need_reset || (x) < (w)->left_x || (x) >= (w)->right_x)
-
-
-/* the following assumes that PIXMAN_GRADIENT_WALKER_NEED_RESET(w,x) is FALSE */
 uint32_t
 _pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker,
-                               pixman_fixed_32_32_t      x)
+                               pixman_fixed_48_16_t      x)
 {
     int dist, idist;
     uint32_t t1, t2, a, color;
 
-    if (PIXMAN_GRADIENT_WALKER_NEED_RESET (walker, x))
-	_pixman_gradient_walker_reset (walker, x);
+    if (walker->need_reset || x < walker->left_x || x >= walker->right_x)
+	gradient_walker_reset (walker, x);
 
     dist  = ((int)(x - walker->left_x) * walker->stepper) >> 16;
     idist = 256 - dist;
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index cbd48f3..1443bfb 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -299,29 +299,29 @@ typedef struct
     uint32_t                left_rb;
     uint32_t                right_ag;
     uint32_t                right_rb;
-    int32_t                 left_x;
-    int32_t                 right_x;
-    int32_t                 stepper;
+    pixman_fixed_t	    left_x;
+    pixman_fixed_t          right_x;
+    pixman_fixed_t          stepper;
 
     pixman_gradient_stop_t *stops;
     int                     num_stops;
-    unsigned int            spread;
+    pixman_repeat_t	    repeat;
 
-    int                     need_reset;
+    pixman_bool_t           need_reset;
 } pixman_gradient_walker_t;
 
 void
 _pixman_gradient_walker_init (pixman_gradient_walker_t *walker,
                               gradient_t *              gradient,
-                              unsigned int              spread);
+			      pixman_repeat_t           repeat);
 
 void
 _pixman_gradient_walker_reset (pixman_gradient_walker_t *walker,
-                               pixman_fixed_32_32_t      pos);
+                               pixman_fixed_48_16_t      pos);
 
 uint32_t
 _pixman_gradient_walker_pixel (pixman_gradient_walker_t *walker,
-                               pixman_fixed_32_32_t      x);
+                               pixman_fixed_48_16_t      x);
 
 /*
  * Edges
commit ace225b53dee88d134753ac901f26ba3db6781da
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Tue Oct 11 16:12:24 2011 -0400

    Add stable release / development snapshot to draft release notes
    
    This will hopefully serve as a reminder to me that I should put this
    information in the release notes.

diff --git a/Makefile.am b/Makefile.am
index ff87e26..df8677a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -87,6 +87,8 @@ release-upload: release-check $(tar_gz) $(tar_bz2) $(sha1_tgz) $(sha1_tbz2) $(md
 	scp $(tar_gz) $(tar_bz2) $(RELEASE_XORG_HOST):$(RELEASE_XORG_DIR)
 	ssh $(RELEASE_CAIRO_HOST) "rm -f $(RELEASE_CAIRO_DIR)/LATEST-$(PACKAGE)-[0-9]* && ln -s $(tar_gz) $(RELEASE_CAIRO_DIR)/LATEST-$(PACKAGE)-$(VERSION)"
 
+RELEASE_TYPE = $$(if test "x$(PIXMAN_VERSION_MINOR)" = "x$$(echo "$(PIXMAN_VERSION_MINOR)/2*2" | bc)" ; then echo "stable release in the" ; else echo "development snapshot leading up to a stable"; fi)
+
 release-publish-message: $(HASHFILES) ensure-prev
 	@echo "Please follow the instructions in RELEASING to push stuff out and"
 	@echo "send out the announcement mails.  Here is the excerpt you need:"
@@ -94,7 +96,7 @@ release-publish-message: $(HASHFILES) ensure-prev
 	@echo "Lists:  $(RELEASE_ANNOUNCE_LIST)"
 	@echo "Subject: [ANNOUNCE] $(PACKAGE) release $(VERSION) now available"
 	@echo "============================== CUT HERE =============================="
-	@echo "A new $(PACKAGE) release $(VERSION) is now available"
+	@echo "A new $(PACKAGE) release $(VERSION) is now available. This is a $(RELEASE_TYPE)"
 	@echo ""
 	@echo "tar.gz:"
 	@echo "	$(RELEASE_CAIRO_URL)/$(tar_gz)"


More information about the xorg-commit mailing list