aboutsummaryrefslogtreecommitdiff
path: root/src/libui_sdl/libui/unix/drawpath.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libui_sdl/libui/unix/drawpath.c')
-rw-r--r--src/libui_sdl/libui/unix/drawpath.c199
1 files changed, 199 insertions, 0 deletions
diff --git a/src/libui_sdl/libui/unix/drawpath.c b/src/libui_sdl/libui/unix/drawpath.c
new file mode 100644
index 0000000..a0165fb
--- /dev/null
+++ b/src/libui_sdl/libui/unix/drawpath.c
@@ -0,0 +1,199 @@
+// 6 september 2015
+#include "uipriv_unix.h"
+#include "draw.h"
+
+struct uiDrawPath {
+ GArray *pieces;
+ uiDrawFillMode fillMode;
+ gboolean ended;
+};
+
+struct piece {
+ int type;
+ double d[8];
+ int b;
+};
+
+enum {
+ newFigure,
+ newFigureArc,
+ lineTo,
+ arcTo,
+ bezierTo,
+ closeFigure,
+ addRect,
+};
+
+uiDrawPath *uiDrawNewPath(uiDrawFillMode mode)
+{
+ uiDrawPath *p;
+
+ p = uiNew(uiDrawPath);
+ p->pieces = g_array_new(FALSE, TRUE, sizeof (struct piece));
+ p->fillMode = mode;
+ return p;
+}
+
+void uiDrawFreePath(uiDrawPath *p)
+{
+ g_array_free(p->pieces, TRUE);
+ uiFree(p);
+}
+
+static void add(uiDrawPath *p, struct piece *piece)
+{
+ if (p->ended)
+ userbug("You cannot modify a uiDrawPath that has been ended. (path: %p)", p);
+ g_array_append_vals(p->pieces, piece, 1);
+}
+
+void uiDrawPathNewFigure(uiDrawPath *p, double x, double y)
+{
+ struct piece piece;
+
+ piece.type = newFigure;
+ piece.d[0] = x;
+ piece.d[1] = y;
+ add(p, &piece);
+}
+
+void uiDrawPathNewFigureWithArc(uiDrawPath *p, double xCenter, double yCenter, double radius, double startAngle, double sweep, int negative)
+{
+ struct piece piece;
+
+ if (sweep > 2 * uiPi)
+ sweep = 2 * uiPi;
+ piece.type = newFigureArc;
+ piece.d[0] = xCenter;
+ piece.d[1] = yCenter;
+ piece.d[2] = radius;
+ piece.d[3] = startAngle;
+ piece.d[4] = sweep;
+ piece.b = negative;
+ add(p, &piece);
+}
+
+void uiDrawPathLineTo(uiDrawPath *p, double x, double y)
+{
+ struct piece piece;
+
+ piece.type = lineTo;
+ piece.d[0] = x;
+ piece.d[1] = y;
+ add(p, &piece);
+}
+
+void uiDrawPathArcTo(uiDrawPath *p, double xCenter, double yCenter, double radius, double startAngle, double sweep, int negative)
+{
+ struct piece piece;
+
+ if (sweep > 2 * uiPi)
+ sweep = 2 * uiPi;
+ piece.type = arcTo;
+ piece.d[0] = xCenter;
+ piece.d[1] = yCenter;
+ piece.d[2] = radius;
+ piece.d[3] = startAngle;
+ piece.d[4] = sweep;
+ piece.b = negative;
+ add(p, &piece);
+}
+
+void uiDrawPathBezierTo(uiDrawPath *p, double c1x, double c1y, double c2x, double c2y, double endX, double endY)
+{
+ struct piece piece;
+
+ piece.type = bezierTo;
+ piece.d[0] = c1x;
+ piece.d[1] = c1y;
+ piece.d[2] = c2x;
+ piece.d[3] = c2y;
+ piece.d[4] = endX;
+ piece.d[5] = endY;
+ add(p, &piece);
+}
+
+void uiDrawPathCloseFigure(uiDrawPath *p)
+{
+ struct piece piece;
+
+ piece.type = closeFigure;
+ add(p, &piece);
+}
+
+void uiDrawPathAddRectangle(uiDrawPath *p, double x, double y, double width, double height)
+{
+ struct piece piece;
+
+ piece.type = addRect;
+ piece.d[0] = x;
+ piece.d[1] = y;
+ piece.d[2] = width;
+ piece.d[3] = height;
+ add(p, &piece);
+}
+
+void uiDrawPathEnd(uiDrawPath *p)
+{
+ p->ended = TRUE;
+}
+
+void runPath(uiDrawPath *p, cairo_t *cr)
+{
+ guint i;
+ struct piece *piece;
+ void (*arc)(cairo_t *, double, double, double, double, double);
+
+ if (!p->ended)
+ userbug("You cannot draw with a uiDrawPath that has not been ended. (path: %p)", p);
+ cairo_new_path(cr);
+ for (i = 0; i < p->pieces->len; i++) {
+ piece = &g_array_index(p->pieces, struct piece, i);
+ switch (piece->type) {
+ case newFigure:
+ cairo_move_to(cr, piece->d[0], piece->d[1]);
+ break;
+ case newFigureArc:
+ cairo_new_sub_path(cr);
+ // fall through
+ case arcTo:
+ arc = cairo_arc;
+ if (piece->b)
+ arc = cairo_arc_negative;
+ (*arc)(cr,
+ piece->d[0],
+ piece->d[1],
+ piece->d[2],
+ piece->d[3],
+ piece->d[3] + piece->d[4]);
+ break;
+ case lineTo:
+ cairo_line_to(cr, piece->d[0], piece->d[1]);
+ break;
+ case bezierTo:
+ cairo_curve_to(cr,
+ piece->d[0],
+ piece->d[1],
+ piece->d[2],
+ piece->d[3],
+ piece->d[4],
+ piece->d[5]);
+ break;
+ case closeFigure:
+ cairo_close_path(cr);
+ break;
+ case addRect:
+ cairo_rectangle(cr,
+ piece->d[0],
+ piece->d[1],
+ piece->d[2],
+ piece->d[3]);
+ break;
+ }
+ }
+}
+
+uiDrawFillMode pathFillMode(uiDrawPath *path)
+{
+ return path->fillMode;
+}