genius r735 - in trunk: . gtkextra



Author: jirka
Date: Wed Feb 25 04:06:56 2009
New Revision: 735
URL: http://svn.gnome.org/viewvc/genius?rev=735&view=rev

Log:
Tue Feb 24 22:05:41 2009  Jiri (George) Lebl <jirka 5z com>

	* gtkextra/gtkplotdata.c, gtkextra/gtkplotgdk.c: Move the line
	  clipping code from the GDK backend to the plotdata.  Replace
	  the one relevant draw_lines call with the new one.  I wonder
	  if this should be done in more places.  This is a mess!
	  There are still bugs if you zoom in way too much.  Not quite sure
	  what the bug is.  We may need to actually move the endpoints 
	  of the line.  This fixes broken EPS/PS export and printing
	  when zoomed in to a slopefield/vectorfield/parametric graph.



Modified:
   trunk/ChangeLog
   trunk/gtkextra/gtkplotdata.c
   trunk/gtkextra/gtkplotgdk.c

Modified: trunk/gtkextra/gtkplotdata.c
==============================================================================
--- trunk/gtkextra/gtkplotdata.c	(original)
+++ trunk/gtkextra/gtkplotdata.c	Wed Feb 25 04:06:56 2009
@@ -3548,6 +3548,162 @@
   if(plot->clip_data && !GTK_IS_PLOT3D(plot)) gtk_plot_pc_clip(plot->pc, NULL);
 }
 
+static gboolean
+line_on_screen (double x1, double y1, double x2, double y2,
+		int left, int right,
+	       	int top, int bottom)
+{
+	if ( (x1 >= left && y1 >= top &&
+	      x1 <= right && y1 <= bottom) ||
+	     (x2 >= left && y2 >= top &&
+	      x2 <= right && y2 <= bottom))
+		return TRUE;
+
+	if ( (x1 < left && x2 < left) ||
+	     (x1 > right && x2 > right) ||
+	     (y1 < top && y2 < top) ||
+	     (y1 > bottom && y2 > bottom) )
+		return FALSE; /* obvious */
+
+	if (x1 == x2) {
+		/* in this case it must be true that y is in range, */
+		return TRUE;
+	} else if (x1 > x2) {
+		int t = x1;
+		x1 = x2;
+		x2 = t;
+
+		t = y1;
+		y1 = y2;
+		y2 = t;
+	}
+
+	if (x1 < left) {
+		/* Move line so that x1 = left */
+		double t = (left-x2) / (double)(x1-x2);
+		x1 = t*x1 + (1-t)*x2;
+		y1 = t*y1 + (1-t)*y2;
+
+		/* note that x2 > left, so t < 1 !*/
+
+		if (y1 >= top || y1 <= bottom)
+			return TRUE;
+
+		if (y1 < top) {
+			if (y2 < top)
+				return FALSE;
+
+			/* Move line so that y1 = top */
+			t = (top-y2) / (double)(y1-y2);
+			x1 = t*x1 + (1-t)*x2;
+			y1 = t*y1 + (1-t)*y2;
+
+			/* note that y2 > top, so 0 < t < 1 !*/
+
+			if (x1 <= right)
+				return TRUE;
+			else
+				return FALSE;
+		} else {
+			if (y2 > bottom)
+				return FALSE;
+
+			/* Move line so that y1 = bottom */
+			t = (bottom-y2) / (double)(y1-y2);
+			x1 = t*x1 + (1-t)*x2;
+			y1 = t*y1 + (1-t)*y2;
+
+			/* note that y2 < bottom, so 0 < t < 1 !*/
+
+			if (x1 <= right)
+				return TRUE;
+			else
+				return FALSE;
+		}
+
+	}
+
+	/* must be that x1 <= right and y1 < top or y1 > bottom */
+
+	if (y1 < 0) {
+		/* Move line so that y1 = top */
+		double t = (top-y2) / (double)(y1-y2);
+		x1 = t*x1 + (1-t)*x2;
+		y1 = t*y1 + (1-t)*y2;
+
+		/* y2 >= top so 0 < t < 1 */
+
+		if (x1 <= right)
+			return TRUE;
+		else
+			return FALSE;
+	} else {
+		/* Move line so that y1 = bottom */
+		double t = (bottom-y2) / (double)(y1-y2);
+		x1 = t*x1 + (1-t)*x2;
+		y1 = t*y1 + (1-t)*y2;
+
+		/* y2 < bottom so 0 < t < 1 */
+
+		if (x1 <= right)
+			return TRUE;
+		else
+			return FALSE;
+	}
+}
+
+/*
+ * FIXME:
+ * There is some loss when the line ends are way too far in either direction.
+ * Perhaps roundoff error?  Above?
+ *
+ * But this works better than the alternative of failing completely.
+ */
+static void
+gtk_plot_data_draw_lines (GtkPlotData *dataset,
+			  GtkPlotPoint *points,
+			  int numpoints)
+{
+  GtkPlot *plot;
+  GtkWidget *widget;
+  int beg = 0;
+  int i, j;
+  int lx1, lx2, ly1, ly2;
+  gboolean last_off = TRUE;
+
+  plot = dataset->plot;
+  widget = GTK_WIDGET (plot);
+
+  lx1 = widget->allocation.x;
+  lx2 = lx1 + widget->allocation.width;
+  ly1 = widget->allocation.y;
+  ly2 = ly1 + widget->allocation.height;
+
+  j = 0;
+  for(i = 0; i < numpoints; i++){
+    if (j > 0 && ! line_on_screen (points[i-1].x,
+				   points[i-1].y,
+				   points[i].x,
+				   points[i].y,
+				   lx1, lx2, ly1, ly2)) {
+	    if (j > 1) {
+		    gtk_plot_pc_draw_lines (plot->pc, &(points[beg]), j);
+	    }
+	    last_off = TRUE;
+	    beg = i;
+	    j = 1;
+	    continue;
+    } else {
+	    last_off = FALSE;
+    }
+
+    j++;
+  }
+
+  if ( ! last_off)
+	  gtk_plot_pc_draw_lines (plot->pc, &(points[beg]), j);
+}
+
 static void
 gtk_plot_data_draw_errbars(GtkPlotData *dataset,
                            gdouble x, gdouble y, gdouble z,
@@ -3847,10 +4003,10 @@
   plot = dataset->plot;
   widget = GTK_WIDGET(plot);
 
-  area.x = GTK_WIDGET(plot)->allocation.x;
-  area.y = GTK_WIDGET(plot)->allocation.y;
-  area.width = GTK_WIDGET(plot)->allocation.width;
-  area.height = GTK_WIDGET(plot)->allocation.height;
+  area.x = widget->allocation.x;
+  area.y = widget->allocation.y;
+  area.width = widget->allocation.width;
+  area.height = widget->allocation.height;
 
   clip_area.x = area.x + roundint(plot->x * widget->allocation.width);
   clip_area.y = area.y + roundint(plot->y * widget->allocation.height);
@@ -4058,7 +4214,11 @@
       gtk_plot_pc_draw_polygon(plot->pc, TRUE, points, num_points);
     }
   } else {
-    gtk_plot_pc_draw_lines(plot->pc, points, num_points);
+    /* This function clips offscreen parts, which we need, probably
+     * in more places than here, but I'm not sure if it is necessarily safe
+     * elsewhere
+     * -Jiri */
+    gtk_plot_data_draw_lines(dataset, points, num_points);
   }
 
   if(plot->clip_data && !GTK_IS_PLOT3D(plot)) gtk_plot_pc_clip(plot->pc, NULL);

Modified: trunk/gtkextra/gtkplotgdk.c
==============================================================================
--- trunk/gtkextra/gtkplotgdk.c	(original)
+++ trunk/gtkextra/gtkplotgdk.c	Wed Feb 25 04:06:56 2009
@@ -429,144 +429,24 @@
                 roundint(x1), roundint(y1), roundint(x2), roundint(y2));
 }
 
-static gboolean
-line_on_screen (int x1, int y1, int x2, int y2, int width, int height)
-{
-	if ( (x1 >= 0 && y1 >= 0 && x1 <= width && y1 <= height) ||
-	     (x2 >= 0 && y2 >= 0 && x2 <= width && y2 <= height))
-		return TRUE;
-
-	if ( (x1 < 0 && x2 < 0) ||
-	     (x1 > width && x2 > width) ||
-	     (y1 < 0 && y2 < 0) ||
-	     (y1 > height && y2 > height) )
-		return FALSE; /* obvious */
-
-	if (x1 == x2) {
-		/* in this case it must be true that y is in range, */
-		return TRUE;
-	} else if (x1 > x2) {
-		int t = x1;
-		x1 = x2;
-		x2 = t;
-
-		t = y1;
-		y1 = y2;
-		y2 = t;
-	}
-
-	if (x1 < 0) {
-		/* Move line so that x1 = 0 */
-		double t = -x2 / (double)(x1-x2);
-		x1 = t*x1 + (1-t)*x2;
-		y1 = t*y1 + (1-t)*y2;
-
-		/* note that x2 > 0, so t < 1 !*/
-
-		if (y1 >= 0 || y1 <= height)
-			return TRUE;
-
-		if (y1 < 0) {
-			if (y2 < 0)
-				return FALSE;
-
-			/* Move line so that y1 = 0 */
-			t = -y2 / (double)(y1-y2);
-			x1 = t*x1 + (1-t)*x2;
-			y1 = t*y1 + (1-t)*y2;
-
-			/* note that y2 > 0, so 0 < t < 1 !*/
-
-			if (x1 <= width)
-				return TRUE;
-			else
-				return FALSE;
-		} else {
-			if (y2 > height)
-				return FALSE;
-
-			/* Move line so that y1 = height */
-			t = (height-y2) / (double)(y1-y2);
-			x1 = t*x1 + (1-t)*x2;
-			y1 = t*y1 + (1-t)*y2;
-
-			/* note that y2 < height, so 0 < t < 1 !*/
-
-			if (x1 <= width)
-				return TRUE;
-			else
-				return FALSE;
-		}
-
-	}
-
-	/* must be that x1 <= width and y1 < 0 or y1 > height */
-
-	if (y1 < 0) {
-		/* Move line so that y1 = 0 */
-		double t = -y2 / (double)(y1-y2);
-		x1 = t*x1 + (1-t)*x2;
-		y1 = t*y1 + (1-t)*y2;
-
-		/* y2 >= 0 so 0 < t < 1 */
-
-		if (x1 <= width)
-			return TRUE;
-		else
-			return FALSE;
-	} else {
-		/* Move line so that y1 = height */
-		double t = (height-y2) / (double)(y1-y2);
-		x1 = t*x1 + (1-t)*x2;
-		y1 = t*y1 + (1-t)*y2;
-
-		/* y2 < height so 0 < t < 1 */
-
-		if (x1 <= width)
-			return TRUE;
-		else
-			return FALSE;
-	}
-}
-
 static void
 gtk_plot_gdk_draw_lines                              (GtkPlotPC *pc,
                                                      GtkPlotPoint *points,
                                                      gint numpoints)
 {
   GdkPoint *p = NULL;
-  gint width, height;
-  gboolean last_off = FALSE;
-  gint i, j;
+  gint i;
 
   if(!GTK_PLOT_GDK(pc)->gc) return;
   if(!GTK_PLOT_GDK(pc)->drawable) return;
 
-  gdk_drawable_get_size (GTK_PLOT_GDK(pc)->drawable, &width, &height);
-
   p = (GdkPoint *)g_malloc(numpoints * sizeof(GdkPoint));
-  j = 0;
   for(i = 0; i < numpoints; i++){
-    p[j].x = roundint(points[i].x);
-    p[j].y = roundint(points[i].y);
-    if (j > 0 && ! line_on_screen (p[j-1].x, p[j-1].y, p[j].x, p[j].y, width, height)) {
-	    if (j > 1) {
-		    gdk_draw_lines(GTK_PLOT_GDK(pc)->drawable, GTK_PLOT_GDK(pc)->gc, p, j);
-	    }
-	    last_off = TRUE;
-	    p[0].x = p[j].x;
-	    p[0].y = p[j].y;
-	    j = 1;
-	    continue;
-    } else {
-	    last_off = FALSE;
-    }
-
-    j++;
+    p[i].x = roundint(points[i].x);
+    p[i].y = roundint(points[i].y);
   }
 
-  if ( ! last_off)
-	  gdk_draw_lines(GTK_PLOT_GDK(pc)->drawable, GTK_PLOT_GDK(pc)->gc, p, j);
+  gdk_draw_lines(GTK_PLOT_GDK(pc)->drawable, GTK_PLOT_GDK(pc)->gc, p, numpoints);
 
   g_free(p);
 }



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