gtk-css-engine r115 - in trunk: . libccd/ccd



Author: robsta
Date: Thu Sep 18 16:27:30 2008
New Revision: 115
URL: http://svn.gnome.org/viewvc/gtk-css-engine?rev=115&view=rev

Log:
* libccd/ccd/ccd-background.c:
* libccd/ccd/ccd-position.c:
* libccd/ccd/ccd-position.h:
Background tile creation. Not hooked up yet.


Modified:
   trunk/   (props changed)
   trunk/ChangeLog
   trunk/libccd/ccd/ccd-background.c
   trunk/libccd/ccd/ccd-position.c
   trunk/libccd/ccd/ccd-position.h

Modified: trunk/libccd/ccd/ccd-background.c
==============================================================================
--- trunk/libccd/ccd/ccd-background.c	(original)
+++ trunk/libccd/ccd/ccd-background.c	Thu Sep 18 16:27:30 2008
@@ -232,10 +232,37 @@
 
 	if (0 == strcmp ("background", property)) {
 
-		/* TODO: also support `background-size' here. */
-		ret |= bg_color_parse (&self->bg_color, &values);
-		ret |= bg_image_parse (&self->bg_image, &values);
-		return ret;
+		/* TODO: also support `background-size' here, but let's stick
+		 * to CSS2 for now. */
+		ret = bg_color_parse (&self->bg_color, &values);
+		if (ret && values == NULL)
+			return true;
+		else if (!ret)
+			return false;
+
+		ret = bg_image_parse (&self->bg_image, &values);
+		if (ret && values == NULL)
+			return true;
+		else if (!ret)
+			return false;
+
+		ret = bg_repeat_parse (&self->bg_repeat, &values);
+		if (ret && values == NULL)
+			return true;
+		else if (!ret)
+			return false;
+
+		ret = bg_attachment_parse (&self->bg_attachment, &values);
+		if (ret && values == NULL)
+			return true;
+		else if (!ret)
+			return false;
+
+		ret = bg_position_parse (&self->bg_position, &values);
+		if (ret && values == NULL)
+			return true;
+		else if (!ret)
+			return false;
 	}
 
 	if (0 == strcmp ("background-attachment", property)) {
@@ -271,6 +298,118 @@
 	return false;
 }
 
+#if 0
+/*
+ * x, y are relative to the previous tile.
+ */
+static void
+draw_tile (cairo_t	*cr,
+	   double	 x,
+	   double	 y)
+{
+	cairo_translate (cr, x, y);
+	cairo_fill (cr);
+}
+
+/*
+ * y translation must already be set up when calling this.
+ */
+static void
+repeat_x (cairo_t	*cr,
+	  double	 x,
+	  double	 width,
+	  double	 tile_width)
+{
+	cairo_translate (cr, x - tile_width, 0);
+	for (double xoff = 0; xoff < width; xoff += tile_width) {
+		draw_tile (cr, tile_width, 0);
+	}
+}
+/*
+ * x translation must already be set up when calling this.
+ */
+static void
+repeat_y (cairo_t	*cr,
+	  double	 y,
+	  double	 height,
+	  double	 tile_height)
+{
+	cairo_translate (cr, 0, y - tile_height);
+	for (double yoff = 0; yoff < height; yoff += tile_height) {
+		draw_tile (cr, 0, tile_height);
+	}
+}
+#endif
+
+/*
+ * TODO: find out whether liberal use of cairo_create()/cairo_destroy()
+ * causes performance problems.
+ */
+static cairo_pattern_t *
+create_pattern (ccd_background_image_t const	*bg_image,
+		ccd_background_size_t const	*bg_size,
+		double				 width,
+		double				 height)
+{
+	cairo_t		*cr;
+	cairo_pattern_t *tile;
+	cairo_surface_t	*surface;
+	double		 intrinsic_width;
+	double		 intrinsic_height;
+	double		 tile_width;
+	double		 tile_height;
+	double		 dx;
+	double		 dy;
+	cairo_pattern_t *pattern;
+
+	/* Create a single tile of appropriate size. */
+	intrinsic_width = cairo_image_surface_get_width (bg_image->image.surface);
+	intrinsic_height = cairo_image_surface_get_height (bg_image->image.surface);
+	tile_width = ccd_position_get_horizontal (&bg_size->width, 
+						  width, height,
+						  intrinsic_width,
+						  intrinsic_height);
+	tile_height = ccd_position_get_horizontal (&bg_size->height,
+						   width, height,
+						   intrinsic_width,
+						   intrinsic_height);
+	surface = cairo_surface_create_similar (bg_image->image.surface,
+						CAIRO_CONTENT_COLOR_ALPHA,
+						tile_width, tile_height);
+	cr = cairo_create (surface);
+	cairo_surface_destroy (surface), surface = NULL;
+
+	dx = tile_width / intrinsic_width;
+	dy = tile_height / intrinsic_height;
+	cairo_scale (cr, dx, dy);
+	cairo_set_source_surface (cr, bg_image->image.surface, 0, 0);
+	tile = cairo_get_source (cr);
+	cairo_pattern_set_extend (tile, CAIRO_EXTEND_PAD);
+	cairo_paint (cr);
+	cairo_pattern_reference (tile);
+	cairo_destroy (cr), cr = NULL;
+
+	/* Shortcut if we only want a single tile anyways. */
+	if (tile_width >= width && tile_height >= height)
+		return tile;
+
+	/* Create pattern. */
+	surface = cairo_surface_create_similar (bg_image->image.surface,
+						CAIRO_CONTENT_COLOR_ALPHA,
+						width, height);
+	cr = cairo_create (surface);
+	cairo_surface_destroy (surface), surface = NULL;
+	cairo_pattern_set_extend (tile, CAIRO_EXTEND_REPEAT);
+	cairo_set_source (cr, tile);
+	cairo_pattern_destroy (tile), tile = NULL;
+	cairo_paint (cr);	
+	pattern = cairo_get_source (cr);
+	cairo_pattern_reference (pattern);
+	cairo_destroy (cr), cr = NULL;
+
+	return pattern;
+}
+
 /**
  * ccd_background_fill:
  *

Modified: trunk/libccd/ccd/ccd-position.c
==============================================================================
--- trunk/libccd/ccd/ccd-position.c	(original)
+++ trunk/libccd/ccd/ccd-position.c	Thu Sep 18 16:27:30 2008
@@ -21,7 +21,7 @@
 
 static const struct {
 	char const		*name;
-	ccd_position_flags_t	 match;
+	ccd_position_type_t	 type;
 	const double		 percentage;
 } _position_map[] = {
   { "left",	CCD_POSITION_LEFT,	0	},
@@ -45,24 +45,29 @@
 	switch ((*value)->type) {
 	case TERM_IDENT:
 		name = (char const *) cr_string_peek_raw_str ((*value)->content.str);
-		for (int i = 0; i < G_N_ELEMENTS (_position_map); i++) {
-			if (_position_map[i].match & flags &&
+		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)) {
-				self->type = CCD_POSITION_PERCENTAGE;
-				self->value = _position_map[i].percentage;
-				*value = (*value)->next;
+				if (_position_map[i].percentage > -1) {
+					self->type = CCD_POSITION_PERCENTAGE;
+					self->value = _position_map[i].percentage;
+					*value = (*value)->next;
+				} else {
+					self->type =  _position_map[i].type;
+					self->value = -1;
+				}
 				return true;
 			}
 		}
 		break;
 	case TERM_NUMBER:
-		if (CCD_POSITION_FLAG_PERCENTAGE & flags &&
+		if (CCD_POSITION_PERCENTAGE & flags &&
 		    NUM_PERCENTAGE == (*value)->content.num->type) {
 			self->type = CCD_POSITION_PERCENTAGE;
 			self->value = (*value)->content.num->val;
 			*value = (*value)->next;
 			return true;
-		} else if (CCD_POSITION_FLAG_LENGTH & flags &&
+		} else if (CCD_POSITION_LENGTH & flags &&
 			   NUM_GENERIC == (*value)->content.num->type) {
 			self->type = CCD_POSITION_LENGTH;
 			self->value = (*value)->content.num->val;
@@ -81,30 +86,108 @@
 	return false;
 }
 
-double
-ccd_position_get_offset (ccd_position_t	*self,
-			 double		 extent,
-			 double		 size)
+static void
+contain (double	 extent_x,
+	 double	 extent_y,
+	 double	 width,
+	 double	 height,
+	 double	*x,
+	 double	*y)
 {
-	double ret;
+	/* Try to use full width. */
+	*y = extent_x * height / width;
+	if (*y <= extent_y) {
+		*x = width;
+		return;
+	}
+
+	/* Use full height. */
+	*x = extent_y * width / height;
+	*y = height;
+}
+
+static void
+cover (double	 extent_x,
+       double	 extent_y,
+       double	 width,
+       double	 height,
+       double	*x,
+       double	*y)
+{
+	/* Try to use full width. */
+	*y = extent_x * height / width;
+	if (*y >= extent_y) {
+		*x = width;
+		return;
+	}
 
-	g_return_val_if_fail (self, 0);
+	/* Use full height. */
+	*x = extent_y * width / height;
+	*y = height;
+}
+
+double
+ccd_position_get_horizontal (ccd_position_t const	*self,
+			     double			 extent_x,
+			     double			 extent_y,
+			     double			 width,
+			     double			 height)
+{
+	double x;
+	double y;
 
-	ret = 0;
 	switch (self->type) {
+	case CCD_POSITION_LENGTH:
+		return self->value;
 	case CCD_POSITION_PERCENTAGE:
-		ret = (extent - size) * self->value / 100.;
-		break;
+		return self->value * extent_x / 100.;
+	case CCD_POSITION_CONTAIN:
+		contain (extent_x, extent_y, width, height, &x, &y);
+		return x;
+	case CCD_POSITION_COVER:
+		cover (extent_x, extent_y, width, height, &x, &y);
+		return x;
+	case CCD_POSITION_AUTO:
+		return width;
+	default:
+		g_assert_not_reached ();
+		/* Need some code here when building w/o assertions. */
+		return 0;
+	}
+
+	return 0;
+}
+
+double
+ccd_position_get_vertical (ccd_position_t const	*self,
+			   double		 extent_x,
+			   double		 extent_y,
+			   double		 width,
+			   double		 height)
+{
+	double x;
+	double y;
+
+	switch (self->type) {
 	case CCD_POSITION_LENGTH:
-		ret = size;
-		break;
+		return self->value;
+	case CCD_POSITION_PERCENTAGE:
+		return self->value * extent_y / 100.;
+	case CCD_POSITION_CONTAIN:
+		contain (extent_x, extent_y, width, height, &x, &y);
+		return y;
+	case CCD_POSITION_COVER:
+		cover (extent_x, extent_y, width, height, &x, &y);
+		return y;
+	case CCD_POSITION_AUTO:
+		return height;
 	default:
 		g_assert_not_reached ();
 		/* Need some code here when building w/o assertions. */
 		return 0;
 	}
 
-	return ret;
+	return 0;
 }
 
 #ifdef CCD_DEBUG

Modified: trunk/libccd/ccd/ccd-position.h
==============================================================================
--- trunk/libccd/ccd/ccd-position.h	(original)
+++ trunk/libccd/ccd/ccd-position.h	Thu Sep 18 16:27:30 2008
@@ -31,11 +31,11 @@
 typedef enum {
 	/* Remember to revisit all locations where a mask is used when it's 
 	 * being extended. */
-	CCD_POSITION_FLAG_LENGTH	= 1 << 0,
-	CCD_POSITION_FLAG_PERCENTAGE	= 1 << 1,
+	CCD_POSITION_LENGTH		= 1 << 0,
+	CCD_POSITION_PERCENTAGE		= 1 << 1,
 
-	CCD_POSITION_MASK_NUMERIC	= CCD_POSITION_FLAG_LENGTH | 
-					  CCD_POSITION_FLAG_PERCENTAGE,
+	CCD_POSITION_MASK_NUMERIC	= CCD_POSITION_LENGTH | 
+					  CCD_POSITION_PERCENTAGE,
 
 	CCD_POSITION_LEFT		= 1 << 2,
 	CCD_POSITION_TOP		= 1 << 3,
@@ -57,11 +57,6 @@
 	CCD_POSITION_MASK_AUTO		= CCD_POSITION_AUTO |
 					  CCD_POSITION_CONTAIN |
 					  CCD_POSITION_COVER
-} ccd_position_flags_t;
-
-typedef enum {
-	CCD_POSITION_PERCENTAGE = 0,
-	CCD_POSITION_LENGTH
 } ccd_position_type_t;
 
 typedef struct {
@@ -69,10 +64,16 @@
 	double			value;
 } ccd_position_t;
 
-bool ccd_position_parse	(ccd_position_t *self, uint32_t flags, CRTerm const **value);
+bool ccd_position_parse	(ccd_position_t *self, uint32_t flags, 
+			 CRTerm const **value);
 
-double ccd_position_get_offset (ccd_position_t *self,
-				double extent, double size);
+double ccd_position_get_horizontal (ccd_position_t const *self,
+				    double extent_x, double extent_y,
+				    double width, double height);
+
+double ccd_position_get_vertical (ccd_position_t const *self,
+				  double extent_x, double extent_y,
+				  double width, double height);
 
 #ifdef CCD_DEBUG
 void ccd_position_dump (ccd_position_t const *self);



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