More Direct2D path work.

This commit is contained in:
Pietro Gagliardi 2015-10-06 19:56:38 -04:00
parent 020e128a2c
commit de08c3a202
2 changed files with 99 additions and 60 deletions

View File

@ -66,13 +66,10 @@ ID2D1HwndRenderTarget *makeHWNDRenderTarget(HWND hwnd)
return rt;
}
// TODO move below the path stuff
struct uiDrawContext {
ID2D1RenderTarget *rt;
ID2D1PathGeometry *path;
ID2D1GeometrySink *sink;
BOOL inFigure;
// source color
BOOL useRGB;
uint8_t r;
@ -115,82 +112,121 @@ void uiDrawBeginPathRGBA(uiDrawContext *c, uint8_t r, uint8_t g, uint8_t b, uint
c->inFigure = FALSE;
}
void uiDrawMoveTo(uiDrawContext *c, intmax_t x, intmax_t y)
{
D2D1_POINT_2F p;
struct uiDrawPath {
ID2D1PathGeometry *path;
ID2D1GeometrySink *sink;
BOOL inFigure;
};
if (c->inFigure)
uiDrawPath *uiDrawNewPath(uiDrawFillMode fillmode)
{
uiDrawPath *p;
HRESULT hr;
// TODO uiNew
p = malloc(sizeof (uiDrawPath));
hr = ID2D1Factory_CreatePathGeometry(d2dfactory,
&(p->path));
// TODO make sure this is the only success code
if (hr != S_OK)
logHRESULT("error creating path in uiDrawNewPath()", hr);
hr = ID2D1PathGeometry_Open(p->path,
&(p->sink));
if (hr != S_OK)
logHRESULT("error opening path in uiDrawNewPath()", hr);
switch (fillmode) {
case uiDrawFIllModeWinding:
ID2D1GeometrySink_SetFillMode(s->sink,
D2D1_FILL_MODE_WINDING);
break;
case uiDrawFillModeAlternate:
ID2D1GeometrySink_SetFillMode(s->sink,
D2D1_FILL_MODE_ALTERNATE);
break;
}
p->inFigure = FALSE;
return p;
}
void uiDrawFreePath(uiDrawPath *p)
{
if (p->inFigure)
ID2D1GeometrySink_EndFigure(p->sink,
D2D1_FIGURE_END_OPEN);
if (p->sink != NULL)
// TODO close sink first?
ID2D1GeometrySink_Release(p->sink);
ID2D1PathGeometry_Release(p->path);
// TODO uiFree
free(p);
}
void uiDrawPathNewFigure(uiDrawPath *p, double x, double y)
{
D2D1_POINT_2F pt;
if (p->inFigure)
ID2D1GeometrySink_EndFigure(c->sink,
D2D1_FIGURE_END_OPEN);
p.x = ((FLOAT) x) + 0.5;
p.y = ((FLOAT) y) + 0.5;
ID2D1GeometrySink_BeginFigure(c->sink,
p,
p.x = x;
p.y = y;
ID2D1GeometrySink_BeginFigure(p->sink,
pt,
D2D1_FIGURE_BEGIN_FILLED);
c->inFigure = TRUE;
p->inFigure = TRUE;
}
void uiDrawLineTo(uiDrawContext *c, intmax_t x, intmax_t y)
void uiDrawPathLineTo(uiDrawPath *p, double x, double y)
{
D2D1_POINT_2F p;
D2D1_POINT_2F pt;
p.x = ((FLOAT) x) + 0.5;
p.y = ((FLOAT) y) + 0.5;
ID2D1GeometrySink_AddLine(c->sink, p);
pt.x = x;
pt.y = y;
ID2D1GeometrySink_AddLine(p->sink, pt);
}
void uiDrawRectangle(uiDrawContext *c, intmax_t x, intmax_t y, intmax_t width, intmax_t height)
void uiDrawPathArcTo(uiDrawPath *p, double xCenter, double yCenter, double radius, double startAngle, double endAngle)
{
// TODO
}
void uiDrawArcTo(uiDrawContext *c, intmax_t xCenter, intmax_t yCenter, intmax_t radius, double startAngle, double endAngle, int lineFromCurrentPointToStart)
void uiDrawPathBezierTo(uiDrawPath *p, double c1x, double c1y, double c2x, double c2y, double endX, double endY)
{
if (!lineFromCurrentPointToStart) {
int bx, by, bx2, by2;
int sx, sy, ex, ey;
D2D1_BEZIER_SEGMENT s;
// see http://stackoverflow.com/questions/32465446/how-do-i-inhibit-the-initial-line-segment-of-an-anglearc
// the idea for floor(x + 0.5) is inspired by wine
// TODO make sure this is an accurate imitation of AngleArc()
bx = xCenter - radius;
by = yCenter - radius;
bx2 = xCenter + radius;
by2 = yCenter + radius;
sx = xCenter + floor((double) radius * cos(startAngle));
sy = yCenter - floor((double) radius * sin(startAngle));
ex = xCenter + floor((double) radius * cos(endAngle));
ey = yCenter - floor((double) radius * sin(endAngle));
/* TODO
if (Arc(c->dc, bx, by, bx2, by2, sx, sy, ex, ey) == 0)
logLastError("error drawing current point arc in uiDrawArc()");
return;
*/
}
/* TODO
// AngleArc() expects degrees
startAngle *= (180.0 / M_PI);
endAngle *= (180.0 / M_PI);
if (AngleArc(c->dc,
xCenter, yCenter,
radius,
startAngle,
// the "sweep angle" is relative to the start angle, not to 0
endAngle - startAngle) == 0)
logLastError("error drawing arc in uiDrawArc()");
*/
s.point1.x = c1x;
s.point1.y = c1y;
s.point2.x = c2x;
s.point2.y = c2y;
s.point3.x = endX;
s.point3.y = endY;
ID2D1GeometrySink_AddBezier(p->sink, &s);
}
void uiDrawBezierTo(uiDrawContext *c, intmax_t c1x, intmax_t c1y, intmax_t c2x, intmax_t c2y, intmax_t endX, intmax_t endY)
void uiDrawPathCloseFigure(uiDrawPath *p)
{
// TODO
}
void uiDrawCloseFigure(uiDrawContext *c)
{
ID2D1GeometrySink_EndFigure(c->sink,
ID2D1GeometrySink_EndFigure(p->sink,
D2D1_FIGURE_END_CLOSED);
c->inFigure = FALSE;
p->inFigure = FALSE;
}
void uiDrawPathAddRectangle(uiDrawPath *p, double x0, double y0, double xxxxTODOxxxx, double xxxTODOxxxxxxxxxx)
{
// TODO
}
void uiDrawPathEnd(uiDrawPath *p)
{
HRESULT hr;
if (p->inFigure)
ID2D1GeometrySink_EndFigure(c->sink,
D2D1_FIGURE_END_OPEN);
hr = ID2D1GeometrySink_Close(p->sink);
if (hr != S_OK)
logHRESULT("error closing path in uiDrawPathEnd()", hr);
ID2D1GeometrySink_Release(p->sink);
p->sink = NULL;
}
static ID2D1SolidColorBrush *makeBrush(uiDrawContext *c)

View File

@ -75,13 +75,16 @@ struct uiDrawStrokeParams {
};
uiDrawPath *uiDrawNewPath(uiDrawFillMode);
void uiDrawFreePath(uiDrawPath *);
void uiDrawPathNewFigure(uiDrawPath *, double, double);
// TODO uiDrawPathNewFigureWithArc
void uiDrawPathLineTo(uiDrawPath *, double, double);
// notes: angles are both relative to 0 and go counterclockwise
// TODO is the initial line segment on cairo and OS X a proper join?
void uiDrawPathArcTo(uiDrawPath *, double, double, double, double, double);
void uiDrawPathBezierTo(uiDrawPath *, double, double, double, double, double, double);
// TODO quadratic bezier
void uiDrawPathCloseFigure(uiDrawPath *);
void uiDrawPathAddRectangle(uiDrawPath *, double, double, double, double);