comparison libass/ass_render.c @ 28839:fda4cf558544

Replace rotation functions with a simplified version adapted from vsfilter. This (mostly) fixes http://bugzilla.mplayerhq.hu/show_bug.cgi?id=1394#c7
author greg
date Sun, 08 Mar 2009 02:53:14 +0000
parents 98231639866f
children 7d0ea9013974
comparison
equal deleted inserted replaced
28838:98231639866f 28839:fda4cf558544
1794 break; 1794 break;
1795 } 1795 }
1796 } 1796 }
1797 1797
1798 /** 1798 /**
1799 * \brief Multiply 4-vector by 4-matrix 1799 * \brief Apply transformation to outline points of a glyph
1800 * \param a 4-vector 1800 * Applies rotations given by frx, fry and frz and projects the points back
1801 * \param m 4-matrix] 1801 * onto the screen plane.
1802 * \param b out: 4-vector 1802 */
1803 * Calculates a * m and stores result in b 1803 static void transform_3d_points(FT_Vector shift, FT_Glyph glyph, double frx, double fry, double frz) {
1804 */ 1804 double sx = sin(frx);
1805 static inline void transform_point_3d(double *a, double *m, double *b) 1805 double sy = sin(fry);
1806 { 1806 double sz = sin(frz);
1807 b[0] = a[0] * m[0] + a[1] * m[4] + a[2] * m[8] + a[3] * m[12]; 1807 double cx = cos(frx);
1808 b[1] = a[0] * m[1] + a[1] * m[5] + a[2] * m[9] + a[3] * m[13]; 1808 double cy = cos(fry);
1809 b[2] = a[0] * m[2] + a[1] * m[6] + a[2] * m[10] + a[3] * m[14]; 1809 double cz = cos(frz);
1810 b[3] = a[0] * m[3] + a[1] * m[7] + a[2] * m[11] + a[3] * m[15]; 1810 FT_Outline *outline = &((FT_OutlineGlyph) glyph)->outline;
1811 } 1811 FT_Vector* p = outline->points;
1812 1812 double x, y, z, xx, yy, zz;
1813 /**
1814 * \brief Apply 3d transformation to a vector
1815 * \param v FreeType vector (2d)
1816 * \param m 4-matrix
1817 * Transforms v by m, projects the result back to the screen plane
1818 * Result is returned in v.
1819 */
1820 static inline void transform_vector_3d(FT_Vector* v, double *m) {
1821 const double camera = 2500 * frame_context.border_scale; // camera distance
1822 const double cutoff_z = 10.;
1823 double a[4], b[4];
1824 a[0] = d6_to_double(v->x);
1825 a[1] = d6_to_double(v->y);
1826 a[2] = 0.;
1827 a[3] = 1.;
1828 transform_point_3d(a, m, b);
1829 /* Apply perspective projection with the following matrix:
1830 2500 0 0 0
1831 0 2500 0 0
1832 0 0 0 0
1833 0 0 8 2500
1834 where 2500 is camera distance, 8 - z-axis scale.
1835 Camera is always located in (org_x, org_y, -2500). This means
1836 that different subtitle events can be displayed at the same time
1837 using different cameras. */
1838 b[0] *= camera;
1839 b[1] *= camera;
1840 b[3] = 8 * b[2] + camera;
1841 if (b[3] < cutoff_z)
1842 b[3] = cutoff_z;
1843 v->x = double_to_d6(b[0] / b[3]);
1844 v->y = double_to_d6(b[1] / b[3]);
1845 }
1846
1847 /**
1848 * \brief Apply 3d transformation to a glyph
1849 * \param glyph FreeType glyph
1850 * \param m 4-matrix
1851 * Transforms glyph by m, projects the result back to the screen plane
1852 * Result is returned in glyph.
1853 */
1854 static inline void transform_glyph_3d(FT_Glyph glyph, double *m, FT_Vector shift) {
1855 int i; 1813 int i;
1856 FT_Outline* outline = &((FT_OutlineGlyph)glyph)->outline;
1857 FT_Vector* p = outline->points;
1858 1814
1859 for (i=0; i<outline->n_points; i++) { 1815 for (i=0; i<outline->n_points; i++) {
1860 p[i].x += shift.x; 1816 x = p[i].x + shift.x;
1861 p[i].y += shift.y; 1817 y = p[i].y + shift.y;
1862 transform_vector_3d(p + i, m); 1818 z = 0.;
1863 p[i].x -= shift.x; 1819
1864 p[i].y -= shift.y; 1820 xx = x*cz + y*sz;
1865 } 1821 yy = -(x*sz - y*cz);
1866 1822 zz = z;
1867 //transform_vector_3d(&glyph->advance, m); 1823
1824 x = xx;
1825 y = yy*cx + zz*sx;
1826 z = yy*sx - zz*cx;
1827
1828 xx = x*cy + z*sy;
1829 yy = y;
1830 zz = x*sy - z*cy;
1831
1832 zz = FFMAX(zz, -19000);
1833
1834 x = (xx * 20000) / (zz + 20000);
1835 y = (yy * 20000) / (zz + 20000);
1836 p[i].x = x - shift.x + 0.5;
1837 p[i].y = y - shift.y + 0.5;
1838 }
1868 } 1839 }
1869 1840
1870 /** 1841 /**
1871 * \brief Apply 3d transformation to several objects 1842 * \brief Apply 3d transformation to several objects
1872 * \param shift FreeType vector 1843 * \param shift FreeType vector
1877 * \param frz z-axis rotation angle 1848 * \param frz z-axis rotation angle
1878 * Rotates both glyphs by frx, fry and frz. Shift vector is added before rotation and subtracted after it. 1849 * Rotates both glyphs by frx, fry and frz. Shift vector is added before rotation and subtracted after it.
1879 */ 1850 */
1880 static void transform_3d(FT_Vector shift, FT_Glyph* glyph, FT_Glyph* glyph2, double frx, double fry, double frz) 1851 static void transform_3d(FT_Vector shift, FT_Glyph* glyph, FT_Glyph* glyph2, double frx, double fry, double frz)
1881 { 1852 {
1882 fry = - fry; // FreeType's y axis goes in the opposite direction 1853 frx = - frx;
1854 frz = - frz;
1883 if (frx != 0. || fry != 0. || frz != 0.) { 1855 if (frx != 0. || fry != 0. || frz != 0.) {
1884 double m[16];
1885 double sx = sin(frx);
1886 double sy = sin(fry);
1887 double sz = sin(frz);
1888 double cx = cos(frx);
1889 double cy = cos(fry);
1890 double cz = cos(frz);
1891 m[0] = cy * cz; m[1] = cy*sz; m[2] = -sy; m[3] = 0.0;
1892 m[4] = -cx*sz + sx*sy*cz; m[5] = cx*cz + sx*sy*sz; m[6] = sx*cy; m[7] = 0.0;
1893 m[8] = sx*sz + cx*sy*cz; m[9] = -sx*cz + cx*sy*sz; m[10] = cx*cy; m[11] = 0.0;
1894 m[12] = 0.0; m[13] = 0.0; m[14] = 0.0; m[15] = 1.0;
1895
1896 if (glyph && *glyph) 1856 if (glyph && *glyph)
1897 transform_glyph_3d(*glyph, m, shift); 1857 transform_3d_points(shift, *glyph, frx, fry, frz);
1898 1858
1899 if (glyph2 && *glyph2) 1859 if (glyph2 && *glyph2)
1900 transform_glyph_3d(*glyph2, m, shift); 1860 transform_3d_points(shift, *glyph2, frx, fry, frz);
1901 } 1861 }
1902 } 1862 }
1863
1903 1864
1904 /** 1865 /**
1905 * \brief Main ass rendering function, glues everything together 1866 * \brief Main ass rendering function, glues everything together
1906 * \param event event to render 1867 * \param event event to render
1907 * Process event, appending resulting ass_image_t's to images_root. 1868 * Process event, appending resulting ass_image_t's to images_root.