📄 scope_disp.c
字号:
x = (((0.1 * m) / xminor) + fx) * xscale; gdk_draw_point(disp->win, disp->context, x, y); } } } }}static int select_x, select_y, target;static double min_dist;static int select_trace(int x, int y) { int n; scope_disp_t *disp = &(ctrl_usr->disp); min_dist = hypot(disp->width, disp->height) / 100.; if(min_dist < 5) min_dist = 5; target = -1; DRAWING = 0; select_x = x; select_y = y; for(n=0; n<16; n++) { scope_vert_t *vert = &(ctrl_usr->vert); draw_baseline(n+1, FALSE); if((vert->chan_enabled[n]) && (vert->data_offset[n] >= 0)) { draw_waveform(n+1, FALSE); } } draw_triggerline(ctrl_shm->trig_chan, FALSE); return target;}static int handle_release(GtkWidget *widget, GdkEventButton *event, gpointer data) { return 1;}static void change_zoom(int dir, int x) { scope_horiz_t *horiz = &(ctrl_usr->horiz); scope_disp_t *disp = &(ctrl_usr->disp); double old_pixels_per_sample, pixels_per_div, pixels_per_sec, new_pixels_per_sample, old_fraction, new_fraction, overall_record_length; old_pixels_per_sample = disp->pixels_per_sample; overall_record_length = horiz->sample_period * ctrl_shm->rec_len; set_horiz_zoom(horiz->zoom_setting + dir); /* calculate horizontal params that depend on width */ pixels_per_div = disp->width * 0.1; pixels_per_sec = pixels_per_div / horiz->disp_scale; disp->pixels_per_sample = new_pixels_per_sample = pixels_per_sec * horiz->sample_period; // how many samples away from the center of the window is this // pixel? old_fraction = (x - disp->width / 2) / old_pixels_per_sample / ctrl_shm->rec_len; // and new? new_fraction = (x - disp->width / 2) / new_pixels_per_sample / ctrl_shm->rec_len; // displace by the difference set_horiz_pos( horiz->pos_setting - new_fraction + old_fraction );}static int handle_click(GtkWidget *widget, GdkEventButton *event, gpointer data) { scope_vert_t *vert = &(ctrl_usr->vert); scope_disp_t *disp = &(ctrl_usr->disp); motion_y = event->y; motion_x = event->x; if(event->button == 4) { // zoom in change_zoom(1, event->x); } else if(event->button == 5) { // zoom out change_zoom(-1, event->x); } else { int z = select_trace(event->x, event->y); int new_channel = z & 0xff; int channel_part = z >> 8; disp->selected_part = channel_part; if(new_channel != vert->selected) { if(z == -1) vert->selected = -1; else vert->selected = new_channel; channel_changed(); } if(channel_part == 3) { set_trigger_polarity(!ctrl_shm->trig_edge); } } return 1;}static int get_cursor_info(double *t, double *v) { if(!cursor_valid) return 0; if(t) *t = cursor_time; if(v) *v = cursor_value; return 1;}static int handle_scroll(GtkWidget *widget, GdkEventScroll *event, gpointer data) { change_zoom(event->direction ? -1 : 1, event->x); return TRUE;}static void middle_drag(int dx) { scope_disp_t *disp = &(ctrl_usr->disp); scope_horiz_t *horiz = &(ctrl_usr->horiz); float dt = (dx / disp->pixels_per_sample) / ctrl_shm->rec_len; set_horiz_pos(horiz->pos_setting + 5 * dt); refresh_display();}static double snap(int y) { scope_disp_t *disp = &(ctrl_usr->disp); double new_position = y * 1.0 / disp->height; double mod = fmod(new_position, 0.05); if(mod > .045) new_position = new_position + (.05-mod); if(mod < .005) new_position = new_position - mod; return new_position;}static void left_drag(int dy, int y, GdkModifierType state) { scope_disp_t *disp = &(ctrl_usr->disp); scope_vert_t *vert = &(ctrl_usr->vert); scope_chan_t *chan = &(ctrl_usr->chan[vert->selected - 1]); if(vert->selected == -1) return; if(disp->selected_part == 2 || (state & GDK_CONTROL_MASK)) { double new_position = snap(y); set_trigger_level(new_position); } else if(disp->selected_part == 1 || (state & GDK_SHIFT_MASK)) { double new_position = snap(y); set_vert_pos(new_position); // chan->position = new_position; refresh_display(); motion_y = y; } else { if(abs(dy) > 5) { int direction = dy > 0 ? 1 : -1; int baseline_y = chan->position * disp-> height; int side = select_y > baseline_y ? -1 : 1; set_vert_scale(chan->scale_index + direction * side); motion_y = y; } }}static int handle_motion(GtkWidget *widget, GdkEventButton *event, gpointer data) { scope_disp_t *disp = &(ctrl_usr->disp); GdkModifierType mod; int x, y; gdk_window_get_pointer(disp->drawing->window, &x, &y, &mod); if(mod & GDK_BUTTON1_MASK) { left_drag(y-motion_y, y, event->state); return TRUE; } if(mod & GDK_BUTTON2_MASK) { middle_drag(motion_x - x); } motion_x = x; refresh_display(); return TRUE;}#define TIPFORMAT "<tt>f(% 8.5f) = % 8.5f</tt>"static void update_readout(void) { scope_vert_t *vert = &(ctrl_usr->vert); char tip[512]; GdkRectangle r = {vert->readout_label->allocation.x, vert->readout_label->allocation.y, vert->readout_label->allocation.width, vert->readout_label->allocation.height}; if(vert->selected != -1) { double t=0, v=0; int result = get_cursor_info(&t, &v); if(result > 0) { snprintf(tip, sizeof(tip), TIPFORMAT, t, v); } else { strcpy(tip, ""); } } else { strcpy(tip, ""); } gtk_label_set_markup(GTK_LABEL(vert->readout_label), tip); gtk_widget_draw(vert->readout_label, &r);}struct pt { double x, y; };static double dot(struct pt *a, struct pt *b) { return a->x * b->x + a->y * b->y;}static double mag(struct pt *p) { return hypot(p->x, p->y);}static double distance_point_line(int x, int y, int x1, int y1, int x2, int y2) { struct pt M = {x2-x1, y2-y1}, Q = {x-x1, y-y1}, R; double t0 = dot(&M, &Q) / dot(&M, &M); if(t0 < 0) t0 = 0; if(t0 > 1) t0 = 1; R.x = x - (x1 + t0 * M.x); R.y = y - (y1 + t0 * M.y); return mag(&R);}#define COORDINATE_CLIP(coord) ((coord < -32768) ? -32768 : (coord > 32767) ? 32767 : coord)void line(int chan_num, int x1, int y1, int x2, int y2) { scope_disp_t *disp = &(ctrl_usr->disp); if(DRAWING) { gdk_draw_line(disp->win, disp->context, COORDINATE_CLIP(x1), COORDINATE_CLIP(y1), COORDINATE_CLIP(x2), COORDINATE_CLIP(y2)); } else { double dist = distance_point_line(select_x, select_y, x1, y1, x2, y2); if(dist < min_dist) { min_dist = dist; target = chan_num; } }}void lines(int chan_num, GdkPoint points[], gint npoints) { double dist; scope_disp_t *disp = &(ctrl_usr->disp); if(DRAWING) { gdk_draw_lines(disp->win, disp->context, points, npoints); } else { int x1 = points[0].x, y1 = points[0].y, x2, y2, i; for(i=1; i<npoints; i++) { x2 = points[i].x; y2 = points[i].y; dist = distance_point_line(select_x, select_y, x1, y1, x2, y2); if(dist < min_dist) { min_dist = dist; target = chan_num; } x1 = x2; y1 = y2; } }}staticvoid draw_triggerline(int chan_num, int highlight) { static gint8 dashes[2] = {2,4}; scope_disp_t *disp = &(ctrl_usr->disp); scope_chan_t *chan = &(ctrl_usr->chan[chan_num - 1]); scope_trig_t *trig = &(ctrl_usr->trig); double yfoffset = chan->vert_offset; double ypoffset = chan->position * disp->height; double yscale = disp->height / (-10.0 * chan->scale); double fp_level = chan->scale * ((chan->position - trig->level) * 10) + chan->vert_offset; int y1 = (fp_level-yfoffset) * yscale + ypoffset; double dx = hypot(disp->width, disp->height) * .01; double dy = dx * 1.3; if(dx < 5) dx = 5; if(dy < dx + 1) dy = dx + 1; if(chan->data_type == HAL_BIT) y1 = ypoffset; if(ctrl_shm->trig_edge) dy = -dy; if(highlight) { gdk_gc_set_foreground(disp->context, &(disp->color_selected[chan_num-1])); } else { gdk_gc_set_foreground(disp->context, &(disp->color_normal[chan_num-1])); } gdk_gc_set_dashes(disp->context, 0, dashes, 2); gdk_gc_set_line_attributes(disp->context, 0, GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT, GDK_JOIN_MITER); line(chan_num | 0x200, 0, y1, disp->width, y1); gdk_gc_set_line_attributes(disp->context, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER); if(highlight) { gdk_gc_set_foreground(disp->context, &(disp->color_grid)); } else { gdk_gc_set_foreground(disp->context, &(disp->color_baseline)); } line(chan_num | 0x300, 2*dx, y1, 2*dx, y1 + 2*dy); line(chan_num | 0x300, dx, y1+dy, 2*dx, y1 + 2*dy); line(chan_num | 0x300, 3*dx, y1+dy, 2*dx, y1 + 2*dy);}void draw_baseline(int chan_num, int highlight) { scope_disp_t *disp = &(ctrl_usr->disp); scope_chan_t *chan = &(ctrl_usr->chan[chan_num - 1]); double yfoffset = chan->vert_offset; double ypoffset = chan->position * disp->height; double yscale = disp->height / (-10.0 * chan->scale); int y1 = -yfoffset * yscale + ypoffset;; if(highlight) { gdk_gc_set_foreground(disp->context, &(disp->color_grid)); } else { gdk_gc_set_foreground(disp->context, &(disp->color_baseline)); } line(chan_num | 0x100, 0, y1, disp->width, y1);}/* waveform styles: if neither is defined, an intermediate style is used */// #define DRAW_STEPPED// #define DRAW_SMOOTHvoid draw_waveform(int chan_num, int highlight){ scope_data_t *dptr; int start, end, n, sample_len; scope_disp_t *disp; scope_chan_t *chan; double xscale, xoffset; double yscale, yfoffset, ypoffset, fy; hal_type_t type; int x1, y1, x2, y2, miny, maxy, midx, ct, pn; GdkPoint *points; int first=1; scope_horiz_t *horiz = &(ctrl_usr->horiz); cursor_valid = 0; disp = &(ctrl_usr->disp); chan = &(ctrl_usr->chan[chan_num - 1]); /* calculate a bunch of local vars */ sample_len = ctrl_shm->sample_len; xscale = disp->pixels_per_sample; xoffset = disp->horiz_offset; miny = -disp->height; maxy = 2 * disp->height; type = chan->data_type; yscale = disp->height / (-10.0 * chan->scale); yfoffset = chan->vert_offset; ypoffset = chan->position * disp->height; /* point to first sample in the record for this channel */ dptr = ctrl_usr->disp_buf + ctrl_usr->vert.data_offset[chan_num - 1]; /* point to first one that gets displayed */ start = disp->start_sample; end = disp->end_sample; ct = end - start + 1; points = alloca(2 * ct * sizeof(GdkPoint)); pn = 0; n = start; dptr += n * sample_len; /* set color to draw */ if (highlight) { gdk_gc_set_foreground(disp->context, &(disp->color_selected[chan_num-1])); } else { gdk_gc_set_foreground(disp->context, &(disp->color_normal[chan_num-1])); } x1 = y1 = 0; while (n <= end) { /* calc x coordinate of this point */ x2 = (n * xscale) - xoffset; /* calc y coordinate of this point */ switch (type) { case HAL_BIT: if (dptr->d_u8) { fy = 1.0; } else { fy = 0.0; }; break; case HAL_FLOAT: fy = dptr->d_float; break; case HAL_S32: fy = dptr->d_s32; break; case HAL_U32: fy = dptr->d_u32; break; default: fy = 0.0; break; } y2 = ((fy - yfoffset) * yscale) + ypoffset; if (y2 < miny) { y2 = miny; } else if (y2 > maxy) { y2 = maxy; } x1 = COORDINATE_CLIP(x1); x2 = COORDINATE_CLIP(x2); y1 = COORDINATE_CLIP(y1); y2 = COORDINATE_CLIP(y2); /* don't draw segment ending at first point */ if (n > start) { if(pn == 0) { points[pn].x = x1; points[pn].y = y1; pn++; } if(xscale < 1) { if(points[pn-1].x != x2 || points[pn-1].y != y2) { points[pn].x = x2; points[pn].y = y2; pn++; } } else {#if defined(DRAW_SMOOTH) /* this is a smoothed line display */ points[pn].x = x2; points[pn].y = y2; pn++;#elif defined(DRAW_STEPPED) /* this is a stepped one */ points[pn].x = x1; points[pn].y = y2; pn++; points[pn].x = x2; points[pn].y = y2; pn++;#else /* this is halfway between the two extremes */ midx = (x1 + x2) / 2; if(midx != x2) { points[pn].x = midx; points[pn].y = y2; pn++; } points[pn].x = x2; points[pn].y = y2; pn++;#endif } if(first && highlight && DRAWING && x2 >= motion_x) { first = 0; gdk_draw_arc(disp->win, disp->context, TRUE, x2-3, y2-3, 7, 7, 0, 360*64); cursor_value = fy; cursor_time = (n - ctrl_shm->pre_trig)*horiz->sample_period; cursor_valid = 1; } } /* end of this segment is start of next one */ x1 = x2; y1 = y2; /* point to next sample */ dptr += sample_len; n++; } if(pn) { PangoLayout *p; char scale[HAL_NAME_LEN]; char buffer[2 * HAL_NAME_LEN]; lines(chan_num, points, pn); format_scale_value(scale, sizeof(scale), chan->scale); snprintf(buffer, sizeof(buffer), "%s\n%s", chan->name, scale); gdk_draw_layout(disp->win, disp->context, 5, points[0].y, p=gtk_widget_create_pango_layout(disp->drawing, buffer)); g_object_unref(p); }}// vim:sts=4:sw=4:et
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -