Implemented the matrix stuff on Windows. Also fixed the signature of uiDrawMatrixSkew().

This commit is contained in:
Pietro Gagliardi 2015-10-11 12:36:48 -04:00
parent 3d8f8f0756
commit 0ae3ef918d
7 changed files with 211 additions and 3 deletions

View File

@ -15,3 +15,67 @@ void setIdentity(uiDrawMatrix *m)
// TODO skew
// see windows/draw.c for more information
// TODO we don't need to do this if we can bypass the multiplication somehow
void fallbackTranslate(uiDrawMatrix *m, double x, double y)
{
uiDrawMatrix m2;
setIdentity(&m2);
m2.M31 = x;
m2.M32 = y;
fallbackMultiply(m, &m2);
}
// TODO the Direct2D version takes a center argument; investigate it
void fallbackScale(uiDrawMatrix *m, double x, double y)
{
uiDrawMatrix m2;
setIdentity(&m2);
m2.M11 = x;
m2.M22 = y;
fallbackMultiply(m, &m2);
}
void fallbackMultiply(uiDrawMatrix *dest, uiDrawMatrix *src)
{
uiDrawMatrix out;
out.M11 = (dest->M11 * src->M11) +
(dest->M12 * src->M21);
out.M12 = (dest->M11 * src->M12) +
(dest->M12 * src->M22);
out.M21 = (dest->M21 * src->M11) +
(dest->M22 * src->M21);
out.M22 = (dest->M21 * src->M12) +
(dest->M22 * src->M22);
out.M31 = (dest->M31 * src->M11) +
(dest->M32 * src->M21) +
src->M31;
out.M32 = (dest->M31 * src->M12) +
(dest->M32 * src->M22) +
src->M32;
*dest = out;
}
void fallbackTransformPoint(uiDrawMatrix *m, double *x, double *y)
{
double xout, yout;
xout = (*x * m->M11) + (*y * m->M21) + m->M31;
yout = (*x * m->M12) + (*y * m->M22) + m->M32;
*x = xout;
*y = yout;
}
// and this algorithm is according to cairo
void fallbackTransformSize(uiDrawMatrix *m, double *x, double *y)
{
double xout, yout;
xout = (*x * m->M11) + (*y * m->M21);
yout = (*x * m->M12) + (*y * m->M22);
*x = xout;
*y = yout;
}

2
ui.h
View File

@ -416,7 +416,7 @@ _UI_EXTERN void uiDrawMatrixSetIdentity(uiDrawMatrix *m);
_UI_EXTERN void uiDrawMatrixTranslate(uiDrawMatrix *m, double x, double y);
_UI_EXTERN void uiDrawMatrixScale(uiDrawMatrix *m, double x, double y);
_UI_EXTERN void uiDrawMatrixRotate(uiDrawMatrix *m, double x, double y, double amount);
_UI_EXTERN void uiDrawMatrixSkew(uiDrawMatrix *m, double x, double y, double amount);
_UI_EXTERN void uiDrawMatrixSkew(uiDrawMatrix *m, double x, double y, double xamount, double yamount);
_UI_EXTERN void uiDrawMatrixMultiply(uiDrawMatrix *dest, uiDrawMatrix *src);
_UI_EXTERN int uiDrawMatrixInvertible(uiDrawMatrix *m);
_UI_EXTERN int uiDrawMatrixInvert(uiDrawMatrix *m);

View File

@ -62,3 +62,8 @@ extern int fromScancode(uintptr_t, uiAreaKeyEvent *);
// matrix.c
extern void setIdentity(uiDrawMatrix *);
extern void fallbackTranslate(uiDrawMatrix *, double, double);
extern void fallbackScale(uiDrawMatrix *, double, double);
extern void fallbackMultiply(uiDrawMatrix *, uiDrawMatrix *);
extern void fallbackTransformPoint(uiDrawMatrix *, double *, double *);
extern void fallbackTransformSize(uiDrawMatrix *, double *, double *);

View File

@ -178,7 +178,7 @@ static gboolean areaWidget_draw(GtkWidget *w, cairo_t *cr)
dp.HScrollPos = gtk_adjustment_get_value(ap->ha);
dp.VScrollPos = gtk_adjustment_get_value(ap->va);
// no need to save or restore the graphics state; GTK+ does that for us
// no need to save or restore the graphics state to reset transformations; GTK+ does that for us
(*(ap->ah->Draw))(ap->ah, ap->a, &dp);
freeContext(dp.Context);

View File

@ -353,7 +353,7 @@ void uiDrawMatrixRotate(uiDrawMatrix *m, double x, double y, double amount)
c2m(&c, m);
}
void uiDrawMatrixSkew(uiDrawMatrix *m, double x, double y, double amount)
void uiDrawMatrixSkew(uiDrawMatrix *m, double x, double y, double amount, double yamount)
{
complain("TODO");
}

View File

@ -54,6 +54,7 @@ static HRESULT doPaint(uiArea *a, ID2D1RenderTarget *rt, RECT *client, RECT *cli
bgcolor.a = 1.0;
ID2D1RenderTarget_Clear(rt, &bgcolor);
// no need to save or restore the graphics state to reset transformations; it's handled by resetTarget() in draw.c, called by newContext() above
(*(ah->Draw))(ah, a, &dp);
freeContext(dp.Context);

View File

@ -294,12 +294,25 @@ struct uiDrawContext {
ID2D1RenderTarget *rt;
};
static void resetTarget(ID2D1RenderTarget *rt)
{
D2D1_MATRIX_3X2_F dm;
// transformations persist
// reset to the identity matrix
ZeroMemory(&dm, sizeof (D2D1_MATRIX_3X2_F));
dm._11 = 1;
dm._22 = 1;
ID2D1RenderTarget_SetTransform(rt, &dm);
}
uiDrawContext *newContext(ID2D1RenderTarget *rt)
{
uiDrawContext *c;
c = uiNew(uiDrawContext);
c->rt = rt;
resetTarget(c->rt);
return c;
}
@ -512,3 +525,128 @@ void uiDrawFill(uiDrawContext *c, uiDrawPath *p, uiDrawBrush *b)
NULL);
ID2D1Brush_Release(brush);
}
static void m2d(uiDrawMatrix *m, D2D1_MATRIX_3X2_F *d)
{
d->_11 = m->M11;
d->_12 = m->M12;
d->_21 = m->M21;
d->_22 = m->M22;
d->_31 = m->M31;
d->_32 = m->M32;
}
static void d2m(D2D1_MATRIX_3X2_F *d, uiDrawMatrix *m)
{
m->M11 = d->_11;
m->M12 = d->_12;
m->M21 = d->_21;
m->M22 = d->_22;
m->M31 = d->_31;
m->M32 = d->_32;
}
void uiDrawMatrixSetIdentity(uiDrawMatrix *m)
{
setIdentity(m);
}
// frustratingly all of the operations on a matrix except rotation and skeweing are provided by the C++-only d2d1helper.h
// we'll have to recreate their functionalities here
// the implementations are all in the main matrix.c file
void uiDrawMatrixTranslate(uiDrawMatrix *m, double x, double y)
{
fallbackTranslate(m, x, y);
}
void uiDrawMatrixScale(uiDrawMatrix *m, double x, double y)
{
fallbackScale(m, x, y);
}
void uiDrawMatrixRotate(uiDrawMatrix *m, double x, double y, double amount)
{
D2D1_POINT_2F center;
D2D1_MATRIX_3X2_F dm;
uiDrawMatrix rm;
amount *= 180 / M_PI; // must be in degrees
center.x = x;
center.y = y;
// TODO explain this
D2D1MakeRotateMatrix(-amount, center, &dm);
d2m(&dm, &rm);
uiDrawMatrixMultiply(m, &rm);
}
void uiDrawMatrixSkew(uiDrawMatrix *m, double x, double y, double xamount, double yamount)
{
D2D1_POINT_2F center;
D2D1_MATRIX_3X2_F dm;
uiDrawMatrix sm;
xamount *= 180 / M_PI; // must be in degrees
yamount *= 180 / M_PI; // must be in degrees
center.x = x;
center.y = y;
D2D1MakeSkewMatrix(xamount, yamount, center, &dm);
d2m(&dm, &sm);
uiDrawMatrixMultiply(m, &sm);
}
void uiDrawMatrixMultiply(uiDrawMatrix *dest, uiDrawMatrix *src)
{
fallbackMultiply(dest, src);
}
int uiDrawMatrixInvertible(uiDrawMatrix *m)
{
D2D1_MATRIX_3X2_F d;
m2d(m, &d);
return D2D1IsMatrixInvertible(&d) != FALSE;
}
int uiDrawMatrixInvert(uiDrawMatrix *m)
{
D2D1_MATRIX_3X2_F d;
m2d(m, &d);
if (D2D1InvertMatrix(&d) == FALSE)
return 0;
d2m(&d, m);
return 1;
}
void uiDrawMatrixTransformPoint(uiDrawMatrix *m, double *x, double *y)
{
fallbackTransformPoint(m, x, y);
}
void uiDrawMatrixTransformSize(uiDrawMatrix *m, double *x, double *y)
{
fallbackTransformSize(m, x, y);
}
void uiDrawSave(uiDrawContext *c)
{
// TODO
}
void uiDrawRestore(uiDrawContext *c)
{
// TODO
}
void uiDrawTransform(uiDrawContext *c, uiDrawMatrix *m)
{
D2D1_MATRIX_3X2_F dm;
uiDrawMatrix already;
ID2D1RenderTarget_GetTransform(c->rt, &dm);
d2m(&dm, &already);
uiDrawMatrixMultiply(&already, m);
m2d(&already, &dm);
ID2D1RenderTarget_SetTransform(c->rt, &dm);
}