summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: addb39f)
raw | patch | inline | side by side (parent: addb39f)
author | Krzysztof Kosiński <tweenk.pl@gmail.com> | |
Thu, 18 Nov 2010 21:25:01 +0000 (22:25 +0100) | ||
committer | Krzysztof Kosiński <tweenk.pl@gmail.com> | |
Thu, 18 Nov 2010 21:25:01 +0000 (22:25 +0100) |
src/widgets/ruler.cpp | patch | blob | history |
diff --git a/src/widgets/ruler.cpp b/src/widgets/ruler.cpp
index c70d969919edc3db03797f2635e22ffd61032be2..dd0336413859da71428577822e47373ea22b6687 100644 (file)
--- a/src/widgets/ruler.cpp
+++ b/src/widgets/ruler.cpp
#define MAXIMUM_SCALES 10
#define UNUSED_PIXELS 2 // There appear to be two pixels that are not being used at each end of the ruler
+static void sp_ruler_common_draw_ticks (GtkRuler *ruler);
+
static void sp_hruler_class_init (SPHRulerClass *klass);
static void sp_hruler_init (SPHRuler *hruler);
static gint sp_hruler_motion_notify (GtkWidget *widget, GdkEventMotion *event);
-static void sp_hruler_draw_ticks (GtkRuler *ruler);
-static void sp_hruler_draw_pos (GtkRuler *ruler);
-static void sp_hruler_size_allocate (GtkWidget *widget, GtkAllocation *allocation);
static GtkWidgetClass *hruler_parent_class;
ruler_class = (GtkRulerClass*) klass;
widget_class->motion_notify_event = sp_hruler_motion_notify;
- widget_class->size_allocate = sp_hruler_size_allocate;
- ruler_class->draw_ticks = sp_hruler_draw_ticks;
- ruler_class->draw_pos = sp_hruler_draw_pos;
+ ruler_class->draw_ticks = sp_ruler_common_draw_ticks;
}
static void
ruler = GTK_RULER (widget);
double x = event->x; //Although event->x is double according to the docs, it only appears to return integers
- ruler->position = ruler->lower + (ruler->upper - ruler->lower) * (x + UNUSED_PIXELS) / (widget->allocation.width + 2*UNUSED_PIXELS);
-
- /* Make sure the ruler has been allocated already */
- if (ruler->backing_store != NULL)
- gtk_ruler_draw_pos (ruler);
-
- return FALSE;
-}
-
-static void
-sp_hruler_draw_ticks (GtkRuler *ruler)
-{
- GtkWidget *widget;
- GdkGC *gc, *bg_gc;
- PangoFontDescription *pango_desc;
- PangoContext *pango_context;
- PangoLayout *pango_layout;
- gint i, tick_index;
- gint width, height;
- gint xthickness;
- gint ythickness;
- gint length, ideal_length;
- double lower, upper; /* Upper and lower limits, in ruler units */
- double increment; /* Number of pixels per unit */
- gint scale; /* Number of units per major unit */
- double subd_incr;
- double start, end, cur;
- gchar unit_str[32];
- gint digit_height;
- gint text_width;
- gint pos;
-
- g_return_if_fail (ruler != NULL);
- g_return_if_fail (SP_IS_HRULER (ruler));
-
- if (!GTK_WIDGET_DRAWABLE (ruler))
- return;
-
- widget = GTK_WIDGET (ruler);
-
- gc = widget->style->fg_gc[GTK_STATE_NORMAL];
- bg_gc = widget->style->bg_gc[GTK_STATE_NORMAL];
-
- pango_desc = widget->style->font_desc;
-
- // Create the pango layout
- pango_context = gtk_widget_get_pango_context (widget);
-
- pango_layout = pango_layout_new (pango_context);
-
- PangoFontDescription *fs = pango_font_description_new ();
- pango_font_description_set_size (fs, RULER_FONT_SIZE);
- pango_layout_set_font_description (pango_layout, fs);
- pango_font_description_free (fs);
-
- digit_height = (int) floor (RULER_FONT_SIZE * RULER_FONT_VERTICAL_SPACING / PANGO_SCALE + 0.5);
-
- xthickness = widget->style->xthickness;
- ythickness = widget->style->ythickness;
-
- width = widget->allocation.width; // in pixels; is apparently 2 pixels shorter than the canvas at each end
- height = widget->allocation.height;// - ythickness * 2;
-
- gtk_paint_box (widget->style, ruler->backing_store,
- GTK_STATE_NORMAL, GTK_SHADOW_NONE,
- NULL, widget, "hruler",
- 0, 0,
- widget->allocation.width, widget->allocation.height);
-
- upper = ruler->upper / ruler->metric->pixels_per_unit; // upper and lower are expressed in ruler units
- lower = ruler->lower / ruler->metric->pixels_per_unit;
- /* "pixels_per_unit" should be "points_per_unit". This is the size of the unit
- * in 1/72nd's of an inch and has nothing to do with screen pixels */
-
- if ((upper - lower) == 0)
- return;
- increment = (double) (width + 2*UNUSED_PIXELS) / (upper - lower); // screen pixels per ruler unit
-
- /* determine the scale
- * We calculate the text size as for the vruler instead of using
- * text_width = gdk_string_width(font, unit_str), so that the result
- * for the scale looks consistent with an accompanying vruler
- */
- scale = (int)(ceil (ruler->max_size / ruler->metric->pixels_per_unit));
- sprintf (unit_str, "%d", scale);
- text_width = strlen (unit_str) * digit_height + 1;
-
- for (scale = 0; scale < MAXIMUM_SCALES; scale++)
- if (ruler->metric->ruler_scale[scale] * fabs(increment) > 2 * text_width)
- break;
-
- if (scale == MAXIMUM_SCALES)
- scale = MAXIMUM_SCALES - 1;
-
- /* drawing starts here */
- length = 0;
- for (i = MAXIMUM_SUBDIVIDE - 1; i >= 0; i--)
- {
- subd_incr = ruler->metric->ruler_scale[scale] /
- ruler->metric->subdivide[i];
- if (subd_incr * fabs(increment) <= MINIMUM_INCR)
- continue;
-
- /* Calculate the length of the tickmarks. Make sure that
- * this length increases for each set of ticks
- */
- ideal_length = height / (i + 1) - 1;
- if (ideal_length > ++length)
- length = ideal_length;
-
- if (lower < upper)
- {
- start = floor (lower / subd_incr) * subd_incr;
- end = ceil (upper / subd_incr) * subd_incr;
- }
- else
- {
- start = floor (upper / subd_incr) * subd_incr;
- end = ceil (lower / subd_incr) * subd_incr;
- }
-
- tick_index = 0;
- cur = start; // location (in ruler units) of the first invisible tick at the left side of the canvas
-
- while (cur <= end)
- {
- // due to the typical values for cur, lower and increment, pos will often end up to
- // be e.g. 641.50000000000; rounding behaviour is not defined in such a case (see round.h)
- // and jitter will be apparent (upon redrawing some of the lines on the ruler might jump a
- // by a pixel, and jump back on the next redraw). This is suppressed by adding 1e-9 (that's only one nanopixel ;-))
- pos = int(Inkscape::round((cur - lower) * increment + 1e-12)) - UNUSED_PIXELS;
- gdk_draw_line (ruler->backing_store, gc,
- pos, height + ythickness,
- pos, height - length + ythickness);
-
- /* draw label */
- double label_spacing_px = (increment*(double)ruler->metric->ruler_scale[scale])/ruler->metric->subdivide[i];
- if (i == 0 &&
- (label_spacing_px > 6*digit_height || tick_index%2 == 0 || cur == 0) &&
- (label_spacing_px > 3*digit_height || tick_index%4 == 0 || cur == 0))
- {
- if (fabs((int)cur) >= 2000 && (((int) cur)/1000)*1000 == ((int) cur))
- sprintf (unit_str, "%dk", ((int) cur)/1000);
- else
- sprintf (unit_str, "%d", (int) cur);
-
- pango_layout_set_text (pango_layout, unit_str, -1);
-
- gdk_draw_layout (ruler->backing_store, gc,
- pos + 2, 0, pango_layout);
- }
-
- /* Calculate cur from start rather than incrementing by subd_incr
- * in each iteration. This is to avoid propagation of floating point
- * errors in subd_incr.
- */
- ++tick_index;
- cur = start + tick_index * subd_incr;
- }
- }
-}
-
-static void
-sp_hruler_draw_pos (GtkRuler *ruler)
-{
- GtkWidget *widget;
- GdkGC *gc;
- int i;
- gint x, y;
- gint width, height;
- gint bs_width, bs_height;
- gint xthickness;
- gint ythickness;
- gfloat increment;
+ double pos = ruler->lower + (ruler->upper - ruler->lower) * (x + UNUSED_PIXELS) / (widget->allocation.width + 2*UNUSED_PIXELS);
- g_return_if_fail (ruler != NULL);
- g_return_if_fail (SP_IS_HRULER (ruler));
-
- if (GTK_WIDGET_DRAWABLE (ruler))
- {
- widget = GTK_WIDGET (ruler);
-
- gc = widget->style->fg_gc[GTK_STATE_NORMAL];
- xthickness = widget->style->xthickness;
- ythickness = widget->style->ythickness;
- width = widget->allocation.width; // in pixels; is apparently 2 pixels shorter than the canvas at each end
- height = widget->allocation.height - ythickness * 2;
-
- bs_width = height / 2;
- bs_width |= 1; /* make sure it's odd */
- bs_height = bs_width / 2 + 1;
-
- if ((bs_width > 0) && (bs_height > 0))
- {
- /* If a backing store exists, restore the ruler */
- if (ruler->backing_store && ruler->non_gr_exp_gc)
- gdk_draw_pixmap (ruler->widget.window,
- ruler->non_gr_exp_gc,
- ruler->backing_store,
- ruler->xsrc, ruler->ysrc,
- ruler->xsrc, ruler->ysrc,
- bs_width, bs_height);
-
- increment = (gfloat) (width + 2*UNUSED_PIXELS) / (ruler->upper - ruler->lower);
-
- // Calculate the coordinates (x, y, in pixels) of the tip of the triangle
- x = int(Inkscape::round((ruler->position - ruler->lower) * increment + double(xthickness - bs_width) / 2.0) - UNUSED_PIXELS);
- y = (height + bs_height) / 2 + ythickness;
-
- for (i = 0; i < bs_height; i++)
- gdk_draw_line (widget->window, gc,
- x + i, y + i,
- x + bs_width - 1 - i, y + i);
-
-
- ruler->xsrc = x;
- ruler->ysrc = y;
- }
- }
-}
+ gtk_ruler_set_range(ruler, ruler->lower, ruler->upper, pos, ruler->max_size);
-/**
- * The hruler widget's size_allocate callback.
- */
-static void
-sp_hruler_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
-{
- g_assert (widget != NULL);
- g_assert (SP_IS_HRULER (widget));
-
- // First call the default gtk_widget_size_allocate() method (which is being overridden here)
- if (GTK_WIDGET_CLASS (hruler_parent_class)->size_allocate)
- (* GTK_WIDGET_CLASS (hruler_parent_class)->size_allocate) (widget, allocation);
-
- // Now the size of the ruler has changed, the ruler bounds (upper & lower) need to be updated
- // For this we first need to obtain a pointer to the desktop, by walking up the tree of ancestors
- GtkWidget *parent = gtk_widget_get_parent(widget);
- do {
- if (SP_IS_DESKTOP_WIDGET(parent)) {
- // Now we've found the desktop widget we can have the ruler boundaries updated
- sp_desktop_widget_update_hruler(SP_DESKTOP_WIDGET(parent));
- // If the size of the ruler has increased, then a blank part is uncovered; therefore
- // it must be redrawn
- sp_hruler_draw_ticks(GTK_RULER(widget));
- break;
- }
- parent = gtk_widget_get_parent(parent);
- } while (parent != NULL);
+ return FALSE;
}
-
-
-
// vruler
static void sp_vruler_class_init (SPVRulerClass *klass);
static void sp_vruler_init (SPVRuler *vruler);
static gint sp_vruler_motion_notify (GtkWidget *widget,
GdkEventMotion *event);
-static void sp_vruler_draw_ticks (GtkRuler *ruler);
-static void sp_vruler_draw_pos (GtkRuler *ruler);
static void sp_vruler_size_request (GtkWidget *widget, GtkRequisition *requisition);
-static void sp_vruler_size_allocate (GtkWidget *widget, GtkAllocation *allocation);
static GtkWidgetClass *vruler_parent_class;
ruler_class = (GtkRulerClass*) klass;
widget_class->motion_notify_event = sp_vruler_motion_notify;
- widget_class->size_allocate = sp_vruler_size_allocate;
widget_class->size_request = sp_vruler_size_request;
- ruler_class->draw_ticks = sp_vruler_draw_ticks;
- ruler_class->draw_pos = sp_vruler_draw_pos;
+ ruler_class->draw_ticks = sp_ruler_common_draw_ticks;
}
static void
widget = GTK_WIDGET (vruler);
widget->requisition.width = widget->style->xthickness * 2 + RULER_WIDTH;
widget->requisition.height = widget->style->ythickness * 2 + 1;
+
+ g_object_set(G_OBJECT(vruler), "orientation", GTK_ORIENTATION_VERTICAL, NULL);
}
GtkWidget*
ruler = GTK_RULER (widget);
double y = event->y; //Although event->y is double according to the docs, it only appears to return integers
- ruler->position = ruler->lower + (ruler->upper - ruler->lower) * (y + UNUSED_PIXELS) / (widget->allocation.height + 2*UNUSED_PIXELS);
+ double pos = ruler->lower + (ruler->upper - ruler->lower) * (y + UNUSED_PIXELS) / (widget->allocation.height + 2*UNUSED_PIXELS);
- /* Make sure the ruler has been allocated already */
- if (ruler->backing_store != NULL)
- gtk_ruler_draw_pos (ruler);
+ gtk_ruler_set_range(ruler, ruler->lower, ruler->upper, pos, ruler->max_size);
return FALSE;
}
static void
-sp_vruler_draw_ticks (GtkRuler *ruler)
+sp_vruler_size_request (GtkWidget *widget, GtkRequisition *requisition)
{
- GtkWidget *widget;
- GdkGC *gc, *bg_gc;
- PangoFontDescription *pango_desc;
- PangoContext *pango_context;
- PangoLayout *pango_layout;
- gint i, j, tick_index;
- gint width, height;
- gint xthickness;
- gint ythickness;
- gint length, ideal_length;
- double lower, upper; /* Upper and lower limits, in ruler units */
- double increment; /* Number of pixels per unit */
- gint scale; /* Number of units per major unit */
- double subd_incr;
- double start, end, cur;
- gchar unit_str[32];
- gchar digit_str[2] = { '\0', '\0' };
- gint digit_height;
- gint text_height;
- gint pos;
-
- g_return_if_fail (ruler != NULL);
- g_return_if_fail (SP_IS_VRULER (ruler));
-
- if (!GTK_WIDGET_DRAWABLE (ruler))
- return;
-
- widget = GTK_WIDGET (ruler);
-
- gc = widget->style->fg_gc[GTK_STATE_NORMAL];
- bg_gc = widget->style->bg_gc[GTK_STATE_NORMAL];
-
- pango_desc = widget->style->font_desc;
-
- // Create the pango layout
- pango_context = gtk_widget_get_pango_context (widget);
-
- pango_layout = pango_layout_new (pango_context);
-
- PangoFontDescription *fs = pango_font_description_new ();
- pango_font_description_set_size (fs, RULER_FONT_SIZE);
- pango_layout_set_font_description (pango_layout, fs);
- pango_font_description_free (fs);
-
- digit_height = (int) floor (RULER_FONT_SIZE * RULER_FONT_VERTICAL_SPACING / PANGO_SCALE + 0.5);
-
- xthickness = widget->style->xthickness;
- ythickness = widget->style->ythickness;
-
- width = widget->allocation.height; //in pixels; is apparently 2 pixels shorter than the canvas at each end
- height = widget->allocation.width;// - ythickness * 2;
-
- gtk_paint_box (widget->style, ruler->backing_store,
- GTK_STATE_NORMAL, GTK_SHADOW_NONE,
- NULL, widget, "vruler",
- 0, 0,
- widget->allocation.width, widget->allocation.height);
-
- upper = ruler->upper / ruler->metric->pixels_per_unit; // upper and lower are expressed in ruler units
- lower = ruler->lower / ruler->metric->pixels_per_unit;
- /* "pixels_per_unit" should be "points_per_unit". This is the size of the unit
- * in 1/72nd's of an inch and has nothing to do with screen pixels */
-
- if ((upper - lower) == 0)
- return;
- increment = (double) (width + 2*UNUSED_PIXELS) / (upper - lower); // screen pixels per ruler unit
-
- /* determine the scale
- * use the maximum extents of the ruler to determine the largest
- * possible number to be displayed. Calculate the height in pixels
- * of this displayed text. Use this height to find a scale which
- * leaves sufficient room for drawing the ruler.
- */
- scale = (int)ceil (ruler->max_size / ruler->metric->pixels_per_unit);
- sprintf (unit_str, "%d", scale);
- text_height = strlen (unit_str) * digit_height + 1;
-
- for (scale = 0; scale < MAXIMUM_SCALES; scale++)
- if (ruler->metric->ruler_scale[scale] * fabs(increment) > 2 * text_height)
- break;
-
- if (scale == MAXIMUM_SCALES)
- scale = MAXIMUM_SCALES - 1;
-
- /* drawing starts here */
- length = 0;
- for (i = MAXIMUM_SUBDIVIDE - 1; i >= 0; i--) {
- subd_incr = (double) ruler->metric->ruler_scale[scale] /
- (double) ruler->metric->subdivide[i];
- if (subd_incr * fabs(increment) <= MINIMUM_INCR)
- continue;
-
- /* Calculate the length of the tickmarks. Make sure that
- * this length increases for each set of ticks
- */
- ideal_length = height / (i + 1) - 1;
- if (ideal_length > ++length)
- length = ideal_length;
-
- if (lower < upper)
- {
- start = floor (lower / subd_incr) * subd_incr;
- end = ceil (upper / subd_incr) * subd_incr;
- }
- else
- {
- start = floor (upper / subd_incr) * subd_incr;
- end = ceil (lower / subd_incr) * subd_incr;
- }
-
- tick_index = 0;
- cur = start; // location (in ruler units) of the first invisible tick at the top side of the canvas
-
- while (cur < end) {
- // due to the typical values for cur, lower and increment, pos will often end up to
- // be e.g. 641.50000000000; rounding behaviour is not defined in such a case (see round.h)
- // and jitter will be apparent (upon redrawing some of the lines on the ruler might jump a
- // by a pixel, and jump back on the next redraw). This is suppressed by adding 1e-9 (that's only one nanopixel ;-))
- pos = int(Inkscape::round((cur - lower) * increment + 1e-12)) - UNUSED_PIXELS;
-
- gdk_draw_line (ruler->backing_store, gc,
- height + xthickness - length, pos,
- height + xthickness, pos);
-
- /* draw label */
- double label_spacing_px = fabs((increment*(double)ruler->metric->ruler_scale[scale])/ruler->metric->subdivide[i]);
- if (i == 0 &&
- (label_spacing_px > 6*digit_height || tick_index%2 == 0 || cur == 0) &&
- (label_spacing_px > 3*digit_height || tick_index%4 == 0 || cur == 0))
- {
- if (fabs((int)cur) >= 2000 && (((int) cur)/1000)*1000 == ((int) cur))
- sprintf (unit_str, "%dk", ((int) cur)/1000);
- else
- sprintf (unit_str, "%d", (int) cur);
- for (j = 0; j < (int) strlen (unit_str); j++)
- {
- digit_str[0] = unit_str[j];
-
- pango_layout_set_text (pango_layout, digit_str, 1);
-
- gdk_draw_layout (ruler->backing_store, gc,
- xthickness + 1,
- pos + digit_height * (j) + 1,
- pango_layout);
- }
- }
-
- /* Calculate cur from start rather than incrementing by subd_incr
- * in each iteration. This is to avoid propagation of floating point
- * errors in subd_incr.
- */
- ++tick_index;
- cur = start + tick_index * subd_incr;
- }
- }
+ requisition->width = widget->style->xthickness * 2 + RULER_WIDTH;
}
static void
-sp_vruler_draw_pos (GtkRuler *ruler)
+sp_ruler_common_draw_ticks (GtkRuler *ruler)
{
- GtkWidget *widget;
- GdkGC *gc;
- int i;
- gint x, y;
- gint width, height;
- gint bs_width, bs_height;
- gint xthickness;
- gint ythickness;
- gfloat increment;
-
- g_return_if_fail (ruler != NULL);
- g_return_if_fail (SP_IS_VRULER (ruler));
-
- if (GTK_WIDGET_DRAWABLE (ruler))
- {
- widget = GTK_WIDGET (ruler);
-
- gc = widget->style->fg_gc[GTK_STATE_NORMAL];
- xthickness = widget->style->xthickness;
- ythickness = widget->style->ythickness;
- width = widget->allocation.width - xthickness * 2;
- height = widget->allocation.height; // in pixels; is apparently 2 pixels shorter than the canvas at each end
-
- bs_height = width / 2;
- bs_height |= 1; /* make sure it's odd */
- bs_width = bs_height / 2 + 1;
-
- if ((bs_width > 0) && (bs_height > 0))
- {
- /* If a backing store exists, restore the ruler */
- if (ruler->backing_store && ruler->non_gr_exp_gc)
- gdk_draw_pixmap (ruler->widget.window,
- ruler->non_gr_exp_gc,
- ruler->backing_store,
- ruler->xsrc, ruler->ysrc,
- ruler->xsrc, ruler->ysrc,
- bs_width, bs_height);
-
- increment = (gfloat) (height + 2*UNUSED_PIXELS) / (ruler->upper - ruler->lower);
-
- // Calculate the coordinates (x, y, in pixels) of the tip of the triangle
- x = (width + bs_width) / 2 + xthickness;
- y = int(Inkscape::round((ruler->position - ruler->lower) * increment + double(ythickness - bs_height) / 2.0) - UNUSED_PIXELS);
-
- for (i = 0; i < bs_width; i++)
- gdk_draw_line (widget->window, gc,
- x + i, y + i,
- x + i, y + bs_height - 1 - i);
-
- ruler->xsrc = x;
- ruler->ysrc = y;
- }
+ GtkWidget *widget;
+ GdkGC *gc, *bg_gc;
+ PangoFontDescription *pango_desc;
+ PangoContext *pango_context;
+ PangoLayout *pango_layout;
+ gint i, j, tick_index;
+ gint width, height;
+ gint xthickness;
+ gint ythickness;
+ gint length, ideal_length;
+ double lower, upper; /* Upper and lower limits, in ruler units */
+ double increment; /* Number of pixels per unit */
+ gint scale; /* Number of units per major unit */
+ double subd_incr;
+ double start, end, cur;
+ gchar unit_str[32];
+ gchar digit_str[2] = { '\0', '\0' };
+ gint digit_height;
+ //gint text_width, text_height;
+ gint text_dimension;
+ gint pos;
+ GtkOrientation orientation;
+
+ g_return_if_fail (ruler != NULL);
+
+ if (!GTK_WIDGET_DRAWABLE (ruler))
+ return;
+
+ g_object_get(G_OBJECT(ruler), "orientation", &orientation, NULL);
+ widget = GTK_WIDGET (ruler);
+ gc = widget->style->fg_gc[GTK_STATE_NORMAL];
+ bg_gc = widget->style->bg_gc[GTK_STATE_NORMAL];
+
+ pango_desc = widget->style->font_desc;
+ pango_context = gtk_widget_get_pango_context (widget);
+ pango_layout = pango_layout_new (pango_context);
+ PangoFontDescription *fs = pango_font_description_new ();
+ pango_font_description_set_size (fs, RULER_FONT_SIZE);
+ pango_layout_set_font_description (pango_layout, fs);
+ pango_font_description_free (fs);
+
+ digit_height = (int) floor (RULER_FONT_SIZE * RULER_FONT_VERTICAL_SPACING / PANGO_SCALE + 0.5);
+ xthickness = widget->style->xthickness;
+ ythickness = widget->style->ythickness;
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL) {
+ width = widget->allocation.width; // in pixels; is apparently 2 pixels shorter than the canvas at each end
+ height = widget->allocation.height;
+ } else {
+ width = widget->allocation.height;
+ height = widget->allocation.width;
}
-}
-static void
-sp_vruler_size_request (GtkWidget *widget, GtkRequisition *requisition)
-{
- requisition->width = widget->style->xthickness * 2 + RULER_WIDTH;
-}
+ gtk_paint_box (widget->style, ruler->backing_store,
+ GTK_STATE_NORMAL, GTK_SHADOW_NONE, NULL, widget,
+ orientation == GTK_ORIENTATION_HORIZONTAL ? "hruler" : "vruler",
+ 0, 0,
+ widget->allocation.width, widget->allocation.height);
+
+ upper = ruler->upper / ruler->metric->pixels_per_unit; // upper and lower are expressed in ruler units
+ lower = ruler->lower / ruler->metric->pixels_per_unit;
+ /* "pixels_per_unit" should be "points_per_unit". This is the size of the unit
+ * in 1/72nd's of an inch and has nothing to do with screen pixels */
+
+ if ((upper - lower) == 0)
+ return;
+
+ increment = (double) (width + 2*UNUSED_PIXELS) / (upper - lower); // screen pixels per ruler unit
+
+ /* determine the scale
+ * For vruler, use the maximum extents of the ruler to determine the largest
+ * possible number to be displayed. Calculate the height in pixels
+ * of this displayed text. Use this height to find a scale which
+ * leaves sufficient room for drawing the ruler.
+ * For hruler, we calculate the text size as for the vruler instead of using
+ * text_width = gdk_string_width(font, unit_str), so that the result
+ * for the scale looks consistent with an accompanying vruler
+ */
+ scale = (int)(ceil (ruler->max_size / ruler->metric->pixels_per_unit));
+ sprintf (unit_str, "%d", scale);
+ text_dimension = strlen (unit_str) * digit_height + 1;
+
+ for (scale = 0; scale < MAXIMUM_SCALES; scale++)
+ if (ruler->metric->ruler_scale[scale] * fabs(increment) > 2 * text_dimension)
+ break;
+
+ if (scale == MAXIMUM_SCALES)
+ scale = MAXIMUM_SCALES - 1;
+
+ /* drawing starts here */
+ length = 0;
+ for (i = MAXIMUM_SUBDIVIDE - 1; i >= 0; i--) {
+ subd_incr = ruler->metric->ruler_scale[scale] /
+ ruler->metric->subdivide[i];
+ if (subd_incr * fabs(increment) <= MINIMUM_INCR)
+ continue;
+
+ /* Calculate the length of the tickmarks. Make sure that
+ * this length increases for each set of ticks
+ */
+ ideal_length = height / (i + 1) - 1;
+ if (ideal_length > ++length)
+ length = ideal_length;
+
+ if (lower < upper) {
+ start = floor (lower / subd_incr) * subd_incr;
+ end = ceil (upper / subd_incr) * subd_incr;
+ } else {
+ start = floor (upper / subd_incr) * subd_incr;
+ end = ceil (lower / subd_incr) * subd_incr;
+ }
+ tick_index = 0;
+ cur = start; // location (in ruler units) of the first invisible tick at the left side of the canvas
-/**
- * The vruler widget's size_allocate callback.
- */
-static void
-sp_vruler_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
-{
- g_assert (widget != NULL);
- g_assert (SP_IS_VRULER (widget));
-
- // First call the default gtk_widget_size_allocate() method (which is being overridden here)
- if (GTK_WIDGET_CLASS (vruler_parent_class)->size_allocate)
- (* GTK_WIDGET_CLASS (vruler_parent_class)->size_allocate) (widget, allocation);
-
- // Now the size of the ruler has changed, the ruler bounds (upper & lower) need to be updated
- // For this we first need to obtain a pointer to the desktop, by walking up the tree of ancestors
- GtkWidget *parent = gtk_widget_get_parent(widget);
- do {
- if (SP_IS_DESKTOP_WIDGET(parent)) {
- // Now we've found the desktop widget we can have the ruler boundaries updated
- sp_desktop_widget_update_vruler(SP_DESKTOP_WIDGET(parent));
- // If the size of the ruler has increased, then a blank part is uncovered; therefore
- // it must be redrawn
- sp_vruler_draw_ticks(GTK_RULER(widget));
- break;
+ while (cur <= end) {
+ // due to the typical values for cur, lower and increment, pos will often end up to
+ // be e.g. 641.50000000000; rounding behaviour is not defined in such a case (see round.h)
+ // and jitter will be apparent (upon redrawing some of the lines on the ruler might jump a
+ // by a pixel, and jump back on the next redraw). This is suppressed by adding 1e-9 (that's only one nanopixel ;-))
+ pos = int(Inkscape::round((cur - lower) * increment + 1e-12)) - UNUSED_PIXELS;
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL) {
+ gdk_draw_line (ruler->backing_store, gc,
+ pos, height + ythickness,
+ pos, height - length + ythickness);
+ } else {
+ gdk_draw_line (ruler->backing_store, gc,
+ height + xthickness - length, pos,
+ height + xthickness, pos);
+ }
+
+ /* draw label */
+ double label_spacing_px = fabs((increment*(double)ruler->metric->ruler_scale[scale])/ruler->metric->subdivide[i]);
+ if (i == 0 &&
+ (label_spacing_px > 6*digit_height || tick_index%2 == 0 || cur == 0) &&
+ (label_spacing_px > 3*digit_height || tick_index%4 == 0 || cur == 0))
+ {
+ if (fabs((int)cur) >= 2000 && (((int) cur)/1000)*1000 == ((int) cur))
+ sprintf (unit_str, "%dk", ((int) cur)/1000);
+ else
+ sprintf (unit_str, "%d", (int) cur);
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL) {
+ pango_layout_set_text (pango_layout, unit_str, -1);
+ gdk_draw_layout (ruler->backing_store, gc,
+ pos + 2, 0, pango_layout);
+ } else {
+ for (j = 0; j < (int) strlen (unit_str); j++) {
+ digit_str[0] = unit_str[j];
+ pango_layout_set_text (pango_layout, digit_str, 1);
+
+ gdk_draw_layout (ruler->backing_store, gc,
+ xthickness + 1,
+ pos + digit_height * (j) + 1,
+ pango_layout);
+ }
+ }
+ }
+ /* Calculate cur from start rather than incrementing by subd_incr
+ * in each iteration. This is to avoid propagation of floating point
+ * errors in subd_incr.
+ */
+ ++tick_index;
+ cur = start + tick_index * subd_incr;
}
- parent = gtk_widget_get_parent(parent);
- } while (parent != NULL);
+ }
}
//TODO: warning: deprecated conversion from string constant to ‘gchar*’