--- rxvt-unicode/src/rxvtimg.C 2012/06/15 18:05:15 1.92 +++ rxvt-unicode/src/rxvtimg.C 2012/06/15 18:36:26 1.95 @@ -7,94 +7,128 @@ typedef rxvt_img::nv nv; -struct mat3x3 +namespace { - nv v[3][3]; - mat3x3 () + struct mat3x3 { - } + nv v[3][3]; - mat3x3 (nv matrix[3][3]) - { - memcpy (v, matrix, sizeof (v)); - } + mat3x3 () + { + } - mat3x3 (nv v11, nv v12, nv v13, nv v21, nv v22, nv v23, nv v31, nv v32, nv v33) - { - v[0][0] = v11; v[0][1] = v12; v[0][2] = v13; - v[1][0] = v21; v[1][1] = v22; v[1][2] = v23; - v[2][0] = v31; v[2][1] = v32; v[2][2] = v33; - } + mat3x3 (const nv *matrix) + { + memcpy (v, matrix, sizeof (v)); + } - mat3x3 invert (); + mat3x3 (nv v11, nv v12, nv v13, nv v21, nv v22, nv v23, nv v31, nv v32, nv v33) + { + v[0][0] = v11; v[0][1] = v12; v[0][2] = v13; + v[1][0] = v21; v[1][1] = v22; v[1][2] = v23; + v[2][0] = v31; v[2][1] = v32; v[2][2] = v33; + } - nv *operator [](int i) { return &v[i][0]; } - const nv *operator [](int i) const { return &v[i][0]; } + mat3x3 invert (); - // quite inefficient, hopefully gcc pulls the w calc out of any loops - nv apply1 (int i, nv x, nv y) + nv *operator [](int i) { return &v[i][0]; } + const nv *operator [](int i) const { return &v[i][0]; } + + operator const nv * () const { return &v[0][0]; } + operator nv * () { return &v[0][0]; } + + // quite inefficient, hopefully gcc pulls the w calc out of any loops + nv apply1 (int i, nv x, nv y) + { + mat3x3 &m = *this; + + nv v = m[i][0] * x + m[i][1] * y + m[i][2]; + nv w = m[2][0] * x + m[2][1] * y + m[2][2]; + + return v * (1. / w); + } + + static mat3x3 translate (nv x, nv y); + static mat3x3 scale (nv s, nv t); + static mat3x3 rotate (nv phi); + }; + + mat3x3 + mat3x3::invert () { mat3x3 &m = *this; + mat3x3 inv; - nv v = m[i][0] * x + m[i][1] * y + m[i][2]; - nv w = m[2][0] * x + m[2][1] * y + m[2][2]; + nv s0 = m[2][2] * m[1][1] - m[2][1] * m[1][2]; + nv s1 = m[2][1] * m[0][2] - m[2][2] * m[0][1]; + nv s2 = m[1][2] * m[0][1] - m[1][1] * m[0][2]; - return v * (1. / w); - } + nv invdet = 1. / (m[0][0] * s0 + m[1][0] * s1 + m[2][0] * s2); - static mat3x3 translate (nv x, nv y); -}; + inv[0][0] = invdet * s0; + inv[0][1] = invdet * s1; + inv[0][2] = invdet * s2; -mat3x3 -mat3x3::invert () -{ - mat3x3 &m = *this; - mat3x3 inv; + inv[1][0] = invdet * (m[2][0] * m[1][2] - m[2][2] * m[1][0]); + inv[1][1] = invdet * (m[2][2] * m[0][0] - m[2][0] * m[0][2]); + inv[1][2] = invdet * (m[1][0] * m[0][2] - m[1][2] * m[0][0]); - nv s0 = m[2][2] * m[1][1] - m[2][1] * m[1][2]; - nv s1 = m[2][1] * m[0][2] - m[2][2] * m[0][1]; - nv s2 = m[1][2] * m[0][1] - m[1][1] * m[0][2]; + inv[2][0] = invdet * (m[2][1] * m[1][0] - m[2][0] * m[1][1]); + inv[2][1] = invdet * (m[2][0] * m[0][1] - m[2][1] * m[0][0]); + inv[2][2] = invdet * (m[1][1] * m[0][0] - m[1][0] * m[0][1]); - nv invdet = 1. / (m[0][0] * s0 + m[1][0] * s1 + m[2][0] * s2); + return inv; + } - inv[0][0] = invdet * s0; - inv[0][1] = invdet * s1; - inv[0][2] = invdet * s2; + static mat3x3 + operator *(const mat3x3 &a, const mat3x3 &b) + { + mat3x3 r; - inv[1][0] = invdet * (m[2][0] * m[1][2] - m[2][2] * m[1][0]); - inv[1][1] = invdet * (m[2][2] * m[0][0] - m[2][0] * m[0][2]); - inv[1][2] = invdet * (m[1][0] * m[0][2] - m[1][2] * m[0][0]); + for (int i = 0; i < 3; ++i) + for (int j = 0; j < 3; ++j) + r[i][j] = a[i][0] * b[0][j] + + a[i][1] * b[1][j] + + a[i][2] * b[2][j]; - inv[2][0] = invdet * (m[2][1] * m[1][0] - m[2][0] * m[1][1]); - inv[2][1] = invdet * (m[2][0] * m[0][1] - m[2][1] * m[0][0]); - inv[2][2] = invdet * (m[1][1] * m[0][0] - m[1][0] * m[0][1]); + return r; + } - return inv; -} + mat3x3 + mat3x3::translate (nv x, nv y) + { + return mat3x3 ( + 1, 0, x, + 0, 1, y, + 0, 0, 1 + ); + } -static mat3x3 -operator *(const mat3x3 &a, const mat3x3 &b) -{ - mat3x3 r; + mat3x3 + mat3x3::scale (nv s, nv t) + { + return mat3x3 ( + s, 0, 0, + 0, t, 0, + 0, 0, 1 + ); + } - for (int i = 0; i < 3; ++i) - for (int j = 0; j < 3; ++j) - r[i][j] = a[i][0] * b[0][j] - + a[i][1] * b[1][j] - + a[i][2] * b[2][j]; + // clockwise + mat3x3 + mat3x3::rotate (nv phi) + { + nv s = sin (phi); + nv c = cos (phi); - return r; -} + return mat3x3 ( + c, -s, 0, + s, c, 0, + 0, 0, 1 + ); + } -mat3x3 -mat3x3::translate (nv x, nv y) -{ - return mat3x3 ( - 1, 0, x, - 0, 1, y, - 0, 0, 1 - ); } #if 0 @@ -691,13 +725,19 @@ } rxvt_img * -rxvt_img::transform (nv matrix[3][3]) +rxvt_img::transform (const nv matrix[3][3]) { - // calculate new pixel bounding box coordinates - nv r[2], rmin[2], rmax[2]; + return transform (mat3x3 (&matrix[0][0])); +} +rxvt_img * +rxvt_img::transform (const nv *matrix) +{ mat3x3 m (matrix); + // calculate new pixel bounding box coordinates + nv r[2], rmin[2], rmax[2]; + for (int i = 0; i < 2; ++i) { nv v; @@ -738,16 +778,6 @@ XRenderSetPictureFilter (dpy, src, "good", 0, 0); XRenderSetPictureTransform (dpy, src, &xfrm); XRenderComposite (dpy, PictOpSrc, src, None, dst, sx, sy, 0, 0, 0, 0, new_width, new_height); -#if 1 - { - XRenderColor rc = { 65535,0,0,65535 }; - XRenderFillRectangle (dpy, PictOpSrc, dst, &rc, 0, 0, new_width, new_height); - }{ - XRenderColor rc = { 0,0,0,65535 }; - XRenderFillRectangle (dpy, PictOpSrc, dst, &rc, 1, 1, new_width - 2, new_height - 2); - } - XRenderComposite (dpy, PictOpOver, src, None, dst, sx, sy, 0, 0, 0, 0, new_width, new_height); -#endif XRenderFreePicture (dpy, src); XRenderFreePicture (dpy, dst); @@ -761,16 +791,10 @@ if (w == new_width && h == new_height) return clone (); - nv matrix[3][3] = { - { new_width / (nv)w, 0, 0 }, - { 0, new_height / (nv)h, 0 }, - { 0, 0, 1 } - }; - int old_repeat_mode = repeat; repeat = RepeatPad; // not right, but xrender can't properly scale it seems - rxvt_img *img = transform (matrix); + rxvt_img *img = transform (mat3x3::scale (new_width / (nv)w, new_height / (nv)h)); repeat = old_repeat_mode; img->repeat = repeat; @@ -781,23 +805,14 @@ rxvt_img * rxvt_img::rotate (int cx, int cy, nv phi) { - nv s = sin (phi); - nv c = cos (phi); - - nv matrix[3][3] = { #if 0 { c, -s, cx - c * cx + s * cy }, { s, c, cy - s * cx - c * cy }, { 0, 0, 1 } -#else - { c, -s, 0 }, - { s, c, 0 }, - { 0, 0, 1 } #endif - }; move (-cx, -cy); - rxvt_img *img = transform (matrix); + rxvt_img *img = transform (mat3x3::rotate (phi)); move ( cx, cy); img->move (cx, cy);