[cairo-commit] goocanvas/src goocanvasview.c, 1.31, 1.32 goocanvasview.h, 1.10, 1.11

Damon Chaplin commit at pdx.freedesktop.org
Thu Aug 31 08:45:11 PDT 2006


Committed by: damon

Update of /cvs/cairo/goocanvas/src
In directory kemper:/tmp/cvs-serv3560/src

Modified Files:
	goocanvasview.c goocanvasview.h 
Log Message:
2006-08-31  Damon Chaplin  <damon at gnome.org>

	* src/goocanvasview.c: added "units", "resolution-x" & "resolution-y"
	properties so we can support points, inches and millimeters being used
	for item units as well as just pixels. Thus you can create a complete
	WYSIWYG printable document. But note that you must use absolute units
	for font sizes, i.e. use "px" after the size in any font description
	strings, e.g. "Sans 10px".  That stops us scaling fonts twice.
	(goo_canvas_view_set_default_line_width): set a reasonable default
	line width according to the current units.

	* demo/units-demo.c: new demo showing different units in use.



Index: goocanvasview.c
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasview.c,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -d -r1.31 -r1.32
--- goocanvasview.c	30 Aug 2006 12:18:48 -0000	1.31
+++ goocanvasview.c	31 Aug 2006 15:45:09 -0000	1.32
@@ -126,7 +126,10 @@
   PROP_X1,
   PROP_Y1,
   PROP_X2,
-  PROP_Y2
+  PROP_Y2,
+  PROP_UNITS,
+  PROP_RESOLUTION_X,
+  PROP_RESOLUTION_Y
 };
 
 enum {
@@ -288,6 +291,30 @@
 							G_PARAM_READWRITE));
 
 
+  g_object_class_install_property (gobject_class, PROP_UNITS,
+				   g_param_spec_enum ("units",
+						      _("Units"),
+						      _("The units to use for the canvas"),
+						      GTK_TYPE_UNIT,
+						      GTK_UNIT_PIXEL,
+						      G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_RESOLUTION_X,
+				   g_param_spec_double ("resolution-x",
+							_("Resolution X"),
+							_("The horizontal resolution of the display, in dots per inch"),
+							0.0, G_MAXDOUBLE,
+							96.0,
+							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_RESOLUTION_Y,
+				   g_param_spec_double ("resolution-y",
+							_("Resolution Y"),
+							_("The vertical resolution of the display, in dots per inch"),
+							0.0, G_MAXDOUBLE,
+							96.0,
+							G_PARAM_READWRITE));
+
 
   /**
    * GooCanvasView::set-scroll-adjustments
@@ -350,6 +377,10 @@
   canvas_view->bounds.x2 = 1000.0;
   canvas_view->bounds.y2 = 1000.0;
 
+  canvas_view->units = GTK_UNIT_PIXEL;
+  canvas_view->resolution_x = 96.0;
+  canvas_view->resolution_y = 96.0;
+
   /* Create our own adjustments, in case we aren't inserted into a scrolled
      window. The accessibility code needs these. */
   canvas_view->hadjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
@@ -406,6 +437,35 @@
 }
 
 
+/* Set the default line width based on the current units setting. */
+static void
+goo_canvas_view_set_default_line_width (GooCanvasView *view,
+					cairo_t       *cr)
+{
+  gdouble line_width = 2.0;
+
+  /* We use the same default as cairo when using pixels, i.e. 2 pixels.
+     For other units we use 2 points, or thereabouts. */
+  switch (view->units)
+    {
+    case GTK_UNIT_PIXEL:
+      line_width = 2.0;
+      break;
+    case GTK_UNIT_POINTS:
+      line_width = 2.0;
+      break;
+    case GTK_UNIT_INCH:
+      line_width = 2.0 / 72.0;
+      break;
+    case GTK_UNIT_MM:
+      line_width = 0.7;
+      break;
+    }
+
+  cairo_set_line_width (cr, line_width);
+}
+
+
 static cairo_t*
 goo_canvas_view_create_cairo (GooCanvasView *view)
 {
@@ -415,6 +475,9 @@
 
   /*cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);*/
 
+  /* Set the default line width based on the current units setting. */
+  goo_canvas_view_set_default_line_width (view, cr);
+
   return cr;
 }
 
@@ -450,6 +513,15 @@
     case PROP_Y2:
       g_value_set_double (value, view->bounds.y2);
       break;
+    case PROP_UNITS:
+      g_value_set_enum (value, view->units);
+      break;
+    case PROP_RESOLUTION_X:
+      g_value_set_double (value, view->resolution_x);
+      break;
+    case PROP_RESOLUTION_Y:
+      g_value_set_double (value, view->resolution_y);
+      break;
 
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -465,6 +537,7 @@
 				 GParamSpec         *pspec)
 {
   GooCanvasView *view = (GooCanvasView*) object;
+  gboolean need_reconfigure = FALSE;
 
   switch (prop_id)
     {
@@ -476,29 +549,44 @@
       break;
     case PROP_ANCHOR:
       view->anchor = g_value_get_enum (value);
-      reconfigure_canvas (view, TRUE);
+      need_reconfigure = TRUE;
       break;
     case PROP_X1:
       view->bounds.x1 = g_value_get_double (value);
-      reconfigure_canvas (view, TRUE);
+      need_reconfigure = TRUE;
       break;
     case PROP_Y1:
       view->bounds.y1 = g_value_get_double (value);
-      reconfigure_canvas (view, TRUE);
+      need_reconfigure = TRUE;
       break;
     case PROP_X2:
       view->bounds.x2 = g_value_get_double (value);
-      reconfigure_canvas (view, TRUE);
+      need_reconfigure = TRUE;
       break;
     case PROP_Y2:
       view->bounds.y2 = g_value_get_double (value);
-      reconfigure_canvas (view, TRUE);
+      need_reconfigure = TRUE;
+      break;
+    case PROP_UNITS:
+      view->units = g_value_get_enum (value);
+      need_reconfigure = TRUE;
+      break;
+    case PROP_RESOLUTION_X:
+      view->resolution_x = g_value_get_double (value);
+      need_reconfigure = TRUE;
+      break;
+    case PROP_RESOLUTION_Y:
+      view->resolution_y = g_value_get_double (value);
+      need_reconfigure = TRUE;
       break;
 
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
+
+  if (need_reconfigure)
+    reconfigure_canvas (view, TRUE);
 }
 
 
@@ -688,8 +776,8 @@
   gdk_window_set_user_data (widget->window, widget);
 
   /* We want to round the sizes up to the next pixel. */
-  width_pixels = ((view->bounds.x2 - view->bounds.x1) * view->scale) + 1;
-  height_pixels = ((view->bounds.y2 - view->bounds.y1) * view->scale) + 1;
+  width_pixels = ((view->bounds.x2 - view->bounds.x1) * view->scale_x) + 1;
+  height_pixels = ((view->bounds.y2 - view->bounds.y1) * view->scale_y) + 1;
 
   attributes.x = view->hadjustment ? - view->hadjustment->value : 0,
   attributes.y = view->vadjustment ? - view->vadjustment->value : 0;
@@ -866,6 +954,32 @@
 }
 
 
+static void
+recalculate_scales (GooCanvasView *view)
+{
+  switch (view->units)
+    {
+    case GTK_UNIT_PIXEL:
+      view->scale_x = view->scale;
+      view->scale_y = view->scale;
+      break;
+    case GTK_UNIT_POINTS:
+      view->scale_x = view->scale * (view->resolution_x / 72.0);
+      view->scale_y = view->scale * (view->resolution_y / 72.0);
+      break;
+    case GTK_UNIT_INCH:
+      view->scale_x = view->scale * view->resolution_x;
+      view->scale_y = view->scale * view->resolution_y;
+      break;
+    case GTK_UNIT_MM:
+      /* There are 25.4 mm to an inch. */
+      view->scale_x = view->scale * (view->resolution_x / 25.4);
+      view->scale_y = view->scale * (view->resolution_y / 25.4);
+      break;
+    }
+}
+
+
 /* This makes sure the canvas is all set up correctly, i.e. the scrollbar
    adjustments are set, the canvas x & y offsets are calculated, and the
    canvas window is sized. */
@@ -886,10 +1000,13 @@
   if (view->bounds.y2 < view->bounds.y1)
     view->bounds.y2 = view->bounds.y1;
 
+  /* Recalculate scale_x & scale_y. */
+  recalculate_scales (view);
+
   /* This is the natural size of the canvas window in pixels, rounded up to
      the next pixel. */
-  width_pixels = ((view->bounds.x2 - view->bounds.x1) * view->scale) + 1;
-  height_pixels = ((view->bounds.y2 - view->bounds.y1) * view->scale) + 1;
+  width_pixels = ((view->bounds.x2 - view->bounds.x1) * view->scale_x) + 1;
+  height_pixels = ((view->bounds.y2 - view->bounds.y1) * view->scale_y) + 1;
 
   /* The actual window size is always at least as big as the widget's window.*/
   window_width = MAX (width_pixels, widget->allocation.width);
@@ -1298,8 +1415,8 @@
   reconfigure_canvas (view, FALSE);
 
   /* Convert from the center point to the new desired top-left posision. */
-  x -= view->hadjustment->page_size / view->scale / 2;
-  y -= view->vadjustment->page_size / view->scale / 2;
+  x -= view->hadjustment->page_size / view->scale_x / 2;
+  y -= view->vadjustment->page_size / view->scale_y / 2;
 
   /* Now try to scroll to it. */
   goo_canvas_view_scroll_to (view, x, y);
@@ -1476,14 +1593,14 @@
 
   /* We subtract one from the left & top edges, in case anti-aliasing makes
      the drawing use an extra pixel. */
-  rect.x = (double) (bounds->x1 - view->bounds.x1) * view->scale - 1;
-  rect.y = (double) (bounds->y1 - view->bounds.y1) * view->scale - 1;
+  rect.x = (double) (bounds->x1 - view->bounds.x1) * view->scale_x - 1;
+  rect.y = (double) (bounds->y1 - view->bounds.y1) * view->scale_y - 1;
 
   /* We add an extra one here for the same reason. (The other extra one is to
      round up to the next pixel.) And one for luck! */
-  rect.width = (double) (bounds->x2 - view->bounds.x1) * view->scale
+  rect.width = (double) (bounds->x2 - view->bounds.x1) * view->scale_x
     - rect.x + 2 + 1;
-  rect.height = (double) (bounds->y2 - view->bounds.y1) * view->scale
+  rect.height = (double) (bounds->y2 - view->bounds.y1) * view->scale_y
     - rect.y + 2 + 1;
 
   rect.x += view->canvas_x_offset;
@@ -1512,19 +1629,19 @@
   if (view->need_update)
     goo_canvas_view_update_internal (view, cr);
 
-  bounds.x1 = ((event->area.x - view->canvas_x_offset) / view->scale)
+  bounds.x1 = ((event->area.x - view->canvas_x_offset) / view->scale_x)
     + view->bounds.x1;
-  bounds.y1 = ((event->area.y - view->canvas_y_offset) / view->scale)
+  bounds.y1 = ((event->area.y - view->canvas_y_offset) / view->scale_y)
     + view->bounds.y1;
-  bounds.x2 = (event->area.width / view->scale) + bounds.x1;
-  bounds.y2 = (event->area.height / view->scale) + bounds.y1;
+  bounds.x2 = (event->area.width / view->scale_x) + bounds.x1;
+  bounds.y2 = (event->area.height / view->scale_y) + bounds.y1;
 
   /* Translate it to use the canvas pixel offsets (used when the canvas is
      smaller than the window and the anchor isn't set to NORTH_WEST). */
   cairo_translate (cr, view->canvas_x_offset, view->canvas_y_offset);
 
   /* Scale it so we can use canvas coordinates. */
-  cairo_scale (cr, view->scale, view->scale);
+  cairo_scale (cr, view->scale_x, view->scale_y);
 
   /* Translate it so the top-left of the canvas becomes (0,0). */
   cairo_translate (cr, -view->bounds.x1, -view->bounds.y1);
@@ -1554,6 +1671,9 @@
 			GooCanvasBounds *bounds,
 			gdouble          scale)
 {
+  /* Set the default line width based on the current units setting. */
+  goo_canvas_view_set_default_line_width (view, cr);
+
   if (bounds)
     goo_canvas_item_view_paint (view->root_view, cr, bounds, scale);
   else
@@ -2314,9 +2434,9 @@
 				   gdouble           *x,
 				   gdouble           *y)
 {
-  *x = ((*x - canvas_view->bounds.x1) * canvas_view->scale)
+  *x = ((*x - canvas_view->bounds.x1) * canvas_view->scale_x)
     + canvas_view->canvas_x_offset;
-  *y = ((*y - canvas_view->bounds.y1) * canvas_view->scale)
+  *y = ((*y - canvas_view->bounds.y1) * canvas_view->scale_y)
     + canvas_view->canvas_y_offset;
 }
 
@@ -2342,9 +2462,9 @@
 				     gdouble           *x,
 				     gdouble           *y)
 {
-  *x = ((*x - canvas_view->canvas_x_offset) / canvas_view->scale)
+  *x = ((*x - canvas_view->canvas_x_offset) / canvas_view->scale_x)
     + canvas_view->bounds.x1;
-  *y = ((*y - canvas_view->canvas_y_offset) / canvas_view->scale)
+  *y = ((*y - canvas_view->canvas_y_offset) / canvas_view->scale_y)
     + canvas_view->bounds.y1;
 }
 

Index: goocanvasview.h
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasview.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- goocanvasview.h	23 Aug 2006 11:56:05 -0000	1.10
+++ goocanvasview.h	31 Aug 2006 15:45:09 -0000	1.11
@@ -101,6 +101,17 @@
 
   /* A hash table mapping canvas items to canvas views. */
   GHashTable *item_to_view;
+
+  /* The units of the canvas, which applies to all item coords. */
+  GtkUnit units;
+
+  /* The horizontal and vertical resolution of the display, in dots per inch.
+     This is only needed when units other than pixels are used. */
+  gdouble resolution_x, resolution_y;
+
+  /* The multiplers to convert from device units to pixels, taking into account
+     the canvas scale, the units setting and the display resolution. */
+  gdouble scale_x, scale_y;
 };
 
 struct _GooCanvasViewClass



More information about the cairo-commit mailing list