⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gcanvas.c

📁 Graphviz - Graph Drawing Programs from AT&T Research and Lucent Bell Labs See doc/build.html for
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: gcanvas.c,v 1.2 2005/11/30 22:19:13 erg Exp $ $Revision: 1.2 $ *//* vim:set shiftwidth=4 ts=8: *//***********************************************************      This software is part of the graphviz package      **                http://www.graphviz.org/                 **                                                         **            Copyright (c) 1994-2004 AT&T Corp.           **                and is licensed under the                **            Common Public License, Version 1.0           **                      by AT&T Corp.                      **                                                         **        Information and Software Systems Research        **              AT&T Research, Florham Park NJ             ***********************************************************/#include "common.h"#include "g.h"#include "gcommon.h"#define WCU widget->u.c#define WINDOW widget->u.c->window#define GC widget->u.c->gc#define ISVISIBLE(r) ( \	(r.o.x <= WCU->clip.c.x) && (r.c.x >= WCU->clip.o.x) && \	(r.o.y <= WCU->clip.c.y) && (r.c.y >= WCU->clip.o.y) \)#define IS8BIT(font) ((font)->min_byte1 == 0 && (font)->max_byte1 == 0)#define max(a, b) (((a) >= (b)) ? (a) : (b))#define min(a, b) (((a) <= (b)) ? (a) : (b))#define SETFONT(font) { \	if(font != WCU->font) { \		WCU->font = font; \		gdk_gc_set_font(GC, font); \	} \}Gwidget_t *canvas;static int curcursori = -1;static gchar gstyles[][2] = {    /* G_SOLID */ {16},    /* G_DASHED */ {4, 4},    /* G_DOTTED */ {2, 2},    /* G_LONGDASHED */ {4, 12},    /* G_SHORTDASHED */ {12, 4}};static char grays[][4] = {    {0x00, 0x00, 0x00, 0x00,},    {0x08, 0x00, 0x00, 0x00,},    {0x08, 0x00, 0x02, 0x00,},    {0x0A, 0x00, 0x02, 0x00,},    {0x0A, 0x00, 0x0A, 0x00,},    {0x0A, 0x04, 0x0A, 0x00,},    {0x0A, 0x04, 0x0A, 0x01,},    {0x0A, 0x05, 0x0A, 0x01,},    {0x0A, 0x05, 0x0A, 0x05,},    {0x0E, 0x05, 0x0A, 0x05,},    {0x0E, 0x05, 0x0B, 0x05,},    {0x0F, 0x05, 0x0B, 0x05,},    {0x0F, 0x05, 0x0F, 0x05,},    {0x0F, 0x0D, 0x0F, 0x05,},    {0x0F, 0x0D, 0x0F, 0x07,},    {0x0F, 0x0F, 0x0F, 0x07,},    {0x0F, 0x0F, 0x0F, 0x0F,},};static void setgattr(Gwidget_t *, Ggattr_t *);static PIXrect_t rdrawtopix(Gwidget_t *, Grect_t);static PIXpoint_t pdrawtopix(Gwidget_t *, Gpoint_t);static PIXsize_t sdrawtopix(Gwidget_t *, Gsize_t);static Gpoint_t Gppixtodraw(Gwidget_t *, PIXpoint_t);static Gsize_t spixtodraw(Gwidget_t *, PIXsize_t);static Grect_t rpixtodraw(Gwidget_t *, PIXrect_t);static PIXrect_t rdrawtobpix(Gbitmap_t *, Grect_t);static PIXpoint_t pdrawtobpix(Gbitmap_t *, Gpoint_t);static void adjustclip(Gwidget_t *);int GCcreatewidget(Gwidget_t * parent, Gwidget_t * widget,		   int attrn, Gwattr_t * attrp){    PIXsize_t ps;    int width, height;    int ai, i;    GdkGCValues gcv;    int r, g, b, color;    GdkColor *cp;    if (!parent) {	Gerr(POS, G_ERRNOPARENTWIDGET);	return -1;    }    canvas = widget;    WCU->func = NULL;    WCU->needredraw = FALSE;    WCU->buttonsdown = 0;    WCU->bstate[0] = WCU->bstate[1] = WCU->bstate[2] = 0;    ps.x = ps.y = MINCWSIZE;    for (ai = 0; ai < attrn; ai++) {	switch (attrp[ai].id) {	case G_ATTRSIZE:	    GETSIZE(attrp[ai].u.s, ps, MINCWSIZE);	    break;	case G_ATTRBORDERWIDTH:	    break;#ifdef FEATURE_GMAP	case G_ATTRMODE:	    if (Strcmp("gmap", attrp[ai].u.t) == 0) {		gmapmode = TRUE;	    } else {		Gerr(POS, G_ERRBADATTRVALUE, attrp[ai].u.t);		return -1;	    }	    break;#endif	case G_ATTRCURSOR:	    break;	case G_ATTRCOLOR:	    break;	case G_ATTRVIEWPORT:	    break;	case G_ATTRWINDOW:	    break;	case G_ATTRWINDOWID:	    Gerr(POS, G_ERRCANNOTSETATTR2, "windowid");	    return -1;	case G_ATTREVENTCB:	    WCU->func = (Gcanvascb) attrp[ai].u.func;	    break;	case G_ATTRUSERDATA:	    widget->udata = attrp[ai].u.u;	    break;	default:	    Gerr(POS, G_ERRBADATTRID, attrp[ai].id);	    return -1;	}    }/*    	XtSetValues (widget->w, argp, argn);	*/    widget->w = gtk_drawing_area_new();    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(parent->w),					  widget->w);    gtk_drawing_area_size(GTK_DRAWING_AREA(widget->w), ps.x, ps.y);    gtk_widget_add_events(widget->w, GDK_ALL_EVENTS_MASK);    gtk_signal_connect(GTK_OBJECT(widget->w), "key_release_event",		       GTK_SIGNAL_FUNC(Gcwkeyaction), NULL);    gtk_signal_connect(GTK_OBJECT(widget->w), "key_press_event",		       GTK_SIGNAL_FUNC(Gcwkeyaction), NULL);    gtk_signal_connect(G_OBJECT(widget->w), "button_press_event",		       GTK_SIGNAL_FUNC(Gcwbutaction), NULL);    gtk_signal_connect(G_OBJECT(widget->w), "button_release_event",		       GTK_SIGNAL_FUNC(Gcwbutaction), NULL);    gtk_signal_connect(G_OBJECT(widget->w), "visibility_notify_event",		       GTK_SIGNAL_FUNC(cweventhandler), NULL);    gtk_signal_connect(G_OBJECT(widget->w), "expose_event",		       GTK_SIGNAL_FUNC(exposeeventhandler), NULL);    gtk_signal_connect(G_OBJECT(widget->w), "motion_notify_event",		       GTK_SIGNAL_FUNC(cweventhandler), NULL);    gtk_widget_show(widget->w);    gtk_widget_show(parent->w);    GC = gdk_gc_new(widget->w->window);    WCU->cmap = gdk_colormap_get_system();    WCU->colors[0].color.pixel = WCU->colors[1].color.pixel = 1000000;    if (WCU->colors[0].color.pixel == 1000000) {	gdk_gc_get_values(GC, &gcv);	WCU->colors[0].color = gcv.background;    }    if (WCU->colors[1].color.pixel == 1000000) {	gdk_gc_get_values(GC, &gcv);	WCU->colors[1].color = gcv.foreground;    }    WCU->colors[0].color.red = 65535;    WCU->colors[0].color.green = 65535;    WCU->colors[0].color.blue = 65535;    WCU->colors[1].color.red = 0;    WCU->colors[1].color.green = 0;    WCU->colors[1].color.blue = 0;    gdk_colormap_alloc_color(WCU->cmap, &WCU->colors[0].color, FALSE,			     TRUE);    WCU->colors[0].inuse = TRUE;    gdk_colormap_alloc_color(WCU->cmap, &WCU->colors[1].color, FALSE,			     TRUE);    WCU->colors[1].inuse = TRUE;    WCU->allocedcolor[0] = WCU->allocedcolor[1] = FALSE;    for (i = 2; i < G_MAXCOLORS; i++)	WCU->colors[i].inuse = FALSE;    WCU->gattr.color = 1;/*	gdk_gc_set_background(GC, widget->w->style->white_gc);	gdk_gc_set_foreground(GC, widget->w->style->black_gc);*/    WCU->gattr.width = 0;    WCU->gattr.mode = 0;    WCU->gattr.fill = 0;    WCU->gattr.style = 0;    WCU->defgattr = WCU->gattr;    WCU->font = NULL;    WCU->wrect.o.x = 0.0, WCU->wrect.o.y = 0.0;    WCU->wrect.c.x = 1.0, WCU->wrect.c.y = 1.0;    WCU->vsize.x = ps.x, WCU->vsize.y = ps.y;    for (ai = 0; ai < attrn; ai++) {	switch (attrp[ai].id) {	case G_ATTRCURSOR:	    if (Strcmp(attrp[ai].u.t, "default") == 0) {		curcursori = -1;	    }	    break;	case G_ATTRCOLOR:	    color = attrp[ai].u.c.index;	    if (color < 0 || color > G_MAXCOLORS) {		Gerr(POS, G_ERRBADCOLORINDEX, color);		return -1;	    }	    r = attrp[ai].u.c.r * 257;	    g = attrp[ai].u.c.g * 257;	    b = attrp[ai].u.c.b * 257;	    cp = &WCU->colors[color].color;	    if (WCU->colors[color].inuse)		if (cp->red != r || cp->green != g || cp->blue != b)		    if (color > 1 || WCU->allocedcolor[color])			gdk_colormap_free_colors(WCU->cmap, cp, 1);	    cp->red = r, cp->green = g, cp->blue = b;	    if (gdk_colormap_alloc_color(WCU->cmap, cp, TRUE, TRUE)) {		WCU->colors[color].inuse = TRUE;		if (color <= 1)		    WCU->allocedcolor[color] = TRUE;	    }	    cp->red = r, cp->green = g, cp->blue = b;	    if (color == WCU->gattr.color)		WCU->gattr.color = -1;	    break;	case G_ATTRVIEWPORT:	    WCU->vsize.x = (int) (attrp[ai].u.s.x + 0.5);	    WCU->vsize.y = (int) (attrp[ai].u.s.y + 0.5);	    break;	case G_ATTRWINDOW:	    WCU->wrect = attrp[ai].u.r;	    break;	}    }    adjustclip(widget);    return 0;}int GCsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp){    PIXsize_t ps;    int ai, r, g, b, color;    GdkColor *cp;    for (ai = 0; ai < attrn; ai++) {	switch (attrp[ai].id) {	case G_ATTRSIZE:	    GETSIZE(attrp[ai].u.s, ps, MINCWSIZE);	    gtk_drawing_area_size(GTK_DRAWING_AREA(widget->w), ps.x, ps.y);	    break;	case G_ATTRBORDERWIDTH:	    break;	case G_ATTRCURSOR:	    if (Strcmp(attrp[ai].u.t, "watch") == 0) {		gdk_window_set_cursor(widget->w->window,				      gdk_cursor_new(GDK_WATCH));	    } else {		gdk_window_set_cursor(widget->w->window,				      gdk_cursor_new(GDK_LEFT_PTR));	    }	    Gsync();	    break;	case G_ATTRCOLOR:	    color = attrp[ai].u.c.index;	    if (color < 0 || color > G_MAXCOLORS) {		Gerr(POS, G_ERRBADCOLORINDEX, color);		return -1;	    }	    r = attrp[ai].u.c.r * 257;	    g = attrp[ai].u.c.g * 257;	    b = attrp[ai].u.c.b * 257;	    cp = &WCU->colors[color].color;	    if (WCU->colors[color].inuse)		if (cp->red != r || cp->green != g || cp->blue != b)		    if (color > 1 || WCU->allocedcolor[color])			gdk_colormap_free_colors(WCU->cmap, cp, 1);	    cp->red = r, cp->green = g, cp->blue = b;	    if (gdk_colormap_alloc_color(WCU->cmap, cp, TRUE, TRUE)) {		WCU->colors[color].inuse = TRUE;		if (color <= 1)		    WCU->allocedcolor[color] = TRUE;	    }	    cp->red = r, cp->green = g, cp->blue = b;	    if (color == WCU->gattr.color)		WCU->gattr.color = -1;	    break;	case G_ATTRVIEWPORT:	    WCU->vsize.x = (int) (attrp[ai].u.s.x + 0.5);	    WCU->vsize.y = (int) (attrp[ai].u.s.y + 0.5);	    break;	case G_ATTRWINDOW:	    WCU->wrect = attrp[ai].u.r;	    adjustclip(widget);	    break;	case G_ATTRWINDOWID:	    Gerr(POS, G_ERRCANNOTSETATTR2, "windowid");	    return -1;	case G_ATTREVENTCB:	    WCU->func = (Gcanvascb) attrp[ai].u.func;	    break;	case G_ATTRUSERDATA:	    widget->udata = attrp[ai].u.u;	    break;	default:	    Gerr(POS, G_ERRBADATTRID, attrp[ai].id);	    return -1;	}    }    return 0;}int GCgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp){    GdkColor *cp;    int width, height;    int ai, color;    for (ai = 0; ai < attrn; ai++) {	switch (attrp[ai].id) {	case G_ATTRSIZE:	    attrp[ai].u.s.x = width, attrp[ai].u.s.y = height;	    break;	case G_ATTRBORDERWIDTH:	    attrp[ai].u.i = width;	    break;	case G_ATTRCURSOR:/*				attrp[ai].u.t = (curcursori == -1) ? "default" : cursormap[curcursori].name;*/	    attrp[ai].u.t = (curcursori == -1) ? "default" : "watch";	    break;	case G_ATTRCOLOR:	    color = attrp[ai].u.c.index;	    if (color < 0 || color > G_MAXCOLORS) {		Gerr(POS, G_ERRBADCOLORINDEX, color);		return -1;	    }	    if (WCU->colors[color].inuse) {		cp = &WCU->colors[color].color;		attrp[ai].u.c.r = cp->red / 257.0;		attrp[ai].u.c.g = cp->green / 257.0;		attrp[ai].u.c.b = cp->blue / 257.0;	    } else {		attrp[ai].u.c.r = -1;		attrp[ai].u.c.g = -1;		attrp[ai].u.c.b = -1;	    }	    break;	case G_ATTRVIEWPORT:	    attrp[ai].u.s = WCU->vsize;	    break;	case G_ATTRWINDOW:	    attrp[ai].u.r = WCU->wrect;	    break;	case G_ATTRWINDOWID:	    sprintf(&Gbufp[0], "0x%lx", (unsigned long) widget->w);	    break;	case G_ATTREVENTCB:	    attrp[ai].u.func = WCU->func;	    break;	case G_ATTRUSERDATA:	    attrp[ai].u.u = widget->udata;	    break;	default:	    Gerr(POS, G_ERRBADATTRID, attrp[ai].id);	    return -1;	}    }    return 0;}int GCdestroywidget(Gwidget_t * widget){    gtk_widget_destroy(widget->w);    return 0;}int GCsetgfxattr(Gwidget_t * widget, Ggattr_t * ap){    setgattr(widget, ap);    WCU->defgattr = WCU->gattr;    return 0;}int GCarrow(Gwidget_t * widget, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t * ap){    PIXpoint_t pp1, pp2, pa, pb, pd;    Grect_t gr;    double tangent, l;    if (gp1.x < gp2.x)	gr.o.x = gp1.x, gr.c.x = gp2.x;    else	gr.o.x = gp2.x, gr.c.x = gp1.x;    if (gp1.y < gp2.y)	gr.o.y = gp1.y, gr.c.y = gp2.y;    else	gr.o.y = gp2.y, gr.c.y = gp1.y;    pp1 = pdrawtopix(widget, gp1), pp2 = pdrawtopix(widget, gp2);    pd.x = pp1.x - pp2.x, pd.y = pp1.y - pp2.y;    if (pd.x == 0 && pd.y == 0)	return 0;    tangent = atan2((double) pd.y, (double) pd.x);    if ((l = sqrt((double) (pd.x * pd.x + pd.y * pd.y))) > 30)	l = 30;    pa.x = l * cos(tangent + M_PI / 7) + pp2.x;    pa.y = l * sin(tangent + M_PI / 7) + pp2.y;    pb.x = l * cos(tangent - M_PI / 7) + pp2.x;    pb.y = l * sin(tangent - M_PI / 7) + pp2.y;    setgattr(widget, ap);    gdk_draw_line(widget->w->window, GC, pp1.x, pp1.y, pp2.x, pp2.y);    gdk_draw_line(widget->w->window, GC, pa.x, pa.y, pp2.x, pp2.y);    gdk_draw_line(widget->w->window, GC, pb.x, pb.y, pp2.x, pp2.y);    return 0;}int GCline(Gwidget_t * widget, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t * ap){    PIXpoint_t pp1, pp2;    Grect_t gr;    if (gp1.x < gp2.x)	gr.o.x = gp1.x, gr.c.x = gp2.x;    else	gr.o.x = gp2.x, gr.c.x = gp1.x;    if (gp1.y < gp2.y)	gr.o.y = gp1.y, gr.c.y = gp2.y;    else	gr.o.y = gp2.y, gr.c.y = gp1.y;/*	if(!ISVISIBLE(gr))		return 1;*/    pp1 = pdrawtopix(widget, gp1), pp2 = pdrawtopix(widget, gp2);    setgattr(widget, ap);    gdk_draw_line(widget->w->window, GC, pp1.x, pp1.y, pp2.x, pp2.y);    return 0;}int GCbox(Gwidget_t * widget, Grect_t gr, Ggattr_t * ap){    PIXrect_t pr;    Gxy_t p;    if (gr.o.x > gr.c.x)	p.x = gr.o.x, gr.o.x = gr.c.x, gr.c.x = p.x;    if (gr.o.y > gr.c.y)	p.y = gr.o.y, gr.o.y = gr.c.y, gr.c.y = p.y;/*	if(!ISVISIBLE(gr))		return 1;*/    pr = rdrawtopix(widget, gr);    setgattr(widget, ap);    if (WCU->gattr.fill)	gdk_draw_rectangle(widget->w->window, GC, TRUE, pr.o.x, pr.o.y,			   pr.c.x - pr.o.x, pr.c.y - pr.o.y);    else {	gdk_draw_rectangle(widget->w->window, GC, FALSE, pr.o.x, pr.o.y,			   pr.c.x - pr.o.x, pr.c.y - pr.o.y);    }    return 0;}int GCpolygon(Gwidget_t * widget, int gpn, Gpoint_t * gpp, Ggattr_t * ap){    Grect_t gr;    int n, i;    if (gpn == 0)	return 0;    gr.o = gpp[0], gr.c = gpp[0];    for (i = 1; i < gpn; i++) {	gr.o.x = min(gr.o.x, gpp[i].x);	gr.o.y = min(gr.o.y, gpp[i].y);	gr.c.x = min(gr.c.x, gpp[i].x);	gr.c.y = min(gr.c.y, gpp[i].y);    }/*	if(!ISVISIBLE(gr))		return 1;*/    if (gpn + 1 > Gppn) {	n = (((gpn + 1) + PPINCR - 1) / PPINCR) * PPINCR;	Gppp = Marraygrow(Gppp, (long) n * PPSIZE);	Gppn = n;    }    for (i = 0; i < gpn; i++)	Gppp[i] = pdrawtopix(widget, gpp[i]);    setgattr(widget, ap);    if (WCU->gattr.fill) {	if (Gppp[gpn - 1].x != Gppp[0].x || Gppp[gpn - 1].y != Gppp[0].y)	    Gppp[gpn] = Gppp[0], gpn++;	gdk_draw_polygon(widget->w, GC, TRUE, Gppp, gpn);    } else	gdk_draw_polygon(widget->w, GC, FALSE, Gppp, gpn);    return 0;}static void bezier(PIXpoint_t p0, PIXpoint_t p1, PIXpoint_t p2,		   PIXpoint_t p3){    Gpoint_t gp0, gp1, gp2;    Gsize_t s;    PIXpoint_t p;    double t;    int n, i, steps;    if ((s.x = p3.x - p0.x) < 0)	s.x = -s.x;    if ((s.y = p3.y - p0.y) < 0)	s.y = -s.y;    if (s.x > s.y)	steps = s.x / 5 + 1;    else	steps = s.y / 5 + 1;    for (i = 0; i <= steps; i++) {	t = i / (double) steps;	gp0.x = p0.x + t * (p1.x - p0.x);	gp0.y = p0.y + t * (p1.y - p0.y);	gp1.x = p1.x + t * (p2.x - p1.x);	gp1.y = p1.y + t * (p2.y - p1.y);	gp2.x = p2.x + t * (p3.x - p2.x);	gp2.y = p2.y + t * (p3.y - p2.y);	gp0.x = gp0.x + t * (gp1.x - gp0.x);	gp0.y = gp0.y + t * (gp1.y - gp0.y);	gp1.x = gp1.x + t * (gp2.x - gp1.x);	gp1.y = gp1.y + t * (gp2.y - gp1.y);	p.x = gp0.x + t * (gp1.x - gp0.x) + 0.5;	p.y = gp0.y + t * (gp1.y - gp0.y) + 0.5;	if (Gppi >= Gppn) {	    n = (((Gppi + 1) + PPINCR - 1) / PPINCR) * PPINCR;	    Gppp = Marraygrow(Gppp, (long) n * PPSIZE);	    Gppn = n;	}	Gppp[Gppi++] = p;    }}int GCsplinegon(Gwidget_t * widget, int gpn, Gpoint_t * gpp, Ggattr_t * ap){    PIXpoint_t p0, p1, p2, p3;    Grect_t gr;    int n, i;    if (gpn == 0)	return 0;    gr.o = gpp[0], gr.c = gpp[0];    for (i = 1; i < gpn; i++) {	gr.o.x = min(gr.o.x, gpp[i].x);	gr.o.y = min(gr.o.y, gpp[i].y);	gr.c.x = max(gr.c.x, gpp[i].x);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -