diff -u inkscape-0.48.0/debian/changelog inkscape-0.48.0/debian/changelog --- inkscape-0.48.0/debian/changelog +++ inkscape-0.48.0/debian/changelog @@ -1,3 +1,10 @@ +inkscape (0.48.0-1ubuntu1.1) maverick-proposed; urgency=low + + * Backport upstream patch 02-fix-cursor-redraw.dpatch to fix cursor + redraw in rulers (LP: #627134) + + -- Alex Valavanis Tue, 15 Feb 2011 00:16:43 +0100 + inkscape (0.48.0-1ubuntu1) maverick; urgency=low * Merge with Debian unstable (LP: #628048, LP: #401567, LP: #456248, diff -u inkscape-0.48.0/debian/patches/00list inkscape-0.48.0/debian/patches/00list --- inkscape-0.48.0/debian/patches/00list +++ inkscape-0.48.0/debian/patches/00list @@ -2 +2 @@ - +02-fix-cursor-redraw only in patch2: unchanged: --- inkscape-0.48.0.orig/debian/patches/02-fix-cursor-redraw.dpatch +++ inkscape-0.48.0/debian/patches/02-fix-cursor-redraw.dpatch @@ -0,0 +1,755 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## 02-fix-cursor-redraw.dpatch by Alex Valavanis +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: Description: Fix cursor redraw in rulers +## DP: Author: Krzysztof Kosinski +## DP: Bug: https://bugs.launchpad.net/inkscape/+bug/627134 +## DP: Applied-Upstream: 0.48.1 + +@DPATCH@ +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' inkscape-0.48.0~/src/widgets/ruler.cpp inkscape-0.48.0/src/widgets/ruler.cpp +--- inkscape-0.48.0~/src/widgets/ruler.cpp 2010-07-13 04:48:40.000000000 +0100 ++++ inkscape-0.48.0/src/widgets/ruler.cpp 2011-02-08 13:33:03.791768001 +0000 +@@ -29,12 +29,11 @@ + #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; + +@@ -79,10 +78,8 @@ + 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 +@@ -114,269 +111,20 @@ + + 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; +- +- 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); +- ++ double pos = ruler->lower + (ruler->upper - ruler->lower) * (x + UNUSED_PIXELS) / (widget->allocation.width + 2*UNUSED_PIXELS); + +- 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; + +@@ -421,11 +169,9 @@ + 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 +@@ -436,6 +182,8 @@ + 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* +@@ -457,267 +205,189 @@ + + 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; ++ requisition->width = widget->style->xthickness * 2 + RULER_WIDTH; ++} + +- if (scale == MAXIMUM_SCALES) +- scale = MAXIMUM_SCALES - 1; ++static void ++sp_ruler_common_draw_ticks (GtkRuler *ruler) ++{ ++ 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; + +- /* 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; ++ g_return_if_fail (ruler != NULL); + +- /* 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 (!GTK_WIDGET_DRAWABLE (ruler)) ++ return; + +- 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; +- } ++ 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]; + +- tick_index = 0; +- cur = start; // location (in ruler units) of the first invisible tick at the top side of the canvas ++ 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); + +- 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; ++ digit_height = (int) floor (RULER_FONT_SIZE * RULER_FONT_VERTICAL_SPACING / PANGO_SCALE + 0.5); ++ xthickness = widget->style->xthickness; ++ ythickness = widget->style->ythickness; + +- gdk_draw_line (ruler->backing_store, gc, +- height + xthickness - length, pos, +- height + xthickness, pos); ++ 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; ++ } + +- /* 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); +- } +- } ++ 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); + +- /* 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; +- } +- } +-} ++ 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 */ + +-static void +-sp_vruler_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; ++ if ((upper - lower) == 0) ++ return; + +- g_return_if_fail (ruler != NULL); +- g_return_if_fail (SP_IS_VRULER (ruler)); ++ increment = (double) (width + 2*UNUSED_PIXELS) / (upper - lower); // screen pixels per ruler unit + +- if (GTK_WIDGET_DRAWABLE (ruler)) +- { +- widget = GTK_WIDGET (ruler); ++ /* 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; + +- 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 ++ for (scale = 0; scale < MAXIMUM_SCALES; scale++) ++ if (ruler->metric->ruler_scale[scale] * fabs(increment) > 2 * text_dimension) ++ break; + +- bs_height = width / 2; +- bs_height |= 1; /* make sure it's odd */ +- bs_width = bs_height / 2 + 1; ++ if (scale == MAXIMUM_SCALES) ++ scale = MAXIMUM_SCALES - 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); ++ /* 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; + +- increment = (gfloat) (height + 2*UNUSED_PIXELS) / (ruler->upper - ruler->lower); ++ /* 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; + +- // 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); ++ 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; ++ } + +- for (i = 0; i < bs_width; i++) +- gdk_draw_line (widget->window, gc, +- x + i, y + i, +- x + i, y + bs_height - 1 - i); ++ tick_index = 0; ++ cur = start; // location (in ruler units) of the first invisible tick at the left side of the canvas + +- ruler->xsrc = x; +- ruler->ysrc = y; +- } +- } +-} ++ 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; + +-static void +-sp_vruler_size_request (GtkWidget *widget, GtkRequisition *requisition) +-{ +- requisition->width = widget->style->xthickness * 2 + RULER_WIDTH; +-} ++ 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); + +-/** +- * 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); ++ 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); + +- // 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; ++ 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*’