Commit 675864e2 authored by Olivier Teulière's avatar Olivier Teulière

* modules/gui/skins2/bezier.*: Compute the points coordinates only once

 * modules/gui/skins2/ctrl_slider.cpp: Fixed a couple of bugs
parent d1cf41c4
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* ctrl_slider.cpp * ctrl_slider.cpp
***************************************************************************** *****************************************************************************
* Copyright (C) 2003 VideoLAN * Copyright (C) 2003 VideoLAN
* $Id: ctrl_slider.cpp,v 1.2 2004/01/11 17:12:17 asmax Exp $ * $Id: ctrl_slider.cpp,v 1.3 2004/02/01 21:13:04 ipkiss Exp $
* *
* Authors: Cyril Deguet <asmax@via.ecp.fr> * Authors: Cyril Deguet <asmax@via.ecp.fr>
* Olivier Teulire <ipkiss@via.ecp.fr> * Olivier Teulire <ipkiss@via.ecp.fr>
...@@ -133,7 +133,7 @@ bool CtrlSliderCursor::mouseOver( int x, int y ) const ...@@ -133,7 +133,7 @@ bool CtrlSliderCursor::mouseOver( int x, int y ) const
m_curve.getPoint( m_rVariable.get(), xPos, yPos ); m_curve.getPoint( m_rVariable.get(), xPos, yPos );
// Compute the resize factors // Compute the resize factors
float factorX = 0, factorY = 0; float factorX, factorY;
getResizeFactors( factorX, factorY ); getResizeFactors( factorX, factorY );
xPos = (int)(xPos * factorX); xPos = (int)(xPos * factorX);
yPos = (int)(yPos * factorY); yPos = (int)(yPos * factorY);
...@@ -157,7 +157,7 @@ void CtrlSliderCursor::draw( OSGraphics &rImage, int xDest, int yDest ) ...@@ -157,7 +157,7 @@ void CtrlSliderCursor::draw( OSGraphics &rImage, int xDest, int yDest )
m_curve.getPoint( m_rVariable.get(), xPos, yPos ); m_curve.getPoint( m_rVariable.get(), xPos, yPos );
// Compute the resize factors // Compute the resize factors
float factorX = 0, factorY = 0; float factorX, factorY;
getResizeFactors( factorX, factorY ); getResizeFactors( factorX, factorY );
xPos = (int)(xPos * factorX); xPos = (int)(xPos * factorX);
yPos = (int)(yPos * factorY); yPos = (int)(yPos * factorY);
...@@ -190,14 +190,19 @@ void CtrlSliderCursor::transOverDown( SkinObject *pCtrl ) ...@@ -190,14 +190,19 @@ void CtrlSliderCursor::transOverDown( SkinObject *pCtrl )
EvtMouse *pEvtMouse = (EvtMouse*)pThis->m_pEvt; EvtMouse *pEvtMouse = (EvtMouse*)pThis->m_pEvt;
// Compute the resize factors // Compute the resize factors
float factorX = 0, factorY = 0; float factorX, factorY;
pThis->getResizeFactors( factorX, factorY ); pThis->getResizeFactors( factorX, factorY );
// Get the position of the control
const Position *pPos = pThis->getPosition();
// Compute the offset // Compute the offset
int tempX, tempY; int tempX, tempY;
pThis->m_curve.getPoint( pThis->m_rVariable.get(), tempX, tempY ); pThis->m_curve.getPoint( pThis->m_rVariable.get(), tempX, tempY );
pThis->m_xOffset = pEvtMouse->getXPos() - (int)(tempX * factorX); pThis->m_xOffset = pEvtMouse->getXPos() - pPos->getLeft()
pThis->m_yOffset = pEvtMouse->getYPos() - (int)(tempY * factorY); - (int)(tempX * factorX);
pThis->m_yOffset = pEvtMouse->getYPos() - pPos->getTop()
- (int)(tempY * factorY);
pThis->captureMouse(); pThis->captureMouse();
pThis->m_pImg = pThis->m_pImgDown; pThis->m_pImg = pThis->m_pImgDown;
...@@ -245,17 +250,21 @@ void CtrlSliderCursor::transMove( SkinObject *pCtrl ) ...@@ -245,17 +250,21 @@ void CtrlSliderCursor::transMove( SkinObject *pCtrl )
const Position *pPos = pThis->getPosition(); const Position *pPos = pThis->getPosition();
// Compute the resize factors // Compute the resize factors
float factorX = 0, factorY = 0; float factorX, factorY;
pThis->getResizeFactors( factorX, factorY ); pThis->getResizeFactors( factorX, factorY );
// XXX: This could be optimized a little bit // Compute the relative position of the centre of the cursor
if( pThis->m_curve.getMinDist( float relX = pEvtMouse->getXPos() - pPos->getLeft() - pThis->m_xOffset;
(int)((pEvtMouse->getXPos() - pPos->getLeft()) / factorX), float relY = pEvtMouse->getYPos() - pPos->getTop() - pThis->m_yOffset;
(int)((pEvtMouse->getYPos() - pPos->getTop()) / factorY) ) < RANGE ) // Ponderate with the resize factors
int relXPond = (int)(relX / factorX);
int relYPond = (int)(relY / factorY);
// Update the position
if( pThis->m_curve.getMinDist( relXPond, relYPond ) < RANGE )
{ {
float percentage = pThis->m_curve.getNearestPercent( float percentage = pThis->m_curve.getNearestPercent( relXPond,
(int)((pEvtMouse->getXPos() - pThis->m_xOffset) / factorX), relYPond );
(int)((pEvtMouse->getYPos() - pThis->m_yOffset) / factorY) );
pThis->m_rVariable.set( percentage ); pThis->m_rVariable.set( percentage );
} }
else else
...@@ -326,10 +335,10 @@ bool CtrlSliderBg::mouseOver( int x, int y ) const ...@@ -326,10 +335,10 @@ bool CtrlSliderBg::mouseOver( int x, int y ) const
} }
// Compute the resize factors // Compute the resize factors
float factorX = 0, factorY = 1.0; float factorX, factorY;
getResizeFactors( factorX, factorY ); getResizeFactors( factorX, factorY );
return (m_curve.getMinDist( (int)(x / factorY), return (m_curve.getMinDist( (int)(x / factorX),
(int)(y / factorY) ) < m_thickness ); (int)(y / factorY) ) < m_thickness );
} }
...@@ -339,7 +348,7 @@ void CtrlSliderBg::handleEvent( EvtGeneric &rEvent ) ...@@ -339,7 +348,7 @@ void CtrlSliderBg::handleEvent( EvtGeneric &rEvent )
if( rEvent.getAsString().find( "mouse:left:down" ) != string::npos ) if( rEvent.getAsString().find( "mouse:left:down" ) != string::npos )
{ {
// Compute the resize factors // Compute the resize factors
float factorX = 0, factorY = 1.0; float factorX, factorY;
getResizeFactors( factorX, factorY ); getResizeFactors( factorX, factorY );
// Get the position of the control // Get the position of the control
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* bezier.cpp * bezier.cpp
***************************************************************************** *****************************************************************************
* Copyright (C) 2003 VideoLAN * Copyright (C) 2003 VideoLAN
* $Id: bezier.cpp,v 1.2 2004/01/11 17:12:17 asmax Exp $ * $Id: bezier.cpp,v 1.3 2004/02/01 21:13:04 ipkiss Exp $
* *
* Authors: Cyril Deguet <asmax@via.ecp.fr> * Authors: Cyril Deguet <asmax@via.ecp.fr>
* Olivier Teulire <ipkiss@via.ecp.fr> * Olivier Teulire <ipkiss@via.ecp.fr>
...@@ -50,75 +50,69 @@ Bezier::Bezier( intf_thread_t *p_intf, const vector<float> &rAbscissas, ...@@ -50,75 +50,69 @@ Bezier::Bezier( intf_thread_t *p_intf, const vector<float> &rAbscissas,
m_topVect.reserve( MAX_BEZIER_POINT + 1 ); m_topVect.reserve( MAX_BEZIER_POINT + 1 );
// Calculate the first point // Calculate the first point
getPoint( 0, oldx, oldy ); computePoint( 0, oldx, oldy );
m_leftVect[0] = oldx; m_leftVect[0] = oldx;
m_topVect[0] = oldy; m_topVect[0] = oldy;
// Compute the number of different points // Calculate the other points
float percentage; float percentage;
for( float j = 1; j <= MAX_BEZIER_POINT; j++ ) for( float j = 1; j <= MAX_BEZIER_POINT; j++ )
{ {
percentage = j / MAX_BEZIER_POINT; percentage = j / MAX_BEZIER_POINT;
getPoint( percentage, cx, cy ); computePoint( percentage, cx, cy );
if( ( flag == kCoordsBoth && ( cx != oldx || cy != oldy ) ) || if( ( flag == kCoordsBoth && ( cx != oldx || cy != oldy ) ) ||
( flag == kCoordsX && cx != oldx ) || ( flag == kCoordsX && cx != oldx ) ||
( flag == kCoordsY && cy != oldy ) ) ( flag == kCoordsY && cy != oldy ) )
{ {
m_percVect.push_back( percentage );
m_leftVect.push_back( cx ); m_leftVect.push_back( cx );
m_topVect.push_back( cy ); m_topVect.push_back( cy );
oldx = cx; oldx = cx;
oldy = cy; oldy = cy;
} }
} }
m_nbPoints = m_leftVect.size(); m_nbPoints = m_percVect.size();
// Small hack to ensure that the percentage of the last point is always 1
m_percVect[m_nbPoints - 1] = 1;
} }
float Bezier::getNearestPercent( int x, int y ) const float Bezier::getNearestPercent( int x, int y ) const
{ {
int nearest = findNearestPoint( x, y ); int nearest = findNearestPoint( x, y );
return (float)nearest / (float)(m_nbPoints - 1); return m_percVect[nearest];
} }
float Bezier::getMinDist( int x, int y ) const float Bezier::getMinDist( int x, int y ) const
{ {
// XXX: duplicate code with findNearestPoint int nearest = findNearestPoint( x, y );
int minDist = (m_leftVect[0] - x) * (m_leftVect[0] - x) + return sqrt( (m_leftVect[nearest] - x) * (m_leftVect[nearest] - x) +
(m_topVect[0] - y) * (m_topVect[0] - y); (m_topVect[nearest] - y) * (m_topVect[nearest] - y) );
int dist;
for( int i = 1; i < m_nbPoints; i++ )
{
dist = (m_leftVect[i] - x) * (m_leftVect[i] - x) +
(m_topVect[i] - y) * (m_topVect[i] - y);
if( dist < minDist )
{
minDist = dist;
}
}
return sqrt( minDist );
} }
void Bezier::getPoint( float t, int &x, int &y ) const void Bezier::getPoint( float t, int &x, int &y ) const
{ {
// See http://astronomy.swin.edu.au/~pbourke/curves/bezier/ for a simple // Find the precalculated point whose percentage is nearest from t
// explanation of the algorithm int refPoint = 0;
float xPos = 0; float minDiff = fabs( m_percVect[0] - t );
float yPos = 0;
float coeff; // The percentages are stored in increasing order, so we can stop the loop
for( int i = 0; i < m_nbCtrlPt; i++ ) // as soon as 'diff' starts increasing
float diff;
while( refPoint < m_nbPoints &&
(diff = fabs( m_percVect[refPoint] - t )) <= minDiff )
{ {
coeff = computeCoeff( i, m_nbCtrlPt - 1, t ); refPoint++;
xPos += m_ptx[i] * coeff; minDiff = diff;
yPos += m_pty[i] * coeff;
} }
// float cast to avoid strange truncatures // The searched point is then (refPoint - 1)
// XXX: not very nice... // We know that refPoint > 0 because we looped at least once
x = (int)(float)xPos; x = m_leftVect[refPoint - 1];
y = (int)(float)yPos; y = m_topVect[refPoint - 1];
} }
...@@ -152,7 +146,6 @@ int Bezier::getHeight() const ...@@ -152,7 +146,6 @@ int Bezier::getHeight() const
int Bezier::findNearestPoint( int x, int y ) const int Bezier::findNearestPoint( int x, int y ) const
{ {
// XXX: duplicate code with getMinDist
// The distance to the first point is taken as the reference // The distance to the first point is taken as the reference
int refPoint = 0; int refPoint = 0;
int minDist = (m_leftVect[0] - x) * (m_leftVect[0] - x) + int minDist = (m_leftVect[0] - x) * (m_leftVect[0] - x) +
...@@ -174,6 +167,27 @@ int Bezier::findNearestPoint( int x, int y ) const ...@@ -174,6 +167,27 @@ int Bezier::findNearestPoint( int x, int y ) const
} }
void Bezier::computePoint( float t, int &x, int &y ) const
{
// See http://astronomy.swin.edu.au/~pbourke/curves/bezier/ for a simple
// explanation of the algorithm
float xPos = 0;
float yPos = 0;
float coeff;
for( int i = 0; i < m_nbCtrlPt; i++ )
{
coeff = computeCoeff( i, m_nbCtrlPt - 1, t );
xPos += m_ptx[i] * coeff;
yPos += m_pty[i] * coeff;
}
// Float cast to avoid strange truncatures
// XXX: not very nice...
x = (int)(float)xPos;
y = (int)(float)yPos;
}
inline float Bezier::computeCoeff( int i, int n, float t ) const inline float Bezier::computeCoeff( int i, int n, float t ) const
{ {
return (power( t, i ) * power( 1 - t, (n - i) ) * return (power( t, i ) * power( 1 - t, (n - i) ) *
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* bezier.hpp * bezier.hpp
***************************************************************************** *****************************************************************************
* Copyright (C) 2003 VideoLAN * Copyright (C) 2003 VideoLAN
* $Id: bezier.hpp,v 1.3 2004/02/01 16:15:40 asmax Exp $ * $Id: bezier.hpp,v 1.4 2004/02/01 21:13:04 ipkiss Exp $
* *
* Authors: Cyril Deguet <asmax@via.ecp.fr> * Authors: Cyril Deguet <asmax@via.ecp.fr>
* Olivier Teulière <ipkiss@via.ecp.fr> * Olivier Teulière <ipkiss@via.ecp.fr>
...@@ -53,13 +53,12 @@ class Bezier: public SkinObject ...@@ -53,13 +53,12 @@ class Bezier: public SkinObject
/// Return the percentage (between 0 and 1) of the curve point nearest /// Return the percentage (between 0 and 1) of the curve point nearest
/// from (x, y) /// from (x, y)
float getNearestPercent( int x, int y ) const; float getNearestPercent( int x, int y ) const;
/// Return the distance of (x, y) to the curve /// Return the distance of (x, y) to the curve
float getMinDist( int x, int y ) const; float getMinDist( int x, int y ) const;
/// Get the coordinates of the point at t precent of /// Get the coordinates of the point at t percent of
/// the curve (t must be between 0 and 1) /// the curve (t must be between 0 and 1)
void getPoint( float t, int &x, int &y ) const; void getPoint( float t, int &x, int &y ) const;
...@@ -83,9 +82,14 @@ class Bezier: public SkinObject ...@@ -83,9 +82,14 @@ class Bezier: public SkinObject
/// Vectors with the coordinates of the different points of the curve /// Vectors with the coordinates of the different points of the curve
vector<int> m_leftVect; vector<int> m_leftVect;
vector<int> m_topVect; vector<int> m_topVect;
/// Vector with the percentages associated with the points of the curve
vector<float> m_percVect;
/// Return the index of the curve point that is the nearest from (x, y) /// Return the index of the curve point that is the nearest from (x, y)
int findNearestPoint( int x, int y ) const; int findNearestPoint( int x, int y ) const;
/// Compute the coordinates of a point corresponding to a given
/// percentage
void computePoint( float t, int &x, int &y ) const;
/// Helper function to compute a coefficient of the curve /// Helper function to compute a coefficient of the curve
inline float computeCoeff( int i, int n, float t ) const; inline float computeCoeff( int i, int n, float t ) const;
/// x^n /// x^n
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment