gtk-css-engine r119 - in trunk: . libccd/ccd themes/gtk-css-test/gtk-2.0



Author: robsta
Date: Mon Sep 22 13:14:44 2008
New Revision: 119
URL: http://svn.gnome.org/viewvc/gtk-css-engine?rev=119&view=rev

Log:
* TODO: remember some background-image standard compliancy issues.
* libccd/ccd/ccd-background.c:
* libccd/ccd/ccd-position.c:

Initial background-image support.


Modified:
   trunk/   (props changed)
   trunk/ChangeLog
   trunk/TODO
   trunk/libccd/ccd/ccd-background.c
   trunk/libccd/ccd/ccd-position.c
   trunk/themes/gtk-css-test/gtk-2.0/styles.css

Modified: trunk/TODO
==============================================================================
--- trunk/TODO	(original)
+++ trunk/TODO	Mon Sep 22 13:14:44 2008
@@ -7,6 +7,9 @@
 
 Features:
 * Background image: repeating, tiling, position.
+* Add a `fixup' stage when the stylesheet is loaded, handle things like 
+  single `background-size: <length>;' there. Possibly piggy-back on the
+  stylesheet reading/walking API.
 * Border images, c.f. http://ejohn.org/blog/border-image-in-firefox/
 * Unit tests.
 * Test using the theme torturer.

Modified: trunk/libccd/ccd/ccd-background.c
==============================================================================
--- trunk/libccd/ccd/ccd-background.c	(original)
+++ trunk/libccd/ccd/ccd-background.c	Mon Sep 22 13:14:44 2008
@@ -17,6 +17,7 @@
  * MA 02110-1301, USA.
  */
 
+#include <math.h>
 #include <string.h>
 #include "ccd-background.h"
 
@@ -300,17 +301,14 @@
 
 static cairo_pattern_t *
 create_pattern (ccd_background_image_t const	*bg_image,
-		ccd_background_size_t const	*bg_size,
 		double				 width,
-		double				 height)
+		double				 height,
+		double				 tile_width,
+		double				 tile_height)
 {
 	cairo_t		*cr;
 	cairo_surface_t	*surface;
 	cairo_status_t	 status;
-	double		 tile_width;
-	double		 tile_height;
-	double		 dx;
-	double		 dy;
 	cairo_pattern_t *pattern;
 
 	/* Setup. */
@@ -325,67 +323,95 @@
 						CAIRO_CONTENT_COLOR_ALPHA,
 						width, height);
 	cr = cairo_create (surface);
-	cairo_surface_destroy (surface), surface = NULL;
 
 	/* Drawing. */
-	tile_width = ccd_position_get_horizontal (&bg_size->width, 
-						  width, height,
-						  bg_image->image.width,
-						  bg_image->image.height);
-	tile_height = ccd_position_get_horizontal (&bg_size->height,
-						   width, height,
-						   bg_image->image.width,
-						   bg_image->image.height);
-	dx = tile_width / bg_image->image.width;
-	dy = tile_height / bg_image->image.height;
-	cairo_scale (cr, dx, dy);
-
 	cairo_pattern_set_extend (bg_image->image.pattern, CAIRO_EXTEND_REPEAT);
 	cairo_set_source (cr, bg_image->image.pattern);
 	cairo_paint (cr);
 
 	/* Cleanup. */
-	pattern = cairo_get_source (cr);
-	cairo_pattern_reference (pattern);
+	pattern = cairo_pattern_create_for_surface (surface);
 	cairo_destroy (cr), cr = NULL;
+	cairo_surface_destroy (surface), surface = NULL;
 
 	return pattern;
 }
 
 static void
 repeat (ccd_background_image_t const	*bg_image,
-	ccd_background_size_t const	*bg_size,
 	cairo_t				*cr,
-	int32_t				 x,
-	int32_t				 y, 
 	int32_t				 width,
-	int32_t				 height)
-{
-
+	int32_t				 height,
+	double				 tile_width,
+	double				 tile_height)
+{
+	cairo_pattern_t	*pattern;
+
+	/* Create pattern for (width + tile_width, height + tile_height)
+	 * so we can account for `background-position'. */
+	pattern = create_pattern (bg_image,
+				  width + tile_width, height + tile_height,
+				  tile_width, tile_height);
+
+	cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
+	cairo_set_source (cr, pattern);
+	cairo_pattern_destroy (pattern), pattern = NULL;
+	cairo_fill_preserve (cr);
 }
 
 static void
 repeat_x (ccd_background_image_t const	*bg_image,
-	  ccd_background_size_t const	*bg_size,
 	  cairo_t			*cr,
-	  int32_t			 x,
-	  int32_t			 y, 
 	  int32_t			 width,
-	  int32_t			 height)
-{
-
+	  int32_t			 height,
+	  double			 tile_width,
+	  double			 tile_height)
+{
+	cairo_pattern_t	*pattern;
+
+	/* Create pattern for (width + tile_width, tile_height)
+	 * so we can account for `background-position'. */
+	pattern = create_pattern (bg_image,
+				  width + tile_width, tile_height,
+				  tile_width, tile_height);
+
+	cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
+	cairo_set_source (cr, pattern);
+	cairo_pattern_destroy (pattern), pattern = NULL;
+	cairo_fill_preserve (cr);
 }
 
 static void
 repeat_y (ccd_background_image_t const	*bg_image,
-	  ccd_background_size_t const	*bg_size,
 	  cairo_t			*cr,
-	  int32_t			 x,
-	  int32_t			 y, 
 	  int32_t			 width,
-	  int32_t			 height)
-{
+	  int32_t			 height,
+	  double			 tile_width,
+	  double			 tile_height)
+{
+	cairo_pattern_t	*pattern;
+
+	/* Create pattern for (tile_width, height + tile_height)
+	 * so we can account for `background-position'. */
+	pattern = create_pattern (bg_image,
+				  tile_width, height + tile_height,
+				  tile_width, tile_height);
+
+	cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
+	cairo_set_source (cr, pattern);
+	cairo_pattern_destroy (pattern), pattern = NULL;
+	cairo_fill_preserve (cr);
+}
 
+static void
+no_repeat (ccd_background_image_t const	*bg_image,
+	   cairo_t			*cr,
+	   int32_t			 width,
+	   int32_t			 height)
+{
+	cairo_pattern_set_extend (bg_image->image.pattern, CAIRO_EXTEND_PAD);
+	cairo_set_source (cr, bg_image->image.pattern);
+	cairo_fill_preserve (cr);
 }
 
 /**
@@ -430,27 +456,71 @@
 
 	if (ccd_property_is_set (bg_image->spec)) {
 
-		cairo_translate (cr, x, y);
-#if 0
+		double tile_width;
+		double tile_height;
+		double xoff;
+		double yoff;
+
+		tile_width = ccd_position_get_horizontal (&bg_size->width, 
+							  width, height,
+							  bg_image->image.width,
+							  bg_image->image.height);
+		tile_height = ccd_position_get_vertical (&bg_size->height,
+							 width, height,
+							 bg_image->image.width,
+							 bg_image->image.height);
+
+		xoff = ccd_position_get_horizontal (&bg_position->hpos,
+						    width, height,
+						    tile_width, tile_height);
+		yoff = ccd_position_get_vertical (&bg_position->vpos,
+						  width, height,
+						  tile_width, tile_height);
+
+		dx = tile_width / bg_image->image.width;
+		dy = tile_height / bg_image->image.height;
+
 		switch (bg_repeat->repeat) {
 		case CCD_BACKGROUND_REPEAT:
-			repeat (bg_image, bg_size, cr, x, y, width, height);
+			/* Normalise offsets, we don't create an infinite
+			 * background pattern. */
+			xoff = fmod (xoff, tile_width) - tile_width;
+			yoff = fmod (yoff, tile_height) - tile_height;
+			cairo_translate (cr, x + lround (xoff), y + lround (yoff));
+			cairo_scale (cr, dx, dy);
+			repeat (bg_image, cr, width / dx, height / dy,
+				tile_width / dx, tile_height / dy);
 			break;
 		case CCD_BACKGROUND_REPEAT_X:
-			repeat_x (bg_image, bg_size, cr, x, y, width, height);
+			/* Normalise vertical offset, we don't create an infinite
+			 * background pattern. */
+			xoff = fmod (xoff, tile_width) - tile_width;
+			cairo_translate (cr, x + lround (xoff), y + lround (yoff));
+			cairo_scale (cr, dx, dy);
+			repeat_x (bg_image, cr, width / dx, height / dy,
+				  tile_width / dx, tile_height / dy);
 			break;
 		case CCD_BACKGROUND_REPEAT_Y:
-			repeat_y (bg_image, bg_size, cr, x, y, width, height);
+			/* Normalise horizontal offset, we don't create an infinite
+			 * background pattern. */
+			yoff = fmod (yoff, tile_height) - tile_height;
+			cairo_translate (cr, x + lround (xoff), y + lround (yoff));
+			cairo_scale (cr, dx, dy);
+			repeat_y (bg_image, cr, width / dx, height / dy,
+				  tile_width / dx, tile_height / dy);
 			break;
 		case CCD_BACKGROUND_NO_REPEAT:
-			/* TODO */
+			cairo_translate (cr, x + lround (xoff), y + lround (yoff));
+			cairo_scale (cr, dx, dy);
+			no_repeat (bg_image, cr, width / dx, height / dy);
 			break;
 		default:
 			g_assert_not_reached ();
 			/* Need some code here when building w/o assertions. */
 			break;
 		}
-#endif
+
+/*
 		dx = (double) width / bg_image->image.width;
 		dy = (double) height / bg_image->image.height;
 		cairo_scale (cr, dx, dy);
@@ -460,6 +530,7 @@
 
 		cairo_set_source (cr, bg_image->image.pattern);
 		cairo_fill_preserve (cr);
+*/
 
 		status = cairo_status (cr);
 		if (status != CAIRO_STATUS_SUCCESS) {

Modified: trunk/libccd/ccd/ccd-position.c
==============================================================================
--- trunk/libccd/ccd/ccd-position.c	(original)
+++ trunk/libccd/ccd/ccd-position.c	Mon Sep 22 13:14:44 2008
@@ -38,20 +38,24 @@
 bool
 ccd_position_parse (ccd_position_t	 *self,
 		    uint32_t		  flags,
-		    CRTerm const	**value)
+		    CRTerm const	**values)
 {
 	char const *name;
 
-	switch ((*value)->type) {
+	if (!*values) {
+		return false;
+	}
+
+	switch ((*values)->type) {
 	case TERM_IDENT:
-		name = (char const *) cr_string_peek_raw_str ((*value)->content.str);
+		name = (char const *) cr_string_peek_raw_str ((*values)->content.str);
 		for (unsigned int i = 0; i < G_N_ELEMENTS (_position_map); i++) {
 			if (_position_map[i].type & flags &&
 			    0 == g_ascii_strcasecmp (_position_map[i].name, name)) {
 				if (_position_map[i].percentage > -1) {
 					self->type = CCD_POSITION_PERCENTAGE;
 					self->value = _position_map[i].percentage;
-					*value = (*value)->next;
+					*values = (*values)->next;
 				} else {
 					self->type =  _position_map[i].type;
 					self->value = -1;
@@ -62,16 +66,16 @@
 		break;
 	case TERM_NUMBER:
 		if (CCD_POSITION_PERCENTAGE & flags &&
-		    NUM_PERCENTAGE == (*value)->content.num->type) {
+		    NUM_PERCENTAGE == (*values)->content.num->type) {
 			self->type = CCD_POSITION_PERCENTAGE;
-			self->value = (*value)->content.num->val;
-			*value = (*value)->next;
+			self->value = (*values)->content.num->val;
+			*values = (*values)->next;
 			return true;
 		} else if (CCD_POSITION_LENGTH & flags &&
-			   NUM_GENERIC == (*value)->content.num->type) {
+			   NUM_GENERIC == (*values)->content.num->type) {
 			self->type = CCD_POSITION_LENGTH;
-			self->value = (*value)->content.num->val;
-			*value = (*value)->next;
+			self->value = (*values)->content.num->val;
+			*values = (*values)->next;
 			return true;
 		} else {
 			return false;
@@ -97,13 +101,13 @@
 	/* Try to use full width. */
 	*y = extent_x * height / width;
 	if (*y <= extent_y) {
-		*x = width;
+		*x = extent_x;
 		return;
 	}
 
 	/* Use full height. */
 	*x = extent_y * width / height;
-	*y = height;
+	*y = extent_y;
 }
 
 static void
@@ -117,13 +121,13 @@
 	/* Try to use full width. */
 	*y = extent_x * height / width;
 	if (*y >= extent_y) {
-		*x = width;
+		*x = extent_x;
 		return;
 	}
 
 	/* Use full height. */
 	*x = extent_y * width / height;
-	*y = height;
+	*y = extent_y;
 }
 
 double
@@ -140,7 +144,7 @@
 	case CCD_POSITION_LENGTH:
 		return self->value;
 	case CCD_POSITION_PERCENTAGE:
-		return self->value * extent_x / 100.;
+		return (self->value * extent_x / 100.) - (width / 2.);
 	case CCD_POSITION_CONTAIN:
 		contain (extent_x, extent_y, width, height, &x, &y);
 		return x;
@@ -172,7 +176,7 @@
 	case CCD_POSITION_LENGTH:
 		return self->value;
 	case CCD_POSITION_PERCENTAGE:
-		return self->value * extent_y / 100.;
+		return (self->value * extent_y / 100.) - (height / 2.);
 	case CCD_POSITION_CONTAIN:
 		contain (extent_x, extent_y, width, height, &x, &y);
 		return y;

Modified: trunk/themes/gtk-css-test/gtk-2.0/styles.css
==============================================================================
--- trunk/themes/gtk-css-test/gtk-2.0/styles.css	(original)
+++ trunk/themes/gtk-css-test/gtk-2.0/styles.css	Mon Sep 22 13:14:44 2008
@@ -103,10 +103,11 @@
 }
 */
 
+/*
 check {
 	background-image: url(nordic.svg#CheckMarkOn.Shape);
 }
-
+*/
 extension {
 	background: khaki;
 	border: 1px solid black;
@@ -118,6 +119,31 @@
 	border-radius: 60;
 }
 
+box[gap=top] {/*
+	background-image: url(foo.png);
+	background-repeat: repeat;
+	background-size: 16 16;
+*/}
+
+box[gap=bottom] {
+	background-image: url(foo.png);
+	background-repeat: repeat-x;
+	background-position: center;
+	background-size: cover;
+}
+
+box[gap=left] {/*
+	background-image: url(foo.png);
+	background-repeat: repeat-y;
+*/}
+
+box[gap=right] {/*
+	background-image: url(foo.png);
+	background-repeat: no-repeat;
+	background-position: 32% 32%;
+	background-size: 100% 100%;
+*/}
+
 shadow {
 	background: khaki;
 	border: 1px solid black;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]