📄 gcanvas.c
字号:
/* $Id: gcanvas.c,v 1.4 2005/11/08 17:21:46 ellson Exp $ $Revision: 1.4 $ */ /* 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 ***********************************************************//* Lefteris Koutsofios - AT&T Labs Research */#include "common.h"#include "g.h"#include "gcommon.h"#include "mem.h"#ifdef FEATURE_GMAP#include <gmap.h>#endif#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)static struct cursormap_t { Cursor id; char name[40];} cursormap[XC_num_glyphs];static int curcursori = -1;#define max(a, b) (((a) >= (b)) ? (a) : (b))#define min(a, b) (((a) <= (b)) ? (a) : (b))static char gstyles[][2] = { /* G_SOLID */ { 16, 0, }, /* 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 bezier (PIXpoint_t, PIXpoint_t, PIXpoint_t, PIXpoint_t);static XFontStruct *findfont (char *, int);static int scalebitmap (Gwidget_t *, Gbitmap_t *, Gsize_t, int, int);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 *);static Bool cwvpredicate (Display *, XEvent *, XPointer);static void cweventhandler (Widget, XtPointer, XEvent *, Boolean *);static Bool cwepredicate (Display *, XEvent *, XPointer);int GCcreatewidget ( Gwidget_t *parent, Gwidget_t *widget, int attrn, Gwattr_t *attrp) { PIXsize_t ps; Dimension width, height;#ifdef FEATURE_BACKINGSTORE XSetWindowAttributes xswa;#endif XEvent ev; XColor *cp; XGCValues gcv; int curi, color, ai, r, g, b, i;#ifdef FEATURE_GMAP XVisualInfo *vip; int gmapmode = FALSE;#endif if (!parent) { Gerr (POS, G_ERRNOPARENTWIDGET); return -1; } WCU->func = NULL; WCU->needredraw = FALSE; WCU->buttonsdown = 0; WCU->bstate[0] = WCU->bstate[1] = WCU->bstate[2] = 0; WCU->bstate[3] = WCU->bstate[4] = 0; ps.x = ps.y = MINCWSIZE; RESETARGS; for (ai = 0; ai < attrn; ai++) { switch (attrp[ai].id) { case G_ATTRSIZE: GETSIZE (attrp[ai].u.s, ps, MINCWSIZE); break; case G_ATTRBORDERWIDTH: ADD2ARGS (XtNborderWidth, attrp[ai].u.i); 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: /* will do it after the widget is created */ break; case G_ATTRCOLOR: /* will do it after the widget is created */ break; case G_ATTRVIEWPORT: /* will do it after the widget is created */ break; case G_ATTRWINDOW: /* will do it after the widget is created */ break; case G_ATTRWINDOWID: Gerr (POS, G_ERRCANNOTSETATTR1, "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; } } ADD2ARGS (XtNwidth, ps.x); ADD2ARGS (XtNheight, ps.y);#ifdef FEATURE_GMAP if (gmapmode) { vip = pfChooseFBConfig (Gdisplay, -1, NULL); ADD2ARGS (GLwNvisualInfo, vip); if (!(widget->w = XtCreateWidget ( "graphics", glwDrawingAreaWidgetClass, parent->w, argp, argn ))) { Gerr (POS, G_ERRCANNOTCREATEWIDGET); return -1; } } else { if (!(widget->w = XtCreateWidget ( "graphics", coreWidgetClass, parent->w, argp, argn ))) { Gerr (POS, G_ERRCANNOTCREATEWIDGET); return -1; } } WCU->gmapmode = gmapmode;#else if (!(widget->w = XtCreateWidget ( "graphics", coreWidgetClass, parent->w, argp, argn ))) { Gerr (POS, G_ERRCANNOTCREATEWIDGET); return -1; }#endif XtOverrideTranslations (widget->w, Gcwanytable); XtAddEventHandler ( widget->w, VisibilityChangeMask | ExposureMask, FALSE, cweventhandler, NULL ); Glazymanage (widget->w); Gflushlazyq ();#ifdef FEATURE_BACKINGSTORE xswa.backing_store = WhenMapped; XChangeWindowAttributes ( Gdisplay, XtWindow (widget->w), CWBackingStore, &xswa );#endif /* wait for window to become visible */ XPeekIfEvent (Gdisplay, &ev, cwvpredicate, (XPointer) XtWindow (widget->w)); RESETARGS; ADD2ARGS (XtNwidth, &width); ADD2ARGS (XtNheight, &height); XtGetValues (widget->w, argp, argn); ps.x = width, ps.y = height; WCU->window = XtWindow (widget->w); WCU->cmap = DefaultColormap (Gdisplay, Gscreenn); WCU->gc = XCreateGC (Gdisplay, WCU->window, 0, NULL); RESETARGS; WCU->colors[0].color.pixel = WCU->colors[1].color.pixel = 1000000; ADD2ARGS (XtNbackground, &WCU->colors[0].color.pixel); ADD2ARGS (XtNforeground, &WCU->colors[1].color.pixel); XtGetValues (widget->w, argp, argn); if (WCU->colors[0].color.pixel == 1000000) { if (XGetGCValues (Gdisplay, GC, GCBackground, &gcv) != 0) WCU->colors[0].color.pixel = gcv.background; else WCU->colors[0].color.pixel = WhitePixel (Gdisplay, Gscreenn); } if (WCU->colors[1].color.pixel == 1000000) { if (XGetGCValues (Gdisplay, GC, GCForeground, &gcv) != 0) WCU->colors[1].color.pixel = gcv.foreground; else WCU->colors[1].color.pixel = BlackPixel (Gdisplay, Gscreenn); } XQueryColor (Gdisplay, WCU->cmap, &WCU->colors[0].color); WCU->colors[0].inuse = TRUE; XQueryColor (Gdisplay, WCU->cmap, &WCU->colors[1].color); 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; XSetBackground (Gdisplay, GC, WCU->colors[0].color.pixel); XSetForeground (Gdisplay, GC, WCU->colors[1].color.pixel); WCU->gattr.width = 0; WCU->gattr.mode = G_SRC; 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; if (Gdepth == 1) { XSetFillStyle (Gdisplay, GC, FillTiled); for (i = 0; i < 17; i++) WCU->grays[i] = XCreatePixmapFromBitmapData ( Gdisplay, WCU->window, &grays[i][0], 4, 4, BlackPixel (Gdisplay, Gscreenn), WhitePixel (Gdisplay, Gscreenn), 1 ); } for (ai = 0; ai < attrn; ai++) { switch (attrp[ai].id) { case G_ATTRCURSOR: if ((curi = XmuCursorNameToIndex (attrp[ai].u.t)) == -1) { if (strcmp (attrp[ai].u.t, "default") == 0) { XUndefineCursor (Gdisplay, XtWindow (widget->w)); curcursori = -1; } else { Gerr (POS, G_ERRNOSUCHCURSOR, attrp[ai].u.t); return -1; } } else { if (!cursormap[curi].id) { cursormap[curi].id = XCreateFontCursor (Gdisplay, curi); strcpy (cursormap[curi].name, attrp[ai].u.t); } XDefineCursor ( Gdisplay, XtWindow (widget->w), cursormap[curi].id ); curcursori = curi; } 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]) XFreeColors (Gdisplay, WCU->cmap, &cp->pixel, 1, 0); cp->red = r, cp->green = g, cp->blue = b; if (XAllocColor (Gdisplay, WCU->cmap, cp)) { WCU->colors[color].inuse = TRUE; if (color <= 1) WCU->allocedcolor[color] = TRUE; } /* XAllocColor may change the rgb values */ cp->red = r, cp->green = g, cp->blue = b; if (color == WCU->gattr.color) WCU->gattr.color = -1; if (color == 0 || color == 1) { RESETARGS; if (color == 0) ADD2ARGS (XtNbackground, cp->pixel); else ADD2ARGS (XtNforeground, cp->pixel); XtSetValues (widget->w, argp, argn); } 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); if (WCU->vsize.x > 32767) WCU->vsize.x = 32767; if (WCU->vsize.y > 32767) WCU->vsize.y = 32767; RESETARGS; ADD2ARGS (XtNwidth, WCU->vsize.x); ADD2ARGS (XtNheight, WCU->vsize.y); XtSetValues (widget->w, argp, argn); 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; XColor *cp; int curi, color, ai, r, g, b; RESETARGS; for (ai = 0; ai < attrn; ai++) { switch (attrp[ai].id) { case G_ATTRSIZE: GETSIZE (attrp[ai].u.s, ps, MINCWSIZE); ADD2ARGS (XtNwidth, ps.x); ADD2ARGS (XtNheight, ps.y); break; case G_ATTRBORDERWIDTH: ADD2ARGS (XtNborderWidth, attrp[ai].u.i); break; case G_ATTRCURSOR: if ((curi = XmuCursorNameToIndex (attrp[ai].u.t)) == -1) { if (strcmp (attrp[ai].u.t, "default") == 0) { XUndefineCursor (Gdisplay, XtWindow (widget->w)); curcursori = -1; } else { Gerr (POS, G_ERRNOSUCHCURSOR, attrp[ai].u.t); return -1; } } else { if (!cursormap[curi].id) { cursormap[curi].id = XCreateFontCursor (Gdisplay, curi); strcpy (cursormap[curi].name, attrp[ai].u.t); } XDefineCursor ( Gdisplay, XtWindow (widget->w), cursormap[curi].id ); curcursori = curi; } 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]) XFreeColors (Gdisplay, WCU->cmap, &cp->pixel, 1, 0); cp->red = r, cp->green = g, cp->blue = b; if (XAllocColor (Gdisplay, WCU->cmap, cp)) { WCU->colors[color].inuse = TRUE; if (color <= 1) WCU->allocedcolor[color] = TRUE; } /* XAllocColor may change the rgb values */ cp->red = r, cp->green = g, cp->blue = b; if (color == 0) { XSetBackground (Gdisplay, GC, WCU->colors[0].color.pixel); ADD2ARGS (XtNbackground, WCU->colors[0].color.pixel); } else if (color == 1) { XSetForeground (Gdisplay, GC, WCU->colors[1].color.pixel); ADD2ARGS (XtNforeground, WCU->colors[1].color.pixel); } XtSetValues (widget->w, argp, argn); RESETARGS; 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); if (WCU->vsize.x > 32767) WCU->vsize.x = 32767; if (WCU->vsize.y > 32767) WCU->vsize.y = 32767; ADD2ARGS (XtNwidth, WCU->vsize.x); ADD2ARGS (XtNheight, WCU->vsize.y); XtSetValues (widget->w, argp, argn); adjustclip (widget); RESETARGS; break; case G_ATTRWINDOW: WCU->wrect = attrp[ai].u.r; XtSetValues (widget->w, argp, argn); adjustclip (widget); RESETARGS; break; case G_ATTRWINDOWID: Gerr (POS, G_ERRCANNOTSETATTR2, "windowid"); return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -