diff --git a/src/subtitles/xy_widen_region.cpp b/src/subtitles/xy_widen_region.cpp index 50e76ad83..d5c1005d6 100644 --- a/src/subtitles/xy_widen_region.cpp +++ b/src/subtitles/xy_widen_region.cpp @@ -28,10 +28,6 @@ typedef unsigned __int64 XY_POINT; #define XY_POINT_Y(point) ((point)>>32) #define XY_POINT_SET(point,x,y) ((point)=(((long long)(y)<<32)|(x))) -//ToDo: set a reg option for these -static const int LOOKUP_TABLE_SIZE_RX = 64; -static const int LOOKUP_TABLE_SIZE_RY = 64; - struct LinkArcItem { LinkArcItem():dead_line(0),arc_center(0){} @@ -80,17 +76,12 @@ struct XyEllipse int init_cross_point(); int m_rx, m_ry; - float m_f_rx, m_f_ry; - float m_f_half_inv_rx, m_f_half_inv_ry; - int *m_left_arc; int *m_left_arc_base; int *m_cross_matrix; int *m_cross_matrix_base; private: - int cross_left(int dx, int dy) const; - XyEllipse(const XyEllipse&); void operator=(const XyEllipse&); }; @@ -584,10 +575,6 @@ int XyEllipse::init( int rx, int ry ) m_left_arc = m_left_arc_base + ry; m_rx = rx; m_ry = ry; - m_f_rx = rx; - m_f_ry = ry; - m_f_half_inv_rx = rx > 0 ? 0.5f / m_f_rx : 0; - m_f_half_inv_ry = /*ry > 0*/ 0.5f / m_f_ry; init_cross_point(); return 0; } @@ -618,10 +605,6 @@ int XyEllipse::init_cross_point() { return 0; } - if ((2*m_ry+1)*(2*m_rx+1)>(2*LOOKUP_TABLE_SIZE_RY+1)*(2*LOOKUP_TABLE_SIZE_RX+1)) - { - return 0; - } m_cross_matrix_base = DEBUG_NEW int[ (2*m_ry+1)*(2*m_rx+1) ]; if (!m_cross_matrix_base) { @@ -631,8 +614,10 @@ int XyEllipse::init_cross_point() m_cross_matrix = m_cross_matrix_base + (2*m_ry)*(2*m_rx+1) + m_rx; - ASSERT(m_f_ry>0); - float rx_devide_ry = m_f_rx/m_f_ry; + float f_rx = m_rx; + float f_ry = m_ry; + ASSERT(f_ry>0); + float rx_devide_ry = f_rx/f_ry; float ry_2 = m_ry * m_ry; std::vector cross_x_base(2*m_ry+1+1); @@ -640,23 +625,16 @@ int XyEllipse::init_cross_point() cross_x[-m_ry-1] = m_rx; for (int dy=-2*m_ry;dy<=-1;dy++) { - static bool first = true; int y=-m_ry; for ( ;y-dy<=m_ry;y++) { - //f_cross_x = rx_devide_ry * ( sqrt(ry_2-(y-dy)*(y-dy))-sqrt(ry_2-y*y) ) - // But we have to do it this way because ry_2 may < y*y due to float rounding error - float fxo_2 = ry_2 - float(y-dy)*float(y-dy); - if (fxo_2<0) fxo_2 = 0; - float fx_2 = ry_2 - float(y)*float(y); - if (fx_2<0) fx_2 = 0; - float f_cross_x = rx_devide_ry * ( sqrt(fxo_2)-sqrt(fx_2) ); + float f_cross_x = rx_devide_ry * ( sqrt(ry_2 - (y - dy)*(y - dy)) - sqrt(ry_2 - y*y) ); cross_x[y] = ceil(f_cross_x); //This assertion may fail, e.g. when (m_rx,m_ry)=(15,19) and dy=y=-19, because of rounding of float // ASSERT(cross_x[y]<=cross_x[y-1] && abs(cross_x[y])<=m_rx); cross_x[y] = min(cross_x[y-1], max(min(cross_x[y],m_rx),-m_rx)); } - + int *cross_matrix = m_cross_matrix + dy*(2*m_rx+1); y--; @@ -687,18 +665,28 @@ int XyEllipse::cross_left( XY_POINT c1, XY_POINT base ) const { int dx = XY_POINT_X(c1) - XY_POINT_X(base); int dy = XY_POINT_Y(c1) - XY_POINT_Y(base); - return cross_left(dx, dy); + ASSERT(dy<0 && dy>=-2*m_ry); + if (dx < -m_rx) + { + return MAX_CROSS_LINE; + } + else if (dx > m_rx) + { + return MIN_CROSS_LINE; + } + else // [-m_rx, m_rx] + { + ASSERT( abs( *(m_cross_matrix + dy*(2*m_rx+1) + dx) )<=m_ry || + *(m_cross_matrix + dy*(2*m_rx+1) + dx) == MIN_CROSS_LINE || + *(m_cross_matrix + dy*(2*m_rx+1) + dx) == MAX_CROSS_LINE ); + return *(m_cross_matrix + dy*(2*m_rx+1) + dx); + } } int XyEllipse::cross_right( XY_POINT c1, XY_POINT base ) const { int dx = XY_POINT_X(base) - XY_POINT_X(c1); int dy = XY_POINT_Y(c1) - XY_POINT_Y(base); - return cross_left(dx, dy); -} - -int XyEllipse::cross_left( int dx, int dy ) const -{ ASSERT(dy<0 && dy>=-2*m_ry); if (dx < -m_rx) { @@ -708,38 +696,11 @@ int XyEllipse::cross_left( int dx, int dy ) const { return MIN_CROSS_LINE; } - else if (m_cross_matrix)// [-m_rx, m_rx], use lookup table + else // [-m_rx, m_rx] { ASSERT( abs( *(m_cross_matrix + dy*(2*m_rx+1) + dx) )<=m_ry || *(m_cross_matrix + dy*(2*m_rx+1) + dx) == MIN_CROSS_LINE || *(m_cross_matrix + dy*(2*m_rx+1) + dx) == MAX_CROSS_LINE ); return *(m_cross_matrix + dy*(2*m_rx+1) + dx); } - else - { - // unit circle with center at (0,0) and unit circle with center at (dx,dy) cross at points: - // x = 0.5*dx +/- 0.5*dy*sqrt(4/(dx*dx+dy*dy)-1) - // y = 0.5*dy -/+ 0.5*dx*sqrt(4/(dx*dx+dy*dy)-1) - float f_half_dy = dy*m_f_half_inv_ry; - float f_half_dx = dx*m_f_half_inv_rx; - float f_tmp = 1.0f/(f_half_dx*f_half_dx+f_half_dy*f_half_dy)-1.0f; - if (f_tmp >= 0) - { - f_tmp = sqrt(f_tmp); - if (fabs(f_half_dx)+f_half_dy*f_tmp<=0) - { - float ret = f_half_dy - f_half_dx*f_tmp; - ret *= m_f_ry; - return ceil(ret); - } - else - { - return dx > 0 ? MIN_CROSS_LINE : MAX_CROSS_LINE; - } - } - else - { - return dx > 0 ? MIN_CROSS_LINE : MAX_CROSS_LINE; - } - } }