[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