Started bringing the new drawing code over to the other backends.
This commit is contained in:
parent
6787130125
commit
b43ec18561
205
gtkarea/main.c
205
gtkarea/main.c
|
@ -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)
|
||||||
|
|
81
gtkarea/ui.h
81
gtkarea/ui.h
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue