draw.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. /*************************************************************************
  2. * Copyright (c) 2011 AT&T Intellectual Property
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * https://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: Details at https://graphviz.org
  9. *************************************************************************/
  10. /*
  11. XDOT DRAWING FUNCTIONS, maybe need to move them somewhere else
  12. for now keep them at the bottom
  13. */
  14. #include "draw.h"
  15. #include <common/colorprocs.h>
  16. #include <common/types.h>
  17. #include <common/utils.h>
  18. #include "smyrna_utils.h"
  19. #include <glcomp/glutils.h>
  20. #include <math.h>
  21. #include <stdbool.h>
  22. #include <stdlib.h>
  23. #include <util/unreachable.h>
  24. #include <xdot/xdot.h>
  25. #include "viewport.h"
  26. #include "topfisheyeview.h"
  27. #include "appmouse.h"
  28. #include "hotkeymap.h"
  29. #include "polytess.h"
  30. #include <glcomp/glcompimage.h>
  31. //delta values
  32. static float dx = 0.0;
  33. static float dy = 0.0;
  34. #define LAYER_DIFF 0.001
  35. static void DrawBezier(xdot_point* pts, int filled, int param)
  36. {
  37. /*copied from NEHE */
  38. /*Written by: David Nikdel ( [email protected] ) */
  39. double Ax = pts[0].x;
  40. double Ay = pts[0].y;
  41. double Az = pts[0].z;
  42. double Bx = pts[1].x;
  43. double By = pts[1].y;
  44. double Bz = pts[1].z;
  45. double Cx = pts[2].x;
  46. double Cy = pts[2].y;
  47. double Cz = pts[2].z;
  48. double Dx = pts[3].x;
  49. double Dy = pts[3].y;
  50. double Dz = pts[3].z;
  51. double X;
  52. double Y;
  53. double Z;
  54. int i = 0; //loop index
  55. // Variable
  56. double a = 1.0;
  57. double b = 1.0 - a;
  58. /* Tell OGL to start drawing a line strip */
  59. glLineWidth(view->LineWidth);
  60. if (!filled) {
  61. if (param == 0)
  62. glColor4f(view->penColor.R, view->penColor.G, view->penColor.B,
  63. view->penColor.A);
  64. else if (param == 1) //selected
  65. glColor4f(view->selectedNodeColor.R, view->selectedNodeColor.G,
  66. view->selectedNodeColor.B,
  67. view->selectedNodeColor.A);
  68. glBegin(GL_LINE_STRIP);
  69. } else {
  70. if (param == 0)
  71. glColor4f(view->fillColor.R, view->fillColor.G,
  72. view->fillColor.B, view->penColor.A);
  73. else if (param == 1) //selected
  74. glColor4f(view->selectedNodeColor.R, view->selectedNodeColor.G,
  75. view->selectedNodeColor.B,
  76. view->selectedNodeColor.A);
  77. glBegin(GL_POLYGON);
  78. }
  79. /* We will not actually draw a curve, but we will divide the curve into small
  80. points and draw a line between each point. If the points are close enough, it
  81. will appear as a curved line. 20 points are plenty, and since the variable goes
  82. from 1.0 to 0.0 we must change it by 1/20 = 0.05 each time */
  83. for (i = 0; i <= 20; i++) {
  84. // Get a point on the curve
  85. X = Ax * a * a * a + Bx * 3 * a * a * b + Cx * 3 * a * b * b +
  86. Dx * b * b * b;
  87. Y = Ay * a * a * a + By * 3 * a * a * b + Cy * 3 * a * b * b +
  88. Dy * b * b * b;
  89. Z = Az * a * a * a + Bz * 3 * a * a * b + Cz * 3 * a * b * b +
  90. Dz * b * b * b;
  91. // Draw the line from point to point (assuming OGL is set up properly)
  92. glVertex3d(X, Y, Z + view->Topview->global_z);
  93. // Change the variable
  94. a -= 0.05;
  95. b = 1.0 - a;
  96. }
  97. // Tell OGL to stop drawing the line strip
  98. glEnd();
  99. }
  100. static void set_options(int param)
  101. {
  102. int a=get_mode(view);
  103. if ((param == 1) && (a == 10) && (view->mouse.down == 1)) //selected, if there is move, move it
  104. {
  105. dx = view->mouse.GLinitPos.x-view->mouse.GLfinalPos.x;
  106. dy = view->mouse.GLinitPos.y-view->mouse.GLfinalPos.y;
  107. } else {
  108. dx = 0;
  109. dy = 0;
  110. }
  111. }
  112. static void DrawBeziers(sdot_op* o, int param)
  113. {
  114. int filled;
  115. xdot_op * op=&o->op;
  116. xdot_point* ps = op->u.bezier.pts;
  117. view->Topview->global_z += o->layer * LAYER_DIFF;
  118. if (op->kind == xd_filled_bezier)
  119. filled = 1;
  120. else
  121. filled = 0;
  122. for (size_t i = 1; i < op->u.bezier.cnt; i += 3) {
  123. DrawBezier(ps, filled, param);
  124. ps += 3;
  125. }
  126. }
  127. //Draws an ellipse made out of points.
  128. static void DrawEllipse(sdot_op* o, int param)
  129. {
  130. int i = 0;
  131. int filled;
  132. xdot_op * op=&o->op;
  133. view->Topview->global_z += o->layer * LAYER_DIFF;
  134. set_options(param);
  135. double x = op->u.ellipse.x - dx;
  136. double y = op->u.ellipse.y - dy;
  137. double xradius = op->u.ellipse.w;
  138. double yradius = op->u.ellipse.h;
  139. if (op->kind == xd_filled_ellipse) {
  140. if (param == 0)
  141. glColor4f(view->fillColor.R, view->fillColor.G,
  142. view->fillColor.B, view->fillColor.A);
  143. if (param == 1) //selected
  144. glColor4f(view->selectedNodeColor.R, view->selectedNodeColor.G,
  145. view->selectedNodeColor.B,
  146. view->selectedNodeColor.A);
  147. filled = 1;
  148. } else {
  149. if (param == 0)
  150. glColor4f(view->penColor.R, view->penColor.G, view->penColor.B,
  151. view->penColor.A);
  152. if (param == 1) //selected
  153. glColor4f(view->selectedNodeColor.R, view->selectedNodeColor.G,
  154. view->selectedNodeColor.B,
  155. view->selectedNodeColor.A);
  156. filled = 0;
  157. }
  158. if (!filled)
  159. glBegin(GL_LINE_LOOP);
  160. else
  161. glBegin(GL_POLYGON);
  162. for (i = 0; i < 360; i = i + 1) {
  163. //convert degrees into radians
  164. float degInRad = (float) (i * DEG2RAD);
  165. glVertex3f((float)(x + cos(degInRad) * xradius),
  166. (float)(y + sin(degInRad) * yradius), (float)view->Topview->global_z);
  167. }
  168. glEnd();
  169. }
  170. static void DrawPolygon(sdot_op * o, int param)
  171. {
  172. xdot_op * op=&o->op;
  173. view->Topview->global_z += o->layer * LAYER_DIFF;
  174. set_options(param);
  175. if (op->kind == xd_filled_polygon) {
  176. if (param == 0)
  177. glColor4f(view->fillColor.R, view->fillColor.G,
  178. view->fillColor.B, view->fillColor.A);
  179. if (param == 1) //selected
  180. glColor4f(view->selectedNodeColor.R, view->selectedNodeColor.G,
  181. view->selectedNodeColor.B,
  182. view->selectedNodeColor.A);
  183. } else {
  184. if (param == 0)
  185. glColor4f(view->penColor.R, view->penColor.G, view->penColor.B,
  186. view->penColor.A);
  187. if (param == 1) //selected
  188. glColor4f(view->selectedNodeColor.R, view->selectedNodeColor.G,
  189. view->selectedNodeColor.B,
  190. view->selectedNodeColor.A);
  191. }
  192. glLineWidth(view->LineWidth);
  193. drawTessPolygon(o);
  194. }
  195. static void DrawPolyline(sdot_op* o, int param)
  196. {
  197. xdot_op * op=&o->op;
  198. view->Topview->global_z += o->layer * LAYER_DIFF;
  199. if (param == 0)
  200. glColor4f(view->penColor.R, view->penColor.G, view->penColor.B,
  201. view->penColor.A);
  202. if (param == 1) //selected
  203. glColor4f(view->selectedNodeColor.R, view->selectedNodeColor.G,
  204. view->selectedNodeColor.B, view->selectedNodeColor.A);
  205. set_options(param);
  206. glLineWidth(view->LineWidth);
  207. glBegin(GL_LINE_STRIP);
  208. for (size_t i = 0; i < op->u.polyline.cnt; ++i) {
  209. glVertex3f((float)op->u.polyline.pts[i].x - dx,
  210. (float)op->u.polyline.pts[i].y - dy,
  211. (float)(op->u.polyline.pts[i].z + view->Topview->global_z));
  212. }
  213. glEnd();
  214. }
  215. static glCompColor GetglCompColor(const char *color) {
  216. gvcolor_t cl;
  217. glCompColor c;
  218. if (color != NULL) {
  219. colorxlate(color, &cl, RGBA_DOUBLE);
  220. c.R = (float) cl.u.RGBA[0];
  221. c.G = (float) cl.u.RGBA[1];
  222. c.B = (float) cl.u.RGBA[2];
  223. c.A = (float) cl.u.RGBA[3];
  224. } else {
  225. c = view->penColor;
  226. }
  227. return c;
  228. }
  229. static void SetFillColor(sdot_op* o, int param)
  230. {
  231. (void)param;
  232. xdot_op * op=&o->op;
  233. view->fillColor = GetglCompColor(op->u.color);
  234. }
  235. static void SetPenColor(sdot_op* o, int param)
  236. {
  237. (void)param;
  238. xdot_op * op=&o->op;
  239. view->penColor = GetglCompColor(op->u.color);
  240. }
  241. static void SetStyle(sdot_op* o, int param)
  242. {
  243. (void)o;
  244. (void)param;
  245. }
  246. static sdot_op * font_op;
  247. static void SetFont(sdot_op * o, int param)
  248. {
  249. (void)param;
  250. font_op=o;
  251. }
  252. /*for now we only support png files in 2d space, no image rotation*/
  253. static void InsertImage(sdot_op * o, int param)
  254. {
  255. (void)param;
  256. float x,y;
  257. glCompImage *i;
  258. if(!o->obj)
  259. return;
  260. if(!o->img) {
  261. x = o->op.u.image.pos.x;
  262. y = o->op.u.image.pos.y;
  263. i = o->img = glCompImageNewFile(x, y, o->op.u.image.name);
  264. if (!o->img) {
  265. fprintf (stderr, "Could not open file \"%s\" to read image.\n", o->op.u.image.name);
  266. return;
  267. }
  268. i->width = o->op.u.image.pos.w;
  269. i->height = o->op.u.image.pos.h;
  270. i->base.common.functions.draw(i);
  271. }
  272. }
  273. // see usage in EmbedText
  274. static int put(void *buffer, const char *s) {
  275. char **b = buffer;
  276. for (; *s != '\0'; ++s) {
  277. **b = *s;
  278. ++(*b);
  279. }
  280. return 0;
  281. }
  282. static void EmbedText(sdot_op* o, int param)
  283. {
  284. (void)param;
  285. float x, y;
  286. glColor4f(view->penColor.R,view->penColor.G,view->penColor.B,view->penColor.A);
  287. view->Topview->global_z += o->layer * LAYER_DIFF + 0.05;
  288. switch (o->op.u.text.align)
  289. {
  290. case xd_left:
  291. x=o->op.u.text.x ;
  292. break;
  293. case xd_center:
  294. x=o->op.u.text.x - o->op.u.text.width / 2.0;
  295. break;
  296. case xd_right:
  297. x=o->op.u.text.x - o->op.u.text.width;
  298. break;
  299. default:
  300. UNREACHABLE();
  301. }
  302. y=o->op.u.text.y;
  303. if (o->font.fontdesc == NULL) {
  304. // allocate a buffer large enough to hold the maximum escaped version of the
  305. // text
  306. char *escaped = calloc(sizeof(char), strlen(o->op.u.text.text) *
  307. sizeof("&#xFFFFFFFF;") + 1);
  308. if (escaped == NULL)
  309. return;
  310. // XML-escape the text
  311. const xml_flags_t flags = {.dash = 1, .nbsp = 1};
  312. char **ptr = &escaped;
  313. (void)xml_escape(o->op.u.text.text, flags, put, ptr);
  314. o->font = glNewFont(view->widgets, escaped, &view->penColor,
  315. font_op->op.u.font.name, font_op->op.u.font.size,
  316. false);
  317. free(escaped);
  318. }
  319. glCompDrawText3D(o->font, x, y, view->Topview->global_z, o->op.u.text.width,
  320. font_op->op.u.font.size);
  321. }
  322. void drawBorders(ViewInfo * vi)
  323. {
  324. if (vi->bdVisible) {
  325. glColor4f(vi->borderColor.R, vi->borderColor.G,
  326. vi->borderColor.B, vi->borderColor.A);
  327. glLineWidth(2);
  328. glBegin(GL_LINE_STRIP);
  329. glVertex3d(vi->bdxLeft, vi->bdyBottom,-0.001);
  330. glVertex3d(vi->bdxRight, vi->bdyBottom,-0.001);
  331. glVertex3d(vi->bdxRight, vi->bdyTop,-0.001);
  332. glVertex3d(vi->bdxLeft, vi->bdyTop,-0.001);
  333. glVertex3d(vi->bdxLeft, vi->bdyBottom,-0.001);
  334. glEnd();
  335. glLineWidth(1);
  336. }
  337. }
  338. void drawCircle(float x, float y, float radius, float zdepth)
  339. {
  340. int i;
  341. if (radius < 0.3)
  342. radius = 0.4f;
  343. glBegin(GL_POLYGON);
  344. for (i = 0; i < 360; i = i + 36) {
  345. float degInRad = (float) (i * DEG2RAD);
  346. glVertex3f((float)(x + cos(degInRad) * radius),
  347. (float)(y + sin(degInRad) * radius),
  348. (float)(zdepth + view->Topview->global_z));
  349. }
  350. glEnd();
  351. }
  352. drawfunc_t OpFns[] = {
  353. (drawfunc_t)DrawEllipse,
  354. (drawfunc_t)DrawPolygon,
  355. (drawfunc_t)DrawBeziers,
  356. (drawfunc_t)DrawPolyline,
  357. (drawfunc_t)EmbedText,
  358. (drawfunc_t)SetFillColor,
  359. (drawfunc_t)SetPenColor,
  360. (drawfunc_t)SetFont,
  361. (drawfunc_t)SetStyle,
  362. (drawfunc_t)InsertImage,
  363. };
  364. void draw_selpoly(glCompPoly_t *selPoly) {
  365. glColor4f(1,0,0,1);
  366. glBegin(GL_LINE_STRIP);
  367. for (size_t i = 0; i < glCompPoly_size(selPoly); ++i) {
  368. const glCompPoint pt = glCompPoly_get(selPoly, i);
  369. glVertex3f(pt.x, pt.y, pt.z);
  370. }
  371. glEnd();
  372. if (!glCompPoly_is_empty(selPoly)) {
  373. const glCompPoint last = *glCompPoly_back(selPoly);
  374. glBegin(GL_LINE_STRIP);
  375. glVertex3f(last.x, last.y, last.z);
  376. glVertex3f(view->mouse.GLpos.x,view->mouse.GLpos.y,0);
  377. glEnd();
  378. }
  379. }