📄 gcanvas.c
字号:
/* $Id: gcanvas.c,v 1.2 2005/04/08 20:45:34 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 ***********************************************************//* Lefteris Koutsofios - AT&T Labs Research */#include "common.h"#include "g.h"#include "gcommon.h"#include "mem.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 max(a, b) (((a) >= (b)) ? (a) : (b))#define min(a, b) (((a) <= (b)) ? (a) : (b))static long gstyles[5] = { /* G_SOLID */ PS_SOLID, /* G_DASHED */ PS_DASH, /* G_DOTTED */ PS_DOT, /* G_LONGDASHED */ PS_DASH, /* G_SHORTDASHED */ PS_DASH,};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 int curcursori = -1;static void bezier (PIXpoint_t, PIXpoint_t, PIXpoint_t, PIXpoint_t);static HFONT 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 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);int GCcreatewidget ( Gwidget_t *parent, Gwidget_t *widget, int attrn, Gwattr_t *attrp) { PIXsize_t ps; /* the 2 here is to provide enough space for palPalEntry[0] and [1] */ LOGPALETTE pal[2]; HBRUSH brush; HPEN pen; HBITMAP bmap; HCURSOR cursor; DWORD wflags; int color, ai, i; if (!parent) { Gerr (POS, G_ERRNOPARENTWIDGET); return -1; } wflags = WS_CHILDWINDOW; 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: wflags |= WS_BORDER; break; 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 = 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; } } Gadjustwrect (parent, &ps); 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 (!(widget->w = CreateWindow ( "CanvasClass", "canvas", wflags, 0, 0, ps.x, ps.y, parent->w, (HMENU) (widget - &Gwidgets[0]), hinstance, NULL ))) { Gerr (POS, G_ERRCANNOTCREATEWIDGET); return -1; } ShowWindow (widget->w, SW_SHOW); UpdateWindow (widget->w); SetCursor (LoadCursor ((HINSTANCE) NULL, IDC_ARROW)); GC = GetDC (widget->w); WCU->ncolor = 2; pal[0].palVersion = 0x300; /* HA HA HA */ pal[0].palNumEntries = 2; pal[0].palPalEntry[0].peRed = 255; pal[0].palPalEntry[0].peGreen = 255; pal[0].palPalEntry[0].peBlue = 255; pal[0].palPalEntry[0].peFlags = 0; pal[0].palPalEntry[1].peRed = 0; pal[0].palPalEntry[1].peGreen = 0; pal[0].palPalEntry[1].peBlue = 0; pal[0].palPalEntry[1].peFlags = 0; WCU->cmap = CreatePalette (&pal[0]); WCU->colors[0].color = pal[0].palPalEntry[0]; for (i = 1; i < G_MAXCOLORS; i++) WCU->colors[i].color = pal[0].palPalEntry[1]; SelectPalette (GC, WCU->cmap, FALSE); RealizePalette (GC); WCU->colors[0].inuse = TRUE; WCU->colors[1].inuse = TRUE; for (i = 2; i < G_MAXCOLORS; i++) WCU->colors[i].inuse = FALSE; WCU->gattr.color = 1; brush = CreateSolidBrush (PALETTEINDEX (1)); SelectObject (GC, brush); pen = CreatePen (PS_SOLID, 1, PALETTEINDEX (1)); SelectObject (GC, pen); SetTextColor (GC, PALETTEINDEX (1)); SetBkMode (GC, TRANSPARENT); WCU->gattr.width = 0; WCU->gattr.mode = G_SRC; WCU->gattr.fill = 0; WCU->gattr.style = 0; WCU->defgattr = WCU->gattr; WCU->font = NULL; if (Gdepth == 1) { for (i = 0; i < 17; i++) { if (!(bmap = CreateBitmap (4, 4, 1, 1, &grays[i][0]))) continue; WCU->grays[i] = CreatePatternBrush (bmap); } } for (ai = 0; ai < attrn; ai++) { switch (attrp[ai].id) { case G_ATTRCURSOR: if (strcmp (attrp[ai].u.t, "watch") == 0) { curcursori = 1; cursor = LoadCursor ((HINSTANCE) NULL, IDC_WAIT); } else if (strcmp (attrp[ai].u.t, "default") == 0) { curcursori = -1; cursor = LoadCursor ((HINSTANCE) NULL, IDC_ARROW); } else { Gerr (POS, G_ERRNOSUCHCURSOR, attrp[ai].u.t); return -1; } SetCursor (cursor); break; case G_ATTRCOLOR: color = attrp[ai].u.c.index; if (color < 0 || color > G_MAXCOLORS) { Gerr (POS, G_ERRBADCOLORINDEX, color); return -1; } WCU->colors[color].color.peRed = attrp[ai].u.c.r; WCU->colors[color].color.peGreen = attrp[ai].u.c.g; WCU->colors[color].color.peBlue = attrp[ai].u.c.b; WCU->colors[color].color.peFlags = 0; if (color >= WCU->ncolor) ResizePalette (WCU->cmap, color + 1), WCU->ncolor = color + 1; SetPaletteEntries ( WCU->cmap, (int) color, 1, &WCU->colors[color].color); RealizePalette (GC); WCU->colors[color].inuse = TRUE; if (color == WCU->gattr.color) WCU->gattr.color = -1; break; case G_ATTRVIEWPORT: if (attrp[ai].u.s.x == 0) attrp[ai].u.s.x = 1; if (attrp[ai].u.s.y == 0) attrp[ai].u.s.y = 1; WCU->vsize.x = (int) (attrp[ai].u.s.x + 0.5); WCU->vsize.y = (int) (attrp[ai].u.s.y + 0.5); SetWindowPos ( widget->w, (HWND) NULL, 0, 0, WCU->vsize.x, WCU->vsize.y, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE ); break; case G_ATTRWINDOW: if (attrp[ai].u.r.o.x == attrp[ai].u.r.c.x) attrp[ai].u.r.c.x = attrp[ai].u.r.o.x + 1; if (attrp[ai].u.r.o.y == attrp[ai].u.r.c.y) attrp[ai].u.r.c.y = attrp[ai].u.r.o.y + 1; WCU->wrect = attrp[ai].u.r; break; } } if (parent && parent->type == G_ARRAYWIDGET) Gawinsertchild (parent, widget); Gadjustclip (widget); return 0;}int GCsetwidgetattr (Gwidget_t *widget, int attrn, Gwattr_t *attrp) { HCURSOR cursor; Gwidget_t *parent; PIXsize_t ps; DWORD wflags1; int ai, color; parent = (widget->pwi == -1) ? NULL : &Gwidgets[widget->pwi]; wflags1 = SWP_NOMOVE | SWP_NOZORDER; for (ai = 0; ai < attrn; ai++) { switch (attrp[ai].id) { case G_ATTRSIZE: GETSIZE (attrp[ai].u.s, ps, MINCWSIZE); Gadjustwrect (parent, &ps); SetWindowPos (widget->w, (HWND) NULL, 0, 0, ps.x, ps.y, wflags1); break; case G_ATTRBORDERWIDTH: Gerr (POS, G_ERRCANNOTSETATTR2, "borderwidth"); return -1; case G_ATTRCURSOR: if (strcmp (attrp[ai].u.t, "watch") == 0) { curcursori = 1; cursor = LoadCursor ((HINSTANCE) NULL, IDC_WAIT); } else if (strcmp (attrp[ai].u.t, "default") == 0) { curcursori = -1; cursor = LoadCursor ((HINSTANCE) NULL, IDC_ARROW); } else { Gerr (POS, G_ERRNOSUCHCURSOR, attrp[ai].u.t); return -1; } SetCursor (cursor); break; case G_ATTRCOLOR: color = attrp[ai].u.c.index; if (color < 0 || color > G_MAXCOLORS) { Gerr (POS, G_ERRBADCOLORINDEX, color); return -1; } WCU->colors[color].color.peRed = attrp[ai].u.c.r; WCU->colors[color].color.peGreen = attrp[ai].u.c.g; WCU->colors[color].color.peBlue = attrp[ai].u.c.b; WCU->colors[color].color.peFlags = 0; if (color >= WCU->ncolor) ResizePalette (WCU->cmap, color + 1), WCU->ncolor = color + 1; SetPaletteEntries ( WCU->cmap, (int) color, 1, &WCU->colors[color].color ); RealizePalette (GC); WCU->colors[color].inuse = TRUE; if (color == WCU->gattr.color) WCU->gattr.color = -1; break; case G_ATTRVIEWPORT: if (attrp[ai].u.s.x == 0) attrp[ai].u.s.x = 1; if (attrp[ai].u.s.y == 0) attrp[ai].u.s.y = 1; WCU->vsize.x = (int) (attrp[ai].u.s.x + 0.5); WCU->vsize.y = (int) (attrp[ai].u.s.y + 0.5); ps.x = WCU->vsize.x, ps.y = WCU->vsize.y; Gadjustwrect (&Gwidgets[widget->pwi], &ps); SetWindowPos ( widget->w, (HWND) NULL, 0, 0, ps.x, ps.y, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE ); Gadjustclip (widget); break; case G_ATTRWINDOW: if (attrp[ai].u.r.o.x == attrp[ai].u.r.c.x) attrp[ai].u.r.c.x = attrp[ai].u.r.o.x + 1; if (attrp[ai].u.r.o.y == attrp[ai].u.r.c.y) attrp[ai].u.r.c.y = attrp[ai].u.r.o.y + 1; WCU->wrect = attrp[ai].u.r; Gadjustclip (widget); break; case G_ATTRWINDOWID: Gerr (POS, G_ERRCANNOTSETATTR2, "windowid"); return -1; case G_ATTREVENTCB: WCU->func = 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) { PALETTEENTRY *cp; RECT r; int color, ai; for (ai = 0; ai < attrn; ai++) { switch (attrp[ai].id) { case G_ATTRSIZE: GetWindowRect (widget->w, &r); attrp[ai].u.s.x = r.right - r.left; attrp[ai].u.s.y = r.bottom - r.top; break; case G_ATTRBORDERWIDTH: Gerr (POS, G_ERRCANNOTGETATTR, "borderwidth"); return -1; case G_ATTRCURSOR: 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->peRed; attrp[ai].u.c.g = cp->peGreen; attrp[ai].u.c.b = cp->peBlue; } 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", widget->w); attrp[ai].u.t = &Gbufp[0]; 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) { Gwidget_t *parent; parent = (widget->pwi == -1) ? NULL : &Gwidgets[widget->pwi]; if (parent && parent->type == G_ARRAYWIDGET) Gawdeletechild (parent, widget); DestroyWindow (widget->w); return 0;}int GCcanvasclear (Gwidget_t *widget) { Ggattr_t attr; RECT r; HBRUSH brush, pbrush; attr.flags = 0; setgattr (widget, &attr); brush = CreateSolidBrush (PALETTEINDEX (0)); pbrush = SelectObject (GC, brush); GetClientRect (widget->w, &r); Rectangle (GC, r.left, r.top, r.right, r.bottom); SelectObject (GC, pbrush); DeleteObject (brush); WCU->needredraw = FALSE; return 0;}int GCsetgfxattr (Gwidget_t *widget, Ggattr_t *ap) { setgattr (widget, ap); WCU->defgattr = WCU->gattr; return 0;}int GCgetgfxattr (Gwidget_t *widget, Ggattr_t *ap) { if ((ap->flags & G_GATTRCOLOR)) ap->color = WCU->gattr.color; if ((ap->flags & G_GATTRWIDTH)) ap->width = WCU->gattr.width; if ((ap->flags & G_GATTRMODE)) ap->mode = WCU->gattr.mode; if ((ap->flags & G_GATTRFILL)) ap->fill = WCU->gattr.fill; if ((ap->flags & G_GATTRSTYLE)) ap->style = WCU->gattr.style; 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -