Migrated the cairo backend to the new drawing system. That was quick...
This commit is contained in:
parent
b43ec18561
commit
4c2a4aa807
|
@ -5,6 +5,7 @@
|
||||||
#define GDK_VERSION_MAX_ALLOWED GDK_VERSION_3_4
|
#define GDK_VERSION_MAX_ALLOWED GDK_VERSION_3_4
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#define areaWidgetType (areaWidget_get_type())
|
#define areaWidgetType (areaWidget_get_type())
|
||||||
#define areaWidget(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), areaWidgetType, areaWidget))
|
#define areaWidget(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), areaWidgetType, areaWidget))
|
||||||
|
|
296
gtkarea/draw.c
296
gtkarea/draw.c
|
@ -1,6 +1,190 @@
|
||||||
// 6 september 2015
|
// 6 september 2015
|
||||||
#include "area.h"
|
#include "area.h"
|
||||||
|
|
||||||
|
struct uiDrawPath {
|
||||||
|
GArray *pieces;
|
||||||
|
uiDrawFillMode fillMode;
|
||||||
|
gboolean ended;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct piece {
|
||||||
|
int type;
|
||||||
|
double d[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
newFigure,
|
||||||
|
newFigureArc,
|
||||||
|
lineTo,
|
||||||
|
arcTo,
|
||||||
|
bezierTo,
|
||||||
|
closeFigure,
|
||||||
|
addRect,
|
||||||
|
};
|
||||||
|
|
||||||
|
uiDrawPath *uiDrawNewPath(uiDrawFillMode mode)
|
||||||
|
{
|
||||||
|
uiDrawPath *p;
|
||||||
|
|
||||||
|
// TODO uiNew
|
||||||
|
p = g_malloc0(sizeof (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);
|
||||||
|
// TODO uiFree
|
||||||
|
g_free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add(uiDrawPath *p, struct piece *piece)
|
||||||
|
{
|
||||||
|
if (p->ended)
|
||||||
|
g_error("path ended in add()");
|
||||||
|
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 endAngle)
|
||||||
|
{
|
||||||
|
struct piece piece;
|
||||||
|
|
||||||
|
piece.type = newFigureArc;
|
||||||
|
piece.d[0] = xCenter;
|
||||||
|
piece.d[1] = yCenter;
|
||||||
|
piece.d[2] = radius;
|
||||||
|
piece.d[3] = startAngle;
|
||||||
|
piece.d[4] = endAngle;
|
||||||
|
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 endAngle)
|
||||||
|
{
|
||||||
|
struct piece piece;
|
||||||
|
|
||||||
|
piece.type = arcTo;
|
||||||
|
piece.d[0] = xCenter;
|
||||||
|
piece.d[1] = yCenter;
|
||||||
|
piece.d[2] = radius;
|
||||||
|
piece.d[3] = startAngle;
|
||||||
|
piece.d[4] = endAngle;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void runPath(uiDrawPath *p, cairo_t *cr)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
struct piece *piece;
|
||||||
|
|
||||||
|
if (!p->ended)
|
||||||
|
g_error("path not ended in runPath()");
|
||||||
|
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:
|
||||||
|
// the Windows AngleArc() function only goes counterclockwise, so our uiDrawArc() function does too
|
||||||
|
// simulate it in cairo by drawing a negative arc from end to start
|
||||||
|
cairo_arc_negative(cr,
|
||||||
|
piece->d[0],
|
||||||
|
piece->d[1],
|
||||||
|
piece->d[2],
|
||||||
|
piece->d[4],
|
||||||
|
piece->d[3]);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct uiDrawContext {
|
struct uiDrawContext {
|
||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
};
|
};
|
||||||
|
@ -15,72 +199,51 @@ uiDrawContext *newContext(cairo_t *cr)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uiDrawBeginPathRGB(uiDrawContext *c, uint8_t r, uint8_t g, uint8_t b)
|
// TODO replace all g_error with complain
|
||||||
|
static cairo_pattern_t *mkbrush(uiDrawBrush *b)
|
||||||
{
|
{
|
||||||
cairo_set_source_rgb(c->cr,
|
cairo_pattern_t *pat;
|
||||||
((double) r) / 255,
|
size_t i;
|
||||||
((double) g) / 255,
|
|
||||||
((double) b) / 255);
|
switch (b->Type) {
|
||||||
cairo_new_path(c->cr);
|
case uiDrawBrushTypeSolid:
|
||||||
|
pat = cairo_pattern_create_rgba(b->R, b->G, b->B, b->A);
|
||||||
|
break;
|
||||||
|
case uiDrawBrushTypeLinearGradient:
|
||||||
|
pat = cairo_pattern_create_linear(b->X0, b->Y0, b->X1, b->Y1);
|
||||||
|
break;
|
||||||
|
case uiDrawBrushTypeRadialGradient:
|
||||||
|
// make the start circle radius 0 to make it a point
|
||||||
|
pat = cairo_pattern_create_radial(
|
||||||
|
b->X0, b->Y0, 0,
|
||||||
|
b->X1, b->Y1, b->OuterRadius);
|
||||||
|
break;
|
||||||
|
// case uiDrawBrushTypeImage:
|
||||||
|
}
|
||||||
|
if (cairo_pattern_status(pat) != CAIRO_STATUS_SUCCESS)
|
||||||
|
g_error("error creating pattern in mkbrush(): %s",
|
||||||
|
cairo_status_to_string(cairo_pattern_status(pat)));
|
||||||
|
switch (b->Type) {
|
||||||
|
case uiDrawBrushTypeLinearGradient:
|
||||||
|
case uiDrawBrushTypeRadialGradient:
|
||||||
|
for (i = 0; i < b->NumStops; i++)
|
||||||
|
cairo_pattern_add_color_stop_rgba(pat,
|
||||||
|
b->Stops[i].Pos,
|
||||||
|
b->Stops[i].R,
|
||||||
|
b->Stops[i].G,
|
||||||
|
b->Stops[i].B,
|
||||||
|
b->Stops[i].A);
|
||||||
|
}
|
||||||
|
return pat;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uiDrawBeginPathRGBA(uiDrawContext *c, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
void uiDrawStroke(uiDrawContext *c, uiDrawPath *path, uiDrawBrush *b, uiDrawStrokeParams *p)
|
||||||
{
|
{
|
||||||
cairo_set_source_rgba(c->cr,
|
cairo_pattern_t *pat;
|
||||||
((double) r) / 255,
|
|
||||||
((double) g) / 255,
|
|
||||||
((double) b) / 255,
|
|
||||||
((double) a) / 255);
|
|
||||||
cairo_new_path(c->cr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void uiDrawMoveTo(uiDrawContext *c, intmax_t x, intmax_t y)
|
runPath(path, c->cr);
|
||||||
{
|
pat = mkbrush(b);
|
||||||
cairo_move_to(c->cr, ((double) x) + 0.5, ((double) y) + 0.5);
|
cairo_set_source(c->cr, pat);
|
||||||
}
|
|
||||||
|
|
||||||
void uiDrawLineTo(uiDrawContext *c, intmax_t x, intmax_t y)
|
|
||||||
{
|
|
||||||
cairo_line_to(c->cr, ((double) x) + 0.5, ((double) y) + 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
void uiDrawRectangle(uiDrawContext *c, intmax_t x, intmax_t y, intmax_t width, intmax_t height)
|
|
||||||
{
|
|
||||||
cairo_rectangle(c->cr, ((double) x) + 0.5, ((double) y) + 0.5, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void uiDrawArcTo(uiDrawContext *c, intmax_t xCenter, intmax_t yCenter, intmax_t radius, double startAngle, double endAngle, int lineFromCurrentPointToStart)
|
|
||||||
{
|
|
||||||
if (!lineFromCurrentPointToStart)
|
|
||||||
cairo_new_sub_path(c->cr);
|
|
||||||
// the Windows AngleArc() function only goes counterclockwise, so our uiDrawArc() function does too
|
|
||||||
// simulate it in cairo by drawing a negative arc from end to start
|
|
||||||
cairo_arc_negative(c->cr,
|
|
||||||
((double) xCenter) + 0.5,
|
|
||||||
((double) yCenter) + 0.5,
|
|
||||||
radius,
|
|
||||||
endAngle,
|
|
||||||
startAngle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void uiDrawBezierTo(uiDrawContext *c, intmax_t c1x, intmax_t c1y, intmax_t c2x, intmax_t c2y, intmax_t endX, intmax_t endY)
|
|
||||||
{
|
|
||||||
cairo_curve_to(c->cr,
|
|
||||||
((double) c1x) + 0.5,
|
|
||||||
((double) c1y) + 0.5,
|
|
||||||
((double) c2x) + 0.5,
|
|
||||||
((double) c2y) + 0.5,
|
|
||||||
((double) endX) + 0.5,
|
|
||||||
((double) endY) + 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
void uiDrawCloseFigure(uiDrawContext *c)
|
|
||||||
{
|
|
||||||
cairo_close_path(c->cr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void uiDrawStroke(uiDrawContext *c, uiDrawStrokeParams *p)
|
|
||||||
{
|
|
||||||
switch (p->Cap) {
|
switch (p->Cap) {
|
||||||
case uiDrawLineCapFlat:
|
case uiDrawLineCapFlat:
|
||||||
cairo_set_line_cap(c->cr, CAIRO_LINE_CAP_BUTT);
|
cairo_set_line_cap(c->cr, CAIRO_LINE_CAP_BUTT);
|
||||||
|
@ -106,11 +269,17 @@ void uiDrawStroke(uiDrawContext *c, uiDrawStrokeParams *p)
|
||||||
}
|
}
|
||||||
cairo_set_line_width(c->cr, p->Thickness);
|
cairo_set_line_width(c->cr, p->Thickness);
|
||||||
cairo_stroke(c->cr);
|
cairo_stroke(c->cr);
|
||||||
|
cairo_pattern_destroy(pat);
|
||||||
}
|
}
|
||||||
|
|
||||||
void uiDrawFill(uiDrawContext *c, uiDrawFillMode mode)
|
void uiDrawFill(uiDrawContext *c, uiDrawPath *path, uiDrawBrush *b)
|
||||||
{
|
{
|
||||||
switch (mode) {
|
cairo_pattern_t *pat;
|
||||||
|
|
||||||
|
runPath(path, c->cr);
|
||||||
|
pat = mkbrush(b);
|
||||||
|
cairo_set_source(c->cr, pat);
|
||||||
|
switch (path->fillMode) {
|
||||||
case uiDrawFillModeWinding:
|
case uiDrawFillModeWinding:
|
||||||
cairo_set_fill_rule(c->cr, CAIRO_FILL_RULE_WINDING);
|
cairo_set_fill_rule(c->cr, CAIRO_FILL_RULE_WINDING);
|
||||||
break;
|
break;
|
||||||
|
@ -119,4 +288,5 @@ void uiDrawFill(uiDrawContext *c, uiDrawFillMode mode)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cairo_fill(c->cr);
|
cairo_fill(c->cr);
|
||||||
|
cairo_pattern_destroy(pat);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// 29 march 2014
|
// 29 march 2014
|
||||||
// TODO remove
|
// TODO remove
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "uipriv.h"
|
#include "uipriv.h"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue