예제 #1
0
파일: ppg-ruler.c 프로젝트: stieg/perfkit
/**
 * ppg_ruler_size_request:
 * @ruler: (in): A #PpgRuler.
 *
 * Handle the "size-request" for the widget. Make sure we have enough space
 * to render the time labels as well as the ticks.
 *
 * Returns: None.
 * Side effects: None.
 */
static void
ppg_ruler_size_request (GtkWidget *widget,
                        GtkRequisition *req)
{
	PpgRuler *ruler = (PpgRuler *)widget;
	PpgRulerPrivate *priv;
	GdkWindow *window;
	PangoLayout *layout;
	cairo_t *cr;
	gint width;
	gint height;

	g_return_if_fail(PPG_IS_RULER(ruler));

	priv = ruler->priv;

	GTK_WIDGET_CLASS(ppg_ruler_parent_class)->size_request(widget, req);

	if ((window = gtk_widget_get_window(widget))) {
		cr = gdk_cairo_create(window);
		layout = pango_cairo_create_layout(cr);
		pango_layout_set_text(layout, "00:00:00", -1);

		pango_layout_get_pixel_size(layout, &width, &height);
		height += 12;

		g_object_unref(layout);
		cairo_destroy(cr);

		if (req->height < height) {
			req->height = height;
		}
	}
}
예제 #2
0
/**
 * ppg_ruler_size_allocate:
 * @ruler: (in): A #PpgRuler.
 *
 * Handle the "size-allocate" for the #GtkWidget. The pixmap for the
 * background is created and drawn if necessary.
 *
 * Returns: None.
 * Side effects: None.
 */
static void
ppg_ruler_size_allocate (GtkWidget     *widget,
                         GtkAllocation *alloc)
{
	PpgRuler *ruler = (PpgRuler *)widget;
	PpgRulerPrivate *priv;
	GdkWindow *window;

	g_return_if_fail(PPG_IS_RULER(ruler));

	priv = ruler->priv;

	GTK_WIDGET_CLASS(ppg_ruler_parent_class)->size_allocate(widget, alloc);

	if (priv->ruler) {
		cairo_surface_destroy(priv->ruler);
	}

	if (gtk_widget_is_drawable(widget)) {
		window = gtk_widget_get_window(widget);
		priv->ruler = gdk_window_create_similar_surface(window,
														CAIRO_CONTENT_COLOR_ALPHA,
														alloc->width,
														alloc->height);
		ppg_ruler_draw_ruler(ruler);
	}
}
예제 #3
0
/**
 * ppg_ruler_get_preferred_height:
 * @ruler: (in): A #PpgRuler.
 * @min_height: (out): A #gint.
 * @natural_height: (out): A #gint.
 *
 * Handle the "get_preferred_height" virtual function for the ruler.
 *
 * Returns: None.
 * Side effects: None.
 */
static void
ppg_ruler_get_preferred_height (GtkWidget *widget,
                                gint      *min_height,
                                gint      *natural_height)
{
	GdkWindow *window;
	PangoLayout *layout;
	cairo_t *cr;
	gint width;
	gint height;

	g_return_if_fail(PPG_IS_RULER(widget));

	*min_height = *natural_height = 0;

	if ((window = gtk_widget_get_window(widget))) {
		cr = gdk_cairo_create(window);
		layout = pango_cairo_create_layout(cr);
		pango_layout_set_text(layout, "00:00:00", -1);

		pango_layout_get_pixel_size(layout, &width, &height);
		height += 12;

		g_object_unref(layout);
		cairo_destroy(cr);

		*min_height = *natural_height = height;
	}
}
예제 #4
0
파일: ppg-ruler.c 프로젝트: stieg/perfkit
/**
 * ppg_ruler_size_allocate:
 * @ruler: (in): A #PpgRuler.
 *
 * Handle the "size-allocate" for the #GtkWidget. The pixmap for the
 * background is created and drawn if necessary.
 *
 * Returns: None.
 * Side effects: None.
 */
static void
ppg_ruler_size_allocate (GtkWidget     *widget,
                         GtkAllocation *alloc)
{
	PpgRuler *ruler = (PpgRuler *)widget;
	PpgRulerPrivate *priv;
	GdkColormap *colormap;
	GdkVisual *visual;

	g_return_if_fail(PPG_IS_RULER(ruler));

	priv = ruler->priv;

	GTK_WIDGET_CLASS(ppg_ruler_parent_class)->size_allocate(widget, alloc);

	if (priv->ruler) {
		g_object_unref(priv->ruler);
	}

	priv->ruler = gdk_pixmap_new(NULL, alloc->width, alloc->height, 32);
	visual = gdk_visual_get_best_with_depth(32);
	colormap = gdk_colormap_new(visual, FALSE);
	gdk_drawable_set_colormap(priv->ruler, colormap);

	if (GTK_WIDGET_DRAWABLE(widget)) {
		ppg_ruler_draw_ruler(ruler);
	}
}
예제 #5
0
파일: ppg-ruler.c 프로젝트: stieg/perfkit
/**
 * ppg_ruler_realize:
 * @widget: (in): A #PpgRuler.
 *
 * Handle the "realize" event for the widget.
 *
 * Returns: None.
 * Side effects: None.
 */
static void
ppg_ruler_realize (GtkWidget *widget)
{
	PpgRuler *ruler = (PpgRuler *)widget;
	PpgRulerPrivate *priv;
	GdkColormap *colormap;
	GdkVisual *visual;

	g_return_if_fail(PPG_IS_RULER(ruler));

	priv = ruler->priv;

	GTK_WIDGET_CLASS(ppg_ruler_parent_class)->realize(widget);
	gtk_widget_queue_resize(widget);

	/*
	 * Create pixmap for arrow.
	 */
	if (priv->arrow) {
		g_object_unref(priv->arrow);
	}
	priv->arrow = gdk_pixmap_new(NULL, ARROW_SIZE, ARROW_SIZE, 32);
	visual = gdk_visual_get_best_with_depth(32);
	colormap = gdk_colormap_new(visual, FALSE);
	gdk_drawable_set_colormap(priv->arrow, colormap);
}
예제 #6
0
파일: ppg-ruler.c 프로젝트: stieg/perfkit
/**
 * ppg_ruler_expose_event:
 * @ruler: (in): A #PpgRuler.
 *
 * Handle the "expose-event" for the widget. Blit the background and position
 * arrow to the surface.
 *
 * Returns: None.
 * Side effects: None.
 */
static gboolean
ppg_ruler_expose_event (GtkWidget      *widget,
                        GdkEventExpose *expose)
{
	PpgRuler *ruler = (PpgRuler *)widget;
	PpgRulerPrivate *priv;
	GtkAllocation alloc;
	cairo_t *cr;
	gint x;
	gint y;

	g_return_val_if_fail(PPG_IS_RULER(ruler), FALSE);

	GTK_WIDGET_CLASS(ppg_ruler_parent_class)->expose_event(widget, expose);

	priv = ruler->priv;

	gtk_widget_get_allocation(widget, &alloc);
	cr = gdk_cairo_create(expose->window);

	/*
	 * Clip to exposure region.
	 */
	gdk_cairo_rectangle(cr, &expose->area);
	cairo_clip(cr);

	/*
	 * Render the contents immediately if needed.
	 */
	if (priv->dirty) {
		ppg_ruler_draw_arrow(ruler);
		ppg_ruler_draw_ruler(ruler);
		priv->dirty = FALSE;
	}

	/*
	 * Blit the background to the surface.
	 */
	cairo_rectangle(cr, 0, 0, alloc.width, alloc.height);
	gdk_cairo_set_source_pixmap(cr, priv->ruler, 0, 0);
	cairo_fill(cr);

	/*
	 * Blit the arrow to the surface.
	 */
	x = (gint)(((priv->pos - priv->lower) /
                (priv->upper - priv->lower) *
                alloc.width) - (ARROW_SIZE / 2.0));
	y = alloc.height - ARROW_SIZE - 1;
	gdk_cairo_set_source_pixmap(cr, priv->arrow, x, y);
	cairo_rectangle(cr, x, y, ARROW_SIZE, ARROW_SIZE);
	cairo_fill(cr);

	/*
	 * Cleanup.
	 */
	cairo_destroy(cr);
	return FALSE;
}
예제 #7
0
파일: ppg-ruler.c 프로젝트: stieg/perfkit
/**
 * ppg_ruler_set_position:
 * @ruler: (in): A #PpgRuler.
 * @position: (in): The position.
 *
 * Sets the position of the arrow in the ruler.
 *
 * Returns: None.
 * Side effects: None.
 */
static void
ppg_ruler_set_position (PpgRuler *ruler,
                        gdouble   position)
{
	g_return_if_fail(PPG_IS_RULER(ruler));

	ruler->priv->pos = position;
	gtk_widget_queue_draw(GTK_WIDGET(ruler));
	g_object_notify(G_OBJECT(ruler), "position");
}
예제 #8
0
파일: ppg-ruler.c 프로젝트: jjardon/perfkit
static void
ppg_ruler_set_upper (PpgRuler *ruler,
                     gdouble   upper)
{
	g_return_if_fail(PPG_IS_RULER(ruler));

	ruler->priv->upper = upper;
	gtk_widget_queue_draw(GTK_WIDGET(ruler));
	g_object_notify(G_OBJECT(ruler), "upper");
}
예제 #9
0
/**
 * ppg_ruler_draw:
 * @ruler: (in): A #PpgRuler.
 * @cr: (in): A #cairo_t to draw to.
 *
 * Handle the "draw" event for the widget. Blit the background and position
 * arrow to the surface.
 *
 * Returns: FALSE always.
 * Side effects: None.
 */
static gboolean
ppg_ruler_draw (GtkWidget *widget,
                cairo_t   *cr)
{
	PpgRuler *ruler = (PpgRuler *)widget;
	PpgRulerPrivate *priv;
	GtkAllocation alloc;
	gboolean ret;
	gint x;
	gint y;

	g_return_val_if_fail(PPG_IS_RULER(ruler), FALSE);

#if GTK_CHECK_VERSION(2, 91, 0)
	ret = GTK_WIDGET_CLASS(ppg_ruler_parent_class)->draw(widget, cr);
#else
	ret = GTK_WIDGET_CLASS(ppg_ruler_parent_class)->
		expose_event(widget, (GdkEventExpose *)gtk_get_current_event());
#endif

	priv = ruler->priv;

	gtk_widget_get_allocation(widget, &alloc);

	/*
	 * Render the contents immediately if needed.
	 */
	if (priv->dirty) {
		ppg_ruler_draw_arrow(ruler);
		ppg_ruler_draw_ruler(ruler);
		priv->dirty = FALSE;
	}

	/*
	 * Blit the background to the surface.
	 */
	cairo_rectangle(cr, 0, 0, alloc.width, alloc.height);
	cairo_set_source_surface(cr, priv->ruler, 0, 0);
	cairo_fill(cr);

	/*
	 * Blit the arrow to the surface.
	 */
	x = (gint)(((priv->pos - priv->lower) /
                (priv->upper - priv->lower) *
                alloc.width) - (ARROW_SIZE / 2.0));
	y = alloc.height - ARROW_SIZE - 1;
	cairo_set_source_surface(cr, priv->arrow, x, y);
	cairo_rectangle(cr, x, y, ARROW_SIZE, ARROW_SIZE);
	cairo_fill(cr);

	return ret;
}
예제 #10
0
파일: ppg-ruler.c 프로젝트: stieg/perfkit
/**
 * ppg_ruler_set_lower:
 * @ruler: (in): A #PpgRuler.
 * @lower: (in): A #gdouble containing the lower bounds.
 *
 * Sets the lower range of the ruler.
 *
 * Returns: None.
 * Side effects: None.
 */
static void
ppg_ruler_set_lower (PpgRuler *ruler,
                     gdouble   lower)
{
	PpgRulerPrivate *priv;

	g_return_if_fail(PPG_IS_RULER(ruler));

	priv = ruler->priv;
	priv->lower = lower;
	priv->dirty = TRUE;

	gtk_widget_queue_draw(GTK_WIDGET(ruler));
	g_object_notify(G_OBJECT(ruler), "lower");
}
예제 #11
0
파일: ppg-ruler.c 프로젝트: stieg/perfkit
/**
 * ppg_ruler_style_set:
 * @ruler: (in): A #PpgRuler.
 *
 * Handle the "style-set" event and force a redraw of the widget content.
 *
 * Returns: None.
 * Side effects: None.
 */
static void
ppg_ruler_style_set (GtkWidget *widget,
                     GtkStyle *old_style)
{
	PpgRulerPrivate *priv;
	PpgRuler *ruler = (PpgRuler *)widget;

	g_return_if_fail(PPG_IS_RULER(ruler));

	priv = ruler->priv;

	GTK_WIDGET_CLASS(ppg_ruler_parent_class)->style_set(widget, old_style);

	priv->dirty = TRUE;
	gtk_widget_queue_draw(widget);
}
예제 #12
0
파일: ppg-ruler.c 프로젝트: jjardon/perfkit
static gboolean
ppg_ruler_motion_notify_event (GtkWidget *widget,
                               GdkEventMotion *motion)
{
	PpgRulerPrivate *priv;
	PpgRuler *ruler = (PpgRuler *)widget;
	GtkAllocation alloc;
	gdouble pos;

	g_return_val_if_fail(PPG_IS_RULER(ruler), FALSE);

	priv = ruler->priv;

	gtk_widget_get_allocation(widget, &alloc);
	pos = priv->lower + (motion->x / alloc.width * (priv->upper - priv->lower));
	ppg_ruler_set_position(ruler, pos);

	return FALSE;
}
예제 #13
0
파일: ppg-ruler.c 프로젝트: jjardon/perfkit
static gboolean
ppg_ruler_expose_event (GtkWidget *widget,
                        GdkEventExpose *expose)
{
	PpgRuler *ruler = (PpgRuler *)widget;
	PpgRulerPrivate *priv;
	GtkAllocation alloc;
	cairo_t *cr;
	gint x;
	gint y;

	g_return_val_if_fail(PPG_IS_RULER(ruler), FALSE);

	GTK_WIDGET_CLASS(ppg_ruler_parent_class)->expose_event(widget, expose);

	priv = ruler->priv;

	gtk_widget_get_allocation(widget, &alloc);
	cr = gdk_cairo_create(expose->window);

	if (priv->dirty) {
		ppg_ruler_draw_arrow(ruler);
		ppg_ruler_draw_ruler(ruler);
		priv->dirty = FALSE;
	}

	cairo_rectangle(cr, 0, 0, alloc.width, alloc.height);
	gdk_cairo_set_source_pixmap(cr, priv->ruler, 0, 0);
	cairo_fill(cr);

	x = (gint)(((priv->pos - priv->lower) /
                (priv->upper - priv->lower) *
                alloc.width) - (ARROW_SIZE / 2.0));
	y = alloc.height - ARROW_SIZE - 1;
	gdk_cairo_set_source_pixmap(cr, priv->arrow, x, y);
	cairo_rectangle(cr, x, y, ARROW_SIZE, ARROW_SIZE);
	cairo_fill(cr);

	cairo_destroy(cr);

	return FALSE;
}
예제 #14
0
/**
 * ppg_ruler_get_range:
 * @ruler: (in): A #PpgRuler.
 * @lower: (out): A location for a #gdouble or %NULL.
 * @upper: (out): A location for a #gdouble or %NULL.
 * @position: (out): A location for a #gdouble or %NULL.
 *
 * Retrieves the range and position for the ruler widget.
 *
 * Returns: None.
 * Side effects: None.
 */
void
ppg_ruler_get_range (PpgRuler *ruler,
                     gdouble  *lower,
                     gdouble  *upper,
                     gdouble  *position)
{
	PpgRulerPrivate *priv;

	g_return_if_fail(PPG_IS_RULER(ruler));

	priv = ruler->priv;

	if (lower) {
		*lower = priv->lower;
	}
	if (upper) {
		*upper = priv->upper;
	}
	if (position) {
		*position = priv->pos;
	}
}
예제 #15
0
파일: ppg-ruler.c 프로젝트: stieg/perfkit
/**
 * ppg_ruler_set_range:
 * @ruler: (in): A #PpgRuler.
 * @lower: (in): The lower value for the range.
 * @upper: (in): The upper value for the range.
 * @position: (in): The current position in the range.
 *
 * Sets the visible range for the ruler.
 *
 * Returns: None.
 * Side effects: None.
 */
void
ppg_ruler_set_range (PpgRuler *ruler,
                     gdouble   lower,
                     gdouble   upper,
                     gdouble   position)
{
	PpgRulerPrivate *priv;

	g_return_if_fail(PPG_IS_RULER(ruler));

	priv = ruler->priv;

	priv->lower = lower;
	priv->upper = upper;
	priv->pos = position;
	priv->dirty = TRUE;

	gtk_widget_queue_draw(GTK_WIDGET(ruler));

	g_object_notify(G_OBJECT(ruler), "lower");
	g_object_notify(G_OBJECT(ruler), "upper");
	g_object_notify(G_OBJECT(ruler), "position");
}
예제 #16
0
/**
 * ppg_ruler_realize:
 * @widget: (in): A #PpgRuler.
 *
 * Handle the "realize" event for the widget.
 *
 * Returns: None.
 * Side effects: None.
 */
static void
ppg_ruler_realize (GtkWidget *widget)
{
	PpgRuler *ruler = (PpgRuler *)widget;
	PpgRulerPrivate *priv;
	GdkWindow *window;

	g_return_if_fail(PPG_IS_RULER(ruler));

	priv = ruler->priv;

	GTK_WIDGET_CLASS(ppg_ruler_parent_class)->realize(widget);
	gtk_widget_queue_resize(widget);

	if (priv->arrow) {
		cairo_surface_destroy(priv->arrow);
	}

	window = gtk_widget_get_window(widget);
	priv->arrow = gdk_window_create_similar_surface(window,
	                                                CAIRO_CONTENT_COLOR_ALPHA,
	                                                ARROW_SIZE, ARROW_SIZE);
}
예제 #17
0
파일: ppg-ruler.c 프로젝트: stieg/perfkit
/**
 * ppg_ruler_draw_arrow:
 * @ruler: (in): A #PpgRuler.
 *
 * Draw the arrow to a pixmap for rendering on top of the background.
 *
 * Returns: None.
 * Side effects: None.
 */
static void
ppg_ruler_draw_arrow (PpgRuler *ruler)
{
	PpgRulerPrivate *priv;
	GtkStyle *style;
	GdkColor base_light;
	GdkColor base_dark;
	GdkColor hl_light;
	GdkColor hl_dark;
	cairo_t *cr;
	gint half;
	gint line_width;
	gint center;
	gint middle;
	gdouble top;
	gdouble bottom;
	gdouble left;
	gdouble right;

	g_return_if_fail(PPG_IS_RULER(ruler));

	priv = ruler->priv;
	style = gtk_widget_get_style(GTK_WIDGET(ruler));

	cr = gdk_cairo_create(priv->arrow);

	cairo_save(cr);
	cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
	cairo_rectangle(cr, 0, 0, ARROW_SIZE, ARROW_SIZE);
	cairo_fill(cr);
	cairo_restore(cr);

	center = middle = half = ARROW_SIZE / 2;
	line_width = half / 6;

	base_light = style->light[GTK_STATE_SELECTED];
	base_dark = style->dark[GTK_STATE_SELECTED];
	hl_light = style->light[GTK_STATE_SELECTED];
	hl_dark = style->mid[GTK_STATE_SELECTED];

	top = middle - half + line_width + 0.5;
	bottom = middle + half - line_width + 0.5;
	left = center - half + line_width + 0.5;
	right = center +half - line_width - 0.5;

	cairo_set_line_width(cr, line_width);

	cairo_move_to(cr, left + line_width, top + line_width);
	cairo_line_to(cr, right + line_width, top + line_width);
	cairo_line_to(cr, right + line_width, middle + line_width);
	cairo_line_to(cr, center + line_width, bottom + line_width);
	cairo_line_to(cr, left + line_width, middle + line_width);
	cairo_line_to(cr, left + line_width, top + line_width);
	cairo_close_path(cr);
	cairo_set_source_rgba(cr, 0, 0, 0, 0.5);
	cairo_fill(cr);

	cairo_move_to(cr, left, top);
	cairo_line_to(cr, center, top);
	cairo_line_to(cr, center, bottom);
	cairo_line_to(cr, left, middle);
	cairo_line_to(cr, left, top);
	cairo_close_path(cr);
	gdk_cairo_set_source_color(cr, &base_light);
	cairo_fill(cr);

	cairo_move_to(cr, center, top);
	cairo_line_to(cr, right, top);
	cairo_line_to(cr, right, middle);
	cairo_line_to(cr, center, bottom);
	cairo_line_to(cr, center, top);
	cairo_close_path(cr);
	gdk_cairo_set_source_color(cr, &base_light);
	cairo_fill_preserve(cr);
	cairo_set_source_rgba(cr,
	                      base_dark.red / 65535.0,
	                      base_dark.green / 65535.0,
	                      base_dark.blue / 65535.0,
	                      0.5);
	cairo_fill(cr);

	cairo_move_to(cr, left + line_width, top + line_width);
	cairo_line_to(cr, right - line_width, top + line_width);
	cairo_line_to(cr, right - line_width, middle);
	cairo_line_to(cr, center, bottom - line_width - 0.5);
	cairo_line_to(cr, left + line_width, middle);
	cairo_line_to(cr, left + line_width, top + line_width);
	cairo_close_path(cr);
	gdk_cairo_set_source_color(cr, &hl_light);
	cairo_stroke(cr);

	cairo_move_to(cr, left, top);
	cairo_line_to(cr, right, top);
	cairo_line_to(cr, right, middle);
	cairo_line_to(cr, center, bottom);
	cairo_line_to(cr, left, middle);
	cairo_line_to(cr, left, top);
	cairo_close_path(cr);
	gdk_cairo_set_source_color(cr, &base_dark);
	cairo_stroke(cr);

	cairo_destroy(cr);
}
예제 #18
0
/**
 * ppg_ruler_get_position:
 * @ruler: (in): A #PpgRuler.
 *
 * Retrieves the current position of the arrow in the ruler.
 *
 * Returns: The position of the arrow.
 * Side effects: None.
 */
gdouble
ppg_ruler_get_position (PpgRuler *ruler)
{
	g_return_val_if_fail(PPG_IS_RULER(ruler), 0.0);
	return ruler->priv->pos;
}
예제 #19
0
파일: ppg-ruler.c 프로젝트: stieg/perfkit
/**
 * ppg_ruler_draw_ruler:
 * @ruler: (in): A #PpgRuler.
 *
 * Draws the background of the ruler containing the time values and ticks
 * to an offscreen pixmap that can be blitted to the widget during
 * "expose-event".
 *
 * Returns: None.
 * Side effects: None.
 */
static void
ppg_ruler_draw_ruler (PpgRuler *ruler)
{
	PpgRulerPrivate *priv;
	GtkAllocation alloc;
	PangoLayout *layout;
	cairo_t *cr;
	GtkStyle *style;
	GdkColor text_color;
	gint text_width;
	gint text_height;
	gdouble every = 1.0;
	gdouble n_seconds;
	gdouble v;
	gdouble p;
	gint pw;
	gint ph;
	gint x;
	gint xx;
	gint n;
	gint z = 0;

	g_return_if_fail(PPG_IS_RULER(ruler));

	priv = ruler->priv;

	gtk_widget_get_allocation(GTK_WIDGET(ruler), &alloc);
	style = gtk_widget_get_style(GTK_WIDGET(ruler));
	cr = gdk_cairo_create(priv->ruler);

	cairo_save(cr);
	cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
	cairo_rectangle(cr, 0, 0, alloc.width, alloc.height);
	cairo_fill(cr);
	cairo_restore(cr);

	text_color = style->text[GTK_STATE_NORMAL];
	cairo_set_line_width(cr, 1.0);
	gdk_cairo_set_source_color(cr, &text_color);

	layout = pango_cairo_create_layout(cr);
	pango_layout_set_font_description(layout, priv->font_desc);
	pango_layout_set_markup(layout, "00:00:00.000", -1);
	pango_layout_get_pixel_size(layout, &text_width, &text_height);
	text_width += 5;

	n_seconds = priv->upper - priv->lower;
	if ((alloc.width / n_seconds) < text_width) {
		every = ceil(text_width / (alloc.width / n_seconds));
	}

	for (v = floor(priv->lower); v < priv->upper; v += every) {
		gdk_cairo_set_source_color(cr, &text_color);
		x = get_x_offset(priv, &alloc, v);
		cairo_move_to(cr, x + 0.5, alloc.height - 1.5);
		cairo_line_to(cr, x + 0.5, 0.5);

		/*
		 * Mini lines.
		 */
		for (p = v, n = 0, z = 0;
		     p < v + every;
		     p += (every / 10), n++, z++)
		{
			if (n == 0 || n == 10) {
				continue;
			}

			xx = get_x_offset(priv, &alloc, p);
			cairo_move_to(cr, xx + 0.5, alloc.height - 1.5);
			if (z % 2 == 0) {
				cairo_line_to(cr, xx + 0.5, text_height + 8.5);
			} else {
				cairo_line_to(cr, xx + 0.5, text_height + 5.5);
			}
		}

		cairo_stroke(cr);

		cairo_move_to(cr, x + 1.5, 1.5);
		ppg_ruler_update_layout_text(ruler, layout,
		                             CLAMP(v, priv->lower, priv->upper));

		/*
		 * If there is enough room to draw this layout before we get to the
		 * next layout, then draw it.
		 */
		pango_layout_get_pixel_size(layout, &pw, &ph);
		if ((x + pw) < get_x_offset(priv, &alloc, floor(v) + every)) {
			pango_cairo_show_layout(cr, layout);
		}
	}

	g_object_unref(layout);
	cairo_destroy(cr);
}