Started bringing the new drawing code over to the other backends.

This commit is contained in:
Pietro Gagliardi 2015-10-08 08:04:23 -04:00
parent 6787130125
commit b43ec18561
4 changed files with 478 additions and 94 deletions

View File

@ -17,77 +17,216 @@ static GtkWidget *textstr;
static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *p) static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *p)
{ {
uiDrawPath *path;
uiDrawBrush brush;
uiDrawStrokeParams sp; uiDrawStrokeParams sp;
uiDrawBeginPathRGB(p->Context, 0xFF, 0x00, 0x00); brush.Type = uiDrawBrushTypeSolid;
uiDrawMoveTo(p->Context, p->ClipX + 5, p->ClipY + 5); brush.A = 1;
uiDrawLineTo(p->Context, (p->ClipX + p->ClipWidth) - 5, (p->ClipY + p->ClipHeight) - 5);
brush.R = 1;
brush.G = 0;
brush.B = 0;
path = uiDrawNewPath(uiDrawFillModeWinding);
uiDrawPathNewFigure(path, p->ClipX + 5, p->ClipY + 5);
uiDrawPathLineTo(path, (p->ClipX + p->ClipWidth) - 5, (p->ClipY + p->ClipHeight) - 5);
uiDrawPathEnd(path);
sp.Cap = uiDrawLineCapFlat; sp.Cap = uiDrawLineCapFlat;
sp.Join = uiDrawLineJoinMiter; sp.Join = uiDrawLineJoinMiter;
sp.Thickness = 1; sp.Thickness = 1;
sp.MiterLimit = uiDrawDefaultMiterLimit; sp.MiterLimit = uiDrawDefaultMiterLimit;
uiDrawStroke(p->Context, &sp); uiDrawStroke(p->Context, path, &brush, &sp);
uiDrawFreePath(path);
uiDrawBeginPathRGB(p->Context, 0x00, 0x00, 0xC0); brush.R = 0;
uiDrawMoveTo(p->Context, p->ClipX, p->ClipY); brush.G = 0;
uiDrawLineTo(p->Context, p->ClipX + p->ClipWidth, p->ClipY); brush.B = 0.75;
uiDrawLineTo(p->Context, 50, 150); path = uiDrawNewPath(uiDrawFillModeWinding);
uiDrawLineTo(p->Context, 50, 50); uiDrawPathNewFigure(path, p->ClipX, p->ClipY);
uiDrawCloseFigure(p->Context); uiDrawPathLineTo(path, p->ClipX + p->ClipWidth, p->ClipY);
uiDrawPathLineTo(path, 50, 150);
uiDrawPathLineTo(path, 50, 50);
uiDrawPathCloseFigure(path);
uiDrawPathEnd(path);
sp.Cap = uiDrawLineCapFlat; sp.Cap = uiDrawLineCapFlat;
sp.Join = uiDrawLineJoinRound; sp.Join = uiDrawLineJoinRound;
sp.Thickness = 5; sp.Thickness = 5;
uiDrawStroke(p->Context, &sp); uiDrawStroke(p->Context, path, &brush, &sp);
uiDrawFreePath(path);
uiDrawBeginPathRGBA(p->Context, 0x00, 0xC0, 0x00, 0x80); brush.R = 0;
uiDrawRectangle(p->Context, 120, 80, 50, 50); brush.G = 0.75;
uiDrawFill(p->Context, uiDrawFillModeWinding); brush.B = 0;
brush.A = 0.5;
path = uiDrawNewPath(uiDrawFillModeWinding);
uiDrawPathAddRectangle(path, 120, 80, 50, 50);
uiDrawPathEnd(path);
uiDrawFill(p->Context, path, &brush);
uiDrawFreePath(path);
brush.A = 1;
uiDrawBeginPathRGB(p->Context, 0x00, 0x80, 0x00); brush.R = 0;
uiDrawMoveTo(p->Context, 5, 10); brush.G = 0.5;
uiDrawLineTo(p->Context, 5, 50); brush.B = 0;
path = uiDrawNewPath(uiDrawFillModeWinding);
uiDrawPathNewFigure(path, 5.5, 10.5);
uiDrawPathLineTo(path, 5.5, 50.5);
uiDrawPathEnd(path);
sp.Cap = uiDrawLineCapFlat; sp.Cap = uiDrawLineCapFlat;
sp.Join = uiDrawLineJoinMiter; sp.Join = uiDrawLineJoinMiter;
sp.Thickness = 1; sp.Thickness = 1;
sp.MiterLimit = uiDrawDefaultMiterLimit; sp.MiterLimit = uiDrawDefaultMiterLimit;
uiDrawStroke(p->Context, &sp); uiDrawStroke(p->Context, path, &brush, &sp);
uiDrawFreePath(path);
uiDrawBeginPathRGB(p->Context, 0x80, 0xC0, 0x00); brush.R = 0.5;
uiDrawMoveTo(p->Context, 400, 100); brush.G = 0.75;
uiDrawArcTo(p->Context, brush.B = 0;
path = uiDrawNewPath(uiDrawFillModeWinding);
uiDrawPathNewFigure(path, 400, 100);
uiDrawPathArcTo(path,
400, 100, 400, 100,
50, 50,
30. * (M_PI / 180.), 30. * (M_PI / 180.),
// note the end angle here // note the end angle here
// in GDI, the second angle to AngleArc() is relative to the start, not to 0 // in GDI, the second angle to AngleArc() is relative to the start, not to 0
330. * (M_PI / 180.), 330. * (M_PI / 180.));
1);
// TODO add a checkbox for this // TODO add a checkbox for this
uiDrawLineTo(p->Context, 400, 100); uiDrawPathLineTo(path, 400, 100);
uiDrawArcTo(p->Context, uiDrawPathNewFigureWithArc(path,
510, 100, 510, 100,
50, 50,
30. * (M_PI / 180.), 30. * (M_PI / 180.),
330. * (M_PI / 180.), 330. * (M_PI / 180.));
0); uiDrawPathCloseFigure(path);
uiDrawCloseFigure(p->Context); uiDrawPathEnd(path);
sp.Cap = uiDrawLineCapFlat; sp.Cap = uiDrawLineCapFlat;
sp.Join = uiDrawLineJoinMiter; sp.Join = uiDrawLineJoinMiter;
sp.Thickness = 1; sp.Thickness = 1;
sp.MiterLimit = uiDrawDefaultMiterLimit; sp.MiterLimit = uiDrawDefaultMiterLimit;
uiDrawStroke(p->Context, &sp); uiDrawStroke(p->Context, path, &brush, &sp);
uiDrawFreePath(path);
uiDrawBeginPathRGB(p->Context, 0x00, 0x80, 0xC0); brush.R = 0;
uiDrawMoveTo(p->Context, 300, 300); brush.G = 0.5;
uiDrawBezierTo(p->Context, brush.B = 0.75;
path = uiDrawNewPath(uiDrawFillModeWinding);
uiDrawPathNewFigure(path, 300, 300);
uiDrawPathBezierTo(path,
350, 320, 350, 320,
310, 390, 310, 390,
435, 372); 435, 372);
uiDrawPathEnd(path);
sp.Cap = uiDrawLineCapFlat; sp.Cap = uiDrawLineCapFlat;
sp.Join = uiDrawLineJoinMiter; sp.Join = uiDrawLineJoinMiter;
sp.Thickness = 1; sp.Thickness = 1;
sp.MiterLimit = uiDrawDefaultMiterLimit; sp.MiterLimit = uiDrawDefaultMiterLimit;
uiDrawStroke(p->Context, &sp); uiDrawStroke(p->Context, path, &brush, &sp);
uiDrawFreePath(path);
// based on https://msdn.microsoft.com/en-us/library/windows/desktop/dd756682%28v=vs.85%29.aspx
path = uiDrawNewPath(uiDrawFillModeWinding);
#define XO 50
#define YO 250
uiDrawPathNewFigure(path, 0 + XO, 0 + YO);
uiDrawPathLineTo(path, 200 + XO, 0 + YO);
uiDrawPathBezierTo(path,
150 + XO, 50 + YO,
150 + XO, 150 + YO,
200 + XO, 200 + YO);
uiDrawPathLineTo(path, 0 + XO, 200 + YO);
uiDrawPathBezierTo(path,
50 + XO, 150 + YO,
50 + XO, 50 + YO,
0 + XO, 0 + YO);
uiDrawPathCloseFigure(path);
uiDrawPathEnd(path);
// first the stroke
brush.Type = uiDrawBrushTypeSolid;
brush.R = 0;
brush.G = 0;
brush.B = 0;
brush.A = 1;
sp.Cap = uiDrawLineCapFlat;
sp.Join = uiDrawLineJoinMiter;
sp.MiterLimit = uiDrawDefaultMiterLimit;
sp.Thickness = 10;
uiDrawStroke(p->Context, path, &brush, &sp);
// and now the fill
{
uiDrawBrushGradientStop stops[2];
stops[0].Pos = 0.0;
stops[0].R = 0.0;
stops[0].G = 1.0;
stops[0].B = 1.0;
stops[0].A = 0.25;
stops[1].Pos = 1.0;
stops[1].R = 0.0;
stops[1].G = 0.0;
stops[1].B = 1.0;
stops[1].A = 1.0;
brush.Type = uiDrawBrushTypeLinearGradient;
brush.X0 = 100 + XO;
brush.Y0 = 0 + YO;
brush.X1 = 100 + XO;
brush.Y1 = 200 + YO;
brush.Stops = stops;
brush.NumStops = 2;
uiDrawFill(p->Context, path, &brush);
}
#undef YO
#undef XO
uiDrawFreePath(path);
// based on https://msdn.microsoft.com/en-us/library/windows/desktop/dd756679%28v=vs.85%29.aspx
path = uiDrawNewPath(uiDrawFillModeWinding);
uiDrawPathNewFigure(path, 585, 235);
uiDrawPathArcTo(path,
510, 235,
75,
0,
// TODO why doesn't 360° work
2 * M_PI - 0.1);
uiDrawPathEnd(path);
// first the stroke
brush.Type = uiDrawBrushTypeSolid;
brush.R = 0;
brush.G = 0;
brush.B = 0;
brush.A = 1;
sp.Cap = uiDrawLineCapFlat;
sp.Join = uiDrawLineJoinMiter;
sp.MiterLimit = uiDrawDefaultMiterLimit;
sp.Thickness = 1;
uiDrawStroke(p->Context, path, &brush, &sp);
// then the fill
{
uiDrawBrushGradientStop stops[2];
stops[0].Pos = 0.0;
stops[0].R = 1.0;
stops[0].G = 1.0;
stops[0].B = 0.0;
stops[0].A = 1.0;
stops[1].Pos = 1.0;
stops[1].R = ((double) 0x22) / 255.0;
stops[1].G = ((double) 0x8B) / 255.0;
stops[1].B = ((double) 0x22) / 255.0;
stops[1].A = 1.0;
brush.Type = uiDrawBrushTypeRadialGradient;
// start point
brush.X0 = 510;
brush.Y0 = 235;
// outer circle's center
brush.X1 = 510;
brush.Y1 = 235;
brush.OuterRadius = 75;
brush.Stops = stops;
brush.NumStops = 2;
uiDrawFill(p->Context, path, &brush);
}
uiDrawFreePath(path);
} }
static uintmax_t handlerHScrollMax(uiAreaHandler *a, uiArea *area) static uintmax_t handlerHScrollMax(uiAreaHandler *a, uiArea *area)

View File

@ -36,14 +36,26 @@ struct uiAreaDrawParams {
intmax_t VScrollPos; intmax_t VScrollPos;
}; };
// TODO proper sources
// TODO dotting/dashing // TODO dotting/dashing
typedef struct uiDrawPath uiDrawPath;
typedef struct uiDrawBrush uiDrawBrush;
typedef struct uiDrawStrokeParams uiDrawStrokeParams; typedef struct uiDrawStrokeParams uiDrawStrokeParams;
typedef enum uiDrawBrushType uiDrawBrushType;
typedef struct uiDrawBrushGradientStop uiDrawBrushGradientStop;
typedef enum uiDrawLineCap uiDrawLineCap; typedef enum uiDrawLineCap uiDrawLineCap;
typedef enum uiDrawLineJoin uiDrawLineJoin; typedef enum uiDrawLineJoin uiDrawLineJoin;
typedef enum uiDrawFillMode uiDrawFillMode; typedef enum uiDrawFillMode uiDrawFillMode;
enum uiDrawBrushType {
uiDrawBrushTypeSolid,
uiDrawBrushTypeLinearGradient,
uiDrawBrushTypeRadialGradient,
uiDrawBrushTypeImage,
};
enum uiDrawLineCap { enum uiDrawLineCap {
uiDrawLineCapFlat, uiDrawLineCapFlat,
uiDrawLineCapRound, uiDrawLineCapRound,
@ -66,28 +78,69 @@ enum uiDrawFillMode {
uiDrawFillModeAlternate, uiDrawFillModeAlternate,
}; };
struct uiDrawBrush {
uiDrawBrushType Type;
// solid brushes
double R;
double G;
double B;
double A;
// gradient brushes
double X0; // linear: start X, radial: start X
double Y0; // linear: start Y, radial: start Y
double X1; // linear: end X, radial: outer circle center X
double Y1; // linear: end Y, radial: outer circle center Y
double OuterRadius; // radial gradients only
uiDrawBrushGradientStop *Stops;
size_t NumStops;
// TODO extend mode
// cairo: none, repeat, reflect, pad; no individual control
// Direct2D: repeat, reflect, pad; no individual control
// Core Graphics: none, pad; before and after individually
// TODO cairo documentation is inconsistent about pad
// TODO images
// TODO transforms
};
struct uiDrawBrushGradientStop {
double Pos;
double R;
double G;
double B;
double A;
};
struct uiDrawStrokeParams { struct uiDrawStrokeParams {
uiDrawLineCap Cap; uiDrawLineCap Cap;
uiDrawLineJoin Join; uiDrawLineJoin Join;
intmax_t Thickness; double Thickness;
double MiterLimit; double MiterLimit;
}; };
void uiDrawBeginPathRGB(uiDrawContext *, uint8_t, uint8_t, uint8_t); uiDrawPath *uiDrawNewPath(uiDrawFillMode);
// TODO verify these aren't alpha premultiplied anywhere void uiDrawFreePath(uiDrawPath *);
void uiDrawBeginPathRGBA(uiDrawContext *, uint8_t, uint8_t, uint8_t, uint8_t);
void uiDrawMoveTo(uiDrawContext *, intmax_t, intmax_t); void uiDrawPathNewFigure(uiDrawPath *, double, double);
void uiDrawLineTo(uiDrawContext *, intmax_t, intmax_t); void uiDrawPathNewFigureWithArc(uiDrawPath *, double, double, double, double, double);
void uiDrawRectangle(uiDrawContext *, intmax_t, intmax_t, intmax_t, intmax_t); void uiDrawPathLineTo(uiDrawPath *, double, double);
// notes: angles are both relative to 0 and go counterclockwise // notes: angles are both relative to 0 and go counterclockwise
void uiDrawArcTo(uiDrawContext *, intmax_t, intmax_t, intmax_t, double, double, int); // TODO is the initial line segment on cairo and OS X a proper join?
// TODO behavior when there is no initial point on Windows and OS X void uiDrawPathArcTo(uiDrawPath *, double, double, double, double, double);
void uiDrawBezierTo(uiDrawContext *, intmax_t, intmax_t, intmax_t, intmax_t, intmax_t, intmax_t); void uiDrawPathBezierTo(uiDrawPath *, double, double, double, double, double, double);
void uiDrawCloseFigure(uiDrawContext *); // TODO quadratic bezier
void uiDrawPathCloseFigure(uiDrawPath *);
void uiDrawStroke(uiDrawContext *, uiDrawStrokeParams *); // TODO effect of these when a figure is already started
void uiDrawFill(uiDrawContext *, uiDrawFillMode); void uiDrawPathAddRectangle(uiDrawPath *, double, double, double, double);
void uiDrawPathEnd(uiDrawPath *);
void uiDrawStroke(uiDrawContext *, uiDrawPath *, uiDrawBrush *, uiDrawStrokeParams *);
void uiDrawFill(uiDrawContext *, uiDrawPath *, uiDrawBrush *);
// TODO primitives: // TODO primitives:
// - rounded rectangles // - rounded rectangles

View File

@ -16,77 +16,216 @@ static struct handler h;
static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *p) static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *p)
{ {
uiDrawPath *path;
uiDrawBrush brush;
uiDrawStrokeParams sp; uiDrawStrokeParams sp;
uiDrawBeginPathRGB(p->Context, 0xFF, 0x00, 0x00); brush.Type = uiDrawBrushTypeSolid;
uiDrawMoveTo(p->Context, p->ClipX + 5, p->ClipY + 5); brush.A = 1;
uiDrawLineTo(p->Context, (p->ClipX + p->ClipWidth) - 5, (p->ClipY + p->ClipHeight) - 5);
brush.R = 1;
brush.G = 0;
brush.B = 0;
path = uiDrawNewPath(uiDrawFillModeWinding);
uiDrawPathNewFigure(path, p->ClipX + 5, p->ClipY + 5);
uiDrawPathLineTo(path, (p->ClipX + p->ClipWidth) - 5, (p->ClipY + p->ClipHeight) - 5);
uiDrawPathEnd(path);
sp.Cap = uiDrawLineCapFlat; sp.Cap = uiDrawLineCapFlat;
sp.Join = uiDrawLineJoinMiter; sp.Join = uiDrawLineJoinMiter;
sp.Thickness = 1; sp.Thickness = 1;
sp.MiterLimit = uiDrawDefaultMiterLimit; sp.MiterLimit = uiDrawDefaultMiterLimit;
uiDrawStroke(p->Context, &sp); uiDrawStroke(p->Context, path, &brush, &sp);
uiDrawFreePath(path);
uiDrawBeginPathRGB(p->Context, 0x00, 0x00, 0xC0); brush.R = 0;
uiDrawMoveTo(p->Context, p->ClipX, p->ClipY); brush.G = 0;
uiDrawLineTo(p->Context, p->ClipX + p->ClipWidth, p->ClipY); brush.B = 0.75;
uiDrawLineTo(p->Context, 50, 150); path = uiDrawNewPath(uiDrawFillModeWinding);
uiDrawLineTo(p->Context, 50, 50); uiDrawPathNewFigure(path, p->ClipX, p->ClipY);
uiDrawCloseFigure(p->Context); uiDrawPathLineTo(path, p->ClipX + p->ClipWidth, p->ClipY);
uiDrawPathLineTo(path, 50, 150);
uiDrawPathLineTo(path, 50, 50);
uiDrawPathCloseFigure(path);
uiDrawPathEnd(path);
sp.Cap = uiDrawLineCapFlat; sp.Cap = uiDrawLineCapFlat;
sp.Join = uiDrawLineJoinRound; sp.Join = uiDrawLineJoinRound;
sp.Thickness = 5; sp.Thickness = 5;
uiDrawStroke(p->Context, &sp); uiDrawStroke(p->Context, path, &brush, &sp);
uiDrawFreePath(path);
uiDrawBeginPathRGBA(p->Context, 0x00, 0xC0, 0x00, 0x80); brush.R = 0;
uiDrawRectangle(p->Context, 120, 80, 50, 50); brush.G = 0.75;
uiDrawFill(p->Context, uiDrawFillModeWinding); brush.B = 0;
brush.A = 0.5;
path = uiDrawNewPath(uiDrawFillModeWinding);
uiDrawPathAddRectangle(path, 120, 80, 50, 50);
uiDrawPathEnd(path);
uiDrawFill(p->Context, path, &brush);
uiDrawFreePath(path);
brush.A = 1;
uiDrawBeginPathRGB(p->Context, 0x00, 0x80, 0x00); brush.R = 0;
uiDrawMoveTo(p->Context, 5, 10); brush.G = 0.5;
uiDrawLineTo(p->Context, 5, 50); brush.B = 0;
path = uiDrawNewPath(uiDrawFillModeWinding);
uiDrawPathNewFigure(path, 5.5, 10.5);
uiDrawPathLineTo(path, 5.5, 50.5);
uiDrawPathEnd(path);
sp.Cap = uiDrawLineCapFlat; sp.Cap = uiDrawLineCapFlat;
sp.Join = uiDrawLineJoinMiter; sp.Join = uiDrawLineJoinMiter;
sp.Thickness = 1; sp.Thickness = 1;
sp.MiterLimit = uiDrawDefaultMiterLimit; sp.MiterLimit = uiDrawDefaultMiterLimit;
uiDrawStroke(p->Context, &sp); uiDrawStroke(p->Context, path, &brush, &sp);
uiDrawFreePath(path);
uiDrawBeginPathRGB(p->Context, 0x80, 0xC0, 0x00); brush.R = 0.5;
uiDrawMoveTo(p->Context, 400, 100); brush.G = 0.75;
uiDrawArcTo(p->Context, brush.B = 0;
path = uiDrawNewPath(uiDrawFillModeWinding);
uiDrawPathNewFigure(path, 400, 100);
uiDrawPathArcTo(path,
400, 100, 400, 100,
50, 50,
30. * (M_PI / 180.), 30. * (M_PI / 180.),
// note the end angle here // note the end angle here
// in GDI, the second angle to AngleArc() is relative to the start, not to 0 // in GDI, the second angle to AngleArc() is relative to the start, not to 0
330. * (M_PI / 180.), 330. * (M_PI / 180.));
1);
// TODO add a checkbox for this // TODO add a checkbox for this
uiDrawLineTo(p->Context, 400, 100); uiDrawPathLineTo(path, 400, 100);
uiDrawArcTo(p->Context, uiDrawPathNewFigureWithArc(path,
510, 100, 510, 100,
50, 50,
30. * (M_PI / 180.), 30. * (M_PI / 180.),
330. * (M_PI / 180.), 330. * (M_PI / 180.));
0); uiDrawPathCloseFigure(path);
uiDrawCloseFigure(p->Context); uiDrawPathEnd(path);
sp.Cap = uiDrawLineCapFlat; sp.Cap = uiDrawLineCapFlat;
sp.Join = uiDrawLineJoinMiter; sp.Join = uiDrawLineJoinMiter;
sp.Thickness = 1; sp.Thickness = 1;
sp.MiterLimit = uiDrawDefaultMiterLimit; sp.MiterLimit = uiDrawDefaultMiterLimit;
uiDrawStroke(p->Context, &sp); uiDrawStroke(p->Context, path, &brush, &sp);
uiDrawFreePath(path);
uiDrawBeginPathRGB(p->Context, 0x00, 0x80, 0xC0); brush.R = 0;
uiDrawMoveTo(p->Context, 300, 300); brush.G = 0.5;
uiDrawBezierTo(p->Context, brush.B = 0.75;
path = uiDrawNewPath(uiDrawFillModeWinding);
uiDrawPathNewFigure(path, 300, 300);
uiDrawPathBezierTo(path,
350, 320, 350, 320,
310, 390, 310, 390,
435, 372); 435, 372);
uiDrawPathEnd(path);
sp.Cap = uiDrawLineCapFlat; sp.Cap = uiDrawLineCapFlat;
sp.Join = uiDrawLineJoinMiter; sp.Join = uiDrawLineJoinMiter;
sp.Thickness = 1; sp.Thickness = 1;
sp.MiterLimit = uiDrawDefaultMiterLimit; sp.MiterLimit = uiDrawDefaultMiterLimit;
uiDrawStroke(p->Context, &sp); uiDrawStroke(p->Context, path, &brush, &sp);
uiDrawFreePath(path);
// based on https://msdn.microsoft.com/en-us/library/windows/desktop/dd756682%28v=vs.85%29.aspx
path = uiDrawNewPath(uiDrawFillModeWinding);
#define XO 50
#define YO 250
uiDrawPathNewFigure(path, 0 + XO, 0 + YO);
uiDrawPathLineTo(path, 200 + XO, 0 + YO);
uiDrawPathBezierTo(path,
150 + XO, 50 + YO,
150 + XO, 150 + YO,
200 + XO, 200 + YO);
uiDrawPathLineTo(path, 0 + XO, 200 + YO);
uiDrawPathBezierTo(path,
50 + XO, 150 + YO,
50 + XO, 50 + YO,
0 + XO, 0 + YO);
uiDrawPathCloseFigure(path);
uiDrawPathEnd(path);
// first the stroke
brush.Type = uiDrawBrushTypeSolid;
brush.R = 0;
brush.G = 0;
brush.B = 0;
brush.A = 1;
sp.Cap = uiDrawLineCapFlat;
sp.Join = uiDrawLineJoinMiter;
sp.MiterLimit = uiDrawDefaultMiterLimit;
sp.Thickness = 10;
uiDrawStroke(p->Context, path, &brush, &sp);
// and now the fill
{
uiDrawBrushGradientStop stops[2];
stops[0].Pos = 0.0;
stops[0].R = 0.0;
stops[0].G = 1.0;
stops[0].B = 1.0;
stops[0].A = 0.25;
stops[1].Pos = 1.0;
stops[1].R = 0.0;
stops[1].G = 0.0;
stops[1].B = 1.0;
stops[1].A = 1.0;
brush.Type = uiDrawBrushTypeLinearGradient;
brush.X0 = 100 + XO;
brush.Y0 = 0 + YO;
brush.X1 = 100 + XO;
brush.Y1 = 200 + YO;
brush.Stops = stops;
brush.NumStops = 2;
uiDrawFill(p->Context, path, &brush);
}
#undef YO
#undef XO
uiDrawFreePath(path);
// based on https://msdn.microsoft.com/en-us/library/windows/desktop/dd756679%28v=vs.85%29.aspx
path = uiDrawNewPath(uiDrawFillModeWinding);
uiDrawPathNewFigure(path, 585, 235);
uiDrawPathArcTo(path,
510, 235,
75,
0,
// TODO why doesn't 360° work
2 * M_PI - 0.1);
uiDrawPathEnd(path);
// first the stroke
brush.Type = uiDrawBrushTypeSolid;
brush.R = 0;
brush.G = 0;
brush.B = 0;
brush.A = 1;
sp.Cap = uiDrawLineCapFlat;
sp.Join = uiDrawLineJoinMiter;
sp.MiterLimit = uiDrawDefaultMiterLimit;
sp.Thickness = 1;
uiDrawStroke(p->Context, path, &brush, &sp);
// then the fill
{
uiDrawBrushGradientStop stops[2];
stops[0].Pos = 0.0;
stops[0].R = 1.0;
stops[0].G = 1.0;
stops[0].B = 0.0;
stops[0].A = 1.0;
stops[1].Pos = 1.0;
stops[1].R = ((double) 0x22) / 255.0;
stops[1].G = ((double) 0x8B) / 255.0;
stops[1].B = ((double) 0x22) / 255.0;
stops[1].A = 1.0;
brush.Type = uiDrawBrushTypeRadialGradient;
// start point
brush.X0 = 510;
brush.Y0 = 235;
// outer circle's center
brush.X1 = 510;
brush.Y1 = 235;
brush.OuterRadius = 75;
brush.Stops = stops;
brush.NumStops = 2;
uiDrawFill(p->Context, path, &brush);
}
uiDrawFreePath(path);
} }
static uintmax_t handlerHScrollMax(uiAreaHandler *a, uiArea *area) static uintmax_t handlerHScrollMax(uiAreaHandler *a, uiArea *area)

View File

@ -36,14 +36,26 @@ struct uiAreaDrawParams {
intmax_t VScrollPos; intmax_t VScrollPos;
}; };
// TODO proper sources
// TODO dotting/dashing // TODO dotting/dashing
typedef struct uiDrawPath uiDrawPath;
typedef struct uiDrawBrush uiDrawBrush;
typedef struct uiDrawStrokeParams uiDrawStrokeParams; typedef struct uiDrawStrokeParams uiDrawStrokeParams;
typedef enum uiDrawBrushType uiDrawBrushType;
typedef struct uiDrawBrushGradientStop uiDrawBrushGradientStop;
typedef enum uiDrawLineCap uiDrawLineCap; typedef enum uiDrawLineCap uiDrawLineCap;
typedef enum uiDrawLineJoin uiDrawLineJoin; typedef enum uiDrawLineJoin uiDrawLineJoin;
typedef enum uiDrawFillMode uiDrawFillMode; typedef enum uiDrawFillMode uiDrawFillMode;
enum uiDrawBrushType {
uiDrawBrushTypeSolid,
uiDrawBrushTypeLinearGradient,
uiDrawBrushTypeRadialGradient,
uiDrawBrushTypeImage,
};
enum uiDrawLineCap { enum uiDrawLineCap {
uiDrawLineCapFlat, uiDrawLineCapFlat,
uiDrawLineCapRound, uiDrawLineCapRound,
@ -66,28 +78,69 @@ enum uiDrawFillMode {
uiDrawFillModeAlternate, uiDrawFillModeAlternate,
}; };
struct uiDrawBrush {
uiDrawBrushType Type;
// solid brushes
double R;
double G;
double B;
double A;
// gradient brushes
double X0; // linear: start X, radial: start X
double Y0; // linear: start Y, radial: start Y
double X1; // linear: end X, radial: outer circle center X
double Y1; // linear: end Y, radial: outer circle center Y
double OuterRadius; // radial gradients only
uiDrawBrushGradientStop *Stops;
size_t NumStops;
// TODO extend mode
// cairo: none, repeat, reflect, pad; no individual control
// Direct2D: repeat, reflect, pad; no individual control
// Core Graphics: none, pad; before and after individually
// TODO cairo documentation is inconsistent about pad
// TODO images
// TODO transforms
};
struct uiDrawBrushGradientStop {
double Pos;
double R;
double G;
double B;
double A;
};
struct uiDrawStrokeParams { struct uiDrawStrokeParams {
uiDrawLineCap Cap; uiDrawLineCap Cap;
uiDrawLineJoin Join; uiDrawLineJoin Join;
intmax_t Thickness; double Thickness;
double MiterLimit; double MiterLimit;
}; };
void uiDrawBeginPathRGB(uiDrawContext *, uint8_t, uint8_t, uint8_t); uiDrawPath *uiDrawNewPath(uiDrawFillMode);
// TODO verify these aren't alpha premultiplied anywhere void uiDrawFreePath(uiDrawPath *);
void uiDrawBeginPathRGBA(uiDrawContext *, uint8_t, uint8_t, uint8_t, uint8_t);
void uiDrawMoveTo(uiDrawContext *, intmax_t, intmax_t); void uiDrawPathNewFigure(uiDrawPath *, double, double);
void uiDrawLineTo(uiDrawContext *, intmax_t, intmax_t); void uiDrawPathNewFigureWithArc(uiDrawPath *, double, double, double, double, double);
void uiDrawRectangle(uiDrawContext *, intmax_t, intmax_t, intmax_t, intmax_t); void uiDrawPathLineTo(uiDrawPath *, double, double);
// notes: angles are both relative to 0 and go counterclockwise // notes: angles are both relative to 0 and go counterclockwise
void uiDrawArcTo(uiDrawContext *, intmax_t, intmax_t, intmax_t, double, double, int); // TODO is the initial line segment on cairo and OS X a proper join?
// TODO behavior when there is no initial point on Windows and OS X void uiDrawPathArcTo(uiDrawPath *, double, double, double, double, double);
void uiDrawBezierTo(uiDrawContext *, intmax_t, intmax_t, intmax_t, intmax_t, intmax_t, intmax_t); void uiDrawPathBezierTo(uiDrawPath *, double, double, double, double, double, double);
void uiDrawCloseFigure(uiDrawContext *); // TODO quadratic bezier
void uiDrawPathCloseFigure(uiDrawPath *);
void uiDrawStroke(uiDrawContext *, uiDrawStrokeParams *); // TODO effect of these when a figure is already started
void uiDrawFill(uiDrawContext *, uiDrawFillMode); void uiDrawPathAddRectangle(uiDrawPath *, double, double, double, double);
void uiDrawPathEnd(uiDrawPath *);
void uiDrawStroke(uiDrawContext *, uiDrawPath *, uiDrawBrush *, uiDrawStrokeParams *);
void uiDrawFill(uiDrawContext *, uiDrawPath *, uiDrawBrush *);
// TODO primitives: // TODO primitives:
// - rounded rectangles // - rounded rectangles