diff --git a/darwin/draw.m b/darwin/draw.m index 64bb5b3a..a8569737 100644 --- a/darwin/draw.m +++ b/darwin/draw.m @@ -306,12 +306,19 @@ void uiDrawMatrixTranslate(uiDrawMatrix *m, double x, double y) c2m(&c, m); } -void uiDrawMatrixScale(uiDrawMatrix *m, double x, double y) +void uiDrawMatrixScale(uiDrawMatrix *m, double xCenter, double yCenter, double x, double y) { CGAffineTransform c; + double xt, yt; m2c(m, &c); + // TODO explain why the translation must come first + xt = x; + yt = y; + scaleCenter(xCenter, yCenter, &xt, &yt); + c = CGAffineTransformTranslate(c, xt, yt); c = CGAffineTransformScale(c, x, y); + // TODO undo the translation? c2m(&c, m); } diff --git a/matrix.c b/matrix.c index 6af1bcee..eda79ed8 100644 --- a/matrix.c +++ b/matrix.c @@ -27,14 +27,22 @@ void fallbackTranslate(uiDrawMatrix *m, double x, double y) fallbackMultiply(m, &m2); } -// TODO the Direct2D version takes a center argument; investigate it -void fallbackScale(uiDrawMatrix *m, double x, double y) +void scaleCenter(double xCenter, double yCenter, double *x, double *y) +{ + *x = xCenter - (*x * xCenter); + *y = yCenter - (*y * yCenter); +} + +void fallbackScale(uiDrawMatrix *m, double xCenter, double yCenter, double x, double y) { uiDrawMatrix m2; setIdentity(&m2); m2.M11 = x; m2.M22 = y; + scaleCenter(xCenter, yCenter, &x, &y); + m2.M31 = x; + m2.M32 = y; fallbackMultiply(m, &m2); } diff --git a/test/drawtests.c b/test/drawtests.c index 73c5103b..fd9f1ff1 100644 --- a/test/drawtests.c +++ b/test/drawtests.c @@ -871,9 +871,9 @@ static void drawD2DScale(uiAreaDrawParams *p) uiDrawStroke(p->Context, path, &original, &originalsp); uiDrawMatrixSetIdentity(&m); -// TODO THIS DOES NOT WORK CORRECTLY -// that pivot point is required... - uiDrawMatrixScale(&m, 1.3, 1.3); + uiDrawMatrixScale(&m, + 438.0, 80.5, + 1.3, 1.3); uiDrawTransform(p->Context, &m); uiDrawFill(p->Context, path, &fill); @@ -881,12 +881,31 @@ static void drawD2DScale(uiAreaDrawParams *p) uiDrawRestore(p->Context); - // TODO translate and show what happens if the center is (0, 0) + // for testing purposes, show what happens if we scale about (0, 0) + uiDrawMatrixSetIdentity(&m); + uiDrawMatrixTranslate(&m, -300, 50); + uiDrawTransform(p->Context, &m); + + uiDrawStroke(p->Context, path, &original, &originalsp); + + uiDrawMatrixSetIdentity(&m); + uiDrawMatrixScale(&m, + 0, 0, + 1.3, 1.3); + uiDrawTransform(p->Context, &m); + + uiDrawFill(p->Context, path, &fill); + uiDrawStroke(p->Context, path, &transform, &transformsp); uiDrawFreePath(path); } -// TODOTODOTODO +// TODO skewing https://msdn.microsoft.com/en-us/library/windows/desktop/dd756689%28v=vs.85%29.aspx +// especially TODO counterclockwise?! + +// TODO translating https://msdn.microsoft.com/en-us/library/windows/desktop/dd756691%28v=vs.85%29.aspx + +// TODO multiple transforms https://msdn.microsoft.com/en-us/library/windows/desktop/dd756672%28v=vs.85%29.aspx // TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756675%28v=vs.85%29.aspx diff --git a/ui.h b/ui.h index bcc0fa9e..29921567 100644 --- a/ui.h +++ b/ui.h @@ -414,7 +414,7 @@ _UI_EXTERN void uiDrawFill(uiDrawContext *c, uiDrawPath *path, uiDrawBrush *b); _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 uiDrawMatrixScale(uiDrawMatrix *m, double xCenter, double yCenter, 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 xamount, double yamount); _UI_EXTERN void uiDrawMatrixMultiply(uiDrawMatrix *dest, uiDrawMatrix *src); diff --git a/uipriv.h b/uipriv.h index d2410cdc..6c355d2a 100644 --- a/uipriv.h +++ b/uipriv.h @@ -63,7 +63,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 scaleCenter(double, double, double *, double *); +extern void fallbackScale(uiDrawMatrix *, double, double, double, double); extern void fallbackMultiply(uiDrawMatrix *, uiDrawMatrix *); extern void fallbackTransformPoint(uiDrawMatrix *, double *, double *); extern void fallbackTransformSize(uiDrawMatrix *, double *, double *); diff --git a/unix/draw.c b/unix/draw.c index ebae5c7c..24c13dda 100644 --- a/unix/draw.c +++ b/unix/draw.c @@ -335,12 +335,19 @@ void uiDrawMatrixTranslate(uiDrawMatrix *m, double x, double y) c2m(&c, m); } -void uiDrawMatrixScale(uiDrawMatrix *m, double x, double y) +void uiDrawMatrixScale(uiDrawMatrix *m, double xCenter, double yCenter, double x, double y) { cairo_matrix_t c; + double xt, yt; m2c(m, &c); + // TODO explain why the translation must come first + xt = x; + yt = y; + scaleCenter(xCenter, yCenter, &xt, &yt); + cairo_matrix_translate(&c, xt, yt); cairo_matrix_scale(&c, x, y); + // TODO undo the translation? c2m(&c, m); } @@ -349,10 +356,8 @@ void uiDrawMatrixRotate(uiDrawMatrix *m, double x, double y, double amount) cairo_matrix_t c; m2c(m, &c); - // TODO verify this cairo_matrix_translate(&c, x, y); - // TODO explain this - cairo_matrix_rotate(&c, -amount); + cairo_matrix_rotate(&c, amount); cairo_matrix_translate(&c, -x, -y); c2m(&c, m); } diff --git a/windows/draw.c b/windows/draw.c index d3c1d6e2..a9690e9e 100644 --- a/windows/draw.c +++ b/windows/draw.c @@ -578,9 +578,9 @@ void uiDrawMatrixTranslate(uiDrawMatrix *m, double x, double y) fallbackTranslate(m, x, y); } -void uiDrawMatrixScale(uiDrawMatrix *m, double x, double y) +void uiDrawMatrixScale(uiDrawMatrix *m, double xCenter, double yCenter, double x, double y) { - fallbackScale(m, x, y); + fallbackScale(m, xCenter, yCenter, x, y); } void uiDrawMatrixRotate(uiDrawMatrix *m, double x, double y, double amount)