diff options
Diffstat (limited to 'src/libui_sdl/libui/unix/drawpath.c')
-rw-r--r-- | src/libui_sdl/libui/unix/drawpath.c | 199 |
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; +} |