123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428 |
- /*************************************************************************
- * Copyright (c) 2011 AT&T Intellectual Property
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * https://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors: Details at https://graphviz.org
- *************************************************************************/
- /*
- XDOT DRAWING FUNCTIONS, maybe need to move them somewhere else
- for now keep them at the bottom
- */
- #include "draw.h"
- #include <common/colorprocs.h>
- #include <common/types.h>
- #include <common/utils.h>
- #include "smyrna_utils.h"
- #include <glcomp/glutils.h>
- #include <math.h>
- #include <stdbool.h>
- #include <stdlib.h>
- #include <util/unreachable.h>
- #include <xdot/xdot.h>
- #include "viewport.h"
- #include "topfisheyeview.h"
- #include "appmouse.h"
- #include "hotkeymap.h"
- #include "polytess.h"
- #include <glcomp/glcompimage.h>
- //delta values
- static float dx = 0.0;
- static float dy = 0.0;
- #define LAYER_DIFF 0.001
- static void DrawBezier(xdot_point* pts, int filled, int param)
- {
- /*copied from NEHE */
- /*Written by: David Nikdel ( [email protected] ) */
- double Ax = pts[0].x;
- double Ay = pts[0].y;
- double Az = pts[0].z;
- double Bx = pts[1].x;
- double By = pts[1].y;
- double Bz = pts[1].z;
- double Cx = pts[2].x;
- double Cy = pts[2].y;
- double Cz = pts[2].z;
- double Dx = pts[3].x;
- double Dy = pts[3].y;
- double Dz = pts[3].z;
- double X;
- double Y;
- double Z;
- int i = 0; //loop index
- // Variable
- double a = 1.0;
- double b = 1.0 - a;
- /* Tell OGL to start drawing a line strip */
- glLineWidth(view->LineWidth);
- if (!filled) {
- if (param == 0)
- glColor4f(view->penColor.R, view->penColor.G, view->penColor.B,
- view->penColor.A);
- else if (param == 1) //selected
- glColor4f(view->selectedNodeColor.R, view->selectedNodeColor.G,
- view->selectedNodeColor.B,
- view->selectedNodeColor.A);
- glBegin(GL_LINE_STRIP);
- } else {
- if (param == 0)
- glColor4f(view->fillColor.R, view->fillColor.G,
- view->fillColor.B, view->penColor.A);
- else if (param == 1) //selected
- glColor4f(view->selectedNodeColor.R, view->selectedNodeColor.G,
- view->selectedNodeColor.B,
- view->selectedNodeColor.A);
- glBegin(GL_POLYGON);
- }
- /* We will not actually draw a curve, but we will divide the curve into small
- points and draw a line between each point. If the points are close enough, it
- will appear as a curved line. 20 points are plenty, and since the variable goes
- from 1.0 to 0.0 we must change it by 1/20 = 0.05 each time */
- for (i = 0; i <= 20; i++) {
- // Get a point on the curve
- X = Ax * a * a * a + Bx * 3 * a * a * b + Cx * 3 * a * b * b +
- Dx * b * b * b;
- Y = Ay * a * a * a + By * 3 * a * a * b + Cy * 3 * a * b * b +
- Dy * b * b * b;
- Z = Az * a * a * a + Bz * 3 * a * a * b + Cz * 3 * a * b * b +
- Dz * b * b * b;
- // Draw the line from point to point (assuming OGL is set up properly)
- glVertex3d(X, Y, Z + view->Topview->global_z);
- // Change the variable
- a -= 0.05;
- b = 1.0 - a;
- }
- // Tell OGL to stop drawing the line strip
- glEnd();
- }
- static void set_options(int param)
- {
- int a=get_mode(view);
- if ((param == 1) && (a == 10) && (view->mouse.down == 1)) //selected, if there is move, move it
- {
- dx = view->mouse.GLinitPos.x-view->mouse.GLfinalPos.x;
- dy = view->mouse.GLinitPos.y-view->mouse.GLfinalPos.y;
- } else {
- dx = 0;
- dy = 0;
- }
- }
- static void DrawBeziers(sdot_op* o, int param)
- {
- int filled;
- xdot_op * op=&o->op;
- xdot_point* ps = op->u.bezier.pts;
- view->Topview->global_z += o->layer * LAYER_DIFF;
- if (op->kind == xd_filled_bezier)
- filled = 1;
- else
- filled = 0;
- for (size_t i = 1; i < op->u.bezier.cnt; i += 3) {
- DrawBezier(ps, filled, param);
- ps += 3;
- }
- }
- //Draws an ellipse made out of points.
- static void DrawEllipse(sdot_op* o, int param)
- {
- int i = 0;
- int filled;
- xdot_op * op=&o->op;
- view->Topview->global_z += o->layer * LAYER_DIFF;
- set_options(param);
- double x = op->u.ellipse.x - dx;
- double y = op->u.ellipse.y - dy;
- double xradius = op->u.ellipse.w;
- double yradius = op->u.ellipse.h;
- if (op->kind == xd_filled_ellipse) {
- if (param == 0)
- glColor4f(view->fillColor.R, view->fillColor.G,
- view->fillColor.B, view->fillColor.A);
- if (param == 1) //selected
- glColor4f(view->selectedNodeColor.R, view->selectedNodeColor.G,
- view->selectedNodeColor.B,
- view->selectedNodeColor.A);
- filled = 1;
- } else {
- if (param == 0)
- glColor4f(view->penColor.R, view->penColor.G, view->penColor.B,
- view->penColor.A);
- if (param == 1) //selected
- glColor4f(view->selectedNodeColor.R, view->selectedNodeColor.G,
- view->selectedNodeColor.B,
- view->selectedNodeColor.A);
- filled = 0;
- }
- if (!filled)
- glBegin(GL_LINE_LOOP);
- else
- glBegin(GL_POLYGON);
- for (i = 0; i < 360; i = i + 1) {
- //convert degrees into radians
- float degInRad = (float) (i * DEG2RAD);
- glVertex3f((float)(x + cos(degInRad) * xradius),
- (float)(y + sin(degInRad) * yradius), (float)view->Topview->global_z);
- }
- glEnd();
- }
- static void DrawPolygon(sdot_op * o, int param)
- {
- xdot_op * op=&o->op;
- view->Topview->global_z += o->layer * LAYER_DIFF;
- set_options(param);
- if (op->kind == xd_filled_polygon) {
- if (param == 0)
- glColor4f(view->fillColor.R, view->fillColor.G,
- view->fillColor.B, view->fillColor.A);
- if (param == 1) //selected
- glColor4f(view->selectedNodeColor.R, view->selectedNodeColor.G,
- view->selectedNodeColor.B,
- view->selectedNodeColor.A);
- } else {
- if (param == 0)
- glColor4f(view->penColor.R, view->penColor.G, view->penColor.B,
- view->penColor.A);
- if (param == 1) //selected
- glColor4f(view->selectedNodeColor.R, view->selectedNodeColor.G,
- view->selectedNodeColor.B,
- view->selectedNodeColor.A);
- }
- glLineWidth(view->LineWidth);
- drawTessPolygon(o);
- }
- static void DrawPolyline(sdot_op* o, int param)
- {
- xdot_op * op=&o->op;
- view->Topview->global_z += o->layer * LAYER_DIFF;
- if (param == 0)
- glColor4f(view->penColor.R, view->penColor.G, view->penColor.B,
- view->penColor.A);
- if (param == 1) //selected
- glColor4f(view->selectedNodeColor.R, view->selectedNodeColor.G,
- view->selectedNodeColor.B, view->selectedNodeColor.A);
- set_options(param);
- glLineWidth(view->LineWidth);
- glBegin(GL_LINE_STRIP);
- for (size_t i = 0; i < op->u.polyline.cnt; ++i) {
- glVertex3f((float)op->u.polyline.pts[i].x - dx,
- (float)op->u.polyline.pts[i].y - dy,
- (float)(op->u.polyline.pts[i].z + view->Topview->global_z));
- }
- glEnd();
- }
- static glCompColor GetglCompColor(const char *color) {
- gvcolor_t cl;
- glCompColor c;
- if (color != NULL) {
- colorxlate(color, &cl, RGBA_DOUBLE);
- c.R = (float) cl.u.RGBA[0];
- c.G = (float) cl.u.RGBA[1];
- c.B = (float) cl.u.RGBA[2];
- c.A = (float) cl.u.RGBA[3];
- } else {
- c = view->penColor;
- }
- return c;
- }
- static void SetFillColor(sdot_op* o, int param)
- {
- (void)param;
- xdot_op * op=&o->op;
- view->fillColor = GetglCompColor(op->u.color);
- }
- static void SetPenColor(sdot_op* o, int param)
- {
- (void)param;
- xdot_op * op=&o->op;
- view->penColor = GetglCompColor(op->u.color);
- }
- static void SetStyle(sdot_op* o, int param)
- {
- (void)o;
- (void)param;
- }
- static sdot_op * font_op;
- static void SetFont(sdot_op * o, int param)
- {
- (void)param;
- font_op=o;
- }
- /*for now we only support png files in 2d space, no image rotation*/
- static void InsertImage(sdot_op * o, int param)
- {
- (void)param;
- float x,y;
- glCompImage *i;
- if(!o->obj)
- return;
- if(!o->img) {
- x = o->op.u.image.pos.x;
- y = o->op.u.image.pos.y;
- i = o->img = glCompImageNewFile(x, y, o->op.u.image.name);
- if (!o->img) {
- fprintf (stderr, "Could not open file \"%s\" to read image.\n", o->op.u.image.name);
- return;
- }
- i->width = o->op.u.image.pos.w;
- i->height = o->op.u.image.pos.h;
- i->base.common.functions.draw(i);
- }
- }
- // see usage in EmbedText
- static int put(void *buffer, const char *s) {
- char **b = buffer;
- for (; *s != '\0'; ++s) {
- **b = *s;
- ++(*b);
- }
- return 0;
- }
- static void EmbedText(sdot_op* o, int param)
- {
- (void)param;
- float x, y;
- glColor4f(view->penColor.R,view->penColor.G,view->penColor.B,view->penColor.A);
- view->Topview->global_z += o->layer * LAYER_DIFF + 0.05;
- switch (o->op.u.text.align)
- {
- case xd_left:
- x=o->op.u.text.x ;
- break;
- case xd_center:
- x=o->op.u.text.x - o->op.u.text.width / 2.0;
- break;
- case xd_right:
- x=o->op.u.text.x - o->op.u.text.width;
- break;
- default:
- UNREACHABLE();
- }
- y=o->op.u.text.y;
- if (o->font.fontdesc == NULL) {
- // allocate a buffer large enough to hold the maximum escaped version of the
- // text
- char *escaped = calloc(sizeof(char), strlen(o->op.u.text.text) *
- sizeof("�") + 1);
- if (escaped == NULL)
- return;
- // XML-escape the text
- const xml_flags_t flags = {.dash = 1, .nbsp = 1};
- char **ptr = &escaped;
- (void)xml_escape(o->op.u.text.text, flags, put, ptr);
- o->font = glNewFont(view->widgets, escaped, &view->penColor,
- font_op->op.u.font.name, font_op->op.u.font.size,
- false);
- free(escaped);
- }
- glCompDrawText3D(o->font, x, y, view->Topview->global_z, o->op.u.text.width,
- font_op->op.u.font.size);
- }
- void drawBorders(ViewInfo * vi)
- {
- if (vi->bdVisible) {
- glColor4f(vi->borderColor.R, vi->borderColor.G,
- vi->borderColor.B, vi->borderColor.A);
- glLineWidth(2);
- glBegin(GL_LINE_STRIP);
- glVertex3d(vi->bdxLeft, vi->bdyBottom,-0.001);
- glVertex3d(vi->bdxRight, vi->bdyBottom,-0.001);
- glVertex3d(vi->bdxRight, vi->bdyTop,-0.001);
- glVertex3d(vi->bdxLeft, vi->bdyTop,-0.001);
- glVertex3d(vi->bdxLeft, vi->bdyBottom,-0.001);
- glEnd();
- glLineWidth(1);
- }
- }
- void drawCircle(float x, float y, float radius, float zdepth)
- {
- int i;
- if (radius < 0.3)
- radius = 0.4f;
- glBegin(GL_POLYGON);
- for (i = 0; i < 360; i = i + 36) {
- float degInRad = (float) (i * DEG2RAD);
- glVertex3f((float)(x + cos(degInRad) * radius),
- (float)(y + sin(degInRad) * radius),
- (float)(zdepth + view->Topview->global_z));
- }
- glEnd();
- }
- drawfunc_t OpFns[] = {
- (drawfunc_t)DrawEllipse,
- (drawfunc_t)DrawPolygon,
- (drawfunc_t)DrawBeziers,
- (drawfunc_t)DrawPolyline,
- (drawfunc_t)EmbedText,
- (drawfunc_t)SetFillColor,
- (drawfunc_t)SetPenColor,
- (drawfunc_t)SetFont,
- (drawfunc_t)SetStyle,
- (drawfunc_t)InsertImage,
- };
- void draw_selpoly(glCompPoly_t *selPoly) {
- glColor4f(1,0,0,1);
- glBegin(GL_LINE_STRIP);
- for (size_t i = 0; i < glCompPoly_size(selPoly); ++i) {
- const glCompPoint pt = glCompPoly_get(selPoly, i);
- glVertex3f(pt.x, pt.y, pt.z);
- }
- glEnd();
- if (!glCompPoly_is_empty(selPoly)) {
- const glCompPoint last = *glCompPoly_back(selPoly);
- glBegin(GL_LINE_STRIP);
- glVertex3f(last.x, last.y, last.z);
- glVertex3f(view->mouse.GLpos.x,view->mouse.GLpos.y,0);
- glEnd();
- }
- }
|