static void gimp_ruler_update_position (GimpRuler *ruler, gdouble x, gdouble y) { GimpRulerPrivate *priv = GIMP_RULER_GET_PRIVATE (ruler); GtkAllocation allocation; gdouble lower; gdouble upper; gtk_widget_get_allocation (GTK_WIDGET (ruler), &allocation); gimp_ruler_get_range (ruler, &lower, &upper, NULL); if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { gimp_ruler_set_position (ruler, lower + (upper - lower) * x / allocation.width); } else { gimp_ruler_set_position (ruler, lower + (upper - lower) * y / allocation.height); } }
static GdkRectangle gimp_ruler_get_pos_rect (GimpRuler *ruler, gdouble position) { GtkWidget *widget = GTK_WIDGET (ruler); GtkStyleContext *context = gtk_widget_get_style_context (widget); GimpRulerPrivate *priv = GIMP_RULER_GET_PRIVATE (ruler); GtkAllocation allocation; GtkBorder border; gint width, height; gdouble upper, lower; gdouble increment; GdkRectangle rect = { 0, }; if (! gtk_widget_is_drawable (widget)) return rect; gtk_widget_get_allocation (widget, &allocation); gtk_style_context_get_border (context, 0, &border); if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { width = allocation.width; height = allocation.height - (border.top + border.bottom); rect.width = height / 2 + 2; rect.width |= 1; /* make sure it's odd */ rect.height = rect.width / 2 + 1; } else { width = allocation.width - (border.left + border.right); height = allocation.height; rect.height = width / 2 + 2; rect.height |= 1; /* make sure it's odd */ rect.width = rect.height / 2 + 1; } gimp_ruler_get_range (ruler, &lower, &upper, NULL); if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { increment = (gdouble) width / (upper - lower); rect.x = ROUND ((position - lower) * increment) + (border.left + border.right - rect.width) / 2 - 1; rect.y = (height + rect.height) / 2 + border.top; } else { increment = (gdouble) height / (upper - lower); rect.x = (width + rect.width) / 2 + border.left; rect.y = ROUND ((position - lower) * increment) + (border.top + border.bottom - rect.height) / 2 - 1; } return rect; }
static void gimp_ruler_draw_ticks (GimpRuler *ruler) { GtkWidget *widget = GTK_WIDGET (ruler); GtkStyle *style = gtk_widget_get_style (widget); GimpRulerPrivate *priv = GIMP_RULER_GET_PRIVATE (ruler); GtkStateType state = gtk_widget_get_state (widget); GtkAllocation allocation; cairo_t *cr; gint i; gint width, height; gint xthickness; gint ythickness; gint length, ideal_length; gdouble lower, upper; /* Upper and lower limits, in ruler units */ gdouble increment; /* Number of pixels per unit */ gint scale; /* Number of units per major unit */ gdouble start, end, cur; gchar unit_str[32]; gint digit_height; gint digit_offset; gint text_size; gint pos; gdouble max_size; GimpUnit unit; PangoLayout *layout; PangoRectangle logical_rect, ink_rect; if (! gtk_widget_is_drawable (widget)) return; gtk_widget_get_allocation (widget, &allocation); xthickness = style->xthickness; ythickness = style->ythickness; layout = gimp_ruler_get_layout (widget, "0123456789"); pango_layout_get_extents (layout, &ink_rect, &logical_rect); digit_height = PANGO_PIXELS (ink_rect.height) + 2; digit_offset = ink_rect.y; if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { width = allocation.width; height = allocation.height - ythickness * 2; } else { width = allocation.height; height = allocation.width - ythickness * 2; } cr = cairo_create (priv->backing_store); gdk_cairo_set_source_color (cr, &style->bg[state]); #if 0 gtk_paint_box (style, priv->backing_store, GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, widget, priv->orientation == GTK_ORIENTATION_HORIZONTAL ? "hruler" : "vruler", 0, 0, allocation.width, allocation.height); #else cairo_paint (cr); #endif gdk_cairo_set_source_color (cr, &style->fg[state]); if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { cairo_rectangle (cr, xthickness, height + ythickness, allocation.width - 2 * xthickness, 1); } else { cairo_rectangle (cr, height + xthickness, ythickness, 1, allocation.height - 2 * ythickness); } gimp_ruler_get_range (ruler, &lower, &upper, &max_size); if ((upper - lower) == 0) goto out; increment = (gdouble) width / (upper - lower); /* 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. * * We calculate the text size as for the vruler instead of * actually measuring the text width, so that the result for the * scale looks consistent with an accompanying vruler. */ scale = ceil (max_size); g_snprintf (unit_str, sizeof (unit_str), "%d", scale); text_size = strlen (unit_str) * digit_height + 1; for (scale = 0; scale < G_N_ELEMENTS (ruler_metric.ruler_scale); scale++) if (ruler_metric.ruler_scale[scale] * fabs (increment) > 2 * text_size) break; if (scale == G_N_ELEMENTS (ruler_metric.ruler_scale)) scale = G_N_ELEMENTS (ruler_metric.ruler_scale) - 1; unit = gimp_ruler_get_unit (ruler); /* drawing starts here */ length = 0; for (i = G_N_ELEMENTS (ruler_metric.subdivide) - 1; i >= 0; i--) { gdouble subd_incr; /* hack to get proper subdivisions at full pixels */ if (unit == GIMP_UNIT_PIXEL && scale == 1 && i == 1) subd_incr = 1.0; else subd_incr = ((gdouble) ruler_metric.ruler_scale[scale] / (gdouble) ruler_metric.subdivide[i]); if (subd_incr * fabs (increment) <= MINIMUM_INCR) continue; /* don't subdivide pixels */ if (unit == GIMP_UNIT_PIXEL && subd_incr < 1.0) 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; } for (cur = start; cur <= end; cur += subd_incr) { pos = ROUND ((cur - lower) * increment); if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { cairo_rectangle (cr, pos, height + ythickness - length, 1, length); } else { cairo_rectangle (cr, height + xthickness - length, pos, length, 1); } /* draw label */ if (i == 0) { g_snprintf (unit_str, sizeof (unit_str), "%d", (int) cur); if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { pango_layout_set_text (layout, unit_str, -1); pango_layout_get_extents (layout, &logical_rect, NULL); #if 0 gtk_paint_layout (style, priv->backing_store, state, FALSE, NULL, widget, "hruler", pos + 2, ythickness + PANGO_PIXELS (logical_rect.y - digit_offset), layout); #else cairo_move_to (cr, pos + 2, ythickness + PANGO_PIXELS (logical_rect.y - digit_offset)); pango_cairo_show_layout (cr, layout); #endif } else { gint j; for (j = 0; j < (int) strlen (unit_str); j++) { pango_layout_set_text (layout, unit_str + j, 1); pango_layout_get_extents (layout, NULL, &logical_rect); #if 0 gtk_paint_layout (style, priv->backing_store, state, FALSE, NULL, widget, "vruler", xthickness + 1, pos + digit_height * j + 2 + PANGO_PIXELS (logical_rect.y - digit_offset), layout); #else cairo_move_to (cr, xthickness + 1, pos + digit_height * j + 2 + PANGO_PIXELS (logical_rect.y - digit_offset)); pango_cairo_show_layout (cr, layout); #endif } } } } } cairo_fill (cr); out: cairo_destroy (cr); }
static void gimp_ruler_draw_pos (GimpRuler *ruler) { GtkWidget *widget = GTK_WIDGET (ruler); GtkStyle *style = gtk_widget_get_style (widget); GimpRulerPrivate *priv = GIMP_RULER_GET_PRIVATE (ruler); GtkStateType state = gtk_widget_get_state (widget); GtkAllocation allocation; gint x, y; gint width, height; gint bs_width, bs_height; gint xthickness; gint ythickness; if (! gtk_widget_is_drawable (widget)) return; gtk_widget_get_allocation (widget, &allocation); xthickness = style->xthickness; ythickness = style->ythickness; if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { width = allocation.width; height = allocation.height - ythickness * 2; bs_width = height / 2 + 2; bs_width |= 1; /* make sure it's odd */ bs_height = bs_width / 2 + 1; } else { width = allocation.width - xthickness * 2; height = allocation.height; bs_height = width / 2 + 2; bs_height |= 1; /* make sure it's odd */ bs_width = bs_height / 2 + 1; } if ((bs_width > 0) && (bs_height > 0)) { cairo_t *cr = gdk_cairo_create (gtk_widget_get_window (widget)); gdouble lower; gdouble upper; gdouble position; gdouble increment; cairo_rectangle (cr, allocation.x, allocation.y, allocation.width, allocation.height); cairo_clip (cr); cairo_translate (cr, allocation.x, allocation.y); /* If a backing store exists, restore the ruler */ if (priv->backing_store) { cairo_set_source_surface (cr, priv->backing_store, 0, 0); cairo_rectangle (cr, priv->xsrc, priv->ysrc, bs_width, bs_height); cairo_fill (cr); } position = gimp_ruler_get_position (ruler); gimp_ruler_get_range (ruler, &lower, &upper, NULL); if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { increment = (gdouble) width / (upper - lower); x = ROUND ((position - lower) * increment) + (xthickness - bs_width) / 2 - 1; y = (height + bs_height) / 2 + ythickness; } else { increment = (gdouble) height / (upper - lower); x = (width + bs_width) / 2 + xthickness; y = ROUND ((position - lower) * increment) + (ythickness - bs_height) / 2 - 1; } gdk_cairo_set_source_color (cr, &style->fg[state]); cairo_move_to (cr, x, y); if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { cairo_line_to (cr, x + bs_width / 2.0, y + bs_height); cairo_line_to (cr, x + bs_width, y); } else { cairo_line_to (cr, x + bs_width, y + bs_height / 2.0); cairo_line_to (cr, x, y + bs_height); } cairo_fill (cr); cairo_destroy (cr); priv->xsrc = x; priv->ysrc = y; } }
static GdkRectangle gimp_ruler_get_pos_rect (GimpRuler *ruler, gdouble position) { GtkWidget *widget = GTK_WIDGET (ruler); GtkStyle *style = gtk_widget_get_style (widget); GimpRulerPrivate *priv = GIMP_RULER_GET_PRIVATE (ruler); GtkAllocation allocation; gint width, height; gint xthickness; gint ythickness; gdouble upper, lower; gdouble increment; GdkRectangle rect = { 0, }; if (! gtk_widget_is_drawable (widget)) return rect; gtk_widget_get_allocation (widget, &allocation); xthickness = style->xthickness; ythickness = style->ythickness; if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { width = allocation.width; height = allocation.height - ythickness * 2; rect.width = height / 2 + 2; rect.width |= 1; /* make sure it's odd */ rect.height = rect.width / 2 + 1; } else { width = allocation.width - xthickness * 2; height = allocation.height; rect.height = width / 2 + 2; rect.height |= 1; /* make sure it's odd */ rect.width = rect.height / 2 + 1; } gimp_ruler_get_range (ruler, &lower, &upper, NULL); if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { increment = (gdouble) width / (upper - lower); rect.x = ROUND ((position - lower) * increment) + (xthickness - rect.width) / 2 - 1; rect.y = (height + rect.height) / 2 + ythickness; } else { increment = (gdouble) height / (upper - lower); rect.x = (width + rect.width) / 2 + xthickness; rect.y = ROUND ((position - lower) * increment) + (ythickness - rect.height) / 2 - 1; } rect.x += allocation.x; rect.y += allocation.y; return rect; }