From 900c1116fbd1f53ae56397cfe84c9c13a295768c Mon Sep 17 00:00:00 2001 From: Joseph Pingenot Date: Sun, 27 Jul 2008 14:50:34 -0500 Subject: [PATCH] * Making progress on the rework. There are nifty new features coming in. --- graph.c | 2 +- graphwidget.c | 96 ++++++++++++++++++++++++++++++++++++++------------------- 2 files changed, 66 insertions(+), 32 deletions(-) diff --git a/graph.c b/graph.c index f855cc9..647c310 100644 --- a/graph.c +++ b/graph.c @@ -210,7 +210,7 @@ struct graph_axis* autoset_axis(Graph* g, GString* title, double min, double max if(stop_mag == start_mag) stop_mag *= 10; axis->major=10; axis->minor=9; - axis->subminor=9; + axis->subminor=0; axis->major_start=start_mag; axis->major_step=(stop_mag - start_mag)/(axis->major); } diff --git a/graphwidget.c b/graphwidget.c index 473aa49..132b4a1 100644 --- a/graphwidget.c +++ b/graphwidget.c @@ -35,23 +35,27 @@ G_DEFINE_TYPE(GraphWidget, graph_widget, GTK_TYPE_DRAWING_AREA); #define INSET_PERCENT 0.1 +#define TITLE_PERCENT 0.1 #define DEBUG_DRAW_AXIS struct drawing_context { GtkWidget *widget; cairo_t *cr; double radius; - double xoffset; - double yoffset; - double xscaling; - double yscaling; + double xmax; + double ymax; + cairo_matrix_t data_scale; + cairo_matrix_t data_xlat; }; static void draw_point(gpointer data, gpointer user_data) { struct drawing_context *cxt = user_data; struct graph_point *pt = data; - double x = (pt->x + cxt->xoffset)*cxt->xscaling; - double y = (pt->y + cxt->yoffset)*cxt->yscaling; + cairo_save(cxt->cr); + cairo_transform(cxt->cr, cxt->data_xlat); + cairo_transform(cxt->cr, cxt->data_scale); + double x = pt->x; + double y = pt->y; cairo_move_to(cxt->cr, x, y); cairo_arc(cxt->cr, x, y, cxt->radius, 0, 2*M_PI); if(pt->label != NULL) { @@ -60,27 +64,35 @@ static void draw_point(gpointer data, gpointer user_data) { cairo_show_text(cxt->cr, pt->label->str); cairo_restore(cxt->cr); } + cairo_restore; } static void draw_lines(gpointer data, gpointer user_data) { struct drawing_context *cxt = user_data; struct graph_line *l = data; - double p0_x = (l->p0_x + cxt->xoffset)*cxt->xscaling; - double p0_y = (l->p0_y + cxt->yoffset)*cxt->yscaling; - double p1_x = (l->p1_x + cxt->xoffset)*cxt->xscaling; - double p1_y = (l->p1_y + cxt->yoffset)*cxt->yscaling; - double p2_x = (l->p2_x + cxt->xoffset)*cxt->xscaling; - double p2_y = (l->p2_y + cxt->yoffset)*cxt->yscaling; - double p3_x = (l->p3_x + cxt->xoffset)*cxt->xscaling; - double p3_y = (l->p3_y + cxt->yoffset)*cxt->yscaling; + cairo_save(cxt->cr); + cairo_transform(cxt->cr, cxt->data_xlat); + cairo_transform(cxt->cr, cxt->data_scale); + double p0_x = l->p0_x; + double p0_y = l->p0_y; + double p1_x = l->p1_x; + double p1_y = l->p1_y; + double p2_x = l->p2_x; + double p2_y = l->p2_y; + double p3_x = l->p3_x; + double p3_y = l->p3_y; #ifdef DEBUG_DRAW fprintf(stderr, "draw_lines: p0_x=%g, p0_y=%g, p1_x=%g, p1_y=%g, p2_x=%g, p2_y=%g, p3_x=%g, p3_y=%g\n", p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y); #endif cairo_move_to(cxt->cr, p0_x, p0_y); cairo_curve_to(cxt->cr, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y); + cairo_restore(cxt->cr); } -static void draw_axis(struct drawing_context* cxt, struct graph_axis *axis, double scaling, double offset) { +static void draw_axis(struct drawing_context* cxt, struct graph_axis *axis) { + cairo_save(cxt->cr); + cairo_transform(cxt->cr, cxt->data_xlat); + cairo_transform(cxt->cr, cxt->data_scale); #ifdef DEBUG_DRAW_AXIS fprintf(stderr, "draw_axis; major_start=%g, major_step=%g, >major=%d, minor=%d, subminor=%d, label=%s\n", axis->major_start, axis->major_step, axis->major, axis->minor, axis->subminor, axis->title->str); #endif @@ -111,6 +123,7 @@ static void draw_axis(struct drawing_context* cxt, struct graph_axis *axis, doub pos=i*axis->major_step + axis->major_start; cairo_move_to(cxt->cr, (pos + offset)*scaling, 0); cairo_line_to(cxt->cr, (pos + offset)*scaling, 0.05); + cairo_restore(cxt->cr); } static void draw(GtkWidget *graph, cairo_t *cr) { @@ -139,24 +152,45 @@ static void draw(GtkWidget *graph, cairo_t *cr) { cxt.widget = graph; cxt.cr = cr; cxt.radius = 0.01; - cxt.xscaling = (gw->graph->points->len == 1)? 1 : (1/(maxx - minx)); - cxt.yscaling = (gw->graph->points->len == 1)? 1 : (1/(maxy - miny)); - cxt.xoffset = (gw->graph->points->len == 1)? (-minx/2) : (-minx); - cxt.yoffset = (gw->graph->points->len == 1)? (-miny/2) : (-miny); - #ifdef DEBUG - fprintf(stderr, "minx=%g, maxx=%g, miny=%g, maxy=%g, xscaling=%g, yscaling=%g, xoffset=%g, yoffset=%g\n", minx, maxx, miny, maxy, cxt.xscaling, cxt.yscaling, cxt.xoffset, cxt.yoffset); - fprintf(stderr, "x0=%g, y0=%g, width=%g, height=%g\n", x0, y0, height, width); - fprintf(stderr, "translate=(%g, %g)\n", x0 + ((width>height)?(width-height)/2.0:0), y0+((width > height)?height:width) + ((height>width)?(height-width)/2.0:0)); -#endif - double offset_height = ((width>=height)?height*INSET_PERCENT:0);; - double offset_width = ((height>=width)?width*INSET_PERCENT:0); - double inset_height = height - offset_height; - double inset_width = width - offset_width; + /*Set up our semi-normalized scaling. The shortest direction range + [0, 1]; the other range depends upon the relative sizes.*/ + double effective_height = height; + double effective_width = width; + double inset, axis_inset; + if((INSET_PERCENT > 0) && (INSET_PERCENT < 1.0)) { + inset = ((effective_height > effective_width)?effective_width:effective_height)*INSET_PERCENT; + effective_height -= inset; + effective_width -= inset; + } + if((gw->graph->xaxis != NULL) && (gw->graph->yaxis != NULL)) { + /*key off the smaller size.*/ + axis_inset = ((effective_height > effective_width)?effective_width:effective_height)*TITLE_PERCENT; + effective_height -= axis_inset; + effective_width -= axis_inset; + }elsif(gw->graph->xaxis != NULL) { + effective_height -= effective_height*TITLE_PERCENT; + }elsif(gw->graph->yaxis != NULL) { + effective_width -= effective_width*TITLE_PERCENT; + } + if(effective_width > effective_height) { + cxt.xmax = effective_width/effective_height; + cxt.ymax = 1.0; + }else{ + cxt.xmax = 1.0; + cxt.ymax = effective_height/effective_width; + } + /*Convert from data space to the semi-normalized space*/ + double xscaling = (gw->graph->points->len == 1)? cxt.xmax : (cxt.xmax/(maxx-minx)); + double yscaling = (gw->graph->points->len == 1)? cxt.ymax : (cxt.ymax/(maxy-miny)); + double xoffset = (gw->graph->points->len == 1)? (-minx/2) : (-minx); + double yoffset = (gw->graph->points->len == 1)? (-miny/2) : (-miny); + cairo_matrix_translate(&(cxt.data_xlat), xoffset, yoffset); + cairo_matrix_scale(&(cxt.data_scale), xscaling, yscaling); cairo_save(cr); - cairo_translate(cr, x0 + ((inset_width>inset_height)?(inset_width-inset_height)/2.0:0) + offset_width/2, y0+((inset_width > inset_height)?inset_height:inset_width) + ((inset_width>=inset_height)?0:(inset_height-inset_width)/2.0) + offset_height/2 ); - cairo_scale(cr, (inset_width > inset_height)?inset_height:inset_width, (inset_width > inset_height)?-inset_height:-inset_width); + cairo_translate(cr, effective_width - inset/2, effective_height - inset/2); + cairo_scale(cr, effective_width, effective_height); cairo_set_line_width(cr, 0.005); - cairo_select_font_face (cr, "Georgia", + cairo_select_font_face (cr, "Sans Serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); cairo_set_font_size (cr, 0.05); if(gw->graph->lines != NULL) { -- 1.7.9.5