+void graph_add_extra_space(struct graph *g, double left_percent, double right_percent,
+ double top_percent, double bottom_percent)
+{
+ g->left_extra = left_percent;
+ g->right_extra = right_percent;
+ g->top_extra = top_percent;
+ g->bottom_extra = bottom_percent;
+}
+
+/*
+ * Normally values are logged in a base unit of 0, but for other purposes
+ * it makes more sense to log in higher unit. For instance for bandwidth
+ * purposes, you may want to log in KB/sec (or MB/sec) rather than bytes/sec.
+ */
+void graph_set_base_offset(struct graph *g, unsigned int base_offset)
+{
+ g->base_offset = base_offset;
+}
+
+int graph_has_tooltips(struct graph *g)
+{
+ struct graph_label *i;
+
+ for (i = g->labels; i; i = i->next)
+ if (i->tooltip_count)
+ return 1;
+
+ return 0;
+}
+
+int graph_contains_xy(struct graph *g, int x, int y)
+{
+ int first_x = g->xoffset;
+ int last_x = g->xoffset + g->xdim;
+ int first_y = g->yoffset;
+ int last_y = g->yoffset + g->ydim;
+
+ return (x >= first_x && x <= last_x) && (y >= first_y && y <= last_y);
+}
+
+const char *graph_find_tooltip(struct graph *g, int ix, int iy)
+{
+ double x = ix, y = iy;
+ struct prio_tree_iter iter;
+ struct prio_tree_node *n;
+ struct graph_label *i;
+ struct graph_value *best = NULL;
+ double best_delta;
+ double maxx, minx;
+
+ x -= g->xoffset;
+ y -= g->yoffset;
+
+ x = g->xtick_zero_val + ((x - g->xtick_zero) * g->xtick_delta);
+ y = g->ytick_zero_val + ((y - g->ytick_zero) * g->ytick_delta);
+
+ maxx = x * TOOLTIP_DELTA;
+ minx = x / TOOLTIP_DELTA;
+ best_delta = UINT_MAX;
+ i = g->labels;
+ do {
+ prio_tree_iter_init(&iter, &i->prio_tree, y, y);
+
+ n = prio_tree_next(&iter);
+ if (!n)
+ continue;
+
+ do {
+ struct graph_value *v;
+ double xval, xdiff;
+
+ v = container_of(n, struct graph_value, node);
+ xval = getx(v);
+
+ if (xval > x)
+ xdiff = xval - x;
+ else
+ xdiff = x - xval;
+
+ /*
+ * zero delta, or within or match critera, break
+ */
+ if (xdiff < best_delta) {
+ best_delta = xdiff;
+ if (!best_delta ||
+ (xval >= minx && xval <= maxx)) {
+ best = v;
+ break;
+ }
+ }
+ } while ((n = prio_tree_next(&iter)) != NULL);
+
+ /*
+ * If we got matches in one label, don't check others.
+ */
+ break;
+ } while ((i = i->next) != NULL);
+
+ if (best)
+ return best->tooltip;
+
+ return NULL;
+}